Initial Qt6 support

This commit is contained in:
Adam Lamar 2024-02-26 22:18:34 +00:00
parent ef1489193e
commit d842a288f7
26 changed files with 280 additions and 63 deletions

12
.gitignore vendored
View File

@ -30,6 +30,18 @@
*.exe
*.out
*.app
/kiwix-desktop
# QtCreator Environment Settings (not suitable for sharing)
kiwix-desktop.pro.user
# Qt autogenerated files
/qrc_*.cpp
/ui_*.h
/moc_*.h
/moc_*.cpp
/Makefile
/.qmake.stash
# IDE files
/.vscode

View File

@ -73,6 +73,38 @@ You may want to simply open the kiwix-desktop project in QtCreator and
then compile the project from there (don't forget to update
`PKG_CONFIG_PATH` if necessary).
Compilation with Qt6
--------------------
There is initial support for Qt6. Additional packages are needed:
```bash
sudo apt install qt6-base-dev qt6-base-dev-tools qt6-webengine-dev libqt6webenginecore6-bin libqt6svg6
```
And `qmake` needs to be configured to use Qt6. First confirm `qmake` is using the right version:
```bash
qtchooser -install qt6 $(which qmake6) # run once
export QT_SELECT=qt6 # set in environments where Qt6 builds are desired
qmake --version
```
produces this output:
```bash
$ qmake --version
QMake version 3.1
Using Qt version 6.2.4 in /usr/lib/aarch64-linux-gnu
```
then build as normal:
```bash
qmake .
make
```
Installation
------------

View File

@ -30,7 +30,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
@ -124,6 +124,7 @@ HEADERS += \
src/fullscreennotification.h \
src/menuproxystyle.h \
src/zimview.h \
src/portutils.h \
FORMS += \
src/choiceitem.ui \

View File

@ -125,6 +125,7 @@
"ok":"ok",
"no-filter":"no filter",
"open-link-in-web-browser":"Open link in web browser",
"open-link-new-tab":"Open link in new tab",
"download-dir-dialog-title":"Are you sure you want to change the download directory?",
"download-dir-dialog-msg":"The new download directory path will be:\n{{DIRECTORY}}",
"invalid-port":"Invalid port",

View File

@ -6,6 +6,7 @@
class BlobBuffer : public QBuffer
{
Q_OBJECT
public:
BlobBuffer(zim::Blob m_blob);
virtual ~BlobBuffer() = default;

View File

@ -316,7 +316,7 @@ ContentManager::BookInfo ContentManager::getBookInfos(QString id, const QStringL
QStringList tagList = QString::fromStdString(b->getTags()).split(';');
QMap<QString, bool> displayTagMap;
for(auto tag: tagList) {
if (tag[0] == "_") {
if (tag[0] == '_') {
auto splitTag = tag.split(":");
displayTagMap[splitTag[0]] = splitTag[1] == "yes" ? true:false;
}

View File

@ -2,11 +2,12 @@
#include "contentmanagerdelegate.h"
#include <QApplication>
#include <QDialog>
#include <QStyleOptionViewItemV4>
#include <QStyleOptionViewItem>
#include "kiwixapp.h"
#include <QStyleOptionViewItem>
#include "rownode.h"
#include "descriptionnode.h"
#include "portutils.h"
ContentManagerDelegate::ContentManagerDelegate(QObject *parent)
: QStyledItemDelegate(parent), baseButton(new QPushButton)
@ -198,7 +199,11 @@ void ContentManagerDelegate::paint(QPainter *painter, const QStyleOptionViewItem
}
if (index.column() == 1) {
auto bFont = painter->font();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
bFont.setWeight(60);
#else
bFont.setWeight(QFont::DemiBold);
#endif
eOpt.font = bFont;
}
QStyledItemDelegate::paint(painter, eOpt, index);
@ -209,8 +214,8 @@ bool ContentManagerDelegate::editorEvent(QEvent *event, QAbstractItemModel *mode
if(event->type() == QEvent::MouseButtonRelease )
{
QMouseEvent * e = (QMouseEvent *)event;
int clickX = e->x();
int clickY = e->y();
int clickX = portutils::getX(*e);
int clickY = portutils::getY(*e);
QRect r = option.rect;
int x,y,w,h;
@ -238,7 +243,7 @@ void ContentManagerDelegate::handleLastColumnClicked(const QModelIndex& index, Q
{
const auto node = static_cast<RowNode*>(index.internalPointer());
const auto id = node->getBookId();
int clickX = mouseEvent->x();
int clickX = portutils::getX(*mouseEvent);
QRect r = option.rect;
int x = r.left();

View File

@ -57,6 +57,7 @@
//! [0]
class FlowLayout : public QLayout
{
Q_OBJECT
public:
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);

View File

@ -1,3 +1,5 @@
class QMenu;
#include "fullscreenwindow.h"
#include <QAction>

View File

@ -1,6 +1,7 @@
#ifndef FULLSCREENWINDOW_H
#define FULLSCREENWINDOW_H
class QMenu;
#include <QWidget>
#include <QWebEngineView>
#include "fullscreennotification.h"

View File

@ -40,8 +40,13 @@ KiwixApp::KiwixApp(int& argc, char *argv[])
QMessageBox::critical(nullptr, "Translation error", e.what());
return;
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
m_qtTranslator.load(QLocale(), "qt", "_",
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
#else
m_qtTranslator.load(QLocale(), "qt", "_",
QLibraryInfo::path(QLibraryInfo::TranslationsPath));
#endif
installTranslator(&m_qtTranslator);
m_appTranslator.load(QLocale(), "kiwix-desktop", "_", ":/i18n/");
@ -201,6 +206,7 @@ void KiwixApp::printPage()
{
if(!getTabWidget()->currentZimView())
return;
QPrinter* printer = new QPrinter();
QPrintDialog printDialog(printer, mp_mainWindow);
printDialog.setStyle(nullptr);
@ -209,12 +215,23 @@ void KiwixApp::printPage()
auto webview = getTabWidget()->currentWebView();
if(!webview)
return;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
webview->page()->print(printer, [=](bool success) {
if (!success) {
showMessage(gt("print-page-error"), gt("error-title"), QMessageBox::Critical);
}
delete printer;
});
#else
webview->print(printer);
connect(webview, &QWebEngineView::printFinished, this, [=](bool success) {
if (!success) {
showMessage(gt("print-page-error"), gt("error-title"), QMessageBox::Critical);
}
delete printer;
});
#endif
}
}
@ -329,25 +346,25 @@ void KiwixApp::setMonitorDir(const QString &dir) {
void KiwixApp::createAction()
{
CREATE_ACTION_ICON_SHORTCUT(KiwixServeAction, "share", gt("local-kiwix-server"), QKeySequence(Qt::CTRL+Qt::Key_I));
CREATE_ACTION_ICON_SHORTCUT(KiwixServeAction, "share", gt("local-kiwix-server"), QKeySequence(Qt::CTRL | Qt::Key_I));
CREATE_ACTION_ICON_SHORTCUT(RandomArticleAction, "random", gt("random-article"), QKeySequence(Qt::CTRL+Qt::Key_R));
CREATE_ACTION_ICON_SHORTCUT(RandomArticleAction, "random", gt("random-article"), QKeySequence(Qt::CTRL | Qt::Key_R));
connect(mpa_actions[RandomArticleAction], &QAction::triggered,
this, [=]() { this->openRandomUrl(false); });
CREATE_ACTION_SHORTCUT(OpenHomePageAction, gt("home-page"), QKeySequence(Qt::ALT + Qt::Key_Home));
CREATE_ACTION_SHORTCUT(OpenHomePageAction, gt("home-page"), QKeySequence(Qt::ALT | Qt::Key_Home));
if (QGuiApplication::isLeftToRight()) {
CREATE_ACTION_ICON_SHORTCUT(HistoryBackAction, "history-left", gt("back"), QKeySequence(Qt::ALT + Qt::Key_Left));
CREATE_ACTION_ICON_SHORTCUT(HistoryBackAction, "history-left", gt("back"), QKeySequence(Qt::ALT | Qt::Key_Left));
} else {
CREATE_ACTION_ICON_SHORTCUT(HistoryBackAction, "history-right", gt("back"), QKeySequence(Qt::ALT + Qt::Key_Right));
CREATE_ACTION_ICON_SHORTCUT(HistoryBackAction, "history-right", gt("back"), QKeySequence(Qt::ALT | Qt::Key_Right));
}
DISABLE_ACTION(HistoryBackAction);
if (QGuiApplication::isLeftToRight()) {
CREATE_ACTION_ICON_SHORTCUT(HistoryForwardAction, "history-right", gt("forward"), QKeySequence(Qt::ALT + Qt::Key_Right));
CREATE_ACTION_ICON_SHORTCUT(HistoryForwardAction, "history-right", gt("forward"), QKeySequence(Qt::ALT | Qt::Key_Right));
} else {
CREATE_ACTION_ICON_SHORTCUT(HistoryForwardAction, "history-left", gt("forward"), QKeySequence(Qt::ALT + Qt::Key_Left));
CREATE_ACTION_ICON_SHORTCUT(HistoryForwardAction, "history-left", gt("forward"), QKeySequence(Qt::ALT | Qt::Key_Left));
}
DISABLE_ACTION(HistoryForwardAction);
@ -357,13 +374,13 @@ void KiwixApp::createAction()
CREATE_ACTION_ICON_SHORTCUT(NewTabAction,"new-tab-icon", gt("new-tab"), QKeySequence::AddTab);
CREATE_ACTION_ICON_SHORTCUTS(CloseTabAction, "close", gt("close-tab"), QList<QKeySequence>({QKeySequence(Qt::CTRL + Qt::Key_F4), QKeySequence(Qt::CTRL + Qt::Key_W)}));
CREATE_ACTION_ICON_SHORTCUTS(CloseTabAction, "close", gt("close-tab"), QList<QKeySequence>({QKeySequence(Qt::CTRL | Qt::Key_F4), QKeySequence(Qt::CTRL | Qt::Key_W)}));
mpa_actions[CloseTabAction]->setIconVisibleInMenu(false);
CREATE_ACTION_SHORTCUT(ReopenClosedTabAction, gt("reopen-closed-tab"), QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_T));
CREATE_ACTION_SHORTCUT(ReopenClosedTabAction, gt("reopen-closed-tab"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_T));
HIDE_ACTION(ReopenClosedTabAction);
CREATE_ACTION_SHORTCUT(BrowseLibraryAction, gt("browse-library"), QKeySequence(Qt::CTRL+Qt::Key_E));
CREATE_ACTION_SHORTCUT(BrowseLibraryAction, gt("browse-library"), QKeySequence(Qt::CTRL | Qt::Key_E));
HIDE_ACTION(BrowseLibraryAction);
CREATE_ACTION_ICON_SHORTCUT(OpenFileAction, "open-file", gt("open-file"), QKeySequence::Open);
@ -379,10 +396,10 @@ void KiwixApp::createAction()
HIDE_ACTION(SavePageAsAction);
*/
CREATE_ACTION_SHORTCUT(SearchArticleAction, gt("search-article"), QKeySequence(Qt::CTRL+Qt::Key_L));
CREATE_ACTION_SHORTCUT(SearchArticleAction, gt("search-article"), QKeySequence(Qt::CTRL | Qt::Key_L));
HIDE_ACTION(SearchArticleAction);
CREATE_ACTION_SHORTCUT(SearchLibraryAction, gt("search-in-library"), QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_R));
CREATE_ACTION_SHORTCUT(SearchLibraryAction, gt("search-in-library"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_R));
HIDE_ACTION(SearchLibraryAction);
CREATE_ACTION(FindInPageAction, gt("find-in-page"));
@ -400,20 +417,20 @@ void KiwixApp::createAction()
});
mpa_actions[ToggleFullscreenAction]->setCheckable(true);
CREATE_ACTION_SHORTCUT(ToggleTOCAction, gt("table-of-content"), QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_1));
CREATE_ACTION_SHORTCUT(ToggleTOCAction, gt("table-of-content"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_1));
HIDE_ACTION(ToggleTOCAction);
CREATE_ACTION_ONOFF_ICON_SHORTCUT(ToggleReadingListAction, "reading-list-active", "reading-list", gt("reading-list"), QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_2));
CREATE_ACTION_ONOFF_ICON_SHORTCUT(ToggleReadingListAction, "reading-list-active", "reading-list", gt("reading-list"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_2));
CREATE_ACTION_SHORTCUTS(ZoomInAction, gt("zoom-in"), QList<QKeySequence>({QKeySequence::ZoomIn, QKeySequence(Qt::CTRL+Qt::Key_Equal)}));
CREATE_ACTION_SHORTCUTS(ZoomInAction, gt("zoom-in"), QList<QKeySequence>({QKeySequence::ZoomIn, QKeySequence(Qt::CTRL | Qt::Key_Equal)}));
CREATE_ACTION_SHORTCUT(ZoomOutAction, gt("zoom-out"), QKeySequence::ZoomOut);
CREATE_ACTION_SHORTCUT(ZoomResetAction, gt("zoom-reset"), QKeySequence(Qt::CTRL+Qt::Key_0));
CREATE_ACTION_SHORTCUT(ZoomResetAction, gt("zoom-reset"), QKeySequence(Qt::CTRL | Qt::Key_0));
CREATE_ACTION_SHORTCUT(NextTabAction, gt("next-tab"), QKeySequence(Qt::CTRL + Qt::Key_Tab));
CREATE_ACTION_SHORTCUT(NextTabAction, gt("next-tab"), QKeySequence(Qt::CTRL | Qt::Key_Tab));
CREATE_ACTION_SHORTCUT(PreviousTabAction, gt("previous-tab"), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab));
CREATE_ACTION_SHORTCUT(PreviousTabAction, gt("previous-tab"), QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Tab));
CREATE_ACTION_SHORTCUT(HelpAction, gt("help"), QKeySequence::HelpContents);
HIDE_ACTION(HelpAction);
@ -431,7 +448,7 @@ void KiwixApp::createAction()
CREATE_ACTION_ICON_SHORTCUT(SettingAction, "settings", gt("settings"), QKeySequence(Qt::Key_F12));
CREATE_ACTION_ICON_SHORTCUT(DonateAction, "donate", gt("donate-to-support-kiwix"), QKeySequence(Qt::CTRL+Qt::Key_D));
CREATE_ACTION_ICON_SHORTCUT(DonateAction, "donate", gt("donate-to-support-kiwix"), QKeySequence(Qt::CTRL | Qt::Key_D));
CREATE_ACTION_ICON_SHORTCUT(ExitAction, "exit", gt("exit"), QKeySequence::Quit);
}

View File

@ -13,7 +13,11 @@ KProfile::KProfile(QObject *parent) :
settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void KProfile::startDownload(QWebEngineDownloadItem* download)
#else
void KProfile::startDownload(QWebEngineDownloadRequest* download)
#endif
{
QString defaultFileName = download->url().fileName();
QString fileName = QFileDialog::getSaveFileName(KiwixApp::instance()->getMainWindow(),
@ -30,7 +34,11 @@ void KProfile::startDownload(QWebEngineDownloadItem* download)
#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
download->accept();
}

View File

@ -2,6 +2,11 @@
#define KPROFILE_H
#include <QWebEngineProfile>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QWebEngineDownloadItem>
#else
#include <QWebEngineDownloadRequest>
#endif
#include "urlschemehandler.h"
@ -16,7 +21,12 @@ private:
signals:
public slots:
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void startDownload(QWebEngineDownloadItem*);
#else
void startDownload(QWebEngineDownloadRequest*);
#endif
void downloadFinished();
};

View File

@ -18,8 +18,10 @@ int main(int argc, char *argv[])
}
// End of hack ^^^
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
// High DPI Scaling is enabled by default in Qt6. This attribute no longer exists in 6.0 and later
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
QWebEngineUrlScheme scheme("zim");
QWebEngineUrlScheme::registerScheme(scheme);

View File

@ -1,5 +1,6 @@
#include "mainwindow.h"
#include "portutils.h"
#include "ui_mainwindow.h"
#include "ui_about.h"
@ -108,10 +109,12 @@ bool MainWindow::eventFilter(QObject* /*object*/, QEvent* event)
{
const auto mouseEvent = static_cast<QMouseEvent*>(event);
const int tabRegion = getTabBar()->height() + getTopWidget()->height() + 30;
int clickY = portutils::getY(*mouseEvent);
// We don't have to check for visibilty as calling hide() on a hidden widget, or show() on a non-hidden widget is a no-op
if (mouseEvent->y() == 0) {
if (clickY == 0) {
showTabAndTop();
} else if(mouseEvent->y() >= tabRegion) {
} else if(clickY >= tabRegion) {
hideTabAndTop();
}
return true;

View File

@ -27,7 +27,7 @@ public:
QWidget getMainView();
protected:
void keyPressEvent(QKeyEvent *event);
void keyPressEvent(QKeyEvent *event) override;
bool eventFilter(QObject* object, QEvent* event) override;
private slots:

39
src/portutils.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef PORTUTILS_H
#define PORTUTILS_H
#include <QEvent>
namespace portutils {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // Earlier than Qt6
inline int getX(const QMouseEvent& e) {
return e.x();
}
inline int getY(const QMouseEvent& e) {
return e.y();
}
inline QPoint getGlobalPos(const QMouseEvent& e) {
return e.globalPos();
}
#else // Qt6 and later
inline int getX(const QMouseEvent& e) {
return e.position().x();
}
inline int getY(const QMouseEvent& e) {
return e.position().y();
}
inline QPoint getGlobalPos(const QMouseEvent& e) {
return e.globalPosition().toPoint();
}
#endif
}
#endif // PORTUTILS_H

View File

@ -5,6 +5,7 @@
#include <QMessageBox>
#include <kiwix/tools.h>
#include <QLocale>
#include <QList>
SettingsManager::SettingsManager(QObject *parent)
: QObject(parent),
@ -147,8 +148,18 @@ void SettingsManager::initSettings()
m_kiwixServerIpAddress = m_settings.value("localKiwixServer/ipAddress", QString("0.0.0.0")).toString();
m_monitorDir = m_settings.value("monitor/dir", QString("")).toString();
m_moveToTrash = m_settings.value("moveToTrash", true).toBool();
QVariant defaultLang = QVariant::fromValue(QLocale::languageToString(QLocale().language()) + '|' + QLocale().name().split("_").at(0));
m_langList = m_settings.value("language", {defaultLang}).toList();
QString defaultLang = QLocale::languageToString(QLocale().language()) + '|' + QLocale().name().split("_").at(0);
QList<QString> defaultLangList; // Qt5 QList doesn't support supplying a constructor list, so use append() for Qt5+Qt6 compat
defaultLangList.append(defaultLang);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QVariant defaultLangVariant(defaultLangList); // Qt5 requires explicit conversion from QList to QVariant
m_langList = m_settings.value("language", defaultLangVariant).toList();
#else
m_langList = m_settings.value("language", defaultLangList).toList();
#endif
m_categoryList = m_settings.value("category", {}).toList();
m_contentTypeList = m_settings.value("contentType", {}).toList();
}

View File

@ -1,3 +1,5 @@
class QMenu;
#include "tabbar.h"
#include "kiwixapp.h"
@ -76,7 +78,7 @@ TabBar::TabBar(QWidget *parent) :
for (int i = 0 ; i <= 9 ; i++) {
QAction *a = new QAction(this);
a->setData(QVariant::fromValue(i));
QKeySequence ks(Qt::ALT + (Qt::Key_0 + i));
QKeySequence ks(Qt::ALT | (Qt::Key_0 + i));
a->setShortcut(ks);
addAction(a);
connect(a, &QAction::triggered, this, [=](){

View File

@ -4,6 +4,7 @@
#include "kiwixapp.h"
#include "mainmenu.h"
#include "tabbar.h"
#include "portutils.h"
#include <QMouseEvent>
#include <QAction>
@ -48,12 +49,13 @@ TopWidget::TopWidget(QWidget *parent) :
addAction(KiwixApp::instance()->getAction(KiwixApp::OpenFileAction));
QMenu* menu = new MainMenu();
QAction* menuAction = new QAction(this);
menuAction->setIcon(QIcon(":/icons/more.svg"));
menuAction->setMenu(menu);
menuAction->setToolTip(gt("main-menu"));
QToolButton *toolButton = new QToolButton(menu);
toolButton->setIcon(QIcon(":/icons/more.svg"));
toolButton->setPopupMode(QToolButton::InstantPopup);
toolButton->setToolTip(gt("main-menu"));
toolButton->setMenu(menu);
addWidget(toolButton);
addAction(menuAction);
setContextMenuPolicy( Qt::PreventContextMenu );
#if !SYSTEMTITLEBAR
@ -92,7 +94,8 @@ void TopWidget::mousePressEvent(QMouseEvent *event) {
if (event->button() != Qt::LeftButton)
return;
m_cursorPos = event->globalPos() + frameGeometry().topLeft() - parentWidget()->frameGeometry().topLeft();
QPoint globalPos = portutils::getGlobalPos(*event);
m_cursorPos = globalPos + frameGeometry().topLeft() - parentWidget()->frameGeometry().topLeft();
m_timestamp = event->timestamp();
event->accept();
}
@ -101,8 +104,9 @@ void TopWidget::mouseMoveEvent(QMouseEvent *event) {
if (event->timestamp() <= m_timestamp)
return;
QPoint globalPos = portutils::getGlobalPos(*event);
m_timestamp = event->timestamp();
auto delta = event->globalPos() - m_cursorPos;
auto delta = globalPos - m_cursorPos;
parentWidget()->move(delta);
event->accept();
}

View File

@ -5,6 +5,7 @@
class UrlSchemeHandler : public QWebEngineUrlSchemeHandler
{
Q_OBJECT
public:
UrlSchemeHandler();
void requestStarted(QWebEngineUrlRequestJob *request);

View File

@ -5,6 +5,7 @@
class WebPage : public QWebEnginePage
{
Q_OBJECT
public:
explicit WebPage(QObject *parent = nullptr);

View File

@ -1,3 +1,5 @@
class QMenu;
#include "webview.h"
#include <QDesktopServices>
@ -80,11 +82,13 @@ WebView::WebView(QWidget *parent)
* If the page is search results, we put the default zoom factor
* If in Qt 6.x, the bug is fixed this code can be removed.
*/
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
connect(this, &QWebEngineView::loadFinished, this, [=] (bool ok) {
if (ok) {
applyCorrectZoomFactor();
}
});
#endif
}
WebView::~WebView()
@ -202,23 +206,67 @@ void WebView::wheelEvent(QWheelEvent *event) {
void WebView::contextMenuEvent(QContextMenuEvent *event)
{
auto menu = this->page()->createStandardContextMenu();
pageAction(QWebEnginePage::OpenLinkInNewWindow)->setVisible(false);
if (!m_linkHovered.isEmpty()) {
QMenu* menu;
if (m_linkHovered.isEmpty()) {
menu = createStandardContextMenu();
} else {
menu = createLinkContextMenu();
}
menu->exec(event->globalPos());
}
QMenu* WebView::createStandardContextMenu() {
auto app = KiwixApp::instance();
QMenu* menu = new QMenu(this);
auto backAction = new QAction(gt("back"));
backAction->setEnabled(app->getAction(KiwixApp::HistoryBackAction)->isEnabled());
backAction->setIcon(app->getAction(KiwixApp::HistoryBackAction)->icon());
menu->addAction(backAction);
connect(menu, &QObject::destroyed, backAction, &QObject::deleteLater);
connect(backAction, &QAction::triggered, this, [=](bool checked) {
Q_UNUSED(checked);
KiwixApp::instance()->getTabWidget()->triggerWebPageAction(QWebEnginePage::Back);
});
auto forwardAction = new QAction(gt("forward"));
forwardAction->setEnabled(app->getAction(KiwixApp::HistoryForwardAction)->isEnabled());
forwardAction->setIcon(app->getAction(KiwixApp::HistoryForwardAction)->icon());
menu->addAction(forwardAction);
connect(menu, &QObject::destroyed, forwardAction, &QObject::deleteLater);
connect(forwardAction, &QAction::triggered, this, [=](bool checked) {
Q_UNUSED(checked);
KiwixApp::instance()->getTabWidget()->triggerWebPageAction(QWebEnginePage::Forward);
});
return menu;
}
QMenu* WebView::createLinkContextMenu() {
QMenu* menu = new QMenu(this);
if (!m_linkHovered.startsWith("zim://")) {
pageAction(QWebEnginePage::OpenLinkInNewTab)->setVisible(false);
auto openLinkInWebBrowserAction = new QAction(gt("open-link-in-web-browser"));
menu->insertAction(pageAction(QWebEnginePage::DownloadLinkToDisk) , openLinkInWebBrowserAction);
menu->addAction(openLinkInWebBrowserAction);
connect(menu, &QObject::destroyed, openLinkInWebBrowserAction, &QObject::deleteLater);
connect(openLinkInWebBrowserAction, &QAction::triggered, this, [=](bool checked) {
Q_UNUSED(checked);
QDesktopServices::openUrl(m_linkHovered);
});
} else {
pageAction(QWebEnginePage::OpenLinkInNewTab)->setVisible(true);
auto openLinkNewTab = new QAction(gt("open-link-new-tab"));
openLinkNewTab->setIcon(QIcon(":/icons/new-tab-icon.svg"));
menu->addAction(openLinkNewTab);
connect(menu, &QObject::destroyed, openLinkNewTab, &QObject::deleteLater);
connect(openLinkNewTab, &QAction::triggered, this, [=](bool checked) {
Q_UNUSED(checked);
KiwixApp::instance()->openUrl(m_linkHovered, true);
});
}
}
menu->exec(event->globalPos());
return menu;
}

View File

@ -1,10 +1,10 @@
#ifndef WEBVIEW_H
#define WEBVIEW_H
#include <QMenu>
#include <QWebEngineView>
#include <QIcon>
#include <QWheelEvent>
#include <QMenu>
#include "findinpagebar.h"
@ -69,6 +69,8 @@ private slots:
private:
void addHistoryItemAction(QMenu *menu, const QWebEngineHistoryItem &item, int n) const;
void applyCorrectZoomFactor();
QMenu* createStandardContextMenu();
QMenu* createLinkContextMenu();
};
#endif // WEBVIEW_H

View File

@ -38,11 +38,11 @@
**
****************************************************************************/
#include "qtlocalpeer.h"
#include <QCoreApplication>
#include <QDataStream>
#include <QTime>
#include <QRegularExpression>
#if defined(Q_OS_WIN)
#include <QLibrary>
@ -76,15 +76,25 @@ QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
#if defined(Q_OS_WIN)
id = id.toLower();
#endif
prefix = id.section(QLatin1Char('/'), -1);
prefix = id.section(u'/', -1);
}
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
prefix.remove(QRegExp("[^a-zA-Z]"));
#else
prefix.remove(QRegularExpression("[^a-zA-Z]"));
#endif
prefix.truncate(6);
QByteArray idc = id.toUtf8();
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
quint16 idNum = qChecksum(idc.constData(), idc.size());
#else
QByteArrayView v = QByteArrayView(idc);
quint16 idNum = qChecksum(v);
#endif
socketName = QLatin1String("qtsingleapp-") + prefix
+ QLatin1Char('-') + QString::number(idNum, 16);
+ u'-' + QString::number(idNum, 16);
#if defined(Q_OS_WIN)
if (!pProcessIdToSessionId) {
@ -97,12 +107,12 @@ QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
socketName += QLatin1Char('-') + QString::number(sessionId, 16);
}
#else
socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
socketName += u'-' + QString::number(::getuid(), 16);
#endif
server = new QLocalServer(this);
QString lockName = QDir(QDir::tempPath()).absolutePath()
+ QLatin1Char('/') + socketName
+ u'/' + socketName
+ QLatin1String("-lockfile");
lockFile.setFileName(lockName);
lockFile.open(QIODevice::ReadWrite);
@ -122,7 +132,7 @@ bool QtLocalPeer::isClient()
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
// ### Workaround
if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
QFile::remove(QDir::cleanPath(QDir::tempPath())+u'/'+socketName);
res = server->listen(socketName);
}
#endif

View File

@ -66,6 +66,9 @@ namespace QtLP_Private {
class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile
{
//Q_OBJECT
// TODO: Uncomment Q_OBJECT. Setting Q_OBJECT here causes this error:
// undefined reference to `vtable for QtLP_Private::QtLockedFile'
public:
enum LockMode { NoLock = 0, ReadLock, WriteLock };