added a QStyledItemDelegate to the list QListView in EmptyFolderWidget to center aling folders' names

This commit is contained in:
Luis Ángel San Martín
2016-01-01 13:11:31 +01:00
commit 9a62cd4a72
953 changed files with 81449 additions and 0 deletions

View 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.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();
}

View 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

View 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

View File

@ -0,0 +1,171 @@
#include "comic_vine_client.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 = "http://www.comicvine.com/api";
//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");
}
ComicVineClient::~ComicVineClient()
{
delete settings;
}
//CV_SEARCH
void ComicVineClient::search(const QString & query, int page)
{
HttpWorker * search = new HttpWorker(QString(CV_SEARCH).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_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_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_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_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)
{
}

View File

@ -0,0 +1,46 @@
#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;
};
#endif // COMIC_VINE_CLIENT_H

View 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);
}

View 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

View File

@ -0,0 +1,6 @@
#include "comics_model.h"
ComicsModel::ComicsModel(QObject *parent) :
JSONModel(parent)
{
}

View 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

View File

@ -0,0 +1,6 @@
#include "json_model.h"
JSONModel::JSONModel(QObject *parent) :
QAbstractItemModel(parent)
{
}

View 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

View 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());
}

View 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

View 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;
}
}

View 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

View 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;
}

View 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

View 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];
}

View 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

View 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);
}

View 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

View 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;
}

View 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

View 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));
}

View 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

View 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);
}

View 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

View 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);
}

View 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

View 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();
}

View 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

View 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();
}

View 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

View 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());
}

View 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

View 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()));
}

View 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

View 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);
}

View 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

View 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;
}

View 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

View 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
{
}
}

View 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