mirror of
https://github.com/YACReader/yacreader
synced 2025-07-14 02:54:46 -04:00
added a border to selected/mouseHover elements in the grid view
This commit is contained in:
BIN
YACReaderLibrary/YACReaderLibrary.icns
Normal file
BIN
YACReaderLibrary/YACReaderLibrary.icns
Normal file
Binary file not shown.
324
YACReaderLibrary/YACReaderLibrary.pro
Normal file
324
YACReaderLibrary/YACReaderLibrary.pro
Normal file
@ -0,0 +1,324 @@
|
||||
######################################################################
|
||||
# Automatically generated by qmake (2.01a) dom 12. oct 20:47:48 2008
|
||||
######################################################################
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = YACReaderLibrary
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += .
|
||||
INCLUDEPATH += ../common \
|
||||
./server \
|
||||
./db \
|
||||
../custom_widgets \
|
||||
./comic_vine \
|
||||
./comic_vine/model
|
||||
|
||||
DEFINES += SERVER_RELEASE NOMINMAX YACREADER_LIBRARY
|
||||
QMAKE_MAC_SDK = macosx10.11
|
||||
#load default build flags
|
||||
include (../config.pri)
|
||||
|
||||
CONFIG(legacy_gl_widget) {
|
||||
INCLUDEPATH += ../common/gl_legacy \
|
||||
} else {
|
||||
INCLUDEPATH += ../common/gl \
|
||||
}
|
||||
|
||||
#there are going to be two builds for windows, OpenGL based and ANGLE based
|
||||
win32 {
|
||||
CONFIG(force_angle) {
|
||||
message("using ANGLE")
|
||||
LIBS += -L../dependencies/poppler/lib -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32
|
||||
#linking extra libs are necesary for a successful compilation, a better approach should be
|
||||
#to remove any OpenGL (desktop) dependencies
|
||||
#the OpenGL stuff should be migrated to OpenGL ES
|
||||
DEFINES += FORCE_ANGLE
|
||||
} else {
|
||||
LIBS += -L../dependencies/poppler/lib -loleaut32 -lole32 -lshell32 -lopengl32 -lglu32 -luser32
|
||||
}
|
||||
|
||||
LIBS += -lpoppler-qt5
|
||||
INCLUDEPATH += ../dependencies/poppler/include/qt5
|
||||
|
||||
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT /GL
|
||||
QMAKE_LFLAGS_RELEASE += /LTCG
|
||||
CONFIG -= embed_manifest_exe
|
||||
}
|
||||
|
||||
unix:!macx{
|
||||
|
||||
INCLUDEPATH += /usr/include/poppler/qt5
|
||||
LIBS += -L/usr/lib -lpoppler-qt5
|
||||
|
||||
!CONFIG(no_opengl) {
|
||||
LIBS += -lGLU
|
||||
}
|
||||
}
|
||||
|
||||
macx{
|
||||
#INCLUDEPATH += "/Volumes/Mac OS X Lion/usr/X11/include"
|
||||
#isEqual(QT_MAJOR_VERSION, 5) {
|
||||
#INCLUDEPATH += /usr/local/include/poppler/qt5
|
||||
#LIBS += -L/usr/local/lib -lpoppler-qt5
|
||||
#}
|
||||
#else {
|
||||
#INCLUDEPATH += /usr/local/include/poppler/qt4
|
||||
#LIBS += -L/usr/local/lib -lpoppler-qt4
|
||||
#}
|
||||
#QT += macextras
|
||||
|
||||
LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
|
||||
|
||||
OBJECTIVE_SOURCES += $$PWD/../common/pdf_comic.mm
|
||||
HEADERS += $$PWD/../common/pdf_comic.h
|
||||
CONFIG += objective_c
|
||||
QT += macextras gui-private
|
||||
}
|
||||
|
||||
unix{
|
||||
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 \
|
||||
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
|
||||
|
||||
!CONFIG(no_opengl) {
|
||||
CONFIG(legacy_gl_widget) {
|
||||
message("using legacy YACReaderFlowGL (QGLWidget) header")
|
||||
HEADERS += ../common/gl_legacy/yacreader_flow_gl.h
|
||||
} else {
|
||||
HEADERS += ../common/gl/yacreader_flow_gl.h
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
!CONFIG(no_opengl) {
|
||||
CONFIG(legacy_gl_widget) {
|
||||
message("using legacy YACReaderFlowGL (QGLWidget) source code")
|
||||
SOURCES += ../common/gl_legacy/yacreader_flow_gl.cpp
|
||||
} else {
|
||||
SOURCES += ../common/gl/yacreader_flow_gl.cpp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
||||
CONFIG(force_angle) {
|
||||
Release:DESTDIR = ../release_angle
|
||||
Debug:DESTDIR = ../debug_angle
|
||||
} else {
|
||||
Release:DESTDIR = ../release
|
||||
Debug:DESTDIR = ../debug
|
||||
}
|
||||
|
||||
#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
|
||||
}
|
||||
|
||||
BINDIR = $$PREFIX/bin
|
||||
LIBDIR = $$PREFIX/lib
|
||||
DATADIR = $$PREFIX/share
|
||||
|
||||
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/yacreader
|
||||
icon.files = ../images/iconLibrary.png ../images/db.png ../images/coversPackage.png
|
||||
|
||||
desktop.path = $$DATADIR/applications
|
||||
desktop.extra = desktop-file-edit --set-icon=$$DATADIR/yacreader/iconLibrary.png $$PWD/../YACReaderLibrary.desktop
|
||||
desktop.files = ../YACReaderLibrary.desktop
|
||||
#TODO: icons should be located at /usr/share/icons and have the same basename as their application
|
||||
|
||||
translation.path = $$DATADIR/yacreader/languages
|
||||
translation.files = ../release/languages/yacreaderlibrary_*
|
||||
|
||||
manpage.path = $$DATADIR/man/man1
|
||||
manpage.files = ../YACReaderLibrary.1
|
||||
}
|
151
YACReaderLibrary/YACReaderLibraryServer.pro
Normal file
151
YACReaderLibrary/YACReaderLibraryServer.pro
Normal file
@ -0,0 +1,151 @@
|
||||
######################################################################
|
||||
# Automatically generated by qmake (2.01a) dom 12. oct 20:47:48 2008
|
||||
######################################################################
|
||||
|
||||
TEMPLATE = app
|
||||
TARGET = YACReaderLibraryServer
|
||||
CONFIG += console
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += .
|
||||
INCLUDEPATH += ../common \
|
||||
./server \
|
||||
./db
|
||||
|
||||
DEFINES += SERVER_RELEASE NOMINMAX YACREADER_LIBRARY QT_NO_DEBUG_OUTPUT
|
||||
QMAKE_MAC_SDK = macosx10.11
|
||||
#load default build flags
|
||||
#do a basic dependency check
|
||||
include(headless_config.pri)
|
||||
|
||||
win32 {
|
||||
LIBS += -L../dependencies/poppler/lib -loleaut32 -lole32 -lshell32 -luser32
|
||||
LIBS += -lpoppler-qt5
|
||||
INCLUDEPATH += ../dependencies/poppler/include/qt5
|
||||
|
||||
QMAKE_CXXFLAGS_RELEASE += /MP /Ob2 /Oi /Ot /GT /GL
|
||||
QMAKE_LFLAGS_RELEASE += /LTCG
|
||||
CONFIG -= embed_manifest_exe
|
||||
}
|
||||
|
||||
unix:!macx{
|
||||
INCLUDEPATH += /usr/include/poppler/qt5
|
||||
LIBS += -L/usr/lib -lpoppler-qt5
|
||||
}
|
||||
|
||||
macx{
|
||||
LIBS += -framework Foundation -framework ApplicationServices -framework AppKit
|
||||
|
||||
OBJECTIVE_SOURCES += $$PWD/../common/pdf_comic.mm
|
||||
HEADERS += $$PWD/../common/pdf_comic.h
|
||||
CONFIG += objective_c
|
||||
}
|
||||
|
||||
unix{
|
||||
CONFIG += c++11
|
||||
}
|
||||
|
||||
#CONFIG += release
|
||||
CONFIG -= flat
|
||||
QT += core sql network script
|
||||
|
||||
# Input
|
||||
HEADERS += library_creator.h \
|
||||
package_manager.h \
|
||||
bundle_creator.h \
|
||||
db_helper.h \
|
||||
./db/data_base_management.h \
|
||||
../common/comic_db.h \
|
||||
../common/folder.h \
|
||||
../common/library_item.h \
|
||||
../common/comic.h \
|
||||
../common/bookmarks.h \
|
||||
../common/qnaturalsorting.h \
|
||||
../common/yacreader_global.h \
|
||||
yacreader_local_server.h \
|
||||
comics_remover.h \
|
||||
../common/http_worker.h \
|
||||
yacreader_libraries.h \
|
||||
comic_files_manager.h \
|
||||
headless/console_ui_library_creator.h
|
||||
|
||||
|
||||
SOURCES += library_creator.cpp \
|
||||
.\headless\main.cpp \
|
||||
package_manager.cpp \
|
||||
bundle_creator.cpp \
|
||||
db_helper.cpp \
|
||||
./db/data_base_management.cpp \
|
||||
../common/comic_db.cpp \
|
||||
../common/folder.cpp \
|
||||
../common/library_item.cpp \
|
||||
../common/comic.cpp \
|
||||
../common/bookmarks.cpp \
|
||||
../common/qnaturalsorting.cpp \
|
||||
yacreader_local_server.cpp \
|
||||
comics_remover.cpp \
|
||||
../common/http_worker.cpp \
|
||||
../common/yacreader_global.cpp \
|
||||
yacreader_libraries.cpp \
|
||||
comic_files_manager.cpp \
|
||||
headless/console_ui_library_creator.cpp
|
||||
|
||||
|
||||
include(./server/server.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(../QsLog/QsLog.pri)
|
||||
|
||||
|
||||
TRANSLATIONS = yacreaderlibraryserver_es.ts \
|
||||
yacreaderlibraryserver_ru.ts \
|
||||
yacreaderlibraryserver_pt.ts \
|
||||
yacreaderlibraryserver_fr.ts \
|
||||
yacreaderlibraryserver_nl.ts \
|
||||
yacreaderlibraryserver_tr.ts \
|
||||
yacreaderlibraryserver_de.ts \
|
||||
yacreaderlibraryserver_source.ts
|
||||
|
||||
|
||||
RESOURCES += headless/images.qrc
|
||||
|
||||
|
||||
Release:DESTDIR = ../release
|
||||
Debug:DESTDIR = ../debug
|
||||
|
||||
|
||||
unix:!macx {
|
||||
#set install prefix if it's empty
|
||||
isEmpty(PREFIX) {
|
||||
PREFIX = /usr
|
||||
}
|
||||
|
||||
BINDIR = $$PREFIX/bin
|
||||
LIBDIR = $$PREFIX/lib
|
||||
DATADIR = $$PREFIX/share
|
||||
|
||||
DEFINES += "LIBDIR=\\\"$$LIBDIR\\\"" "DATADIR=\\\"$$DATADIR\\\"" "BINDIR=\\\"$$BINDIR\\\""
|
||||
|
||||
#MAKE INSTALL
|
||||
INSTALLS += bin server translation #manpage
|
||||
|
||||
bin.path = $$BINDIR
|
||||
isEmpty(DESTDIR) {
|
||||
bin.files = YACReaderLibraryServer
|
||||
} else {
|
||||
bin.files = $$DESTDIR/YACReaderLibraryServer
|
||||
}
|
||||
|
||||
server.path = $$DATADIR/yacreader
|
||||
server.files = ../release/server
|
||||
|
||||
translation.path = $$DATADIR/yacreader/languages
|
||||
translation.files = ../release/languages/yacreaderlibrary_*
|
||||
|
||||
#manpage.path = $$DATADIR/man/man1
|
||||
#manpage.files = ../YACReaderLibrary.1
|
||||
}
|
84
YACReaderLibrary/add_label_dialog.cpp
Normal file
84
YACReaderLibrary/add_label_dialog.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "add_label_dialog.h"
|
||||
|
||||
AddLabelDialog::AddLabelDialog(QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
QVBoxLayout * layout = new QVBoxLayout;
|
||||
|
||||
layout->addWidget(new QLabel(tr("Label name:")));
|
||||
layout->addWidget(edit = new QLineEdit());
|
||||
|
||||
layout->addWidget(new QLabel(tr("Choose a color:")));
|
||||
layout->addWidget(list = new QListWidget() );
|
||||
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_red.png"), tr("red")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_orange.png"), tr("orange")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_yellow.png"), tr("yellow")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_green.png"), tr("green")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_cyan.png"), tr("cyan")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_blue.png"), tr("blue")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_violet.png"), tr("violet")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_purple.png"), tr("purple")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_pink.png"), tr("pink")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_white.png"), tr("white")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_light.png"), tr("light")));
|
||||
list->addItem(new QListWidgetItem(QIcon(":/images/lists/label_dark.png"), tr("dark")));
|
||||
|
||||
QColor backgroundColor = this->palette().background().color();
|
||||
list->setStyleSheet(QString("QListWidget {border : none; background-color: rgb(%1,%2,%3);}").arg(backgroundColor.red()).arg(backgroundColor.green()).arg(backgroundColor.blue()));
|
||||
list->setMinimumHeight(225);
|
||||
|
||||
setModal(true);
|
||||
|
||||
setMinimumHeight(340);
|
||||
|
||||
//buttons
|
||||
acceptButton = new QPushButton(tr("accept"),this);
|
||||
cancelButton = new QPushButton(tr("cancel"),this);
|
||||
|
||||
QHBoxLayout * buttons = new QHBoxLayout;
|
||||
buttons->addStretch();
|
||||
buttons->addWidget(acceptButton);
|
||||
buttons->addWidget(cancelButton);
|
||||
|
||||
layout->addStretch();
|
||||
layout->addLayout(buttons);
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
//connections
|
||||
connect(edit,SIGNAL(textChanged(QString)),this,SLOT(validateName(QString)));
|
||||
connect(cancelButton,SIGNAL(clicked()),this,SLOT(close()));
|
||||
connect(acceptButton,SIGNAL(clicked()),this,SLOT(accept()));
|
||||
|
||||
}
|
||||
|
||||
YACReader::LabelColors AddLabelDialog::selectedColor()
|
||||
{
|
||||
return YACReader::LabelColors(list->currentRow()+1);
|
||||
}
|
||||
|
||||
QString AddLabelDialog::name()
|
||||
{
|
||||
return edit->text();
|
||||
}
|
||||
|
||||
int AddLabelDialog::exec()
|
||||
{
|
||||
edit->clear();
|
||||
list->clearSelection();
|
||||
|
||||
acceptButton->setDisabled(true);
|
||||
|
||||
list->setCurrentRow(0);
|
||||
|
||||
return QDialog::exec();
|
||||
}
|
||||
|
||||
void AddLabelDialog::validateName(const QString &name)
|
||||
{
|
||||
if(name.isEmpty())
|
||||
acceptButton->setDisabled(true);
|
||||
else
|
||||
acceptButton->setEnabled(true);
|
||||
}
|
31
YACReaderLibrary/add_label_dialog.h
Normal file
31
YACReaderLibrary/add_label_dialog.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef ADD_LABEL_DIALOG_H
|
||||
#define ADD_LABEL_DIALOG_H
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "yacreader_global.h"
|
||||
|
||||
class AddLabelDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AddLabelDialog(QWidget *parent = 0);
|
||||
YACReader::LabelColors selectedColor();
|
||||
QString name();
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
int exec();
|
||||
|
||||
protected slots:
|
||||
void validateName(const QString & name);
|
||||
|
||||
protected:
|
||||
QLineEdit * edit;
|
||||
QListWidget * list;
|
||||
|
||||
QPushButton * acceptButton;
|
||||
QPushButton * cancelButton;
|
||||
};
|
||||
|
||||
#endif // ADD_LABEL_DIALOG_H
|
124
YACReaderLibrary/add_library_dialog.cpp
Normal file
124
YACReaderLibrary/add_library_dialog.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
#include "add_library_dialog.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QFileDialog>
|
||||
#include <QGridLayout>
|
||||
|
||||
|
||||
AddLibraryDialog::AddLibraryDialog(QWidget * parent)
|
||||
:QDialog(parent)
|
||||
{
|
||||
setupUI();
|
||||
}
|
||||
|
||||
void AddLibraryDialog::setupUI()
|
||||
{
|
||||
textLabel = new QLabel(tr("Comics folder : "));
|
||||
path = new QLineEdit;
|
||||
textLabel->setBuddy(path);
|
||||
connect(path,SIGNAL(textChanged(QString)),this,SLOT(pathSetted(QString)));
|
||||
|
||||
nameLabel = new QLabel(tr("Library Name : "));
|
||||
nameEdit = new QLineEdit;
|
||||
nameLabel->setBuddy(nameEdit);
|
||||
connect(nameEdit,SIGNAL(textChanged(QString)),this,SLOT(nameSetted(QString)));
|
||||
|
||||
accept = new QPushButton(tr("Add"));
|
||||
accept->setDisabled(true);
|
||||
connect(accept,SIGNAL(clicked()),this,SLOT(add()));
|
||||
|
||||
cancel = new QPushButton(tr("Cancel"));
|
||||
connect(cancel,SIGNAL(clicked()),this,SLOT(close()));
|
||||
|
||||
find = new QPushButton(QIcon(":/images/find_folder.png"),"");
|
||||
connect(find,SIGNAL(clicked()),this,SLOT(findPath()));
|
||||
|
||||
QGridLayout * content = new QGridLayout;
|
||||
|
||||
content->addWidget(nameLabel,0,0);
|
||||
content->addWidget(nameEdit,0,1);
|
||||
|
||||
content->addWidget(textLabel,1,0);
|
||||
content->addWidget(path,1,1);
|
||||
content->addWidget(find,1,2);
|
||||
content->setColumnStretch(2,0);
|
||||
|
||||
QHBoxLayout *bottomLayout = new QHBoxLayout;
|
||||
bottomLayout->addStretch();
|
||||
bottomLayout->addWidget(accept);
|
||||
bottomLayout->addWidget(cancel);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(content);
|
||||
mainLayout->addStretch();
|
||||
mainLayout->addLayout(bottomLayout);
|
||||
|
||||
QHBoxLayout * imgMainLayout = new QHBoxLayout;
|
||||
QLabel * imgLabel = new QLabel(this);
|
||||
QPixmap p(":/images/openLibrary.png");
|
||||
imgLabel->setPixmap(p);
|
||||
imgMainLayout->addWidget(imgLabel);//,0,Qt::AlignTop);
|
||||
imgMainLayout->addLayout(mainLayout);
|
||||
|
||||
setLayout(imgMainLayout);
|
||||
|
||||
setModal(true);
|
||||
setWindowTitle(tr("Add an existing library"));
|
||||
}
|
||||
|
||||
void AddLibraryDialog::add()
|
||||
{
|
||||
//accept->setEnabled(false);
|
||||
emit(addLibrary(QDir::cleanPath(path->text()),nameEdit->text()));
|
||||
}
|
||||
|
||||
void AddLibraryDialog::nameSetted(const QString & text)
|
||||
{
|
||||
if(!text.isEmpty())
|
||||
{
|
||||
if(!path->text().isEmpty())
|
||||
{
|
||||
QFileInfo fi(path->text());
|
||||
if(fi.isDir())
|
||||
accept->setEnabled(true);
|
||||
else
|
||||
accept->setEnabled(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
accept->setEnabled(false);
|
||||
}
|
||||
|
||||
void AddLibraryDialog::pathSetted(const QString & text)
|
||||
{
|
||||
QFileInfo fi(text);
|
||||
if(fi.isDir())
|
||||
{
|
||||
if(!nameEdit->text().isEmpty())
|
||||
accept->setEnabled(true);
|
||||
}
|
||||
else
|
||||
accept->setEnabled(false);
|
||||
}
|
||||
|
||||
void AddLibraryDialog::findPath()
|
||||
{
|
||||
QString s = QFileDialog::getExistingDirectory(0,"Comics directory",".");
|
||||
if(!s.isEmpty())
|
||||
{
|
||||
path->setText(s);
|
||||
if(!nameEdit->text().isEmpty())
|
||||
accept->setEnabled(true);
|
||||
}
|
||||
else
|
||||
accept->setEnabled(false);
|
||||
}
|
||||
|
||||
void AddLibraryDialog::close()
|
||||
{
|
||||
path->clear();
|
||||
nameEdit->clear();
|
||||
accept->setEnabled(false);
|
||||
QDialog::close();
|
||||
}
|
35
YACReaderLibrary/add_library_dialog.h
Normal file
35
YACReaderLibrary/add_library_dialog.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef __ADD_LIBRARY_DIALOG_H
|
||||
#define __ADD_LIBRARY_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QThread>
|
||||
|
||||
class AddLibraryDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AddLibraryDialog(QWidget * parent = 0);
|
||||
private:
|
||||
QLabel * nameLabel;
|
||||
QLabel * textLabel;
|
||||
QLineEdit * path;
|
||||
QLineEdit * nameEdit;
|
||||
QPushButton * find;
|
||||
QPushButton * accept;
|
||||
QPushButton * cancel;
|
||||
void setupUI();
|
||||
public slots:
|
||||
void add();
|
||||
void findPath();
|
||||
void close();
|
||||
void nameSetted(const QString & text);
|
||||
void pathSetted(const QString & text);
|
||||
signals:
|
||||
void addLibrary(QString target, QString name);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
13
YACReaderLibrary/bundle_creator.cpp
Normal file
13
YACReaderLibrary/bundle_creator.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include "bundle_creator.h"
|
||||
|
||||
|
||||
BundleCreator::BundleCreator(void)
|
||||
:QObject()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
BundleCreator::~BundleCreator(void)
|
||||
{
|
||||
}
|
14
YACReaderLibrary/bundle_creator.h
Normal file
14
YACReaderLibrary/bundle_creator.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef __BUNDLE_CREATOR_H
|
||||
#define __BUNDLE_CREATOR_H
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
class BundleCreator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BundleCreator(void);
|
||||
~BundleCreator(void);
|
||||
};
|
||||
|
||||
#endif
|
375
YACReaderLibrary/classic_comics_view.cpp
Normal file
375
YACReaderLibrary/classic_comics_view.cpp
Normal file
@ -0,0 +1,375 @@
|
||||
#include "classic_comics_view.h"
|
||||
|
||||
#include "QStackedWidget"
|
||||
|
||||
#include "comic_flow_widget.h"
|
||||
#include "QsLog.h"
|
||||
#include "shortcuts_manager.h"
|
||||
#include "yacreader_table_view.h"
|
||||
#include "yacreader_tool_bar_stretch.h"
|
||||
|
||||
ClassicComicsView::ClassicComicsView(QWidget *parent)
|
||||
:ComicsView(parent),searching(false)
|
||||
{
|
||||
QHBoxLayout * layout = new QHBoxLayout;
|
||||
|
||||
settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor
|
||||
settings->beginGroup("libraryConfig");
|
||||
//FLOW-----------------------------------------------------------------------
|
||||
//---------------------------------------------------------------------------
|
||||
//FORCE_ANGLE is not used here, because ComicFlowWidgetGL will use OpenGL ES in the future
|
||||
#ifndef NO_OPENGL
|
||||
if((settings->value(USE_OPEN_GL).toBool() == true))
|
||||
comicFlow = new ComicFlowWidgetGL(0);
|
||||
else
|
||||
comicFlow = new ComicFlowWidgetSW(0);
|
||||
#else
|
||||
comicFlow = new ComicFlowWidgetSW(0);
|
||||
#endif
|
||||
comicFlow->updateConfig(settings);
|
||||
comicFlow->setFocusPolicy(Qt::StrongFocus);
|
||||
comicFlow->setShowMarks(true);
|
||||
setFocusProxy(comicFlow);
|
||||
|
||||
comicFlow->setFocus(Qt::OtherFocusReason);
|
||||
|
||||
comicFlow->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
|
||||
//layout-----------------------------------------------
|
||||
sVertical = new QSplitter(Qt::Vertical); //spliter derecha
|
||||
|
||||
stack = new QStackedWidget;
|
||||
stack->addWidget(comicFlow);
|
||||
setupSearchingIcon();
|
||||
stack->addWidget(searchingIcon);
|
||||
|
||||
|
||||
sVertical->addWidget(stack);
|
||||
comics = new QWidget;
|
||||
QVBoxLayout * comicsLayout = new QVBoxLayout;
|
||||
comicsLayout->setSpacing(0);
|
||||
comicsLayout->setContentsMargins(0,0,0,0);
|
||||
//TODO ComicsView:(set toolbar) comicsLayout->addWidget(editInfoToolBar);
|
||||
|
||||
tableView = new YACReaderTableView;
|
||||
tableView->verticalHeader()->hide();
|
||||
tableView->setFocusPolicy(Qt::StrongFocus);
|
||||
comicsLayout->addWidget(tableView);
|
||||
comics->setLayout(comicsLayout);
|
||||
sVertical->addWidget(comics);
|
||||
|
||||
tableView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
|
||||
//config--------------------------------------------------
|
||||
if(settings->contains(COMICS_VIEW_HEADERS))
|
||||
tableView->horizontalHeader()->restoreState(settings->value(COMICS_VIEW_HEADERS).toByteArray());
|
||||
|
||||
//connections---------------------------------------------
|
||||
connect(tableView, SIGNAL(clicked(QModelIndex)), this, SLOT(centerComicFlow(QModelIndex)));
|
||||
connect(tableView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(selectedComicForOpening(QModelIndex)));
|
||||
connect(comicFlow, SIGNAL(centerIndexChanged(int)), this, SLOT(updateTableView(int)));
|
||||
connect(tableView, SIGNAL(comicRated(int,QModelIndex)), this, SIGNAL(comicRated(int,QModelIndex)));
|
||||
connect(comicFlow, SIGNAL(selected(uint)), this, SIGNAL(selected(uint)));
|
||||
connect(tableView->horizontalHeader(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(saveTableHeadersStatus()));
|
||||
connect(tableView->horizontalHeader(), SIGNAL(sectionResized(int,int,int)), this, SLOT(saveTableHeadersStatus()));
|
||||
connect(comicFlow, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(requestedViewContextMenu(QPoint)));
|
||||
connect(tableView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(requestedItemContextMenu(QPoint)));
|
||||
layout->addWidget(sVertical);
|
||||
setLayout(layout);
|
||||
|
||||
layout->setMargin(0);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
sVertical->setCollapsible(1,false);
|
||||
#endif
|
||||
|
||||
if(settings->contains(COMICS_VIEW_FLOW_SPLITTER_STATUS))
|
||||
sVertical->restoreState(settings->value(COMICS_VIEW_FLOW_SPLITTER_STATUS).toByteArray());
|
||||
|
||||
//hide flow widgets
|
||||
toolBarStretch = new YACReaderToolBarStretch(this);
|
||||
|
||||
hideFlowViewAction = new QAction(this);
|
||||
hideFlowViewAction->setText(tr("Hide comic flow"));
|
||||
hideFlowViewAction->setData(HIDE_COMIC_VIEW_ACTION_YL);
|
||||
hideFlowViewAction->setShortcut(ShortcutsManager::getShortcutsManager().getShortcut(HIDE_COMIC_VIEW_ACTION_YL));
|
||||
hideFlowViewAction->setIcon(QIcon(":/images/comics_view_toolbar/hideComicFlow.png"));
|
||||
hideFlowViewAction->setCheckable(true);
|
||||
hideFlowViewAction->setChecked(false);
|
||||
|
||||
connect(hideFlowViewAction, SIGNAL(toggled(bool)),this, SLOT(hideComicFlow(bool)));
|
||||
}
|
||||
|
||||
void ClassicComicsView::hideComicFlow(bool hide)
|
||||
{
|
||||
if(hide)
|
||||
{
|
||||
QList<int> sizes;
|
||||
sizes.append(0);
|
||||
int total = sVertical->sizes().at(0) + sVertical->sizes().at(1);
|
||||
sizes.append(total);
|
||||
sVertical->setSizes(sizes);
|
||||
}
|
||||
else
|
||||
{
|
||||
QList<int> sizes;
|
||||
int total = sVertical->sizes().at(0) + sVertical->sizes().at(1);
|
||||
sizes.append(2*total/3);
|
||||
sizes.append(total/3);
|
||||
sVertical->setSizes(sizes);
|
||||
}
|
||||
}
|
||||
|
||||
//the toolbar has to be populated
|
||||
void ClassicComicsView::setToolBar(QToolBar *toolBar)
|
||||
{
|
||||
static_cast<QVBoxLayout *>(comics->layout())->insertWidget(0,toolBar);
|
||||
this->toolbar = toolBar;
|
||||
|
||||
toolBarStretchAction = toolBar->addWidget(toolBarStretch);
|
||||
toolBar->addAction(hideFlowViewAction);
|
||||
}
|
||||
|
||||
void ClassicComicsView::setModel(ComicModel *model)
|
||||
{
|
||||
ComicsView::setModel(model);
|
||||
|
||||
if(model == NULL)
|
||||
{
|
||||
comicFlow->clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), this, SLOT(applyModelChanges(QModelIndex,QModelIndex,QVector<int>)),Qt::UniqueConnection);
|
||||
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(removeItemsFromFlow(QModelIndex,int,int)),Qt::UniqueConnection);
|
||||
connect(model, SIGNAL(resortedIndexes(QList<int>)),comicFlow,SLOT(resortCovers(QList<int>)),Qt::UniqueConnection);
|
||||
connect(model, SIGNAL(newSelectedIndex(QModelIndex)),this,SLOT(setCurrentIndex(QModelIndex)),Qt::UniqueConnection);
|
||||
|
||||
tableView->setModel(model);
|
||||
if(model->rowCount()>0)
|
||||
tableView->setCurrentIndex(model->index(0,0));
|
||||
|
||||
tableView->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
|
||||
#if QT_VERSION >= 0x050000
|
||||
tableView->horizontalHeader()->setSectionsMovable(true);
|
||||
#else
|
||||
tableView->horizontalHeader()->setMovable(true);
|
||||
#endif
|
||||
//TODO parametrizar la configuración de las columnas
|
||||
/*if(!settings->contains(COMICS_VIEW_HEADERS))
|
||||
{*/
|
||||
for(int i = 0;i<tableView->horizontalHeader()->count();i++)
|
||||
tableView->horizontalHeader()->hideSection(i);
|
||||
|
||||
tableView->horizontalHeader()->showSection(ComicModel::Number);
|
||||
tableView->horizontalHeader()->showSection(ComicModel::Title);
|
||||
tableView->horizontalHeader()->showSection(ComicModel::FileName);
|
||||
tableView->horizontalHeader()->showSection(ComicModel::NumPages);
|
||||
tableView->horizontalHeader()->showSection(ComicModel::Hash); //Size is part of the Hash...TODO add Columns::Size to Columns
|
||||
tableView->horizontalHeader()->showSection(ComicModel::ReadColumn);
|
||||
tableView->horizontalHeader()->showSection(ComicModel::CurrentPage);
|
||||
tableView->horizontalHeader()->showSection(ComicModel::Rating);
|
||||
//}
|
||||
|
||||
//debido a un bug, qt4 no es capaz de ajustar el ancho teniendo en cuenta todas la filas (no sólo las visibles)
|
||||
//así que se ecala la primera vez y después se deja el control al usuario.
|
||||
//if(!settings->contains(COMICS_VIEW_HEADERS))
|
||||
|
||||
|
||||
QStringList paths = model->getPaths(model->getCurrentPath());//TODO ComicsView: get currentpath from somewhere currentPath());
|
||||
comicFlow->setImagePaths(paths);
|
||||
comicFlow->setMarks(model->getReadList());
|
||||
//comicFlow->setFocus(Qt::OtherFocusReason);
|
||||
|
||||
if(settings->contains(COMICS_VIEW_HEADERS))
|
||||
tableView->horizontalHeader()->restoreState(settings->value(COMICS_VIEW_HEADERS).toByteArray());
|
||||
|
||||
tableView->resizeColumnsToContents();
|
||||
|
||||
tableView->horizontalHeader()->setStretchLastSection(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicComicsView::setCurrentIndex(const QModelIndex &index)
|
||||
{
|
||||
tableView->setCurrentIndex(index);
|
||||
centerComicFlow(index);
|
||||
}
|
||||
|
||||
QModelIndex ClassicComicsView::currentIndex()
|
||||
{
|
||||
return tableView->currentIndex();
|
||||
}
|
||||
|
||||
QItemSelectionModel *ClassicComicsView::selectionModel()
|
||||
{
|
||||
return tableView->selectionModel();
|
||||
}
|
||||
|
||||
void ClassicComicsView::scrollTo(const QModelIndex & mi, QAbstractItemView::ScrollHint hint)
|
||||
{
|
||||
comicFlow->setCenterIndex(mi.row());
|
||||
}
|
||||
|
||||
void ClassicComicsView::toFullScreen()
|
||||
{
|
||||
comicFlow->hide();
|
||||
comicFlow->setCenterIndex(comicFlow->centerIndex());
|
||||
comics->hide();
|
||||
|
||||
//showFullScreen() //parent windows
|
||||
|
||||
comicFlow->show();
|
||||
comicFlow->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
void ClassicComicsView::toNormal()
|
||||
{
|
||||
comicFlow->hide();
|
||||
comicFlow->setCenterIndex(comicFlow->centerIndex());
|
||||
comicFlow->render();
|
||||
comics->show();
|
||||
comicFlow->show();
|
||||
}
|
||||
|
||||
void ClassicComicsView::updateConfig(QSettings *settings)
|
||||
{
|
||||
comicFlow->updateConfig(settings);
|
||||
}
|
||||
|
||||
void ClassicComicsView::enableFilterMode(bool enabled)
|
||||
{
|
||||
if(enabled)
|
||||
{
|
||||
comicFlow->clear();
|
||||
if(previousSplitterStatus.isEmpty())
|
||||
previousSplitterStatus = sVertical->saveState();
|
||||
sVertical->setSizes(QList<int> () << 100 << 10000000);
|
||||
showSearchingIcon();
|
||||
}else
|
||||
{
|
||||
hideSearchingIcon();
|
||||
sVertical->restoreState(previousSplitterStatus);
|
||||
previousSplitterStatus.clear();
|
||||
}
|
||||
|
||||
//sVertical->setCollapsible(0,!enabled);
|
||||
searching = enabled;
|
||||
}
|
||||
|
||||
void ClassicComicsView::selectIndex(int index)
|
||||
{
|
||||
tableView->selectRow(index);
|
||||
}
|
||||
|
||||
void ClassicComicsView::selectAll()
|
||||
{
|
||||
tableView->selectAll();
|
||||
}
|
||||
|
||||
void ClassicComicsView::selectedComicForOpening(const QModelIndex &mi)
|
||||
{
|
||||
emit selected(mi.row());
|
||||
}
|
||||
|
||||
void ClassicComicsView::requestedViewContextMenu(const QPoint &point)
|
||||
{
|
||||
emit customContextMenuViewRequested(comicFlow->mapTo(this, point));
|
||||
}
|
||||
|
||||
void ClassicComicsView::requestedItemContextMenu(const QPoint &point)
|
||||
{
|
||||
emit customContextMenuItemRequested(tableView->mapTo(this, point));
|
||||
}
|
||||
|
||||
void ClassicComicsView::setShowMarks(bool show)
|
||||
{
|
||||
comicFlow->setShowMarks(show);
|
||||
}
|
||||
|
||||
void ClassicComicsView::centerComicFlow(const QModelIndex & mi)
|
||||
{
|
||||
comicFlow->showSlide(mi.row());
|
||||
comicFlow->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
void ClassicComicsView::updateTableView(int i)
|
||||
{
|
||||
QModelIndex mi = model->index(i,2);
|
||||
tableView->setCurrentIndex(mi);
|
||||
tableView->scrollTo(mi,QAbstractItemView::EnsureVisible);
|
||||
}
|
||||
|
||||
void ClassicComicsView::saveTableHeadersStatus()
|
||||
{
|
||||
settings->setValue(COMICS_VIEW_HEADERS,tableView->horizontalHeader()->saveState());
|
||||
}
|
||||
|
||||
void ClassicComicsView::saveSplitterStatus()
|
||||
{
|
||||
settingsMutex.lock();
|
||||
if(!searching)
|
||||
settings->setValue(COMICS_VIEW_FLOW_SPLITTER_STATUS, sVertical->saveState());
|
||||
settingsMutex.unlock();
|
||||
}
|
||||
|
||||
void ClassicComicsView::applyModelChanges(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
|
||||
{
|
||||
Q_UNUSED(topLeft);
|
||||
Q_UNUSED(bottomRight);
|
||||
if(roles.contains(ComicModel::ReadColumnRole))
|
||||
{
|
||||
comicFlow->setMarks(model->getReadList());
|
||||
comicFlow->updateMarks();
|
||||
}
|
||||
}
|
||||
|
||||
void ClassicComicsView::removeItemsFromFlow(const QModelIndex &parent, int from, int to)
|
||||
{
|
||||
Q_UNUSED(parent);
|
||||
for(int i = from; i<=to; i++)
|
||||
comicFlow->remove(i);
|
||||
}
|
||||
|
||||
void ClassicComicsView::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
toolbar->removeAction(toolBarStretchAction);
|
||||
toolbar->removeAction(hideFlowViewAction);
|
||||
|
||||
saveTableHeadersStatus();
|
||||
saveSplitterStatus();
|
||||
ComicsView::closeEvent(event);
|
||||
}
|
||||
|
||||
void ClassicComicsView::setupSearchingIcon()
|
||||
{
|
||||
searchingIcon = new QWidget(comicFlow);
|
||||
|
||||
QHBoxLayout * h = new QHBoxLayout;
|
||||
|
||||
QPixmap p(":/images/searching_icon.png");
|
||||
QLabel * l = new QLabel(searchingIcon);
|
||||
l->setPixmap(p);
|
||||
l->setFixedSize(p.size());
|
||||
h->addWidget(l,0,Qt::AlignCenter);
|
||||
searchingIcon->setLayout(h);
|
||||
|
||||
QPalette pal(searchingIcon->palette());
|
||||
pal.setColor(QPalette::Background, Qt::black);
|
||||
searchingIcon->setAutoFillBackground(true);
|
||||
searchingIcon->setPalette(pal);
|
||||
|
||||
hideSearchingIcon();
|
||||
}
|
||||
|
||||
void ClassicComicsView::showSearchingIcon()
|
||||
{
|
||||
stack->setCurrentWidget(searchingIcon);
|
||||
}
|
||||
|
||||
void ClassicComicsView::hideSearchingIcon()
|
||||
{
|
||||
stack->setCurrentWidget(comicFlow);
|
||||
}
|
||||
|
79
YACReaderLibrary/classic_comics_view.h
Normal file
79
YACReaderLibrary/classic_comics_view.h
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef CLASSIC_COMICS_VIEW_H
|
||||
#define CLASSIC_COMICS_VIEW_H
|
||||
|
||||
#include "comics_view.h"
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QModelIndexList>
|
||||
|
||||
class QSplitter;
|
||||
class QStackedWidget;
|
||||
class QToolBar;
|
||||
|
||||
class ComicFlowWidget;
|
||||
class ComicModel;
|
||||
class YACReaderTableView;
|
||||
class YACReaderToolBarStretch;
|
||||
|
||||
class ClassicComicsView : public ComicsView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ClassicComicsView(QWidget *parent = 0);
|
||||
void setToolBar(QToolBar * toolBar);
|
||||
void setModel(ComicModel *model);
|
||||
|
||||
QModelIndex currentIndex();
|
||||
QItemSelectionModel * selectionModel();
|
||||
void scrollTo(const QModelIndex & mi, QAbstractItemView::ScrollHint hint );
|
||||
void toFullScreen();
|
||||
void toNormal();
|
||||
void updateConfig(QSettings * settings);
|
||||
void enableFilterMode(bool enabled);
|
||||
void selectIndex(int index);
|
||||
|
||||
public slots:
|
||||
void setCurrentIndex(const QModelIndex &index);
|
||||
void centerComicFlow(const QModelIndex & mi);
|
||||
void updateTableView(int i);
|
||||
void saveTableHeadersStatus();
|
||||
void saveSplitterStatus();
|
||||
void applyModelChanges(const QModelIndex & topLeft,const QModelIndex & bottomRight,const QVector<int> & roles);
|
||||
void removeItemsFromFlow(const QModelIndex & parent, int from, int to);
|
||||
//ComicsView
|
||||
void setShowMarks(bool show);
|
||||
void selectAll();
|
||||
void selectedComicForOpening(const QModelIndex & mi);
|
||||
|
||||
protected slots:
|
||||
void hideComicFlow(bool hide);
|
||||
void requestedViewContextMenu(const QPoint & point);
|
||||
void requestedItemContextMenu(const QPoint & point);
|
||||
|
||||
|
||||
private:
|
||||
YACReaderTableView * tableView;
|
||||
YACReaderToolBarStretch * toolBarStretch;
|
||||
QAction * toolBarStretchAction;
|
||||
QToolBar * toolbar;
|
||||
QWidget *comics;
|
||||
QSplitter * sVertical;
|
||||
ComicFlowWidget * comicFlow;
|
||||
QSettings * settings;
|
||||
void closeEvent ( QCloseEvent * event );
|
||||
QAction * hideFlowViewAction;
|
||||
|
||||
QStackedWidget * stack;
|
||||
|
||||
QByteArray previousSplitterStatus;
|
||||
QWidget * searchingIcon;
|
||||
bool searching;
|
||||
void setupSearchingIcon();
|
||||
void showSearchingIcon();
|
||||
void hideSearchingIcon();
|
||||
void updateSearchingIconPosition();
|
||||
|
||||
QMutex settingsMutex;
|
||||
};
|
||||
|
||||
#endif // CLASSIC_COMICS_VIEW_H
|
108
YACReaderLibrary/comic_files_manager.cpp
Normal file
108
YACReaderLibrary/comic_files_manager.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
#include "comic_files_manager.h"
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
#include <QsLog.h>
|
||||
|
||||
#include "comic.h"
|
||||
|
||||
ComicFilesManager::ComicFilesManager(QObject *parent) :
|
||||
QObject(parent), canceled(false)
|
||||
{
|
||||
}
|
||||
|
||||
void ComicFilesManager::copyComicsTo(const QList<QPair<QString,QString> > &sourceComics, const QString &folderDest, const QModelIndex & dest)
|
||||
{
|
||||
comics = sourceComics;
|
||||
folder = folderDest;
|
||||
folderDestinationModelIndex = dest;
|
||||
move = false;
|
||||
}
|
||||
|
||||
void ComicFilesManager::moveComicsTo(const QList<QPair<QString, QString> > &sourceComics, const QString &folderDest, const QModelIndex &dest)
|
||||
{
|
||||
comics = sourceComics;
|
||||
folder = folderDest;
|
||||
folderDestinationModelIndex = dest;
|
||||
move = true;
|
||||
}
|
||||
|
||||
QList<QPair<QString, QString> > ComicFilesManager::getDroppedFiles(const QList<QUrl> &urls)
|
||||
{
|
||||
QList<QPair<QString,QString> > dropedFiles;
|
||||
|
||||
QString currentPath;
|
||||
foreach(QUrl url, urls)
|
||||
{
|
||||
currentPath = url.toLocalFile();
|
||||
if(currentPath.endsWith('/'))
|
||||
currentPath = currentPath.remove(currentPath.length()-1,1); //QTBUG-35896 QUrl.toLocalFile inconsistency.
|
||||
if(Comic::fileIsComic(currentPath))
|
||||
dropedFiles << QPair<QString, QString>(currentPath,"/");
|
||||
else
|
||||
{
|
||||
QLOG_DEBUG() << "XXXXXXXXXXXX :" << currentPath;
|
||||
QFileInfo info(currentPath);
|
||||
if(info.isDir())
|
||||
{
|
||||
QLOG_DEBUG() << "origin path prior to absoluteFilePath : " << info.absolutePath();
|
||||
foreach(QString comicPath, Comic::findValidComicFilesInFolder(info.absoluteFilePath()))
|
||||
{
|
||||
QFileInfo comicInfo(comicPath);
|
||||
QString path = comicInfo.absolutePath();
|
||||
QLOG_DEBUG() << "comic path : " << comicPath;
|
||||
QLOG_DEBUG() << "full comic path : " << path;
|
||||
QLOG_DEBUG() << "origin path : " << info.absolutePath();
|
||||
dropedFiles << QPair<QString, QString>(comicPath, path.remove(info.absolutePath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dropedFiles;
|
||||
}
|
||||
|
||||
void ComicFilesManager::process()
|
||||
{
|
||||
int i=0;
|
||||
bool successProcesingFiles = false;
|
||||
QPair<QString, QString> source;
|
||||
foreach (source, comics) {
|
||||
|
||||
if(canceled)
|
||||
{
|
||||
if(successProcesingFiles)
|
||||
emit success(folderDestinationModelIndex);
|
||||
emit finished();
|
||||
|
||||
return; //TODO rollback?
|
||||
}
|
||||
|
||||
QFileInfo info(source.first);
|
||||
QString destPath = QDir::cleanPath(folder+'/'+source.second);
|
||||
QLOG_DEBUG() << "crear : " << destPath;
|
||||
QDir().mkpath(destPath);
|
||||
if(QFile::copy(source.first, QDir::cleanPath(destPath+'/'+info.fileName())))
|
||||
{
|
||||
successProcesingFiles = true;
|
||||
if(move)
|
||||
{
|
||||
QFile::remove(source.first); //TODO: remove the whole path....
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
emit progress(i);
|
||||
}
|
||||
|
||||
if(successProcesingFiles)
|
||||
emit success(folderDestinationModelIndex);
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void ComicFilesManager::cancel()
|
||||
{
|
||||
QLOG_DEBUG() << "Operation canceled";
|
||||
canceled = true;
|
||||
}
|
37
YACReaderLibrary/comic_files_manager.h
Normal file
37
YACReaderLibrary/comic_files_manager.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef COMIC_FILES_MANAGER_H
|
||||
#define COMIC_FILES_MANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QPair>
|
||||
#include <QModelIndex>
|
||||
|
||||
|
||||
//this class is intended to work in background, just use moveToThread and process to start working
|
||||
class ComicFilesManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComicFilesManager(QObject *parent = 0);
|
||||
void copyComicsTo(const QList<QPair<QString,QString> > & sourceComics, const QString & folderDest, const QModelIndex &dest);
|
||||
void moveComicsTo(const QList<QPair<QString,QString> > & comics, const QString & folderDest, const QModelIndex &dest);
|
||||
static QList<QPair<QString, QString> > getDroppedFiles(const QList<QUrl> & urls);
|
||||
signals:
|
||||
void currentComic(QString);
|
||||
void progress(int);
|
||||
void finished();
|
||||
void success(QModelIndex); //at least one comics has been copied or moved
|
||||
public slots:
|
||||
void process();
|
||||
void cancel();
|
||||
|
||||
protected:
|
||||
bool move;
|
||||
bool canceled;
|
||||
QList<QPair<QString,QString> > comics;
|
||||
QString folder;
|
||||
QModelIndex folderDestinationModelIndex;
|
||||
|
||||
};
|
||||
|
||||
#endif // COMIC_FILES_MANAGER_H
|
265
YACReaderLibrary/comic_flow.cpp
Normal file
265
YACReaderLibrary/comic_flow.cpp
Normal file
@ -0,0 +1,265 @@
|
||||
#include "comic_flow.h"
|
||||
#include "qnaturalsorting.h"
|
||||
|
||||
#include "yacreader_global.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QMutex>
|
||||
#include <QImageReader>
|
||||
#include <QTimer>
|
||||
|
||||
ComicFlow::ComicFlow(QWidget* parent,FlowType flowType)
|
||||
:YACReaderFlow(parent,flowType)
|
||||
{
|
||||
updateTimer = new QTimer;
|
||||
connect(updateTimer, SIGNAL(timeout()), this, SLOT(updateImageData()));
|
||||
|
||||
worker = new ImageLoader;
|
||||
connect(this, SIGNAL(centerIndexChanged(int)), this, SLOT(preload()));
|
||||
connect(this, SIGNAL(centerIndexChangedSilent(int)), this, SLOT(preload()));
|
||||
|
||||
setReflectionEffect(PlainReflection);
|
||||
}
|
||||
|
||||
ComicFlow::~ComicFlow()
|
||||
{
|
||||
worker->terminate();
|
||||
delete worker;
|
||||
delete updateTimer;
|
||||
}
|
||||
|
||||
void ComicFlow::setImagePaths(const QStringList& paths)
|
||||
{
|
||||
clear();
|
||||
|
||||
//imagePath = path;
|
||||
imageFiles = paths;
|
||||
imagesLoaded.clear();
|
||||
imagesLoaded.fill(false,imageFiles.size());
|
||||
numImagesLoaded = 0;
|
||||
|
||||
imagesSetted.clear();
|
||||
imagesSetted.fill(false,imageFiles.size());
|
||||
|
||||
// populate with empty images
|
||||
QImage img; //TODO remove
|
||||
QString s;
|
||||
for(int i = 0; i < (int)imageFiles.size(); i++)
|
||||
{
|
||||
addSlide(img);
|
||||
s = imageFiles.at(i);
|
||||
s.remove(s.size()-4,4);
|
||||
if(QFileInfo(s+".r").exists())
|
||||
markSlide(i);
|
||||
}
|
||||
|
||||
setCenterIndex(0);
|
||||
worker->reset();
|
||||
preload();
|
||||
}
|
||||
|
||||
void ComicFlow::preload()
|
||||
{
|
||||
if(numImagesLoaded < imagesLoaded.size())
|
||||
updateTimer->start(30); //TODO comprobar rendimiento, originalmente era 70
|
||||
}
|
||||
|
||||
void ComicFlow::updateImageData()
|
||||
{
|
||||
// can't do anything, wait for the next possibility
|
||||
if(worker->busy())
|
||||
return;
|
||||
|
||||
// set image of last one
|
||||
int idx = worker->index();
|
||||
if( idx >= 0 && !worker->result().isNull())
|
||||
{
|
||||
if(!imagesSetted[idx])
|
||||
{
|
||||
setSlide(idx, worker->result());
|
||||
imagesSetted[idx] = true;
|
||||
numImagesLoaded++;
|
||||
imagesLoaded[idx]=true;
|
||||
}
|
||||
}
|
||||
|
||||
// try to load only few images on the left and right side
|
||||
// i.e. all visible ones plus some extra
|
||||
#define COUNT 8
|
||||
int indexes[2*COUNT+1];
|
||||
int center = centerIndex();
|
||||
indexes[0] = center;
|
||||
for(int j = 0; j < COUNT; j++)
|
||||
{
|
||||
indexes[j*2+1] = center+j+1;
|
||||
indexes[j*2+2] = center-j-1;
|
||||
}
|
||||
for(int c = 0; c < 2*COUNT+1; c++)
|
||||
{
|
||||
int i = indexes[c];
|
||||
if((i >= 0) && (i < slideCount()))
|
||||
if(!imagesLoaded[i])//slide(i).isNull())
|
||||
{
|
||||
// schedule thumbnail generation
|
||||
QString fname = imageFiles[i];
|
||||
|
||||
|
||||
worker->generate(i, fname, slideSize());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// no need to generate anything? stop polling...
|
||||
updateTimer->stop();
|
||||
}
|
||||
|
||||
void ComicFlow::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
PictureFlow::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void ComicFlow::wheelEvent(QWheelEvent * event)
|
||||
{
|
||||
if(event->delta()<0)
|
||||
showNext();
|
||||
else
|
||||
showPrevious();
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void ComicFlow::removeSlide(int cover)
|
||||
{
|
||||
worker->lock();
|
||||
|
||||
worker->reset();
|
||||
|
||||
imageFiles.removeAt(cover);
|
||||
if(imagesLoaded[cover])
|
||||
numImagesLoaded--;
|
||||
imagesLoaded.remove(cover);
|
||||
imagesSetted.remove(cover);
|
||||
|
||||
YACReaderFlow::removeSlide(cover);
|
||||
worker->unlock();
|
||||
|
||||
preload();
|
||||
}
|
||||
|
||||
void ComicFlow::resortCovers(QList<int> newOrder)
|
||||
{
|
||||
worker->lock();
|
||||
worker->reset();
|
||||
|
||||
YACReaderFlow::resortCovers(newOrder);
|
||||
|
||||
QStringList imageFilesNew;
|
||||
QVector<bool> imagesLoadedNew;
|
||||
QVector<bool> imagesSettedNew;
|
||||
foreach(int index, newOrder)
|
||||
{
|
||||
imageFilesNew << imageFiles.at(index);
|
||||
imagesLoadedNew << imagesLoaded.at(index);
|
||||
imagesSettedNew << imagesSetted.at(index);
|
||||
}
|
||||
|
||||
|
||||
|
||||
imageFiles = imageFilesNew;
|
||||
imagesLoaded = imagesLoadedNew;
|
||||
imagesSetted = imagesSettedNew;
|
||||
|
||||
worker->unlock();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
//ImageLoader
|
||||
//-----------------------------------------------------------------------------
|
||||
static QImage loadImage(const QString& fileName)
|
||||
{
|
||||
QImage image;
|
||||
bool result = image.load(fileName);
|
||||
|
||||
if(!result)
|
||||
return QImage();
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
ImageLoader::ImageLoader():
|
||||
QThread(), restart(false), working(false), idx(-1)
|
||||
{
|
||||
}
|
||||
|
||||
ImageLoader::~ImageLoader()
|
||||
{
|
||||
mutex.lock();
|
||||
condition.wakeOne();
|
||||
mutex.unlock();
|
||||
wait();
|
||||
}
|
||||
|
||||
bool ImageLoader::busy() const
|
||||
{
|
||||
return isRunning() ? working : false;
|
||||
}
|
||||
|
||||
void ImageLoader::generate(int index, const QString& fileName, QSize size)
|
||||
{
|
||||
mutex.lock();
|
||||
this->idx = index;
|
||||
this->fileName = fileName;
|
||||
this->size = size;
|
||||
this->img = QImage();
|
||||
mutex.unlock();
|
||||
|
||||
if (!isRunning())
|
||||
start();
|
||||
else
|
||||
{
|
||||
// already running, wake up whenever ready
|
||||
restart = true;
|
||||
condition.wakeOne();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageLoader::lock()
|
||||
{
|
||||
mutex.lock();
|
||||
}
|
||||
|
||||
void ImageLoader::unlock()
|
||||
{
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
void ImageLoader::run()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
// copy necessary data
|
||||
mutex.lock();
|
||||
this->working = true;
|
||||
QString fileName = this->fileName;
|
||||
mutex.unlock();
|
||||
|
||||
QImage image = loadImage(fileName);
|
||||
|
||||
// let everyone knows it is ready
|
||||
mutex.lock();
|
||||
this->working = false;
|
||||
this->img = image;
|
||||
mutex.unlock();
|
||||
|
||||
// put to sleep
|
||||
mutex.lock();
|
||||
if (!this->restart)
|
||||
condition.wait(&mutex);
|
||||
restart = false;
|
||||
mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
QImage ImageLoader::result()
|
||||
{
|
||||
return img;
|
||||
}
|
78
YACReaderLibrary/comic_flow.h
Normal file
78
YACReaderLibrary/comic_flow.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef __COMICFLOW_H
|
||||
#define __COMICFLOW_H
|
||||
|
||||
#include "yacreader_flow.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QImage>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include <QString>
|
||||
#include <QWheelEvent>
|
||||
|
||||
class ImageLoader;
|
||||
class ComicFlow : public YACReaderFlow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComicFlow(QWidget* parent = 0,FlowType flowType = CoverFlowLike);
|
||||
virtual ~ComicFlow();
|
||||
|
||||
void setImagePaths(const QStringList& paths);
|
||||
//bool eventFilter(QObject *target, QEvent *event);
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void removeSlide(int cover);
|
||||
void resortCovers(QList<int> newOrder);
|
||||
|
||||
private slots:
|
||||
void preload();
|
||||
void updateImageData();
|
||||
|
||||
private:
|
||||
//QString imagePath;
|
||||
QStringList imageFiles;
|
||||
QVector<bool> imagesLoaded;
|
||||
QVector<bool> imagesSetted;
|
||||
int numImagesLoaded;
|
||||
QTimer* updateTimer;
|
||||
ImageLoader* worker;
|
||||
virtual void wheelEvent(QWheelEvent * event);
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Source code of ImageLoader class was modified from http://code.google.com/p/photoflow/
|
||||
//------------------------------------------------------------------------------
|
||||
class ImageLoader : public QThread
|
||||
{
|
||||
public:
|
||||
ImageLoader();
|
||||
~ImageLoader();
|
||||
// returns FALSE if worker is still busy and can't take the task
|
||||
bool busy() const;
|
||||
void generate(int index, const QString& fileName, QSize size);
|
||||
void reset(){idx = -1;};
|
||||
int index() const { return idx; };
|
||||
void lock();
|
||||
void unlock();
|
||||
QImage result();
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
QMutex mutex;
|
||||
QWaitCondition condition;
|
||||
|
||||
bool restart;
|
||||
bool working;
|
||||
int idx;
|
||||
QString fileName;
|
||||
QSize size;
|
||||
QImage img;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
355
YACReaderLibrary/comic_flow_widget.cpp
Normal file
355
YACReaderLibrary/comic_flow_widget.cpp
Normal file
@ -0,0 +1,355 @@
|
||||
#include "comic_flow_widget.h"
|
||||
#include <QVBoxLayout>
|
||||
ComicFlowWidget::ComicFlowWidget(QWidget * parent)
|
||||
:QWidget(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ComicFlowWidgetSW::ComicFlowWidgetSW(QWidget * parent)
|
||||
:ComicFlowWidget(parent)
|
||||
{
|
||||
flow = new ComicFlow(parent);
|
||||
|
||||
connect(flow,SIGNAL(centerIndexChanged(int)),this,SIGNAL(centerIndexChanged(int)));
|
||||
connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(selected(unsigned int)));
|
||||
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
l->addWidget(flow);
|
||||
setLayout(l);
|
||||
|
||||
//TODO eleminar "padding"
|
||||
QPalette Pal(palette());
|
||||
// set black background
|
||||
Pal.setColor(QPalette::Background, Qt::black);
|
||||
setAutoFillBackground(true);
|
||||
setPalette(Pal);
|
||||
|
||||
//config
|
||||
QMatrix m;
|
||||
m.rotate(-90);
|
||||
m.scale(-1,1);
|
||||
QImage image(":/images/setRead.png");
|
||||
QImage imageTransformed = image.transformed(m,Qt::SmoothTransformation);
|
||||
setMarkImage(imageTransformed);
|
||||
}
|
||||
|
||||
QSize ComicFlowWidgetSW::minimumSizeHint() const
|
||||
{
|
||||
return flow->minimumSizeHint();
|
||||
}
|
||||
QSize ComicFlowWidgetSW::sizeHint() const
|
||||
{
|
||||
return flow->sizeHint();
|
||||
}
|
||||
|
||||
void ComicFlowWidgetSW::setShowMarks(bool value)
|
||||
{
|
||||
flow->setShowMarks(value);
|
||||
}
|
||||
void ComicFlowWidgetSW::setMarks(QVector<YACReaderComicReadStatus> marks)
|
||||
{
|
||||
flow->setMarks(marks);
|
||||
}
|
||||
void ComicFlowWidgetSW::setMarkImage(QImage & image)
|
||||
{
|
||||
flow->setMarkImage(image);
|
||||
}
|
||||
void ComicFlowWidgetSW::markSlide(int index, YACReaderComicReadStatus status)
|
||||
{
|
||||
flow->markSlide(index,status);
|
||||
}
|
||||
void ComicFlowWidgetSW::unmarkSlide(int index)
|
||||
{
|
||||
flow->unmarkSlide(index);
|
||||
}
|
||||
void ComicFlowWidgetSW::setSlideSize(QSize size)
|
||||
{
|
||||
flow->setSlideSize(size);
|
||||
}
|
||||
void ComicFlowWidgetSW::clear()
|
||||
{
|
||||
flow->clear();
|
||||
}
|
||||
void ComicFlowWidgetSW::setImagePaths(QStringList paths)
|
||||
{
|
||||
flow->setImagePaths(paths);
|
||||
}
|
||||
void ComicFlowWidgetSW::setCenterIndex(int index)
|
||||
{
|
||||
flow->setCenterIndex(index);
|
||||
}
|
||||
void ComicFlowWidgetSW::showSlide(int index)
|
||||
{
|
||||
flow->showSlide(index);
|
||||
}
|
||||
int ComicFlowWidgetSW::centerIndex()
|
||||
{
|
||||
return flow->centerIndex();
|
||||
}
|
||||
void ComicFlowWidgetSW::updateMarks()
|
||||
{
|
||||
flow->updateMarks();
|
||||
}
|
||||
void ComicFlowWidgetSW::setFlowType(FlowType flowType)
|
||||
{
|
||||
flow->setFlowType(flowType);
|
||||
}
|
||||
void ComicFlowWidgetSW::render()
|
||||
{
|
||||
flow->render();
|
||||
}
|
||||
void ComicFlowWidgetSW::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
flow->keyPressEvent(event);
|
||||
}
|
||||
void ComicFlowWidgetSW::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
flow->paintEvent(event);
|
||||
}
|
||||
void ComicFlowWidgetSW::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
flow->mousePressEvent(event);
|
||||
}
|
||||
void ComicFlowWidgetSW::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
flow->resizeEvent(event);
|
||||
}
|
||||
void ComicFlowWidgetSW::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
flow->mouseDoubleClickEvent(event);
|
||||
}
|
||||
void ComicFlowWidgetSW::updateConfig(QSettings * settings)
|
||||
{
|
||||
switch (settings->value(FLOW_TYPE_SW).toInt())
|
||||
{
|
||||
case CoverFlowLike:
|
||||
flow->setFlowType(CoverFlowLike);
|
||||
return;
|
||||
case Strip:
|
||||
flow->setFlowType(Strip);
|
||||
return;
|
||||
case StripOverlapped:
|
||||
flow->setFlowType(StripOverlapped);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ComicFlowWidgetSW::remove(int cover)
|
||||
{
|
||||
flow->removeSlide(cover);
|
||||
}
|
||||
|
||||
void ComicFlowWidgetSW::resortCovers(QList<int> newOrder)
|
||||
{
|
||||
flow->resortCovers(newOrder);
|
||||
}
|
||||
|
||||
#ifndef NO_OPENGL
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
///OpenGL ComicFlow
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ComicFlowWidgetGL::ComicFlowWidgetGL(QWidget * parent)
|
||||
:ComicFlowWidget(parent)
|
||||
{
|
||||
flow = new YACReaderComicFlowGL(parent);
|
||||
|
||||
connect(flow,SIGNAL(centerIndexChanged(int)),this,SIGNAL(centerIndexChanged(int)));
|
||||
connect(flow,SIGNAL(selected(unsigned int)),this,SIGNAL(selected(unsigned int)));
|
||||
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
l->addWidget(flow);
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
setLayout(l);
|
||||
|
||||
//TODO eleminar "padding"
|
||||
QPalette Pal(palette());
|
||||
// set black background
|
||||
Pal.setColor(QPalette::Background, Qt::black);
|
||||
setAutoFillBackground(true);
|
||||
setPalette(Pal);
|
||||
}
|
||||
|
||||
QSize ComicFlowWidgetGL::minimumSizeHint() const
|
||||
{
|
||||
return flow->minimumSizeHint();
|
||||
}
|
||||
QSize ComicFlowWidgetGL::sizeHint() const
|
||||
{
|
||||
return flow->sizeHint();
|
||||
}
|
||||
|
||||
void ComicFlowWidgetGL::setShowMarks(bool value)
|
||||
{
|
||||
flow->setShowMarks(value);
|
||||
}
|
||||
void ComicFlowWidgetGL::setMarks(QVector<YACReaderComicReadStatus> marks)
|
||||
{
|
||||
flow->setMarks(marks);
|
||||
}
|
||||
void ComicFlowWidgetGL::setMarkImage(QImage & image)
|
||||
{
|
||||
flow->setMarkImage(image);
|
||||
}
|
||||
void ComicFlowWidgetGL::markSlide(int index, YACReaderComicReadStatus status)
|
||||
{
|
||||
flow->markSlide(index,status);
|
||||
}
|
||||
void ComicFlowWidgetGL::unmarkSlide(int index)
|
||||
{
|
||||
flow->unmarkSlide(index);
|
||||
}
|
||||
void ComicFlowWidgetGL::setSlideSize(QSize size)
|
||||
{
|
||||
flow->setSlideSize(size);
|
||||
}
|
||||
void ComicFlowWidgetGL::clear()
|
||||
{
|
||||
flow->clear();
|
||||
}
|
||||
void ComicFlowWidgetGL::setImagePaths(QStringList paths)
|
||||
{
|
||||
flow->setImagePaths(paths);
|
||||
}
|
||||
void ComicFlowWidgetGL::setCenterIndex(int index)
|
||||
{
|
||||
flow->setCenterIndex(index);
|
||||
}
|
||||
void ComicFlowWidgetGL::showSlide(int index)
|
||||
{
|
||||
flow->showSlide(index);
|
||||
}
|
||||
int ComicFlowWidgetGL::centerIndex()
|
||||
{
|
||||
return flow->centerIndex();
|
||||
}
|
||||
void ComicFlowWidgetGL::updateMarks()
|
||||
{
|
||||
flow->updateMarks();
|
||||
}
|
||||
void ComicFlowWidgetGL::setFlowType(FlowType flowType)
|
||||
{
|
||||
if(flowType == CoverFlowLike)
|
||||
flow->setPreset(presetYACReaderFlowClassicConfig);
|
||||
else if(flowType == Strip)
|
||||
flow->setPreset(presetYACReaderFlowStripeConfig);
|
||||
else if(flowType == StripOverlapped)
|
||||
flow->setPreset(presetYACReaderFlowOverlappedStripeConfig);
|
||||
else
|
||||
flow->setPreset(defaultYACReaderFlowConfig);
|
||||
}
|
||||
void ComicFlowWidgetGL::render()
|
||||
{
|
||||
flow->render();
|
||||
}
|
||||
void ComicFlowWidgetGL::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
flow->keyPressEvent(event);
|
||||
}
|
||||
void ComicFlowWidgetGL::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
//flow->paintEvent(event);
|
||||
ComicFlowWidget::paintEvent(event);
|
||||
}
|
||||
void ComicFlowWidgetGL::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
flow->mousePressEvent(event);
|
||||
}
|
||||
void ComicFlowWidgetGL::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
flow->resizeGL(event->size().width(),event->size().height());
|
||||
}
|
||||
void ComicFlowWidgetGL::mouseDoubleClickEvent(QMouseEvent* event)
|
||||
{
|
||||
flow->mouseDoubleClickEvent(event);
|
||||
}
|
||||
|
||||
void ComicFlowWidgetGL::updateConfig(QSettings * settings)
|
||||
{
|
||||
Performance performance = medium;
|
||||
|
||||
switch (settings->value(PERFORMANCE).toInt())
|
||||
{
|
||||
case 0:
|
||||
performance = low;
|
||||
break;
|
||||
case 1:
|
||||
performance = medium;
|
||||
break;
|
||||
case 2:
|
||||
performance = high;
|
||||
break;
|
||||
case 3:
|
||||
performance = ultraHigh;
|
||||
break;
|
||||
}
|
||||
|
||||
flow->setPerformance(performance);
|
||||
if(!settings->contains(V_SYNC))
|
||||
flow->useVSync(false);
|
||||
else
|
||||
flow->useVSync(settings->value(V_SYNC).toBool());
|
||||
|
||||
switch (settings->value(FLOW_TYPE_GL).toInt())
|
||||
{
|
||||
case 0:
|
||||
flow->setPreset(presetYACReaderFlowClassicConfig);
|
||||
return;
|
||||
case 1:
|
||||
flow->setPreset(presetYACReaderFlowStripeConfig);
|
||||
return;
|
||||
case 2:
|
||||
flow->setPreset(presetYACReaderFlowOverlappedStripeConfig);
|
||||
return;
|
||||
case 3:
|
||||
flow->setPreset(defaultYACReaderFlowConfig);
|
||||
return;
|
||||
case 4:
|
||||
flow->setPreset(pressetYACReaderFlowDownConfig);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//custom config
|
||||
|
||||
flow->setCF_RX(settings->value(X_ROTATION).toInt());
|
||||
flow->setCF_Y(settings->value(Y_POSITION).toInt());
|
||||
flow->setX_Distance(settings->value(COVER_DISTANCE).toInt());
|
||||
flow->setCenter_Distance(settings->value(CENTRAL_DISTANCE).toInt());
|
||||
flow->setCF_Z(settings->value(ZOOM_LEVEL).toInt());
|
||||
flow->setY_Distance(settings->value(Y_COVER_OFFSET).toInt());
|
||||
flow->setZ_Distance(settings->value(Z_COVER_OFFSET).toInt());
|
||||
flow->setRotation(settings->value(COVER_ROTATION).toInt());
|
||||
flow->setFadeOutDist(settings->value(FADE_OUT_DIST).toInt());
|
||||
flow->setLightStrenght(settings->value(LIGHT_STRENGTH).toInt());
|
||||
flow->setMaxAngle(settings->value(MAX_ANGLE).toInt());
|
||||
|
||||
/* flow->setVisibility(settings->value("visibilityDistance").toInt());
|
||||
flow->setLightStrenght(settings->value("lightStrength").toInt())*/;
|
||||
|
||||
}
|
||||
|
||||
void ComicFlowWidgetGL::remove(int cover)
|
||||
{
|
||||
flow->remove(cover);
|
||||
}
|
||||
|
||||
void ComicFlowWidgetGL::resortCovers(QList<int> newOrder)
|
||||
{
|
||||
flow->resortCovers(newOrder);
|
||||
}
|
||||
#endif
|
||||
//void ComicFlowWidgetGL::setCF_RX(int value){ flow->setCF_RX(value);}
|
||||
//void ComicFlowWidgetGL::setCF_RY(int value){ flow->setCF_RY(value);}
|
||||
//void ComicFlowWidgetGL::setCF_RZ(int value){ flow->setCF_RZ(value);}
|
||||
//void ComicFlowWidgetGL::setZoom(int zoom){ flow->setZoom(zoom);}
|
||||
//void ComicFlowWidgetGL::setRotation(int angle){ flow->setRotation(angle);}
|
||||
//void ComicFlowWidgetGL::setX_Distance(int distance){ flow->setX_Distance(distance);}
|
||||
//void ComicFlowWidgetGL::setCenter_Distance(int distance){ flow->setCenter_Distance(distance);}
|
||||
//void ComicFlowWidgetGL::setZ_Distance(int distance){ flow->setZ_Distance(distance);}
|
||||
//void ComicFlowWidgetGL::setCF_Y(int value){ flow->setCF_Y(value);}
|
||||
//void ComicFlowWidgetGL::setY_Distance(int value){ flow->setY_Distance(value);}
|
||||
//void ComicFlowWidgetGL::setPreset(const Preset & p){ flow->setPreset(p);}
|
133
YACReaderLibrary/comic_flow_widget.h
Normal file
133
YACReaderLibrary/comic_flow_widget.h
Normal file
@ -0,0 +1,133 @@
|
||||
#ifndef __COMIC_FLOW_WIDGET_H
|
||||
#define __COMIC_FLOW_WIDGET_H
|
||||
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "pictureflow.h"
|
||||
#include "comic_flow.h"
|
||||
#ifndef NO_OPENGL
|
||||
#include "yacreader_flow_gl.h"
|
||||
#endif
|
||||
class ComicFlowWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComicFlowWidget(QWidget * paret = 0);
|
||||
|
||||
public slots:
|
||||
virtual void setShowMarks(bool value) = 0;
|
||||
virtual void setMarks(QVector<YACReaderComicReadStatus> marks) = 0;
|
||||
virtual void setMarkImage(QImage & image) = 0;
|
||||
virtual void markSlide(int index, YACReaderComicReadStatus status) = 0;
|
||||
virtual void unmarkSlide(int index) = 0;
|
||||
virtual void setSlideSize(QSize size) = 0;
|
||||
virtual void clear() = 0;
|
||||
virtual void setImagePaths(QStringList paths) = 0;
|
||||
virtual void setCenterIndex(int index) = 0;
|
||||
virtual void showSlide(int index) = 0;
|
||||
virtual int centerIndex() = 0;
|
||||
virtual void updateMarks() = 0;
|
||||
virtual void setFlowType(FlowType flowType) = 0;
|
||||
virtual void render() = 0;
|
||||
virtual void updateConfig(QSettings * settings) = 0;
|
||||
virtual void remove(int cover) = 0;
|
||||
virtual void resortCovers(QList<int> newOrder) = 0;
|
||||
signals:
|
||||
void centerIndexChanged(int);
|
||||
void selected(unsigned int);
|
||||
};
|
||||
|
||||
|
||||
class ComicFlowWidgetSW : public ComicFlowWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
ComicFlow * flow;
|
||||
public:
|
||||
ComicFlowWidgetSW(QWidget * parent = 0);
|
||||
|
||||
void setShowMarks(bool value);
|
||||
void setMarks(QVector<YACReaderComicReadStatus> marks);
|
||||
void setMarkImage(QImage & image);
|
||||
void markSlide(int index, YACReaderComicReadStatus status);
|
||||
void unmarkSlide(int index);
|
||||
void setSlideSize(QSize size);
|
||||
void clear();
|
||||
void setImagePaths(QStringList paths);
|
||||
void setCenterIndex(int index);
|
||||
void showSlide(int index);
|
||||
int centerIndex();
|
||||
void updateMarks();
|
||||
void setFlowType(FlowType flowType);
|
||||
void render();
|
||||
void updateConfig(QSettings * settings);
|
||||
void remove(int cover);
|
||||
void resortCovers(QList<int> newOrder);
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
void mouseDoubleClickEvent(QMouseEvent* event);
|
||||
QSize minimumSizeHint() const;
|
||||
QSize sizeHint() const;
|
||||
QSize slideSizeW;
|
||||
QSize slideSizeF;
|
||||
};
|
||||
|
||||
#ifndef NO_OPENGL
|
||||
class ComicFlowWidgetGL : public ComicFlowWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
YACReaderComicFlowGL * flow;
|
||||
public:
|
||||
ComicFlowWidgetGL(QWidget * parent = 0);
|
||||
|
||||
void setShowMarks(bool value);
|
||||
void setMarks(QVector<YACReaderComicReadStatus> marks);
|
||||
void setMarkImage(QImage & image);
|
||||
void markSlide(int index, YACReaderComicReadStatus status);
|
||||
void unmarkSlide(int index);
|
||||
void setSlideSize(QSize size);
|
||||
void clear();
|
||||
void setImagePaths(QStringList paths);
|
||||
void setCenterIndex(int index);
|
||||
void showSlide(int index);
|
||||
int centerIndex();
|
||||
void updateMarks();
|
||||
void setFlowType(FlowType flowType);
|
||||
void render();
|
||||
void updateConfig(QSettings * settings);
|
||||
void remove(int cover);
|
||||
void resortCovers(QList<int> newOrder);
|
||||
//public slots:
|
||||
// void setCF_RX(int value);
|
||||
// //the Y Rotation of the Coverflow
|
||||
// void setCF_RY(int value);
|
||||
// //the Z Rotation of the Coverflow
|
||||
// void setCF_RZ(int value);
|
||||
// //perspective
|
||||
// void setZoom(int zoom);
|
||||
// void setRotation(int angle);
|
||||
// //sets the distance between the covers
|
||||
// void setX_Distance(int distance);
|
||||
// //sets the distance between the centered and the non centered covers
|
||||
// void setCenter_Distance(int distance);
|
||||
// //sets the pushback amount
|
||||
// void setZ_Distance(int distance);
|
||||
// void setCF_Y(int value);
|
||||
// void setY_Distance(int value);
|
||||
// void setPreset(const Preset & p);
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
void mouseDoubleClickEvent(QMouseEvent* event);
|
||||
QSize minimumSizeHint() const;
|
||||
QSize sizeHint() const;
|
||||
};
|
||||
#endif
|
||||
#endif
|
68
YACReaderLibrary/comic_vine/api_key_dialog.cpp
Normal file
68
YACReaderLibrary/comic_vine/api_key_dialog.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include "api_key_dialog.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QSettings>
|
||||
|
||||
#include "yacreader_global_gui.h"
|
||||
|
||||
ApiKeyDialog::ApiKeyDialog(QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
QVBoxLayout * layout = new QVBoxLayout;
|
||||
QHBoxLayout * buttonsLayout = new QHBoxLayout;
|
||||
|
||||
settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor
|
||||
settings->beginGroup("ComicVine");
|
||||
|
||||
QLabel * info = new QLabel(tr("Before you can connect to Comic Vine, you need your own API key. Please, get one free <a href=\"http://www.comicvine.com/api/\">here</a>"));
|
||||
info->setWordWrap(true);
|
||||
info->setOpenExternalLinks(true);
|
||||
edit = new QLineEdit();
|
||||
edit->setPlaceholderText(tr("Paste here your Comic Vine API key"));
|
||||
connect(edit,SIGNAL(textChanged(QString)),this,SLOT(enableAccept(QString)));
|
||||
|
||||
acceptButton = new QPushButton(tr("Accept"));
|
||||
acceptButton->setDisabled(true);
|
||||
connect(acceptButton,SIGNAL(clicked()),this,SLOT(saveApiKey()));
|
||||
|
||||
cancelButton = new QPushButton(tr("Cancel"));
|
||||
connect(cancelButton,SIGNAL(clicked()),this,SLOT(reject()));
|
||||
|
||||
layout->addWidget(info);
|
||||
layout->addWidget(edit);
|
||||
layout->addStretch();
|
||||
|
||||
buttonsLayout->addStretch();
|
||||
buttonsLayout->addWidget(acceptButton);
|
||||
buttonsLayout->addWidget(cancelButton);
|
||||
|
||||
layout->addLayout(buttonsLayout);
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
resize(400,150);
|
||||
|
||||
if(settings->contains(COMIC_VINE_API_KEY))
|
||||
edit->setText(settings->value(COMIC_VINE_API_KEY).toString());
|
||||
}
|
||||
|
||||
ApiKeyDialog::~ApiKeyDialog()
|
||||
{
|
||||
delete settings;
|
||||
}
|
||||
|
||||
void ApiKeyDialog::enableAccept(const QString &text)
|
||||
{
|
||||
//TODO key validation
|
||||
acceptButton->setEnabled(!text.isEmpty());
|
||||
}
|
||||
|
||||
void ApiKeyDialog::saveApiKey()
|
||||
{
|
||||
settings->setValue(COMIC_VINE_API_KEY,edit->text());
|
||||
accept();
|
||||
}
|
31
YACReaderLibrary/comic_vine/api_key_dialog.h
Normal file
31
YACReaderLibrary/comic_vine/api_key_dialog.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef API_KEY_DIALOG_H
|
||||
#define API_KEY_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QPushButton;
|
||||
class QLineEdit;
|
||||
class QSettings;
|
||||
|
||||
class ApiKeyDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ApiKeyDialog(QWidget *parent = 0);
|
||||
~ApiKeyDialog();
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
protected slots:
|
||||
void enableAccept(const QString & text);
|
||||
void saveApiKey();
|
||||
|
||||
protected:
|
||||
QPushButton * acceptButton;
|
||||
QPushButton * cancelButton;
|
||||
QLineEdit * edit;
|
||||
QSettings * settings;
|
||||
};
|
||||
|
||||
#endif // API_KEY_DIALOG_H
|
46
YACReaderLibrary/comic_vine/comic_vine.pri
Normal file
46
YACReaderLibrary/comic_vine/comic_vine.pri
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
HEADERS += \
|
||||
comic_vine/comic_vine_dialog.h \
|
||||
comic_vine/comic_vine_client.h \
|
||||
comic_vine/scraper_lineedit.h \
|
||||
comic_vine/title_header.h \
|
||||
comic_vine/series_question.h \
|
||||
comic_vine/search_single_comic.h \
|
||||
comic_vine/search_volume.h \
|
||||
comic_vine/select_comic.h \
|
||||
comic_vine/select_volume.h \
|
||||
comic_vine/model/volumes_model.h \
|
||||
comic_vine/model/comics_model.h \
|
||||
comic_vine/model/json_model.h \
|
||||
comic_vine/model/response_parser.h \
|
||||
comic_vine/scraper_tableview.h \
|
||||
comic_vine/sort_volume_comics.h \
|
||||
comic_vine/model/local_comic_list_model.h \
|
||||
comic_vine/model/volume_comics_model.h \
|
||||
comic_vine/scraper_scroll_label.h \
|
||||
comic_vine/scraper_results_paginator.h \
|
||||
comic_vine/scraper_selector.h \
|
||||
comic_vine/api_key_dialog.h
|
||||
|
||||
SOURCES += \
|
||||
comic_vine/comic_vine_dialog.cpp \
|
||||
comic_vine/comic_vine_client.cpp \
|
||||
comic_vine/scraper_lineedit.cpp \
|
||||
comic_vine/title_header.cpp \
|
||||
comic_vine/series_question.cpp \
|
||||
comic_vine/search_single_comic.cpp \
|
||||
comic_vine/search_volume.cpp \
|
||||
comic_vine/select_comic.cpp \
|
||||
comic_vine/select_volume.cpp \
|
||||
comic_vine/model/volumes_model.cpp \
|
||||
comic_vine/model/comics_model.cpp \
|
||||
comic_vine/model/json_model.cpp \
|
||||
comic_vine/model/response_parser.cpp \
|
||||
comic_vine/scraper_tableview.cpp \
|
||||
comic_vine/sort_volume_comics.cpp \
|
||||
comic_vine/model/local_comic_list_model.cpp \
|
||||
comic_vine/model/volume_comics_model.cpp \
|
||||
comic_vine/scraper_scroll_label.cpp \
|
||||
comic_vine/scraper_results_paginator.cpp \
|
||||
comic_vine/scraper_selector.cpp \
|
||||
comic_vine/api_key_dialog.cpp
|
173
YACReaderLibrary/comic_vine/comic_vine_client.cpp
Normal file
173
YACReaderLibrary/comic_vine/comic_vine_client.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include "comic_vine_client.h"
|
||||
#include "yacreader_global_gui.h"
|
||||
|
||||
//this is the API key used by YACReader to access Comic Vine
|
||||
//please, do not use it in your own software, get one for free at Comic Vine
|
||||
static const QString CV_API_KEY = "%CV_API_KEY%"; //get from settings
|
||||
static const QString CV_API_KEY_DEFAULT = "46680bebb358f1de690a5a365e15d325f9649f91";
|
||||
|
||||
static const QString CV_WEB_ADDRESS = "%CV_WEB_ADDRESS%"; //get from settings
|
||||
|
||||
//gets any volumen containing any comic matching 'query'
|
||||
static const QString CV_SEARCH = CV_WEB_ADDRESS + "/search/?api_key=" + CV_API_KEY +
|
||||
"&format=json&limit=100&resources=volume"
|
||||
"&field_list=name,start_year,publisher,id,image,count_of_issues,deck"
|
||||
"&sort=name:asc"
|
||||
"&query=%1&page=%2";
|
||||
//http://www.comicvine.com/api/search/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&format=json&limit=100&resources=volume&field_list=name,start_year,publisher,id,image,count_of_issues,deck&query=superman
|
||||
|
||||
//gets the detail for a volume %1
|
||||
static const QString CV_SERIES_DETAIL = CV_WEB_ADDRESS + "/volume/4050-%1/?api_key=" + CV_API_KEY +
|
||||
"&format=json&field_list=name,start_year,publisher,image,count_of_issues,id,description";
|
||||
|
||||
//gets info for comics in a volume id %1
|
||||
static const QString CV_COMICS_INFO = CV_WEB_ADDRESS + "/issues/?api_key=" + CV_API_KEY +
|
||||
"&format=json&field_list=name,issue_number,id,image&filter=volume:%1"
|
||||
"&sort=cover_date:asc" //sorting by cover_date, because comic vine doesn't use natural sorting (issue_number -> 1 10 11 ... 100 2 20 21....)
|
||||
"&offset=%2";
|
||||
|
||||
//"http://www.comicvine.com/api/issues/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&format=json&field_list=name,issue_number,id,image&filter=volume:%1&page=%2
|
||||
|
||||
//gets id for comic number %2 in a volume id %1
|
||||
static const QString CV_COMIC_ID = CV_WEB_ADDRESS + "/issues/?api_key=" + CV_API_KEY +
|
||||
"&format=json&field_list=name,issue_number,id,image"
|
||||
"&filter=volume:%1,issue_number:%2";
|
||||
//gets comic detail
|
||||
static const QString CV_COMIC_DETAIL = CV_WEB_ADDRESS + "/issue/4000-%1/?api_key=" + CV_API_KEY + "&format=json";
|
||||
//http://www.comicvine.com/api/issue/4000-%1/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&format=json
|
||||
|
||||
//gets comic cover URL
|
||||
static const QString CV_COVER_URL = CV_WEB_ADDRESS + "/issue/4000-%1/?api_key=" + CV_API_KEY + "&format=json&field_list=image";
|
||||
|
||||
//gets comics matching name %1 and number %2
|
||||
//http://comicvine.com/api/issues/?api_key=46680bebb358f1de690a5a365e15d325f9649f91&limit=20&filter=name:super,issue_number:15
|
||||
|
||||
ComicVineClient::ComicVineClient(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat); //TODO unificar la creación del fichero de config con el servidor
|
||||
settings->beginGroup("ComicVine");
|
||||
baseURL = settings->value(COMIC_VINE_BASE_URL, "http://comicvine.gamespot.com/api").toString();
|
||||
}
|
||||
|
||||
ComicVineClient::~ComicVineClient()
|
||||
{
|
||||
delete settings;
|
||||
}
|
||||
|
||||
//CV_SEARCH
|
||||
void ComicVineClient::search(const QString & query, int page)
|
||||
{
|
||||
HttpWorker * search = new HttpWorker(QString(CV_SEARCH).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(query).arg(page));
|
||||
connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessVolumesSearchData(const QByteArray &)));
|
||||
connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut()));
|
||||
connect(search,SIGNAL(finished()),search,SLOT(deleteLater()));
|
||||
search->get();
|
||||
}
|
||||
//CV_SEARCH result
|
||||
void ComicVineClient::proccessVolumesSearchData(const QByteArray & data)
|
||||
{
|
||||
QString json(data);
|
||||
emit searchResult(json);
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void ComicVineClient::proccessSeriesDetailData(const QByteArray &data)
|
||||
{
|
||||
QString json(data);
|
||||
emit seriesDetail(json);
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void ComicVineClient::processVolumeComicsInfo(const QByteArray &data)
|
||||
{
|
||||
QString json(data);
|
||||
emit volumeComicsInfo(json);
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void ComicVineClient::proccessComicDetailData(const QByteArray &data)
|
||||
{
|
||||
QString json(data);
|
||||
emit comicDetail(json);
|
||||
emit finished();
|
||||
}
|
||||
|
||||
//CV_SERIES_DETAIL
|
||||
void ComicVineClient::getSeriesDetail(const QString & id)
|
||||
{
|
||||
HttpWorker * search = new HttpWorker(QString(CV_SERIES_DETAIL).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(id));
|
||||
connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessSeriesDetailData(const QByteArray &)));
|
||||
connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut()));
|
||||
connect(search,SIGNAL(finished()),search,SLOT(deleteLater()));
|
||||
search->get();
|
||||
}
|
||||
|
||||
void ComicVineClient::getSeriesCover(const QString & url)
|
||||
{
|
||||
HttpWorker * search = new HttpWorker(url);
|
||||
connect(search,SIGNAL(dataReady(const QByteArray &)),this,SIGNAL(seriesCover(const QByteArray &)));
|
||||
connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); //TODO
|
||||
connect(search,SIGNAL(finished()),search,SLOT(deleteLater()));
|
||||
search->get();
|
||||
}
|
||||
|
||||
//CV_COMIC_IDS
|
||||
void ComicVineClient::getVolumeComicsInfo(const QString & idVolume, int page)
|
||||
{
|
||||
HttpWorker * search = new HttpWorker(QString(CV_COMICS_INFO).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(idVolume).arg((page-1)*100)); //page on works for search, using offset instead
|
||||
connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(processVolumeComicsInfo(const QByteArray &)));
|
||||
connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); //TODO
|
||||
connect(search,SIGNAL(finished()),search,SLOT(deleteLater()));
|
||||
search->get();
|
||||
}
|
||||
|
||||
//CV_COMIC_ID
|
||||
void ComicVineClient::getComicId(const QString & id, int comicNumber)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//CV_COMIC_DETAIL
|
||||
QByteArray ComicVineClient::getComicDetail(const QString & id, bool & outError, bool & outTimeout)
|
||||
{
|
||||
HttpWorker * search = new HttpWorker(QString(CV_COMIC_DETAIL).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(id));
|
||||
|
||||
//connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessComicDetailData(const QByteArray &)));
|
||||
//connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut()));
|
||||
//connect(search,SIGNAL(finished()),search,SLOT(deleteLater()));
|
||||
search->get();
|
||||
search->wait();
|
||||
outError = !(search->wasValid());
|
||||
outTimeout = search->wasTimeout();
|
||||
QByteArray result = search->getResult();
|
||||
delete search;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//CV_COMIC_DETAIL
|
||||
void ComicVineClient::getComicDetailAsync(const QString & id)
|
||||
{
|
||||
HttpWorker * search = new HttpWorker(QString(CV_COMIC_DETAIL).replace(CV_WEB_ADDRESS, baseURL).replace(CV_API_KEY,settings->value(COMIC_VINE_API_KEY,CV_API_KEY_DEFAULT).toString()).arg(id));
|
||||
|
||||
connect(search,SIGNAL(dataReady(const QByteArray &)),this,SLOT(proccessComicDetailData(const QByteArray &)));
|
||||
connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut()));
|
||||
connect(search,SIGNAL(finished()),search,SLOT(deleteLater()));
|
||||
search->get();
|
||||
}
|
||||
|
||||
void ComicVineClient::getComicCover(const QString &url)
|
||||
{
|
||||
HttpWorker * search = new HttpWorker(url);
|
||||
connect(search,SIGNAL(dataReady(const QByteArray &)),this,SIGNAL(comicCover(QByteArray)));
|
||||
connect(search,SIGNAL(timeout()),this,SIGNAL(timeOut())); //TODO
|
||||
connect(search,SIGNAL(finished()),search,SLOT(deleteLater()));
|
||||
search->get();
|
||||
}
|
||||
|
||||
//CV_COVER_DETAIL
|
||||
void ComicVineClient::getCoverURL(const QString & id)
|
||||
{
|
||||
|
||||
}
|
47
YACReaderLibrary/comic_vine/comic_vine_client.h
Normal file
47
YACReaderLibrary/comic_vine/comic_vine_client.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef COMIC_VINE_CLIENT_H
|
||||
#define COMIC_VINE_CLIENT_H
|
||||
|
||||
#include "http_worker.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QSettings>
|
||||
|
||||
class ComicVineClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComicVineClient(QObject *parent = 0);
|
||||
~ComicVineClient();
|
||||
|
||||
signals:
|
||||
void searchResult(QString);
|
||||
void seriesDetail(QString);//JSON
|
||||
void comicDetail(QString);//JSON
|
||||
void seriesCover(const QByteArray &);
|
||||
void comicCover(const QByteArray &);
|
||||
void volumeComicsInfo(QString);
|
||||
void timeOut();
|
||||
void finished();
|
||||
public slots:
|
||||
void search(const QString & query, int page = 1);
|
||||
void getSeriesDetail(const QString & id);
|
||||
void getSeriesCover(const QString & url);
|
||||
void getVolumeComicsInfo(const QString & idVolume, int page=1);
|
||||
QByteArray getComicDetail(const QString & id, bool &outError, bool &outTimeout);
|
||||
void getComicCover(const QString & url);
|
||||
|
||||
void getComicId(const QString & id, int comicNumber);
|
||||
void getCoverURL(const QString & id);
|
||||
void getComicDetailAsync(const QString &id);
|
||||
protected slots:
|
||||
void proccessVolumesSearchData(const QByteArray & data);
|
||||
void proccessSeriesDetailData(const QByteArray & data);
|
||||
void processVolumeComicsInfo(const QByteArray & data);
|
||||
void proccessComicDetailData(const QByteArray & data);
|
||||
|
||||
protected:
|
||||
QSettings * settings;
|
||||
QString baseURL;
|
||||
|
||||
};
|
||||
#endif // COMIC_VINE_CLIENT_H
|
722
YACReaderLibrary/comic_vine/comic_vine_dialog.cpp
Normal file
722
YACReaderLibrary/comic_vine/comic_vine_dialog.cpp
Normal file
@ -0,0 +1,722 @@
|
||||
#include "comic_vine_dialog.h"
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QStackedWidget>
|
||||
#include <QRadioButton>
|
||||
#include <QMessageBox>
|
||||
#include <QTableView>
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#else
|
||||
#include <QtConcurrentRun>
|
||||
#endif
|
||||
#include <QSqlDatabase>
|
||||
#include <QtScript>
|
||||
#include "data_base_management.h"
|
||||
|
||||
#include "yacreader_busy_widget.h"
|
||||
#include "comic_vine_client.h"
|
||||
#include "scraper_lineedit.h"
|
||||
#include "title_header.h"
|
||||
#include "series_question.h"
|
||||
#include "search_single_comic.h"
|
||||
#include "search_volume.h"
|
||||
#include "select_comic.h"
|
||||
#include "select_volume.h"
|
||||
#include "sort_volume_comics.h"
|
||||
#include "db_helper.h"
|
||||
#include "response_parser.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
|
||||
|
||||
ComicVineDialog::ComicVineDialog(QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
doLayout();
|
||||
doStackedWidgets();
|
||||
doConnections();
|
||||
}
|
||||
|
||||
void ComicVineDialog::doLayout()
|
||||
{
|
||||
setStyleSheet(""
|
||||
"QDialog {background-color: #404040; }"
|
||||
"");
|
||||
|
||||
QString dialogButtonsStyleSheet = "QPushButton {border: 1px solid #242424; background: #2e2e2e; color:white; padding: 5px 26px 5px 26px; font-size:12px;font-family:Arial; font-weight:bold;}";
|
||||
|
||||
skipButton = new QPushButton(tr("skip"));
|
||||
backButton = new QPushButton(tr("back"));
|
||||
nextButton = new QPushButton(tr("next"));
|
||||
searchButton = new QPushButton(tr("search"));
|
||||
closeButton = new QPushButton(tr("close"));
|
||||
|
||||
skipButton->setStyleSheet(dialogButtonsStyleSheet);
|
||||
backButton->setStyleSheet(dialogButtonsStyleSheet);
|
||||
nextButton->setStyleSheet(dialogButtonsStyleSheet);
|
||||
searchButton->setStyleSheet(dialogButtonsStyleSheet);
|
||||
closeButton->setStyleSheet(dialogButtonsStyleSheet);
|
||||
|
||||
content = new QStackedWidget(this);
|
||||
|
||||
QVBoxLayout * mainLayout = new QVBoxLayout;
|
||||
|
||||
QHBoxLayout * buttonLayout = new QHBoxLayout;
|
||||
|
||||
buttonLayout->addStretch();
|
||||
buttonLayout->addWidget(skipButton);
|
||||
buttonLayout->addWidget(backButton);
|
||||
buttonLayout->addWidget(nextButton);
|
||||
buttonLayout->addWidget(searchButton);
|
||||
buttonLayout->addWidget(closeButton);
|
||||
buttonLayout->setContentsMargins(0,0,0,0);
|
||||
|
||||
mainLayout->addWidget(titleHeader = new TitleHeader);
|
||||
mainLayout->addWidget(content);
|
||||
mainLayout->addStretch();
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
|
||||
mainLayout->setContentsMargins(26,16,26,11);
|
||||
|
||||
setLayout(mainLayout);
|
||||
setFixedSize(872,529);
|
||||
|
||||
setWindowTitle("Comic Vine Scraper (beta)");
|
||||
}
|
||||
|
||||
void ComicVineDialog::doStackedWidgets()
|
||||
{
|
||||
doLoading();
|
||||
content->addWidget(seriesQuestionWidget = new SeriesQuestion);
|
||||
content->addWidget(searchSingleComicWidget = new SearchSingleComic);
|
||||
content->addWidget(searchVolumeWidget = new SearchVolume);
|
||||
content->addWidget(selectVolumeWidget = new SelectVolume);
|
||||
content->addWidget(selectComicWidget = new SelectComic);
|
||||
content->addWidget(sortVolumeComicsWidget = new SortVolumeComics);
|
||||
}
|
||||
|
||||
void ComicVineDialog::doConnections()
|
||||
{
|
||||
connect(closeButton,SIGNAL(clicked()),this,SLOT(close()));
|
||||
connect(nextButton,SIGNAL(clicked()),this,SLOT(goNext()));
|
||||
connect(backButton,SIGNAL(clicked()),this,SLOT(goBack()));
|
||||
connect(searchButton,SIGNAL(clicked()),this,SLOT(search()));
|
||||
connect(skipButton,SIGNAL(clicked()),this,SLOT(goToNextComic()));
|
||||
|
||||
connect(selectVolumeWidget,SIGNAL(loadPage(QString,int)),this,SLOT(searchVolume(QString,int)));
|
||||
connect(selectComicWidget,SIGNAL(loadPage(QString,int)),this,SLOT(getVolumeComicsInfo(QString,int)));
|
||||
connect(sortVolumeComicsWidget,SIGNAL(loadPage(QString,int)),this,SLOT(getVolumeComicsInfo(QString,int)));
|
||||
}
|
||||
|
||||
void ComicVineDialog::goNext()
|
||||
{
|
||||
//
|
||||
if(content->currentWidget() == seriesQuestionWidget)
|
||||
{
|
||||
if(seriesQuestionWidget->getYes())
|
||||
{
|
||||
QString volumeSearchString = comics[0].getParentFolderName();
|
||||
mode = Volume;
|
||||
|
||||
if(volumeSearchString.isEmpty())
|
||||
showSearchVolume();
|
||||
else
|
||||
{
|
||||
status = AutoSearching;
|
||||
showLoading(tr("Looking for volume..."));
|
||||
searchVolume(volumeSearchString);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = AutoSearching;
|
||||
mode = SingleComicInList;
|
||||
ComicDB comic = comics[currentIndex];
|
||||
QString title = comic.getTitleOrFileName();
|
||||
titleHeader->setSubTitle(tr("comic %1 of %2 - %3").arg(currentIndex+1).arg(comics.length()).arg(title));
|
||||
|
||||
showLoading(tr("Looking for volume..."));
|
||||
searchVolume(title);
|
||||
}
|
||||
}
|
||||
else if (content->currentWidget() == selectVolumeWidget) {
|
||||
currentVolumeId = selectVolumeWidget->getSelectedVolumeId();
|
||||
getVolumeComicsInfo(currentVolumeId);
|
||||
|
||||
} else if (content->currentWidget() == sortVolumeComicsWidget) {
|
||||
showLoading();
|
||||
|
||||
//ComicDB-ComicVineID
|
||||
QList<QPair<ComicDB,QString> > matchingInfo = sortVolumeComicsWidget->getMatchingInfo();
|
||||
int count = selectVolumeWidget->getSelectedVolumeNumIssues();
|
||||
QString publisher = selectVolumeWidget->getSelectedVolumePublisher();
|
||||
QtConcurrent::run(this, &ComicVineDialog::getComicsInfo,matchingInfo,count,publisher);
|
||||
} else if (content->currentWidget() == selectComicWidget)
|
||||
{
|
||||
showLoading();
|
||||
QString comicId = selectComicWidget->getSelectedComicId();
|
||||
int count = selectVolumeWidget->getSelectedVolumeNumIssues();
|
||||
QString publisher = selectVolumeWidget->getSelectedVolumePublisher();
|
||||
QtConcurrent::run(this, &ComicVineDialog::getComicInfo,comicId,count,publisher);
|
||||
}
|
||||
}
|
||||
|
||||
void ComicVineDialog::goBack()
|
||||
{
|
||||
switch (status) {
|
||||
case SelectingSeries:
|
||||
if(mode == Volume)
|
||||
showSearchVolume();
|
||||
else
|
||||
showSearchSingleComic();
|
||||
break;
|
||||
case SortingComics:
|
||||
showSelectVolume();
|
||||
break;
|
||||
case SelectingComic:
|
||||
if(mode == SingleComic)
|
||||
showSelectVolume();
|
||||
break;
|
||||
case AutoSearching:
|
||||
if(mode == Volume)
|
||||
showSearchVolume();
|
||||
else
|
||||
showSearchSingleComic();
|
||||
default:
|
||||
if(mode == Volume)
|
||||
showSearchVolume();
|
||||
else
|
||||
showSearchSingleComic();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ComicVineDialog::setComics(const QList<ComicDB> & comics)
|
||||
{
|
||||
this->comics = comics;
|
||||
}
|
||||
|
||||
void ComicVineDialog::show()
|
||||
{
|
||||
QDialog::show();
|
||||
|
||||
currentIndex = 0;
|
||||
|
||||
seriesQuestionWidget->setYes(true);
|
||||
searchSingleComicWidget->clean();
|
||||
searchVolumeWidget->clean();
|
||||
|
||||
if(comics.length() == 1)
|
||||
{
|
||||
status = AutoSearching;
|
||||
mode = SingleComic;
|
||||
|
||||
ComicDB singleComic = comics[0];
|
||||
QString title = singleComic.getTitleOrFileName();
|
||||
titleHeader->setSubTitle(title);
|
||||
showLoading(tr("Looking for volume..."));
|
||||
|
||||
searchVolume(singleComic.getParentFolderName());
|
||||
QLOG_TRACE() << singleComic.getParentFolderName();
|
||||
}else if(comics.length()>1)
|
||||
{
|
||||
titleHeader->setSubTitle(tr("%1 comics selected").arg(comics.length()));
|
||||
showSeriesQuestion();
|
||||
}
|
||||
}
|
||||
|
||||
void ComicVineDialog::doLoading()
|
||||
{
|
||||
QWidget * w = new QWidget;
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
|
||||
YACReaderBusyWidget * bw = new YACReaderBusyWidget;
|
||||
loadingMessage = new QLabel;
|
||||
|
||||
loadingMessage->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}");
|
||||
|
||||
l->addStretch();
|
||||
l->addWidget(bw,0,Qt::AlignHCenter);
|
||||
l->addStretch();
|
||||
l->addWidget(loadingMessage);
|
||||
|
||||
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
w->setLayout(l);
|
||||
w->setContentsMargins(0,0,0,0);
|
||||
|
||||
content->addWidget(w);
|
||||
}
|
||||
|
||||
void ComicVineDialog::debugClientResults(const QString & string)
|
||||
{
|
||||
ResponseParser p;
|
||||
p.loadJSONResponse(string);
|
||||
//QMessageBox::information(0,"Result", QString("Number of results : %1").arg(p.getNumResults()));
|
||||
if(p.responseError())
|
||||
{
|
||||
QMessageBox::critical(0,tr("Error connecting to ComicVine"), p.errorDescription());
|
||||
goBack();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case SingleComic: case SingleComicInList:
|
||||
if(p.getNumResults() == 0)
|
||||
showSearchSingleComic();
|
||||
else
|
||||
if(status == SearchingVolume)
|
||||
showSelectVolume(string);
|
||||
else
|
||||
showSelectComic(string);
|
||||
break;
|
||||
case Volume:
|
||||
if(p.getNumResults() == 0)
|
||||
showSearchVolume();
|
||||
else
|
||||
showSelectVolume(string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ComicVineDialog::showSeriesQuestion()
|
||||
{
|
||||
status = AskingForInfo;
|
||||
content->setCurrentWidget(seriesQuestionWidget);
|
||||
backButton->setHidden(true);
|
||||
skipButton->setHidden(true);
|
||||
nextButton->setVisible(true);
|
||||
searchButton->setHidden(true);
|
||||
closeButton->setVisible(true);
|
||||
|
||||
if(mode == SingleComicInList)
|
||||
skipButton->setVisible(true);
|
||||
else
|
||||
skipButton->setHidden(true);
|
||||
}
|
||||
|
||||
void ComicVineDialog::showSearchSingleComic()
|
||||
{
|
||||
status = AskingForInfo;
|
||||
content->setCurrentWidget(searchSingleComicWidget);
|
||||
backButton->setHidden(true);
|
||||
skipButton->setHidden(true);
|
||||
nextButton->setHidden(true);
|
||||
searchButton->setVisible(true);
|
||||
closeButton->setVisible(true);
|
||||
|
||||
if(mode == SingleComicInList)
|
||||
skipButton->setVisible(true);
|
||||
else
|
||||
skipButton->setHidden(true);
|
||||
}
|
||||
|
||||
void ComicVineDialog::showSearchVolume()
|
||||
{
|
||||
status = AskingForInfo;
|
||||
content->setCurrentWidget(searchVolumeWidget);
|
||||
backButton->setHidden(true);
|
||||
nextButton->setHidden(true);
|
||||
searchButton->setVisible(true);
|
||||
closeButton->setVisible(true);
|
||||
toggleSkipButton();
|
||||
}
|
||||
|
||||
void ComicVineDialog::showSelectVolume(const QString & json)
|
||||
{
|
||||
showSelectVolume();
|
||||
selectVolumeWidget->load(json,currentVolumeSearchString);
|
||||
}
|
||||
|
||||
void ComicVineDialog::showSelectVolume()
|
||||
{
|
||||
status = SelectingSeries;
|
||||
|
||||
content->setCurrentWidget(selectVolumeWidget);
|
||||
|
||||
backButton->setVisible(true);
|
||||
nextButton->setVisible(true);
|
||||
searchButton->setHidden(true);
|
||||
closeButton->setVisible(true);
|
||||
toggleSkipButton();
|
||||
}
|
||||
|
||||
void ComicVineDialog::showSelectComic(const QString &json)
|
||||
{
|
||||
status = SelectingComic;
|
||||
|
||||
content->setCurrentWidget(selectComicWidget);
|
||||
selectComicWidget->load(json,currentVolumeId);
|
||||
|
||||
backButton->setVisible(true);
|
||||
nextButton->setVisible(true);
|
||||
searchButton->setHidden(true);
|
||||
closeButton->setVisible(true);
|
||||
toggleSkipButton();
|
||||
}
|
||||
|
||||
void ComicVineDialog::showSortVolumeComics(const QString &json)
|
||||
{
|
||||
status = SortingComics;
|
||||
|
||||
content->setCurrentWidget(sortVolumeComicsWidget);
|
||||
|
||||
sortVolumeComicsWidget->setData(comics, json, currentVolumeId);
|
||||
|
||||
backButton->setVisible(true);
|
||||
nextButton->setVisible(true);
|
||||
searchButton->setHidden(true);
|
||||
closeButton->setVisible(true);
|
||||
toggleSkipButton();
|
||||
}
|
||||
|
||||
void ComicVineDialog::queryTimeOut()
|
||||
{
|
||||
QMessageBox::warning(this,"Comic Vine error", "Time out connecting to Comic Vine");
|
||||
|
||||
switch (status) {
|
||||
case AutoSearching:
|
||||
if(mode == Volume)
|
||||
showSearchVolume();
|
||||
else
|
||||
showSearchSingleComic();
|
||||
break;
|
||||
case SearchingVolume:
|
||||
if(mode == Volume)
|
||||
showSearchVolume();
|
||||
else
|
||||
showSearchSingleComic();
|
||||
break;
|
||||
case SearchingSingleComic:
|
||||
showSearchSingleComic();
|
||||
break;
|
||||
case GettingVolumeComics:
|
||||
showSelectVolume();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ComicVineDialog::getComicsInfo(QList<QPair<ComicDB, QString> > & matchingInfo, int count,const QString & publisher)
|
||||
{
|
||||
QPair<ComicDB, QString> p;
|
||||
QList<ComicDB> comics;
|
||||
foreach (p, matchingInfo) {
|
||||
ComicVineClient * comicVineClient = new ComicVineClient;
|
||||
//connect(comicVineClient,SIGNAL(searchResult(QString)),this,SLOT(debugClientResults(QString)));
|
||||
//connect(comicVineClient,SIGNAL(timeOut()),this,SLOT(queryTimeOut()));
|
||||
//connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater()));
|
||||
bool error;
|
||||
bool timeout;
|
||||
QByteArray result = comicVineClient->getComicDetail(p.second,error,timeout); //TODO check timeOut or Connection error
|
||||
if(error || timeout)
|
||||
continue; //TODO
|
||||
ComicDB comic = parseComicInfo(p.first,result,count,publisher);//TODO check result error
|
||||
comic.info.comicVineID = p.second;
|
||||
comics.push_back(comic);
|
||||
|
||||
setLoadingMessage(tr("Retrieving tags for : %1").arg(p.first.getFileName()));
|
||||
}
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||
db.open();
|
||||
db.transaction();
|
||||
foreach(ComicDB comic, comics)
|
||||
{
|
||||
DBHelper::update(&(comic.info),db);
|
||||
}
|
||||
db.commit();
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(databasePath);
|
||||
|
||||
close();
|
||||
emit accepted();
|
||||
}
|
||||
|
||||
void ComicVineDialog::getComicInfo(const QString &comicId, int count, const QString &publisher)
|
||||
{
|
||||
|
||||
ComicVineClient * comicVineClient = new ComicVineClient;
|
||||
bool error;
|
||||
bool timeout;
|
||||
QByteArray result = comicVineClient->getComicDetail(comicId,error,timeout); //TODO check timeOut or Connection error
|
||||
if(error || timeout)
|
||||
{
|
||||
//TODO
|
||||
if(mode == SingleComic || currentIndex == (comics.count()-1))
|
||||
{
|
||||
close();
|
||||
emit accepted();
|
||||
} else
|
||||
{
|
||||
goToNextComic();
|
||||
}
|
||||
}
|
||||
|
||||
ComicDB comic = parseComicInfo(comics[currentIndex],result,count,publisher); //TODO check result error
|
||||
comic.info.comicVineID = comicId;
|
||||
setLoadingMessage(tr("Retrieving tags for : %1").arg(comics[currentIndex].getFileName()));
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(databasePath);
|
||||
db.open();
|
||||
db.transaction();
|
||||
|
||||
DBHelper::update(&(comic.info),db);
|
||||
|
||||
db.commit();
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(databasePath);
|
||||
|
||||
if(mode == SingleComic || currentIndex == (comics.count()-1))
|
||||
{
|
||||
close();
|
||||
emit accepted();
|
||||
} else
|
||||
{
|
||||
goToNextComic();
|
||||
}
|
||||
}
|
||||
|
||||
ComicDB ComicVineDialog::parseComicInfo(ComicDB & comic, const QString & json, int count, const QString & publisher)
|
||||
{
|
||||
QScriptEngine engine;
|
||||
QScriptValue sc;
|
||||
sc = engine.evaluate("(" + json + ")");
|
||||
|
||||
if (!sc.property("error").isValid() && sc.property("error").toString() != "OK")
|
||||
{
|
||||
qDebug("Error detected");
|
||||
}
|
||||
else
|
||||
{
|
||||
int numResults = sc.property("number_of_total_results").toString().toInt(); //fix to weird behaviour using hasNext
|
||||
|
||||
if(numResults > 0)
|
||||
{
|
||||
QScriptValue result = sc.property("results");
|
||||
|
||||
QString title = result.property("name").toString();
|
||||
|
||||
QString number = result.property("issue_number").toString();
|
||||
//QString count; //get from select volume
|
||||
|
||||
|
||||
QString volume = result.property("volume").property("name").toString();
|
||||
QString storyArc; //story_arc
|
||||
QString arcNumber; //??
|
||||
QString arcCount; //count_of_issue_appearances -> NO
|
||||
|
||||
QString genere; //no
|
||||
|
||||
QMap<QString,QString> authors = getAuthors(result.property("person_credits"));
|
||||
|
||||
QString writer = QStringList(authors.values("writer")).join("\n");
|
||||
QString penciller = QStringList(authors.values("penciller")).join("\n");
|
||||
QString inker = QStringList(authors.values("inker")).join("\n");
|
||||
QString colorist = QStringList(authors.values("colorist")).join("\n");
|
||||
QString letterer = QStringList(authors.values("letterer")).join("\n");
|
||||
QString coverArtist = QStringList(authors.values("cover")).join("\n");
|
||||
|
||||
QString date = result.property("cover_date").toString();
|
||||
|
||||
//QString publisher; //get from select volume
|
||||
QString format; //no
|
||||
bool color; //no
|
||||
QString ageRating; //no
|
||||
|
||||
QString synopsis = result.property("description").toString().remove(QRegExp("<[^>]*>")); //description
|
||||
QString characters = getCharacters(result.property("character_credits"));
|
||||
|
||||
comic.info.title = title;
|
||||
|
||||
comic.info.number = number;
|
||||
comic.info.count = count;
|
||||
|
||||
comic.info.writer = writer;
|
||||
comic.info.penciller = penciller;
|
||||
comic.info.inker = inker;
|
||||
comic.info.colorist = colorist;
|
||||
comic.info.letterer = letterer;
|
||||
comic.info.coverArtist = coverArtist;
|
||||
|
||||
QStringList tempList = date.split("-");
|
||||
std::reverse(tempList.begin(),tempList.end());
|
||||
comic.info.date = tempList.join("/");
|
||||
comic.info.volume = volume;
|
||||
|
||||
comic.info.publisher = publisher;
|
||||
|
||||
comic.info.synopsis = synopsis;
|
||||
comic.info.characters = characters;
|
||||
}
|
||||
}
|
||||
return comic;
|
||||
}
|
||||
|
||||
QString ComicVineDialog::getCharacters(const QScriptValue &json_characters)
|
||||
{
|
||||
QString characters;
|
||||
|
||||
QScriptValueIterator it(json_characters);
|
||||
QScriptValue resultsValue;
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if(it.flags() & QScriptValue::SkipInEnumeration)
|
||||
continue;
|
||||
resultsValue = it.value();
|
||||
|
||||
characters += resultsValue.property("name").toString() + "\n";
|
||||
}
|
||||
|
||||
return characters;
|
||||
}
|
||||
|
||||
QMap<QString, QString> ComicVineDialog::getAuthors(const QScriptValue &json_authors)
|
||||
{
|
||||
QMap<QString, QString> authors;
|
||||
|
||||
QScriptValueIterator it(json_authors);
|
||||
QScriptValue resultsValue;
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if(it.flags() & QScriptValue::SkipInEnumeration)
|
||||
continue;
|
||||
resultsValue = it.value();
|
||||
|
||||
QString authorName = resultsValue.property("name").toString();
|
||||
|
||||
QStringList roles = resultsValue.property("role").toString().split(",");
|
||||
foreach(QString role, roles)
|
||||
{
|
||||
if(role.trimmed() == "writer")
|
||||
authors.insertMulti("writer",authorName);
|
||||
else if(role.trimmed() == "inker")
|
||||
authors.insertMulti("inker",authorName);
|
||||
else if(role.trimmed() == "penciler" || role.trimmed() == "penciller")
|
||||
authors.insertMulti("penciller",authorName);
|
||||
else if(role.trimmed() == "colorist")
|
||||
authors.insertMulti("colorist",authorName);
|
||||
else if(role.trimmed() == "letterer")
|
||||
authors.insertMulti("letterer",authorName);
|
||||
else if(role.trimmed() == "cover")
|
||||
authors.insertMulti("cover",authorName);
|
||||
}
|
||||
}
|
||||
|
||||
return authors;
|
||||
}
|
||||
|
||||
void ComicVineDialog::toggleSkipButton()
|
||||
{
|
||||
if (mode == SingleComicInList)
|
||||
skipButton->setVisible(true);
|
||||
else
|
||||
skipButton->setHidden(true);
|
||||
}
|
||||
|
||||
void ComicVineDialog::goToNextComic()
|
||||
{
|
||||
if(mode == SingleComic || currentIndex == (comics.count()-1))
|
||||
{
|
||||
close();
|
||||
emit accepted();
|
||||
return;
|
||||
}
|
||||
|
||||
currentIndex++;
|
||||
|
||||
showSearchSingleComic();
|
||||
|
||||
ComicDB comic = comics[currentIndex];
|
||||
QString title = comic.getTitleOrFileName();
|
||||
titleHeader->setSubTitle(tr("comic %1 of %2 - %3").arg(currentIndex+1).arg(comics.length()).arg(title));
|
||||
}
|
||||
|
||||
void ComicVineDialog::showLoading(const QString &message)
|
||||
{
|
||||
content->setCurrentIndex(0);
|
||||
loadingMessage->setText(message);
|
||||
backButton->setHidden(true);
|
||||
skipButton->setHidden(true);
|
||||
nextButton->setHidden(true);
|
||||
searchButton->setHidden(true);
|
||||
closeButton->setVisible(true);
|
||||
}
|
||||
|
||||
void ComicVineDialog::setLoadingMessage(const QString &message)
|
||||
{
|
||||
loadingMessage->setText(message);
|
||||
}
|
||||
|
||||
void ComicVineDialog::search()
|
||||
{
|
||||
switch (mode) {
|
||||
case Volume:
|
||||
launchSearchVolume();
|
||||
break;
|
||||
default:
|
||||
launchSearchComic();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ComicVineDialog::searchVolume(const QString &v, int page)
|
||||
{
|
||||
showLoading(tr("Looking for volume..."));
|
||||
|
||||
currentVolumeSearchString = v;
|
||||
|
||||
ComicVineClient * comicVineClient = new ComicVineClient;
|
||||
connect(comicVineClient,SIGNAL(searchResult(QString)),this,SLOT(debugClientResults(QString)));
|
||||
connect(comicVineClient,SIGNAL(timeOut()),this,SLOT(queryTimeOut()));
|
||||
connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater()));
|
||||
comicVineClient->search(v,page);
|
||||
|
||||
status = SearchingVolume;
|
||||
}
|
||||
|
||||
void ComicVineDialog::getVolumeComicsInfo(const QString &vID, int page)
|
||||
{
|
||||
showLoading(tr("Retrieving volume info..."));
|
||||
|
||||
status = GettingVolumeComics;
|
||||
|
||||
ComicVineClient * comicVineClient = new ComicVineClient;
|
||||
if(mode == Volume)
|
||||
connect(comicVineClient,SIGNAL(volumeComicsInfo(QString)),this,SLOT(showSortVolumeComics(QString)));
|
||||
else
|
||||
connect(comicVineClient,SIGNAL(volumeComicsInfo(QString)),this,SLOT(showSelectComic(QString)));
|
||||
connect(comicVineClient,SIGNAL(timeOut()),this,SLOT(queryTimeOut()));
|
||||
connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater()));
|
||||
|
||||
QLOG_TRACE() << vID;
|
||||
|
||||
comicVineClient->getVolumeComicsInfo(vID,page);
|
||||
}
|
||||
|
||||
void ComicVineDialog::launchSearchVolume()
|
||||
{
|
||||
showLoading(tr("Looking for volume..."));
|
||||
//TODO: check if volume info is empty.
|
||||
searchVolume(searchVolumeWidget->getVolumeInfo());
|
||||
}
|
||||
|
||||
void ComicVineDialog::launchSearchComic()
|
||||
{
|
||||
showLoading(tr("Looking for comic..."));
|
||||
|
||||
QString volumeInfo = searchSingleComicWidget->getVolumeInfo();
|
||||
//QString comicInfo = searchSingleComicWidget->getComicInfo();
|
||||
//int comicNumber = searchSingleComicWidget->getComicNumber();
|
||||
|
||||
//if(comicInfo.isEmpty() && comicNumber == -1)
|
||||
searchVolume(volumeInfo);
|
||||
}
|
||||
|
130
YACReaderLibrary/comic_vine/comic_vine_dialog.h
Normal file
130
YACReaderLibrary/comic_vine/comic_vine_dialog.h
Normal file
@ -0,0 +1,130 @@
|
||||
#ifndef COMIC_VINE_DIALOG_H
|
||||
#define COMIC_VINE_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
#include "comic_db.h"
|
||||
|
||||
class QPushButton;
|
||||
class QStackedWidget;
|
||||
class QLabel;
|
||||
class QRadioButton;
|
||||
class ComicVineClient;
|
||||
class QTableView;
|
||||
class TitleHeader;
|
||||
class SeriesQuestion;
|
||||
class SearchSingleComic;
|
||||
class SearchVolume;
|
||||
class SelectComic;
|
||||
class SelectVolume;
|
||||
class SortVolumeComics;
|
||||
class QScriptValue;
|
||||
|
||||
//TODO this should use a QStateMachine
|
||||
//----------------------------------------
|
||||
class ComicVineDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComicVineDialog(QWidget *parent = 0);
|
||||
QString databasePath;
|
||||
QString basePath;
|
||||
void setComics(const QList<ComicDB> & comics);
|
||||
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void show();
|
||||
|
||||
protected slots:
|
||||
void goNext();
|
||||
void goBack();
|
||||
void debugClientResults(const QString & string);
|
||||
//show widget methods
|
||||
void showSeriesQuestion();
|
||||
void showSearchSingleComic();
|
||||
void showSearchVolume();
|
||||
void showLoading(const QString & message = "");
|
||||
void search();
|
||||
void searchVolume(const QString & v, int page = 1);
|
||||
void getVolumeComicsInfo(const QString &vID, int page = 1);
|
||||
void launchSearchVolume();
|
||||
void launchSearchComic();
|
||||
void showSelectVolume(const QString & json);
|
||||
void showSelectVolume();
|
||||
void showSelectComic(const QString & json);
|
||||
void showSortVolumeComics(const QString & json);
|
||||
void queryTimeOut();
|
||||
void getComicsInfo(QList<QPair<ComicDB,QString> > & matchingInfo, int count, const QString & publisher);
|
||||
void getComicInfo(const QString & comicId, int count, const QString & publisher);
|
||||
ComicDB parseComicInfo(ComicDB &comic, const QString & json, int count, const QString &publisher);
|
||||
void setLoadingMessage(const QString &message);
|
||||
void goToNextComic();
|
||||
|
||||
private:
|
||||
|
||||
QString getCharacters(const QScriptValue & json_characters);
|
||||
QMap<QString,QString> getAuthors(const QScriptValue & json_authors);
|
||||
|
||||
void toggleSkipButton();
|
||||
|
||||
enum ScraperMode
|
||||
{
|
||||
SingleComic, //the scraper has been opened for a single comic
|
||||
Volume, //the scraper is trying to get comics info for a whole volume
|
||||
SingleComicInList //the scraper has been opened for a list of unrelated comics
|
||||
};
|
||||
|
||||
enum ScraperStatus
|
||||
{
|
||||
AutoSearching,
|
||||
AskingForInfo,
|
||||
SelectingComic,
|
||||
SelectingSeries,
|
||||
SearchingSingleComic,
|
||||
SearchingVolume,
|
||||
SortingComics,
|
||||
GettingVolumeComics
|
||||
};
|
||||
|
||||
ScraperMode mode;
|
||||
ScraperStatus status;
|
||||
|
||||
int currentIndex;
|
||||
|
||||
TitleHeader * titleHeader;
|
||||
|
||||
QPushButton * skipButton;
|
||||
QPushButton * backButton;
|
||||
QPushButton * nextButton;
|
||||
QPushButton * searchButton;
|
||||
QPushButton * closeButton;
|
||||
|
||||
//stacked widgets
|
||||
QStackedWidget * content;
|
||||
|
||||
QWidget * infoNotFound;
|
||||
QWidget * singleComicBrowser;
|
||||
|
||||
QLabel * loadingMessage;
|
||||
|
||||
void doLayout();
|
||||
void doStackedWidgets();
|
||||
void doLoading();
|
||||
void doConnections();
|
||||
|
||||
QList<ComicDB> comics;
|
||||
|
||||
SeriesQuestion * seriesQuestionWidget;
|
||||
SearchSingleComic * searchSingleComicWidget;
|
||||
SearchVolume * searchVolumeWidget;
|
||||
SelectVolume * selectVolumeWidget;
|
||||
SelectComic * selectComicWidget;
|
||||
SortVolumeComics * sortVolumeComicsWidget;
|
||||
|
||||
QString currentVolumeSearchString;
|
||||
QString currentVolumeId;
|
||||
};
|
||||
|
||||
#endif // COMIC_VINE_DIALOG_H
|
6
YACReaderLibrary/comic_vine/model/comics_model.cpp
Normal file
6
YACReaderLibrary/comic_vine/model/comics_model.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "comics_model.h"
|
||||
|
||||
ComicsModel::ComicsModel(QObject *parent) :
|
||||
JSONModel(parent)
|
||||
{
|
||||
}
|
18
YACReaderLibrary/comic_vine/model/comics_model.h
Normal file
18
YACReaderLibrary/comic_vine/model/comics_model.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef COMICS_MODEL_H
|
||||
#define COMICS_MODEL_H
|
||||
|
||||
#include "json_model.h"
|
||||
|
||||
class ComicsModel : public JSONModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComicsModel(QObject *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // COMICS_MODEL_H
|
6
YACReaderLibrary/comic_vine/model/json_model.cpp
Normal file
6
YACReaderLibrary/comic_vine/model/json_model.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include "json_model.h"
|
||||
|
||||
JSONModel::JSONModel(QObject *parent) :
|
||||
QAbstractItemModel(parent)
|
||||
{
|
||||
}
|
19
YACReaderLibrary/comic_vine/model/json_model.h
Normal file
19
YACReaderLibrary/comic_vine/model/json_model.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef JSON_MODEL_H
|
||||
#define JSON_MODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
class JSONModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit JSONModel(QObject *parent = 0);
|
||||
virtual void load(const QString & json) = 0 ;
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // JSON_MODEL_H
|
183
YACReaderLibrary/comic_vine/model/local_comic_list_model.cpp
Normal file
183
YACReaderLibrary/comic_vine/model/local_comic_list_model.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
#include "local_comic_list_model.h"
|
||||
|
||||
LocalComicListModel::LocalComicListModel(QObject *parent) :
|
||||
QAbstractItemModel(parent),numExtraRows(0)
|
||||
{
|
||||
}
|
||||
|
||||
void LocalComicListModel::load(QList<ComicDB> &comics)
|
||||
{
|
||||
_data = comics;
|
||||
}
|
||||
|
||||
|
||||
QModelIndex LocalComicListModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
return QModelIndex(); //no parent
|
||||
}
|
||||
|
||||
int LocalComicListModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return _data.count();
|
||||
}
|
||||
|
||||
int LocalComicListModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
if(_data.isEmpty())
|
||||
return 0;
|
||||
else
|
||||
return 1;//_data.at(0)->count();
|
||||
}
|
||||
|
||||
QVariant LocalComicListModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DecorationRole)
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
if (role == Qt::TextAlignmentRole)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
if(role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
int row = index.row();
|
||||
|
||||
//if(row < _data.count())
|
||||
return _data[row].getFileName();
|
||||
//else
|
||||
//return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags LocalComicListModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
QVariant LocalComicListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
|
||||
if ( role == Qt::TextAlignmentRole)
|
||||
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
{
|
||||
return QVariant(QString(tr("file name")));
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex LocalComicListModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(row, column);
|
||||
}
|
||||
|
||||
QList<ComicDB> LocalComicListModel::getData()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
void LocalComicListModel::removeComics(const QList<QModelIndex> &selectedIndexes)
|
||||
{
|
||||
QModelIndex mi = selectedIndexes.first();
|
||||
QModelIndex lastMi = selectedIndexes.last();
|
||||
int sourceRow = mi.row();
|
||||
int sourceLastRow = lastMi.row();
|
||||
|
||||
beginRemoveRows(QModelIndex(),selectedIndexes.first().row(),selectedIndexes.last().row());
|
||||
|
||||
for(int i = sourceLastRow;i>=sourceRow;i--)
|
||||
{
|
||||
_removed.push_front(_data.at(i));
|
||||
_data.removeAt(i);
|
||||
}
|
||||
|
||||
endRemoveRows();
|
||||
|
||||
beginInsertRows(QModelIndex(),_data.count()-_removed.count(),_data.count()-1);
|
||||
for(int i = 0; i<_removed.count(); i++)
|
||||
_data.append(ComicDB());
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void LocalComicListModel::restoreAll()
|
||||
{
|
||||
int numItemsToRemove = 0;
|
||||
for(int i = 0;numItemsToRemove<_removed.count();i++)
|
||||
{
|
||||
if(_data.at(i).getFileName().isEmpty())
|
||||
{
|
||||
beginRemoveRows(QModelIndex(),i,i);
|
||||
_data.removeAt(i);
|
||||
endRemoveRows();
|
||||
|
||||
beginInsertRows(QModelIndex(),i,i);
|
||||
_data.insert(i,_removed.at(numItemsToRemove));
|
||||
endInsertRows();
|
||||
|
||||
numItemsToRemove++;
|
||||
}
|
||||
}
|
||||
|
||||
_removed.clear();
|
||||
}
|
||||
|
||||
void LocalComicListModel::moveSelectionUp(const QList<QModelIndex> &selectedIndexes)
|
||||
{
|
||||
QModelIndex mi = selectedIndexes.first();
|
||||
QModelIndex lastMi = selectedIndexes.last();
|
||||
int sourceRow = mi.row();
|
||||
int sourceLastRow = lastMi.row();
|
||||
int destRow = sourceRow - 1;
|
||||
|
||||
if(destRow < 0)
|
||||
return;
|
||||
|
||||
beginMoveRows(mi.parent(),sourceRow,sourceLastRow,mi.parent(),destRow);
|
||||
|
||||
for(int i = sourceRow; i <= sourceLastRow; i++)
|
||||
_data.swap(i, i-1);
|
||||
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
void LocalComicListModel::moveSelectionDown(const QList<QModelIndex> &selectedIndexes)
|
||||
{
|
||||
QModelIndex mi = selectedIndexes.first();
|
||||
QModelIndex lastMi = selectedIndexes.last();
|
||||
int sourceRow = mi.row();
|
||||
int sourceLastRow = lastMi.row();
|
||||
int destRow = sourceLastRow + 1;
|
||||
|
||||
if(destRow >= _data.count())
|
||||
return;
|
||||
|
||||
beginMoveRows(mi.parent(),sourceRow,sourceLastRow,mi.parent(),destRow+1);
|
||||
|
||||
for(int i = sourceLastRow; i >= sourceRow; i--)
|
||||
_data.swap(i, i+1);
|
||||
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
void LocalComicListModel::addExtraRows(int numRows)
|
||||
{
|
||||
numExtraRows = numRows;
|
||||
for(int i = 0; i<numExtraRows; i++)
|
||||
_data.append(ComicDB());
|
||||
}
|
||||
|
42
YACReaderLibrary/comic_vine/model/local_comic_list_model.h
Normal file
42
YACReaderLibrary/comic_vine/model/local_comic_list_model.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef LOCAL_COMIC_LIST_MODEL_H
|
||||
#define LOCAL_COMIC_LIST_MODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include "comic_db.h"
|
||||
|
||||
class LocalComicListModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LocalComicListModel(QObject *parent = 0);
|
||||
|
||||
void load(QList<ComicDB> & comics);
|
||||
|
||||
//QAbstractItemModel methods
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
|
||||
QList<ComicDB> getData();
|
||||
|
||||
void removeComics(const QList<QModelIndex> & selectedIndexes);
|
||||
void restoreAll();
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void moveSelectionUp(const QList<QModelIndex> & selectedIndexes);
|
||||
void moveSelectionDown(const QList<QModelIndex> & selectedIndexes);
|
||||
void addExtraRows(int numRows);
|
||||
|
||||
private:
|
||||
int numExtraRows;
|
||||
QList<ComicDB> _data;
|
||||
QList<ComicDB> _removed;
|
||||
};
|
||||
|
||||
#endif // LOCAL_COMIC_LIST_MODEL_H
|
83
YACReaderLibrary/comic_vine/model/response_parser.cpp
Normal file
83
YACReaderLibrary/comic_vine/model/response_parser.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include "response_parser.h"
|
||||
|
||||
#include <QtScript>
|
||||
#include <QDebug>
|
||||
|
||||
ResponseParser::ResponseParser(QObject *parent) :
|
||||
QObject(parent),error(false),numResults(-1),currentPage(-1),totalPages(-1),errorTxt("None")
|
||||
{
|
||||
}
|
||||
|
||||
bool ResponseParser::responseError()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
QString ResponseParser::errorDescription()
|
||||
{
|
||||
return errorTxt;
|
||||
}
|
||||
|
||||
qint32 ResponseParser::getNumResults()
|
||||
{
|
||||
return numResults;
|
||||
}
|
||||
|
||||
qint32 ResponseParser::getCurrentPage()
|
||||
{
|
||||
return currentPage;
|
||||
}
|
||||
|
||||
qint32 ResponseParser::getTotalPages()
|
||||
{
|
||||
return totalPages;
|
||||
}
|
||||
|
||||
bool ResponseParser::isError(qint32 error)
|
||||
{
|
||||
switch(error)
|
||||
{
|
||||
case 100:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ResponseParser::loadJSONResponse(const QString &response)
|
||||
{
|
||||
QScriptEngine engine;
|
||||
QScriptValue sc;
|
||||
sc = engine.evaluate("(" + response + ")");
|
||||
|
||||
errorTxt = "None";
|
||||
|
||||
if (!sc.property("status_code").isValid() || isError(sc.property("status_code").toInt32()))
|
||||
{
|
||||
error = true;
|
||||
if(sc.property("error").isValid())
|
||||
errorTxt = sc.property("error").toString();
|
||||
else
|
||||
errorTxt = "Unknown error";
|
||||
}
|
||||
else
|
||||
{
|
||||
error = false;
|
||||
if(sc.property("number_of_total_results").isValid())
|
||||
numResults = sc.property("number_of_total_results").toString().toInt();// sc.property("number_of_total_results").toInt32();
|
||||
else
|
||||
qDebug() << sc.property("oops").toString();
|
||||
|
||||
int limit = sc.property("limit").toInt32();
|
||||
int offset = sc.property("offset").toInt32();
|
||||
int total = sc.property("number_of_total_results").toInt32();
|
||||
if(limit > 0)
|
||||
{
|
||||
totalPages = (total / limit) + (total%limit>0?1:0);
|
||||
currentPage = (offset / limit) + 1;
|
||||
}
|
||||
else
|
||||
totalPages = currentPage = 1;
|
||||
}
|
||||
}
|
30
YACReaderLibrary/comic_vine/model/response_parser.h
Normal file
30
YACReaderLibrary/comic_vine/model/response_parser.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef RESPONSE_PARSER_H
|
||||
#define RESPONSE_PARSER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class ResponseParser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ResponseParser(QObject *parent = 0);
|
||||
bool responseError();
|
||||
QString errorDescription();
|
||||
qint32 getNumResults();
|
||||
qint32 getCurrentPage();
|
||||
qint32 getTotalPages();
|
||||
bool isError(qint32 error);
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void loadJSONResponse(const QString & response);
|
||||
|
||||
protected:
|
||||
bool error;
|
||||
QString errorTxt;
|
||||
qint32 numResults;
|
||||
qint32 currentPage;
|
||||
qint32 totalPages;
|
||||
};
|
||||
|
||||
#endif // RESPONSE_PARSER_H
|
172
YACReaderLibrary/comic_vine/model/volume_comics_model.cpp
Normal file
172
YACReaderLibrary/comic_vine/model/volume_comics_model.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
#include "volume_comics_model.h"
|
||||
#include "qnaturalsorting.h"
|
||||
|
||||
|
||||
#include <QtScript>
|
||||
|
||||
bool lessThan(const QList<QString> & left, const QList<QString> & right)
|
||||
{
|
||||
if ((left.count() > 0) && (right.count() > 0))
|
||||
return naturalSortLessThanCI(left.at(0),right.at(0));
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
VolumeComicsModel::VolumeComicsModel(QObject * parent) :
|
||||
JSONModel(parent),numExtraRows(0)
|
||||
{
|
||||
}
|
||||
|
||||
void VolumeComicsModel::load(const QString & json)
|
||||
{
|
||||
QScriptEngine engine;
|
||||
QScriptValue sc;
|
||||
sc = engine.evaluate("(" + json + ")");
|
||||
|
||||
if (!sc.property("error").isValid() && sc.property("error").toString() != "OK")
|
||||
{
|
||||
qDebug("Error detected");
|
||||
}
|
||||
else
|
||||
{
|
||||
QScriptValueIterator it(sc.property("results"));
|
||||
//bool test;
|
||||
QScriptValue resultsValue;
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
if(it.flags() & QScriptValue::SkipInEnumeration)
|
||||
continue;
|
||||
resultsValue = it.value();
|
||||
QString issueNumber = resultsValue.property("issue_number").toString();
|
||||
QString name = resultsValue.property("name").toString();
|
||||
QString coverURL = resultsValue.property("image").property("medium_url").toString();
|
||||
QString id = resultsValue.property("id").toString();
|
||||
QStringList l;
|
||||
l << issueNumber << name << coverURL << id;
|
||||
_data.push_back(l);
|
||||
}
|
||||
|
||||
qSort(_data.begin(),_data.end(),lessThan);
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex VolumeComicsModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
return QModelIndex(); //no parent
|
||||
}
|
||||
|
||||
int VolumeComicsModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return _data.count() + numExtraRows;
|
||||
}
|
||||
|
||||
int VolumeComicsModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
if(_data.isEmpty())
|
||||
return 0;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
QVariant VolumeComicsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
int row = index.row();
|
||||
int column = index.column();
|
||||
|
||||
if (role == Qt::DecorationRole)
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
if (role == Qt::TextAlignmentRole)
|
||||
{
|
||||
switch(column)//TODO obtener esto de la query
|
||||
{
|
||||
case ISSUE:
|
||||
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
||||
case TITLE:
|
||||
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
}
|
||||
}
|
||||
|
||||
if(role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
if(row<_data.count())
|
||||
return _data[row][column];
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags VolumeComicsModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
QVariant VolumeComicsModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
{
|
||||
switch(section)//TODO obtener esto de la query
|
||||
{
|
||||
case ISSUE:
|
||||
return QVariant(QString("issue"));
|
||||
case TITLE:
|
||||
return QVariant(QString(tr("title")));
|
||||
}
|
||||
}
|
||||
|
||||
if (orientation == Qt::Horizontal && role == Qt::TextAlignmentRole)
|
||||
{
|
||||
switch(section)//TODO obtener esto de la query
|
||||
{
|
||||
case ISSUE:
|
||||
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
||||
case TITLE:
|
||||
return QVariant(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex VolumeComicsModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(row, column);
|
||||
}
|
||||
|
||||
QString VolumeComicsModel::getComicId(const QModelIndex &index) const
|
||||
{
|
||||
int row = index.row();
|
||||
if(row >= _data.count())
|
||||
return "";
|
||||
return _data[row][ID];
|
||||
}
|
||||
|
||||
QString VolumeComicsModel::getComicId(int row) const
|
||||
{
|
||||
if(row >= _data.count())
|
||||
return "";
|
||||
return _data[row][ID];
|
||||
}
|
||||
|
||||
QString VolumeComicsModel::getCoverURL(const QModelIndex &index) const
|
||||
{
|
||||
return _data[index.row()][COVER_URL];
|
||||
}
|
||||
|
||||
void VolumeComicsModel::addExtraRows(int numRows)
|
||||
{
|
||||
numExtraRows = numRows;
|
||||
}
|
||||
|
41
YACReaderLibrary/comic_vine/model/volume_comics_model.h
Normal file
41
YACReaderLibrary/comic_vine/model/volume_comics_model.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef VOLUME_COMICS_MODEL_H
|
||||
#define VOLUME_COMICS_MODEL_H
|
||||
|
||||
#include "json_model.h"
|
||||
|
||||
class VolumeComicsModel : public JSONModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VolumeComicsModel(QObject *parent = 0);
|
||||
void load(const QString & json);
|
||||
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
QString getComicId(const QModelIndex &index) const;
|
||||
QString getComicId(int row) const;
|
||||
QString getCoverURL(const QModelIndex &index) const;
|
||||
void addExtraRows(int numRows);
|
||||
|
||||
private:
|
||||
int numExtraRows;
|
||||
QList <QList <QString> > _data;
|
||||
|
||||
enum Column {
|
||||
ISSUE = 0,
|
||||
TITLE,
|
||||
COVER_URL,
|
||||
ID
|
||||
};
|
||||
};
|
||||
|
||||
#endif // VOLUME_COMICS_MODEL_H
|
161
YACReaderLibrary/comic_vine/model/volumes_model.cpp
Normal file
161
YACReaderLibrary/comic_vine/model/volumes_model.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
#include "volumes_model.h"
|
||||
|
||||
#include <QtScript>
|
||||
|
||||
|
||||
VolumesModel::VolumesModel(QObject *parent) :
|
||||
JSONModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
VolumesModel::~VolumesModel()
|
||||
{
|
||||
//std::for_each(_data.begin(), _data.end(), [](QList<QString> * ptr) { delete ptr; });
|
||||
}
|
||||
|
||||
void VolumesModel::load(const QString &json)
|
||||
{
|
||||
QScriptEngine engine;
|
||||
QScriptValue sc;
|
||||
sc = engine.evaluate("(" + json + ")");
|
||||
|
||||
if (!sc.property("error").isValid() && sc.property("error").toString() != "OK")
|
||||
{
|
||||
qDebug("Error detected");
|
||||
}
|
||||
else
|
||||
{
|
||||
int numResults = sc.property("number_of_total_results").toString().toInt(); //fix to weird behaviour using hasNext
|
||||
QScriptValueIterator it(sc.property("results"));
|
||||
bool test;
|
||||
QScriptValue resultsValue;
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
resultsValue = it.value();
|
||||
QString numIssues = resultsValue.property("count_of_issues").toString();
|
||||
QString year = resultsValue.property("start_year").toString();
|
||||
QString name = resultsValue.property("name").toString();
|
||||
QString publisher = resultsValue.property("publisher").property("name").toString();
|
||||
QString url = resultsValue.property("image").property("medium_url").toString();
|
||||
QString deck = resultsValue.property("deck").toString();
|
||||
QString id = resultsValue.property("id").toString();
|
||||
QStringList l;
|
||||
l << name << year << numIssues << publisher << url << deck << id;
|
||||
test = name.isEmpty() && year.isEmpty() && numIssues.isEmpty() && url.isEmpty();
|
||||
if(numResults>0 && !test)
|
||||
_data.push_back(l);
|
||||
numResults--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex VolumesModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
return QModelIndex(); //no parent
|
||||
}
|
||||
|
||||
int VolumesModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return _data.count();
|
||||
}
|
||||
|
||||
int VolumesModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
if(_data.isEmpty())
|
||||
return 0;
|
||||
else
|
||||
return 4;//_data.at(0)->count();
|
||||
}
|
||||
|
||||
QVariant VolumesModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DecorationRole)
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
if (role == Qt::TextAlignmentRole)
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
if(role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
int row = index.row();
|
||||
int column = index.column();
|
||||
return _data[row][column];
|
||||
}
|
||||
|
||||
Qt::ItemFlags VolumesModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
}
|
||||
|
||||
QVariant VolumesModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
{
|
||||
switch(section)//TODO obtener esto de la query
|
||||
{
|
||||
case SERIES:
|
||||
return QVariant(QString("series"));
|
||||
case YEAR:
|
||||
return QVariant(QString(tr("year")));
|
||||
case ISSUES:
|
||||
return QVariant(QString(tr("issues")));
|
||||
case PUBLISHER:
|
||||
return QVariant(QString(tr("publisher")));
|
||||
}
|
||||
}
|
||||
|
||||
if (orientation == Qt::Horizontal && role == Qt::TextAlignmentRole)
|
||||
{
|
||||
switch(section)//TODO obtener esto de la query
|
||||
{
|
||||
case YEAR:
|
||||
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
||||
case ISSUES:
|
||||
return QVariant(Qt::AlignRight | Qt::AlignVCenter);
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex VolumesModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(row, column);
|
||||
}
|
||||
|
||||
QString VolumesModel::getVolumeId(const QModelIndex &index) const
|
||||
{
|
||||
return _data[index.row()][ID];
|
||||
}
|
||||
|
||||
int VolumesModel::getNumIssues(const QModelIndex &index) const
|
||||
{
|
||||
return _data[index.row()][ISSUES].toInt();
|
||||
}
|
||||
|
||||
QString VolumesModel::getPublisher(const QModelIndex &index) const
|
||||
{
|
||||
return _data[index.row()][PUBLISHER];
|
||||
}
|
||||
|
||||
QString VolumesModel::getCoverURL(const QModelIndex &index) const
|
||||
{
|
||||
return _data[index.row()][COVER_URL];
|
||||
}
|
||||
|
50
YACReaderLibrary/comic_vine/model/volumes_model.h
Normal file
50
YACReaderLibrary/comic_vine/model/volumes_model.h
Normal file
@ -0,0 +1,50 @@
|
||||
#ifndef VOLUMES_MODEL_H
|
||||
#define VOLUMES_MODEL_H
|
||||
|
||||
#include "json_model.h"
|
||||
|
||||
class VolumesModel : public JSONModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VolumesModel(QObject *parent = 0);
|
||||
virtual ~VolumesModel();
|
||||
//receive a valid json with a list of volumes
|
||||
void load(const QString & json);
|
||||
|
||||
//QAbstractItemModel methods
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
QString getVolumeId(const QModelIndex & index) const;
|
||||
int getNumIssues(const QModelIndex & index) const;
|
||||
QString getPublisher(const QModelIndex & index) const;
|
||||
QString getCoverURL(const QModelIndex & index) const;
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
QList <QList <QString> > _data;
|
||||
|
||||
public:
|
||||
enum Column {
|
||||
SERIES = 0,
|
||||
YEAR,
|
||||
ISSUES,
|
||||
PUBLISHER,
|
||||
COVER_URL,
|
||||
DECK,
|
||||
ID
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif // VOLUMES_MODEL_H
|
21
YACReaderLibrary/comic_vine/scraper_lineedit.cpp
Normal file
21
YACReaderLibrary/comic_vine/scraper_lineedit.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "scraper_lineedit.h"
|
||||
#include <QLabel>
|
||||
|
||||
ScraperLineEdit::ScraperLineEdit(const QString & title, QWidget * widget)
|
||||
:QLineEdit(widget)
|
||||
{
|
||||
titleLabel = new QLabel(title,this);
|
||||
titleLabel->setStyleSheet("QLabel {color:white;}");
|
||||
|
||||
setStyleSheet(QString("QLineEdit {"
|
||||
"border:none; background-color: #2E2E2E; color : white; padding-left: %1; padding-bottom: 1px; margin-bottom: 0px;"
|
||||
"}").arg(titleLabel->sizeHint().width()+6));
|
||||
|
||||
setFixedHeight(22);
|
||||
}
|
||||
|
||||
void ScraperLineEdit::resizeEvent(QResizeEvent *)
|
||||
{
|
||||
QSize szl = titleLabel->sizeHint();
|
||||
titleLabel->move(6,(rect().bottom() + 1 - szl.height())/2);
|
||||
}
|
19
YACReaderLibrary/comic_vine/scraper_lineedit.h
Normal file
19
YACReaderLibrary/comic_vine/scraper_lineedit.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef SCRAPPER_LINEEDIT_H
|
||||
#define SCRAPPER_LINEEDIT_H
|
||||
|
||||
#include <QLineEdit>
|
||||
|
||||
class QLabel;
|
||||
|
||||
class ScraperLineEdit : public QLineEdit
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScraperLineEdit(const QString & title, QWidget * widget = 0);
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *);
|
||||
private:
|
||||
QLabel * titleLabel;
|
||||
};
|
||||
|
||||
#endif // SCRAPPER_LINEEDIT_H
|
75
YACReaderLibrary/comic_vine/scraper_results_paginator.cpp
Normal file
75
YACReaderLibrary/comic_vine/scraper_results_paginator.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include "scraper_results_paginator.h"
|
||||
#include "response_parser.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
#include <QtScript>
|
||||
|
||||
|
||||
ScraperResultsPaginator::ScraperResultsPaginator(QWidget *parent) :
|
||||
QWidget(parent),customLabel("items")
|
||||
{
|
||||
QHBoxLayout * pagesButtonsLayout = new QHBoxLayout;
|
||||
|
||||
QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}";
|
||||
|
||||
nextPage = new QToolButton;
|
||||
nextPage->setStyleSheet("QToolButton {border:none;}");
|
||||
QPixmap np(":/images/comic_vine/nextPage.png");
|
||||
nextPage->setIconSize(np.size());
|
||||
nextPage->setIcon(np);
|
||||
|
||||
previousPage = new QToolButton;
|
||||
previousPage->setStyleSheet("QToolButton {border:none;}");
|
||||
QPixmap pp(":/images/comic_vine/previousPage.png");
|
||||
previousPage->setIconSize(pp.size());
|
||||
previousPage->setIcon(pp);
|
||||
|
||||
connect(nextPage,SIGNAL(clicked()),this,SIGNAL(loadNextPage()));
|
||||
connect(previousPage,SIGNAL(clicked()),this,SIGNAL(loadPreviousPage()));
|
||||
|
||||
numElements = new QLabel(tr("Number of volumes found : %1"));
|
||||
numElements->setStyleSheet(labelStylesheet);
|
||||
numPages = new QLabel(tr("page %1 of %2"));
|
||||
numPages->setStyleSheet(labelStylesheet);
|
||||
|
||||
pagesButtonsLayout->addSpacing(15);
|
||||
pagesButtonsLayout->addWidget(numElements);
|
||||
pagesButtonsLayout->addStretch();
|
||||
pagesButtonsLayout->addWidget(numPages);
|
||||
pagesButtonsLayout->addWidget(previousPage);
|
||||
pagesButtonsLayout->addWidget(nextPage);
|
||||
|
||||
setContentsMargins(0,0,0,0);
|
||||
pagesButtonsLayout->setContentsMargins(0,0,0,0);
|
||||
|
||||
setLayout(pagesButtonsLayout);
|
||||
}
|
||||
|
||||
void ScraperResultsPaginator::update(const QString &json)
|
||||
{
|
||||
ResponseParser rp;
|
||||
rp.loadJSONResponse(json);
|
||||
|
||||
currentPage = rp.getCurrentPage();
|
||||
numElements->setText(tr("Number of %1 found : %2").arg(customLabel).arg(rp.getNumResults()));
|
||||
numPages->setText(tr("page %1 of %2").arg(currentPage).arg(rp.getTotalPages()));
|
||||
|
||||
previousPage->setDisabled(currentPage == 1);
|
||||
nextPage->setDisabled(currentPage == rp.getTotalPages());
|
||||
|
||||
numPages->setHidden(rp.getTotalPages()==1);
|
||||
previousPage->setHidden(rp.getTotalPages()==1);
|
||||
nextPage->setHidden(rp.getTotalPages()==1);
|
||||
}
|
||||
|
||||
int ScraperResultsPaginator::getCurrentPage()
|
||||
{
|
||||
return currentPage;
|
||||
}
|
||||
|
||||
void ScraperResultsPaginator::setCustomLabel(const QString &label)
|
||||
{
|
||||
customLabel = label;
|
||||
}
|
34
YACReaderLibrary/comic_vine/scraper_results_paginator.h
Normal file
34
YACReaderLibrary/comic_vine/scraper_results_paginator.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef SCRAPER_RESULTS_PAGINATOR_H
|
||||
#define SCRAPER_RESULTS_PAGINATOR_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QToolButton;
|
||||
class QLabel;
|
||||
|
||||
class ScraperResultsPaginator : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScraperResultsPaginator(QWidget *parent = 0);
|
||||
void update(const QString & json);
|
||||
int getCurrentPage();
|
||||
void setCustomLabel(const QString & label);
|
||||
signals:
|
||||
void loadNextPage();
|
||||
void loadPreviousPage();
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
QToolButton * nextPage;
|
||||
QToolButton * previousPage;
|
||||
QLabel * numElements;
|
||||
QLabel * numPages;
|
||||
|
||||
int currentPage;
|
||||
|
||||
QString customLabel;
|
||||
};
|
||||
|
||||
#endif // SCRAPER_RESULTS_PAGINATOR_H
|
53
YACReaderLibrary/comic_vine/scraper_scroll_label.cpp
Normal file
53
YACReaderLibrary/comic_vine/scraper_scroll_label.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "scraper_scroll_label.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QDesktopServices>
|
||||
#include <QUrl>
|
||||
|
||||
ScraperScrollLabel::ScraperScrollLabel(QWidget *parent) :
|
||||
QScrollArea(parent)
|
||||
{
|
||||
textLabel = new QLabel(this);
|
||||
textLabel->setStyleSheet("QLabel {background-color: #2B2B2B; color:white; font-size:12px; font-family:Arial; }");
|
||||
|
||||
textLabel->setWordWrap(true);
|
||||
textLabel->setMinimumSize(168,12);
|
||||
|
||||
setWidget(textLabel);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setStyleSheet(
|
||||
"QScrollArea {background-color:#2B2B2B; border:none;}"
|
||||
"QScrollBar:vertical { border: none; background: #2B2B2B; width: 3px; margin: 0; }"
|
||||
"QScrollBar:horizontal { border: none; background: #2B2B2B; height: 3px; margin: 0; }"
|
||||
"QScrollBar::handle:vertical { background: #DDDDDD; width: 7px; min-height: 20px; }"
|
||||
"QScrollBar::handle:horizontal { background: #DDDDDD; width: 7px; min-height: 20px; }"
|
||||
"QScrollBar::add-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}"
|
||||
"QScrollBar::sub-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}"
|
||||
"QScrollBar::add-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 0 3px 0;}"
|
||||
"QScrollBar::sub-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 0 3px 0;}"
|
||||
"QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}"
|
||||
"QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}"
|
||||
"QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {background: none; }"
|
||||
);
|
||||
|
||||
connect(textLabel,SIGNAL(linkActivated(QString)),this,SLOT(openLink(QString)));
|
||||
}
|
||||
|
||||
void ScraperScrollLabel::setAltText(const QString &text)
|
||||
{
|
||||
textLabel->setAlignment(Qt::AlignTop|Qt::AlignHCenter);
|
||||
textLabel->setText(text);
|
||||
textLabel->adjustSize();
|
||||
}
|
||||
|
||||
void ScraperScrollLabel::setText(const QString &text)
|
||||
{
|
||||
textLabel->setAlignment(Qt::AlignTop|Qt::AlignLeft);
|
||||
textLabel->setText(text);
|
||||
textLabel->adjustSize();
|
||||
}
|
||||
|
||||
void ScraperScrollLabel::openLink(const QString & link)
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("http://www.comicvine.com"+link));
|
||||
}
|
25
YACReaderLibrary/comic_vine/scraper_scroll_label.h
Normal file
25
YACReaderLibrary/comic_vine/scraper_scroll_label.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef SCRAPER_SCROLL_LABEL_H
|
||||
#define SCRAPER_SCROLL_LABEL_H
|
||||
|
||||
#include <QScrollArea>
|
||||
|
||||
class QLabel;
|
||||
|
||||
class ScraperScrollLabel : public QScrollArea
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScraperScrollLabel(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void setText(const QString & text);
|
||||
void setAltText(const QString &text);
|
||||
|
||||
void openLink(const QString &link);
|
||||
private:
|
||||
QLabel * textLabel;
|
||||
};
|
||||
|
||||
#endif // SCRAPER_SCROLL_LABEL_H
|
25
YACReaderLibrary/comic_vine/scraper_selector.cpp
Normal file
25
YACReaderLibrary/comic_vine/scraper_selector.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "scraper_selector.h"
|
||||
|
||||
ScraperSelector::ScraperSelector(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
paginator = new ScraperResultsPaginator;
|
||||
connect(paginator,SIGNAL(loadNextPage()),this,SLOT(loadNextPage()));
|
||||
connect(paginator,SIGNAL(loadPreviousPage()),this,SLOT(loadPreviousPage()));
|
||||
}
|
||||
|
||||
void ScraperSelector::load(const QString &json, const QString &searchString)
|
||||
{
|
||||
currentSearchString = searchString;
|
||||
paginator->update(json);
|
||||
}
|
||||
|
||||
void ScraperSelector::loadNextPage()
|
||||
{
|
||||
emit loadPage(currentSearchString,paginator->getCurrentPage()+1);
|
||||
}
|
||||
|
||||
void ScraperSelector::loadPreviousPage()
|
||||
{
|
||||
emit loadPage(currentSearchString,paginator->getCurrentPage()-1);
|
||||
}
|
28
YACReaderLibrary/comic_vine/scraper_selector.h
Normal file
28
YACReaderLibrary/comic_vine/scraper_selector.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef SCRAPER_SELECTOR_H
|
||||
#define SCRAPER_SELECTOR_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "scraper_results_paginator.h"
|
||||
|
||||
class ScraperSelector : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScraperSelector(QWidget *parent = 0);
|
||||
virtual void load(const QString & json, const QString & searchString);
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
void loadPage(QString,int);
|
||||
|
||||
private slots:
|
||||
void loadNextPage();
|
||||
void loadPreviousPage();
|
||||
|
||||
protected:
|
||||
QString currentSearchString;
|
||||
ScraperResultsPaginator * paginator;
|
||||
};
|
||||
|
||||
#endif // SCRAPER_SELECTOR_H
|
61
YACReaderLibrary/comic_vine/scraper_tableview.cpp
Normal file
61
YACReaderLibrary/comic_vine/scraper_tableview.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include "scraper_tableview.h"
|
||||
|
||||
#include <QHeaderView>
|
||||
|
||||
ScraperTableView::ScraperTableView(QWidget *parent) :
|
||||
QTableView(parent)
|
||||
{
|
||||
QString tableStylesheet = "QTableView {color:white; border:0px;alternate-background-color: #2E2E2E;background-color: #2B2B2B; outline: 0px;}"
|
||||
"QTableView::item {outline: 0px; border: 0px; color:#FFFFFF;}"
|
||||
"QTableView::item:selected {outline: 0px; background-color: #555555; }"
|
||||
"QHeaderView::section:horizontal {background-color:#292929; border-bottom:1px solid #1F1F1F; border-right:1px solid qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #292929, stop: 1 #1F1F1F); border-left:none; border-top:none; padding:4px; color:#ebebeb;}"
|
||||
"QHeaderView::section:vertical {border-bottom: 1px solid #DFDFDF;border-top: 1px solid #FEFEFE;}"
|
||||
"QHeaderView::down-arrow {image: url(':/images/comic_vine/downArrow.png');}"
|
||||
"QHeaderView::up-arrow {image: url(':/images/comic_vine/upArrow.png');}"
|
||||
"QScrollBar:vertical { border: none; background: #2B2B2B; width: 3px; margin: 0; }"
|
||||
"QScrollBar:horizontal { border: none; background: #2B2B2B; height: 3px; margin: 0; }"
|
||||
"QScrollBar::handle:vertical { background: #DDDDDD; width: 7px; min-height: 20px; }"
|
||||
"QScrollBar::handle:horizontal { background: #DDDDDD; width: 7px; min-height: 20px; }"
|
||||
"QScrollBar::add-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}"
|
||||
"QScrollBar::sub-line:vertical { border: none; background: #404040; height: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}"
|
||||
"QScrollBar::add-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 0 3px 0;}"
|
||||
"QScrollBar::sub-line:horizontal { border: none; background: #404040; width: 10px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 0 3px 0;}"
|
||||
"QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}"
|
||||
"QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}"
|
||||
"QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {background: none; }";
|
||||
|
||||
setStyleSheet(tableStylesheet);
|
||||
|
||||
setShowGrid(false);
|
||||
#if QT_VERSION >= 0x050000
|
||||
verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
#else
|
||||
verticalHeader()->setResizeMode(QHeaderView::Fixed);
|
||||
#endif
|
||||
|
||||
//comicView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
horizontalHeader()->setStretchLastSection(true);
|
||||
#if QT_VERSION >= 0x050000
|
||||
horizontalHeader()->setSectionsClickable(false);
|
||||
#else
|
||||
horizontalHeader()->setClickable(false);
|
||||
#endif
|
||||
//comicView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
|
||||
verticalHeader()->setDefaultSectionSize(24);
|
||||
#if QT_VERSION >= 0x050000
|
||||
verticalHeader()->setSectionsClickable(false); //TODO comportamiento anómalo
|
||||
#else
|
||||
verticalHeader()->setClickable(false); //TODO comportamiento anómalo
|
||||
#endif
|
||||
|
||||
setCornerButtonEnabled(false);
|
||||
|
||||
setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
|
||||
setAlternatingRowColors(true);
|
||||
|
||||
verticalHeader()->hide();
|
||||
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
}
|
18
YACReaderLibrary/comic_vine/scraper_tableview.h
Normal file
18
YACReaderLibrary/comic_vine/scraper_tableview.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef SCRAPPER_TABLEVIEW_H
|
||||
#define SCRAPPER_TABLEVIEW_H
|
||||
|
||||
#include <QTableView>
|
||||
|
||||
class ScraperTableView : public QTableView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScraperTableView(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // SCRAPPER_TABLEVIEW_H
|
62
YACReaderLibrary/comic_vine/search_single_comic.cpp
Normal file
62
YACReaderLibrary/comic_vine/search_single_comic.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include "search_single_comic.h"
|
||||
|
||||
#include "scraper_lineedit.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
SearchSingleComic::SearchSingleComic(QWidget * parent)
|
||||
:QWidget(parent)
|
||||
{
|
||||
|
||||
//QLabel * label = new QLabel(tr("Please provide some additional information. At least one field is needed."));
|
||||
QLabel * label = new QLabel(tr("Please provide some additional information."));
|
||||
label->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}");
|
||||
|
||||
//titleEdit = new ScraperLineEdit(tr("Title:"));
|
||||
//numberEdit = new ScraperLineEdit(tr("Number:"));
|
||||
volumeEdit = new ScraperLineEdit(tr("Series:"));
|
||||
|
||||
//numberEdit->setMaximumWidth(126);
|
||||
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
//QHBoxLayout * hl = new QHBoxLayout;
|
||||
//hl->addWidget(titleEdit);
|
||||
//hl->addWidget(numberEdit);
|
||||
|
||||
l->addSpacing(35);
|
||||
l->addWidget(label);
|
||||
//l->addLayout(hl);
|
||||
l->addWidget(volumeEdit);
|
||||
l->addStretch();
|
||||
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
setLayout(l);
|
||||
setContentsMargins(0,0,0,0);
|
||||
}
|
||||
|
||||
QString SearchSingleComic::getVolumeInfo()
|
||||
{
|
||||
return volumeEdit->text();
|
||||
}
|
||||
|
||||
QString SearchSingleComic::getComicInfo()
|
||||
{
|
||||
//return titleEdit->text();
|
||||
return "";
|
||||
}
|
||||
|
||||
int SearchSingleComic::getComicNumber()
|
||||
{
|
||||
//QString numberText = numberEdit->text();
|
||||
//if(numberText.isEmpty())
|
||||
// return -1;
|
||||
//return numberText.toInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SearchSingleComic::clean()
|
||||
{
|
||||
volumeEdit->clear();
|
||||
}
|
22
YACReaderLibrary/comic_vine/search_single_comic.h
Normal file
22
YACReaderLibrary/comic_vine/search_single_comic.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef SEARCH_SINGLE_COMIC_H
|
||||
#define SEARCH_SINGLE_COMIC_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class ScraperLineEdit;
|
||||
|
||||
class SearchSingleComic : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SearchSingleComic(QWidget * parent = 0);
|
||||
QString getVolumeInfo();
|
||||
QString getComicInfo();
|
||||
int getComicNumber();
|
||||
void clean();
|
||||
private:
|
||||
ScraperLineEdit * titleEdit;
|
||||
ScraperLineEdit * numberEdit;
|
||||
ScraperLineEdit * volumeEdit;
|
||||
};
|
||||
#endif // SEARCH_SINGLE_COMIC_H
|
36
YACReaderLibrary/comic_vine/search_volume.cpp
Normal file
36
YACReaderLibrary/comic_vine/search_volume.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "search_volume.h"
|
||||
|
||||
#include "scraper_lineedit.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
SearchVolume::SearchVolume(QWidget * parent)
|
||||
:QWidget(parent)
|
||||
{
|
||||
QLabel * label = new QLabel(tr("Please provide some additional information."));
|
||||
label->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}");
|
||||
|
||||
volumeEdit = new ScraperLineEdit(tr("Series:"));
|
||||
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
|
||||
l->addSpacing(35);
|
||||
l->addWidget(label);
|
||||
l->addWidget(volumeEdit);
|
||||
l->addStretch();
|
||||
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
setLayout(l);
|
||||
setContentsMargins(0,0,0,0);
|
||||
}
|
||||
|
||||
void SearchVolume::clean()
|
||||
{
|
||||
volumeEdit->clear();
|
||||
}
|
||||
|
||||
QString SearchVolume::getVolumeInfo()
|
||||
{
|
||||
return volumeEdit->text();
|
||||
}
|
21
YACReaderLibrary/comic_vine/search_volume.h
Normal file
21
YACReaderLibrary/comic_vine/search_volume.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef SEARCH_VOLUME_H
|
||||
#define SEARCH_VOLUME_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class ScraperLineEdit;
|
||||
|
||||
|
||||
class SearchVolume : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SearchVolume(QWidget * parent = 0);
|
||||
void clean();
|
||||
public slots:
|
||||
QString getVolumeInfo();
|
||||
private:
|
||||
ScraperLineEdit * volumeEdit;
|
||||
};
|
||||
|
||||
#endif // SEARCH_VOLUME_H
|
150
YACReaderLibrary/comic_vine/select_comic.cpp
Normal file
150
YACReaderLibrary/comic_vine/select_comic.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include "select_comic.h"
|
||||
|
||||
#include "comic_vine_client.h"
|
||||
#include "scraper_scroll_label.h"
|
||||
#include "scraper_tableview.h"
|
||||
#include "volume_comics_model.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QLayout>
|
||||
#include <QtScript>
|
||||
|
||||
SelectComic::SelectComic(QWidget *parent)
|
||||
:ScraperSelector(parent),model(0)
|
||||
{
|
||||
QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}";
|
||||
|
||||
QLabel * label = new QLabel(tr("Please, select the right comic info."));
|
||||
label->setStyleSheet(labelStylesheet);
|
||||
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
QWidget * leftWidget = new QWidget;
|
||||
QVBoxLayout * left = new QVBoxLayout;
|
||||
QVBoxLayout * right = new QVBoxLayout;
|
||||
QHBoxLayout * content = new QHBoxLayout;
|
||||
|
||||
right->setContentsMargins(0,0,0,0);
|
||||
|
||||
//widgets
|
||||
cover = new QLabel();
|
||||
cover->setScaledContents(true);
|
||||
cover->setAlignment(Qt::AlignTop|Qt::AlignHCenter);
|
||||
cover->setMinimumSize(168,168*5.0/3);
|
||||
cover->setStyleSheet("QLabel {background-color: #2B2B2B; color:white; font-size:12px; font-family:Arial; }");
|
||||
detailLabel = new ScraperScrollLabel(this);
|
||||
|
||||
tableComics = new ScraperTableView(this);
|
||||
//connections
|
||||
connect(tableComics,SIGNAL(clicked(QModelIndex)),this,SLOT(loadComicInfo(QModelIndex)));
|
||||
|
||||
paginator->setCustomLabel(tr("comics"));
|
||||
|
||||
left->addWidget(cover);
|
||||
left->addWidget(detailLabel,1);
|
||||
left->addStretch();
|
||||
leftWidget->setMaximumWidth(180);
|
||||
leftWidget->setLayout(left);
|
||||
left->setContentsMargins(0,0,0,0);
|
||||
leftWidget->setContentsMargins(0,0,0,0);
|
||||
|
||||
right->addWidget(tableComics,0,Qt::AlignRight|Qt::AlignTop);
|
||||
right->addWidget(paginator);
|
||||
|
||||
content->addWidget(leftWidget);
|
||||
content->addLayout(right);
|
||||
|
||||
l->addSpacing(15);
|
||||
l->addWidget(label);
|
||||
l->addSpacing(5);
|
||||
l->addLayout(content);
|
||||
l->addStretch();
|
||||
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
setLayout(l);
|
||||
setContentsMargins(0,0,0,0);
|
||||
}
|
||||
|
||||
void SelectComic::load(const QString &json, const QString & searchString)
|
||||
{
|
||||
VolumeComicsModel * tempM = new VolumeComicsModel();
|
||||
tempM->load(json);
|
||||
tableComics->setModel(tempM);
|
||||
|
||||
tableComics->setFixedSize(619,341);
|
||||
|
||||
if(model != 0)
|
||||
delete model;
|
||||
|
||||
model = tempM;
|
||||
|
||||
if(model->rowCount()>0)
|
||||
{
|
||||
tableComics->selectRow(0);
|
||||
loadComicInfo(model->index(0,0));
|
||||
}
|
||||
|
||||
tableComics->resizeColumnToContents(0);
|
||||
|
||||
ScraperSelector::load(json,searchString);
|
||||
}
|
||||
|
||||
SelectComic::~SelectComic() {}
|
||||
|
||||
void SelectComic::loadComicInfo(const QModelIndex &mi)
|
||||
{
|
||||
QString coverURL = model->getCoverURL(mi);
|
||||
QString id = model->getComicId(mi);
|
||||
|
||||
QString loadingStyle = "<font color='#AAAAAA'>%1</font>";
|
||||
cover->setText(loadingStyle.arg(tr("loading cover")));
|
||||
detailLabel->setAltText(loadingStyle.arg(tr("loading description")));
|
||||
|
||||
ComicVineClient * comicVineClient = new ComicVineClient;
|
||||
connect(comicVineClient,SIGNAL(comicCover(const QByteArray &)),this,SLOT(setCover(const QByteArray &)));
|
||||
connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater()));
|
||||
comicVineClient->getComicCover(coverURL);
|
||||
|
||||
ComicVineClient * comicVineClient2 = new ComicVineClient;
|
||||
connect(comicVineClient2,SIGNAL(comicDetail(QString)),this,SLOT(setDescription(QString)));
|
||||
connect(comicVineClient2,SIGNAL(finished()),comicVineClient2,SLOT(deleteLater()));
|
||||
comicVineClient2->getComicDetailAsync(id);
|
||||
}
|
||||
|
||||
void SelectComic::setCover(const QByteArray & data)
|
||||
{
|
||||
QPixmap p;
|
||||
p.loadFromData(data);
|
||||
int w = p.width();
|
||||
int h = p.height();
|
||||
|
||||
cover->setPixmap(p);
|
||||
float aspectRatio = static_cast<float>(w)/h;
|
||||
|
||||
cover->setFixedSize(180,static_cast<int>(180/aspectRatio));
|
||||
|
||||
cover->update();
|
||||
}
|
||||
|
||||
void SelectComic::setDescription(const QString &jsonDetail)
|
||||
{
|
||||
QScriptEngine engine;
|
||||
QScriptValue sc;
|
||||
sc = engine.evaluate("(" + jsonDetail + ")");
|
||||
|
||||
if (!sc.property("error").isValid() && sc.property("error").toString() != "OK")
|
||||
{
|
||||
qDebug("Error detected");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
QScriptValue descriptionValues = sc.property("results").property("description");
|
||||
bool valid = !descriptionValues.isNull() && descriptionValues.isValid();
|
||||
detailLabel->setText(valid?descriptionValues.toString().replace("<a","<a style = 'color:#827A68; text-decoration:none;'"):tr("description unavailable"));
|
||||
}
|
||||
}
|
||||
|
||||
QString SelectComic::getSelectedComicId()
|
||||
{
|
||||
return model->getComicId(tableComics->currentIndex());
|
||||
}
|
34
YACReaderLibrary/comic_vine/select_comic.h
Normal file
34
YACReaderLibrary/comic_vine/select_comic.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef SELECT_COMIC_H
|
||||
#define SELECT_COMIC_H
|
||||
|
||||
#include "scraper_selector.h"
|
||||
|
||||
class QLabel;
|
||||
class VolumeComicsModel;
|
||||
class QModelIndex;
|
||||
|
||||
class ScraperScrollLabel;
|
||||
class ScraperTableView;
|
||||
|
||||
class SelectComic : public ScraperSelector
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SelectComic(QWidget * parent = 0);
|
||||
void load(const QString & json, const QString & searchString);
|
||||
virtual ~SelectComic();
|
||||
|
||||
public slots:
|
||||
void loadComicInfo(const QModelIndex & mi);
|
||||
void setCover(const QByteArray &);
|
||||
void setDescription(const QString & jsonDetail);
|
||||
QString getSelectedComicId();
|
||||
|
||||
private:
|
||||
QLabel * cover;
|
||||
ScraperScrollLabel * detailLabel;
|
||||
ScraperTableView * tableComics;
|
||||
VolumeComicsModel * model;
|
||||
};
|
||||
|
||||
#endif // SELECT_COMIC_H
|
191
YACReaderLibrary/comic_vine/select_volume.cpp
Normal file
191
YACReaderLibrary/comic_vine/select_volume.cpp
Normal file
@ -0,0 +1,191 @@
|
||||
#include "select_volume.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QScrollBar>
|
||||
#include <QModelIndex>
|
||||
#include <QScrollArea>
|
||||
#include <QDesktopServices>
|
||||
#include <QHeaderView>
|
||||
#include <QToolButton>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include "scraper_tableview.h"
|
||||
|
||||
#include <QtScript>
|
||||
|
||||
#include "volumes_model.h"
|
||||
#include "comic_vine_client.h"
|
||||
#include "scraper_scroll_label.h"
|
||||
|
||||
#include "response_parser.h"
|
||||
#include "scraper_results_paginator.h"
|
||||
|
||||
SelectVolume::SelectVolume(QWidget *parent)
|
||||
:ScraperSelector(parent),model(0)
|
||||
{
|
||||
proxyModel = new QSortFilterProxyModel;
|
||||
|
||||
QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}";
|
||||
|
||||
QLabel * label = new QLabel(tr("Please, select the right series for your comic."));
|
||||
label->setStyleSheet(labelStylesheet);
|
||||
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
QWidget * leftWidget = new QWidget;
|
||||
QVBoxLayout * left = new QVBoxLayout;
|
||||
QVBoxLayout * right = new QVBoxLayout;
|
||||
QHBoxLayout * content = new QHBoxLayout;
|
||||
|
||||
right->setContentsMargins(0,0,0,0);
|
||||
|
||||
//widgets
|
||||
cover = new QLabel();
|
||||
cover->setScaledContents(true);
|
||||
cover->setAlignment(Qt::AlignTop|Qt::AlignHCenter);
|
||||
cover->setMinimumSize(168,168*5.0/3);
|
||||
cover->setStyleSheet("QLabel {background-color: #2B2B2B; color:white; font-size:12px; font-family:Arial; }");
|
||||
detailLabel = new ScraperScrollLabel(this);
|
||||
|
||||
tableVolumes = new ScraperTableView(this);
|
||||
tableVolumes->setSortingEnabled(true);
|
||||
#if QT_VERSION >= 0x050000
|
||||
tableVolumes->horizontalHeader()->setSectionsClickable(true);
|
||||
#else
|
||||
tableVolumes->horizontalHeader()->setClickable(true);
|
||||
#endif
|
||||
//tableVolumes->horizontalHeader()->setSortIndicatorShown(false);
|
||||
connect(tableVolumes->horizontalHeader(),SIGNAL(sectionClicked(int)), tableVolumes, SLOT(sortByColumn(int)));
|
||||
//connections
|
||||
connect(tableVolumes,SIGNAL(clicked(QModelIndex)),this,SLOT(loadVolumeInfo(QModelIndex)));
|
||||
|
||||
paginator->setCustomLabel(tr("volumes"));
|
||||
|
||||
left->addWidget(cover);
|
||||
left->addWidget(detailLabel,1);
|
||||
left->addStretch();
|
||||
leftWidget->setMaximumWidth(180);
|
||||
leftWidget->setLayout(left);
|
||||
left->setContentsMargins(0,0,0,0);
|
||||
leftWidget->setContentsMargins(0,0,0,0);
|
||||
|
||||
right->addWidget(tableVolumes,0,Qt::AlignRight|Qt::AlignTop);
|
||||
right->addWidget(paginator);
|
||||
|
||||
content->addWidget(leftWidget);
|
||||
content->addLayout(right);
|
||||
|
||||
l->addSpacing(15);
|
||||
l->addWidget(label);
|
||||
l->addSpacing(5);
|
||||
l->addLayout(content);
|
||||
l->addStretch();
|
||||
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
setLayout(l);
|
||||
setContentsMargins(0,0,0,0);
|
||||
}
|
||||
|
||||
void SelectVolume::load(const QString & json, const QString & searchString)
|
||||
{
|
||||
VolumesModel * tempM = new VolumesModel();
|
||||
tempM->load(json);
|
||||
//tableVolumes->setModel(tempM);
|
||||
|
||||
proxyModel->setSourceModel( tempM );
|
||||
tableVolumes->setModel(proxyModel);
|
||||
tableVolumes->sortByColumn(0,Qt::AscendingOrder);
|
||||
tableVolumes->resizeColumnsToContents();
|
||||
|
||||
tableVolumes->setFixedSize(619,341);
|
||||
|
||||
if(model != 0)
|
||||
delete model;
|
||||
|
||||
model = tempM;
|
||||
|
||||
if(model->rowCount()>0)
|
||||
{
|
||||
tableVolumes->selectRow(0);
|
||||
loadVolumeInfo(proxyModel->index(0,0));
|
||||
}
|
||||
|
||||
tableVolumes->setColumnWidth(0,350);
|
||||
|
||||
ScraperSelector::load(json,searchString);
|
||||
}
|
||||
|
||||
SelectVolume::~SelectVolume() {}
|
||||
|
||||
void SelectVolume::loadVolumeInfo(const QModelIndex & omi)
|
||||
{
|
||||
QModelIndex mi = proxyModel->mapToSource(omi);
|
||||
QString coverURL = model->getCoverURL(mi);
|
||||
QString id = model->getVolumeId(mi);
|
||||
|
||||
QString loadingStyle = "<font color='#AAAAAA'>%1</font>";
|
||||
cover->setText(loadingStyle.arg(tr("loading cover")));
|
||||
detailLabel->setAltText(loadingStyle.arg(tr("loading description")));
|
||||
|
||||
ComicVineClient * comicVineClient = new ComicVineClient;
|
||||
connect(comicVineClient,SIGNAL(seriesCover(const QByteArray &)),this,SLOT(setCover(const QByteArray &)));
|
||||
connect(comicVineClient,SIGNAL(finished()),comicVineClient,SLOT(deleteLater()));
|
||||
comicVineClient->getSeriesCover(coverURL);
|
||||
|
||||
ComicVineClient * comicVineClient2 = new ComicVineClient;
|
||||
connect(comicVineClient2,SIGNAL(seriesDetail(QString)),this,SLOT(setDescription(QString)));
|
||||
connect(comicVineClient2,SIGNAL(finished()),comicVineClient2,SLOT(deleteLater()));
|
||||
comicVineClient2->getSeriesDetail(id);
|
||||
}
|
||||
|
||||
void SelectVolume::setCover(const QByteArray & data)
|
||||
{
|
||||
QPixmap p;
|
||||
p.loadFromData(data);
|
||||
int w = p.width();
|
||||
int h = p.height();
|
||||
|
||||
cover->setPixmap(p);
|
||||
float aspectRatio = static_cast<float>(w)/h;
|
||||
|
||||
cover->setFixedSize(180,static_cast<int>(180/aspectRatio));
|
||||
|
||||
cover->update();
|
||||
}
|
||||
|
||||
void SelectVolume::setDescription(const QString & jsonDetail)
|
||||
{
|
||||
QScriptEngine engine;
|
||||
QScriptValue sc;
|
||||
sc = engine.evaluate("(" + jsonDetail + ")");
|
||||
|
||||
if (!sc.property("error").isValid() && sc.property("error").toString() != "OK")
|
||||
{
|
||||
qDebug("Error detected");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
QScriptValue descriptionValues = sc.property("results").property("description");
|
||||
bool valid = !descriptionValues.isNull() && descriptionValues.isValid();
|
||||
detailLabel->setText(valid?descriptionValues.toString().replace("<a","<a style = 'color:#827A68; text-decoration:none;'"):tr("description unavailable"));
|
||||
}
|
||||
}
|
||||
|
||||
QString SelectVolume::getSelectedVolumeId()
|
||||
{
|
||||
return model->getVolumeId(proxyModel->mapToSource(tableVolumes->currentIndex()));
|
||||
}
|
||||
|
||||
int SelectVolume::getSelectedVolumeNumIssues()
|
||||
{
|
||||
return model->getNumIssues(proxyModel->mapToSource(tableVolumes->currentIndex()));
|
||||
}
|
||||
|
||||
QString SelectVolume::getSelectedVolumePublisher()
|
||||
{
|
||||
return model->getPublisher(proxyModel->mapToSource(tableVolumes->currentIndex()));
|
||||
}
|
||||
|
||||
|
39
YACReaderLibrary/comic_vine/select_volume.h
Normal file
39
YACReaderLibrary/comic_vine/select_volume.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef SELECT_VOLUME_H
|
||||
#define SELECT_VOLUME_H
|
||||
|
||||
#include "scraper_selector.h"
|
||||
|
||||
class QLabel;
|
||||
class VolumesModel;
|
||||
class QModelIndex;
|
||||
class QToolButton;
|
||||
class QSortFilterProxyModel;
|
||||
|
||||
class ScraperScrollLabel;
|
||||
class ScraperTableView;
|
||||
|
||||
class SelectVolume : public ScraperSelector
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SelectVolume(QWidget * parent = 0);
|
||||
void load(const QString & json, const QString & searchString);
|
||||
virtual ~SelectVolume();
|
||||
|
||||
public slots:
|
||||
void loadVolumeInfo(const QModelIndex & mi);
|
||||
void setCover(const QByteArray &);
|
||||
void setDescription(const QString & jsonDetail);
|
||||
QString getSelectedVolumeId();
|
||||
int getSelectedVolumeNumIssues();
|
||||
QString getSelectedVolumePublisher();
|
||||
|
||||
private:
|
||||
QLabel * cover;
|
||||
ScraperScrollLabel * detailLabel;
|
||||
ScraperTableView * tableVolumes;
|
||||
VolumesModel * model;
|
||||
QSortFilterProxyModel * proxyModel;
|
||||
};
|
||||
|
||||
#endif // SELECT_VOLUME_H
|
46
YACReaderLibrary/comic_vine/series_question.cpp
Normal file
46
YACReaderLibrary/comic_vine/series_question.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include "series_question.h"
|
||||
|
||||
#include <QRadioButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
|
||||
|
||||
SeriesQuestion::SeriesQuestion(QWidget * parent)
|
||||
:QWidget(parent)
|
||||
{
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
|
||||
QLabel * questionLabel = new QLabel(tr("You are trying to get information for various comics at once, are they part of the same series?"));
|
||||
questionLabel->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}");
|
||||
yes = new QRadioButton(tr("yes"));
|
||||
no = new QRadioButton(tr("no"));
|
||||
|
||||
QString rbStyle = "QRadioButton {margin-left:27px; margin-top:5px; color:white;font-size:12px;font-family:Arial;}"
|
||||
"QRadioButton::indicator {width:11px;height:11px;}"
|
||||
"QRadioButton::indicator::unchecked {image : url(:/images/comic_vine/radioUnchecked.png);}"
|
||||
"QRadioButton::indicator::checked {image : url(:/images/comic_vine/radioChecked.png);}";
|
||||
yes->setStyleSheet(rbStyle);
|
||||
no->setStyleSheet(rbStyle);
|
||||
|
||||
yes->setChecked(true);
|
||||
|
||||
l->addSpacing(35);
|
||||
l->addWidget(questionLabel);
|
||||
l->addWidget(yes);
|
||||
l->addWidget(no);
|
||||
l->addStretch();
|
||||
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
setLayout(l);
|
||||
setContentsMargins(0,0,0,0);
|
||||
}
|
||||
|
||||
bool SeriesQuestion::getYes()
|
||||
{
|
||||
return yes->isChecked();
|
||||
}
|
||||
|
||||
void SeriesQuestion::setYes(bool y)
|
||||
{
|
||||
yes->setChecked(y);
|
||||
}
|
23
YACReaderLibrary/comic_vine/series_question.h
Normal file
23
YACReaderLibrary/comic_vine/series_question.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef SERIES_QUESTION_H
|
||||
#define SERIES_QUESTION_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QRadioButton;
|
||||
|
||||
class SeriesQuestion : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SeriesQuestion(QWidget * parent = 0);
|
||||
bool getYes();
|
||||
void setYes(bool yes = true);
|
||||
|
||||
private:
|
||||
QRadioButton * yes;
|
||||
QRadioButton * no;
|
||||
};
|
||||
|
||||
|
||||
#endif // SERIES_QUESTION_H
|
226
YACReaderLibrary/comic_vine/sort_volume_comics.cpp
Normal file
226
YACReaderLibrary/comic_vine/sort_volume_comics.cpp
Normal file
@ -0,0 +1,226 @@
|
||||
#include "sort_volume_comics.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QScrollBar>
|
||||
#include <QAction>
|
||||
|
||||
#include "scraper_tableview.h"
|
||||
#include "local_comic_list_model.h"
|
||||
#include "volume_comics_model.h"
|
||||
|
||||
SortVolumeComics::SortVolumeComics(QWidget *parent) :
|
||||
ScraperSelector(parent)
|
||||
{
|
||||
QString labelStylesheet = "QLabel {color:white; font-size:12px;font-family:Arial;}";
|
||||
|
||||
QLabel * label = new QLabel(tr("Please, sort the list of comics on the left until it matches the comics' information."));
|
||||
label->setStyleSheet(labelStylesheet);
|
||||
|
||||
QLabel * sortLabel = new QLabel(tr("sort comics to match comic information"));
|
||||
sortLabel->setStyleSheet(labelStylesheet);
|
||||
|
||||
moveUpButtonCL = new ScrapperToolButton(ScrapperToolButton::LEFT);
|
||||
moveUpButtonCL->setIcon(QIcon(":/images/comic_vine/rowUp.png"));
|
||||
moveUpButtonCL->setAutoRepeat(true);
|
||||
moveDownButtonCL = new ScrapperToolButton(ScrapperToolButton::RIGHT);
|
||||
moveDownButtonCL->setIcon(QIcon(":/images/comic_vine/rowDown.png"));
|
||||
moveDownButtonCL->setAutoRepeat(true);
|
||||
//moveUpButtonIL = new ScrapperToolButton(ScrapperToolButton::LEFT);
|
||||
//moveUpButtonIL->setIcon(QIcon(":/images/comic_vine/rowUp.png"));
|
||||
//moveDownButtonIL = new ScrapperToolButton(ScrapperToolButton::RIGHT);
|
||||
//moveDownButtonIL->setIcon(QIcon(":/images/comic_vine/rowDown.png"));
|
||||
|
||||
connect(moveUpButtonCL,SIGNAL(clicked()),this,SLOT(moveUpCL()));
|
||||
connect(moveDownButtonCL,SIGNAL(clicked()),this,SLOT(moveDownCL()));
|
||||
//connect(moveUpButtonIL,SIGNAL(clicked()),this,SLOT(moveUpIL()));
|
||||
//connect(moveUpButtonIL,SIGNAL(clicked()),this,SLOT(moveDownIL()));
|
||||
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
QHBoxLayout * content = new QHBoxLayout;
|
||||
QHBoxLayout * sortButtonsLayout = new QHBoxLayout;
|
||||
|
||||
tableFiles = new ScraperTableView();
|
||||
tableVolumeComics = new ScraperTableView();
|
||||
|
||||
tableFiles->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
tableFiles->setSelectionMode(QAbstractItemView::ContiguousSelection);
|
||||
|
||||
tableFiles->setFixedSize(407,341);
|
||||
tableVolumeComics->setFixedSize(407,341);
|
||||
content->addWidget(tableFiles,0,Qt::AlignLeft|Qt::AlignTop);
|
||||
content->addWidget(tableVolumeComics,0,Qt::AlignRight|Qt::AlignTop);
|
||||
//content->addWidget(tableVolumes,0,Qt::AlignRight|Qt::AlignTop);
|
||||
|
||||
connect(tableVolumeComics->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int)));
|
||||
connect(tableFiles->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int)));
|
||||
|
||||
//connect(tableVolumeComics, SIGNAL(pressed(QModelIndex)), tableFiles, SLOT(setCurrentIndex(QModelIndex)));
|
||||
//connect(tableFiles, SIGNAL(pressed(QModelIndex)), tableVolumeComics, SLOT(setCurrentIndex(QModelIndex)));
|
||||
|
||||
paginator->setCustomLabel(tr("issues"));
|
||||
paginator->setMinimumWidth(422);
|
||||
|
||||
sortButtonsLayout->addWidget(moveUpButtonCL);
|
||||
sortButtonsLayout->addWidget(ScrapperToolButton::getSeparator());
|
||||
sortButtonsLayout->addWidget(moveDownButtonCL);
|
||||
sortButtonsLayout->addSpacing(10);
|
||||
//sortButtonsLayout->addStretch();
|
||||
sortButtonsLayout->addWidget(sortLabel);
|
||||
sortButtonsLayout->addStretch();
|
||||
sortButtonsLayout->addWidget(paginator);
|
||||
//sortButtonsLayout->addStretch();
|
||||
//sortButtonsLayout->addWidget(moveUpButtonIL);
|
||||
//sortButtonsLayout->addWidget(ScrapperToolButton::getSeparator());
|
||||
//sortButtonsLayout->addWidget(moveDownButtonIL);
|
||||
sortButtonsLayout->setSpacing(0);
|
||||
|
||||
l->addSpacing(15);
|
||||
l->addWidget(label);
|
||||
l->addSpacing(5);
|
||||
l->addLayout(content);
|
||||
l->addLayout(sortButtonsLayout);
|
||||
l->addStretch();
|
||||
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
setLayout(l);
|
||||
setContentsMargins(0,0,0,0);
|
||||
|
||||
//rows actions
|
||||
QAction * removeItemFromList = new QAction(tr("remove selected comics"),this);
|
||||
QAction * restoreAllItems = new QAction(tr("restore all removed comics"),this);
|
||||
QAction * restoreItems = new QAction(tr("restore removed comics"),this);
|
||||
|
||||
tableFiles->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
tableFiles->addAction(removeItemFromList);
|
||||
tableFiles->addAction(restoreAllItems);
|
||||
//tableFiles->addAction(restoreItems);
|
||||
|
||||
connect(removeItemFromList,SIGNAL(triggered()),this,SLOT(removeSelectedComics()));
|
||||
connect(restoreAllItems,SIGNAL(triggered()),this,SLOT(restoreAllComics()));
|
||||
connect(restoreItems,SIGNAL(triggered()),this,SLOT(showRemovedComicsSelector()));
|
||||
}
|
||||
|
||||
void SortVolumeComics::setData(QList<ComicDB> & comics, const QString &json, const QString &vID)
|
||||
{
|
||||
//set up models
|
||||
localComicsModel = new LocalComicListModel;
|
||||
localComicsModel->load(comics);
|
||||
|
||||
volumeComicsModel = new VolumeComicsModel;
|
||||
volumeComicsModel->load(json);
|
||||
|
||||
int numLocalComics = localComicsModel->rowCount();
|
||||
int numVolumeComics = volumeComicsModel->rowCount();
|
||||
|
||||
if(numLocalComics > numVolumeComics)
|
||||
volumeComicsModel->addExtraRows(numLocalComics - numVolumeComics);
|
||||
if(numLocalComics < numVolumeComics)
|
||||
localComicsModel->addExtraRows(numVolumeComics - numLocalComics);
|
||||
|
||||
tableFiles->setModel(localComicsModel);
|
||||
tableVolumeComics->setModel(volumeComicsModel);
|
||||
|
||||
tableVolumeComics->resizeColumnToContents(0);
|
||||
|
||||
ScraperSelector::load(json,vID);
|
||||
}
|
||||
|
||||
void SortVolumeComics::synchronizeScroll(int pos)
|
||||
{
|
||||
void * senderObject = sender();
|
||||
|
||||
if(senderObject == 0) //invalid call
|
||||
return;
|
||||
|
||||
QScrollBar * tableVolumeComicsScrollBar = tableVolumeComics->verticalScrollBar();
|
||||
QScrollBar * tableFilesScrollBar = tableFiles->verticalScrollBar();
|
||||
|
||||
if(senderObject == tableVolumeComicsScrollBar)
|
||||
{
|
||||
disconnect(tableFilesScrollBar,SIGNAL(valueChanged(int)),this,0);
|
||||
tableFilesScrollBar->setValue(pos);
|
||||
connect(tableFilesScrollBar, SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int)));
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect(tableVolumeComicsScrollBar,SIGNAL(valueChanged(int)),this,0);
|
||||
tableVolumeComicsScrollBar->setValue(pos);
|
||||
connect(tableVolumeComicsScrollBar, SIGNAL(valueChanged(int)), this, SLOT(synchronizeScroll(int)));
|
||||
}
|
||||
}
|
||||
|
||||
void SortVolumeComics::moveUpCL()
|
||||
{
|
||||
QList<QModelIndex> selection = tableFiles->selectionModel()->selectedIndexes();
|
||||
|
||||
if(selection.count() == 0)
|
||||
return;
|
||||
|
||||
localComicsModel->moveSelectionUp(selection);
|
||||
|
||||
selection = tableFiles->selectionModel()->selectedIndexes();
|
||||
tableFiles->scrollTo(selection.first());
|
||||
}
|
||||
|
||||
void SortVolumeComics::moveDownCL()
|
||||
{
|
||||
QList<QModelIndex> selection = tableFiles->selectionModel()->selectedIndexes();
|
||||
|
||||
if(selection.count() > 0)
|
||||
{
|
||||
localComicsModel->moveSelectionDown(selection);
|
||||
|
||||
selection = tableFiles->selectionModel()->selectedIndexes();
|
||||
tableFiles->scrollTo(selection.last());
|
||||
}
|
||||
}
|
||||
|
||||
void SortVolumeComics::moveUpIL()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SortVolumeComics::moveDownIL()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SortVolumeComics::removeSelectedComics()
|
||||
{
|
||||
QList<QModelIndex> selection = tableFiles->selectionModel()->selectedIndexes();
|
||||
|
||||
localComicsModel->removeComics(selection);
|
||||
}
|
||||
|
||||
void SortVolumeComics::restoreAllComics()
|
||||
{
|
||||
localComicsModel->restoreAll();
|
||||
}
|
||||
|
||||
void SortVolumeComics::showRemovedComicsSelector()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QList<QPair<ComicDB, QString> > SortVolumeComics::getMatchingInfo()
|
||||
{
|
||||
QList<ComicDB> comicList = localComicsModel->getData();
|
||||
QList<QPair<ComicDB, QString> > l;
|
||||
|
||||
int index = 0;
|
||||
|
||||
QString id;
|
||||
foreach(ComicDB c, comicList)
|
||||
{
|
||||
id = volumeComicsModel->getComicId(index);
|
||||
if(!c.getFileName().isEmpty() && !id.isEmpty()) //there is a valid comic, and valid comic ID
|
||||
{
|
||||
l.push_back(QPair<ComicDB, QString>(c,id));
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
99
YACReaderLibrary/comic_vine/sort_volume_comics.h
Normal file
99
YACReaderLibrary/comic_vine/sort_volume_comics.h
Normal file
@ -0,0 +1,99 @@
|
||||
#ifndef SORT_VOLUME_COMICS_H
|
||||
#define SORT_VOLUME_COMICS_H
|
||||
|
||||
#include "scraper_selector.h"
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QPushButton>
|
||||
#include <QPainter>
|
||||
|
||||
#include "comic_db.h"
|
||||
|
||||
class ScraperTableView;
|
||||
class LocalComicListModel;
|
||||
class VolumeComicsModel;
|
||||
|
||||
class ScrapperToolButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Appearance {
|
||||
DEFAULT,
|
||||
LEFT,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
ScrapperToolButton(ScrapperToolButton::Appearance appearance = DEFAULT, QWidget * parent=0):QPushButton(parent),appearance(appearance) {
|
||||
setStyleSheet("QPushButton {border: none; background: #2e2e2e; color:white; border-radius:2px;}"
|
||||
"QPushButton::pressed {border: none; background: #282828; color:white; border-radius:2px;}");
|
||||
setFixedSize(18,17);
|
||||
}
|
||||
static QWidget * getSeparator(){QWidget * w = new QWidget; w->setFixedWidth(1); w->setStyleSheet("QWidget {background:#282828;}"); return w;}
|
||||
void setAppearance(ScrapperToolButton::Appearance appearance){this->appearance = appearance;}
|
||||
virtual ~ScrapperToolButton() {}
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent * e)
|
||||
{
|
||||
QPainter p(this);
|
||||
|
||||
switch (appearance) {
|
||||
case LEFT:
|
||||
p.fillRect(16,0,2,18,QColor("#2E2E2E"));
|
||||
break;
|
||||
case RIGHT:
|
||||
p.fillRect(0,0,2,18,QColor("#2E2E2E"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QPushButton::paintEvent(e);
|
||||
}
|
||||
|
||||
private:
|
||||
Appearance appearance;
|
||||
};
|
||||
|
||||
|
||||
class SortVolumeComics : public ScraperSelector
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SortVolumeComics(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
void setData(QList<ComicDB> & comics, const QString & json, const QString & vID);
|
||||
QList<QPair<ComicDB,QString> > getMatchingInfo();
|
||||
|
||||
protected slots:
|
||||
void synchronizeScroll(int pos);
|
||||
void moveUpCL();
|
||||
void moveDownCL();
|
||||
void moveUpIL();
|
||||
void moveDownIL();
|
||||
|
||||
void removeSelectedComics();
|
||||
void restoreAllComics();
|
||||
void showRemovedComicsSelector();
|
||||
|
||||
|
||||
private:
|
||||
ScraperTableView * tableFiles;
|
||||
ScraperTableView * tableVolumeComics;
|
||||
|
||||
LocalComicListModel * localComicsModel;
|
||||
VolumeComicsModel * volumeComicsModel;
|
||||
|
||||
ScrapperToolButton * moveUpButtonCL;
|
||||
ScrapperToolButton * moveDownButtonCL;
|
||||
ScrapperToolButton * moveUpButtonIL;
|
||||
ScrapperToolButton * moveDownButtonIL;
|
||||
|
||||
};
|
||||
|
||||
#endif // SORT_VOLUME_COMICS_H
|
53
YACReaderLibrary/comic_vine/title_header.cpp
Normal file
53
YACReaderLibrary/comic_vine/title_header.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "title_header.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
TitleHeader::TitleHeader(QWidget * parent )
|
||||
:QWidget(parent)
|
||||
{
|
||||
mainTitleLabel = new QLabel();
|
||||
subTitleLabel = new QLabel();
|
||||
|
||||
mainTitleLabel->setStyleSheet("QLabel {color:white; font-size:18px;font-family:Arial;}");
|
||||
subTitleLabel->setStyleSheet("QLabel {color:white; font-size:12px;font-family:Arial;}");
|
||||
|
||||
QHBoxLayout * titleLayout = new QHBoxLayout;
|
||||
QVBoxLayout * titleLabelsLayout = new QVBoxLayout;
|
||||
|
||||
titleLabelsLayout->addWidget(mainTitleLabel);
|
||||
titleLabelsLayout->addWidget(subTitleLabel);
|
||||
titleLabelsLayout->setSpacing(0);
|
||||
|
||||
titleLayout->addLayout(titleLabelsLayout);
|
||||
titleLayout->setContentsMargins(0,0,0,0);
|
||||
|
||||
setLayout(titleLayout);
|
||||
|
||||
setContentsMargins(0,0,0,0);
|
||||
|
||||
setTitle(tr("SEARCH"));
|
||||
}
|
||||
|
||||
void TitleHeader::setTitle(const QString & title)
|
||||
{
|
||||
mainTitleLabel->setText(title);
|
||||
}
|
||||
|
||||
void TitleHeader::setSubTitle(const QString & title)
|
||||
{
|
||||
subTitleLabel->setText(title);
|
||||
}
|
||||
|
||||
void TitleHeader::showButtons(bool show)
|
||||
{
|
||||
if(show)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
22
YACReaderLibrary/comic_vine/title_header.h
Normal file
22
YACReaderLibrary/comic_vine/title_header.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef TITLE_HEADER_H
|
||||
#define TITLE_HEADER_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QLabel;
|
||||
|
||||
class TitleHeader : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TitleHeader(QWidget * parent = 0);
|
||||
public slots:
|
||||
void setTitle(const QString & title);
|
||||
void setSubTitle(const QString & title);
|
||||
void showButtons(bool show);
|
||||
private:
|
||||
QLabel * mainTitleLabel;
|
||||
QLabel * subTitleLabel;
|
||||
};
|
||||
|
||||
#endif // TITLE_HEADER_H
|
63
YACReaderLibrary/comics_remover.cpp
Normal file
63
YACReaderLibrary/comics_remover.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
#include "comics_remover.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
ComicsRemover::ComicsRemover(QModelIndexList & il, QList<QString> & ps, QObject *parent)
|
||||
:QObject(parent),indexList(il), paths(ps)
|
||||
{
|
||||
}
|
||||
|
||||
void ComicsRemover::process()
|
||||
{
|
||||
QString currentComicPath;
|
||||
QListIterator<QModelIndex> i(indexList);
|
||||
QListIterator<QString> i2(paths);
|
||||
i.toBack();
|
||||
i2.toBack();
|
||||
|
||||
while (i.hasPrevious() && i2.hasPrevious())
|
||||
{
|
||||
QModelIndex mi = i.previous();
|
||||
currentComicPath = i2.previous();
|
||||
if(QFile::remove(currentComicPath))
|
||||
emit remove(mi.row());
|
||||
else
|
||||
emit removeError();
|
||||
}
|
||||
|
||||
emit finished();
|
||||
}
|
||||
|
||||
|
||||
FoldersRemover::FoldersRemover(QModelIndexList &il, QList<QString> &ps, QObject *parent)
|
||||
:QObject(parent),indexList(il), paths(ps)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void FoldersRemover::process()
|
||||
{
|
||||
QString currentFolderPath;
|
||||
QListIterator<QModelIndex> i(indexList);
|
||||
QListIterator<QString> i2(paths);
|
||||
i.toBack();
|
||||
i2.toBack();
|
||||
|
||||
QLOG_DEBUG() << "Deleting folders" << paths.at(0);
|
||||
|
||||
while (i.hasPrevious() && i2.hasPrevious())
|
||||
{
|
||||
QModelIndex mi = i.previous();
|
||||
currentFolderPath = i2.previous();
|
||||
QDir d(currentFolderPath);
|
||||
if(d.removeRecursively() || !d.exists()) //the folder is in the DB but no in the drive...
|
||||
emit remove(mi);
|
||||
else
|
||||
emit removeError();
|
||||
}
|
||||
|
||||
emit finished();
|
||||
}
|
47
YACReaderLibrary/comics_remover.h
Normal file
47
YACReaderLibrary/comics_remover.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef COMICS_REMOVER_H
|
||||
#define COMICS_REMOVER_H
|
||||
|
||||
#include <QThread>
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <comic_db.h>
|
||||
|
||||
class ComicsRemover : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComicsRemover(QModelIndexList & indexList, QList<QString> & paths, QObject *parent = 0);
|
||||
|
||||
signals:
|
||||
void remove(int);
|
||||
void removeError();
|
||||
void finished();
|
||||
|
||||
public slots:
|
||||
void process();
|
||||
|
||||
private:
|
||||
QModelIndexList indexList;
|
||||
QList<QString> paths;
|
||||
};
|
||||
|
||||
class FoldersRemover : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FoldersRemover(QModelIndexList & indexList, QList<QString> & paths, QObject *parent = 0);
|
||||
|
||||
signals:
|
||||
void remove(QModelIndex);
|
||||
void removeError();
|
||||
void finished();
|
||||
|
||||
public slots:
|
||||
void process();
|
||||
|
||||
private:
|
||||
QModelIndexList indexList;
|
||||
QList<QString> paths;
|
||||
};
|
||||
|
||||
#endif // COMICS_REMOVER_H
|
69
YACReaderLibrary/comics_view.cpp
Normal file
69
YACReaderLibrary/comics_view.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "comics_view.h"
|
||||
#include "comic.h"
|
||||
#include "comic_files_manager.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
ComicsView::ComicsView(QWidget *parent) :
|
||||
QWidget(parent),model(NULL)
|
||||
{
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void ComicsView::setModel(ComicModel *m)
|
||||
{
|
||||
model = m;
|
||||
}
|
||||
|
||||
void ComicsView::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
if(model->canDropMimeData(event->mimeData(),event->proposedAction(),0,0,QModelIndex()))
|
||||
event->acceptProposedAction();
|
||||
else
|
||||
{
|
||||
QLOG_TRACE() << "dragEnterEvent";
|
||||
QList<QUrl> urlList;
|
||||
|
||||
if (event->mimeData()->hasUrls() && event->dropAction() == Qt::CopyAction)
|
||||
{
|
||||
urlList = event->mimeData()->urls();
|
||||
QString currentPath;
|
||||
foreach (QUrl url, urlList)
|
||||
{
|
||||
//comics or folders are accepted, folders' content is validate in dropEvent (avoid any lag before droping)
|
||||
currentPath = url.toLocalFile();
|
||||
if(Comic::fileIsComic(currentPath) || QFileInfo(currentPath).isDir())
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ComicsView::dropEvent(QDropEvent *event)
|
||||
{
|
||||
QLOG_DEBUG() << "drop" << event->dropAction();
|
||||
|
||||
bool validAction = event->dropAction() == Qt::CopyAction;// || event->dropAction() & Qt::MoveAction; TODO move
|
||||
|
||||
if(event->mimeData()->hasUrls() && validAction)
|
||||
{
|
||||
|
||||
QList<QPair<QString, QString> > droppedFiles = ComicFilesManager::getDroppedFiles(event->mimeData()->urls());
|
||||
|
||||
if(event->dropAction() == Qt::CopyAction)
|
||||
{
|
||||
QLOG_DEBUG() << "copy :" << droppedFiles;
|
||||
emit copyComicsToCurrentFolder(droppedFiles);
|
||||
}
|
||||
else if(event->dropAction() & Qt::MoveAction)
|
||||
{
|
||||
QLOG_DEBUG() << "move :" << droppedFiles;
|
||||
emit moveComicsToCurrentFolder(droppedFiles);
|
||||
}
|
||||
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
56
YACReaderLibrary/comics_view.h
Normal file
56
YACReaderLibrary/comics_view.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef COMICS_VIEW_H
|
||||
#define COMICS_VIEW_H
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "comic_model.h"
|
||||
|
||||
class YACReaderTableView;
|
||||
class QSplitter;
|
||||
class ComicFlowWidget;
|
||||
class QToolBar;
|
||||
class ComicModel;
|
||||
class ComicsView : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComicsView(QWidget *parent = 0);
|
||||
virtual void setToolBar(QToolBar * toolBar) = 0;
|
||||
virtual void setModel(ComicModel *model);
|
||||
virtual void setCurrentIndex(const QModelIndex &index) = 0;
|
||||
virtual QModelIndex currentIndex() = 0;
|
||||
virtual QItemSelectionModel * selectionModel() = 0;
|
||||
virtual void scrollTo(const QModelIndex & mi, QAbstractItemView::ScrollHint hint ) = 0;
|
||||
virtual void toFullScreen() = 0;
|
||||
virtual void toNormal() = 0;
|
||||
virtual void updateConfig(QSettings * settings) = 0;
|
||||
virtual void enableFilterMode(bool enabled) = 0;
|
||||
virtual void selectIndex(int index) = 0;
|
||||
|
||||
signals:
|
||||
void selected(unsigned int);
|
||||
void comicRated(int,QModelIndex);
|
||||
|
||||
//Context menus
|
||||
void customContextMenuViewRequested(QPoint);
|
||||
void customContextMenuItemRequested(QPoint);
|
||||
|
||||
//Drops
|
||||
void copyComicsToCurrentFolder(QList<QPair<QString, QString> >);
|
||||
void moveComicsToCurrentFolder(QList<QPair<QString, QString> >);
|
||||
|
||||
public slots:
|
||||
virtual void setShowMarks(bool show) = 0;
|
||||
virtual void selectAll() = 0;
|
||||
protected:
|
||||
ComicModel * model;
|
||||
|
||||
//Drop to import
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dropEvent(QDropEvent *event);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif // COMICS_VIEW_H
|
85
YACReaderLibrary/comics_view_transition.cpp
Normal file
85
YACReaderLibrary/comics_view_transition.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include "comics_view_transition.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QMovie>
|
||||
#include <QSettings>
|
||||
#include <QTimer>
|
||||
#include <QSizePolicy>
|
||||
#include <QPainter>
|
||||
|
||||
#include "yacreader_global_gui.h"
|
||||
|
||||
ComicsViewTransition::ComicsViewTransition(QWidget *parent) :
|
||||
QWidget(parent),movie(0)
|
||||
{
|
||||
QVBoxLayout * layout = new QVBoxLayout;
|
||||
|
||||
settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini",QSettings::IniFormat);
|
||||
settings->beginGroup("libraryConfig");
|
||||
|
||||
movieLabel = new QLabel("Placeholder");
|
||||
movieLabel->setAlignment(Qt::AlignCenter);
|
||||
QLabel * textLabel = new QLabel("Switching comics view");
|
||||
textLabel->setAlignment(Qt::AlignCenter);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
textLabel->setStyleSheet("QLabel {color:#888888; font-size:24px;font-family:Arial;font-weight:bold;}");
|
||||
setStyleSheet("QWidget {background:#FFFFFF}");
|
||||
#else
|
||||
textLabel->setStyleSheet("QLabel {color:#CCCCCC; font-size:24px;font-family:Arial;font-weight:bold;}");
|
||||
setStyleSheet("QWidget {background:#2A2A2A}");
|
||||
#endif
|
||||
|
||||
//movieLabel->setFixedSize(450,350);
|
||||
|
||||
layout->addSpacing(100);
|
||||
layout->addWidget(movieLabel);
|
||||
layout->addSpacing(20);
|
||||
layout->addWidget(textLabel);
|
||||
layout->addStretch();
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
setContentsMargins(0,0,0,0);
|
||||
|
||||
//QSizePolicy sp();
|
||||
setSizePolicy(QSizePolicy ::Expanding , QSizePolicy ::Expanding );
|
||||
//movieLabel->setSizePolicy(QSizePolicy ::Expanding , QSizePolicy ::Expanding );
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
QSize ComicsViewTransition::sizeHint()
|
||||
{
|
||||
return QSize(450,350);
|
||||
}
|
||||
|
||||
void ComicsViewTransition::startMovie()
|
||||
{
|
||||
if(movie)
|
||||
delete movie;
|
||||
|
||||
if(settings->value(COMICS_VIEW_STATUS) == YACReader::Flow)
|
||||
movie = new QMovie(":/images/flow_to_grid.gif");
|
||||
else
|
||||
movie = new QMovie(":/images/grid_to_flow.gif");
|
||||
|
||||
connect(movie,SIGNAL(finished()),this,SIGNAL(transitionFinished()));
|
||||
//connect(movie,SIGNAL(finished()),movie,SLOT(deleteLater());
|
||||
movie->setSpeed(200);
|
||||
movie->jumpToFrame(0);
|
||||
movieLabel->setMovie(movie);
|
||||
|
||||
QTimer::singleShot(100,movie,SLOT(start()));
|
||||
}
|
||||
|
||||
void ComicsViewTransition::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter (this);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
painter.fillRect(0,0,width(),height(),QColor("#FFFFFF"));
|
||||
#else
|
||||
painter.fillRect(0,0,width(),height(),QColor("#2A2A2A"));
|
||||
#endif
|
||||
}
|
31
YACReaderLibrary/comics_view_transition.h
Normal file
31
YACReaderLibrary/comics_view_transition.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef COMICS_VIEW_TRANSITION_H
|
||||
#define COMICS_VIEW_TRANSITION_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QMovie;
|
||||
class QSettings;
|
||||
class QLabel;
|
||||
|
||||
class ComicsViewTransition : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ComicsViewTransition(QWidget *parent = 0);
|
||||
QSize sizeHint();
|
||||
|
||||
signals:
|
||||
void transitionFinished();
|
||||
|
||||
public slots:
|
||||
void startMovie();
|
||||
|
||||
protected:
|
||||
QMovie * movie;
|
||||
QSettings * settings;
|
||||
QLabel * movieLabel;
|
||||
|
||||
void paintEvent(QPaintEvent *);
|
||||
};
|
||||
|
||||
#endif // COMICS_VIEW_TRANSITION_H
|
206
YACReaderLibrary/create_library_dialog.cpp
Normal file
206
YACReaderLibrary/create_library_dialog.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
#include "create_library_dialog.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QFileDialog>
|
||||
#include <QSizePolicy>
|
||||
#include <QMessageBox>
|
||||
|
||||
CreateLibraryDialog::CreateLibraryDialog(QWidget * parent)
|
||||
:QDialog(parent)
|
||||
{
|
||||
setupUI();
|
||||
}
|
||||
|
||||
void CreateLibraryDialog::setupUI()
|
||||
{
|
||||
textLabel = new QLabel(tr("Comics folder : "));
|
||||
path = new QLineEdit;
|
||||
textLabel->setBuddy(path);
|
||||
connect(path,SIGNAL(textChanged(QString)),this,SLOT(pathSetted(QString)));
|
||||
|
||||
nameLabel = new QLabel(tr("Library Name : "));
|
||||
nameEdit = new QLineEdit;
|
||||
nameLabel->setBuddy(nameEdit);
|
||||
connect(nameEdit,SIGNAL(textChanged(QString)),this,SLOT(nameSetted(QString)));
|
||||
|
||||
accept = new QPushButton(tr("Create"));
|
||||
accept->setDisabled(true);
|
||||
connect(accept,SIGNAL(clicked()),this,SLOT(create()));
|
||||
|
||||
cancel = new QPushButton(tr("Cancel"));
|
||||
connect(cancel,SIGNAL(clicked()),this,SIGNAL(cancelCreate()));
|
||||
connect(cancel,SIGNAL(clicked()),this,SLOT(close()));
|
||||
|
||||
find = new QPushButton(QIcon(":/images/find_folder.png"),"");
|
||||
connect(find,SIGNAL(clicked()),this,SLOT(findPath()));
|
||||
|
||||
QGridLayout * content = new QGridLayout;
|
||||
|
||||
//QHBoxLayout *nameLayout = new QHBoxLayout;
|
||||
|
||||
content->addWidget(nameLabel,0,0);
|
||||
content->addWidget(nameEdit,0,1);
|
||||
|
||||
//QHBoxLayout *libraryLayout = new QHBoxLayout;
|
||||
|
||||
content->addWidget(textLabel,1,0);
|
||||
content->addWidget(path,1,1);
|
||||
content->addWidget(find,1,2);
|
||||
content->setColumnMinimumWidth(2,0); //TODO
|
||||
|
||||
QHBoxLayout *bottomLayout = new QHBoxLayout;
|
||||
bottomLayout->addWidget(message = new QLabel(tr("Create a library could take several minutes. You can stop the process and update the library later for completing the task.")));
|
||||
message->setWordWrap(true);
|
||||
//message->hide();
|
||||
bottomLayout->addStretch();
|
||||
bottomLayout->addWidget(accept);
|
||||
bottomLayout->addWidget(cancel);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(content);
|
||||
|
||||
mainLayout->addLayout(bottomLayout);
|
||||
|
||||
QHBoxLayout * imgMainLayout = new QHBoxLayout;
|
||||
QLabel * imgLabel = new QLabel(this);
|
||||
QPixmap p(":/images/new.png");
|
||||
imgLabel->setPixmap(p);
|
||||
imgMainLayout->addWidget(imgLabel);
|
||||
imgMainLayout->addLayout(mainLayout);
|
||||
|
||||
setLayout(imgMainLayout);
|
||||
|
||||
setModal(true);
|
||||
setWindowTitle(tr("Create new library"));
|
||||
}
|
||||
|
||||
void CreateLibraryDialog::open(const YACReaderLibraries & libs)
|
||||
{
|
||||
libraries = libs;
|
||||
QDialog::open();
|
||||
}
|
||||
|
||||
void CreateLibraryDialog::create()
|
||||
{
|
||||
|
||||
QFileInfo f(path->text());
|
||||
if(f.exists() && f.isDir() && f.isWritable())
|
||||
{
|
||||
if(!libraries.contains(nameEdit->text()))
|
||||
{
|
||||
emit(createLibrary(QDir::cleanPath(path->text()),QDir::cleanPath(path->text())+"/.yacreaderlibrary",nameEdit->text()));
|
||||
close();
|
||||
}
|
||||
else
|
||||
emit(libraryExists(nameEdit->text()));
|
||||
}
|
||||
else
|
||||
QMessageBox::critical(NULL,tr("Path not found"),tr("The selected path does not exist or is not a valid path. Be sure that you have write access to this folder"));
|
||||
}
|
||||
|
||||
void CreateLibraryDialog::nameSetted(const QString & text)
|
||||
{
|
||||
if(!text.isEmpty())
|
||||
{
|
||||
if(!path->text().isEmpty())
|
||||
{
|
||||
QFileInfo fi(path->text());
|
||||
if(fi.isDir())
|
||||
accept->setEnabled(true);
|
||||
else
|
||||
accept->setEnabled(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
accept->setEnabled(false);
|
||||
}
|
||||
|
||||
void CreateLibraryDialog::pathSetted(const QString & text)
|
||||
{
|
||||
QFileInfo fi(text);
|
||||
if(fi.isDir())
|
||||
{
|
||||
if(!nameEdit->text().isEmpty())
|
||||
accept->setEnabled(true);
|
||||
}
|
||||
else
|
||||
accept->setEnabled(false);
|
||||
}
|
||||
|
||||
void CreateLibraryDialog::findPath()
|
||||
{
|
||||
QString s = QFileDialog::getExistingDirectory(0,"Comics directory",".");
|
||||
if(!s.isEmpty())
|
||||
{
|
||||
path->setText(s);
|
||||
if(!nameEdit->text().isEmpty())
|
||||
accept->setEnabled(true);
|
||||
}
|
||||
else
|
||||
accept->setEnabled(false);
|
||||
}
|
||||
|
||||
void CreateLibraryDialog::close()
|
||||
{
|
||||
path->clear();
|
||||
nameEdit->clear();
|
||||
accept->setEnabled(false);
|
||||
QDialog::close();
|
||||
}
|
||||
|
||||
void CreateLibraryDialog::setDataAndStart(QString name, QString path)
|
||||
{
|
||||
this->path->setText(path);
|
||||
this->nameEdit->setText(name);
|
||||
QDialog::open();
|
||||
create();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// UpdateLibraryDialog
|
||||
//-----------------------------------------------------------------------------
|
||||
UpdateLibraryDialog::UpdateLibraryDialog(QWidget * parent)
|
||||
:QDialog(parent)
|
||||
{
|
||||
QVBoxLayout * mainLayout = new QVBoxLayout;
|
||||
mainLayout->addWidget(message = new QLabel(tr("Updating....")));
|
||||
mainLayout->addWidget(currentFileLabel = new QLabel("\n\n\n\n"));
|
||||
currentFileLabel->setWordWrap(true);
|
||||
|
||||
QHBoxLayout * bottom = new QHBoxLayout;
|
||||
bottom->addStretch();
|
||||
bottom->addWidget(cancel = new QPushButton(tr("Cancel")));
|
||||
|
||||
connect(cancel,SIGNAL(clicked()),this,SIGNAL(cancelUpdate()));
|
||||
connect(cancel,SIGNAL(clicked()),this,SLOT(close()));
|
||||
|
||||
mainLayout->addStretch();
|
||||
|
||||
mainLayout->addLayout(bottom);
|
||||
|
||||
QHBoxLayout * imgMainLayout = new QHBoxLayout;
|
||||
QLabel * imgLabel = new QLabel(this);
|
||||
QPixmap p(":/images/updateLibrary.png");
|
||||
imgLabel->setPixmap(p);
|
||||
imgMainLayout->addWidget(imgLabel);
|
||||
imgMainLayout->addLayout(mainLayout);
|
||||
|
||||
setLayout(imgMainLayout);
|
||||
|
||||
setModal(true);
|
||||
setWindowTitle(tr("Update library"));
|
||||
}
|
||||
|
||||
void UpdateLibraryDialog::showCurrentFile(QString file)
|
||||
{
|
||||
currentFileLabel->setText(file);
|
||||
currentFileLabel->update();
|
||||
this->update();
|
||||
}
|
||||
|
||||
void UpdateLibraryDialog::close()
|
||||
{
|
||||
currentFileLabel->setText("");
|
||||
this->adjustSize();
|
||||
QDialog::close();
|
||||
}
|
61
YACReaderLibrary/create_library_dialog.h
Normal file
61
YACReaderLibrary/create_library_dialog.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef __CREATE_LIBRARY_DIALOG_H
|
||||
#define __CREATE_LIBRARY_DIALOG_H
|
||||
|
||||
#include "yacreader_libraries.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QThread>
|
||||
#include <QProgressBar>
|
||||
|
||||
class CreateLibraryDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CreateLibraryDialog(QWidget * parent = 0);
|
||||
private:
|
||||
QLabel * nameLabel;
|
||||
QLabel * textLabel;
|
||||
QLabel * message;
|
||||
QProgressBar *progressBar;
|
||||
QLineEdit * path;
|
||||
QLineEdit * nameEdit;
|
||||
QPushButton * find;
|
||||
QPushButton * accept;
|
||||
QPushButton * cancel;
|
||||
YACReaderLibraries libraries;
|
||||
void setupUI();
|
||||
public slots:
|
||||
void create();
|
||||
void findPath();
|
||||
void close();
|
||||
void setDataAndStart(QString name, QString paht);
|
||||
void nameSetted(const QString & text);
|
||||
void pathSetted(const QString & text);
|
||||
void open(const YACReaderLibraries &libraries);
|
||||
signals:
|
||||
void createLibrary(QString source, QString target, QString name);
|
||||
void cancelCreate();
|
||||
void libraryExists(const QString & name);
|
||||
};
|
||||
|
||||
class UpdateLibraryDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
UpdateLibraryDialog(QWidget * parent = 0);
|
||||
private:
|
||||
QLabel * message;
|
||||
QLabel * currentFileLabel;
|
||||
QProgressBar *progressBar;
|
||||
QPushButton * cancel;
|
||||
public slots:
|
||||
void showCurrentFile(QString file);
|
||||
void close();
|
||||
signals:
|
||||
void cancelUpdate();
|
||||
};
|
||||
|
||||
#endif
|
47
YACReaderLibrary/db/comic_item.cpp
Normal file
47
YACReaderLibrary/db/comic_item.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
#include "comic_item.h"
|
||||
|
||||
//! [0]
|
||||
ComicItem::ComicItem(const QList<QVariant> &data)
|
||||
|
||||
{
|
||||
itemData = data;
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
ComicItem::~ComicItem()
|
||||
{
|
||||
|
||||
}
|
||||
//! [1]
|
||||
|
||||
|
||||
//! [5]
|
||||
int ComicItem::columnCount() const
|
||||
{
|
||||
return itemData.count();
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
QVariant ComicItem::data(int column) const
|
||||
{
|
||||
return itemData.value(column);
|
||||
}
|
||||
//! [6]
|
||||
|
||||
void ComicItem::setData(int column,const QVariant & value)
|
||||
{
|
||||
itemData[column] = value;
|
||||
}
|
||||
|
||||
//! [8]
|
||||
int ComicItem::row() const
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [8]
|
27
YACReaderLibrary/db/comic_item.h
Normal file
27
YACReaderLibrary/db/comic_item.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef TABLEITEM_H
|
||||
#define TABLEITEM_H
|
||||
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
|
||||
//! [0]
|
||||
class ComicItem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComicItem(const QList<QVariant> &data);
|
||||
~ComicItem();
|
||||
int columnCount() const;
|
||||
QVariant data(int column) const;
|
||||
void setData(int column,const QVariant & value);
|
||||
int row() const;
|
||||
//unsigned long long int id; //TODO sustituir por una clase adecuada
|
||||
//Comic comic;
|
||||
private:
|
||||
QList<QVariant> itemData;
|
||||
|
||||
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif
|
1158
YACReaderLibrary/db/comic_model.cpp
Normal file
1158
YACReaderLibrary/db/comic_model.cpp
Normal file
File diff suppressed because it is too large
Load Diff
166
YACReaderLibrary/db/comic_model.h
Normal file
166
YACReaderLibrary/db/comic_model.h
Normal file
@ -0,0 +1,166 @@
|
||||
#ifndef TABLEMODEL_H
|
||||
#define TABLEMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlDatabase>
|
||||
|
||||
#include "yacreader_global_gui.h"
|
||||
|
||||
class ComicDB;
|
||||
|
||||
class ComicItem;
|
||||
|
||||
using namespace YACReader;
|
||||
|
||||
//! [0]
|
||||
class ComicModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ComicModel(QObject *parent = 0);
|
||||
ComicModel( QSqlQuery &sqlquery, QObject *parent = 0);
|
||||
~ComicModel();
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
bool canBeResorted();
|
||||
QMimeData * mimeData(const QModelIndexList &indexes) const;
|
||||
QStringList mimeTypes() const;
|
||||
|
||||
void setupFolderModelData(unsigned long long int parentFolder,const QString & databasePath);
|
||||
void setupLabelModelData(unsigned long long int parentLabel, const QString & databasePath);
|
||||
void setupReadingListModelData(unsigned long long int parentReadingList, const QString & databasePath);
|
||||
void setupFavoritesModelData(const QString & databasePath);
|
||||
void setupReadingModelData(const QString & databasePath);
|
||||
//configures the model for showing the comics matching the filter criteria.
|
||||
void setupModelData(const SearchModifiers modifier, const QString & filter, const QString & databasePath);
|
||||
|
||||
//Métodos de conveniencia
|
||||
QStringList getPaths(const QString & _source);
|
||||
QString getComicPath(QModelIndex mi);
|
||||
QString getCurrentPath(){return QString(_databasePath).remove("/.yacreaderlibrary");}
|
||||
ComicDB getComic(const QModelIndex & mi); //--> para la edición
|
||||
//ComicDB getComic(int row);
|
||||
QVector<YACReaderComicReadStatus> getReadList();
|
||||
QVector<YACReaderComicReadStatus> setAllComicsRead(YACReaderComicReadStatus readStatus);
|
||||
QList<ComicDB> getComics(QList<QModelIndex> list); //--> recupera la información común a los comics seleccionados
|
||||
QList<ComicDB> getAllComics();
|
||||
QModelIndex getIndexFromId(quint64 id);
|
||||
QList<QModelIndex> getIndexesFromIds(const QList<qulonglong> &comicIds);
|
||||
//setcomicInfo(QModelIndex & mi); --> inserta en la base datos
|
||||
//setComicInfoForAllComics(); --> inserta la información común a todos los cómics de una sola vez.
|
||||
//setComicInfoForSelectedComis(QList<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 removeInTransaction(int row);
|
||||
void reload(const ComicDB & comic);
|
||||
void resetComicRating(const QModelIndex & mi);
|
||||
|
||||
|
||||
void addComicsToFavorites(const QList<QModelIndex> &comicsList);
|
||||
void addComicsToLabel(const QList<QModelIndex> &comicsList, qulonglong labelId);
|
||||
void addComicsToReadingList(const QList<QModelIndex> &comicsList, qulonglong readingListId);
|
||||
|
||||
void deleteComicsFromFavorites(const QList<QModelIndex> &comicsList);
|
||||
void deleteComicsFromLabel(const QList<QModelIndex> &comicsList, qulonglong labelId);
|
||||
void deleteComicsFromReadingList(const QList<QModelIndex> &comicsList, qulonglong readingListId);
|
||||
|
||||
void deleteComicsFromModel(const QList<QModelIndex> &comicsList);
|
||||
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
|
||||
enum Columns {
|
||||
Number = 0,
|
||||
Title = 1,
|
||||
FileName = 2,
|
||||
NumPages = 3,
|
||||
Id = 4,
|
||||
Parent_Id = 5,
|
||||
Path = 6,
|
||||
Hash = 7,
|
||||
ReadColumn = 8,
|
||||
IsBis = 9,
|
||||
CurrentPage = 10,
|
||||
Rating = 11,
|
||||
HasBeenOpened = 12
|
||||
};
|
||||
|
||||
enum Roles {
|
||||
NumberRole = Qt::UserRole + 1,
|
||||
TitleRole,
|
||||
FileNameRole,
|
||||
NumPagesRole,
|
||||
IdRole,
|
||||
Parent_IdRole,
|
||||
PathRole,
|
||||
HashRole,
|
||||
ReadColumnRole,
|
||||
IsBisRole,
|
||||
CurrentPageRole,
|
||||
RatingRole,
|
||||
HasBeenOpenedRole,
|
||||
CoverPathRole
|
||||
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
Folder,
|
||||
Favorites,
|
||||
Reading,
|
||||
Label,
|
||||
ReadingList
|
||||
};
|
||||
|
||||
|
||||
|
||||
public slots:
|
||||
void remove(int row);
|
||||
void startTransaction();
|
||||
void finishTransaction();
|
||||
void updateRating(int rating, QModelIndex mi);
|
||||
|
||||
void addComicsToFavorites(const QList<qulonglong> &comicIds);
|
||||
void addComicsToLabel(const QList<qulonglong> &comicIds, qulonglong labelId);
|
||||
void addComicsToReadingList(const QList<qulonglong> &comicIds, qulonglong readingListId);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
void setupModelData( QSqlQuery &sqlquery);
|
||||
void setupModelDataForList(QSqlQuery &sqlquery);
|
||||
ComicDB _getComic(const QModelIndex & mi);
|
||||
QList<ComicItem *> _data;
|
||||
|
||||
QString _databasePath;
|
||||
|
||||
QSqlDatabase dbTransaction;
|
||||
|
||||
bool enableResorting;
|
||||
Mode mode;
|
||||
qulonglong sourceId;
|
||||
|
||||
signals:
|
||||
void beforeReset();
|
||||
void reset();
|
||||
void isEmpty();
|
||||
void searchNumResults(int);
|
||||
void resortedIndexes(QList<int>);
|
||||
void newSelectedIndex(const QModelIndex &);
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif
|
790
YACReaderLibrary/db/data_base_management.cpp
Normal file
790
YACReaderLibrary/db/data_base_management.cpp
Normal file
@ -0,0 +1,790 @@
|
||||
#include "data_base_management.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include "library_creator.h"
|
||||
#include "check_new_version.h"
|
||||
|
||||
|
||||
static QString fields = "title ,"
|
||||
|
||||
"coverPage,"
|
||||
"numPages,"
|
||||
|
||||
"number,"
|
||||
"isBis,"
|
||||
"count,"
|
||||
|
||||
"volume,"
|
||||
"storyArc,"
|
||||
"arcNumber,"
|
||||
"arcCount,"
|
||||
|
||||
"genere,"
|
||||
|
||||
"writer,"
|
||||
"penciller,"
|
||||
"inker,"
|
||||
"colorist,"
|
||||
"letterer,"
|
||||
"coverArtist,"
|
||||
|
||||
"date,"
|
||||
"publisher,"
|
||||
"format,"
|
||||
"color,"
|
||||
"ageRating,"
|
||||
|
||||
"synopsis,"
|
||||
"characters,"
|
||||
"notes,"
|
||||
|
||||
"comicVineID,"
|
||||
|
||||
"hash"
|
||||
;
|
||||
|
||||
DataBaseManagement::DataBaseManagement()
|
||||
:QObject(),dataBasesList()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*TreeModel * DataBaseManagement::newTreeModel(QString path)
|
||||
{
|
||||
//la consulta se ejecuta...
|
||||
QSqlQuery selectQuery(loadDatabase(path));
|
||||
selectQuery.setForwardOnly(true);
|
||||
selectQuery.exec("select * from folder order by parentId,name");
|
||||
//selectQuery.finish();
|
||||
return new TreeModel(selectQuery);
|
||||
}*/
|
||||
|
||||
QSqlDatabase DataBaseManagement::createDatabase(QString name, QString path)
|
||||
{
|
||||
return createDatabase(QDir::cleanPath(path) + "/" + name + ".ydb");
|
||||
}
|
||||
|
||||
QSqlDatabase DataBaseManagement::createDatabase(QString dest)
|
||||
{
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",dest);
|
||||
db.setDatabaseName(dest);
|
||||
if (!db.open())
|
||||
qDebug() << db.lastError();
|
||||
else {
|
||||
qDebug() << db.tables();
|
||||
}
|
||||
|
||||
{
|
||||
QSqlQuery pragma("PRAGMA foreign_keys = ON",db);
|
||||
//pragma.finish();
|
||||
DataBaseManagement::createTables(db);
|
||||
|
||||
QSqlQuery query("INSERT INTO folder (parentId, name, path) "
|
||||
"VALUES (1,'root', '/')",db);
|
||||
}
|
||||
//query.finish();
|
||||
//db.close();
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
QSqlDatabase DataBaseManagement::loadDatabase(QString path)
|
||||
{
|
||||
//TODO check path
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",path);
|
||||
db.setDatabaseName(path+"/library.ydb");
|
||||
if (!db.open()) {
|
||||
//se devuelve una base de datos vacía e inválida
|
||||
|
||||
return QSqlDatabase();
|
||||
}
|
||||
QSqlQuery pragma("PRAGMA foreign_keys = ON",db);
|
||||
//pragma.finish();
|
||||
//devuelve la base de datos
|
||||
return db;
|
||||
}
|
||||
|
||||
QSqlDatabase DataBaseManagement::loadDatabaseFromFile(QString filePath)
|
||||
{
|
||||
//TODO check path
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE",filePath);
|
||||
db.setDatabaseName(filePath);
|
||||
if (!db.open()) {
|
||||
//se devuelve una base de datos vacía e inválida
|
||||
|
||||
return QSqlDatabase();
|
||||
}
|
||||
{
|
||||
QSqlQuery pragma("PRAGMA foreign_keys = ON",db);
|
||||
}
|
||||
//pragma.finish();
|
||||
//devuelve la base de datos
|
||||
return db;
|
||||
}
|
||||
|
||||
bool DataBaseManagement::createTables(QSqlDatabase & database)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
//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,"
|
||||
|
||||
"coverPage INTEGER DEFAULT 1,"
|
||||
"numPages INTEGER,"
|
||||
|
||||
"number INTEGER,"
|
||||
"isBis BOOLEAN,"
|
||||
"count INTEGER,"
|
||||
|
||||
"volume TEXT,"
|
||||
"storyArc TEXT,"
|
||||
"arcNumber INTEGER,"
|
||||
"arcCount INTEGER,"
|
||||
|
||||
"genere TEXT,"
|
||||
|
||||
"writer TEXT,"
|
||||
"penciller TEXT,"
|
||||
"inker TEXT,"
|
||||
"colorist TEXT,"
|
||||
"letterer TEXT,"
|
||||
"coverArtist TEXT,"
|
||||
|
||||
"date TEXT," //dd/mm/yyyy --> se mostrará en 3 campos diferentes
|
||||
"publisher TEXT,"
|
||||
"format TEXT,"
|
||||
"color BOOLEAN,"
|
||||
"ageRating BOOLEAN,"
|
||||
|
||||
"synopsis TEXT,"
|
||||
"characters TEXT,"
|
||||
"notes TEXT,"
|
||||
|
||||
"hash TEXT UNIQUE NOT NULL,"
|
||||
"edited BOOLEAN DEFAULT 0,"
|
||||
"read BOOLEAN DEFAULT 0,"
|
||||
//new 7.0 fields
|
||||
|
||||
"hasBeenOpened BOOLEAN DEFAULT 0,"
|
||||
"rating INTEGER DEFAULT 0,"
|
||||
"currentPage INTEGER DEFAULT 1, "
|
||||
"bookmark1 INTEGER DEFAULT -1, "
|
||||
"bookmark2 INTEGER DEFAULT -1, "
|
||||
"bookmark3 INTEGER DEFAULT -1, "
|
||||
"brightness INTEGER DEFAULT -1, "
|
||||
"contrast INTEGER DEFAULT -1, "
|
||||
"gamma INTEGER DEFAULT -1, "
|
||||
//new 7.1 fields
|
||||
"comicVineID TEXT"
|
||||
|
||||
")");
|
||||
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();
|
||||
|
||||
QSqlQuery query("INSERT INTO db_info (version) "
|
||||
"VALUES ('" VERSION "')",database);
|
||||
//query.finish();
|
||||
|
||||
//8.0> tables
|
||||
success = success && DataBaseManagement::createV8Tables(database);
|
||||
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool DataBaseManagement::createV8Tables(QSqlDatabase &database)
|
||||
{
|
||||
bool success = true;
|
||||
{
|
||||
//8.0> tables
|
||||
//LABEL
|
||||
QSqlQuery queryLabel(database);
|
||||
success = success && queryLabel.exec("CREATE TABLE label (id INTEGER PRIMARY KEY, "
|
||||
"name TEXT NOT NULL, "
|
||||
"color TEXT NOT NULL, "
|
||||
"ordering INTEGER NOT NULL); "); //order depends on the color
|
||||
|
||||
QSqlQuery queryIndexLabel(database);
|
||||
success = success && queryIndexLabel.exec("CREATE INDEX label_ordering_index ON label (ordering)");
|
||||
|
||||
//COMIC LABEL
|
||||
QSqlQuery queryComicLabel(database);
|
||||
success = success && queryComicLabel.exec("CREATE TABLE comic_label ("
|
||||
"comic_id INTEGER, "
|
||||
"label_id INTEGER, "
|
||||
"ordering INTEGER, " //TODO order????
|
||||
"FOREIGN KEY(label_id) REFERENCES label(id) ON DELETE CASCADE, "
|
||||
"FOREIGN KEY(comic_id) REFERENCES comic(id) ON DELETE CASCADE, "
|
||||
"PRIMARY KEY(label_id, comic_id))");
|
||||
|
||||
QSqlQuery queryIndexComicLabel(database);
|
||||
success = success && queryIndexComicLabel.exec("CREATE INDEX comic_label_ordering_index ON label (ordering)");
|
||||
|
||||
//READING LIST
|
||||
QSqlQuery queryReadingList(database);
|
||||
success = success && queryReadingList.exec("CREATE TABLE reading_list ("
|
||||
"id INTEGER PRIMARY KEY, "
|
||||
"parentId INTEGER, "
|
||||
"ordering INTEGER DEFAULT 0, " //only use it if the parentId is NULL
|
||||
"name TEXT NOT NULL, "
|
||||
"finished BOOLEAN DEFAULT 0, "
|
||||
"completed BOOLEAN DEFAULT 1, "
|
||||
"FOREIGN KEY(parentId) REFERENCES reading_list(id) ON DELETE CASCADE)");
|
||||
|
||||
QSqlQuery queryIndexReadingList(database);
|
||||
success = success && queryIndexReadingList.exec("CREATE INDEX reading_list_ordering_index ON label (ordering)");
|
||||
|
||||
//COMIC READING LIST
|
||||
QSqlQuery queryComicReadingList(database);
|
||||
success = success && queryComicReadingList.exec("CREATE TABLE comic_reading_list ("
|
||||
"reading_list_id INTEGER, "
|
||||
"comic_id INTEGER, "
|
||||
"ordering INTEGER, "
|
||||
"FOREIGN KEY(reading_list_id) REFERENCES reading_list(id) ON DELETE CASCADE, "
|
||||
"FOREIGN KEY(comic_id) REFERENCES comic(id) ON DELETE CASCADE, "
|
||||
"PRIMARY KEY(reading_list_id, comic_id))");
|
||||
|
||||
QSqlQuery queryIndexComicReadingList(database);
|
||||
success = success && queryIndexComicReadingList.exec("CREATE INDEX comic_reading_list_ordering_index ON label (ordering)");
|
||||
|
||||
//DEFAULT READING LISTS
|
||||
QSqlQuery queryDefaultReadingList(database);
|
||||
success = success && queryDefaultReadingList.exec("CREATE TABLE default_reading_list ("
|
||||
"id INTEGER PRIMARY KEY, "
|
||||
"name TEXT NOT NULL"
|
||||
//TODO icon????
|
||||
")");
|
||||
|
||||
//COMIC DEFAULT READING LISTS
|
||||
QSqlQuery queryComicDefaultReadingList(database);
|
||||
success = success && queryComicDefaultReadingList.exec("CREATE TABLE comic_default_reading_list ("
|
||||
"comic_id INTEGER, "
|
||||
"default_reading_list_id INTEGER, "
|
||||
"ordering INTEGER, " //order????
|
||||
"FOREIGN KEY(default_reading_list_id) REFERENCES default_reading_list(id) ON DELETE CASCADE, "
|
||||
"FOREIGN KEY(comic_id) REFERENCES comic(id) ON DELETE CASCADE,"
|
||||
"PRIMARY KEY(default_reading_list_id, comic_id))");
|
||||
|
||||
QSqlQuery queryIndexComicDefaultReadingList(database);
|
||||
success = success && queryIndexComicDefaultReadingList.exec("CREATE INDEX comic_default_reading_list_ordering_index ON label (ordering)");
|
||||
|
||||
//INSERT DEFAULT READING LISTS
|
||||
QSqlQuery queryInsertDefaultReadingList(database);
|
||||
//if(!queryInsertDefaultReadingList.prepare())
|
||||
|
||||
//1 Favorites
|
||||
//queryInsertDefaultReadingList.bindValue(":name", "Favorites");
|
||||
success = success && queryInsertDefaultReadingList.exec("INSERT INTO default_reading_list (name) VALUES (\"Favorites\")");
|
||||
|
||||
//Reading doesn't need its onw list
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void DataBaseManagement::exportComicsInfo(QString source, QString dest)
|
||||
{
|
||||
//QSqlDatabase sourceDB = loadDatabase(source);
|
||||
QSqlDatabase destDB = loadDatabaseFromFile(dest);
|
||||
//sourceDB.open();
|
||||
{
|
||||
QSqlQuery attach(destDB);
|
||||
attach.prepare("ATTACH DATABASE '"+QDir().toNativeSeparators(dest) +"' AS dest;");
|
||||
//attach.bindValue(":dest",QDir().toNativeSeparators(dest));
|
||||
attach.exec();
|
||||
//attach.finish();
|
||||
|
||||
QSqlQuery attach2(destDB);
|
||||
attach2.prepare("ATTACH DATABASE '"+QDir().toNativeSeparators(source) +"' AS source;");
|
||||
attach2.exec();
|
||||
//attach2.finish();
|
||||
|
||||
//sourceDB.close();
|
||||
QSqlQuery queryDBInfo(destDB);
|
||||
queryDBInfo.prepare("CREATE TABLE dest.db_info (version TEXT NOT NULL)");
|
||||
queryDBInfo.exec();
|
||||
//queryDBInfo.finish();
|
||||
|
||||
/*QSqlQuery queryComicsInfo(sourceDB);
|
||||
queryComicsInfo.prepare("CREATE TABLE dest.comic_info (id INTEGER PRIMARY KEY, hash TEXT NOT NULL, edited BOOLEAN DEFAULT FALSE, title TEXT, read BOOLEAN)");
|
||||
queryComicsInfo.exec();*/
|
||||
|
||||
QSqlQuery query("INSERT INTO dest.db_info (version) "
|
||||
"VALUES ('" VERSION "')",destDB);
|
||||
//query.finish();
|
||||
|
||||
QSqlQuery exportData(destDB);
|
||||
exportData.prepare("create table dest.comic_info as select " + fields +
|
||||
" from source.comic_info where source.comic_info.edited = 1");
|
||||
exportData.exec();
|
||||
//exportData.finish();
|
||||
}
|
||||
|
||||
//sourceDB.close();
|
||||
destDB.close();
|
||||
QSqlDatabase::removeDatabase(dest);
|
||||
|
||||
}
|
||||
|
||||
bool DataBaseManagement::importComicsInfo(QString source, QString dest)
|
||||
{
|
||||
QString error;
|
||||
QString driver;
|
||||
QStringList hashes;
|
||||
|
||||
bool b = false;
|
||||
|
||||
QSqlDatabase sourceDB = loadDatabaseFromFile(source);
|
||||
QSqlDatabase destDB = loadDatabaseFromFile(dest);
|
||||
|
||||
{
|
||||
QSqlQuery pragma("PRAGMA synchronous=OFF",destDB);
|
||||
|
||||
|
||||
QSqlQuery newInfo(sourceDB);
|
||||
newInfo.prepare("SELECT * FROM comic_info");
|
||||
newInfo.exec();
|
||||
destDB.transaction();
|
||||
int cp;
|
||||
while (newInfo.next()) //cada tupla deberá ser insertada o actualizada
|
||||
{
|
||||
QSqlQuery update(destDB);
|
||||
update.prepare("UPDATE comic_info SET "
|
||||
"title = :title,"
|
||||
|
||||
"coverPage = :coverPage,"
|
||||
"numPages = :numPages,"
|
||||
|
||||
"number = :number,"
|
||||
"isBis = :isBis,"
|
||||
"count = :count,"
|
||||
|
||||
"volume = :volume,"
|
||||
"storyArc = :storyArc,"
|
||||
"arcNumber = :arcNumber,"
|
||||
"arcCount = :arcCount,"
|
||||
|
||||
"genere = :genere,"
|
||||
|
||||
"writer = :writer,"
|
||||
"penciller = :penciller,"
|
||||
"inker = :inker,"
|
||||
"colorist = :colorist,"
|
||||
"letterer = :letterer,"
|
||||
"coverArtist = :coverArtist,"
|
||||
|
||||
"date = :date,"
|
||||
"publisher = :publisher,"
|
||||
"format = :format,"
|
||||
"color = :color,"
|
||||
"ageRating = :ageRating,"
|
||||
|
||||
"synopsis = :synopsis,"
|
||||
"characters = :characters,"
|
||||
"notes = :notes,"
|
||||
|
||||
"edited = :edited,"
|
||||
|
||||
"comicVineID = :comicVineID"
|
||||
|
||||
" WHERE hash = :hash ");
|
||||
|
||||
QSqlQuery insert(destDB);
|
||||
insert.prepare("INSERT INTO comic_info "
|
||||
"(title,"
|
||||
"coverPage,"
|
||||
"numPages,"
|
||||
"number,"
|
||||
"isBis,"
|
||||
"count,"
|
||||
"volume,"
|
||||
"storyArc,"
|
||||
"arcNumber,"
|
||||
"arcCount,"
|
||||
"genere,"
|
||||
"writer,"
|
||||
"penciller,"
|
||||
"inker,"
|
||||
"colorist,"
|
||||
"letterer,"
|
||||
"coverArtist,"
|
||||
"date,"
|
||||
"publisher,"
|
||||
"format,"
|
||||
"color,"
|
||||
"ageRating,"
|
||||
"synopsis,"
|
||||
"characters,"
|
||||
"notes,"
|
||||
"read,"
|
||||
"edited,"
|
||||
"comicVineID,"
|
||||
"hash)"
|
||||
|
||||
"VALUES (:title,"
|
||||
":coverPage,"
|
||||
":numPages,"
|
||||
":number,"
|
||||
":isBis,"
|
||||
":count,"
|
||||
|
||||
":volume,"
|
||||
":storyArc,"
|
||||
":arcNumber,"
|
||||
":arcCount,"
|
||||
|
||||
":genere,"
|
||||
|
||||
":writer,"
|
||||
":penciller,"
|
||||
":inker,"
|
||||
":colorist,"
|
||||
":letterer,"
|
||||
":coverArtist,"
|
||||
|
||||
":date,"
|
||||
":publisher,"
|
||||
":format,"
|
||||
":color,"
|
||||
":ageRating,"
|
||||
|
||||
":synopsis,"
|
||||
":characters,"
|
||||
":notes,"
|
||||
|
||||
":read,"
|
||||
":edited,"
|
||||
":comicVineID,"
|
||||
|
||||
":hash )");
|
||||
|
||||
QSqlRecord record = newInfo.record();
|
||||
cp = record.value("coverPage").toInt();
|
||||
if(cp>1)
|
||||
{
|
||||
QSqlQuery checkCoverPage(destDB);
|
||||
checkCoverPage.prepare("SELECT coverPage FROM comic_info where hash = :hash");
|
||||
checkCoverPage.bindValue(":hash",record.value("hash").toString());
|
||||
checkCoverPage.exec();
|
||||
bool extract = false;
|
||||
if(checkCoverPage.next())
|
||||
{
|
||||
extract = checkCoverPage.record().value("coverPage").toInt() != cp;
|
||||
}
|
||||
if(extract)
|
||||
hashes.append(record.value("hash").toString());
|
||||
}
|
||||
|
||||
bindValuesFromRecord(record,update);
|
||||
|
||||
update.bindValue(":edited",1);
|
||||
|
||||
|
||||
update.exec();
|
||||
|
||||
if(update.numRowsAffected() == 0)
|
||||
{
|
||||
|
||||
bindValuesFromRecord(record,insert);
|
||||
insert.bindValue(":edited",1);
|
||||
insert.bindValue(":read",0);
|
||||
|
||||
insert.exec();
|
||||
|
||||
QString error1 = insert.lastError().databaseText();
|
||||
QString error2 = insert.lastError().driverText();
|
||||
|
||||
//QMessageBox::critical(NULL,"db",error1);
|
||||
//QMessageBox::critical(NULL,"driver",error2);
|
||||
}
|
||||
//update.finish();
|
||||
//insert.finish();
|
||||
}
|
||||
}
|
||||
|
||||
destDB.commit();
|
||||
QString hash;
|
||||
foreach(hash, hashes)
|
||||
{
|
||||
QSqlQuery getComic(destDB);
|
||||
getComic.prepare("SELECT c.path,ci.coverPage FROM comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id) where ci.hash = :hash");
|
||||
getComic.bindValue(":hash",hash);
|
||||
getComic.exec();
|
||||
if(getComic.next())
|
||||
{
|
||||
QString basePath = QString(dest).remove("/.yacreaderlibrary/library.ydb");
|
||||
QString path = basePath + getComic.record().value("path").toString();
|
||||
int coverPage = getComic.record().value("coverPage").toInt();
|
||||
ThumbnailCreator tc(path,basePath+"/.yacreaderlibrary/covers/"+hash+".jpg",coverPage);
|
||||
tc.create();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
destDB.close();
|
||||
sourceDB.close();
|
||||
QSqlDatabase::removeDatabase(source);
|
||||
QSqlDatabase::removeDatabase(dest);
|
||||
return b;
|
||||
|
||||
}
|
||||
//TODO fix these bindings
|
||||
void DataBaseManagement::bindValuesFromRecord(const QSqlRecord & record, QSqlQuery & query)
|
||||
{
|
||||
bindString("title",record,query);
|
||||
|
||||
bindInt("coverPage",record,query);
|
||||
bindInt("numPages",record,query);
|
||||
|
||||
bindInt("number",record,query);
|
||||
bindInt("isBis",record,query);
|
||||
bindInt("count",record,query);
|
||||
|
||||
bindString("volume",record,query);
|
||||
bindString("storyArc",record,query);
|
||||
bindInt("arcNumber",record,query);
|
||||
bindInt("arcCount",record,query);
|
||||
|
||||
bindString("genere",record,query);
|
||||
|
||||
bindString("writer",record,query);
|
||||
bindString("penciller",record,query);
|
||||
bindString("inker",record,query);
|
||||
bindString("colorist",record,query);
|
||||
bindString("letterer",record,query);
|
||||
bindString("coverArtist",record,query);
|
||||
|
||||
bindString("date",record,query);
|
||||
bindString("publisher",record,query);
|
||||
bindString("format",record,query);
|
||||
bindInt("color",record,query);
|
||||
bindString("ageRating",record,query);
|
||||
|
||||
bindString("synopsis",record,query);
|
||||
bindString("characters",record,query);
|
||||
bindString("notes",record,query);
|
||||
|
||||
bindString("comicVineID",record,query);
|
||||
|
||||
bindString("hash",record,query);
|
||||
}
|
||||
|
||||
bool DataBaseManagement::addColumns(const QString &tableName, const QStringList &columnDefs, const QSqlDatabase &db)
|
||||
{
|
||||
QString sql = "ALTER TABLE %1 ADD COLUMN %2";
|
||||
bool returnValue = true;
|
||||
|
||||
foreach(QString columnDef, columnDefs)
|
||||
{
|
||||
QSqlQuery alterTable(db);
|
||||
alterTable.prepare(sql.arg(tableName).arg(columnDef));
|
||||
//alterTableComicInfo.bindValue(":column_def",columnDef);
|
||||
alterTable.exec();
|
||||
returnValue = returnValue && (alterTable.numRowsAffected() > 0);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void DataBaseManagement::bindString(const QString & name, const QSqlRecord & record, QSqlQuery & query)
|
||||
{
|
||||
if(!record.value(name).isNull())
|
||||
{
|
||||
query.bindValue(":"+name,record.value(name).toString());
|
||||
}
|
||||
}
|
||||
void DataBaseManagement::bindInt(const QString & name, const QSqlRecord & record, QSqlQuery & query)
|
||||
{
|
||||
if(!record.value(name).isNull())
|
||||
{
|
||||
query.bindValue(":"+name,record.value(name).toInt());
|
||||
}
|
||||
}
|
||||
|
||||
QString DataBaseManagement::checkValidDB(const QString & fullPath)
|
||||
{
|
||||
QSqlDatabase db = loadDatabaseFromFile(fullPath);
|
||||
QString versionString = "";
|
||||
if(db.isValid() && db.isOpen())
|
||||
{
|
||||
QSqlQuery version(db);
|
||||
version.prepare("SELECT * FROM db_info");
|
||||
version.exec();
|
||||
|
||||
if(version.next())
|
||||
versionString = version.record().value("version").toString();
|
||||
}
|
||||
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(fullPath);
|
||||
return versionString;
|
||||
}
|
||||
|
||||
int DataBaseManagement::compareVersions(const QString & v1, const QString v2)
|
||||
{
|
||||
QStringList v1l = v1.split('.');
|
||||
QStringList v2l = v2.split('.');
|
||||
QList<int> v1il;
|
||||
QList<int> v2il;
|
||||
|
||||
foreach(QString s, v1l)
|
||||
v1il.append(s.toInt());
|
||||
|
||||
foreach(QString s,v2l)
|
||||
v2il.append(s.toInt());
|
||||
|
||||
for(int i=0;i<qMin(v1il.length(),v2il.length());i++)
|
||||
{
|
||||
if(v1il[i]<v2il[i])
|
||||
return -1;
|
||||
if(v1il[i]>v2il[i])
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(v1il.length() < v2il.length())
|
||||
return -1;
|
||||
if(v1il.length() == v2il.length())
|
||||
return 0;
|
||||
if(v1il.length() > v2il.length())
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool DataBaseManagement::updateToCurrentVersion(const QString & fullPath)
|
||||
{
|
||||
bool pre7 = false;
|
||||
bool pre7_1 = false;
|
||||
bool pre8 = false;
|
||||
|
||||
if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"7.0.0")<0)
|
||||
pre7 = true;
|
||||
if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"7.0.3")<0)
|
||||
pre7_1 = true;
|
||||
if(compareVersions(DataBaseManagement::checkValidDB(fullPath),"8.0.0")<0)
|
||||
pre8 = true;
|
||||
|
||||
QSqlDatabase db = loadDatabaseFromFile(fullPath);
|
||||
bool returnValue = false;
|
||||
if(db.isValid() && db.isOpen())
|
||||
{
|
||||
QSqlQuery updateVersion(db);
|
||||
updateVersion.prepare("UPDATE db_info SET "
|
||||
"version = :version");
|
||||
updateVersion.bindValue(":version",VERSION);
|
||||
updateVersion.exec();
|
||||
|
||||
if(updateVersion.numRowsAffected() > 0)
|
||||
returnValue = true;
|
||||
|
||||
if(pre7) //TODO: execute only if previous version was < 7.0
|
||||
{
|
||||
//new 7.0 fields
|
||||
QStringList columnDefs;
|
||||
columnDefs << "hasBeenOpened BOOLEAN DEFAULT 0"
|
||||
<< "rating INTEGER DEFAULT 0"
|
||||
<< "currentPage INTEGER DEFAULT 1"
|
||||
<< "bookmark1 INTEGER DEFAULT -1"
|
||||
<< "bookmark2 INTEGER DEFAULT -1"
|
||||
<< "bookmark3 INTEGER DEFAULT -1"
|
||||
<< "brightness INTEGER DEFAULT -1"
|
||||
<< "contrast INTEGER DEFAULT -1"
|
||||
<< "gamma INTEGER DEFAULT -1";
|
||||
|
||||
returnValue = returnValue && addColumns("comic_info", columnDefs, db);
|
||||
}
|
||||
//TODO update hasBeenOpened value
|
||||
|
||||
if(pre7_1)
|
||||
{
|
||||
{
|
||||
QStringList columnDefs;
|
||||
columnDefs << "finished BOOLEAN DEFAULT 0"
|
||||
<< "completed BOOLEAN DEFAULT 1";
|
||||
returnValue = returnValue && addColumns("folder", columnDefs, db);
|
||||
}
|
||||
|
||||
{//comic_info
|
||||
QStringList columnDefs;
|
||||
columnDefs << "comicVineID TEXT DEFAULT NULL";
|
||||
returnValue = returnValue && addColumns("comic_info", columnDefs, db);
|
||||
}
|
||||
}
|
||||
|
||||
if(pre8)
|
||||
{
|
||||
returnValue = returnValue && createV8Tables(db);
|
||||
}
|
||||
}
|
||||
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(fullPath);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
//COMICS_INFO_EXPORTER
|
||||
ComicsInfoExporter::ComicsInfoExporter()
|
||||
:QThread()
|
||||
{
|
||||
}
|
||||
|
||||
void ComicsInfoExporter::exportComicsInfo(QSqlDatabase & source, QSqlDatabase & dest)
|
||||
{
|
||||
Q_UNUSED(source)
|
||||
Q_UNUSED(dest)
|
||||
//TODO check this method
|
||||
}
|
||||
|
||||
void ComicsInfoExporter::run()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//COMICS_INFO_IMPORTER
|
||||
ComicsInfoImporter::ComicsInfoImporter()
|
||||
:QThread()
|
||||
{
|
||||
}
|
||||
|
||||
void ComicsInfoImporter::importComicsInfo(QSqlDatabase & source, QSqlDatabase & dest)
|
||||
{
|
||||
Q_UNUSED(source)
|
||||
Q_UNUSED(dest)
|
||||
//TODO check this method
|
||||
}
|
||||
|
||||
void ComicsInfoImporter::run()
|
||||
{
|
||||
|
||||
}
|
62
YACReaderLibrary/db/data_base_management.h
Normal file
62
YACReaderLibrary/db/data_base_management.h
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef __DATA_BASE_MANAGEMENT_H
|
||||
#define __DATA_BASE_MANAGEMENT_H
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtSql>
|
||||
#include <QSqlDatabase>
|
||||
|
||||
#include "folder_model.h"
|
||||
|
||||
class ComicsInfoExporter : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComicsInfoExporter();
|
||||
void exportComicsInfo(QSqlDatabase & source, QSqlDatabase & dest);
|
||||
private:
|
||||
void run();
|
||||
};
|
||||
|
||||
class ComicsInfoImporter : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComicsInfoImporter();
|
||||
void importComicsInfo(QSqlDatabase & source, QSqlDatabase & dest);
|
||||
private:
|
||||
void run();
|
||||
|
||||
};
|
||||
|
||||
class DataBaseManagement : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
QList<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 bindValuesFromRecord(const QSqlRecord & record, QSqlQuery & query);
|
||||
|
||||
static bool addColumns(const QString & tableName, const QStringList & columnDefs, const QSqlDatabase & db);
|
||||
|
||||
public:
|
||||
DataBaseManagement();
|
||||
//TreeModel * newTreeModel(QString path);
|
||||
//crea una base de datos y todas sus tablas
|
||||
static QSqlDatabase createDatabase(QString name, QString path);
|
||||
static QSqlDatabase createDatabase(QString dest);
|
||||
//carga una base de datos desde la ruta path
|
||||
static QSqlDatabase loadDatabase(QString path);
|
||||
static QSqlDatabase loadDatabaseFromFile(QString path);
|
||||
static bool createTables(QSqlDatabase & database);
|
||||
static bool createV8Tables(QSqlDatabase & database);
|
||||
|
||||
static void exportComicsInfo(QString source, QString dest);
|
||||
static bool importComicsInfo(QString source, QString dest);
|
||||
|
||||
static QString checkValidDB(const QString & fullPath); //retorna "" si la DB es inválida ó la versión si es válida.
|
||||
static int compareVersions(const QString & v1, const QString v2); //retorna <0 si v1 < v2, 0 si v1 = v2 y >0 si v1 > v2
|
||||
static bool updateToCurrentVersion(const QString & path);
|
||||
};
|
||||
|
||||
#endif
|
103
YACReaderLibrary/db/folder_item.cpp
Normal file
103
YACReaderLibrary/db/folder_item.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
#include <QStringList>
|
||||
|
||||
#include "folder_item.h"
|
||||
#include "qnaturalsorting.h"
|
||||
|
||||
FolderItem::FolderItem(const QList<QVariant> &data, FolderItem *parent)
|
||||
{
|
||||
parentItem = parent;
|
||||
itemData = data;
|
||||
}
|
||||
|
||||
FolderItem::~FolderItem()
|
||||
{
|
||||
qDeleteAll(childItems);
|
||||
}
|
||||
|
||||
void FolderItem::appendChild(FolderItem *item)
|
||||
{
|
||||
item->parentItem = this;
|
||||
|
||||
if(childItems.isEmpty())
|
||||
childItems.append(item);
|
||||
else
|
||||
{
|
||||
FolderItem * last = childItems.back();
|
||||
QString nameLast = last->data(1).toString(); //TODO usar info name si est<73> disponible, sino el nombre del fichero.....
|
||||
QString nameCurrent = item->data(1).toString();
|
||||
QList<FolderItem *>::iterator i;
|
||||
i = childItems.end();
|
||||
i--;
|
||||
while (naturalSortLessThanCI(nameCurrent,nameLast) && i != childItems.begin())
|
||||
{
|
||||
i--;
|
||||
nameLast = (*i)->data(1).toString();
|
||||
}
|
||||
if(!naturalSortLessThanCI(nameCurrent,nameLast)) //si se ha encontrado un elemento menor que current, se inserta justo despu<70>s
|
||||
childItems.insert(++i,item);
|
||||
else
|
||||
childItems.insert(i,item);
|
||||
|
||||
}
|
||||
|
||||
//childItems.append(item);
|
||||
}
|
||||
|
||||
FolderItem *FolderItem::child(int row)
|
||||
{
|
||||
return childItems.value(row);
|
||||
}
|
||||
|
||||
int FolderItem::childCount() const
|
||||
{
|
||||
return childItems.count();
|
||||
}
|
||||
|
||||
int FolderItem::columnCount() const
|
||||
{
|
||||
return itemData.count();
|
||||
}
|
||||
|
||||
QVariant FolderItem::data(int column) const
|
||||
{
|
||||
return itemData.value(column);
|
||||
}
|
||||
|
||||
void FolderItem::setData(int column, const QVariant & value)
|
||||
{
|
||||
itemData[column] = value;
|
||||
}
|
||||
|
||||
void FolderItem::removeChild(int childIndex)
|
||||
{
|
||||
childItems.removeAt(childIndex);
|
||||
}
|
||||
|
||||
void FolderItem::clearChildren()
|
||||
{
|
||||
qDeleteAll(childItems);
|
||||
childItems.clear();
|
||||
}
|
||||
|
||||
QList<FolderItem *> FolderItem::children()
|
||||
{
|
||||
return childItems;
|
||||
}
|
||||
|
||||
FolderItem *FolderItem::parent()
|
||||
{
|
||||
return parentItem;
|
||||
}
|
||||
|
||||
int FolderItem::row() const
|
||||
{
|
||||
if (parentItem)
|
||||
return parentItem->childItems.indexOf(const_cast<FolderItem*>(this));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QList<QVariant> FolderItem::getData() const
|
||||
{
|
||||
return itemData;
|
||||
}
|
77
YACReaderLibrary/db/folder_item.h
Normal file
77
YACReaderLibrary/db/folder_item.h
Normal file
@ -0,0 +1,77 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef TREEITEM_H
|
||||
#define TREEITEM_H
|
||||
|
||||
#include <QList>
|
||||
#include <QVariant>
|
||||
#include <QModelIndex>
|
||||
|
||||
class FolderItem
|
||||
{
|
||||
public:
|
||||
FolderItem(const QList<QVariant> &data, FolderItem *parent = 0);
|
||||
~FolderItem();
|
||||
|
||||
void appendChild(FolderItem *child);
|
||||
|
||||
FolderItem *child(int row);
|
||||
int childCount() const;
|
||||
int columnCount() const;
|
||||
QVariant data(int column) const;
|
||||
QList<QVariant> getData() const;
|
||||
int row() const;
|
||||
FolderItem *parent();
|
||||
FolderItem *parentItem;
|
||||
unsigned long long int id;
|
||||
QList<QString> comicNames;
|
||||
FolderItem * originalItem;
|
||||
void setData(int column, const QVariant &value);
|
||||
void removeChild(int childIndex);
|
||||
void clearChildren();
|
||||
QList<FolderItem*> children();
|
||||
private:
|
||||
QList<FolderItem*> childItems;
|
||||
QList<QVariant> itemData;
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif
|
784
YACReaderLibrary/db/folder_model.cpp
Normal file
784
YACReaderLibrary/db/folder_model.cpp
Normal file
@ -0,0 +1,784 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
treemodel.cpp
|
||||
|
||||
Provides a simple tree model to show how to create and use hierarchical
|
||||
models.
|
||||
*/
|
||||
|
||||
#include <QtGui>
|
||||
|
||||
|
||||
#include "folder_item.h"
|
||||
#include "folder_model.h"
|
||||
#include "data_base_management.h"
|
||||
#include "folder.h"
|
||||
#include "db_helper.h"
|
||||
#include "qnaturalsorting.h"
|
||||
#include "yacreader_global_gui.h"
|
||||
#include "QsLog.h"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include <QFileIconProvider>
|
||||
QIcon finishedFolderIcon;
|
||||
void drawMacOSXFinishedFolderIcon()
|
||||
{
|
||||
QIcon ico = QFileIconProvider().icon(QFileIconProvider::Folder);
|
||||
QPixmap pixNormalOff = ico.pixmap(16,16, QIcon::Normal, QIcon::Off);
|
||||
QPixmap pixNormalOn = ico.pixmap(16,16, QIcon::Normal, QIcon::On);
|
||||
QPixmap pixSelectedOff = ico.pixmap(16,16, QIcon::Selected, QIcon::Off);
|
||||
QPixmap pixSelectedOn = ico.pixmap(16,16, QIcon::Selected, QIcon::On);
|
||||
QPixmap tick(":/images/folder_finished_macosx.png");
|
||||
|
||||
|
||||
{
|
||||
QPainter p(&pixNormalOff);
|
||||
p.drawPixmap(4,7,tick);
|
||||
}
|
||||
finishedFolderIcon.addPixmap(pixNormalOff, QIcon::Normal, QIcon::Off);
|
||||
|
||||
{
|
||||
QPainter p(&pixNormalOn);
|
||||
p.drawPixmap(4,7,tick);
|
||||
}
|
||||
finishedFolderIcon.addPixmap(pixNormalOn, QIcon::Normal, QIcon::On);
|
||||
|
||||
{
|
||||
QPainter p(&pixSelectedOff);
|
||||
p.drawPixmap(4,7,tick);
|
||||
}
|
||||
finishedFolderIcon.addPixmap(pixSelectedOff, QIcon::Selected, QIcon::Off);
|
||||
|
||||
{
|
||||
QPainter p(&pixSelectedOn);
|
||||
p.drawPixmap(4,7,tick);
|
||||
}
|
||||
finishedFolderIcon.addPixmap(pixSelectedOn, QIcon::Selected, QIcon::On);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ROOT 1
|
||||
|
||||
FolderModel::FolderModel(QObject *parent)
|
||||
: QAbstractItemModel(parent),rootItem(0)
|
||||
{
|
||||
connect(this,SIGNAL(beforeReset()),this,SIGNAL(modelAboutToBeReset()));
|
||||
connect(this,SIGNAL(reset()),this,SIGNAL(modelReset()));
|
||||
}
|
||||
|
||||
//! [0]
|
||||
FolderModel::FolderModel( QSqlQuery &sqlquery, QObject *parent)
|
||||
: QAbstractItemModel(parent),rootItem(0)
|
||||
{
|
||||
//lo m<>s probable es que el nodo ra<72>z no necesite tener informaci<63>n
|
||||
QList<QVariant> rootData;
|
||||
rootData << "root"; //id 0, padre 0, title "root" (el id, y el id del padre van a ir en la clase TreeItem)
|
||||
rootItem = new FolderItem(rootData);
|
||||
rootItem->id = ROOT;
|
||||
rootItem->parentItem = 0;
|
||||
setupModelData(sqlquery, rootItem);
|
||||
//sqlquery.finish();
|
||||
}
|
||||
//! [0]
|
||||
|
||||
//! [1]
|
||||
FolderModel::~FolderModel()
|
||||
{
|
||||
if(rootItem != 0)
|
||||
delete rootItem;
|
||||
}
|
||||
//! [1]
|
||||
|
||||
//! [2]
|
||||
int FolderModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return static_cast<FolderItem*>(parent.internalPointer())->columnCount();
|
||||
else
|
||||
return rootItem->columnCount();
|
||||
}
|
||||
//! [2]
|
||||
|
||||
//! [3]
|
||||
QVariant FolderModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
FolderItem *item = static_cast<FolderItem*>(index.internalPointer());
|
||||
|
||||
if (role == Qt::DecorationRole)
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
if(item->data(FolderModel::Finished).toBool()){
|
||||
if(finishedFolderIcon.isNull()){
|
||||
drawMacOSXFinishedFolderIcon();
|
||||
}
|
||||
|
||||
return QVariant(finishedFolderIcon);
|
||||
}
|
||||
else {
|
||||
return QVariant(QFileIconProvider().icon(QFileIconProvider::Folder));
|
||||
}
|
||||
#else
|
||||
if(item->data(FolderModel::Finished).toBool())
|
||||
return QVariant(YACReader::noHighlightedIcon(":/images/sidebar/folder_finished.png"));
|
||||
else
|
||||
return QVariant(YACReader::noHighlightedIcon(":/images/sidebar/folder.png"));
|
||||
#endif
|
||||
|
||||
if(role == FolderModel::CompletedRole)
|
||||
return item->data(FolderModel::Completed);
|
||||
|
||||
if(role == FolderModel::FinishedRole)
|
||||
return item->data(FolderModel::Finished);
|
||||
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
|
||||
|
||||
return item->data(index.column());
|
||||
}
|
||||
//! [3]
|
||||
|
||||
//! [4]
|
||||
Qt::ItemFlags FolderModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled;
|
||||
}
|
||||
//! [4]
|
||||
|
||||
//! [5]
|
||||
QVariant FolderModel::headerData(int section, Qt::Orientation orientation,
|
||||
int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return rootItem->data(section);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
//! [5]
|
||||
|
||||
//! [6]
|
||||
QModelIndex FolderModel::index(int row, int column, const QModelIndex &parent)
|
||||
const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
FolderItem *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<FolderItem*>(parent.internalPointer());
|
||||
|
||||
FolderItem *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
//! [6]
|
||||
|
||||
//! [7]
|
||||
QModelIndex FolderModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
FolderItem *childItem = static_cast<FolderItem*>(index.internalPointer());
|
||||
FolderItem *parentItem = childItem->parent();
|
||||
|
||||
if (parentItem == rootItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
//! [7]
|
||||
|
||||
/*
|
||||
QModelIndex FolderModel::indexFromItem(FolderItem * item,int column)
|
||||
{
|
||||
//if(item->parent() != 0)
|
||||
// return index(item->row(),column,parent(indexFromItem(item->parent(),column-1)));
|
||||
//else
|
||||
// return index(item->row(),0,QModelIndex());
|
||||
return createIndex(item->row(), column, item);
|
||||
}*/
|
||||
|
||||
|
||||
//! [8]
|
||||
int FolderModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
FolderItem *parentItem;
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem;
|
||||
else
|
||||
parentItem = static_cast<FolderItem*>(parent.internalPointer());
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
//! [8]
|
||||
|
||||
void FolderModel::setupModelData(QString path)
|
||||
{
|
||||
beginResetModel();
|
||||
if(rootItem != 0)
|
||||
delete rootItem; //TODO comprobar que se libera bien la memoria
|
||||
|
||||
rootItem = 0;
|
||||
|
||||
//inicializar el nodo ra<72>z
|
||||
QList<QVariant> rootData;
|
||||
rootData << "root"; //id 0, padre 0, title "root" (el id, y el id del padre van a ir en la clase TreeItem)
|
||||
rootItem = new FolderItem(rootData);
|
||||
rootItem->id = ROOT;
|
||||
rootItem->parentItem = 0;
|
||||
|
||||
//cargar la base de datos
|
||||
_databasePath = path;
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(path);
|
||||
//crear la consulta
|
||||
{
|
||||
QSqlQuery selectQuery("select * from folder where id <> 1 order by parentId,name",db);
|
||||
|
||||
setupModelData(selectQuery,rootItem);
|
||||
}
|
||||
//selectQuery.finish();
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(path);
|
||||
endResetModel();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FolderModel::setupModelData(QSqlQuery &sqlquery, FolderItem *parent)
|
||||
{
|
||||
//64 bits para la primary key, es decir la misma precisi<73>n que soporta sqlit 2^64
|
||||
//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);
|
||||
|
||||
while (sqlquery.next()) {
|
||||
QList<QVariant> data;
|
||||
QSqlRecord record = sqlquery.record();
|
||||
|
||||
data << record.value("name").toString();
|
||||
data << record.value("path").toString();
|
||||
data << record.value("finished").toBool();
|
||||
data << record.value("completed").toBool();
|
||||
FolderItem * item = new FolderItem(data);
|
||||
|
||||
item->id = record.value("id").toULongLong();
|
||||
//la inserci<63>n de hijos se hace de forma ordenada
|
||||
FolderItem * parent = items.value(record.value("parentId").toULongLong());
|
||||
//if(parent !=0) //TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR.
|
||||
parent->appendChild(item);
|
||||
//se a<>ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones
|
||||
items.insert(item->id,item);
|
||||
}
|
||||
}
|
||||
|
||||
void FolderModel::updateFolderModelData(QSqlQuery &sqlquery, FolderItem *parent)
|
||||
{
|
||||
while (sqlquery.next()) {
|
||||
QLOG_DEBUG () << "habia next";
|
||||
QList<QVariant> data;
|
||||
QSqlRecord record = sqlquery.record();
|
||||
|
||||
data << record.value("name").toString();
|
||||
data << record.value("path").toString();
|
||||
data << record.value("finished").toBool();
|
||||
data << record.value("completed").toBool();
|
||||
FolderItem * item = new FolderItem(data);
|
||||
|
||||
item->id = record.value("id").toULongLong();
|
||||
//la inserci<63>n de hijos se hace de forma ordenada
|
||||
FolderItem * parent = items.value(record.value("parentId").toULongLong());
|
||||
if(parent !=0) //TODO if parent==0 the parent of item was removed from the DB and delete on cascade didn't work, ERROR.
|
||||
parent->appendChild(item);
|
||||
//se a<>ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones
|
||||
items.insert(item->id,item);
|
||||
}
|
||||
}
|
||||
|
||||
QString FolderModel::getDatabase()
|
||||
{
|
||||
return _databasePath;
|
||||
}
|
||||
|
||||
QString FolderModel::getFolderPath(const QModelIndex &folder)
|
||||
{
|
||||
if(!folder.isValid()) //root folder
|
||||
return "/";
|
||||
return static_cast<FolderItem*>(folder.internalPointer())->data(FolderModel::Path).toString();
|
||||
}
|
||||
|
||||
/*
|
||||
void FolderModel::resetFilter()
|
||||
{
|
||||
beginResetModel();
|
||||
filter = "";
|
||||
includeComics = false;
|
||||
//TODO hay que liberar la memoria reservada para el filtrado
|
||||
//items.clear();
|
||||
filteredItems.clear();
|
||||
FolderItem * root = rootItem;
|
||||
rootItem = rootBeforeFilter; //TODO si no se aplica el filtro previamente, esto invalidar<61>a en modelo
|
||||
if(root !=0)
|
||||
delete root;
|
||||
|
||||
rootBeforeFilter = 0;
|
||||
filterEnabled = false;
|
||||
endResetModel();
|
||||
|
||||
|
||||
}*/
|
||||
|
||||
void FolderModel::updateFolderCompletedStatus(const QModelIndexList &list, bool status)
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
db.transaction();
|
||||
foreach (QModelIndex mi, list)
|
||||
{
|
||||
FolderItem * item = static_cast<FolderItem*>(mi.internalPointer());
|
||||
item->setData(FolderModel::Completed,status);
|
||||
|
||||
Folder f = DBHelper::loadFolder(item->id,db);
|
||||
f.setCompleted(status);
|
||||
DBHelper::update(f,db);
|
||||
}
|
||||
db.commit();
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
|
||||
emit dataChanged(index(list.first().row(),FolderModel::Name),index(list.last().row(),FolderModel::Completed));
|
||||
}
|
||||
|
||||
void FolderModel::updateFolderFinishedStatus(const QModelIndexList &list, bool status)
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
db.transaction();
|
||||
foreach (QModelIndex mi, list)
|
||||
{
|
||||
FolderItem * item = static_cast<FolderItem*>(mi.internalPointer());
|
||||
item->setData(FolderModel::Finished,status);
|
||||
|
||||
Folder f = DBHelper::loadFolder(item->id,db);
|
||||
f.setFinished(status);
|
||||
DBHelper::update(f,db);
|
||||
}
|
||||
db.commit();
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
|
||||
emit dataChanged(index(list.first().row(),FolderModel::Name),index(list.last().row(),FolderModel::Completed));
|
||||
}
|
||||
|
||||
QStringList FolderModel::getSubfoldersNames(const QModelIndex &mi)
|
||||
{
|
||||
QStringList result;
|
||||
qulonglong id = 1;
|
||||
if(mi.isValid()){
|
||||
FolderItem * item = static_cast<FolderItem*>(mi.internalPointer());
|
||||
id = item->id;
|
||||
}
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
db.transaction();
|
||||
|
||||
result = DBHelper::loadSubfoldersNames(id,db);
|
||||
|
||||
db.commit();
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
|
||||
//TODO sort result))
|
||||
qSort(result.begin(),result.end(),naturalSortLessThanCI);
|
||||
return result;
|
||||
}
|
||||
|
||||
void FolderModel::fetchMoreFromDB(const QModelIndex &parent)
|
||||
{
|
||||
FolderItem * item;
|
||||
if(parent.isValid())
|
||||
item = static_cast<FolderItem*>(parent.internalPointer());
|
||||
else
|
||||
item = rootItem;
|
||||
|
||||
//Remove all children
|
||||
if(item->childCount() > 0)
|
||||
{
|
||||
beginRemoveRows(parent, 0, item->childCount()-1);
|
||||
item->clearChildren();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
|
||||
QList<FolderItem *> items;
|
||||
QList<FolderItem *> nextLevelItems;
|
||||
|
||||
QSqlQuery selectQuery(db);
|
||||
selectQuery.prepare("select * from folder where id <> 1 and parentId = :parentId order by parentId,name");
|
||||
|
||||
items << item;
|
||||
bool firstLevelUpdated = false;
|
||||
while(items.size() > 0)
|
||||
{
|
||||
nextLevelItems.clear();
|
||||
foreach(FolderItem * item, items)
|
||||
{
|
||||
QLOG_DEBUG() << "ID " << item->id;
|
||||
selectQuery.bindValue(":parentId", item->id);
|
||||
|
||||
selectQuery.exec();
|
||||
|
||||
if(!firstLevelUpdated)
|
||||
{
|
||||
//NO size support
|
||||
int numResults = 0;
|
||||
while(selectQuery.next())
|
||||
numResults++;
|
||||
|
||||
if(!selectQuery.seek(-1))
|
||||
selectQuery.exec();
|
||||
//END no size support
|
||||
|
||||
beginInsertRows(parent, 0, numResults-1);
|
||||
}
|
||||
|
||||
updateFolderModelData(selectQuery,item);
|
||||
|
||||
if(!firstLevelUpdated)
|
||||
{
|
||||
endInsertRows();
|
||||
firstLevelUpdated = true;
|
||||
}
|
||||
|
||||
nextLevelItems << item->children();
|
||||
|
||||
}
|
||||
|
||||
items.clear();
|
||||
items = nextLevelItems;
|
||||
}
|
||||
|
||||
QLOG_DEBUG() << "item->childCount()-1" << item->childCount()-1;
|
||||
|
||||
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
}
|
||||
|
||||
QModelIndex FolderModel::addFolderAtParent(const QString &folderName, const QModelIndex &parent)
|
||||
{
|
||||
FolderItem * parentItem;
|
||||
|
||||
if(parent.isValid())
|
||||
parentItem = static_cast<FolderItem*>(parent.internalPointer());
|
||||
else
|
||||
parentItem = rootItem;
|
||||
|
||||
Folder newFolder;
|
||||
newFolder.name = folderName;
|
||||
newFolder.parentId = parentItem->id;
|
||||
newFolder.path = parentItem->data(1).toString() + "/" + folderName;
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
newFolder.id = DBHelper::insert(&newFolder, db);
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
|
||||
int destRow = 0;
|
||||
|
||||
QList<QVariant> data;
|
||||
data << newFolder.name;
|
||||
data << newFolder.path;
|
||||
data << false; //finished
|
||||
data << true; //completed
|
||||
|
||||
FolderItem * item = new FolderItem(data);
|
||||
item->id = newFolder.id;
|
||||
|
||||
beginInsertRows(parent,0,0); //TODO calculate the destRow before inserting the new child
|
||||
|
||||
parentItem->appendChild(item);
|
||||
destRow = parentItem->children().indexOf(item); //TODO optimize this, appendChild should return the index of the new item
|
||||
items.insert(item->id,item);
|
||||
|
||||
endInsertRows();
|
||||
|
||||
return index(destRow,0,parent);
|
||||
}
|
||||
|
||||
void FolderModel::deleteFolder(const QModelIndex &mi)
|
||||
{
|
||||
beginRemoveRows(mi.parent(),mi.row(),mi.row());
|
||||
|
||||
FolderItem * item = static_cast<FolderItem*>(mi.internalPointer());
|
||||
|
||||
FolderItem * parent = item->parent();
|
||||
parent->removeChild(mi.row());
|
||||
|
||||
Folder f;
|
||||
f.setId(item->id);
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
DBHelper::removeFromDB(&f,db);
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
|
||||
//PROXY
|
||||
|
||||
FolderModelProxy::FolderModelProxy(QObject *parent)
|
||||
:QSortFilterProxyModel(parent),rootItem(0),filterEnabled(false),filter(""),includeComics(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
FolderModelProxy::~FolderModelProxy()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool FolderModelProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||
{
|
||||
if(!filterEnabled)
|
||||
return true;
|
||||
|
||||
FolderItem * parent = static_cast<FolderItem *>(source_parent.internalPointer());
|
||||
|
||||
if(parent == 0)
|
||||
parent = static_cast<FolderModel *>(sourceModel())->rootItem;
|
||||
|
||||
FolderItem * item = parent->children().at(source_row);
|
||||
|
||||
return filteredItems.contains(item->id);
|
||||
}
|
||||
|
||||
void FolderModelProxy::setFilter(const YACReader::SearchModifiers modifier, QString filter, bool includeComics)
|
||||
{
|
||||
clear();
|
||||
this->filter = filter;
|
||||
this->includeComics = includeComics;
|
||||
this->modifier = modifier;
|
||||
filterEnabled = true;
|
||||
setupFilteredModelData();
|
||||
}
|
||||
|
||||
void FolderModelProxy::setupFilteredModelData()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
//TODO hay que liberar memoria de anteriores filtrados
|
||||
|
||||
//inicializar el nodo ra<72>z
|
||||
|
||||
if(rootItem != 0)
|
||||
delete rootItem; //TODO comprobar que se libera bien la memoria
|
||||
|
||||
rootItem = 0;
|
||||
|
||||
//inicializar el nodo ra<72>z
|
||||
QList<QVariant> rootData;
|
||||
rootData << "root";
|
||||
rootItem = new FolderItem(rootData);
|
||||
rootItem->id = ROOT;
|
||||
rootItem->parentItem = 0;
|
||||
|
||||
FolderModel * model = static_cast<FolderModel *>(sourceModel());
|
||||
|
||||
//cargar la base de datos
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(model->_databasePath);
|
||||
//crear la consulta
|
||||
{
|
||||
QSqlQuery selectQuery(db); //TODO check
|
||||
if(!includeComics)
|
||||
{
|
||||
selectQuery.prepare("select * from folder where id <> 1 and upper(name) like upper(:filter) order by parentId,name ");
|
||||
selectQuery.bindValue(":filter", "%%"+filter+"%%");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(modifier)
|
||||
{
|
||||
case YACReader::NoModifiers:
|
||||
selectQuery.prepare("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed "
|
||||
"FROM folder f LEFT JOIN comic c ON (f.id = c.parentId) "
|
||||
"WHERE f.id <> 1 AND ((UPPER(c.fileName) like UPPER(:filter)) OR (UPPER(f.name) like UPPER(:filter2))) ORDER BY f.parentId,f.name");
|
||||
selectQuery.bindValue(":filter", "%%"+filter+"%%");
|
||||
selectQuery.bindValue(":filter2", "%%"+filter+"%%");
|
||||
break;
|
||||
|
||||
case YACReader::OnlyRead:
|
||||
selectQuery.prepare("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed "
|
||||
"FROM folder f LEFT JOIN (comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id)) ON (f.id = c.parentId) "
|
||||
"WHERE f.id <> 1 AND ((UPPER(c.fileName) like UPPER(:filter)) OR (UPPER(f.name) like UPPER(:filter2))) AND ci.read = 1 ORDER BY f.parentId,f.name;");
|
||||
selectQuery.bindValue(":filter", "%%"+filter+"%%");
|
||||
selectQuery.bindValue(":filter2", "%%"+filter+"%%");
|
||||
break;
|
||||
|
||||
case YACReader::OnlyUnread:
|
||||
selectQuery.prepare("SELECT DISTINCT f.id, f.parentId, f.name, f.path, f.finished, f.completed "
|
||||
"FROM folder f LEFT JOIN (comic c INNER JOIN comic_info ci ON (c.comicInfoId = ci.id)) ON (f.id = c.parentId) "
|
||||
"WHERE f.id <> 1 AND ((UPPER(c.fileName) like UPPER(:filter)) OR (UPPER(f.name) like UPPER(:filter2))) AND ci.read = 0 ORDER BY f.parentId,f.name;");
|
||||
selectQuery.bindValue(":filter", "%%"+filter+"%%");
|
||||
selectQuery.bindValue(":filter2", "%%"+filter+"%%");
|
||||
break;
|
||||
|
||||
default:
|
||||
QLOG_ERROR() << "not implemented";
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
selectQuery.exec();
|
||||
|
||||
setupFilteredModelData(selectQuery,rootItem);
|
||||
}
|
||||
//selectQuery.finish();
|
||||
db.close();
|
||||
QSqlDatabase::removeDatabase(model->_databasePath);
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void FolderModelProxy::clear()
|
||||
{
|
||||
filterEnabled = false;
|
||||
|
||||
filteredItems.clear();
|
||||
|
||||
QSortFilterProxyModel::clear();
|
||||
}
|
||||
|
||||
void FolderModelProxy::setupFilteredModelData(QSqlQuery &sqlquery, FolderItem *parent)
|
||||
{
|
||||
FolderModel * model = static_cast<FolderModel *>(sourceModel());
|
||||
|
||||
//64 bits para la primary key, es decir la misma precisi<73>n que soporta sqlit 2^64
|
||||
filteredItems.clear();
|
||||
|
||||
//se a<>ade el nodo 0 al modelo que representa el arbol de elementos que cumplen con el filtro
|
||||
filteredItems.insert(parent->id,parent);
|
||||
|
||||
while (sqlquery.next()) { //se procesan todos los folders que cumplen con el filtro
|
||||
//datos de la base de datos
|
||||
QList<QVariant> data;
|
||||
QSqlRecord record = sqlquery.record();
|
||||
|
||||
data << record.value("name").toString();
|
||||
data << record.value("path").toString();
|
||||
data << record.value("finished").toBool();
|
||||
data << record.value("completed").toBool();
|
||||
|
||||
FolderItem * item = new FolderItem(data);
|
||||
item->id = sqlquery.value(0).toULongLong();
|
||||
|
||||
//id del padre
|
||||
quint64 parentId = record.value("parentId").toULongLong();
|
||||
|
||||
//se a<>ade el item al map, de forma que se pueda encontrar como padre en siguientes iteraciones
|
||||
if(!filteredItems.contains(item->id))
|
||||
filteredItems.insert(item->id,item);
|
||||
|
||||
//es necesario conocer las coordenadas de origen para poder realizar scroll autom<6F>tico en la vista
|
||||
item->originalItem = model->items.value(item->id);
|
||||
|
||||
//si el padre ya existe en el modelo, el item se a<>ade como hijo
|
||||
if(filteredItems.contains(parentId))
|
||||
filteredItems.value(parentId)->appendChild(item);
|
||||
else//si el padre a<>n no se ha a<>adido, hay que a<>adirlo a <20>l y todos los padres hasta el nodo ra<72>z
|
||||
{
|
||||
//comprobamos con esta variable si el <20>ltimo de los padres (antes del nodo ra<72>z) ya exist<73>a en el modelo
|
||||
bool parentPreviousInserted = false;
|
||||
|
||||
//mientras no se alcance el nodo ra<72>z se procesan todos los padres (de abajo a arriba)
|
||||
while(parentId != ROOT )
|
||||
{
|
||||
//el padre no estaba en el modelo filtrado, as<61> que se rescata del modelo original
|
||||
FolderItem * parentItem = model->items.value(parentId);
|
||||
//se debe crear un nuevo nodo (para no compartir los hijos con el nodo original)
|
||||
FolderItem * newparentItem = new FolderItem(parentItem->getData()); //padre que se a<>adir<69> a la estructura de directorios filtrados
|
||||
newparentItem->id = parentId;
|
||||
|
||||
newparentItem->originalItem = parentItem;
|
||||
|
||||
//si el modelo contiene al padre, se a<>ade el item actual como hijo
|
||||
if(filteredItems.contains(parentId))
|
||||
{
|
||||
filteredItems.value(parentId)->appendChild(item);
|
||||
parentPreviousInserted = true;
|
||||
}
|
||||
//sino se registra el nodo para poder encontrarlo con posterioridad y se a<>ade el item actual como hijo
|
||||
else
|
||||
{
|
||||
newparentItem->appendChild(item);
|
||||
filteredItems.insert(newparentItem->id,newparentItem);
|
||||
parentPreviousInserted = false;
|
||||
}
|
||||
|
||||
//variables de control del bucle, se avanza hacia el nodo padre
|
||||
item = newparentItem;
|
||||
parentId = parentItem->parentItem->id;
|
||||
}
|
||||
|
||||
//si el nodo es hijo de 1 y no hab<61>a sido previamente insertado como hijo, se a<>ade como tal
|
||||
if(!parentPreviousInserted)
|
||||
filteredItems.value(ROOT)->appendChild(item);
|
||||
}
|
||||
}
|
||||
}
|
151
YACReaderLibrary/db/folder_model.h
Normal file
151
YACReaderLibrary/db/folder_model.h
Normal file
@ -0,0 +1,151 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** All rights reserved.
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** This file is part of the examples of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:BSD$
|
||||
** You may use this file under the terms of the BSD license as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
|
||||
** the names of its contributors may be used to endorse or promote
|
||||
** products derived from this software without specific prior written
|
||||
** permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef TREEMODEL_H
|
||||
#define TREEMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlDatabase>
|
||||
|
||||
#include "yacreader_global.h"
|
||||
|
||||
class FolderItem;
|
||||
|
||||
class FolderModelProxy : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit FolderModelProxy(QObject *parent = 0);
|
||||
~FolderModelProxy();
|
||||
|
||||
void setFilter(const YACReader::SearchModifiers modifier, QString filter, bool includeComics);
|
||||
void setupFilteredModelData( QSqlQuery &sqlquery, FolderItem *parent);
|
||||
void setupFilteredModelData();
|
||||
void clear();
|
||||
|
||||
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
||||
|
||||
protected:
|
||||
FolderItem *rootItem;
|
||||
QMap<unsigned long long int, FolderItem *> filteredItems; //relación entre folders
|
||||
|
||||
bool includeComics;
|
||||
QString filter;
|
||||
bool filterEnabled;
|
||||
|
||||
YACReader::SearchModifiers modifier;
|
||||
};
|
||||
|
||||
class FolderModel : public QAbstractItemModel
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
friend class FolderModelProxy;
|
||||
|
||||
public:
|
||||
FolderModel(QObject *parent = 0);
|
||||
FolderModel( QSqlQuery &sqlquery, QObject *parent = 0);
|
||||
~FolderModel();
|
||||
|
||||
//QAbstractItemModel methods
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
||||
//Convenience methods
|
||||
void setupModelData(QString path);
|
||||
QString getDatabase();
|
||||
QString getFolderPath(const QModelIndex &folder);
|
||||
//QModelIndex indexFromItem(FolderItem * item, int column);
|
||||
|
||||
|
||||
//bool isFilterEnabled(){return filterEnabled;};
|
||||
|
||||
void updateFolderCompletedStatus(const QModelIndexList & list, bool status);
|
||||
void updateFolderFinishedStatus(const QModelIndexList & list, bool status);
|
||||
|
||||
QStringList getSubfoldersNames(const QModelIndex & mi);
|
||||
|
||||
void fetchMoreFromDB(const QModelIndex & parent);
|
||||
|
||||
QModelIndex addFolderAtParent(const QString & folderName, const QModelIndex & parent);
|
||||
|
||||
enum Columns {
|
||||
Name = 0,
|
||||
Path = 1,
|
||||
Finished = 2,
|
||||
Completed = 3
|
||||
};//id INTEGER PRIMARY KEY, parentId INTEGER NOT NULL, name TEXT NOT NULL, path TEXT NOT NULL
|
||||
|
||||
enum Roles {
|
||||
FinishedRole = Qt::UserRole + 1,
|
||||
CompletedRole
|
||||
};
|
||||
|
||||
public slots:
|
||||
void deleteFolder(const QModelIndex & mi);
|
||||
|
||||
private:
|
||||
void setupModelData( QSqlQuery &sqlquery, FolderItem *parent);
|
||||
void updateFolderModelData( QSqlQuery &sqlquery, FolderItem *parent);
|
||||
|
||||
FolderItem *rootItem; //el árbol
|
||||
QMap<unsigned long long int, FolderItem *> items; //relación entre folders
|
||||
|
||||
QString _databasePath;
|
||||
|
||||
signals:
|
||||
void beforeReset();
|
||||
void reset();
|
||||
};
|
||||
//! [0]
|
||||
|
||||
#endif
|
239
YACReaderLibrary/db/reading_list_item.cpp
Normal file
239
YACReaderLibrary/db/reading_list_item.cpp
Normal file
@ -0,0 +1,239 @@
|
||||
#include "reading_list_item.h"
|
||||
#include "qnaturalsorting.h"
|
||||
|
||||
#include <QFileIconProvider>
|
||||
|
||||
ListItem::ListItem(const QList<QVariant> &data)
|
||||
:itemData(data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int ListItem::columnCount()
|
||||
{
|
||||
return itemData.count();
|
||||
}
|
||||
|
||||
QVariant ListItem::data(int column) const
|
||||
{
|
||||
return itemData.at(column);
|
||||
}
|
||||
|
||||
qulonglong ListItem::getId() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
SpecialListItem::SpecialListItem(const QList<QVariant> &data)
|
||||
:ListItem(data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QIcon SpecialListItem::getIcon() const
|
||||
{
|
||||
if(itemData.count()>Id)
|
||||
{
|
||||
QString id = itemData.at(Id).toString();
|
||||
return YACReader::noHighlightedIcon(QString(":/images/lists/default_%1.png").arg(id));
|
||||
}
|
||||
}
|
||||
|
||||
ReadingListModel::TypeSpecialList SpecialListItem::getType() const
|
||||
{
|
||||
if(itemData.count()>Id)
|
||||
{
|
||||
int id = itemData.at(Id).toInt();
|
||||
return (ReadingListModel::TypeSpecialList)id;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
LabelItem::LabelItem(const QList<QVariant> &data)
|
||||
:ListItem(data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QIcon LabelItem::getIcon() const
|
||||
{
|
||||
if(itemData.count()>Color)
|
||||
{
|
||||
QString color = itemData.at(Color).toString();
|
||||
return YACReader::noHighlightedIcon(QString(":/images/lists/label_%1.png").arg(color).toLower());
|
||||
}
|
||||
}
|
||||
|
||||
YACReader::LabelColors LabelItem::colorid() const
|
||||
{
|
||||
if(itemData.count()>Ordering)
|
||||
{
|
||||
return YACReader::LabelColors(itemData.at(Ordering).toInt());
|
||||
}
|
||||
}
|
||||
|
||||
QString LabelItem::name() const
|
||||
{
|
||||
if(itemData.count()>Name)
|
||||
{
|
||||
return itemData.at(Name).toString();
|
||||
}
|
||||
}
|
||||
|
||||
void LabelItem::setName(const QString &name)
|
||||
{
|
||||
if(itemData.count()>Name)
|
||||
{
|
||||
itemData[Name] = name;
|
||||
}
|
||||
}
|
||||
|
||||
qulonglong LabelItem::getId() const
|
||||
{
|
||||
if(itemData.count()>Id)
|
||||
{
|
||||
return YACReader::LabelColors(itemData.at(Id).toULongLong());
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
ReadingListItem::ReadingListItem(const QList<QVariant> &data, ReadingListItem *p)
|
||||
:ListItem(data), parent(p)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QIcon ReadingListItem::getIcon() const
|
||||
{
|
||||
if(parent->getId() == 0)
|
||||
return YACReader::noHighlightedIcon(":/images/lists/list.png"); //top level list
|
||||
else
|
||||
#ifdef Q_OS_MAC
|
||||
return QFileIconProvider().icon(QFileIconProvider::Folder);
|
||||
#else
|
||||
return YACReader::noHighlightedIcon(":/images/sidebar/folder.png"); //sublist
|
||||
#endif
|
||||
}
|
||||
|
||||
int ReadingListItem::childCount() const
|
||||
{
|
||||
return childItems.count();
|
||||
}
|
||||
|
||||
ReadingListItem *ReadingListItem::child(int row)
|
||||
{
|
||||
return childItems.at(row);
|
||||
}
|
||||
|
||||
//items are sorted by order
|
||||
void ReadingListItem::appendChild(ReadingListItem *item)
|
||||
{
|
||||
item->parent = this;
|
||||
|
||||
if(childItems.isEmpty())
|
||||
childItems.append(item);
|
||||
else
|
||||
{
|
||||
if(item->parent->getId()==0) //sort by name, top level child
|
||||
{
|
||||
int i= 0;
|
||||
while(i<childItems.length() && naturalSortLessThanCI(childItems.at(i)->name(),item->name()))
|
||||
i++;
|
||||
childItems.insert(i,item);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i= 0;
|
||||
while(i<childItems.length() && (childItems.at(i)->getOrdering()<item->getOrdering()))
|
||||
i++;
|
||||
childItems.insert(i,item);
|
||||
}
|
||||
|
||||
/*ReadingListItem * last = childItems.back();
|
||||
QString nameLast = last->data(1).toString(); //TODO usar info name si est<73> disponible, sino el nombre del fichero.....
|
||||
QString nameCurrent = item->data(1).toString();
|
||||
QList<FolderItem *>::iterator i;
|
||||
i = childItems.end();
|
||||
i--;
|
||||
while (naturalSortLessThanCI(nameCurrent,nameLast) && i != childItems.begin())
|
||||
{
|
||||
i--;
|
||||
nameLast = (*i)->data(1).toString();
|
||||
}
|
||||
if(!naturalSortLessThanCI(nameCurrent,nameLast)) //si se ha encontrado un elemento menor que current, se inserta justo despu<70>s
|
||||
childItems.insert(++i,item);
|
||||
else
|
||||
childItems.insert(i,item);*/
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ReadingListItem::appendChild(ReadingListItem *item, int pos)
|
||||
{
|
||||
childItems.insert(pos, item);
|
||||
}
|
||||
|
||||
void ReadingListItem::removeChild(ReadingListItem *item)
|
||||
{
|
||||
childItems.removeOne(item);
|
||||
}
|
||||
|
||||
qulonglong ReadingListItem::getId() const
|
||||
{
|
||||
if(itemData.count()>Id)
|
||||
return itemData.at(Id).toULongLong();
|
||||
}
|
||||
|
||||
QString ReadingListItem::name() const
|
||||
{
|
||||
if(itemData.count()>Name)
|
||||
return itemData.at(Name).toString();
|
||||
}
|
||||
|
||||
void ReadingListItem::setName(const QString &name)
|
||||
{
|
||||
if(itemData.count()>Name)
|
||||
itemData[Name] = name;
|
||||
}
|
||||
|
||||
int ReadingListItem::getOrdering() const
|
||||
{
|
||||
if(itemData.count()>Ordering)
|
||||
return itemData[Ordering].toInt();
|
||||
}
|
||||
|
||||
void ReadingListItem::setOrdering(const int ordering)
|
||||
{
|
||||
if(itemData.count()>Ordering)
|
||||
itemData[Ordering] = ordering;
|
||||
}
|
||||
|
||||
QList<ReadingListItem *> ReadingListItem::children()
|
||||
{
|
||||
return childItems;
|
||||
}
|
||||
|
||||
int ReadingListItem::row() const
|
||||
{
|
||||
if (parent)
|
||||
return parent->childItems.indexOf(const_cast<ReadingListItem*>(this));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ReadingListSeparatorItem::ReadingListSeparatorItem()
|
||||
:ListItem(QList<QVariant>())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QIcon ReadingListSeparatorItem::getIcon() const
|
||||
{
|
||||
return QIcon();
|
||||
}
|
103
YACReaderLibrary/db/reading_list_item.h
Normal file
103
YACReaderLibrary/db/reading_list_item.h
Normal file
@ -0,0 +1,103 @@
|
||||
#ifndef READING_LIST_ITEM_H
|
||||
#define READING_LIST_ITEM_H
|
||||
|
||||
#include <QIcon>
|
||||
#include <QVariant>
|
||||
|
||||
#include "yacreader_global_gui.h"
|
||||
#include "reading_list_model.h"
|
||||
//TODO add propper constructors, using QList<QVariant> is not safe
|
||||
|
||||
class ListItem
|
||||
{
|
||||
public:
|
||||
ListItem(const QList<QVariant> &data);
|
||||
int columnCount();
|
||||
virtual QIcon getIcon() const = 0;
|
||||
QVariant data(int column) const;
|
||||
virtual qulonglong getId() const;
|
||||
QList<QVariant> itemData;
|
||||
};
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
class SpecialListItem : public ListItem
|
||||
{
|
||||
public:
|
||||
SpecialListItem(const QList<QVariant> &data);
|
||||
QIcon getIcon() const;
|
||||
ReadingListModel::TypeSpecialList getType() const;
|
||||
private:
|
||||
enum DataIndexes {
|
||||
Name,
|
||||
Id
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
class LabelItem : public ListItem
|
||||
{
|
||||
public:
|
||||
LabelItem(const QList<QVariant> &data);
|
||||
QIcon getIcon() const;
|
||||
YACReader::LabelColors colorid() const;
|
||||
QString name() const;
|
||||
void setName(const QString & name);
|
||||
qulonglong getId() const;
|
||||
|
||||
|
||||
private:
|
||||
enum DataIndexes {
|
||||
Name,
|
||||
Color,
|
||||
Id,
|
||||
Ordering
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
class ReadingListItem : public ListItem
|
||||
{
|
||||
public:
|
||||
ReadingListItem(const QList<QVariant> &data, ReadingListItem * parent = 0);
|
||||
QIcon getIcon() const;
|
||||
ReadingListItem * parent;
|
||||
int childCount() const;
|
||||
int row() const;
|
||||
ReadingListItem * child(int row);
|
||||
void appendChild(ReadingListItem *item);
|
||||
void appendChild(ReadingListItem *item, int pos);
|
||||
void removeChild(ReadingListItem *item);
|
||||
qulonglong getId() const;
|
||||
QString name() const;
|
||||
void setName(const QString & name);
|
||||
int getOrdering() const;
|
||||
void setOrdering(const int ordering);
|
||||
QList<ReadingListItem*> children();
|
||||
|
||||
private:
|
||||
QList<ReadingListItem*> childItems;
|
||||
|
||||
enum DataIndexes {
|
||||
Name,
|
||||
Id,
|
||||
Finished,
|
||||
Completed,
|
||||
Ordering
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
class ReadingListSeparatorItem : public ListItem
|
||||
{
|
||||
public:
|
||||
ReadingListSeparatorItem();
|
||||
QIcon getIcon() const;
|
||||
};
|
||||
|
||||
#endif // READING_LIST_ITEM_H
|
778
YACReaderLibrary/db/reading_list_model.cpp
Normal file
778
YACReaderLibrary/db/reading_list_model.cpp
Normal file
@ -0,0 +1,778 @@
|
||||
#include "reading_list_model.h"
|
||||
|
||||
#include "reading_list_item.h"
|
||||
|
||||
#include "data_base_management.h"
|
||||
#include "qnaturalsorting.h"
|
||||
#include "db_helper.h"
|
||||
|
||||
#include "QsLog.h"
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
ReadingListModel::ReadingListModel(QObject *parent) :
|
||||
QAbstractItemModel(parent),rootItem(0)
|
||||
{
|
||||
separator1 = new ReadingListSeparatorItem;
|
||||
separator2 = new ReadingListSeparatorItem;
|
||||
}
|
||||
|
||||
int ReadingListModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if(!parent.isValid()) //TOP
|
||||
{
|
||||
int separatorsCount = 2;//labels.isEmpty()?1:2;
|
||||
return specialLists.count() + labels.count() + rootItem->childCount() + separatorsCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
ListItem * item = static_cast<ListItem*>(parent.internalPointer());
|
||||
|
||||
if(typeid(*item) == typeid(ReadingListItem))
|
||||
{
|
||||
ReadingListItem * item = static_cast<ReadingListItem*>(parent.internalPointer());
|
||||
return item->childCount();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ReadingListModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
if(parent.isValid())
|
||||
{
|
||||
ListItem * item = static_cast<ListItem*>(parent.internalPointer());
|
||||
if(typeid(*item) == typeid(ReadingListSeparatorItem))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
/*if (parent.isValid())
|
||||
return static_cast<ListItem*>(parent.internalPointer())->columnCount();
|
||||
else
|
||||
return rootItem->columnCount();*/
|
||||
}
|
||||
|
||||
QVariant ReadingListModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if(!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
ListItem * item = static_cast<ListItem*>(index.internalPointer());
|
||||
|
||||
if (role == ReadingListModel::TypeListsRole)
|
||||
{
|
||||
if(typeid(*item) == typeid(SpecialListItem))
|
||||
return QVariant(ReadingListModel::SpecialList);
|
||||
|
||||
if(typeid(*item) == typeid(LabelItem))
|
||||
return QVariant(ReadingListModel::Label);
|
||||
|
||||
if(typeid(*item) == typeid(ReadingListItem))
|
||||
return QVariant(ReadingListModel::ReadingList);
|
||||
|
||||
if(typeid(*item) == typeid(ReadingListSeparatorItem))
|
||||
return QVariant(ReadingListModel::Separator);
|
||||
}
|
||||
|
||||
if (role == ReadingListModel::LabelColorRole && typeid(*item) == typeid(LabelItem) )
|
||||
{
|
||||
LabelItem * labelItem = static_cast<LabelItem*>(item);
|
||||
return QVariant(labelItem->colorid());
|
||||
}
|
||||
|
||||
if (role == ReadingListModel::IDRole)
|
||||
{
|
||||
QLOG_DEBUG() << "getting role";
|
||||
return item->getId();
|
||||
}
|
||||
|
||||
if (role == ReadingListModel::SpecialListTypeRole && typeid(*item) == typeid(SpecialListItem))
|
||||
{
|
||||
SpecialListItem * specialListItem = static_cast<SpecialListItem*>(item);
|
||||
return QVariant(specialListItem->getType());
|
||||
}
|
||||
|
||||
if(typeid(*item) == typeid(ReadingListSeparatorItem))
|
||||
return QVariant();
|
||||
|
||||
if (role == Qt::DecorationRole)
|
||||
{
|
||||
return QVariant(item->getIcon());
|
||||
}
|
||||
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
return item->data(index.column());
|
||||
}
|
||||
|
||||
Qt::ItemFlags ReadingListModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return 0;
|
||||
|
||||
ListItem * item = static_cast<ListItem*>(index.internalPointer());
|
||||
if(typeid(*item) == typeid(ReadingListSeparatorItem))
|
||||
return 0;
|
||||
|
||||
if(typeid(*item) == typeid(ReadingListItem) && static_cast<ReadingListItem *>(item)->parent->getId()!=0)
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; //only sublists are dragable
|
||||
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
|
||||
}
|
||||
|
||||
QVariant ReadingListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
|
||||
return rootItem->data(section);
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex ReadingListModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
if(!parent.isValid())
|
||||
{
|
||||
int separatorsCount = 2;//labels.isEmpty()?1:2;
|
||||
|
||||
if(rowIsSpecialList(row,parent))
|
||||
return createIndex(row, column, specialLists.at(row));
|
||||
|
||||
if(row == specialLists.count())
|
||||
return createIndex(row,column,separator1);
|
||||
|
||||
if(rowIsLabel(row,parent))
|
||||
return createIndex(row,column,labels.at(row-specialLists.count()-1));
|
||||
|
||||
if(separatorsCount == 2)
|
||||
if(row == specialLists.count() + labels.count() + 1)
|
||||
return createIndex(row,column,separator2);
|
||||
|
||||
if(rowIsReadingList(row,parent))
|
||||
return createIndex(row,column,rootItem->child(row - (specialLists.count() + labels.count() + separatorsCount)));
|
||||
|
||||
} else //sublist
|
||||
{
|
||||
ReadingListItem *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = rootItem; //this should be impossible
|
||||
else
|
||||
parentItem = static_cast<ReadingListItem*>(parent.internalPointer());
|
||||
|
||||
ReadingListItem *childItem = parentItem->child(row);
|
||||
return createIndex(row,column,childItem);
|
||||
}
|
||||
/*FolderItem *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
else*/
|
||||
return QModelIndex();
|
||||
|
||||
}
|
||||
|
||||
QModelIndex ReadingListModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
|
||||
if(!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
ListItem * item = static_cast<ListItem*>(index.internalPointer());
|
||||
|
||||
if(typeid(*item) == typeid(ReadingListItem))
|
||||
{
|
||||
ReadingListItem * childItem = static_cast<ReadingListItem*>(index.internalPointer());
|
||||
ReadingListItem * parent = childItem->parent;
|
||||
if(parent->getId() != 0)
|
||||
return createIndex(parent->row()+specialLists.count()+labels.count()+2, 0, parent);
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
bool ReadingListModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
QLOG_DEBUG() << "trying to drop into row = " << row << "column column = " << column << "parent" << parent;
|
||||
|
||||
if(row == -1)
|
||||
return false;
|
||||
|
||||
if(!parent.isValid()) //top level items
|
||||
{
|
||||
if(row == -1) //no list
|
||||
return false;
|
||||
|
||||
if(row == 1) //reading is just an smart list
|
||||
return false;
|
||||
|
||||
if(rowIsSeparator(row,parent))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat))
|
||||
return true;
|
||||
|
||||
if(rowIsReadingList(row,parent))// TODO avoid droping in a different parent
|
||||
if(!parent.isValid())
|
||||
return false;
|
||||
else
|
||||
{
|
||||
QList<QPair<int,int> > sublistsRows;
|
||||
QByteArray rawData = data->data(YACReader::YACReaderLibrarSubReadingListMimeDataFormat);
|
||||
QDataStream in(&rawData,QIODevice::ReadOnly);
|
||||
in >> sublistsRows; //deserialize the list of indentifiers
|
||||
if(parent.row()!= sublistsRows.at(0).second)
|
||||
return false;
|
||||
return data->formats().contains(YACReader::YACReaderLibrarSubReadingListMimeDataFormat);
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadingListModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
QLOG_DEBUG() << "drop mimedata into row = " << row << " column = " << column << "parent" << parent;
|
||||
if(data->formats().contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat))
|
||||
return dropComics(data, action, row, column, parent);
|
||||
|
||||
if(data->formats().contains(YACReader::YACReaderLibrarSubReadingListMimeDataFormat))
|
||||
return dropSublist(data, action, row, column, parent);
|
||||
}
|
||||
|
||||
bool ReadingListModel::dropComics(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
QList<qulonglong> comicIds = YACReader::mimeDataToComicsIds(data);
|
||||
|
||||
QLOG_DEBUG() << "dropped : " << comicIds;
|
||||
|
||||
QModelIndex dest;
|
||||
QModelIndex parentDest;
|
||||
|
||||
if(row == -1)
|
||||
{
|
||||
dest = parent;
|
||||
}
|
||||
else
|
||||
dest = index(row,column,parent);
|
||||
|
||||
parentDest = dest.parent();
|
||||
|
||||
if(rowIsSpecialList(dest.row(),parentDest)) {
|
||||
if(dest.row() == 0) //add to favorites
|
||||
{
|
||||
QLOG_DEBUG() << "-------addComicsToFavorites : " << comicIds << " to " << dest.data(IDRole).toULongLong();
|
||||
emit addComicsToFavorites(comicIds);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(rowIsLabel(dest.row(),parentDest)) {
|
||||
QLOG_DEBUG() << "+++++++++++addComicsToLabel : " << comicIds << " to " << dest.data(IDRole).toULongLong();
|
||||
emit addComicsToLabel(comicIds, dest.data(IDRole).toULongLong());
|
||||
return true;
|
||||
}
|
||||
|
||||
if(rowIsReadingList(dest.row(),parentDest)) {
|
||||
QLOG_DEBUG() << "///////////addComicsToReadingList : " << comicIds << " to " << dest.data(IDRole).toULongLong();
|
||||
emit addComicsToReadingList(comicIds, dest.data(IDRole).toULongLong());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadingListModel::dropSublist(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
QList<QPair<int,int> > sublistsRows;
|
||||
QByteArray rawData = data->data(YACReader::YACReaderLibrarSubReadingListMimeDataFormat);
|
||||
QDataStream in(&rawData,QIODevice::ReadOnly);
|
||||
in >> sublistsRows; //deserialize the list of indentifiers
|
||||
|
||||
QLOG_DEBUG() << "dropped : " << sublistsRows;
|
||||
|
||||
int sourceRow = sublistsRows.at(0).first;
|
||||
int destRow = row;
|
||||
QModelIndex destParent = parent;
|
||||
if(row == -1)
|
||||
{
|
||||
QLOG_DEBUG() << "droping inside parent";
|
||||
destRow = parent.row();
|
||||
destParent = parent.parent();
|
||||
}
|
||||
QLOG_DEBUG() << "move " << sourceRow << "-" << destRow;
|
||||
|
||||
if(sourceRow == destRow)
|
||||
return false;
|
||||
|
||||
//beginMoveRows(destParent,sourceRow,sourceRow,destParent,destRow);
|
||||
|
||||
ReadingListItem * parentItem = static_cast<ReadingListItem *>(destParent.internalPointer());
|
||||
ReadingListItem * child = parentItem->child(sourceRow);
|
||||
parentItem->removeChild(child);
|
||||
parentItem->appendChild(child,destRow);
|
||||
|
||||
reorderingChildren(parentItem->children());
|
||||
//endMoveRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QMimeData *ReadingListModel::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
QLOG_DEBUG() << "mimeData requested" << indexes;
|
||||
|
||||
if(indexes.length() == 0)
|
||||
{
|
||||
QLOG_ERROR() << "mimeData requested: indexes is empty";
|
||||
return new QMimeData();//TODO what happens if 0 is returned?
|
||||
}
|
||||
|
||||
if(indexes.length() > 1)
|
||||
QLOG_DEBUG() << "mimeData requested for more than one index, this shouldn't be possible";
|
||||
|
||||
QModelIndex modelIndex = indexes.at(0);
|
||||
|
||||
QList<QPair<int,int> > rows;
|
||||
rows << QPair<int,int>(modelIndex.row(),modelIndex.parent().row());
|
||||
QLOG_DEBUG() << "mimeData requested for row : " << modelIndex.row();
|
||||
|
||||
QByteArray data;
|
||||
QDataStream out(&data,QIODevice::WriteOnly);
|
||||
out << rows; //serialize the list of identifiers
|
||||
|
||||
QMimeData * mimeData = new QMimeData();
|
||||
mimeData->setData(YACReader::YACReaderLibrarSubReadingListMimeDataFormat, data);
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
void ReadingListModel::setupReadingListsData(QString path)
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
cleanAll();
|
||||
|
||||
_databasePath = path;
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(path);
|
||||
|
||||
//setup special lists
|
||||
specialLists = setupSpecialLists(db);
|
||||
|
||||
//separator--------------------------------------------
|
||||
|
||||
//setup labels
|
||||
setupLabels(db);
|
||||
|
||||
//separator--------------------------------------------
|
||||
|
||||
//setup reading list
|
||||
setupReadingLists(db);
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void ReadingListModel::addNewLabel(const QString &name, YACReader::LabelColors color)
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
qulonglong id = DBHelper::insertLabel(name, color, db);
|
||||
|
||||
beginInsertRows(QModelIndex(),0, 0);
|
||||
|
||||
int newPos = addLabelIntoList(new LabelItem(QList<QVariant>() << name << YACReader::colorToName(color) << id << color));
|
||||
|
||||
//beginInsertRows(QModelIndex(),specialLists.count()+1+newPos+1, specialLists.count()+1+newPos+1);
|
||||
endInsertRows();
|
||||
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
}
|
||||
|
||||
void ReadingListModel::addReadingList(const QString &name)
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
|
||||
beginInsertRows(QModelIndex(), 0, 0); //TODO calculate the right coordinates before inserting
|
||||
|
||||
qulonglong id = DBHelper::insertReadingList(name,db);
|
||||
ReadingListItem * newItem;
|
||||
rootItem->appendChild(newItem = new ReadingListItem(QList<QVariant>()
|
||||
<< name
|
||||
<< id
|
||||
<< false
|
||||
<< true
|
||||
<< 0));
|
||||
|
||||
items.insert(id, newItem);
|
||||
|
||||
/*int pos = rootItem->children().indexOf(newItem);
|
||||
|
||||
pos += specialLists.count()+1+labels.count()+labels.count()>0?1:0;*/
|
||||
|
||||
|
||||
endInsertRows();
|
||||
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
}
|
||||
|
||||
void ReadingListModel::addReadingListAt(const QString &name, const QModelIndex &mi)
|
||||
{
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
|
||||
beginInsertRows(mi, 0, 0); //TODO calculate the right coordinates before inserting
|
||||
|
||||
ReadingListItem * readingListParent = static_cast<ReadingListItem*>(mi.internalPointer());
|
||||
qulonglong id = DBHelper::insertReadingSubList(name,mi.data(IDRole).toULongLong(),readingListParent->childCount(),db);
|
||||
ReadingListItem * newItem;
|
||||
|
||||
readingListParent->appendChild(newItem = new ReadingListItem(QList<QVariant>()
|
||||
<< name
|
||||
<< id
|
||||
<< false
|
||||
<< true
|
||||
<< readingListParent->childCount()));
|
||||
|
||||
items.insert(id, newItem);
|
||||
|
||||
/*int pos = readingListParent->children().indexOf(newItem);
|
||||
|
||||
pos += specialLists.count()+1+labels.count()+labels.count()>0?1:0;*/
|
||||
|
||||
|
||||
endInsertRows();
|
||||
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
}
|
||||
|
||||
bool ReadingListModel::isEditable(const QModelIndex &mi)
|
||||
{
|
||||
if(!mi.isValid())
|
||||
return false;
|
||||
ListItem * item = static_cast<ListItem*>(mi.internalPointer());
|
||||
return typeid(*item) != typeid(SpecialListItem);
|
||||
}
|
||||
|
||||
bool ReadingListModel::isReadingList(const QModelIndex &mi)
|
||||
{
|
||||
if(!mi.isValid())
|
||||
return false;
|
||||
ListItem * item = static_cast<ListItem*>(mi.internalPointer());
|
||||
return typeid(*item) == typeid(ReadingListItem);
|
||||
}
|
||||
|
||||
bool ReadingListModel::isReadingSubList(const QModelIndex &mi)
|
||||
{
|
||||
if(!mi.isValid())
|
||||
return false;
|
||||
ListItem * item = static_cast<ListItem*>(mi.internalPointer());
|
||||
if(typeid(*item) == typeid(ReadingListItem))
|
||||
{
|
||||
ReadingListItem * readingListItem = static_cast<ReadingListItem *>(item);
|
||||
if(readingListItem->parent == rootItem)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
QString ReadingListModel::name(const QModelIndex &mi)
|
||||
{
|
||||
return data(mi,Qt::DisplayRole).toString();
|
||||
}
|
||||
|
||||
void ReadingListModel::rename(const QModelIndex &mi, const QString &name)
|
||||
{
|
||||
if(!isEditable(mi))
|
||||
return;
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
|
||||
ListItem * item = static_cast<ListItem*>(mi.internalPointer());
|
||||
|
||||
if(typeid(*item) == typeid(ReadingListItem))
|
||||
{
|
||||
ReadingListItem * rli = static_cast<ReadingListItem*>(item);
|
||||
rli->setName(name);
|
||||
DBHelper::renameList(item->getId(), name, db);
|
||||
|
||||
if(rli->parent->getId()!=0)
|
||||
{
|
||||
//TODO
|
||||
//move row depending on the name
|
||||
}else
|
||||
emit dataChanged(index(mi.row(), 0), index(mi.row(), 0));
|
||||
}
|
||||
else if(typeid(*item) == typeid(LabelItem))
|
||||
{
|
||||
LabelItem * li = static_cast<LabelItem*>(item);
|
||||
li->setName(name);
|
||||
DBHelper::renameLabel(item->getId(), name, db);
|
||||
emit dataChanged(index(mi.row(), 0), index(mi.row(), 0));
|
||||
}
|
||||
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
}
|
||||
|
||||
void ReadingListModel::deleteItem(const QModelIndex &mi)
|
||||
{
|
||||
if(isEditable(mi))
|
||||
{
|
||||
QLOG_DEBUG() << "parent row :" << mi.parent().data() << "-" << mi.row();
|
||||
beginRemoveRows(mi.parent(),mi.row(),mi.row());
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
|
||||
ListItem * item = static_cast<ListItem*>(mi.internalPointer());
|
||||
|
||||
if(typeid(*item) == typeid(ReadingListItem))
|
||||
{
|
||||
ReadingListItem * rli = static_cast<ReadingListItem*>(item);
|
||||
QLOG_DEBUG() << "num children : " << rli->parent->childCount();
|
||||
rli->parent->removeChild(rli);
|
||||
QLOG_DEBUG() << "num children : " << rli->parent->childCount();
|
||||
DBHelper::removeListFromDB(item->getId(), db);
|
||||
if(rli->parent->getId()!=0)
|
||||
{
|
||||
reorderingChildren(rli->parent->children());
|
||||
}
|
||||
QLOG_DEBUG() << "num children : " << rli->parent->childCount();
|
||||
}
|
||||
else if(typeid(*item) == typeid(LabelItem))
|
||||
{
|
||||
LabelItem * li = static_cast<LabelItem*>(item);
|
||||
labels.removeOne(li);
|
||||
DBHelper::removeLabelFromDB(item->getId(), db);
|
||||
}
|
||||
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
const QList<LabelItem *> ReadingListModel::getLabels()
|
||||
{
|
||||
return labels;
|
||||
}
|
||||
|
||||
void ReadingListModel::cleanAll()
|
||||
{
|
||||
if(rootItem != 0)
|
||||
{
|
||||
delete rootItem;
|
||||
|
||||
qDeleteAll(specialLists);
|
||||
qDeleteAll(labels);
|
||||
|
||||
specialLists.clear();
|
||||
labels.clear();
|
||||
|
||||
items.clear();
|
||||
}
|
||||
|
||||
rootItem = 0;
|
||||
}
|
||||
|
||||
void ReadingListModel::setupReadingListsData(QSqlQuery &sqlquery, ReadingListItem *parent)
|
||||
{
|
||||
items.insert(parent->getId(),parent);
|
||||
|
||||
while (sqlquery.next())
|
||||
{
|
||||
QSqlRecord record = sqlquery.record();
|
||||
ReadingListItem * rli = new ReadingListItem(QList<QVariant>()
|
||||
<< record.value("name")
|
||||
<< record.value("id")
|
||||
<< record.value("finished")
|
||||
<< record.value("completed")
|
||||
<< record.value("ordering"));
|
||||
|
||||
ReadingListItem * currentParent;
|
||||
if(record.value("parentId").isNull())
|
||||
currentParent = rootItem;
|
||||
else
|
||||
currentParent = items.value(record.value("parentId").toULongLong());
|
||||
|
||||
currentParent->appendChild(rli);
|
||||
|
||||
items.insert(rli->getId(),rli);
|
||||
}
|
||||
}
|
||||
|
||||
QList<SpecialListItem *> ReadingListModel::setupSpecialLists(QSqlDatabase & db)
|
||||
{
|
||||
QList<SpecialListItem *> list;
|
||||
|
||||
QSqlQuery selectQuery("SELECT * FROM default_reading_list ORDER BY id,name",db);
|
||||
while(selectQuery.next()) {
|
||||
QSqlRecord record = selectQuery.record();
|
||||
list << new SpecialListItem(QList<QVariant>()
|
||||
<< record.value("name")
|
||||
<< record.value("id"));
|
||||
}
|
||||
|
||||
//Reading after Favorites, Why? Because I want to :P
|
||||
list.insert(1,new SpecialListItem(QList<QVariant>() << "Reading" << 0));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void ReadingListModel::setupLabels(QSqlDatabase & db)
|
||||
{
|
||||
QSqlQuery selectQuery("SELECT * FROM label ORDER BY ordering,name",db); //TODO add some kind of
|
||||
while(selectQuery.next()) {
|
||||
QSqlRecord record = selectQuery.record();
|
||||
addLabelIntoList(new LabelItem(QList<QVariant>()
|
||||
<< record.value("name")
|
||||
<< record.value("color")
|
||||
<< record.value("id")
|
||||
<< record.value("ordering")));
|
||||
}
|
||||
|
||||
//TEST
|
||||
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("Oh Oh", "red", 1);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("lalala", "orange", 2);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("we are not sorry", "yellow", 3);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("there we go", "green", 4);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("oklabunga", "cyan", 5);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("hailer mailer", "blue", 6);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("lol", "violet", 7);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("problems", "purple", 8);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("me gussssta", "pink", 9);
|
||||
// INSERT INTO label (name, color, ordering) VALUES (":D", "white", 10);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("ainsss", "light", 11);
|
||||
// INSERT INTO label (name, color, ordering) VALUES ("put a smile on my face", "dark", 12);
|
||||
|
||||
}
|
||||
|
||||
void ReadingListModel::setupReadingLists(QSqlDatabase & db)
|
||||
{
|
||||
//setup root item
|
||||
rootItem = new ReadingListItem(QList<QVariant>() << "ROOT" << 0 << true << false);
|
||||
|
||||
QSqlQuery selectQuery("select * from reading_list order by parentId IS NULL DESC",db);
|
||||
|
||||
//setup reading lists
|
||||
setupReadingListsData(selectQuery,rootItem);
|
||||
|
||||
//TEST
|
||||
// ReadingListItem * node1;
|
||||
// rootItem->appendChild(node1 = new ReadingListItem(QList<QVariant>() /*<< 0*/ << "My reading list" << "atr"));
|
||||
// rootItem->appendChild(new ReadingListItem(QList<QVariant>() /*<< 0*/ << "X timeline" << "atr"));
|
||||
|
||||
// node1->appendChild(new ReadingListItem(QList<QVariant>() /*<< 0*/ << "sublist" << "atr",node1));
|
||||
}
|
||||
|
||||
int ReadingListModel::addLabelIntoList(LabelItem *item)
|
||||
{
|
||||
if(labels.isEmpty())
|
||||
labels << item;
|
||||
else
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (i < labels.count() && (labels.at(i)->colorid() < item->colorid()) )
|
||||
i++;
|
||||
|
||||
if(i < labels.count())
|
||||
{
|
||||
if(labels.at(i)->colorid() == item->colorid()) //sort by name
|
||||
{
|
||||
while( i < labels.count() && labels.at(i)->colorid() == item->colorid() && naturalSortLessThanCI(labels.at(i)->name(),item->name()))
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(i >= labels.count())
|
||||
{
|
||||
QLOG_DEBUG() << "insertando label al final " << item->name();
|
||||
labels << item;
|
||||
}
|
||||
else
|
||||
{
|
||||
QLOG_DEBUG() << "insertando label en " << i << "-" << item->name();
|
||||
labels.insert(i,item);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ReadingListModel::reorderingChildren(QList<ReadingListItem *> children)
|
||||
{
|
||||
QList<qulonglong> childrenIds;
|
||||
int i = 0;
|
||||
foreach (ReadingListItem * item, children) {
|
||||
item->setOrdering(i++);
|
||||
childrenIds << item->getId();
|
||||
}
|
||||
|
||||
QSqlDatabase db = DataBaseManagement::loadDatabase(_databasePath);
|
||||
DBHelper::reasignOrderToSublists(childrenIds, db);
|
||||
QSqlDatabase::removeDatabase(_databasePath);
|
||||
}
|
||||
|
||||
bool ReadingListModel::rowIsSpecialList(int row, const QModelIndex &parent) const
|
||||
{
|
||||
if(parent.isValid())
|
||||
return false; //by now no sublists in special list
|
||||
|
||||
if(row >=0 && row < specialLists.count())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadingListModel::rowIsLabel(int row, const QModelIndex &parent) const
|
||||
{
|
||||
if(parent.isValid())
|
||||
return false; //by now no sublists in labels
|
||||
|
||||
if(row > specialLists.count() && row <= specialLists.count() + labels.count())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadingListModel::rowIsReadingList(int row, const QModelIndex &parent) const
|
||||
{
|
||||
if(parent.isValid())
|
||||
return true; //only lists with sublists
|
||||
|
||||
int separatorsCount = labels.isEmpty()?1:2;
|
||||
|
||||
if(row >= specialLists.count() + labels.count() + separatorsCount)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ReadingListModel::rowIsSeparator(int row, const QModelIndex &parent) const
|
||||
{
|
||||
if(parent.isValid())
|
||||
return false; //only separators at top level
|
||||
|
||||
if(row == specialLists.count())
|
||||
return true;
|
||||
|
||||
int separatorsCount = labels.isEmpty()?1:2;
|
||||
if(separatorsCount == 2 && row == specialLists.count() + labels.count() + 1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadingListModelProxy::ReadingListModelProxy(QObject *parent)
|
||||
:QSortFilterProxyModel(parent)
|
||||
{
|
||||
|
||||
}
|
117
YACReaderLibrary/db/reading_list_model.h
Normal file
117
YACReaderLibrary/db/reading_list_model.h
Normal file
@ -0,0 +1,117 @@
|
||||
#ifndef READING_LIST_MODEL_H
|
||||
#define READING_LIST_MODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QModelIndex>
|
||||
#include <QVariant>
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlDatabase>
|
||||
|
||||
#include "yacreader_global.h"
|
||||
|
||||
class LabelItem;
|
||||
class SpecialListItem;
|
||||
class ReadingListItem;
|
||||
class ReadingListSeparatorItem;
|
||||
|
||||
class ReadingListModelProxy : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ReadingListModelProxy(QObject *parent = 0);
|
||||
};
|
||||
|
||||
class ReadingListModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ReadingListModel(QObject *parent = 0);
|
||||
|
||||
//QAbstractItemModel methods
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
QVariant data(const QModelIndex &index, int role) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const;
|
||||
QModelIndex parent(const QModelIndex &index) const;
|
||||
bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const;
|
||||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
QMimeData *mimeData(const QModelIndexList &indexes) const;
|
||||
|
||||
//Convenience methods
|
||||
void setupReadingListsData(QString path);
|
||||
void addNewLabel(const QString & name, YACReader::LabelColors color);
|
||||
void addReadingList(const QString & name);//top level reading list
|
||||
void addReadingListAt(const QString & name, const QModelIndex & mi);
|
||||
bool isEditable(const QModelIndex & mi);
|
||||
bool isReadingList(const QModelIndex & mi);
|
||||
bool isReadingSubList(const QModelIndex & mi);
|
||||
QString name(const QModelIndex & mi);
|
||||
void rename(const QModelIndex & mi, const QString & name);
|
||||
void deleteItem(const QModelIndex & mi);
|
||||
const QList<LabelItem *> getLabels();
|
||||
|
||||
enum Roles {
|
||||
TypeListsRole = Qt::UserRole + 1,
|
||||
IDRole,
|
||||
LabelColorRole,
|
||||
SpecialListTypeRole
|
||||
};
|
||||
|
||||
enum TypeList {
|
||||
SpecialList,
|
||||
Label,
|
||||
ReadingList,
|
||||
Separator
|
||||
};
|
||||
|
||||
enum TypeSpecialList {
|
||||
Reading,
|
||||
Favorites
|
||||
};
|
||||
|
||||
signals:
|
||||
|
||||
void addComicsToFavorites(const QList<qulonglong> & comicIds);
|
||||
void addComicsToLabel(const QList<qulonglong> & comicIds, qulonglong labelId);
|
||||
void addComicsToReadingList(const QList<qulonglong> & comicIds, qulonglong readingListId);
|
||||
|
||||
private:
|
||||
void cleanAll();
|
||||
void setupReadingListsData(QSqlQuery &sqlquery, ReadingListItem *parent);
|
||||
QList<SpecialListItem *> setupSpecialLists(QSqlDatabase &db);
|
||||
void setupLabels(QSqlDatabase &db);
|
||||
void setupReadingLists(QSqlDatabase &db);
|
||||
int addLabelIntoList(LabelItem *item);
|
||||
void reorderingChildren(QList<ReadingListItem *> children);
|
||||
|
||||
bool rowIsSpecialList(int row, const QModelIndex & parent = QModelIndex()) const;
|
||||
bool rowIsLabel(int row, const QModelIndex & parent = QModelIndex()) const;
|
||||
bool rowIsReadingList(int row, const QModelIndex & parent = QModelIndex()) const;
|
||||
bool rowIsSeparator(int row, const QModelIndex & parent = QModelIndex()) const;
|
||||
|
||||
bool dropComics(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
bool dropSublist(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
//Special lists
|
||||
QList<SpecialListItem *> specialLists;
|
||||
|
||||
//Label
|
||||
QList<LabelItem *> labels;
|
||||
|
||||
//Reading lists
|
||||
ReadingListItem * rootItem; //
|
||||
QMap<unsigned long long int, ReadingListItem *> items; //lists relationship
|
||||
|
||||
//separators
|
||||
ReadingListSeparatorItem * separator1;
|
||||
ReadingListSeparatorItem * separator2;
|
||||
|
||||
QString _databasePath;
|
||||
|
||||
};
|
||||
|
||||
#endif // READING_LIST_MODEL_H
|
1064
YACReaderLibrary/db_helper.cpp
Normal file
1064
YACReaderLibrary/db_helper.cpp
Normal file
File diff suppressed because it is too large
Load Diff
81
YACReaderLibrary/db_helper.h
Normal file
81
YACReaderLibrary/db_helper.h
Normal file
@ -0,0 +1,81 @@
|
||||
#ifndef DB_HELPER_H
|
||||
#define DB_HELPER_H
|
||||
|
||||
class QString;
|
||||
#include <QMap>
|
||||
#include <QList>
|
||||
#include "yacreader_global.h"
|
||||
|
||||
class ComicDB;
|
||||
class Folder;
|
||||
class LibraryItem;
|
||||
class QSqlDatabase;
|
||||
class ComicInfo;
|
||||
class QSqlRecord;
|
||||
class QSqlQuery;
|
||||
class YACReaderLibraries;
|
||||
|
||||
class DBHelper
|
||||
{
|
||||
public:
|
||||
//server
|
||||
static YACReaderLibraries getLibraries();
|
||||
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 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);
|
||||
|
||||
//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 removeLabelFromDB(qulonglong id, QSqlDatabase & db);
|
||||
static void removeListFromDB(qulonglong id, QSqlDatabase & db);
|
||||
//logic deletes
|
||||
static void deleteComicsFromFavorites(const QList<ComicDB> & comicsList, QSqlDatabase & db);
|
||||
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 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);
|
||||
static void insertComicsInFavorites(const QList<ComicDB> & comicsList, QSqlDatabase & db);
|
||||
static void insertComicsInLabel(const QList<ComicDB> & comicsList, qulonglong labelId, QSqlDatabase & db);
|
||||
static void insertComicsInReadingList(const QList<ComicDB> & comicsList, qulonglong readingListId, QSqlDatabase & db);
|
||||
//updates
|
||||
static void update(qulonglong libraryId, ComicInfo & comicInfo);
|
||||
static void update(ComicDB * comics, QSqlDatabase & db);
|
||||
static void update(ComicInfo * comicInfo, QSqlDatabase & db);
|
||||
static void updateRead(ComicInfo * comicInfo, QSqlDatabase & db);
|
||||
static void update(const Folder & folder, QSqlDatabase & db);
|
||||
static void updateProgress(qulonglong libraryId,const ComicInfo & comicInfo);
|
||||
static void updateReadingRemoteProgress(const ComicInfo & comicInfo, QSqlDatabase & db);
|
||||
static void updateFromRemoteClient(qulonglong libraryId,const ComicInfo & comicInfo);
|
||||
static void renameLabel(qulonglong id, const QString & name, QSqlDatabase & db);
|
||||
static void renameList(qulonglong id, const QString & name, QSqlDatabase & db);
|
||||
static void reasignOrderToSublists(QList<qulonglong> ids, QSqlDatabase & db);
|
||||
static void reasignOrderToComicsInFavorites(QList<qulonglong> comicIds, QSqlDatabase & db);
|
||||
static void reasignOrderToComicsInLabel(qulonglong labelId, QList<qulonglong> comicIds, QSqlDatabase & db);
|
||||
static void reasignOrderToComicsInReadingList(qulonglong readingListId, QList<qulonglong> comicIds, QSqlDatabase & db);
|
||||
|
||||
static 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 Folder loadFolder(qulonglong id, QSqlDatabase & db);
|
||||
static Folder loadFolder(const QString & folderName, qulonglong parentId, QSqlDatabase & db);
|
||||
static ComicDB loadComic(qulonglong id, QSqlDatabase & db);
|
||||
static ComicDB loadComic(QString cname, QString cpath, QString chash, QSqlDatabase & database);
|
||||
static ComicInfo loadComicInfo(QString hash, QSqlDatabase & db);
|
||||
static QList<QString> loadSubfoldersNames(qulonglong folderId, QSqlDatabase & db);
|
||||
};
|
||||
|
||||
#endif
|
47
YACReaderLibrary/empty_container_info.cpp
Normal file
47
YACReaderLibrary/empty_container_info.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "empty_container_info.h"
|
||||
|
||||
EmptyContainerInfo::EmptyContainerInfo(QWidget *parent) :
|
||||
QWidget(parent), iconLabel(new QLabel()), titleLabel(new QLabel())
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
backgroundColor = "#FFFFFF";
|
||||
titleLabel->setStyleSheet("QLabel {color:#888888; font-size:24px;font-family:Arial;font-weight:bold;}");
|
||||
#else
|
||||
backgroundColor = "#2A2A2A";
|
||||
titleLabel->setStyleSheet("QLabel {color:#CCCCCC; font-size:24px;font-family:Arial;font-weight:bold;}");
|
||||
#endif
|
||||
|
||||
iconLabel->setAlignment(Qt::AlignCenter);
|
||||
titleLabel->setAlignment(Qt::AlignCenter);
|
||||
}
|
||||
|
||||
void EmptyContainerInfo::setPixmap(const QPixmap &pixmap)
|
||||
{
|
||||
iconLabel->setPixmap(pixmap);
|
||||
}
|
||||
|
||||
void EmptyContainerInfo::setText(const QString &text)
|
||||
{
|
||||
titleLabel->setText(text);
|
||||
}
|
||||
|
||||
QVBoxLayout * EmptyContainerInfo::setUpDefaultLayout(bool addStretch)
|
||||
{
|
||||
QVBoxLayout * layout = new QVBoxLayout;
|
||||
|
||||
layout->addSpacing(100);
|
||||
layout->addWidget(iconLabel);
|
||||
layout->addSpacing(30);
|
||||
layout->addWidget(titleLabel);
|
||||
if(addStretch)
|
||||
layout->addStretch();
|
||||
|
||||
setLayout(layout);
|
||||
return layout;
|
||||
}
|
||||
|
||||
void EmptyContainerInfo::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter painter (this);
|
||||
painter.fillRect(0,0,width(),height(),QColor(backgroundColor));
|
||||
}
|
26
YACReaderLibrary/empty_container_info.h
Normal file
26
YACReaderLibrary/empty_container_info.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef EMPTY_CONTAINER_INFO_H
|
||||
#define EMPTY_CONTAINER_INFO_H
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
class EmptyContainerInfo : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EmptyContainerInfo(QWidget *parent = 0);
|
||||
void setPixmap(const QPixmap & pixmap);
|
||||
void setText(const QString & text);
|
||||
QVBoxLayout *setUpDefaultLayout(bool addStretch);
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *);
|
||||
|
||||
QLabel * iconLabel;
|
||||
QLabel * titleLabel;
|
||||
QString backgroundColor;
|
||||
};
|
||||
|
||||
#endif // EMPTY_CONTAINER_INFO_H
|
194
YACReaderLibrary/empty_folder_widget.cpp
Normal file
194
YACReaderLibrary/empty_folder_widget.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
#include "empty_folder_widget.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QListView>
|
||||
#include <QPainter>
|
||||
#include <QStringListModel>
|
||||
|
||||
#include "comic.h"
|
||||
#include "comic_files_manager.h"
|
||||
#include "QsLog.h"
|
||||
|
||||
|
||||
|
||||
void testListView(QListView * l)
|
||||
{
|
||||
QStringListModel * slm = new QStringListModel(QStringList() << "Lorem ipsum" << "Hailer skualer"<< "Mumbaluba X" << "Finger layden" << "Pacum tactus filer" << "Aposum" << "En" << "Lorem ipsum" << "Hailer skualer" << "Mumbaluba X" << "Finger layden" << "Pacum tactus filer" << "Aposum" << "En" );
|
||||
l->setModel(slm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ListviewDelegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
ListviewDelegate() : QStyledItemDelegate() {}
|
||||
|
||||
virtual ~ListviewDelegate() {}
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
painter->save();
|
||||
|
||||
QFontMetrics fm(option.font);
|
||||
QString text = qvariant_cast<QString>(index.data(Qt::DisplayRole));
|
||||
|
||||
QRect textRect = option.rect;
|
||||
|
||||
textRect.setLeft(std::max(0, (option.rect.size().width() - fm.width(text)) / 2));
|
||||
|
||||
painter->drawText(textRect,text);
|
||||
|
||||
painter->restore();
|
||||
|
||||
//TODO add mouse hover style ??
|
||||
}
|
||||
|
||||
QSize sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index ) const
|
||||
{
|
||||
QFontMetrics fm(option.font);
|
||||
QString text = qvariant_cast<QString>(index.data(Qt::DisplayRole));
|
||||
|
||||
return QSize(fm.width(text),fm.height());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
EmptyFolderWidget::EmptyFolderWidget(QWidget *parent) :
|
||||
EmptyContainerInfo(parent),subfoldersModel(new QStringListModel())
|
||||
{
|
||||
QVBoxLayout * layout = setUpDefaultLayout(false);
|
||||
|
||||
iconLabel->setPixmap(QPixmap(":/images/empty_folder.png"));
|
||||
titleLabel->setText(tr("Subfolders in this folder"));
|
||||
|
||||
foldersView = new QListView();
|
||||
foldersView->setAttribute(Qt::WA_MacShowFocusRect,false);
|
||||
foldersView->setItemDelegate(new ListviewDelegate);
|
||||
#ifdef Q_OS_MAC
|
||||
foldersView->setStyleSheet("QListView {background-color:transparent; border: none; color:#959595; outline:0; font-size: 18px; show-decoration-selected: 0; margin:0}"
|
||||
"QListView::item:selected {background-color: #EFEFEF; color:#CCCCCC;}"
|
||||
"QListView::item:hover {background-color:#F4F4F8; color:#757575; }"
|
||||
|
||||
|
||||
"QScrollBar:vertical { border-radius:3px; background: #FFFFFF; width: 14px; margin: 0 10px 0 0; }"
|
||||
"QScrollBar::handle:vertical { border: 1px solid #999999; background: #999999; width: 14px; min-height: 20px; border-radius: 2px; }"
|
||||
"QScrollBar::add-line:vertical { border: none; background: #999999; height: 0px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}"
|
||||
|
||||
"QScrollBar::sub-line:vertical { border: none; background: #999999; height: 0px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}"
|
||||
"QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}"
|
||||
"QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}"
|
||||
|
||||
"QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {background: none; }"
|
||||
"QScrollBar:horizontal{height:0px;}"
|
||||
);
|
||||
#else
|
||||
foldersView->setStyleSheet("QListView {background-color:transparent; border: none; color:#858585; outline:0; font-size: 18px; font:bold; show-decoration-selected: 0; margin:0}"
|
||||
"QListView::item:selected {background-color: #212121; color:#CCCCCC;}"
|
||||
"QListView::item:hover {background-color:#212121; color:#CCCCCC; }"
|
||||
|
||||
|
||||
"QScrollBar:vertical { border: none; background: #212121; width: 14px; margin: 0 10px 0 0; }"
|
||||
"QScrollBar::handle:vertical { background: #858585; width: 14px; min-height: 20px; }"
|
||||
"QScrollBar::add-line:vertical { border: none; background: #212121; height: 0px; subcontrol-position: bottom; subcontrol-origin: margin; margin: 0 3px 0 0;}"
|
||||
|
||||
"QScrollBar::sub-line:vertical { border: none; background: #212121; height: 0px; subcontrol-position: top; subcontrol-origin: margin; margin: 0 3px 0 0;}"
|
||||
"QScrollBar::up-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-up.png') center top no-repeat;}"
|
||||
"QScrollBar::down-arrow:vertical {border:none;width: 9px;height: 6px;background: url(':/images/folders_view/line-down.png') center top no-repeat;}"
|
||||
|
||||
"QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {background: none; }"
|
||||
"QScrollBar:horizontal{height:0px;}"
|
||||
);
|
||||
|
||||
#endif
|
||||
foldersView->setSizePolicy(QSizePolicy ::Expanding , QSizePolicy ::Expanding );
|
||||
|
||||
layout->addSpacing(12);
|
||||
layout->addWidget(foldersView,1);
|
||||
layout->addStretch();
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
setContentsMargins(0,0,0,0);
|
||||
|
||||
setStyleSheet(QString("QWidget {background:%1}").arg(backgroundColor));
|
||||
|
||||
setSizePolicy(QSizePolicy ::Expanding , QSizePolicy ::Expanding );
|
||||
|
||||
setAcceptDrops(true);
|
||||
|
||||
connect(foldersView,SIGNAL(clicked(QModelIndex)),this,SLOT(onItemClicked(QModelIndex)));
|
||||
}
|
||||
|
||||
void EmptyFolderWidget::setSubfolders(const QModelIndex &mi, const QStringList &foldersNames)
|
||||
{
|
||||
parent = mi;
|
||||
subfoldersModel->setStringList(foldersNames);
|
||||
foldersView->setModel(subfoldersModel);
|
||||
|
||||
if(foldersNames.isEmpty())
|
||||
{
|
||||
titleLabel->setText(tr("Empty folder") + QString("<p style='color:rgb(150,150,150);font-size:14px;font-weight:normal;'>%1</p>").arg(tr("Drag and drop folders and comics here")));
|
||||
}
|
||||
else
|
||||
{
|
||||
titleLabel->setText(tr("Subfolders in this folder"));
|
||||
}
|
||||
}
|
||||
|
||||
void EmptyFolderWidget::onItemClicked(const QModelIndex &mi)
|
||||
{
|
||||
emit subfolderSelected(parent,mi.row());
|
||||
}
|
||||
|
||||
//TODO remove repeated code in drag & drop support....
|
||||
void EmptyFolderWidget::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
QList<QUrl> urlList;
|
||||
|
||||
if (event->mimeData()->hasUrls() && event->dropAction() == Qt::CopyAction)
|
||||
{
|
||||
urlList = event->mimeData()->urls();
|
||||
QString currentPath;
|
||||
foreach (QUrl url, urlList)
|
||||
{
|
||||
//comics or folders are accepted, folders' content is validate in dropEvent (avoid any lag before droping)
|
||||
currentPath = url.toLocalFile();
|
||||
if(Comic::fileIsComic(currentPath) || QFileInfo(currentPath).isDir())
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EmptyFolderWidget::dropEvent(QDropEvent *event)
|
||||
{
|
||||
QLOG_DEBUG() << "drop in emptyfolder" << event->dropAction();
|
||||
|
||||
bool validAction = event->dropAction() == Qt::CopyAction; // || event->dropAction() & Qt::MoveAction; TODO move
|
||||
|
||||
if(validAction)
|
||||
{
|
||||
|
||||
QList<QPair<QString, QString> > droppedFiles = ComicFilesManager::getDroppedFiles(event->mimeData()->urls());
|
||||
|
||||
if(event->dropAction() == Qt::CopyAction)
|
||||
{
|
||||
QLOG_DEBUG() << "copy in emptyfolder:" << droppedFiles;
|
||||
emit copyComicsToCurrentFolder(droppedFiles);
|
||||
}
|
||||
else if(event->dropAction() & Qt::MoveAction)
|
||||
{
|
||||
QLOG_DEBUG() << "move in emptyfolder:" << droppedFiles;
|
||||
emit moveComicsToCurrentFolder(droppedFiles);
|
||||
}
|
||||
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
36
YACReaderLibrary/empty_folder_widget.h
Normal file
36
YACReaderLibrary/empty_folder_widget.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef EMPTY_FOLDER_WIDGET_H
|
||||
#define EMPTY_FOLDER_WIDGET_H
|
||||
|
||||
#include "empty_container_info.h"
|
||||
#include <QtWidgets>
|
||||
|
||||
|
||||
|
||||
class EmptyFolderWidget : public EmptyContainerInfo
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EmptyFolderWidget(QWidget *parent = 0);
|
||||
void setSubfolders(const QModelIndex & mi, const QStringList & foldersNames);
|
||||
signals:
|
||||
void subfolderSelected(QModelIndex, int);
|
||||
|
||||
//Drops
|
||||
void copyComicsToCurrentFolder(QList<QPair<QString, QString> >);
|
||||
void moveComicsToCurrentFolder(QList<QPair<QString, QString> >);
|
||||
|
||||
public slots:
|
||||
void onItemClicked(const QModelIndex & mi);
|
||||
|
||||
protected:
|
||||
QListView * foldersView;
|
||||
QModelIndex parent;
|
||||
QStringListModel * subfoldersModel;
|
||||
QString backgroundColor;
|
||||
|
||||
//Drop to import
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dropEvent(QDropEvent *event);
|
||||
};
|
||||
|
||||
#endif // EMPTY_FOLDER_WIDGET_H
|
21
YACReaderLibrary/empty_label_widget.cpp
Normal file
21
YACReaderLibrary/empty_label_widget.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "empty_label_widget.h"
|
||||
|
||||
EmptyLabelWidget::EmptyLabelWidget(QWidget *parent) :
|
||||
EmptyContainerInfo(parent)
|
||||
{
|
||||
setUpDefaultLayout(true);
|
||||
|
||||
iconLabel->setPixmap(QPixmap(":/images/empty_label.png"));
|
||||
|
||||
//titleLabel->setText(tr("This label doesn't contain comics yet") + QString("<p style='color:rgb(150,150,150);font-size:14px;font-weight:normal;'>%1</p>").arg(tr("Drag and drop folders and comics here")));
|
||||
titleLabel->setText(tr("This label doesn't contain comics yet"));
|
||||
}
|
||||
|
||||
void EmptyLabelWidget::setColor(YACReader::LabelColors color)
|
||||
{
|
||||
QPixmap p(":/images/empty_label.png");
|
||||
QImage img = p.toImage().convertToFormat(QImage::Format_ARGB32);
|
||||
QColor destColor(YACReader::labelColorToRGBString(color));
|
||||
YACReader::colorize(img,destColor);
|
||||
iconLabel->setPixmap(QPixmap::fromImage(img));
|
||||
}
|
22
YACReaderLibrary/empty_label_widget.h
Normal file
22
YACReaderLibrary/empty_label_widget.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef EMPTY_LABEL_WIDGET_H
|
||||
#define EMPTY_LABEL_WIDGET_H
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "empty_container_info.h"
|
||||
#include "yacreader_global_gui.h"
|
||||
|
||||
class EmptyLabelWidget : public EmptyContainerInfo
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EmptyLabelWidget(QWidget *parent = 0);
|
||||
void setColor(YACReader::LabelColors color);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // EMPTY_LABEL_WIDGET_H
|
9
YACReaderLibrary/empty_reading_list_widget.cpp
Normal file
9
YACReaderLibrary/empty_reading_list_widget.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
#include "empty_reading_list_widget.h"
|
||||
|
||||
EmptyReadingListWidget::EmptyReadingListWidget(QWidget *parent)
|
||||
:EmptyContainerInfo(parent)
|
||||
{
|
||||
setUpDefaultLayout(true);
|
||||
setPixmap(QPixmap(":/images/empty_reading_list"));
|
||||
setText(tr("This reading list doesn't cotain comics yet"));
|
||||
}
|
13
YACReaderLibrary/empty_reading_list_widget.h
Normal file
13
YACReaderLibrary/empty_reading_list_widget.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef EMPTY_READING_LIST_WIDGET_H
|
||||
#define EMPTY_READING_LIST_WIDGET_H
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "empty_container_info.h"
|
||||
|
||||
class EmptyReadingListWidget : public EmptyContainerInfo
|
||||
{
|
||||
public:
|
||||
EmptyReadingListWidget(QWidget * parent = 0);
|
||||
};
|
||||
|
||||
#endif // EMPTY_READING_LIST_WIDGET_H
|
7
YACReaderLibrary/empty_special_list.cpp
Normal file
7
YACReaderLibrary/empty_special_list.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "empty_special_list.h"
|
||||
|
||||
EmptySpecialListWidget::EmptySpecialListWidget(QWidget *parent)
|
||||
:EmptyContainerInfo(parent)
|
||||
{
|
||||
setUpDefaultLayout(true);
|
||||
}
|
13
YACReaderLibrary/empty_special_list.h
Normal file
13
YACReaderLibrary/empty_special_list.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef EMPTY_SPECIAL_LIST_H
|
||||
#define EMPTY_SPECIAL_LIST_H
|
||||
|
||||
#include <QtWidgets>
|
||||
#include "empty_container_info.h"
|
||||
|
||||
class EmptySpecialListWidget : public EmptyContainerInfo
|
||||
{
|
||||
public:
|
||||
EmptySpecialListWidget(QWidget * parent = 0);
|
||||
};
|
||||
|
||||
#endif // EMPTY_SPECIAL_LIST_H
|
92
YACReaderLibrary/export_comics_info_dialog.cpp
Normal file
92
YACReaderLibrary/export_comics_info_dialog.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include "export_comics_info_dialog.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QFileDialog>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "data_base_management.h"
|
||||
|
||||
ExportComicsInfoDialog::ExportComicsInfoDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
textLabel = new QLabel(tr("Output file : "));
|
||||
path = new QLineEdit;
|
||||
textLabel->setBuddy(path);
|
||||
|
||||
accept = new QPushButton(tr("Create"));
|
||||
accept->setDisabled(true);
|
||||
connect(accept,SIGNAL(clicked()),this,SLOT(exportComicsInfo()));
|
||||
|
||||
cancel = new QPushButton(tr("Cancel"));
|
||||
connect(cancel,SIGNAL(clicked()),this,SLOT(close()));
|
||||
connect(cancel,SIGNAL(clicked()),this,SIGNAL(rejected()));
|
||||
|
||||
find = new QPushButton(QIcon(":/images/find_folder.png"),"");
|
||||
connect(find,SIGNAL(clicked()),this,SLOT(findPath()));
|
||||
|
||||
QHBoxLayout *libraryLayout = new QHBoxLayout;
|
||||
|
||||
libraryLayout->addWidget(textLabel);
|
||||
libraryLayout->addWidget(path);
|
||||
libraryLayout->addWidget(find);
|
||||
libraryLayout->setStretchFactor(find,0); //TODO
|
||||
|
||||
QHBoxLayout *bottomLayout = new QHBoxLayout;
|
||||
bottomLayout->addStretch();
|
||||
bottomLayout->addWidget(accept);
|
||||
bottomLayout->addWidget(cancel);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(libraryLayout);
|
||||
mainLayout->addWidget(progress=new QLabel());
|
||||
mainLayout->addStretch();
|
||||
mainLayout->addLayout(bottomLayout);
|
||||
|
||||
QHBoxLayout * imgMainLayout = new QHBoxLayout;
|
||||
QLabel * imgLabel = new QLabel(this);
|
||||
QPixmap p(":/images/exportComicsInfo.png");
|
||||
imgLabel->setPixmap(p);
|
||||
imgMainLayout->addWidget(imgLabel);
|
||||
imgMainLayout->addLayout(mainLayout);
|
||||
|
||||
setLayout(imgMainLayout);
|
||||
|
||||
setModal(true);
|
||||
setWindowTitle(tr("Export comics info"));
|
||||
}
|
||||
|
||||
ExportComicsInfoDialog::~ExportComicsInfoDialog()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ExportComicsInfoDialog::findPath()
|
||||
{
|
||||
QString s = QFileDialog::getSaveFileName(this,tr("Destination database name"),".","*.ydb");
|
||||
if(!s.isEmpty())
|
||||
{
|
||||
path->setText(s);
|
||||
accept->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ExportComicsInfoDialog::exportComicsInfo()
|
||||
{
|
||||
QFileInfo f(path->text());
|
||||
QFileInfo fPath(f.absoluteDir().path());
|
||||
if(fPath.exists() && fPath.isDir() && fPath.isWritable())
|
||||
{
|
||||
DataBaseManagement::exportComicsInfo(source,path->text());
|
||||
close();
|
||||
}
|
||||
else
|
||||
QMessageBox::critical(NULL,tr("Problem found while writing"),tr("The selected path for the output file does not exist or is not a valid path. Be sure that you have write access to this folder"));
|
||||
}
|
||||
|
||||
void ExportComicsInfoDialog::close()
|
||||
{
|
||||
path->clear();
|
||||
QDialog::close();
|
||||
}
|
35
YACReaderLibrary/export_comics_info_dialog.h
Normal file
35
YACReaderLibrary/export_comics_info_dialog.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef EXPORT_COMICS_INFO_DIALOG_H
|
||||
#define EXPORT_COMICS_INFO_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
|
||||
|
||||
class ExportComicsInfoDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ExportComicsInfoDialog(QWidget *parent = 0);
|
||||
~ExportComicsInfoDialog();
|
||||
QString source;
|
||||
|
||||
public slots:
|
||||
void findPath();
|
||||
void exportComicsInfo();
|
||||
void close();
|
||||
|
||||
private:
|
||||
QLabel * progress;
|
||||
QLabel * textLabel;
|
||||
QLineEdit * path;
|
||||
QPushButton * find;
|
||||
QPushButton * accept;
|
||||
QPushButton * cancel;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // EXPORT_COMICS_INFO_DIALOG_H
|
100
YACReaderLibrary/export_library_dialog.cpp
Normal file
100
YACReaderLibrary/export_library_dialog.cpp
Normal file
@ -0,0 +1,100 @@
|
||||
#include "export_library_dialog.h"
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QDir>
|
||||
|
||||
ExportLibraryDialog::ExportLibraryDialog(QWidget * parent)
|
||||
:QDialog(parent),progressCount(0)
|
||||
{
|
||||
textLabel = new QLabel(tr("Output folder : "));
|
||||
path = new QLineEdit;
|
||||
textLabel->setBuddy(path);
|
||||
|
||||
accept = new QPushButton(tr("Create"));
|
||||
accept->setDisabled(true);
|
||||
connect(accept,SIGNAL(clicked()),this,SLOT(exportLibrary()));
|
||||
|
||||
cancel = new QPushButton(tr("Cancel"));
|
||||
connect(cancel,SIGNAL(clicked()),this,SLOT(close()));
|
||||
connect(cancel,SIGNAL(clicked()),this,SIGNAL(rejected()));
|
||||
|
||||
find = new QPushButton(QIcon(":/images/find_folder.png"),"");
|
||||
connect(find,SIGNAL(clicked()),this,SLOT(findPath()));
|
||||
|
||||
QHBoxLayout *libraryLayout = new QHBoxLayout;
|
||||
|
||||
libraryLayout->addWidget(textLabel);
|
||||
libraryLayout->addWidget(path);
|
||||
libraryLayout->addWidget(find);
|
||||
libraryLayout->setStretchFactor(find,0); //TODO
|
||||
|
||||
QHBoxLayout *bottomLayout = new QHBoxLayout;
|
||||
bottomLayout->addStretch();
|
||||
bottomLayout->addWidget(accept);
|
||||
bottomLayout->addWidget(cancel);
|
||||
|
||||
progressBar = new QProgressBar(this);
|
||||
progressBar->setMinimum(0);
|
||||
progressBar->setMaximum(0);
|
||||
progressBar->setTextVisible(false);
|
||||
progressBar->hide();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(libraryLayout);
|
||||
mainLayout->addStretch();
|
||||
mainLayout->addWidget(progressBar);
|
||||
mainLayout->addLayout(bottomLayout);
|
||||
|
||||
QHBoxLayout * imgMainLayout = new QHBoxLayout;
|
||||
QLabel * imgLabel = new QLabel(this);
|
||||
QPixmap p(":/images/exportLibrary.png");
|
||||
imgLabel->setPixmap(p);
|
||||
imgMainLayout->addWidget(imgLabel);
|
||||
imgMainLayout->addLayout(mainLayout);
|
||||
|
||||
setLayout(imgMainLayout);
|
||||
|
||||
setModal(true);
|
||||
setWindowTitle(tr("Create covers package"));
|
||||
}
|
||||
|
||||
void ExportLibraryDialog::exportLibrary()
|
||||
{
|
||||
QFileInfo f(path->text());
|
||||
if(f.exists() && f.isDir() && f.isWritable())
|
||||
{
|
||||
progressBar->show();
|
||||
accept->setEnabled(false);
|
||||
emit exportPath(QDir::cleanPath(path->text()));
|
||||
}
|
||||
else
|
||||
QMessageBox::critical(NULL,tr("Problem found while writing"),tr("The selected path for the output file does not exist or is not a valid path. Be sure that you have write access to this folder"));
|
||||
|
||||
}
|
||||
|
||||
void ExportLibraryDialog::findPath()
|
||||
{
|
||||
QString s = QFileDialog::getExistingDirectory(0,tr("Destination directory"),".");
|
||||
if(!s.isEmpty())
|
||||
{
|
||||
path->setText(s);
|
||||
accept->setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ExportLibraryDialog::close()
|
||||
{
|
||||
path->clear();
|
||||
progressBar->hide();
|
||||
accept->setEnabled(false);
|
||||
progressCount=0;
|
||||
QDialog::close();
|
||||
}
|
||||
|
||||
void ExportLibraryDialog::run()
|
||||
{
|
||||
|
||||
}
|
||||
|
35
YACReaderLibrary/export_library_dialog.h
Normal file
35
YACReaderLibrary/export_library_dialog.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef EXPORT_LIBRARY_DIALOG_H
|
||||
#define EXPORT_LIBRARY_DIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QProgressBar>
|
||||
|
||||
class ExportLibraryDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ExportLibraryDialog(QWidget * parent = 0);
|
||||
public slots:
|
||||
void exportLibrary();
|
||||
void findPath();
|
||||
void close();
|
||||
private:
|
||||
int progressCount;
|
||||
QProgressBar *progressBar;
|
||||
QLabel * textLabel;
|
||||
QLineEdit * path;
|
||||
QPushButton * find;
|
||||
QPushButton * accept;
|
||||
QPushButton * cancel;
|
||||
void run();
|
||||
signals:
|
||||
void exportPath(QString);
|
||||
};
|
||||
|
||||
#endif
|
12
YACReaderLibrary/files.qrc
Normal file
12
YACReaderLibrary/files.qrc
Normal file
@ -0,0 +1,12 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>../files/about.html</file>
|
||||
<file>../files/helpYACReaderLibrary.html</file>
|
||||
</qresource>
|
||||
|
||||
<qresource lang="es_ES">
|
||||
<file alias="/files/about.html">../files/about_es_ES.html</file>
|
||||
<file alias="/files/helpYACReaderLibrary.html">../files/helpYACReaderLibrary_es_ES.html</file>
|
||||
</qresource>
|
||||
|
||||
</RCC>
|
484
YACReaderLibrary/grid_comics_view.cpp
Normal file
484
YACReaderLibrary/grid_comics_view.cpp
Normal file
@ -0,0 +1,484 @@
|
||||
#include "grid_comics_view.h"
|
||||
|
||||
#include <QtQuick>
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "comic.h"
|
||||
#include "comic_files_manager.h"
|
||||
#include "QsLog.h"
|
||||
#include "yacreader_global.h"
|
||||
#include "yacreader_tool_bar_stretch.h"
|
||||
|
||||
//values relative to visible cells
|
||||
const unsigned int YACREADER_MIN_GRID_ZOOM_WIDTH = 156;
|
||||
const unsigned int YACREADER_MAX_GRID_ZOOM_WIDTH = 312;
|
||||
|
||||
//GridView cells
|
||||
const unsigned int YACREADER_MIN_CELL_CUSTOM_HEIGHT = 295;
|
||||
const unsigned int YACREADER_MIN_CELL_CUSTOM_WIDTH = 185;
|
||||
|
||||
//Covers
|
||||
const unsigned int YACREADER_MAX_COVER_HEIGHT = 236;
|
||||
const unsigned int YACREADER_MIN_COVER_WIDTH = YACREADER_MIN_GRID_ZOOM_WIDTH;
|
||||
|
||||
//visible cells (realCell in qml), grid cells size is used to create faux inner margings
|
||||
const unsigned int YACREADER_MIN_ITEM_HEIGHT = YACREADER_MAX_COVER_HEIGHT + 51; //51 is the height of the bottom rectangle used for title and other info
|
||||
const unsigned int YACREADER_MIN_ITEM_WIDTH = YACREADER_MIN_COVER_WIDTH;
|
||||
|
||||
|
||||
GridComicsView::GridComicsView(QWidget *parent) :
|
||||
ComicsView(parent),_selectionModel(NULL)
|
||||
{
|
||||
settings = new QSettings(YACReader::getSettingsPath()+"/YACReaderLibrary.ini", QSettings::IniFormat, this);
|
||||
settings->beginGroup("libraryConfig");
|
||||
|
||||
qmlRegisterType<ComicModel>("comicModel",1,0,"TableModel");
|
||||
|
||||
view = new QQuickView();
|
||||
container = QWidget::createWindowContainer(view, this);
|
||||
|
||||
container->setMinimumSize(200, 200);
|
||||
container->setFocusPolicy(Qt::TabFocus);
|
||||
|
||||
createCoverSizeSliderWidget();
|
||||
|
||||
int coverSize = settings->value(COMICS_GRID_COVER_SIZES, YACREADER_MIN_COVER_WIDTH).toInt();
|
||||
|
||||
coverSizeSlider->setValue(coverSize);
|
||||
setCoversSize(coverSize);
|
||||
|
||||
QQmlContext *ctxt = view->rootContext();
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
ctxt->setContextProperty("backgroundColor", "#F6F6F6");
|
||||
ctxt->setContextProperty("cellColor", "#FFFFFF");
|
||||
ctxt->setContextProperty("selectedColor", "#FFFFFF");
|
||||
ctxt->setContextProperty("selectedBorderColor", "#007AFF");
|
||||
ctxt->setContextProperty("borderColor", "#DBDBDB");
|
||||
ctxt->setContextProperty("titleColor", "#121212");
|
||||
ctxt->setContextProperty("textColor", "#636363");
|
||||
//fonts settings
|
||||
ctxt->setContextProperty("fontSize", 11);
|
||||
ctxt->setContextProperty("fontFamily", QApplication::font().family());
|
||||
ctxt->setContextProperty("fontSpacing", 0.5);
|
||||
|
||||
#else
|
||||
ctxt->setContextProperty("backgroundColor", "#2A2A2A");
|
||||
ctxt->setContextProperty("cellColor", "#212121");
|
||||
ctxt->setContextProperty("selectedColor", "#121212");
|
||||
ctxt->setContextProperty("selectedBorderColor", "#121212");
|
||||
ctxt->setContextProperty("borderColor", "#121212");
|
||||
ctxt->setContextProperty("titleColor", "#FFFFFF");
|
||||
ctxt->setContextProperty("textColor", "#A8A8A8");
|
||||
ctxt->setContextProperty("dropShadow",false);
|
||||
//fonts settings
|
||||
int fontSize = QApplication::font().pointSize();
|
||||
if(fontSize == -1)
|
||||
fontSize = QApplication::font().pixelSize();
|
||||
ctxt->setContextProperty("fontSize", fontSize);
|
||||
ctxt->setContextProperty("fontFamily", QApplication::font().family());
|
||||
ctxt->setContextProperty("fontSpacing", 0.5);
|
||||
#endif
|
||||
|
||||
ctxt->setContextProperty("backgroundImage", QUrl());
|
||||
ctxt->setContextProperty("backgroundBlurOpacity", 0.0);
|
||||
ctxt->setContextProperty("backgroundBlurRadius", 0.0);
|
||||
ctxt->setContextProperty("backgroundBlurVisible", false);
|
||||
|
||||
ComicModel *model = new ComicModel();
|
||||
QItemSelectionModel *selectionModel = new QItemSelectionModel(model);
|
||||
ctxt->setContextProperty("comicsList", model);
|
||||
ctxt->setContextProperty("comicsSelection", selectionModel);
|
||||
ctxt->setContextProperty("contextMenuHelper",this);
|
||||
ctxt->setContextProperty("comicsSelectionHelper", this);
|
||||
ctxt->setContextProperty("comicRatingHelper", this);
|
||||
ctxt->setContextProperty("dummyValue", true);
|
||||
ctxt->setContextProperty("dragManager", this);
|
||||
ctxt->setContextProperty("dropManager", this);
|
||||
|
||||
view->setSource(QUrl("qrc:/qml/GridComicsView.qml"));
|
||||
|
||||
|
||||
setShowMarks(true);//TODO save this in settings
|
||||
|
||||
QVBoxLayout * l = new QVBoxLayout;
|
||||
l->addWidget(container);
|
||||
this->setLayout(l);
|
||||
|
||||
setContentsMargins(0,0,0,0);
|
||||
l->setContentsMargins(0,0,0,0);
|
||||
l->setSpacing(0);
|
||||
|
||||
QLOG_TRACE() << "GridComicsView";
|
||||
}
|
||||
|
||||
GridComicsView::~GridComicsView()
|
||||
{
|
||||
delete view;
|
||||
}
|
||||
|
||||
void GridComicsView::createCoverSizeSliderWidget()
|
||||
{
|
||||
toolBarStretch = new YACReaderToolBarStretch(this);
|
||||
coverSizeSliderWidget = new QWidget(this);
|
||||
coverSizeSliderWidget->setFixedWidth(200);
|
||||
coverSizeSlider = new QSlider();
|
||||
coverSizeSlider->setOrientation(Qt::Horizontal);
|
||||
coverSizeSlider->setRange(YACREADER_MIN_GRID_ZOOM_WIDTH, YACREADER_MAX_GRID_ZOOM_WIDTH);
|
||||
|
||||
QHBoxLayout * horizontalLayout = new QHBoxLayout();
|
||||
QLabel * smallLabel = new QLabel();
|
||||
smallLabel->setPixmap(QPixmap(":/images/comics_view_toolbar/small_size_grid_zoom.png"));
|
||||
horizontalLayout->addWidget(smallLabel);
|
||||
horizontalLayout->addWidget(coverSizeSlider, 0, Qt::AlignVCenter);
|
||||
QLabel * bigLabel = new QLabel();
|
||||
bigLabel->setPixmap(QPixmap(":/images/comics_view_toolbar/big_size_grid_zoom.png"));
|
||||
horizontalLayout->addWidget(bigLabel);
|
||||
horizontalLayout->addSpacing(10);
|
||||
horizontalLayout->setMargin(0);
|
||||
|
||||
coverSizeSliderWidget->setLayout(horizontalLayout);
|
||||
//TODO add shortcuts (ctrl-+ and ctrl-- for zooming in out, + ctrl-0 for reseting the zoom)
|
||||
|
||||
connect(coverSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setCoversSize(int)));
|
||||
}
|
||||
|
||||
void GridComicsView::setToolBar(QToolBar *toolBar)
|
||||
{
|
||||
static_cast<QVBoxLayout *>(this->layout())->insertWidget(1,toolBar);
|
||||
this->toolbar = toolBar;
|
||||
|
||||
toolBarStretchAction = toolBar->addWidget(toolBarStretch);
|
||||
coverSizeSliderAction = toolBar->addWidget(coverSizeSliderWidget);
|
||||
}
|
||||
|
||||
void GridComicsView::setModel(ComicModel *model)
|
||||
{
|
||||
if(model == NULL)
|
||||
return;
|
||||
|
||||
ComicsView::setModel(model);
|
||||
|
||||
QQmlContext *ctxt = view->rootContext();
|
||||
|
||||
if(_selectionModel != NULL)
|
||||
delete _selectionModel;
|
||||
|
||||
_selectionModel = new QItemSelectionModel(model);
|
||||
|
||||
//TODO fix crash in the following line on comics views switch
|
||||
ctxt->setContextProperty("comicsList", model);
|
||||
ctxt->setContextProperty("comicsSelection", _selectionModel);
|
||||
ctxt->setContextProperty("contextMenuHelper",this);
|
||||
ctxt->setContextProperty("comicsSelectionHelper", this);
|
||||
ctxt->setContextProperty("comicRatingHelper", this);
|
||||
ctxt->setContextProperty("dummyValue", true);
|
||||
ctxt->setContextProperty("dragManager", this);
|
||||
ctxt->setContextProperty("dropManager", this);
|
||||
|
||||
updateBackgroundConfig();
|
||||
|
||||
if(model->rowCount()>0)
|
||||
setCurrentIndex(model->index(0,0));
|
||||
}
|
||||
|
||||
void GridComicsView::updateBackgroundConfig()
|
||||
{
|
||||
if(this->model == NULL)
|
||||
return;
|
||||
|
||||
QQmlContext *ctxt = view->rootContext();
|
||||
|
||||
//backgroun image configuration
|
||||
bool useBackgroundImage = settings->value(USE_BACKGROUND_IMAGE_IN_GRID_VIEW, true).toBool();
|
||||
|
||||
if(useBackgroundImage)
|
||||
{
|
||||
float opacity = settings->value(OPACITY_BACKGROUND_IMAGE_IN_GRID_VIEW, 0.2).toFloat();
|
||||
float blurRadius = settings->value(BLUR_RADIUS_BACKGROUND_IMAGE_IN_GRID_VIEW, 75).toInt();
|
||||
|
||||
int row = settings->value(USE_SELECTED_COMIC_COVER_AS_BACKGROUND_IMAGE_IN_GRID_VIEW, false).toBool() ? currentIndex().row() : 0;
|
||||
|
||||
ctxt->setContextProperty("backgroundImage", this->model->data(this->model->index(row, 0), ComicModel::CoverPathRole));
|
||||
ctxt->setContextProperty("backgroundBlurOpacity", opacity);
|
||||
ctxt->setContextProperty("backgroundBlurRadius", blurRadius);
|
||||
ctxt->setContextProperty("backgroundBlurVisible", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctxt->setContextProperty("backgroundImage", QUrl());
|
||||
ctxt->setContextProperty("backgroundBlurOpacity", 0.0);
|
||||
ctxt->setContextProperty("backgroundBlurRadius", 0.0);
|
||||
ctxt->setContextProperty("backgroundBlurVisible", false);
|
||||
}
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
ctxt->setContextProperty("cellColor", useBackgroundImage?"#99FFFFFF":"#FFFFFF");
|
||||
ctxt->setContextProperty("selectedColor", "#FFFFFF");
|
||||
#else
|
||||
ctxt->setContextProperty("cellColor", useBackgroundImage?"#99212121":"#212121");
|
||||
ctxt->setContextProperty("selectedColor", "#121212");
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridComicsView::setCurrentIndex(const QModelIndex &index)
|
||||
{
|
||||
_selectionModel->clear();
|
||||
_selectionModel->select(index, QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
view->rootContext()->setContextProperty("dummyValue", true);
|
||||
|
||||
if(settings->value(USE_SELECTED_COMIC_COVER_AS_BACKGROUND_IMAGE_IN_GRID_VIEW, false).toBool())
|
||||
updateBackgroundConfig();
|
||||
}
|
||||
|
||||
QModelIndex GridComicsView::currentIndex()
|
||||
{
|
||||
|
||||
if(!_selectionModel)
|
||||
return QModelIndex();
|
||||
|
||||
QModelIndexList indexes = _selectionModel->selectedRows();
|
||||
if(indexes.length()>0)
|
||||
return indexes[0];
|
||||
|
||||
this->selectIndex(0);
|
||||
indexes = _selectionModel->selectedRows();
|
||||
if(indexes.length()>0)
|
||||
return indexes[0];
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QItemSelectionModel *GridComicsView::selectionModel()
|
||||
{
|
||||
QModelIndexList indexes = _selectionModel->selectedRows();
|
||||
if(indexes.length()==0)
|
||||
this->selectIndex(0);
|
||||
|
||||
return _selectionModel;
|
||||
}
|
||||
|
||||
void GridComicsView::scrollTo(const QModelIndex &mi, QAbstractItemView::ScrollHint hint)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GridComicsView::toFullScreen()
|
||||
{
|
||||
toolbar->hide();
|
||||
}
|
||||
|
||||
void GridComicsView::toNormal()
|
||||
{
|
||||
toolbar->show();
|
||||
}
|
||||
|
||||
void GridComicsView::updateConfig(QSettings *settings)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GridComicsView::enableFilterMode(bool enabled)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GridComicsView::selectAll()
|
||||
{
|
||||
QModelIndex top = model->index(0, 0);
|
||||
QModelIndex bottom = model->index(model->rowCount()-1, 0);
|
||||
QItemSelection selection(top, bottom);
|
||||
_selectionModel->select(selection, QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
view->rootContext()->setContextProperty("dummyValue", true);
|
||||
}
|
||||
|
||||
void GridComicsView::rate(int index, int rating)
|
||||
{
|
||||
model->updateRating(rating,model->index(index,0));
|
||||
}
|
||||
|
||||
void GridComicsView::requestedContextMenu(const QPoint &point)
|
||||
{
|
||||
emit customContextMenuViewRequested(point);
|
||||
}
|
||||
|
||||
void GridComicsView::setCoversSize(int width)
|
||||
{
|
||||
QQmlContext *ctxt = view->rootContext();
|
||||
|
||||
QQuickItem * grid = view->rootObject()->findChild<QQuickItem *>(QStringLiteral("grid"));
|
||||
|
||||
if(grid != 0)
|
||||
{
|
||||
QVariant cellCustomWidth = (width * YACREADER_MIN_CELL_CUSTOM_WIDTH) / YACREADER_MIN_GRID_ZOOM_WIDTH;
|
||||
QMetaObject::invokeMethod(grid, "calculateCellWidths",
|
||||
Q_ARG(QVariant, cellCustomWidth));
|
||||
}
|
||||
|
||||
int cellBottomMarging = 8 * (1 + 2*(1 - (float(YACREADER_MAX_GRID_ZOOM_WIDTH - width) / (YACREADER_MAX_GRID_ZOOM_WIDTH - YACREADER_MIN_GRID_ZOOM_WIDTH))) );
|
||||
|
||||
ctxt->setContextProperty("cellCustomHeight", ((width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH) + 51 + cellBottomMarging);
|
||||
ctxt->setContextProperty("cellCustomWidth", (width * YACREADER_MIN_CELL_CUSTOM_WIDTH) / YACREADER_MIN_COVER_WIDTH );
|
||||
|
||||
ctxt->setContextProperty("itemWidth", width);
|
||||
ctxt->setContextProperty("itemHeight", ((width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH) + 51);
|
||||
|
||||
ctxt->setContextProperty("coverWidth", width);
|
||||
ctxt->setContextProperty("coverHeight", (width * YACREADER_MAX_COVER_HEIGHT) / YACREADER_MIN_COVER_WIDTH);
|
||||
}
|
||||
|
||||
QSize GridComicsView::sizeHint()
|
||||
{
|
||||
return QSize(1280,768);
|
||||
}
|
||||
|
||||
QByteArray GridComicsView::getMimeDataFromSelection()
|
||||
{
|
||||
QByteArray data;
|
||||
|
||||
QMimeData * mimeData = model->mimeData(_selectionModel->selectedIndexes());
|
||||
data = mimeData->data(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat);
|
||||
|
||||
delete mimeData;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void GridComicsView::startDrag()
|
||||
{
|
||||
QDrag *drag = new QDrag(this);
|
||||
drag->setMimeData(model->mimeData(_selectionModel->selectedRows()));
|
||||
drag->setPixmap(QPixmap(":/images/comics_view_toolbar/openInYACReader.png")); //TODO add better image
|
||||
|
||||
/*Qt::DropAction dropAction =*/ drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction);
|
||||
}
|
||||
|
||||
bool GridComicsView::canDropUrls(const QList<QUrl> &urls, Qt::DropAction action)
|
||||
{
|
||||
if(action == Qt::CopyAction)
|
||||
{
|
||||
QString currentPath;
|
||||
foreach (QUrl url, urls)
|
||||
{
|
||||
//comics or folders are accepted, folders' content is validate in dropEvent (avoid any lag before droping)
|
||||
currentPath = url.toLocalFile();
|
||||
if(Comic::fileIsComic(currentPath) || QFileInfo(currentPath).isDir())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GridComicsView::canDropFormats(const QString &formats)
|
||||
{
|
||||
return (formats.contains(YACReader::YACReaderLibrarComiscSelectionMimeDataFormat) && model->canBeResorted());
|
||||
}
|
||||
|
||||
void GridComicsView::droppedFiles(const QList<QUrl> &urls, Qt::DropAction action)
|
||||
{
|
||||
bool validAction = action == Qt::CopyAction; //TODO add move
|
||||
|
||||
if(validAction)
|
||||
{
|
||||
QList<QPair<QString, QString> > droppedFiles = ComicFilesManager::getDroppedFiles(urls);
|
||||
emit copyComicsToCurrentFolder(droppedFiles);
|
||||
}
|
||||
}
|
||||
|
||||
void GridComicsView::droppedComicsForResortingAt(const QString &data, int index)
|
||||
{
|
||||
model->dropMimeData(model->mimeData(_selectionModel->selectedRows()), Qt::MoveAction, index, 0, QModelIndex());
|
||||
}
|
||||
|
||||
//helper
|
||||
void GridComicsView::selectIndex(int index)
|
||||
{
|
||||
if(_selectionModel != NULL && model!=NULL)
|
||||
{
|
||||
_selectionModel->select(model->index(index,0),QItemSelectionModel::Select | QItemSelectionModel::Rows);
|
||||
view->rootContext()->setContextProperty("dummyValue", true);
|
||||
}
|
||||
}
|
||||
|
||||
void GridComicsView::setCurrentIndex(int index)
|
||||
{
|
||||
setCurrentIndex(model->index(index,0));
|
||||
}
|
||||
|
||||
void GridComicsView::deselectIndex(int index)
|
||||
{
|
||||
if(_selectionModel != NULL && model!=NULL)
|
||||
{
|
||||
_selectionModel->select(model->index(index,0),QItemSelectionModel::Deselect | QItemSelectionModel::Rows);
|
||||
view->rootContext()->setContextProperty("dummyValue", true);
|
||||
}
|
||||
}
|
||||
|
||||
bool GridComicsView::isSelectedIndex(int index)
|
||||
{
|
||||
if(_selectionModel != NULL && model!=NULL)
|
||||
{
|
||||
QModelIndex mi = model->index(index,0);
|
||||
return _selectionModel->isSelected(mi);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GridComicsView::clear()
|
||||
{
|
||||
if(_selectionModel != NULL)
|
||||
{
|
||||
_selectionModel->clear();
|
||||
|
||||
QQmlContext *ctxt = view->rootContext();
|
||||
ctxt->setContextProperty("dummyValue", true);
|
||||
}
|
||||
//model->forceClear();
|
||||
}
|
||||
|
||||
void GridComicsView::selectedItem(int index)
|
||||
{
|
||||
emit doubleClicked(model->index(index,0));
|
||||
}
|
||||
|
||||
int GridComicsView::numItemsSelected()
|
||||
{
|
||||
if(_selectionModel != NULL)
|
||||
{
|
||||
return _selectionModel->selectedRows().length();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GridComicsView::lastSelectedIndex()
|
||||
{
|
||||
if(_selectionModel != NULL)
|
||||
{
|
||||
return _selectionModel->selectedRows().last().row();
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void GridComicsView::setShowMarks(bool show)
|
||||
{
|
||||
QQmlContext *ctxt = view->rootContext();
|
||||
ctxt->setContextProperty("show_marks", show);
|
||||
}
|
||||
|
||||
void GridComicsView::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
toolbar->removeAction(toolBarStretchAction);
|
||||
toolbar->removeAction(coverSizeSliderAction);
|
||||
|
||||
QObject *object = view->rootObject();
|
||||
QMetaObject::invokeMethod(object, "exit");
|
||||
container->close();
|
||||
view->close();
|
||||
event->accept();
|
||||
ComicsView::closeEvent(event);
|
||||
|
||||
//save settings
|
||||
settings->setValue(COMICS_GRID_COVER_SIZES, coverSizeSlider->value());
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user