initial commit
This commit is contained in:
commit
15cef03f08
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# User files
|
||||
*.user
|
||||
*.user.*
|
||||
|
||||
# Generic build dir
|
||||
[Bb]uild/
|
||||
|
||||
# IDE/Editor config folder
|
||||
.vscode/
|
62
CMakeLists.txt
Normal file
62
CMakeLists.txt
Normal file
@ -0,0 +1,62 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(pineapple-comic-reader VERSION 0.1 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(Qt6 6.8 REQUIRED COMPONENTS Quick Network)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.8)
|
||||
|
||||
qt_add_executable(pcomic
|
||||
main.cpp
|
||||
appcontroller.cpp
|
||||
appcontroller.h
|
||||
dataitems/libraryitem.cpp
|
||||
dataitems/libraryitem.h
|
||||
dataitems/comicitem.cpp
|
||||
dataitems/comicitem.h
|
||||
)
|
||||
|
||||
qt_add_qml_module(pcomic
|
||||
URI net.blumia.pineapple.comic.reader
|
||||
VERSION 1.0
|
||||
QML_FILES
|
||||
Main.qml
|
||||
ConnectServerPage.qml
|
||||
LibrarySelectionPage.qml
|
||||
ComicSelectionPage.qml
|
||||
ComicOverviewPage.qml
|
||||
ComicViewer.qml
|
||||
)
|
||||
|
||||
# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
|
||||
# If you are developing for iOS or macOS you should consider setting an
|
||||
# explicit, fixed bundle identifier manually though.
|
||||
set_target_properties(pcomic PROPERTIES
|
||||
# MACOSX_BUNDLE_GUI_IDENTIFIER net.blumia.pineapple.comic.reader
|
||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||
MACOSX_BUNDLE TRUE
|
||||
WIN32_EXECUTABLE TRUE
|
||||
QT_ANDROID_PACKAGE_NAME "net.blumia.pineapple.comic.reader"
|
||||
)
|
||||
|
||||
target_link_libraries(pcomic
|
||||
PRIVATE Qt6::Quick Qt6::Network
|
||||
)
|
||||
|
||||
qt_import_plugins(pcomic
|
||||
INCLUDE_BY_TYPE imageformats
|
||||
# These are the ones that ship by default if we don't use `qt_import_plugins`
|
||||
Qt::QGifPlugin Qt::QIcoPlugin Qt::QSvgPlugin Qt::QJpegPlugin
|
||||
# We need webp support from Qt imageformats module.
|
||||
Qt::QWebpPlugin
|
||||
)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
install(TARGETS pcomic
|
||||
BUNDLE DESTINATION .
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
)
|
67
ComicOverviewPage.qml
Normal file
67
ComicOverviewPage.qml
Normal file
@ -0,0 +1,67 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import net.blumia.pineapple.comic.reader
|
||||
import net.blumia.pineapple.comic.reader.comicitem
|
||||
|
||||
Control {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
padding: 5
|
||||
|
||||
property var curComicIndex: AppController.currentComicModelIndex()
|
||||
property bool startReading: AppController.selectedComicOpened
|
||||
|
||||
function dataByRole(role) {
|
||||
return AppController.comicsModel.data(curComicIndex, role)
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
Image {
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumHeight: Math.min(root.width / 2, root.height / 2)
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: AppController.coverImageSource(dataByRole(ComicItem.HashRole))
|
||||
// sourceSize.width: root.width / 3
|
||||
// sourceSize.height: root.width / 2
|
||||
}
|
||||
Label {
|
||||
Layout.preferredWidth: root.width - 10
|
||||
text: dataByRole(Qt.DisplayRole)
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
Label {
|
||||
Layout.preferredWidth: root.width - 10
|
||||
text: `${dataByRole(ComicItem.PageCountRole)} pages`
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
Label {
|
||||
Layout.preferredWidth: root.width - 10
|
||||
text: `Last read at ${dataByRole(ComicItem.CurrentPageRole)} page`
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: "Read"
|
||||
onClicked: function() {
|
||||
AppController.openComic()
|
||||
}
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: "Back"
|
||||
onClicked: function() {
|
||||
AppController.selectedComicId = ""
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
}
|
||||
|
||||
ComicViewer {
|
||||
z: 2
|
||||
visible: root.startReading
|
||||
pageCount: dataByRole(ComicItem.PageCountRole)
|
||||
}
|
||||
}
|
42
ComicSelectionPage.qml
Normal file
42
ComicSelectionPage.qml
Normal file
@ -0,0 +1,42 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
Label {
|
||||
text: "Comics"
|
||||
font.pixelSize: 20
|
||||
}
|
||||
GridView {
|
||||
id: gridView
|
||||
clip: true
|
||||
cellHeight: cellWidth * 3 / 2
|
||||
cellWidth: width / Math.max(Math.floor(width / (65 * 2)), 1)
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: AppController.comicsModel
|
||||
delegate: Button {
|
||||
width: GridView.view.cellWidth
|
||||
height: GridView.view.cellHeight
|
||||
Column {
|
||||
Image {
|
||||
source: AppController.coverImageSource(model.hash)
|
||||
width: gridView.cellWidth
|
||||
height: gridView.cellHeight
|
||||
fillMode: Image.PreserveAspectFit
|
||||
retainWhileLoading: true
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: function() {
|
||||
AppController.selectedComicId = model.comicId
|
||||
}
|
||||
}
|
||||
ScrollBar.vertical: ScrollBar { }
|
||||
}
|
||||
|
||||
Component.onCompleted: function() {
|
||||
AppController.updateComicsInFolder()
|
||||
}
|
||||
}
|
89
ComicViewer.qml
Normal file
89
ComicViewer.qml
Normal file
@ -0,0 +1,89 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import net.blumia.pineapple.comic.reader
|
||||
|
||||
Pane {
|
||||
id: root
|
||||
required property int pageCount
|
||||
|
||||
property bool osdVisible: false
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
SwipeView {
|
||||
id: view
|
||||
anchors.fill: parent
|
||||
|
||||
Repeater {
|
||||
model: root.pageCount
|
||||
Loader {
|
||||
active: root.visible && (SwipeView.isCurrentItem || SwipeView.isNextItem || SwipeView.isPreviousItem)
|
||||
sourceComponent: Image {
|
||||
anchors.fill: parent
|
||||
fillMode: Image.PreserveAspectFit
|
||||
source: AppController.comicImageSource(index)
|
||||
onStatusChanged: function() {
|
||||
if (status == Image.Error) {
|
||||
reloadTimer.start()
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: reloadTimer
|
||||
interval: 500
|
||||
onTriggered: {
|
||||
console.log("reload")
|
||||
let origSrc = parent.source
|
||||
parent.source = ""
|
||||
parent.source = origSrc
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pane {
|
||||
visible: root.osdVisible
|
||||
anchors.fill: parent
|
||||
opacity: 0.6
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
visible: root.osdVisible
|
||||
anchors.fill: parent
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
TapHandler {
|
||||
onTapped: function() {
|
||||
root.osdVisible = !root.osdVisible
|
||||
}
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "Close Comic"
|
||||
Layout.fillWidth: true
|
||||
onClicked: function() {
|
||||
AppController.closeComic()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PageIndicator {
|
||||
id: indicator
|
||||
|
||||
visible: !root.osdVisible
|
||||
count: view.count
|
||||
currentIndex: view.currentIndex
|
||||
|
||||
anchors.top: view.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
TapHandler {
|
||||
onTapped: function() {
|
||||
root.osdVisible = !root.osdVisible
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
43
ConnectServerPage.qml
Normal file
43
ConnectServerPage.qml
Normal file
@ -0,0 +1,43 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import net.blumia.pineapple.comic.reader
|
||||
|
||||
Control {
|
||||
anchors.fill: parent
|
||||
padding: 5
|
||||
contentItem: ColumnLayout {
|
||||
Label {
|
||||
text: "Pineapple Comic Reader"
|
||||
font.pixelSize: 20
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
Layout.verticalStretchFactor: 2
|
||||
}
|
||||
Label {
|
||||
text: "YACReader Library Server URL:"
|
||||
}
|
||||
TextField {
|
||||
id: baseUrlEdit
|
||||
Layout.fillWidth: true
|
||||
enabled: AppController.connectionState === AppController.NotConnected
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
Layout.verticalStretchFactor: 1
|
||||
}
|
||||
Button {
|
||||
Layout.fillWidth: true
|
||||
text: AppController.connectionState === AppController.NotConnected ? "Connect" : "Connecting"
|
||||
enabled: baseUrlEdit.enabled
|
||||
onClicked: function() {
|
||||
AppController.connectServer(baseUrlEdit.text)
|
||||
}
|
||||
}
|
||||
Item {
|
||||
Layout.fillHeight: true
|
||||
Layout.verticalStretchFactor: 3
|
||||
}
|
||||
}
|
||||
}
|
40
LibrarySelectionPage.qml
Normal file
40
LibrarySelectionPage.qml
Normal file
@ -0,0 +1,40 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import net.blumia.pineapple.comic.reader
|
||||
import net.blumia.pineapple.comic.reader.libraryitem
|
||||
|
||||
Control {
|
||||
anchors.fill: parent
|
||||
padding: 5
|
||||
contentItem: ColumnLayout {
|
||||
Label {
|
||||
text: "Libraries"
|
||||
font.pixelSize: 20
|
||||
}
|
||||
ListView {
|
||||
id: listView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
model: DelegateModel {
|
||||
model: AppController.librariesModel
|
||||
delegate: ItemDelegate {
|
||||
text: model.display
|
||||
width: ListView.view.width
|
||||
onClicked: function() {
|
||||
AppController.selectedLibraryId = model.libraryId
|
||||
}
|
||||
}
|
||||
onCountChanged: function() {
|
||||
if (count == 1) {
|
||||
AppController.selectedLibraryId = model.data(modelIndex(0), LibraryItem.IdRole)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: function() {
|
||||
AppController.updateLibraries()
|
||||
}
|
||||
}
|
||||
}
|
25
Main.qml
Normal file
25
Main.qml
Normal file
@ -0,0 +1,25 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
ApplicationWindow {
|
||||
width: 480
|
||||
height: 640
|
||||
visible: true
|
||||
title: qsTr("YACReader Client")
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
source: {
|
||||
if (AppController.connectionState !== AppController.Connected) return "ConnectServerPage.qml"
|
||||
if (AppController.selectedLibraryId === -1) return "LibrarySelectionPage.qml"
|
||||
if (AppController.selectedComicId === "") return "ComicSelectionPage.qml"
|
||||
return "ComicOverviewPage.qml"
|
||||
}
|
||||
}
|
||||
// before figure out how to handle back button on Android...
|
||||
onClosing: function(close) {
|
||||
if (Qt.platform.os === "android") {
|
||||
close.accepted = false;
|
||||
}
|
||||
}
|
||||
}
|
148
appcontroller.cpp
Normal file
148
appcontroller.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
#include "appcontroller.h"
|
||||
|
||||
#include "dataitems/libraryitem.h"
|
||||
#include "dataitems/comicitem.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QNetworkReply>
|
||||
#include <QRestAccessManager>
|
||||
#include <QRestReply>
|
||||
#include <QSettings>
|
||||
|
||||
AppController::AppController(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_networkAccessManager(new QNetworkAccessManager(this))
|
||||
, m_restAccessManager(new QRestAccessManager(m_networkAccessManager, this))
|
||||
, m_librariesModel(new QStandardItemModel(this))
|
||||
, m_comicsModel(new QStandardItemModel(this))
|
||||
{
|
||||
m_librariesModel->setItemRoleNames({
|
||||
{Qt::DisplayRole, "display"},
|
||||
{LibraryItem::IdRole, "libraryId"},
|
||||
{LibraryItem::UuidRole, "uuid"},
|
||||
});
|
||||
m_comicsModel->setItemRoleNames({
|
||||
{Qt::DisplayRole, "display"},
|
||||
{ComicItem::IdRole, "comicId"},
|
||||
{ComicItem::HashRole, "hash"},
|
||||
{ComicItem::PageCountRole, "pageCount"},
|
||||
{ComicItem::CurrentPageRole, "currentPage"},
|
||||
{ComicItem::TypeRole, "type"},
|
||||
});
|
||||
}
|
||||
|
||||
void AppController::connectServer(QUrl serverBaseUrl)
|
||||
{
|
||||
setProperty("connectionState", Connecting);
|
||||
serverBaseUrl.setPath("/v2/");
|
||||
QNetworkRequestFactory api(serverBaseUrl);
|
||||
m_restAccessManager->get(api.createRequest("version"), this, [=](QRestReply &reply){
|
||||
if (reply.isSuccess()) {
|
||||
qDebug() << reply.readText();
|
||||
m_requestFactory.setBaseUrl(serverBaseUrl);
|
||||
m_requestFactory.clearCommonHeaders();
|
||||
QHttpHeaders commonHeaders;
|
||||
commonHeaders.append("X-Request-Id", "114514");
|
||||
m_requestFactory.setCommonHeaders(commonHeaders);
|
||||
setProperty("connectionState", Connected);
|
||||
} else {
|
||||
setProperty("connectionState", NotConnected);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void AppController::updateLibraries()
|
||||
{
|
||||
m_restAccessManager->get(apiFactory().createRequest("libraries"), this, [=](QRestReply &reply){
|
||||
if (reply.isSuccess()) {
|
||||
std::optional<QJsonDocument> libraries = reply.readJson();
|
||||
if (libraries && !(*libraries).isEmpty() && (*libraries).isArray()) {
|
||||
const QJsonArray array = (*libraries).array();
|
||||
m_librariesModel->clear();
|
||||
for (const QJsonValue & value : array) {
|
||||
QJsonObject libraryObj = value.toObject();
|
||||
m_librariesModel->appendRow(new LibraryItem(libraryObj["id"].toInt(),
|
||||
libraryObj["name"].toString(),
|
||||
libraryObj["uuid"].toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void AppController::updateComicsInFolder(int folderId)
|
||||
{
|
||||
m_restAccessManager->get(apiFactory().createRequest(QString("library/%1/folder/%2/content")
|
||||
.arg(m_currentLibraryId).arg(folderId)),
|
||||
this, [=](QRestReply &reply){
|
||||
qDebug() << m_currentLibraryId << folderId << reply.httpStatus() << reply.errorString();
|
||||
if (reply.isSuccess()) {
|
||||
std::optional<QJsonDocument> libraries = reply.readJson();
|
||||
if (libraries && !(*libraries).isEmpty() && (*libraries).isArray()) {
|
||||
const QJsonArray array = (*libraries).array();
|
||||
m_comicsModel->clear();
|
||||
for (const QJsonValue & value : array) {
|
||||
QJsonObject comicObj = value.toObject();
|
||||
qDebug() << comicObj;
|
||||
m_comicsModel->appendRow(new ComicItem(comicObj, comicObj["file_name"].toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void AppController::openComic()
|
||||
{
|
||||
m_restAccessManager->get(apiFactory().createRequest(QString("library/%1/comic/%2/remote")
|
||||
.arg(m_currentLibraryId).arg(m_currentComicId)),
|
||||
this, [=](QRestReply &reply){
|
||||
qDebug() << m_currentLibraryId << m_currentComicId << reply.httpStatus() << reply.errorString();
|
||||
if (reply.isSuccess()) {
|
||||
setProperty("selectedComicOpened", true);
|
||||
} else {
|
||||
setProperty("selectedComicOpened", false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void AppController::closeComic()
|
||||
{
|
||||
// the api seems not proceed by the server, so we simply do nothing but set the property
|
||||
setProperty("selectedComicOpened", false);
|
||||
}
|
||||
|
||||
QString AppController::coverImageSource(QString comicHash)
|
||||
{
|
||||
QUrl url(apiFactory().baseUrl());
|
||||
url.setPath(url.path() + "library/" + QString::number(m_currentLibraryId) + "/cover/" + comicHash + ".jpg");
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
QModelIndex AppController::currentComicModelIndex()
|
||||
{
|
||||
if (m_currentComicId.isEmpty()) return QModelIndex();
|
||||
for (int i = 0; i < m_comicsModel->rowCount(); i++) {
|
||||
QModelIndex index = m_comicsModel->index(i, 0);
|
||||
if (m_comicsModel->data(index, ComicItem::IdRole) == m_currentComicId) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QString AppController::comicImageSource(int page)
|
||||
{
|
||||
QNetworkRequest req = apiFactory().createRequest(QString("library/%1/comic/%2/page/%3/remote")
|
||||
.arg(m_currentLibraryId)
|
||||
.arg(m_currentComicId)
|
||||
.arg(page));
|
||||
|
||||
return req.url().toString();
|
||||
}
|
||||
|
||||
QNetworkRequestFactory AppController::apiFactory() const
|
||||
{
|
||||
return m_requestFactory;
|
||||
}
|
57
appcontroller.h
Normal file
57
appcontroller.h
Normal file
@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <QQmlEngine>
|
||||
#include <QNetworkRequestFactory>
|
||||
#include <QRestAccessManager>
|
||||
#include <QStandardItemModel>
|
||||
|
||||
class AppController : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_SINGLETON
|
||||
public:
|
||||
enum ConnectionState {
|
||||
NotConnected,
|
||||
Connecting,
|
||||
Connected
|
||||
};
|
||||
Q_ENUM(ConnectionState)
|
||||
|
||||
Q_PROPERTY(ConnectionState connectionState MEMBER m_connectionState NOTIFY connectionStateChanged FINAL)
|
||||
Q_PROPERTY(int selectedLibraryId MEMBER m_currentLibraryId NOTIFY currentLibraryIdChanged FINAL)
|
||||
Q_PROPERTY(QString selectedComicId MEMBER m_currentComicId NOTIFY currentComicIdChanged FINAL)
|
||||
Q_PROPERTY(bool selectedComicOpened MEMBER m_currentComicOpened NOTIFY currentComicOpenedChanged FINAL)
|
||||
Q_PROPERTY(QStandardItemModel * librariesModel MEMBER m_librariesModel CONSTANT FINAL)
|
||||
Q_PROPERTY(QStandardItemModel * comicsModel MEMBER m_comicsModel CONSTANT FINAL)
|
||||
|
||||
AppController(QObject *parent = nullptr);
|
||||
|
||||
Q_INVOKABLE void connectServer(QUrl serverBaseUrl);
|
||||
Q_INVOKABLE void updateLibraries();
|
||||
Q_INVOKABLE void updateComicsInFolder(int folderId = 1);
|
||||
Q_INVOKABLE void openComic();
|
||||
Q_INVOKABLE void closeComic();
|
||||
Q_INVOKABLE QString coverImageSource(QString comicHash);
|
||||
Q_INVOKABLE QModelIndex currentComicModelIndex();
|
||||
Q_INVOKABLE QString comicImageSource(int page);
|
||||
|
||||
signals:
|
||||
void connectionStateChanged(ConnectionState newState);
|
||||
void currentLibraryIdChanged(int newLibraryId);
|
||||
void currentComicIdChanged(QString newComicId);
|
||||
void currentComicOpenedChanged(bool opened);
|
||||
|
||||
private:
|
||||
QNetworkRequestFactory apiFactory() const;
|
||||
|
||||
ConnectionState m_connectionState = NotConnected;
|
||||
int m_currentLibraryId = -1;
|
||||
QString m_currentComicId;
|
||||
bool m_currentComicOpened = false;
|
||||
QNetworkRequestFactory m_requestFactory;
|
||||
QNetworkAccessManager * m_networkAccessManager;
|
||||
QRestAccessManager * m_restAccessManager;
|
||||
QStandardItemModel * m_librariesModel;
|
||||
QStandardItemModel * m_comicsModel;
|
||||
};
|
11
dataitems/comicitem.cpp
Normal file
11
dataitems/comicitem.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "comicitem.h"
|
||||
|
||||
ComicItem::ComicItem(QJsonObject jsonObj, const QString &name)
|
||||
: QStandardItem(name)
|
||||
{
|
||||
setData(jsonObj["id"].toString(), IdRole);
|
||||
setData(jsonObj["hash"].toString(), HashRole);
|
||||
setData(jsonObj["num_pages"].toInt(), PageCountRole);
|
||||
setData(jsonObj["current_page"].toInt(), CurrentPageRole);
|
||||
setData(jsonObj["type"].toInt(), TypeRole);
|
||||
}
|
21
dataitems/comicitem.h
Normal file
21
dataitems/comicitem.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QStandardItem>
|
||||
#include <QQmlEngine>
|
||||
|
||||
class ComicItem : public QStandardItem
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
enum Roles {
|
||||
IdRole = Qt::UserRole + 1,
|
||||
HashRole,
|
||||
PageCountRole,
|
||||
CurrentPageRole,
|
||||
TypeRole,
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit ComicItem(QJsonObject jsonObj, const QString &name);
|
||||
};
|
8
dataitems/libraryitem.cpp
Normal file
8
dataitems/libraryitem.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
#include "libraryitem.h"
|
||||
|
||||
LibraryItem::LibraryItem(int id, const QString &name, const QString &uuid)
|
||||
: QStandardItem(QIcon::fromTheme(QIcon::ThemeIcon::FolderOpen), name)
|
||||
{
|
||||
setData(id, IdRole);
|
||||
setData(uuid, UuidRole);
|
||||
}
|
16
dataitems/libraryitem.h
Normal file
16
dataitems/libraryitem.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <QStandardItem>
|
||||
|
||||
class LibraryItem : public QStandardItem
|
||||
{
|
||||
Q_GADGET
|
||||
public:
|
||||
enum Roles {
|
||||
IdRole = Qt::UserRole + 1,
|
||||
UuidRole
|
||||
};
|
||||
Q_ENUM(Roles)
|
||||
|
||||
explicit LibraryItem(int id, const QString &name, const QString &uuid);
|
||||
};
|
55
main.cpp
Normal file
55
main.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QQmlNetworkAccessManagerFactory>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
|
||||
#include "dataitems/libraryitem.h"
|
||||
#include "dataitems/comicitem.h"
|
||||
|
||||
class QmlNetworkAccessManager : public QNetworkAccessManager
|
||||
{
|
||||
public:
|
||||
QmlNetworkAccessManager(QObject *parent = nullptr) : QNetworkAccessManager(parent) {}
|
||||
|
||||
protected:
|
||||
QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData = nullptr) override
|
||||
{
|
||||
QNetworkRequest newRequest(request);
|
||||
newRequest.setRawHeader("X-Request-Id", "114514");
|
||||
return QNetworkAccessManager::createRequest(op, newRequest, outgoingData);
|
||||
}
|
||||
};
|
||||
|
||||
class QmlNetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory
|
||||
{
|
||||
public:
|
||||
inline QNetworkAccessManager *create(QObject *parent) override
|
||||
{
|
||||
return new QmlNetworkAccessManager(parent);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
qputenv("QT_QUICK_CONTROLS_STYLE", QByteArray("FluentWinUI3"));
|
||||
|
||||
qmlRegisterUncreatableMetaObject(LibraryItem::staticMetaObject, "net.blumia.pineapple.comic.reader.libraryitem", 1, 0, "LibraryItem", "enum");
|
||||
qmlRegisterUncreatableMetaObject(ComicItem::staticMetaObject, "net.blumia.pineapple.comic.reader.comicitem", 1, 0, "ComicItem", "enum");
|
||||
|
||||
QmlNetworkAccessManagerFactory namFactory;
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
engine.setNetworkAccessManagerFactory(&namFactory);
|
||||
QObject::connect(
|
||||
&engine,
|
||||
&QQmlApplicationEngine::objectCreationFailed,
|
||||
&app,
|
||||
[]() { QCoreApplication::exit(-1); },
|
||||
Qt::QueuedConnection);
|
||||
engine.loadFromModule("net.blumia.pineapple.comic.reader", "Main");
|
||||
|
||||
return app.exec();
|
||||
}
|
Loading…
Reference in New Issue
Block a user