Use tabs to display KiwixWebView.

This is the first step to handling several zim file at the same time.

- The Library class is used has a handler mapping zimId to kiwix::Reader.
- The KiwixWebView display url of the form : "zim://<zimId>.zim/path".
- The KiwixSchemeHandler uses the host (containing the zimid) to get
  the reader from the library and serve the content.
This commit is contained in:
Matthieu Gautier 2018-07-17 14:30:47 +02:00
parent bb9f60acc7
commit 7e4c042824
11 changed files with 108 additions and 79 deletions

View File

@ -36,7 +36,8 @@ SOURCES += \
kiwixapp.cpp \
blobbuffer.cpp \
kiwixrequestinterceptor.cpp \
kiwixwebview.cpp
kiwixwebview.cpp \
library.cpp
HEADERS += \
mainwindow.h \
@ -44,7 +45,8 @@ HEADERS += \
kiwixapp.h \
blobbuffer.h \
kiwixrequestinterceptor.h \
kiwixwebview.h
kiwixwebview.h \
library.h
FORMS += \
mainwindow.ui

View File

@ -2,8 +2,7 @@
#include "zim/error.h"
KiwixApp::KiwixApp(int& argc, char *argv[])
: QApplication(argc, argv),
reader(nullptr)
: QApplication(argc, argv)
{
mainWindow = new MainWindow;
setApplicationName("kiwix-desktop");
@ -13,30 +12,17 @@ KiwixApp::KiwixApp(int& argc, char *argv[])
KiwixApp::~KiwixApp()
{
delete mainWindow;
if (reader)
delete reader;
}
void KiwixApp::openZimFile(const QString &zimfile)
{
if (reader)
delete reader;
const std::string zimfile_ = zimfile.toLocal8Bit().constData();
std::cout << "Opening " << zimfile_ << std::endl;
try {
reader = new kiwix::Reader(zimfile_);
} catch (const zim::ZimFileFormatError& e) {
std::cout << "Cannot open " << zimfile_ << std::endl;
std::cout << e.what() << std::endl;
reader = nullptr;
auto zimId = library.openBook(zimfile);
mainWindow->displayReader(library.getReader(zimId));
} catch (const std::exception& e) {
std::cout << "oup" << e.what() << std::endl;
reader = nullptr;
}
}
kiwix::Reader* KiwixApp::getReader()
{
return reader;
}

View File

@ -5,7 +5,7 @@
#include "kiwixrequestinterceptor.h"
#include <QApplication>
#include <kiwix/reader.h>
#include "library.h"
#include "mainwindow.h"
@ -16,12 +16,16 @@ public:
virtual ~KiwixApp();
void openZimFile(const QString& zimfile);
kiwix::Reader* getReader();
KiwixSchemeHandler* getSchemeHandler() { return &schemeHandler; }
KiwixRequestInterceptor* getRequestInterceptor() { return &requestIntercetor; }
Library* getLibrary() { return &library; }
private:
kiwix::Reader* reader;
Library library;
MainWindow* mainWindow;
KiwixSchemeHandler schemeHandler;
KiwixRequestInterceptor requestIntercetor;
};
#endif // KIWIXAPP_H

View File

@ -16,11 +16,14 @@ void
KiwixSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request)
{
std::cout << "Handling request " << request->requestUrl().toString().toUtf8().constData() << std::endl;
std::string url = request->requestUrl().path().toUtf8().constData();
auto qurl = request->requestUrl();
std::string url = qurl.path().toUtf8().constData();
std::cout << "Url is " << url << std::endl;
if (url[0] == '/')
url = url.substr(1);
auto reader = static_cast<KiwixApp*>(KiwixApp::instance())->getReader();
auto library = static_cast<KiwixApp*>(KiwixApp::instance())->getLibrary();
auto zim_id = qurl.host();
auto reader = library->getReader(zim_id);
if ( reader == nullptr) {
request->fail(QWebEngineUrlRequestJob::UrlNotFound);
return;

View File

@ -2,15 +2,25 @@
#include <QWebEngineProfile>
#include <iostream>
#include "kiwixapp.h"
KiwixWebView::KiwixWebView(QWidget *parent)
: QWebEngineView(parent)
{
auto profile = page()->profile();
profile->installUrlSchemeHandler("zim", &schemeHandler);
profile->setRequestInterceptor(&requestInterceptor);
auto app = static_cast<KiwixApp*>(KiwixApp::instance());
profile->installUrlSchemeHandler("zim", app->getSchemeHandler());
profile->setRequestInterceptor(app->getRequestInterceptor());
}
KiwixWebView::~KiwixWebView()
{}
void KiwixWebView::initFromReader(std::shared_ptr<kiwix::Reader> reader)
{
std::string url("zim://");
url += reader->getId();
url += ".zim/";
page()->setUrl(QUrl(QString::fromStdString(url)));
}

View File

@ -2,9 +2,7 @@
#define KIWIXWEBVIEW_H
#include <QWebEngineView>
#include "kiwixschemehandler.h"
#include "kiwixrequestinterceptor.h"
#include <kiwix/reader.h>
class KiwixWebView : public QWebEngineView
{
@ -14,9 +12,7 @@ public:
KiwixWebView(QWidget *parent = Q_NULLPTR);
virtual ~KiwixWebView();
private:
KiwixSchemeHandler schemeHandler;
KiwixRequestInterceptor requestInterceptor;
void initFromReader(std::shared_ptr<kiwix::Reader> reader);
};
#endif // KIWIXWEBVIEW_H

30
library.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "library.h"
Library::Library()
{
}
QString Library::openBook(const QString &zimPath)
{
for(auto it=readers_map.begin();
it != readers_map.end();
it++)
{
if(QString::fromStdString(it->second->getZimFilePath()) == zimPath)
return it->first;
}
const std::string zimPath_ = zimPath.toLocal8Bit().constData();
auto reader = std::shared_ptr<kiwix::Reader>(new kiwix::Reader(zimPath_));
auto id = QString::fromStdString(reader->getId() + ".zim");
readers_map[id] = reader;
return id;
}
std::shared_ptr<kiwix::Reader> Library::getReader(const QString &zimId)
{
auto it = readers_map.find(zimId);
if (it != readers_map.end())
return it->second;
return nullptr;
}

18
library.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef LIBRARY_H
#define LIBRARY_H
#include <kiwix/manager.h>
#include <map>
#include <qstring.h>
class Library : public kiwix::Manager
{
public:
Library();
QString openBook(const QString& zimPath);
std::shared_ptr<kiwix::Reader> getReader(const QString& zimId);
private:
std::map<QString, std::shared_ptr<kiwix::Reader>> readers_map;
};
#endif // LIBRARY_H

View File

@ -9,10 +9,7 @@ MainWindow::MainWindow(QWidget *parent) :
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->webview->page()->setUrl(QUrl("http://foo.zim"));
//ui->webview->page()->setUrl(QUrl("http://localhost:8080"));
QObject::connect(ui->webview, SIGNAL(urlChanged(const QUrl&)), this, SLOT(on_urlChanged_triggered(const QUrl&)));
ui->tabWidget->tabBar()->setExpanding(false);
}
MainWindow::~MainWindow()
@ -20,14 +17,16 @@ MainWindow::~MainWindow()
delete ui;
}
void MainWindow::on_pushButton_clicked()
void MainWindow::displayReader(std::shared_ptr<kiwix::Reader> reader)
{
ui->webview->reload();
}
void MainWindow::on_urlChanged_triggered(const QUrl& url)
{
std::cout << "new url : " << url.toString().toUtf8().constData() << std::endl;
ui->addressBar->setText(url.toString());
auto webview = new KiwixWebView();
std::string favicon_content;
std::string favicon_mimetype;
reader->getFavicon(favicon_content, favicon_mimetype);
QPixmap pixmap;
pixmap.loadFromData((const uchar*)favicon_content.data(), favicon_content.size());
auto icon = QIcon(pixmap);
// Ownership of webview is passed to the tabWidget
ui->tabWidget->addTab(webview, icon, QString::fromStdString(reader->getTitle()));
webview->initFromReader(reader);
}

View File

@ -2,6 +2,7 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include "kiwixwebview.h"
namespace Ui {
class MainWindow;
@ -15,12 +16,11 @@ public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_urlChanged_triggered(const QUrl& url);
void displayReader(std::shared_ptr<kiwix::Reader> reader);
private:
Ui::MainWindow *ui;
std::map<std::shared_ptr<kiwix::Reader>, KiwixWebView*> webviews_map;
};
#endif // MAINWINDOW_H

View File

@ -16,29 +16,18 @@
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
<widget class="QTabWidget" name="tabWidget">
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<item>
<widget class="QLineEdit" name="addressBar">
<property name="enabled">
<property name="currentIndex">
<number>-1</number>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="refreshButton">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="KiwixWebView" name="webview" native="true"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menuBar">
@ -68,14 +57,6 @@
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>KiwixWebView</class>
<extends>QWidget</extends>
<header>kiwixwebview.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>