Merge pull request #1123 from kiwix/pdfSmth

Show Open/Save dialog on downloading files
This commit is contained in:
Kelson 2024-12-08 15:30:10 +01:00 committed by GitHub
commit 9fe3a3f8b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 298 additions and 132 deletions

View File

@ -56,7 +56,7 @@ SOURCES += \
src/findinpagebar.cpp \
src/flowlayout.cpp \
src/kiwixchoicebox.cpp \
src/kiwixconfirmbox.cpp \
src/kiwixmessagebox.cpp \
src/kiwixlineedit.cpp \
src/kiwixlistwidget.cpp \
src/kiwixloader.cpp \
@ -109,7 +109,7 @@ HEADERS += \
src/findinpagebar.h \
src/flowlayout.h \
src/kiwixchoicebox.h \
src/kiwixconfirmbox.h \
src/kiwixmessagebox.h \
src/kiwixlineedit.h \
src/kiwixlistwidget.h \
src/kiwixloader.h \
@ -159,7 +159,7 @@ FORMS += \
src/contentmanagerview.ui \
src/findinpagebar.ui \
ui/kiwixchoicebox.ui \
ui/kiwixconfirmbox.ui \
ui/kiwixmessagebox.ui \
ui/mainwindow.ui \
ui/about.ui \
src/contentmanagerside.ui \

View File

@ -29,4 +29,11 @@ QPushButton:hover {
color: white;
}
#closeButton {
border: 0;
}
#closeButton:hover {
background-color: transparent;
}

View File

@ -9,6 +9,7 @@
"error-downloader-launch-message":"Impossible to launch downloader, Kiwix-desktop will start but all download functions will not working!",
"error-launch-server-message":"An error has occured!",
"error-archive":"Cannot get the archive",
"error-opening-file": "There was an error opening the file.",
"open-zim":"Open ZIM File",
"local-kiwix-server":"Local Kiwix Server",
"random-article":"Random Article",
@ -23,6 +24,7 @@
"reopen-closed-tab":"Reopen closed tab",
"browse-library":"Browse library",
"open-file":"Open file",
"save-file": "Save file",
"open-recent":"Open recent",
"search-article":"Search article",
"search-in-library":"Search in library",
@ -45,6 +47,7 @@
"donate-to-support-kiwix":"Donate to support Kiwix",
"exit":"Exit",
"save-file-as-window-title":"Save File as",
"download-finished": "Download Finished",
"download-finished-message":"The document has been downloaded.",
"file":"File",
"edit":"Edit",
@ -180,5 +183,7 @@
"stop": "Stop",
"voice": "Voice",
"select-read-voice": "Select reading voice",
"select-read-language": "Select reading language"
"select-read-language": "Select reading language",
"save-or-open": "Save or Open file",
"save-or-open-text": "What should Kiwix do with this file?"
}

View File

@ -17,6 +17,7 @@
"error-downloader-launch-message": "Error text displayed to elaborate on the effect of the downloader failure.",
"error-launch-server-message": "Error text displayed when Kiwix server failed to launch.",
"error-archive": "Error text displayed when the retrieving the archive of a ZIM file failed.",
"error-opening-file": "Error text displayed when opening a downloaded file with an external application fails.",
"open-zim": "Caption text for file explorer window used to choose a ZIM file.",
"local-kiwix-server": "Describes a server hosted locally that contains the local kiwix library.",
"random-article": "A randomly chosen article in a ZIM file.",
@ -31,6 +32,7 @@
"reopen-closed-tab": "Represents the action of reopen a tab that has just been closed.",
"browse-library": "Represents the action of browsing the local kiwix library.",
"open-file": "Represents the action of opening a file from the local file system.",
"save-file": "Represents the action of saving a file to the local file system.",
"open-recent": "Represents the action of choosing to open a file from those recently opened.",
"search-article": "Represents the action of Searching for a article in the current ZIM file.",
"search-in-library": "Represents the action of Searching for a text in the local Kiwix library.",
@ -53,6 +55,7 @@
"donate-to-support-kiwix": "Represents the action of donating to support the Kiwix Organization.",
"exit": "Represents the action of exiting the desktop application",
"save-file-as-window-title": "Title text of the window prompting user to save as a new file.",
"download-finished": "Title of the message box announcing the completion of a download",
"download-finished-message": "Text displayed when the download action has been completed",
"file": "{{Identical|File}}",
"edit": "{{Identical|Edit}}",
@ -188,5 +191,7 @@
"stop": "{{Identical|Stop}}",
"voice": "{{Identical|Voice}}",
"select-read-voice": "Represents the action of opening the voice selection for text-to-speech.",
"select-read-language": "Represents the action of opening the language selection for text-to-speech."
"select-read-language": "Represents the action of opening the language selection for text-to-speech.",
"save-or-open": "Title of the message box allowing to choose whether a remote resource should be saved to disk or opened with a respective application",
"save-or-open-text": "Text of the message box allowing to choose whether a remote resource should be saved to disk or opened with a respective application"
}

View File

@ -3,7 +3,7 @@
<file>css/style.css</file>
<file>css/popup.css</file>
<file>css/localServer.css</file>
<file>css/confirmBox.css</file>
<file>css/messageBox.css</file>
<file>css/contentmanagerside.css</file>
<file>css/choiceBox.css</file>
</qresource>

View File

@ -17,7 +17,7 @@
#include "node.h"
#include "rownode.h"
#include "descriptionnode.h"
#include "kiwixconfirmbox.h"
#include "kiwixmessagebox.h"
#include <QtConcurrent/QtConcurrentRun>
#include "contentmanagerheader.h"
#include <QDesktopServices>

View File

@ -1,7 +1,7 @@
#include "downloadmanagement.h"
#include "kiwixapp.h"
#include "kiwixconfirmbox.h"
#include "kiwixmessagebox.h"
#include <QStorageInfo>
#include <QThread>

View File

@ -1,47 +0,0 @@
#include "kiwixconfirmbox.h"
#include "ui_kiwixconfirmbox.h"
#include <QFile>
#include "kiwixapp.h"
KiwixConfirmBox::KiwixConfirmBox(QString confirmTitle, QString confirmText, bool okDialog, QWidget *parent) :
QDialog(parent), m_confirmTitle(confirmTitle), m_confirmText(confirmText),
ui(new Ui::kiwixconfirmbox)
{
ui->setupUi(this);
setWindowFlag(Qt::FramelessWindowHint, true);
setStyleSheet(KiwixApp::instance()->parseStyleFromFile(":/css/confirmBox.css"));
connect(ui->yesButton, &QPushButton::clicked, [=]() {
emit yesClicked();
});
connect(ui->noButton, &QPushButton::clicked, [=]() {
emit noClicked();
});
connect(ui->okButton, &QPushButton::clicked, [=]() {
emit okClicked();
});
ui->confirmText->setText(confirmText);
ui->confirmTitle->setText(confirmTitle);
ui->yesButton->setText(gt("yes"));
ui->noButton->setText(gt("no"));
ui->okButton->setText(gt("ok"));
ui->okButton->hide();
if (okDialog) {
ui->yesButton->hide();
ui->noButton->hide();
ui->okButton->show();
}
}
KiwixConfirmBox::~KiwixConfirmBox()
{
delete ui;
}
void showInfoBox(QString title, QString text, QWidget *parent)
{
KiwixConfirmBox *dialog = new KiwixConfirmBox(title, text, true, parent);
dialog->show();
QObject::connect(dialog, &KiwixConfirmBox::okClicked, [=]() {
dialog->deleteLater();
});
}

66
src/kiwixmessagebox.cpp Normal file
View File

@ -0,0 +1,66 @@
#include "kiwixmessagebox.h"
#include "ui_kiwixmessagebox.h"
#include <QFile>
#include "kiwixapp.h"
KiwixMessageBox::KiwixMessageBox(QString confirmTitle, QString confirmText, bool okDialog, QWidget *parent,
QString leftAction, QString rightAction) :
QDialog(parent), m_confirmTitle(confirmTitle), m_confirmText(confirmText),
ui(new Ui::kiwixmessagebox)
{
ui->setupUi(this);
setWindowFlag(Qt::FramelessWindowHint, true);
setStyleSheet(KiwixApp::instance()->parseStyleFromFile(":/css/messageBox.css"));
connect(ui->yesButton, &QPushButton::clicked, [=]() {
emit yesClicked();
m_result = YesClicked;
accept();
});
connect(ui->noButton, &QPushButton::clicked, [=]() {
emit noClicked();
m_result = NoClicked;
reject();
});
connect(ui->okButton, &QPushButton::clicked, [=]() {
emit okClicked();
m_result = OkClicked;
});
connect(ui->closeButton, &QPushButton::clicked, [=]() {
this->close();
m_result = CloseClicked;
});
ui->confirmText->setText(confirmText);
ui->confirmTitle->setText(confirmTitle);
ui->yesButton->setText(leftAction);
ui->noButton->setText(rightAction);
ui->okButton->setText(gt("ok"));
ui->okButton->hide();
if (okDialog) {
ui->yesButton->hide();
ui->noButton->hide();
ui->okButton->show();
}
}
KiwixMessageBox::~KiwixMessageBox()
{
delete ui;
}
void showInfoBox(QString title, QString text, QWidget *parent)
{
KiwixMessageBox *dialog = new KiwixMessageBox(title, text, true, parent);
dialog->show();
QObject::connect(dialog, &KiwixMessageBox::okClicked, [=]() {
dialog->deleteLater();
});
}
KiwixMessageBox::Result showKiwixMessageBox(QString title, QString text, QWidget *parent, QString leftTitle, QString rightTitle)
{
KiwixMessageBox *dialog = new KiwixMessageBox(title, text, false, parent, leftTitle, rightTitle);
QObject::connect(dialog, &KiwixMessageBox::finished, [=]() {
dialog->deleteLater();
});
return dialog->execDialog();
}

View File

@ -1,21 +1,30 @@
#ifndef KIWIXCONFIRMBOX_H
#define KIWIXCONFIRMBOX_H
#ifndef KIWIXMESSAGEBOX_H
#define KIWIXMESSAGEBOX_H
#include <QDialog>
#include "kiwixapp.h"
#include <stdexcept>
namespace Ui {
class kiwixconfirmbox;
class kiwixmessagebox;
}
class KiwixConfirmBox : public QDialog
class KiwixMessageBox : public QDialog
{
Q_OBJECT
public:
KiwixConfirmBox(QString confirmTitle, QString confirmText, bool okDialog, QWidget *parent = nullptr);
~KiwixConfirmBox();
KiwixMessageBox(QString confirmTitle, QString confirmText, bool okDialog, QWidget *parent = nullptr,
QString leftAction = gt("yes"), QString rightAction = gt("no"));
~KiwixMessageBox();
enum Result {
YesClicked,
NoClicked,
OkClicked,
CloseClicked
};
Result execDialog() { QDialog::exec(); return m_result; }
signals:
void yesClicked();
@ -25,23 +34,25 @@ signals:
private:
QString m_confirmTitle;
QString m_confirmText;
Ui::kiwixconfirmbox *ui;
Ui::kiwixmessagebox *ui;
Result m_result;
};
void showInfoBox(QString title, QString text, QWidget *parent = nullptr);
KiwixMessageBox::Result showKiwixMessageBox(QString title, QString text, QWidget *parent, QString leftTitle, QString rightTitle);
template<class YesAction>
void showConfirmBox(QString title, QString text, QWidget *parent,
YesAction yesAction)
{
KiwixConfirmBox *dialog = new KiwixConfirmBox(title, text, false, parent);
KiwixMessageBox *dialog = new KiwixMessageBox(title, text, false, parent);
dialog->show();
QObject::connect(dialog, &KiwixConfirmBox::yesClicked, [=]() {
QObject::connect(dialog, &KiwixMessageBox::yesClicked, [=]() {
yesAction();
dialog->deleteLater();
});
QObject::connect(dialog, &KiwixConfirmBox::noClicked, [=]() {
QObject::connect(dialog, &KiwixMessageBox::noClicked, [=]() {
dialog->deleteLater();
});
}
@ -66,4 +77,4 @@ inline void showErrorBox(const KiwixAppError& err, QWidget *parent = nullptr)
showInfoBox(err.summary(), err.details(), parent);
}
#endif // KIWIXCONFIRMBOX_H
#endif // KIWIXMESSAGEBOX_H

View File

@ -1,11 +1,14 @@
#include "kprofile.h"
#include "kiwixapp.h"
#include "kiwixmessagebox.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QWebEngineSettings>
#include <QWebEngineScript>
#include <QWebEngineScriptCollection>
#include <QDesktopServices>
#include <QTemporaryFile>
namespace
{
@ -25,6 +28,12 @@ QWebEngineScript getScript(QString filename,
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#define DownloadFinishedSignal WebEngineDownloadType::finished
#else
#define DownloadFinishedSignal WebEngineDownloadType::isFinishedChanged
#endif
QString askForSaveFilePath(const QString& suggestedName)
{
const auto app = KiwixApp::instance();
@ -37,7 +46,7 @@ QString askForSaveFilePath(const QString& suggestedName)
if (fileName.isEmpty())
return QString();
if (!fileName.endsWith(extension)) {
fileName.append(extension);
}
@ -58,44 +67,100 @@ KProfile::KProfile(QObject *parent) :
#endif
scripts()->insert(getScript(":/js/headerAnchor.js"));
scripts()->insert(getScript(":/qtwebchannel/qwebchannel.js",
scripts()->insert(getScript(":/qtwebchannel/qwebchannel.js",
QWebEngineScript::DocumentCreation));
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void KProfile::startDownload(QWebEngineDownloadItem* download)
#else
void KProfile::startDownload(QWebEngineDownloadRequest* download)
#endif
namespace
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
QString defaultFileName = QUrl(download->path()).fileName();
void setDownloadFilePath(WebEngineDownloadType* download, QString filePath)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
// WebEngineDownloadType is QWebEngineDownloadItem
// and no QWebEngineDownloadItem::setDownloadFileName() yet
download->setPath(filePath);
#else
QString defaultFileName = download->downloadFileName();
// Same API for QWebEngineDownloadItem and QWebEngineDownloadRequest
download->setDownloadFileName(filePath);
#endif
}
QString getDownloadFilePath(WebEngineDownloadType* download)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
// WebEngineDownloadType is QWebEngineDownloadItem
// and no QWebEngineDownloadItem::downloadFileName() yet
return QUrl(download->path()).fileName();
#else
// Same API for QWebEngineDownloadItem and QWebEngineDownloadRequest
return download->downloadFileName();
#endif
}
} // unnamed namespace
void KProfile::openFile(WebEngineDownloadType* download)
{
const QString defaultFileName = getDownloadFilePath(download);
QTemporaryFile tempFile(QDir::tempPath() + "/XXXXXX." + QFileInfo(defaultFileName).suffix());
tempFile.setAutoRemove(false);
if (tempFile.open()) {
QString tempFilePath = tempFile.fileName();
tempFile.close();
setDownloadFilePath(download, tempFilePath);
connect(download, &DownloadFinishedSignal, [tempFilePath]() {
if(!QDesktopServices::openUrl(QUrl::fromLocalFile(tempFilePath)))
showInfoBox(gt("error-title"), gt("error-opening-file"), KiwixApp::instance()->getMainWindow());
});
download->accept();
} else {
qDebug()<<"tmp file err";
download->cancel();
}
}
void KProfile::saveFile(WebEngineDownloadType* download)
{
const QString defaultFileName = getDownloadFilePath(download);
const QString fileName = askForSaveFilePath(defaultFileName);
if (fileName.isEmpty()) {
download->cancel();
return;
}
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
download->setPath(fileName);
#else
download->setDownloadFileName(fileName);
#endif
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
connect(download, &QWebEngineDownloadItem::finished, this, &KProfile::downloadFinished);
#else
connect(download, &QWebEngineDownloadRequest::isFinished, this, &KProfile::downloadFinished);
#endif
setDownloadFilePath(download, fileName);
connect(download, &DownloadFinishedSignal, this, &KProfile::downloadFinished);
download->accept();
}
void KProfile::downloadFinished()
{
QMessageBox msgBox;
msgBox.setText(gt("download-finished-message"));
msgBox.exec();
showInfoBox(gt("download-finished"),
gt("download-finished-message"),
KiwixApp::instance()->getMainWindow()
);
}
void KProfile::startDownload(WebEngineDownloadType* download)
{
const auto res = showKiwixMessageBox(
gt("save-or-open"),
gt("save-or-open-text"),
KiwixApp::instance()->getMainWindow(),
gt("save-file"),
gt("open-file")
);
if (res == KiwixMessageBox::YesClicked) {
saveFile(download);
return;
}
if (res == KiwixMessageBox::NoClicked) {
openFile(download);
return;
}
download->cancel();
}
void ExternalReqInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info)

View File

@ -5,8 +5,10 @@
#include <QWebEngineUrlRequestInterceptor>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QWebEngineDownloadItem>
typedef QWebEngineDownloadItem WebEngineDownloadType;
#else
#include <QWebEngineDownloadRequest>
typedef QWebEngineDownloadRequest WebEngineDownloadType;
#endif
#include "urlschemehandler.h"
@ -21,14 +23,12 @@ private:
UrlSchemeHandler m_schemeHandler;
signals:
public slots:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void startDownload(QWebEngineDownloadItem*);
#else
void startDownload(QWebEngineDownloadRequest*);
#endif
private slots:
void startDownload(WebEngineDownloadType*);
void downloadFinished();
void saveFile(WebEngineDownloadType*);
void openFile(WebEngineDownloadType*);
};
/**

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>kiwixconfirmbox</class>
<widget class="QDialog" name="kiwixconfirmbox">
<class>kiwixmessagebox</class>
<widget class="QDialog" name="kiwixmessagebox">
<property name="geometry">
<rect>
<x>0</x>
@ -26,39 +26,7 @@
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="confirmText">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>600</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Would you like to confirm doing xyz?</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="confirmTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Confirm title</string>
</property>
</widget>
</item>
<item row="2" column="0">
<item row="3" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
@ -90,6 +58,9 @@
<height>0</height>
</size>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>Yes</string>
</property>
@ -112,6 +83,9 @@
<height>0</height>
</size>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>Ok</string>
</property>
@ -134,6 +108,9 @@
<height>0</height>
</size>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>No</string>
</property>
@ -144,8 +121,85 @@
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="confirmText">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>600</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Would you like to confirm doing xyz?</string>
</property>
</widget>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="confirmTitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Confirm title</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<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="closeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>16777215</height>
</size>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/kiwix.qrc">
<normaloff>:/icons/close.svg</normaloff>:/icons/close.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<resources>
<include location="../resources/kiwix.qrc"/>
</resources>
<connections/>
</ui>