mirror of
https://github.com/kiwix/kiwix-desktop.git
synced 2025-09-22 11:37:56 -04:00
commit
bf2c780647
@ -49,13 +49,16 @@ SOURCES += \
|
|||||||
src/topwidget.cpp \
|
src/topwidget.cpp \
|
||||||
src/requestinterceptor.cpp \
|
src/requestinterceptor.cpp \
|
||||||
src/urlschemehandler.cpp \
|
src/urlschemehandler.cpp \
|
||||||
src/tabwidget.cpp \
|
|
||||||
src/webview.cpp \
|
src/webview.cpp \
|
||||||
src/searchbar.cpp \
|
src/searchbar.cpp \
|
||||||
src/mainmenu.cpp \
|
src/mainmenu.cpp \
|
||||||
src/webpage.cpp \
|
src/webpage.cpp \
|
||||||
src/about.cpp \
|
src/about.cpp \
|
||||||
src/tocsidebar.cpp
|
src/tocsidebar.cpp \
|
||||||
|
src/contentmanager.cpp \
|
||||||
|
src/contentmanagerview.cpp \
|
||||||
|
src/tabbar.cpp \
|
||||||
|
src/contentmanagerside.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
src/mainwindow.h \
|
src/mainwindow.h \
|
||||||
@ -66,18 +69,22 @@ HEADERS += \
|
|||||||
src/kconstants.h \
|
src/kconstants.h \
|
||||||
src/requestinterceptor.h \
|
src/requestinterceptor.h \
|
||||||
src/urlschemehandler.h \
|
src/urlschemehandler.h \
|
||||||
src/tabwidget.h \
|
|
||||||
src/webview.h \
|
src/webview.h \
|
||||||
src/searchbar.h \
|
src/searchbar.h \
|
||||||
src/mainmenu.h \
|
src/mainmenu.h \
|
||||||
src/webpage.h \
|
src/webpage.h \
|
||||||
src/about.h \
|
src/about.h \
|
||||||
src/tocsidebar.h
|
src/tocsidebar.h \
|
||||||
|
src/contentmanager.h \
|
||||||
|
src/contentmanagerview.h \
|
||||||
|
src/tabbar.h \
|
||||||
|
src/contentmanagerside.h
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
ui/mainwindow.ui \
|
ui/mainwindow.ui \
|
||||||
ui/about.ui \
|
ui/about.ui \
|
||||||
src/tocsidebar.ui
|
src/tocsidebar.ui \
|
||||||
|
src/contentmanagerside.ui
|
||||||
|
|
||||||
TRANSLATIONS = "resources/i18n/kiwix-desktop_fr.ts"
|
TRANSLATIONS = "resources/i18n/kiwix-desktop_fr.ts"
|
||||||
CODECFORSRC = UTF-8
|
CODECFORSRC = UTF-8
|
||||||
@ -116,7 +123,9 @@ LIBS += $$system(pkg-config --libs $$PKGCONFIG_OPTION kiwix)
|
|||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
resources/kiwix.qrc \
|
resources/kiwix.qrc \
|
||||||
resources/translations.qrc
|
resources/translations.qrc \
|
||||||
|
resources/contentmanager.qrc \
|
||||||
|
resources/style.qrc
|
||||||
|
|
||||||
unix {
|
unix {
|
||||||
system($$QMAKE_LUPDATE -locations relative -no-ui-lines $$_PRO_FILE_)
|
system($$QMAKE_LUPDATE -locations relative -no-ui-lines $$_PRO_FILE_)
|
||||||
|
6
resources/contentmanager.qrc
Normal file
6
resources/contentmanager.qrc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>js/vue.js</file>
|
||||||
|
<file>texts/_contentManager.html</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
@ -177,3 +177,29 @@ QTabBar::close-button {
|
|||||||
border-top-right-radius: 5px;
|
border-top-right-radius: 5px;
|
||||||
border-bottom-right-radius: 5px;
|
border-bottom-right-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------
|
||||||
|
Find Search page
|
||||||
|
*/
|
||||||
|
|
||||||
|
#sideBar {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contentmanagerside QWidget{
|
||||||
|
background-color: white;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contentmanagerside QRadioButton:checked {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#contentmanagerside QRadioButton::indicator {
|
||||||
|
image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#contentmanagerside QCheckBox::indicator {
|
||||||
|
image: none;
|
||||||
|
}
|
||||||
|
10947
resources/js/vue.js
Normal file
10947
resources/js/vue.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -61,7 +61,6 @@
|
|||||||
<file>fonts/SegoeUI/seguisb.ttf</file>
|
<file>fonts/SegoeUI/seguisb.ttf</file>
|
||||||
<file>fonts/SegoeUI/segoeui.ttf</file>
|
<file>fonts/SegoeUI/segoeui.ttf</file>
|
||||||
<file>texts/about.html</file>
|
<file>texts/about.html</file>
|
||||||
<file>css/style.css</file>
|
|
||||||
<file>icons/search_backward.svg</file>
|
<file>icons/search_backward.svg</file>
|
||||||
<file>icons/search_forward.svg</file>
|
<file>icons/search_forward.svg</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
5
resources/style.qrc
Normal file
5
resources/style.qrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>css/style.css</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
229
resources/texts/_contentManager.html
Normal file
229
resources/texts/_contentManager.html
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="qrc:///js/vue.js"></script>
|
||||||
|
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
const units = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
|
function niceBytes(x){
|
||||||
|
var unitIndex = 0;
|
||||||
|
var n = parseInt(x, 10) || 0;
|
||||||
|
while(n >= 1024 && ++unitIndex)
|
||||||
|
n = n/1024;
|
||||||
|
return(n.toFixed(n >= 10 || unitIndex < 1 ? 0 : 2) + ' ' + units[unitIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createDict(keys, values) {
|
||||||
|
var d = {}
|
||||||
|
for(var i=0; i<keys.length; i++) {
|
||||||
|
d[keys[i]] = values[i];
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
const BOOK_KEYS = ["id", "name", "path", "url", "size", "description", "title", "tags", "date", "favicon", "faviconMimeType", "downloadId"];
|
||||||
|
function addBook(values) {
|
||||||
|
var b = createDict(BOOK_KEYS, values);
|
||||||
|
if (b.downloadId && !downloadUpdaters.hasOwnProperty(b.id)) {
|
||||||
|
downloadUpdaters[b.id] = setInterval(function() { getDownloadInfo(b.id); }, 1000);
|
||||||
|
}
|
||||||
|
app.books.push(b);
|
||||||
|
}
|
||||||
|
function onBooksChanged () {
|
||||||
|
app.books = [];
|
||||||
|
for(var i=0; i<contentManager.bookIds.length; i++) {
|
||||||
|
var id = contentManager.bookIds[i];
|
||||||
|
contentManager.getBookInfos(id, BOOK_KEYS, addBook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadUpdaters = {}
|
||||||
|
const DOWNLOAD_KEYS = ["id", "status", "followedBy", "path", "totalLength", "completedLength", "downloadSpeed", "verifiedLength"];
|
||||||
|
function getDownloadInfo(id) {
|
||||||
|
contentManager.updateDownloadInfos(id, DOWNLOAD_KEYS, function(values) {
|
||||||
|
if (values.length == 0) {
|
||||||
|
clearInterval(downloadUpdaters[id]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d = createDict(DOWNLOAD_KEYS, values);
|
||||||
|
if (d.status == "completed") {
|
||||||
|
clearInterval(downloadUpdaters[id]);
|
||||||
|
}
|
||||||
|
Vue.set(app.downloads, id, createDict(DOWNLOAD_KEYS, values));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
new QWebChannel(qt.webChannelTransport, function(channel) {
|
||||||
|
contentManager = channel.objects.contentManager;
|
||||||
|
app = new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data: {
|
||||||
|
contentManager: contentManager,
|
||||||
|
books: [],
|
||||||
|
downloads: {}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openBook : function(book) {
|
||||||
|
contentManager.openBook(book.id, function() {});
|
||||||
|
},
|
||||||
|
changePage : function(delta) {
|
||||||
|
var newPage = contentManager.currentPage+delta;
|
||||||
|
if (newPage < 0) newPage = 0;
|
||||||
|
if (newPage > contentManager.nbPages) newPage = contentManager.nbPages;
|
||||||
|
contentManager.currentPage = newPage;
|
||||||
|
},
|
||||||
|
downloadBook : function(book) {
|
||||||
|
contentManager.downloadBook(book.id, function(did) {
|
||||||
|
book.downloadId = did;
|
||||||
|
downloadUpdaters[book.id] = setInterval(function() { getDownloadInfo(book.id); }, 1000);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
niceBytes : niceBytes
|
||||||
|
}
|
||||||
|
});
|
||||||
|
contentManager.booksChanged.connect(onBooksChanged);
|
||||||
|
onBooksChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
*:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
#searchInput {
|
||||||
|
background-image: url('qrc:///icons/search.svg');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: left top;
|
||||||
|
background-size: 40px 40px;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
padding-left: 45px;
|
||||||
|
height: 40px;
|
||||||
|
width: 90%;
|
||||||
|
border: 1px solid #EEE;
|
||||||
|
}
|
||||||
|
#bookList {
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.tablerow,
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
color: #555;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.tablecell{
|
||||||
|
flex-basis:20%;
|
||||||
|
}
|
||||||
|
.cell0 {
|
||||||
|
flex-basis: 60px;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.tablerow > .cell1 {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.cell0 > img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
.cell1,
|
||||||
|
.cell2,
|
||||||
|
.cell3,
|
||||||
|
.cell4,
|
||||||
|
.cell5 {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
summary::-webkit-details-marker {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
summary {
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
.book {
|
||||||
|
border-top: 1px solid #EEE;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
background: transparent;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
.tablerow button {
|
||||||
|
color: blue;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
border: 0px;
|
||||||
|
background: transparent;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.tablerow button:hover {
|
||||||
|
color: white;
|
||||||
|
background: blue;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body onload="init()">
|
||||||
|
<div id="app">
|
||||||
|
<div id="searchBar">
|
||||||
|
<form>
|
||||||
|
<input id="searchInput" type="text" placeholder="Search files" readonly/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="bookList">
|
||||||
|
<div class="header">
|
||||||
|
<span class="tablecell cell0"></span>
|
||||||
|
<span class="tablecell cell1">File name</span>
|
||||||
|
<span class="tablecell cell2">Size</span>
|
||||||
|
<span class="tablecell cell3">Date</span>
|
||||||
|
<span class="tablecell cell4">Content type</span>
|
||||||
|
<span class="tablecell cell5"></span>
|
||||||
|
</div>
|
||||||
|
<details v-for="book in books" class="book">
|
||||||
|
<summary class="tablerow">
|
||||||
|
<span class="tablecell cell0">
|
||||||
|
<img v-bind:src="'data:image/png;base64,' + book.favicon"/>
|
||||||
|
</span>
|
||||||
|
<span class="tablecell cell1">
|
||||||
|
{{ book.title }}
|
||||||
|
</span>
|
||||||
|
<span class="tablecell cell2">
|
||||||
|
{{ niceBytes(book.size) }}
|
||||||
|
</span>
|
||||||
|
<span class="tablecell cell3">
|
||||||
|
{{ book.date }}
|
||||||
|
</span>
|
||||||
|
<span class="tablecell cell4">
|
||||||
|
{{ book.tags }}
|
||||||
|
</span>
|
||||||
|
<span class="tablecell cell5">
|
||||||
|
<template v-if="book.downloadId">
|
||||||
|
<span v-if="downloads[book.id]">
|
||||||
|
{{ niceBytes(downloads[book.id].completedLength) }} / {{ niceBytes(downloads[book.id].totalLength) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<button v-else-if="book.path" v-on:click="openBook(book)">Open</button>
|
||||||
|
<button v-else v-on:click="downloadBook(book)">Download</button>
|
||||||
|
</span>
|
||||||
|
</summary>
|
||||||
|
<p class="content">
|
||||||
|
{{ book.description }}
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
<div class="footer">
|
||||||
|
<button v-on:click="contentManager.currentPage = 0">First</button>
|
||||||
|
<button v-on:click="changePage(-1)">Previous</button>
|
||||||
|
{{ contentManager.currentPage+1 }} / {{ contentManager.nbPages+1 }}
|
||||||
|
<button v-on:click="changePage(1)">Next</button>
|
||||||
|
<button v-on:click="contentManager.currentPage = contentManager.nbPages">Last</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body></html>
|
238
src/contentmanager.cpp
Normal file
238
src/contentmanager.cpp
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
#include "contentmanager.h"
|
||||||
|
|
||||||
|
#include "kiwixapp.h"
|
||||||
|
#include <kiwix/common/networkTools.h>
|
||||||
|
#include <kiwix/common/otherTools.h>
|
||||||
|
#include <kiwix/manager.h>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
ContentManager::ContentManager(Library* library, kiwix::Downloader* downloader, QObject *parent)
|
||||||
|
: QObject(parent),
|
||||||
|
mp_library(library),
|
||||||
|
mp_downloader(downloader)
|
||||||
|
{
|
||||||
|
// mp_view will be passed to the tab who will take ownership,
|
||||||
|
// so, we don't need to delete it.
|
||||||
|
mp_view = new ContentManagerView();
|
||||||
|
mp_view->registerObject("contentManager", this);
|
||||||
|
mp_view->setHtml();
|
||||||
|
setCurrentLanguage(QLocale().name().split("_").at(0));
|
||||||
|
connect(mp_library, &Library::booksChanged, this, [=]() {emit(this->booksChanged());});
|
||||||
|
connect(this, &ContentManager::remoteParamsChanged, this, &ContentManager::updateRemoteLibrary);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ContentManager::setLocal(bool local) {
|
||||||
|
if (local == m_local) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_local = local;
|
||||||
|
m_currentPage = 0;
|
||||||
|
emit(remoteParamsChanged());
|
||||||
|
emit(booksChanged());
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_V(KEY, METH) {if(key==KEY) values.append(QString::fromStdString((b.METH())));}
|
||||||
|
QStringList ContentManager::getBookInfos(QString id, const QStringList &keys)
|
||||||
|
{
|
||||||
|
QStringList values;
|
||||||
|
if (id.endsWith(".zim")) {
|
||||||
|
id.resize(id.size()-4);
|
||||||
|
}
|
||||||
|
kiwix::Book& b = [=]()->kiwix::Book& {
|
||||||
|
try {
|
||||||
|
return mp_library->getBookById(id);
|
||||||
|
} catch (...) {
|
||||||
|
return m_remoteLibrary.getBookById(id.toStdString());
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
for(auto& key: keys){
|
||||||
|
ADD_V("id", getId);
|
||||||
|
ADD_V("path", getPath);
|
||||||
|
ADD_V("indexPath", getIndexPath);
|
||||||
|
ADD_V("title", getTitle);
|
||||||
|
ADD_V("description", getDescription);
|
||||||
|
ADD_V("language", getLanguage);
|
||||||
|
ADD_V("creator", getCreator);
|
||||||
|
ADD_V("publisher", getPublisher);
|
||||||
|
ADD_V("date", getDate);
|
||||||
|
ADD_V("url", getUrl);
|
||||||
|
ADD_V("name", getName);
|
||||||
|
ADD_V("tags", getTags);
|
||||||
|
ADD_V("origId", getOrigId);
|
||||||
|
ADD_V("faviconMimeType", getFaviconMimeType);
|
||||||
|
ADD_V("downloadId", getDownloadId);
|
||||||
|
if (key == "favicon") {
|
||||||
|
auto s = b.getFavicon();
|
||||||
|
values.append(QByteArray::fromStdString(s).toBase64());
|
||||||
|
}
|
||||||
|
if (key == "size") {
|
||||||
|
values.append(QString::number(b.getSize()));
|
||||||
|
}
|
||||||
|
if (key == "articleCount") {
|
||||||
|
values.append(QString::number(b.getArticleCount()));
|
||||||
|
}
|
||||||
|
if (key == "mediaCount") {
|
||||||
|
values.append(QString::number(b.getMediaCount()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
#undef ADD_V
|
||||||
|
|
||||||
|
void ContentManager::openBook(const QString &id)
|
||||||
|
{
|
||||||
|
QUrl url("zim://"+id+".zim/");
|
||||||
|
KiwixApp::instance()->openUrl(url, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_V(KEY, METH) {if(key==KEY) {values.append(QString::fromStdString((d->METH()))); continue;}}
|
||||||
|
QStringList ContentManager::updateDownloadInfos(QString id, const QStringList &keys)
|
||||||
|
{
|
||||||
|
QStringList values;
|
||||||
|
if (id.endsWith(".zim")) {
|
||||||
|
id.resize(id.size()-4);
|
||||||
|
}
|
||||||
|
auto& b = mp_library->getBookById(id);
|
||||||
|
kiwix::Download* d;
|
||||||
|
try {
|
||||||
|
d = mp_downloader->getDownload(b.getDownloadId());
|
||||||
|
} catch(...) {
|
||||||
|
b.setDownloadId("");
|
||||||
|
mp_library->save();
|
||||||
|
emit(mp_library->booksChanged());
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->updateStatus(true);
|
||||||
|
if (d->getStatus() == kiwix::Download::K_COMPLETE) {
|
||||||
|
b.setPath(d->getPath());
|
||||||
|
b.setDownloadId("");
|
||||||
|
mp_library->save();
|
||||||
|
emit(mp_library->booksChanged());
|
||||||
|
}
|
||||||
|
for(auto& key: keys){
|
||||||
|
ADD_V("id", getDid);
|
||||||
|
if(key == "status") {
|
||||||
|
switch(d->getStatus()){
|
||||||
|
case kiwix::Download::K_ACTIVE:
|
||||||
|
values.append("active");
|
||||||
|
break;
|
||||||
|
case kiwix::Download::K_WAITING:
|
||||||
|
values.append("waiting");
|
||||||
|
break;
|
||||||
|
case kiwix::Download::K_PAUSED:
|
||||||
|
values.append("paused");
|
||||||
|
break;
|
||||||
|
case kiwix::Download::K_ERROR:
|
||||||
|
values.append("error");
|
||||||
|
break;
|
||||||
|
case kiwix::Download::K_COMPLETE:
|
||||||
|
values.append("completed");
|
||||||
|
break;
|
||||||
|
case kiwix::Download::K_REMOVED:
|
||||||
|
values.append("removed");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
values.append("unknown");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ADD_V("followedBy", getFollowedBy);
|
||||||
|
ADD_V("path", getPath);
|
||||||
|
if(key == "totalLength") {
|
||||||
|
values.append(QString::number(d->getTotalLength()));
|
||||||
|
}
|
||||||
|
if(key == "completedLength") {
|
||||||
|
values.append(QString::number(d->getCompletedLength()));
|
||||||
|
}
|
||||||
|
if(key == "downloadSpeed") {
|
||||||
|
values.append(QString::number(d->getDownloadSpeed()));
|
||||||
|
}
|
||||||
|
if(key == "verifiedLength") {
|
||||||
|
values.append(QString::number(d->getVerifiedLength()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
#undef ADD_V
|
||||||
|
|
||||||
|
QString ContentManager::downloadBook(const QString &id)
|
||||||
|
{
|
||||||
|
auto& book = [&]()->kiwix::Book& {
|
||||||
|
try {
|
||||||
|
return m_remoteLibrary.getBookById(id.toStdString());
|
||||||
|
} catch (...) {
|
||||||
|
return mp_library->getBookById(id);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
auto download = mp_downloader->startDownload(book.getUrl());
|
||||||
|
book.setDownloadId(download->getDid());
|
||||||
|
mp_library->addBookToLibrary(book);
|
||||||
|
mp_library->save();
|
||||||
|
emit(mp_library->booksChanged());
|
||||||
|
emit(booksChanged());
|
||||||
|
return QString::fromStdString(download->getDid());
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList ContentManager::getDownloadIds()
|
||||||
|
{
|
||||||
|
QStringList list;
|
||||||
|
for(auto& id: mp_downloader->getDownloadIds()) {
|
||||||
|
list.append(QString::fromStdString(id));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContentManager::setCurrentLanguage(QString language)
|
||||||
|
{
|
||||||
|
if (language.length() == 2) {
|
||||||
|
try {
|
||||||
|
language = QString::fromStdString(
|
||||||
|
kiwix::converta2toa3(language.toStdString()));
|
||||||
|
} catch (std::out_of_range&) {}
|
||||||
|
}
|
||||||
|
m_currentLanguage = language;
|
||||||
|
emit(currentLangChanged());
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CATALOG_HOST "http://library.kiwix.org"
|
||||||
|
void ContentManager::updateRemoteLibrary() {
|
||||||
|
QUrlQuery query;
|
||||||
|
query.addQueryItem("lang", m_currentLanguage);
|
||||||
|
query.addQueryItem("count", QString::number(m_booksPerPage));
|
||||||
|
query.addQueryItem("start", QString::number(getStartBookIndex()));
|
||||||
|
QUrl url;
|
||||||
|
url.setScheme("http");
|
||||||
|
url.setHost("localhost");
|
||||||
|
url.setPort(8080);
|
||||||
|
url.setPath("/catalog/search.xml");
|
||||||
|
url.setQuery(query);
|
||||||
|
qInfo() << "Downloading" << url;
|
||||||
|
kiwix::Manager manager(&m_remoteLibrary);
|
||||||
|
try {
|
||||||
|
auto allContent = kiwix::download(url.toString().toStdString());
|
||||||
|
manager.readOpds(allContent, CATALOG_HOST);
|
||||||
|
} catch (runtime_error&) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList ContentManager::getBookIds() {
|
||||||
|
if (m_local) {
|
||||||
|
return mp_library->getBookIds().mid(getStartBookIndex(), m_booksPerPage);
|
||||||
|
} else {
|
||||||
|
auto bookIds = m_remoteLibrary.getBooksIds();
|
||||||
|
QStringList list;
|
||||||
|
for(auto i=0; i<m_booksPerPage; i++) {
|
||||||
|
try{
|
||||||
|
list.append(QString::fromStdString(bookIds.at(getStartBookIndex()+i)));
|
||||||
|
} catch (out_of_range& e) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
73
src/contentmanager.h
Normal file
73
src/contentmanager.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#ifndef CONTENTMANAGER_H
|
||||||
|
#define CONTENTMANAGER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <math.h>
|
||||||
|
#include "library.h"
|
||||||
|
#include "contentmanagerview.h"
|
||||||
|
#include <kiwix/downloader.h>
|
||||||
|
|
||||||
|
class ContentManager : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int booksPerPage MEMBER m_booksPerPage NOTIFY booksChanged)
|
||||||
|
Q_PROPERTY(int nbPages READ getNbPages NOTIFY booksChanged)
|
||||||
|
Q_PROPERTY(int currentPage MEMBER m_currentPage WRITE setCurrentPage NOTIFY booksChanged)
|
||||||
|
Q_PROPERTY(int startBookIndex READ getStartBookIndex NOTIFY booksChanged)
|
||||||
|
Q_PROPERTY(int endBookIndex READ getEndBookIndex NOTIFY booksChanged)
|
||||||
|
Q_PROPERTY(QStringList bookIds READ getBookIds NOTIFY booksChanged)
|
||||||
|
Q_PROPERTY(QStringList downloadIds READ getDownloadIds NOTIFY downloadsChanged)
|
||||||
|
Q_PROPERTY(QString currentLanguage MEMBER m_currentLanguage WRITE setCurrentLanguage NOTIFY currentLangChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ContentManager(Library* library, kiwix::Downloader *downloader, QObject *parent = nullptr);
|
||||||
|
virtual ~ContentManager() {}
|
||||||
|
|
||||||
|
ContentManagerView* getView() { return mp_view; }
|
||||||
|
void setLocal(bool local);
|
||||||
|
QStringList getDownloadIds();
|
||||||
|
private:
|
||||||
|
Library* mp_library;
|
||||||
|
kiwix::Library m_remoteLibrary;
|
||||||
|
kiwix::Downloader* mp_downloader;
|
||||||
|
ContentManagerView* mp_view;
|
||||||
|
int m_booksPerPage = 10;
|
||||||
|
int m_currentPage = 0;
|
||||||
|
bool m_local = true;
|
||||||
|
QString m_currentLanguage;
|
||||||
|
void setCurrentPage(int currentPage) {
|
||||||
|
m_currentPage = max(0, min(currentPage, getNbPages()));
|
||||||
|
emit(booksChanged());
|
||||||
|
}
|
||||||
|
void setCurrentLanguage(QString language);
|
||||||
|
|
||||||
|
QStringList getBookIds();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void booksChanged();
|
||||||
|
void downloadsChanged();
|
||||||
|
void currentLangChanged();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
int getNbPages() {
|
||||||
|
if (m_local) {
|
||||||
|
return round(float(mp_library->getBookIds().length()) / m_booksPerPage);
|
||||||
|
} else {
|
||||||
|
return round(float(m_remoteLibrary.getBooksIds().size()) / m_booksPerPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int getStartBookIndex() {
|
||||||
|
return m_currentPage * m_booksPerPage;
|
||||||
|
}
|
||||||
|
int getEndBookIndex() {
|
||||||
|
return min((m_currentPage+1) * m_booksPerPage, mp_library->getBookIds().length());
|
||||||
|
}
|
||||||
|
QStringList getBookInfos(QString id, const QStringList &keys);
|
||||||
|
void openBook(const QString& id);
|
||||||
|
QStringList updateDownloadInfos(QString id, const QStringList& keys);
|
||||||
|
QString downloadBook(const QString& id);
|
||||||
|
void updateRemoteLibrary();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTENTMANAGER_H
|
25
src/contentmanagerside.cpp
Normal file
25
src/contentmanagerside.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include "contentmanagerside.h"
|
||||||
|
#include "ui_contentmanagerside.h"
|
||||||
|
|
||||||
|
ContentManagerSide::ContentManagerSide(QWidget *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
mp_ui(new Ui::contentmanagerside)
|
||||||
|
{
|
||||||
|
mp_ui->setupUi(this);
|
||||||
|
connect(mp_ui->allFileButton, &QRadioButton::toggled,
|
||||||
|
this, [=](bool checked) { this->mp_contentManager->setLocal(!checked); });
|
||||||
|
connect(mp_ui->localFileButton, &QRadioButton::toggled,
|
||||||
|
this, [=](bool checked) { this->mp_contentManager->setLocal(checked); });
|
||||||
|
connect(mp_ui->allFileButton, &QRadioButton::toggled,
|
||||||
|
this, [=](bool checked) { mp_ui->allFileButton->setStyleSheet(
|
||||||
|
checked ? "*{font-weight: bold}" : "");});
|
||||||
|
connect(mp_ui->localFileButton, &QRadioButton::toggled,
|
||||||
|
this, [=](bool checked) { mp_ui->localFileButton->setStyleSheet(
|
||||||
|
checked ?"*{font-weight: bold}" : "");});
|
||||||
|
mp_ui->localFileButton->setStyleSheet("*{font-weight: bold}");
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentManagerSide::~ContentManagerSide()
|
||||||
|
{
|
||||||
|
delete mp_ui;
|
||||||
|
}
|
26
src/contentmanagerside.h
Normal file
26
src/contentmanagerside.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef CONTENTMANAGERSIDE_H
|
||||||
|
#define CONTENTMANAGERSIDE_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "contentmanager.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class contentmanagerside;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ContentManagerSide : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ContentManagerSide(QWidget *parent = 0);
|
||||||
|
~ContentManagerSide();
|
||||||
|
|
||||||
|
void setContentManager(ContentManager* contentManager) { mp_contentManager = contentManager; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::contentmanagerside *mp_ui;
|
||||||
|
ContentManager* mp_contentManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTENTMANAGERSIDE_H
|
123
src/contentmanagerside.ui
Normal file
123
src/contentmanagerside.ui
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>contentmanagerside</class>
|
||||||
|
<widget class="QWidget" name="contentmanagerside">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>197</width>
|
||||||
|
<height>366</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="allFileButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>All Files</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="localFileButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Local Files</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="categoryButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Browse By Category</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="languageButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Language</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="contentTypeButton">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Content Type</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
24
src/contentmanagerview.cpp
Normal file
24
src/contentmanagerview.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#include "contentmanagerview.h"
|
||||||
|
#include <QFile>
|
||||||
|
|
||||||
|
ContentManagerView::ContentManagerView(QWidget *parent)
|
||||||
|
: QWebEngineView(parent)
|
||||||
|
{
|
||||||
|
page()->setWebChannel(&m_webChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ContentManagerView::registerObject(const QString& id, QObject* object)
|
||||||
|
{
|
||||||
|
m_webChannel.registerObject(id, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ContentManagerView::setHtml()
|
||||||
|
{
|
||||||
|
QFile contentFile(":texts/_contentManager.html");
|
||||||
|
contentFile.open(QIODevice::ReadOnly);
|
||||||
|
auto byteContent = contentFile.readAll();
|
||||||
|
contentFile.close();
|
||||||
|
QWebEngineView::setHtml(byteContent);
|
||||||
|
}
|
17
src/contentmanagerview.h
Normal file
17
src/contentmanagerview.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#ifndef CONTENTMANAGERVIEW_H
|
||||||
|
#define CONTENTMANAGERVIEW_H
|
||||||
|
|
||||||
|
#include <QWebEngineView>
|
||||||
|
#include <QWebChannel>
|
||||||
|
|
||||||
|
class ContentManagerView : public QWebEngineView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ContentManagerView(QWidget *parent = Q_NULLPTR);
|
||||||
|
void registerObject(const QString &id, QObject *object);
|
||||||
|
void setHtml();
|
||||||
|
private:
|
||||||
|
QWebChannel m_webChannel;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONTENTMANAGERVIEW_H
|
@ -12,7 +12,10 @@
|
|||||||
#include <QPrintDialog>
|
#include <QPrintDialog>
|
||||||
|
|
||||||
KiwixApp::KiwixApp(int& argc, char *argv[])
|
KiwixApp::KiwixApp(int& argc, char *argv[])
|
||||||
: QApplication(argc, argv)
|
: QApplication(argc, argv),
|
||||||
|
m_library(),
|
||||||
|
m_downloader(),
|
||||||
|
m_manager(&m_library, &m_downloader)
|
||||||
{
|
{
|
||||||
m_qtTranslator.load(QLocale(), "qt", "_",
|
m_qtTranslator.load(QLocale(), "qt", "_",
|
||||||
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||||
@ -68,7 +71,10 @@ KiwixApp::KiwixApp(int& argc, char *argv[])
|
|||||||
|
|
||||||
createAction();
|
createAction();
|
||||||
mp_mainWindow = new MainWindow;
|
mp_mainWindow = new MainWindow;
|
||||||
mp_tabWidget = mp_mainWindow->getTabWidget();
|
mp_tabWidget = mp_mainWindow->getTabBar();
|
||||||
|
mp_tabWidget->setContentManagerView(m_manager.getView());
|
||||||
|
mp_mainWindow->getSideContentManager()->setContentManager(&m_manager);
|
||||||
|
setSideBar(CONTENTMANAGER_BAR);
|
||||||
postInit();
|
postInit();
|
||||||
|
|
||||||
mp_errorDialog = new QErrorMessage(mp_mainWindow);
|
mp_errorDialog = new QErrorMessage(mp_mainWindow);
|
||||||
@ -77,6 +83,7 @@ KiwixApp::KiwixApp(int& argc, char *argv[])
|
|||||||
|
|
||||||
KiwixApp::~KiwixApp()
|
KiwixApp::~KiwixApp()
|
||||||
{
|
{
|
||||||
|
m_downloader.close();
|
||||||
delete mp_errorDialog;
|
delete mp_errorDialog;
|
||||||
delete mp_mainWindow;
|
delete mp_mainWindow;
|
||||||
}
|
}
|
||||||
@ -101,7 +108,7 @@ void KiwixApp::openZimFile(const QString &zimfile)
|
|||||||
}
|
}
|
||||||
QString zimId;
|
QString zimId;
|
||||||
try {
|
try {
|
||||||
zimId = m_library.openBook(_zimfile);
|
zimId = m_library.openBookFromPath(_zimfile);
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
showMessage("Cannot open " + _zimfile + ": \n" + e.what());
|
showMessage("Cannot open " + _zimfile + ": \n" + e.what());
|
||||||
return;
|
return;
|
||||||
@ -130,10 +137,29 @@ void KiwixApp::printPage()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KiwixApp::openUrl(const QString &url, bool newTab) {
|
||||||
|
openUrl(QUrl(url), newTab);
|
||||||
|
}
|
||||||
|
|
||||||
void KiwixApp::openUrl(const QUrl &url, bool newTab) {
|
void KiwixApp::openUrl(const QUrl &url, bool newTab) {
|
||||||
mp_tabWidget->openUrl(url, newTab);
|
mp_tabWidget->openUrl(url, newTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KiwixApp::setSideBar(KiwixApp::SideBarType type)
|
||||||
|
{
|
||||||
|
auto sideDockWidget = mp_mainWindow->getSideDockWidget();
|
||||||
|
switch(type) {
|
||||||
|
case SEARCH_BAR:
|
||||||
|
case CONTENTMANAGER_BAR:
|
||||||
|
sideDockWidget->setCurrentIndex(type);
|
||||||
|
sideDockWidget->show();
|
||||||
|
break;
|
||||||
|
case NONE:
|
||||||
|
sideDockWidget->hide();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void KiwixApp::openRandomUrl(bool newTab)
|
void KiwixApp::openRandomUrl(bool newTab)
|
||||||
{
|
{
|
||||||
auto zimId = mp_tabWidget->currentZimId();
|
auto zimId = mp_tabWidget->currentZimId();
|
||||||
@ -220,6 +246,8 @@ void KiwixApp::createAction()
|
|||||||
|
|
||||||
CREATE_ACTION(FindInPageAction, tr("Find in page"));
|
CREATE_ACTION(FindInPageAction, tr("Find in page"));
|
||||||
SET_SHORTCUT(FindInPageAction, QKeySequence::Find);
|
SET_SHORTCUT(FindInPageAction, QKeySequence::Find);
|
||||||
|
connect(mpa_actions[FindInPageAction], &QAction::triggered,
|
||||||
|
this, [=]() { setSideBar(SEARCH_BAR); });
|
||||||
|
|
||||||
CREATE_ACTION_ICON(ToggleFullscreenAction, "full-screen-enter", tr("Set fullScreen"));
|
CREATE_ACTION_ICON(ToggleFullscreenAction, "full-screen-enter", tr("Set fullScreen"));
|
||||||
SET_SHORTCUT(ToggleFullscreenAction, QKeySequence::FullScreen);
|
SET_SHORTCUT(ToggleFullscreenAction, QKeySequence::FullScreen);
|
||||||
@ -277,9 +305,5 @@ void KiwixApp::createAction()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void KiwixApp::postInit() {
|
void KiwixApp::postInit() {
|
||||||
auto realToggleAction = mp_mainWindow->getSideDockWidget()->toggleViewAction();
|
emit(m_library.booksChanged());
|
||||||
auto proxyToggleAction = mpa_actions[FindInPageAction];
|
|
||||||
connect(proxyToggleAction, &QAction::triggered, realToggleAction, &QAction::trigger);
|
|
||||||
connect(realToggleAction, &QAction::toggled, proxyToggleAction, &QAction::setChecked);
|
|
||||||
realToggleAction->toggle();
|
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
#define KIWIXAPP_H
|
#define KIWIXAPP_H
|
||||||
|
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
|
#include "contentmanager.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "tabwidget.h"
|
#include "kiwix/downloader.h"
|
||||||
|
#include "tabbar.h"
|
||||||
#include "tocsidebar.h"
|
#include "tocsidebar.h"
|
||||||
#include "urlschemehandler.h"
|
#include "urlschemehandler.h"
|
||||||
#include "requestinterceptor.h"
|
#include "requestinterceptor.h"
|
||||||
@ -47,12 +49,16 @@ public:
|
|||||||
ExitAction,
|
ExitAction,
|
||||||
MAX_ACTION
|
MAX_ACTION
|
||||||
};
|
};
|
||||||
|
enum SideBarType {
|
||||||
|
SEARCH_BAR,
|
||||||
|
CONTENTMANAGER_BAR,
|
||||||
|
NONE
|
||||||
|
};
|
||||||
|
|
||||||
KiwixApp(int& argc, char *argv[]);
|
KiwixApp(int& argc, char *argv[]);
|
||||||
virtual ~KiwixApp();
|
virtual ~KiwixApp();
|
||||||
static KiwixApp* instance();
|
static KiwixApp* instance();
|
||||||
|
|
||||||
void openUrl(const QUrl& url, bool newTab=true);
|
|
||||||
void openRandomUrl(bool newTab=true);
|
void openRandomUrl(bool newTab=true);
|
||||||
|
|
||||||
void showMessage(const QString& message);
|
void showMessage(const QString& message);
|
||||||
@ -61,11 +67,15 @@ public:
|
|||||||
RequestInterceptor* getRequestInterceptor() { return &m_requestInterceptor; }
|
RequestInterceptor* getRequestInterceptor() { return &m_requestInterceptor; }
|
||||||
Library* getLibrary() { return &m_library; }
|
Library* getLibrary() { return &m_library; }
|
||||||
MainWindow* getMainWindow() { return mp_mainWindow; }
|
MainWindow* getMainWindow() { return mp_mainWindow; }
|
||||||
TabWidget* getTabWidget() { return mp_tabWidget; }
|
kiwix::Downloader* getDownloader() { return &m_downloader; }
|
||||||
|
TabBar* getTabWidget() { return mp_tabWidget; }
|
||||||
QAction* getAction(Actions action);
|
QAction* getAction(Actions action);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void openZimFile(const QString& zimfile="");
|
void openZimFile(const QString& zimfile="");
|
||||||
|
void openUrl(const QString& url, bool newTab=true);
|
||||||
|
void openUrl(const QUrl& url, bool newTab=true);
|
||||||
|
void setSideBar(SideBarType type);
|
||||||
void printPage();
|
void printPage();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -75,8 +85,11 @@ protected:
|
|||||||
private:
|
private:
|
||||||
QTranslator m_qtTranslator, m_appTranslator;
|
QTranslator m_qtTranslator, m_appTranslator;
|
||||||
Library m_library;
|
Library m_library;
|
||||||
|
kiwix::Downloader m_downloader;
|
||||||
|
ContentManager m_manager;
|
||||||
MainWindow* mp_mainWindow;
|
MainWindow* mp_mainWindow;
|
||||||
TabWidget* mp_tabWidget;
|
TabBar* mp_tabWidget;
|
||||||
|
QWidget* mp_currentSideBar;
|
||||||
QErrorMessage* mp_errorDialog;
|
QErrorMessage* mp_errorDialog;
|
||||||
|
|
||||||
UrlSchemeHandler m_schemeHandler;
|
UrlSchemeHandler m_schemeHandler;
|
||||||
|
@ -1,25 +1,65 @@
|
|||||||
#include "library.h"
|
#include "library.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <kiwix/manager.h>
|
||||||
|
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
|
class LibraryManipulator: public kiwix::LibraryManipulator {
|
||||||
|
public:
|
||||||
|
LibraryManipulator(Library* p_library)
|
||||||
|
: mp_library(p_library) {}
|
||||||
|
bool addBookToLibrary(kiwix::Book book) {
|
||||||
|
auto ret = mp_library->m_library.addBook(book);
|
||||||
|
emit(mp_library->booksChanged());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
Library* mp_library;
|
||||||
|
};
|
||||||
|
|
||||||
Library::Library()
|
Library::Library()
|
||||||
{
|
{
|
||||||
|
auto manipulator = LibraryManipulator(this);
|
||||||
|
auto manager = kiwix::Manager(&manipulator);
|
||||||
|
qInfo() << QString::fromStdString(getDataDirectory());
|
||||||
|
manager.readFile(appendToDirectory(getDataDirectory(),"library.xml"), false);
|
||||||
|
qInfo() << getBookIds().length();
|
||||||
|
emit(booksChanged());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Library::openBook(const QString &zimPath)
|
Library::~Library()
|
||||||
|
{
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Library::openBookFromPath(const QString &zimPath)
|
||||||
{
|
{
|
||||||
for(auto it=m_readersMap.begin();
|
for(auto it=m_readersMap.begin();
|
||||||
it != m_readersMap.end();
|
it != m_readersMap.end();
|
||||||
it++)
|
it++)
|
||||||
{
|
{
|
||||||
if(QString::fromStdString(it->second->getZimFilePath()) == zimPath)
|
if(QString::fromStdString(it.value()->getZimFilePath()) == zimPath)
|
||||||
return it->first;
|
return it.key();
|
||||||
}
|
}
|
||||||
qInfo() << "Opening" << zimPath;
|
qInfo() << "Opening" << zimPath;
|
||||||
auto zimPath_ = zimPath.toStdString();
|
auto zimPath_ = zimPath.toStdString();
|
||||||
auto reader = std::shared_ptr<kiwix::Reader>(new kiwix::Reader(zimPath_));
|
auto reader = std::shared_ptr<kiwix::Reader>(new kiwix::Reader(zimPath_));
|
||||||
auto id = QString::fromStdString(reader->getId() + ".zim");
|
auto _id(reader->getId());
|
||||||
|
auto id = QString::fromStdString(_id + ".zim");
|
||||||
|
kiwix::Book b;
|
||||||
|
b.update(*reader);
|
||||||
|
m_library.addBook(b);
|
||||||
|
m_readersMap[id] = reader;
|
||||||
|
save();
|
||||||
|
emit(booksChanged());
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Library::openBookById(const QString& _id)
|
||||||
|
{
|
||||||
|
auto& b = m_library.getBookById(_id.toStdString());
|
||||||
|
auto reader = std::shared_ptr<kiwix::Reader>(new kiwix::Reader(b.getPath()));
|
||||||
|
auto id = _id + ".zim";
|
||||||
m_readersMap[id] = reader;
|
m_readersMap[id] = reader;
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -28,6 +68,40 @@ std::shared_ptr<kiwix::Reader> Library::getReader(const QString &zimId)
|
|||||||
{
|
{
|
||||||
auto it = m_readersMap.find(zimId);
|
auto it = m_readersMap.find(zimId);
|
||||||
if (it != m_readersMap.end())
|
if (it != m_readersMap.end())
|
||||||
return it->second;
|
return it.value();
|
||||||
|
// No reader, try to open the file
|
||||||
|
try {
|
||||||
|
QString _id = zimId;
|
||||||
|
if (_id.endsWith(".zim")) _id.resize(_id.size()-4);
|
||||||
|
openBookById(_id);
|
||||||
|
return m_readersMap.find(zimId).value();
|
||||||
|
} catch(...) {}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList Library::getBookIds()
|
||||||
|
{
|
||||||
|
QStringList list;
|
||||||
|
for(auto& id: m_library.getBooksIds()) {
|
||||||
|
list.append(QString::fromStdString(id));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Library::addBookToLibrary(kiwix::Book &book)
|
||||||
|
{
|
||||||
|
m_library.addBook(book);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Library::save()
|
||||||
|
{
|
||||||
|
m_library.writeToFile(appendToDirectory(getDataDirectory(),"library.xml"));
|
||||||
|
}
|
||||||
|
|
||||||
|
kiwix::Book &Library::getBookById(QString id)
|
||||||
|
{
|
||||||
|
if (id.endsWith(".zim")) {
|
||||||
|
id.resize(id.size()-4);
|
||||||
|
}
|
||||||
|
return m_library.getBookById(id.toStdString());
|
||||||
|
}
|
||||||
|
@ -1,18 +1,47 @@
|
|||||||
#ifndef LIBRARY_H
|
#ifndef LIBRARY_H
|
||||||
#define LIBRARY_H
|
#define LIBRARY_H
|
||||||
|
|
||||||
#include <kiwix/manager.h>
|
#include <kiwix/book.h>
|
||||||
#include <map>
|
#include <kiwix/library.h>
|
||||||
|
#include <kiwix/reader.h>
|
||||||
#include <qstring.h>
|
#include <qstring.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class Library : public kiwix::Manager
|
#include <QObject>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#define TQS(v) (QString::fromStdString(v))
|
||||||
|
#define FORWARD_GETTER(METH) QString METH() const { return TQS(mp_book->METH()); }
|
||||||
|
|
||||||
|
#undef FORWARD_GETTER
|
||||||
|
#undef TQS
|
||||||
|
|
||||||
|
class LibraryManipulator;
|
||||||
|
|
||||||
|
class Library : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QStringList bookIds READ getBookIds NOTIFY booksChanged)
|
||||||
public:
|
public:
|
||||||
Library();
|
Library();
|
||||||
QString openBook(const QString& zimPath);
|
virtual ~Library();
|
||||||
|
QString openBookFromPath(const QString& zimPath);
|
||||||
std::shared_ptr<kiwix::Reader> getReader(const QString& zimId);
|
std::shared_ptr<kiwix::Reader> getReader(const QString& zimId);
|
||||||
|
QStringList getBookIds();
|
||||||
|
void addBookToLibrary(kiwix::Book& book);
|
||||||
|
void save();
|
||||||
|
public slots:
|
||||||
|
QString openBookById(const QString& _id);
|
||||||
|
kiwix::Book& getBookById(QString id);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void booksChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<QString, std::shared_ptr<kiwix::Reader>> m_readersMap;
|
kiwix::Library m_library;
|
||||||
|
QMap<QString, std::shared_ptr<kiwix::Reader>> m_readersMap;
|
||||||
|
friend class LibraryManipulator;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LIBRARY_H
|
#endif // LIBRARY_H
|
||||||
|
@ -16,7 +16,7 @@ int main(int argc, char *argv[])
|
|||||||
auto positionalArguments = parser.positionalArguments();
|
auto positionalArguments = parser.positionalArguments();
|
||||||
if (positionalArguments.size() >= 1){
|
if (positionalArguments.size() >= 1){
|
||||||
zimfile = parser.positionalArguments().at(0);
|
zimfile = parser.positionalArguments().at(0);
|
||||||
|
a.openZimFile(zimfile);
|
||||||
}
|
}
|
||||||
a.openZimFile(zimfile);
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,8 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
mp_about(new About(this))
|
mp_about(new About(this))
|
||||||
{
|
{
|
||||||
mp_ui->setupUi(this);
|
mp_ui->setupUi(this);
|
||||||
mp_ui->tabWidget->tabBar()->setExpanding(false);
|
mp_ui->tabBar->setExpanding(false);
|
||||||
|
mp_ui->tabBar->setStackedWidget(mp_ui->mainView);
|
||||||
auto app = KiwixApp::instance();
|
auto app = KiwixApp::instance();
|
||||||
connect(app->getAction(KiwixApp::ExitAction), &QAction::triggered,
|
connect(app->getAction(KiwixApp::ExitAction), &QAction::triggered,
|
||||||
this, &QMainWindow::close);
|
this, &QMainWindow::close);
|
||||||
@ -39,12 +40,17 @@ void MainWindow::toggleFullScreen() {
|
|||||||
showFullScreen();
|
showFullScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
TabWidget* MainWindow::getTabWidget()
|
TabBar* MainWindow::getTabBar()
|
||||||
{
|
{
|
||||||
return mp_ui->tabWidget;
|
return mp_ui->tabBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDockWidget* MainWindow::getSideDockWidget()
|
QStackedWidget *MainWindow::getSideDockWidget()
|
||||||
{
|
{
|
||||||
return mp_ui->sideDockWidget;
|
return mp_ui->sideBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
ContentManagerSide *MainWindow::getSideContentManager()
|
||||||
|
{
|
||||||
|
return mp_ui->contentmanagerside;
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,10 @@
|
|||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include "webview.h"
|
#include "webview.h"
|
||||||
#include "tabwidget.h"
|
#include "tabbar.h"
|
||||||
#include "tocsidebar.h"
|
#include "tocsidebar.h"
|
||||||
#include "about.h"
|
#include "about.h"
|
||||||
|
#include "contentmanagerside.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
@ -20,8 +21,9 @@ public:
|
|||||||
explicit MainWindow(QWidget *parent = 0);
|
explicit MainWindow(QWidget *parent = 0);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
TabWidget* getTabWidget();
|
TabBar* getTabBar();
|
||||||
QDockWidget* getSideDockWidget();
|
QStackedWidget* getSideDockWidget();
|
||||||
|
ContentManagerSide* getSideContentManager();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void toggleFullScreen();
|
void toggleFullScreen();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "tabwidget.h"
|
#include "tabbar.h"
|
||||||
|
|
||||||
#include "kiwixapp.h"
|
#include "kiwixapp.h"
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
@ -7,15 +7,15 @@
|
|||||||
#define QUITIFNOTCURRENT(VIEW) if((VIEW)!=currentWidget()) {return;}
|
#define QUITIFNOTCURRENT(VIEW) if((VIEW)!=currentWidget()) {return;}
|
||||||
#define CURRENTIFNULL(VIEW) if(nullptr==VIEW) { VIEW = currentWidget();}
|
#define CURRENTIFNULL(VIEW) if(nullptr==VIEW) { VIEW = currentWidget();}
|
||||||
|
|
||||||
TabWidget::TabWidget(QWidget *parent) :
|
TabBar::TabBar(QWidget *parent) :
|
||||||
QTabWidget(parent)
|
QTabBar(parent)
|
||||||
{
|
{
|
||||||
setTabsClosable(true);
|
setTabsClosable(true);
|
||||||
setElideMode(Qt::ElideNone);
|
setElideMode(Qt::ElideNone);
|
||||||
setDocumentMode(true);
|
setDocumentMode(true);
|
||||||
setFocusPolicy(Qt::NoFocus);
|
setFocusPolicy(Qt::NoFocus);
|
||||||
connect(this, &QTabWidget::tabCloseRequested, this, &TabWidget::closeTab);
|
connect(this, &QTabBar::tabCloseRequested, this, &TabBar::closeTab);
|
||||||
connect(this, &QTabWidget::currentChanged, this, &TabWidget::onCurrentChanged);
|
connect(this, &QTabBar::currentChanged, this, &TabBar::onCurrentChanged);
|
||||||
auto app = KiwixApp::instance();
|
auto app = KiwixApp::instance();
|
||||||
connect(app->getAction(KiwixApp::NewTabAction), &QAction::triggered,
|
connect(app->getAction(KiwixApp::NewTabAction), &QAction::triggered,
|
||||||
this, [=]() {
|
this, [=]() {
|
||||||
@ -27,10 +27,14 @@ TabWidget::TabWidget(QWidget *parent) :
|
|||||||
connect(app->getAction(KiwixApp::CloseTabAction), &QAction::triggered,
|
connect(app->getAction(KiwixApp::CloseTabAction), &QAction::triggered,
|
||||||
this, [=]() {
|
this, [=]() {
|
||||||
auto index = this->currentIndex();
|
auto index = this->currentIndex();
|
||||||
if (-1 == index) {
|
if (index <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->closeTab(index);
|
this->closeTab(index);
|
||||||
|
auto widget = mp_stackedWidget->widget(index);
|
||||||
|
mp_stackedWidget->removeWidget(widget);
|
||||||
|
widget->setParent(nullptr);
|
||||||
|
delete widget;
|
||||||
});
|
});
|
||||||
connect(app->getAction(KiwixApp::ZoomInAction), &QAction::triggered,
|
connect(app->getAction(KiwixApp::ZoomInAction), &QAction::triggered,
|
||||||
this, [=]() {
|
this, [=]() {
|
||||||
@ -58,7 +62,22 @@ TabWidget::TabWidget(QWidget *parent) :
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
WebView* TabWidget::createNewTab(bool setCurrent)
|
void TabBar::setStackedWidget(QStackedWidget *widget) {
|
||||||
|
mp_stackedWidget = widget;
|
||||||
|
connect(this, &QTabBar::currentChanged,
|
||||||
|
widget, &QStackedWidget::setCurrentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TabBar::setContentManagerView(ContentManagerView* view)
|
||||||
|
{
|
||||||
|
qInfo() << "add widget";
|
||||||
|
mp_contentManagerView = view;
|
||||||
|
mp_stackedWidget->addWidget(mp_contentManagerView);
|
||||||
|
mp_stackedWidget->show();
|
||||||
|
addTab("contentManager");
|
||||||
|
}
|
||||||
|
|
||||||
|
WebView* TabBar::createNewTab(bool setCurrent)
|
||||||
{
|
{
|
||||||
WebView* webView = new WebView();
|
WebView* webView = new WebView();
|
||||||
connect(webView, &WebView::titleChanged, this,
|
connect(webView, &WebView::titleChanged, this,
|
||||||
@ -72,14 +91,15 @@ WebView* TabWidget::createNewTab(bool setCurrent)
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
// Ownership of webview is passed to the tabWidget
|
// Ownership of webview is passed to the tabWidget
|
||||||
addTab(webView, "");
|
mp_stackedWidget->addWidget(webView);
|
||||||
|
auto index = addTab("");
|
||||||
if (setCurrent) {
|
if (setCurrent) {
|
||||||
setCurrentWidget(webView);
|
setCurrentIndex(index);
|
||||||
}
|
}
|
||||||
return webView;
|
return webView;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabWidget::openUrl(const QUrl& url, bool newTab)
|
void TabBar::openUrl(const QUrl& url, bool newTab)
|
||||||
{
|
{
|
||||||
WebView* webView = currentWidget();
|
WebView* webView = currentWidget();
|
||||||
if (newTab || !webView) {
|
if (newTab || !webView) {
|
||||||
@ -89,31 +109,31 @@ void TabWidget::openUrl(const QUrl& url, bool newTab)
|
|||||||
webView->setUrl(url);
|
webView->setUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabWidget::setTitleOf(const QString& title, WebView* webView)
|
void TabBar::setTitleOf(const QString& title, WebView* webView)
|
||||||
{
|
{
|
||||||
CURRENTIFNULL(webView);
|
CURRENTIFNULL(webView);
|
||||||
if (title.startsWith("zim://")) {
|
if (title.startsWith("zim://")) {
|
||||||
auto url = QUrl(title);
|
auto url = QUrl(title);
|
||||||
setTabText(indexOf(webView), url.path());
|
setTabText(mp_stackedWidget->indexOf(webView), url.path());
|
||||||
} else {
|
} else {
|
||||||
setTabText(indexOf(webView), title);
|
setTabText(mp_stackedWidget->indexOf(webView), title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabWidget::setIconOf(const QIcon &icon, WebView *webView)
|
void TabBar::setIconOf(const QIcon &icon, WebView *webView)
|
||||||
{
|
{
|
||||||
CURRENTIFNULL(webView);
|
CURRENTIFNULL(webView);
|
||||||
setTabIcon(indexOf(webView), icon);
|
setTabIcon(mp_stackedWidget->indexOf(webView), icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TabWidget::currentZimId()
|
QString TabBar::currentZimId()
|
||||||
{
|
{
|
||||||
if (!currentWidget())
|
if (!currentWidget())
|
||||||
return "";
|
return "";
|
||||||
return currentWidget()->zimId();
|
return currentWidget()->zimId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabWidget::triggerWebPageAction(QWebEnginePage::WebAction action, WebView *webView)
|
void TabBar::triggerWebPageAction(QWebEnginePage::WebAction action, WebView *webView)
|
||||||
{
|
{
|
||||||
CURRENTIFNULL(webView);
|
CURRENTIFNULL(webView);
|
||||||
QUITIFNULL(webView);
|
QUITIFNULL(webView);
|
||||||
@ -121,20 +141,29 @@ void TabWidget::triggerWebPageAction(QWebEnginePage::WebAction action, WebView *
|
|||||||
webView->setFocus();
|
webView->setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabWidget::closeTab(int index)
|
void TabBar::closeTab(int index)
|
||||||
{
|
{
|
||||||
|
if (index == 0)
|
||||||
|
return;
|
||||||
auto webview = widget(index);
|
auto webview = widget(index);
|
||||||
removeTab(index);
|
removeTab(index);
|
||||||
webview->close();
|
webview->close();
|
||||||
delete webview;
|
delete webview;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabWidget::onCurrentChanged(int index)
|
void TabBar::onCurrentChanged(int index)
|
||||||
{
|
{
|
||||||
if (index != -1)
|
if (index == -1)
|
||||||
|
return;
|
||||||
|
if (index)
|
||||||
{
|
{
|
||||||
auto view = widget(index);
|
auto view = widget(index);
|
||||||
emit webActionEnabledChanged(QWebEnginePage::Back, view->isWebActionEnabled(QWebEnginePage::Back));
|
emit webActionEnabledChanged(QWebEnginePage::Back, view->isWebActionEnabled(QWebEnginePage::Back));
|
||||||
emit webActionEnabledChanged(QWebEnginePage::Forward, view->isWebActionEnabled(QWebEnginePage::Forward));
|
emit webActionEnabledChanged(QWebEnginePage::Forward, view->isWebActionEnabled(QWebEnginePage::Forward));
|
||||||
|
KiwixApp::instance()->setSideBar(KiwixApp::NONE);
|
||||||
|
} else {
|
||||||
|
emit webActionEnabledChanged(QWebEnginePage::Back, false);
|
||||||
|
emit webActionEnabledChanged(QWebEnginePage::Forward, false);
|
||||||
|
KiwixApp::instance()->setSideBar(KiwixApp::CONTENTMANAGER_BAR);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,20 +1,27 @@
|
|||||||
#ifndef TABWIDGET_H
|
#ifndef TABWIDGET_H
|
||||||
#define TABWIDGET_H
|
#define TABWIDGET_H
|
||||||
|
|
||||||
#include <QTableWidget>
|
#include <QTabBar>
|
||||||
|
#include <QStackedWidget>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "webview.h"
|
#include "webview.h"
|
||||||
|
#include "contentmanagerview.h"
|
||||||
|
|
||||||
class TabWidget : public QTabWidget
|
class TabBar : public QTabBar
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString currentZimId READ currentZimId NOTIFY currentZimIdChanged)
|
Q_PROPERTY(QString currentZimId READ currentZimId NOTIFY currentZimIdChanged)
|
||||||
public:
|
public:
|
||||||
TabWidget(QWidget* parent=nullptr);
|
TabBar(QWidget* parent=nullptr);
|
||||||
|
void setStackedWidget(QStackedWidget* widget);
|
||||||
|
|
||||||
|
void setContentManagerView(ContentManagerView* view);
|
||||||
WebView* createNewTab(bool setCurrent);
|
WebView* createNewTab(bool setCurrent);
|
||||||
WebView* widget(int index) { return static_cast<WebView*>(QTabWidget::widget(index)); }
|
WebView* widget(int index) { return (index != 0) ? static_cast<WebView*>(mp_stackedWidget->widget(index)) : nullptr; }
|
||||||
WebView* currentWidget() { return static_cast<WebView*>(QTabWidget::currentWidget()); }
|
WebView* currentWidget() { auto current = mp_stackedWidget->currentWidget();
|
||||||
|
if (current == mp_contentManagerView) return nullptr;
|
||||||
|
return static_cast<WebView*>(current);
|
||||||
|
}
|
||||||
|
|
||||||
void openUrl(const QUrl &url, bool newTab);
|
void openUrl(const QUrl &url, bool newTab);
|
||||||
// Redirect call to sub-webView
|
// Redirect call to sub-webView
|
||||||
@ -30,6 +37,11 @@ signals:
|
|||||||
public slots:
|
public slots:
|
||||||
void closeTab(int index);
|
void closeTab(int index);
|
||||||
void onCurrentChanged(int index);
|
void onCurrentChanged(int index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ContentManagerView* mp_contentManagerView;
|
||||||
|
QStackedWidget* mp_stackedWidget;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TABWIDGET_H
|
#endif // TABWIDGET_H
|
@ -8,6 +8,8 @@ TocSideBar::TocSideBar(QWidget *parent) :
|
|||||||
{
|
{
|
||||||
mp_ui->setupUi(this);
|
mp_ui->setupUi(this);
|
||||||
mp_findLineEdit = mp_ui->findEdit;
|
mp_findLineEdit = mp_ui->findEdit;
|
||||||
|
connect(mp_ui->hideButton, &QPushButton::released,
|
||||||
|
this, [=]() { KiwixApp::instance()->setSideBar(KiwixApp::NONE);});
|
||||||
connect(mp_ui->fNextButton, &QPushButton::released,
|
connect(mp_ui->fNextButton, &QPushButton::released,
|
||||||
this, &TocSideBar::findNext);
|
this, &TocSideBar::findNext);
|
||||||
connect(mp_ui->fPreviousButton, &QPushButton::released,
|
connect(mp_ui->fPreviousButton, &QPushButton::released,
|
||||||
|
@ -20,75 +20,97 @@
|
|||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<property name="sizeConstraint">
|
|
||||||
<enum>QLayout::SetMaximumSize</enum>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,0">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="sizeConstraint">
|
|
||||||
<enum>QLayout::SetMaximumSize</enum>
|
|
||||||
</property>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="findEdit"/>
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="hideButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Hide</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="fNextButton">
|
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0">
|
||||||
<property name="text">
|
<property name="spacing">
|
||||||
<string/>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="sizeConstraint">
|
||||||
<iconset resource="../resources/kiwix.qrc">
|
<enum>QLayout::SetMaximumSize</enum>
|
||||||
<normaloff>:/icons/search_forward.svg</normaloff>:/icons/search_forward.svg</iconset>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="flat">
|
<item>
|
||||||
<bool>true</bool>
|
<widget class="QLineEdit" name="findEdit"/>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item>
|
||||||
|
<widget class="QPushButton" name="fNextButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../resources/kiwix.qrc">
|
||||||
|
<normaloff>:/icons/search_forward.svg</normaloff>:/icons/search_forward.svg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="fPreviousButton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../resources/kiwix.qrc">
|
||||||
|
<normaloff>:/icons/search_backward.svg</normaloff>:/icons/search_backward.svg</iconset>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="fPreviousButton">
|
<spacer name="verticalSpacer">
|
||||||
<property name="text">
|
<property name="orientation">
|
||||||
<string/>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="sizeHint" stdset="0">
|
||||||
<iconset resource="../resources/kiwix.qrc">
|
<size>
|
||||||
<normaloff>:/icons/search_backward.svg</normaloff>:/icons/search_backward.svg</iconset>
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="flat">
|
</spacer>
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
|
111
ui/mainwindow.ui
111
ui/mainwindow.ui
@ -24,6 +24,9 @@
|
|||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
@ -37,21 +40,58 @@
|
|||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="TabWidget" name="tabWidget">
|
<widget class="TabBar" name="tabBar" native="true"/>
|
||||||
<property name="tabShape">
|
</item>
|
||||||
<enum>QTabWidget::Rounded</enum>
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex">
|
<item>
|
||||||
<number>-1</number>
|
<widget class="QStackedWidget" name="sideBar">
|
||||||
</property>
|
<property name="enabled">
|
||||||
<property name="documentMode">
|
<bool>true</bool>
|
||||||
<bool>false</bool>
|
</property>
|
||||||
</property>
|
<property name="sizePolicy">
|
||||||
</widget>
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="TocSideBar" name="tocsidebar"/>
|
||||||
|
<widget class="ContentManagerSide" name="contentmanagerside">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QStackedWidget" name="mainView"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="TopWidget" name="mainToolBar">
|
<widget class="TopWidget" name="mainToolBar">
|
||||||
|
<property name="movable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="floatable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<attribute name="toolBarArea">
|
<attribute name="toolBarArea">
|
||||||
<enum>TopToolBarArea</enum>
|
<enum>TopToolBarArea</enum>
|
||||||
</attribute>
|
</attribute>
|
||||||
@ -60,39 +100,6 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusBar"/>
|
<widget class="QStatusBar" name="statusBar"/>
|
||||||
<widget class="QDockWidget" name="sideDockWidget">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="floating">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="features">
|
|
||||||
<set>QDockWidget::DockWidgetClosable</set>
|
|
||||||
</property>
|
|
||||||
<property name="allowedAreas">
|
|
||||||
<set>Qt::LeftDockWidgetArea</set>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Find in page</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="dockWidgetArea">
|
|
||||||
<number>1</number>
|
|
||||||
</attribute>
|
|
||||||
<widget class="QWidget" name="dockWidgetContents">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="TocSideBar" name="tocPage" native="true"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
@ -101,18 +108,24 @@
|
|||||||
<extends>QToolBar</extends>
|
<extends>QToolBar</extends>
|
||||||
<header>src/topwidget.h</header>
|
<header>src/topwidget.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
|
||||||
<class>TabWidget</class>
|
|
||||||
<extends>QTabWidget</extends>
|
|
||||||
<header>src/tabwidget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>TocSideBar</class>
|
<class>TocSideBar</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>src/tocsidebar.h</header>
|
<header>src/tocsidebar.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>TabBar</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>src/tabbar.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>ContentManagerSide</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>src/contentmanagerside.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user