Work on mutexes, preparation for two next issues.
This commit is contained in:
parent
136cd10fd5
commit
71996f27de
@ -383,6 +383,7 @@ set(APP_SOURCES
|
|||||||
src/miscellaneous/iconfactory.cpp
|
src/miscellaneous/iconfactory.cpp
|
||||||
src/miscellaneous/iofactory.cpp
|
src/miscellaneous/iofactory.cpp
|
||||||
src/miscellaneous/autosaver.cpp
|
src/miscellaneous/autosaver.cpp
|
||||||
|
src/miscellaneous/mutex.cpp
|
||||||
|
|
||||||
# EXCEPTIONS sources.
|
# EXCEPTIONS sources.
|
||||||
src/exceptions/applicationexception.cpp
|
src/exceptions/applicationexception.cpp
|
||||||
@ -476,6 +477,7 @@ set(APP_HEADERS
|
|||||||
src/miscellaneous/iconfactory.h
|
src/miscellaneous/iconfactory.h
|
||||||
src/miscellaneous/skinfactory.h
|
src/miscellaneous/skinfactory.h
|
||||||
src/miscellaneous/autosaver.h
|
src/miscellaneous/autosaver.h
|
||||||
|
src/miscellaneous/mutex.h
|
||||||
|
|
||||||
# CORE headers.
|
# CORE headers.
|
||||||
src/core/messagesmodel.h
|
src/core/messagesmodel.h
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "miscellaneous/databasefactory.h"
|
#include "miscellaneous/databasefactory.h"
|
||||||
#include "miscellaneous/systemfactory.h"
|
#include "miscellaneous/systemfactory.h"
|
||||||
#include "miscellaneous/iconfactory.h"
|
#include "miscellaneous/iconfactory.h"
|
||||||
|
#include "miscellaneous/mutex.h"
|
||||||
#include "core/messagesproxymodel.h"
|
#include "core/messagesproxymodel.h"
|
||||||
#include "core/feeddownloader.h"
|
#include "core/feeddownloader.h"
|
||||||
#include "core/feedsmodelfeed.h"
|
#include "core/feedsmodelfeed.h"
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "core/feedsmodelrecyclebin.h"
|
#include "core/feedsmodelrecyclebin.h"
|
||||||
#include "core/feedsmodelfeed.h"
|
#include "core/feedsmodelfeed.h"
|
||||||
#include "miscellaneous/systemfactory.h"
|
#include "miscellaneous/systemfactory.h"
|
||||||
|
#include "miscellaneous/mutex.h"
|
||||||
#include "gui/formmain.h"
|
#include "gui/formmain.h"
|
||||||
#include "gui/formcategorydetails.h"
|
#include "gui/formcategorydetails.h"
|
||||||
#include "gui/formfeeddetails.h"
|
#include "gui/formfeeddetails.h"
|
||||||
@ -202,8 +203,7 @@ void FeedsView::executeNextAutoUpdate() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If global auto-update is enabled
|
// If global auto-update is enabled and its interval counter reached zero,
|
||||||
// and its interval counter reached zero,
|
|
||||||
// then we need to restore it.
|
// then we need to restore it.
|
||||||
if (m_globalAutoUpdateEnabled && --m_globalAutoUpdateRemainingInterval < 0) {
|
if (m_globalAutoUpdateEnabled && --m_globalAutoUpdateRemainingInterval < 0) {
|
||||||
// We should start next auto-update interval.
|
// We should start next auto-update interval.
|
||||||
|
@ -36,6 +36,7 @@ class FormImportExport : public QDialog {
|
|||||||
OPML20 = 0
|
OPML20 = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Constructors.
|
||||||
explicit FormImportExport(QWidget *parent = 0);
|
explicit FormImportExport(QWidget *parent = 0);
|
||||||
virtual ~FormImportExport();
|
virtual ~FormImportExport();
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "miscellaneous/settings.h"
|
#include "miscellaneous/settings.h"
|
||||||
#include "miscellaneous/application.h"
|
#include "miscellaneous/application.h"
|
||||||
#include "miscellaneous/systemfactory.h"
|
#include "miscellaneous/systemfactory.h"
|
||||||
|
#include "miscellaneous/mutex.h"
|
||||||
#include "miscellaneous/databasefactory.h"
|
#include "miscellaneous/databasefactory.h"
|
||||||
#include "miscellaneous/iconfactory.h"
|
#include "miscellaneous/iconfactory.h"
|
||||||
#include "network-web/webfactory.h"
|
#include "network-web/webfactory.h"
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "miscellaneous/iconfactory.h"
|
#include "miscellaneous/iconfactory.h"
|
||||||
#include "miscellaneous/iofactory.h"
|
#include "miscellaneous/iofactory.h"
|
||||||
|
#include "miscellaneous/mutex.h"
|
||||||
#include "gui/feedsview.h"
|
#include "gui/feedsview.h"
|
||||||
#include "gui/feedmessageviewer.h"
|
#include "gui/feedmessageviewer.h"
|
||||||
#include "gui/messagebox.h"
|
#include "gui/messagebox.h"
|
||||||
@ -66,13 +67,20 @@ DownloadManager *Application::downloadManager() {
|
|||||||
m_downloadManager = new DownloadManager();
|
m_downloadManager = new DownloadManager();
|
||||||
|
|
||||||
connect(m_downloadManager, SIGNAL(downloadFinished()), mainForm()->statusBar(), SLOT(clearProgressDownload()));
|
connect(m_downloadManager, SIGNAL(downloadFinished()), mainForm()->statusBar(), SLOT(clearProgressDownload()));
|
||||||
connect(m_downloadManager, SIGNAL(downloadProgress(int,QString)),
|
connect(m_downloadManager, SIGNAL(downloadProgress(int,QString)), mainForm()->statusBar(), SLOT(showProgressDownload(int,QString)));
|
||||||
mainForm()->statusBar(), SLOT(showProgressDownload(int,QString)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_downloadManager;
|
return m_downloadManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Mutex *Application::feedUpdateLock() {
|
||||||
|
if (m_updateFeedsLock == NULL) {
|
||||||
|
m_updateFeedsLock = new Mutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_updateFeedsLock;
|
||||||
|
}
|
||||||
|
|
||||||
void Application::backupDatabaseSettings(bool backup_database, bool backup_settings,
|
void Application::backupDatabaseSettings(bool backup_database, bool backup_settings,
|
||||||
const QString &target_path, const QString &backup_name) {
|
const QString &target_path, const QString &backup_name) {
|
||||||
if (!QFileInfo(target_path).isWritable()) {
|
if (!QFileInfo(target_path).isWritable()) {
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include "gui/systemtrayicon.h"
|
#include "gui/systemtrayicon.h"
|
||||||
#include "network-web/downloadmanager.h"
|
#include "network-web/downloadmanager.h"
|
||||||
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
#if defined(qApp)
|
#if defined(qApp)
|
||||||
@ -44,6 +43,7 @@
|
|||||||
class FormMain;
|
class FormMain;
|
||||||
class IconFactory;
|
class IconFactory;
|
||||||
class QAction;
|
class QAction;
|
||||||
|
class Mutex;
|
||||||
|
|
||||||
class Application : public QtSingleApplication {
|
class Application : public QtSingleApplication {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -99,13 +99,7 @@ class Application : public QtSingleApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Access to application-wide close lock.
|
// Access to application-wide close lock.
|
||||||
inline QMutex *feedUpdateLock() {
|
Mutex *feedUpdateLock();
|
||||||
if (m_updateFeedsLock == NULL) {
|
|
||||||
m_updateFeedsLock = new QMutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_updateFeedsLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline FormMain *mainForm() {
|
inline FormMain *mainForm() {
|
||||||
return m_mainForm;
|
return m_mainForm;
|
||||||
@ -178,7 +172,7 @@ class Application : public QtSingleApplication {
|
|||||||
// But of user decides to close the application (in other words,
|
// But of user decides to close the application (in other words,
|
||||||
// tries to lock the lock for writing), then no other
|
// tries to lock the lock for writing), then no other
|
||||||
// action will be allowed to lock for reading.
|
// action will be allowed to lock for reading.
|
||||||
QMutex *m_updateFeedsLock;
|
Mutex *m_updateFeedsLock;
|
||||||
QList<QAction*> m_userActions;
|
QList<QAction*> m_userActions;
|
||||||
FormMain *m_mainForm;
|
FormMain *m_mainForm;
|
||||||
SystemTrayIcon *m_trayIcon;
|
SystemTrayIcon *m_trayIcon;
|
||||||
|
@ -59,76 +59,3 @@ bool IOFactory::copyFile(const QString &source, const QString &destination) {
|
|||||||
|
|
||||||
return QFile::copy(source, destination);
|
return QFile::copy(source, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IOFactory::removeFolder(const QString& directory_name,
|
|
||||||
const QStringList& exception_file_list,
|
|
||||||
const QStringList& exception_folder_list) {
|
|
||||||
bool result = true;
|
|
||||||
QDir dir(directory_name);
|
|
||||||
|
|
||||||
if (dir.exists(directory_name)) {
|
|
||||||
foreach (QFileInfo info,
|
|
||||||
dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System |
|
|
||||||
QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) {
|
|
||||||
if (info.isDir()) {
|
|
||||||
if (!exception_folder_list.contains(info.fileName())) {
|
|
||||||
result &= removeFolder(info.absoluteFilePath(), exception_file_list, exception_folder_list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!exception_file_list.contains(info.fileName())) {
|
|
||||||
if (!QFile::remove(info.absoluteFilePath())) {
|
|
||||||
result &= false;
|
|
||||||
qDebug("Failed to remove file \'%s\'.", qPrintable(QDir::toNativeSeparators(info.absoluteFilePath())));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
result &= true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files).isEmpty()) {
|
|
||||||
result &= dir.rmdir(directory_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IOFactory::copyFolder(const QString &source, const QString &destination) {
|
|
||||||
QDir dir_source(source);
|
|
||||||
|
|
||||||
if (!dir_source.exists()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDir dir_destination(destination);
|
|
||||||
|
|
||||||
if (!dir_destination.exists()) {
|
|
||||||
dir_destination.mkpath(destination);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (QString d, dir_source.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
|
|
||||||
QString dst_path = destination + QDir::separator() + d;
|
|
||||||
dir_source.mkpath(dst_path);
|
|
||||||
copyFolder(source + QDir::separator() + d, dst_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (QString f, dir_source.entryList(QDir::Files)) {
|
|
||||||
QString original_file = source + QDir::separator() + f;
|
|
||||||
QString destination_file = destination + QDir::separator() + f;
|
|
||||||
|
|
||||||
if (!QFile::exists(destination_file) || QFile::remove(destination_file)) {
|
|
||||||
if (QFile::copy(original_file, destination_file)) {
|
|
||||||
qDebug("Copied file \'%s\'.", qPrintable(f));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qDebug("Failed to copy file \'%s\'.", qPrintable(QDir::toNativeSeparators(original_file)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
qDebug("Failed to remove file \'%s\'.", qPrintable(QDir::toNativeSeparators(original_file)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#ifndef IOFACTORY_H
|
#ifndef IOFACTORY_H
|
||||||
#define IOFACTORY_H
|
#define IOFACTORY_H
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
#if QT_VERSION >= 0x050000
|
#if QT_VERSION >= 0x050000
|
||||||
@ -40,19 +39,12 @@ class IOFactory {
|
|||||||
// Returns system-wide folder according to type.
|
// Returns system-wide folder according to type.
|
||||||
static QString getSystemFolder(SYSTEM_FOLDER_ENUM::StandardLocation location);
|
static QString getSystemFolder(SYSTEM_FOLDER_ENUM::StandardLocation location);
|
||||||
|
|
||||||
|
// Returns contents of a file.
|
||||||
|
// Throws exception when no such file exists.
|
||||||
static QByteArray readTextFile(const QString &file_path);
|
static QByteArray readTextFile(const QString &file_path);
|
||||||
|
|
||||||
// Copies file, overwrites destination.
|
// Copies file, overwrites destination.
|
||||||
static bool copyFile(const QString &source, const QString &destination);
|
static bool copyFile(const QString &source, const QString &destination);
|
||||||
|
|
||||||
// Copy whole directory recursively.
|
|
||||||
// Destination path is created if it does not exist.
|
|
||||||
static bool copyFolder(const QString &source, const QString &destination);
|
|
||||||
|
|
||||||
// Removes directory recursively and skips given folders/files.
|
|
||||||
static bool removeFolder(const QString &directory_name,
|
|
||||||
const QStringList &exception_file_list = QStringList(),
|
|
||||||
const QStringList &exception_folder_list = QStringList());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IOFACTORY_H
|
#endif // IOFACTORY_H
|
||||||
|
71
src/miscellaneous/mutex.cpp
Normal file
71
src/miscellaneous/mutex.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// This file is part of RSS Guard.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2011-2015 by Martin Rotter <rotter.martinos@gmail.com>
|
||||||
|
//
|
||||||
|
// RSS Guard is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// RSS Guard is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "miscellaneous/mutex.h"
|
||||||
|
|
||||||
|
|
||||||
|
Mutex::Mutex(QMutex::RecursionMode mode, QObject *parent) : QObject(parent), m_mutex(new QMutex(mode)), m_isLocked(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::~Mutex() {
|
||||||
|
qDebug("Destroying Mutex instance.");
|
||||||
|
delete m_mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::lock() {
|
||||||
|
m_mutex->lock();
|
||||||
|
setLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mutex::tryLock() {
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
if (result = m_mutex->tryLock()) {
|
||||||
|
setLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mutex::tryLock(int timeout) {
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
if (result = m_mutex->tryLock(timeout)) {
|
||||||
|
setLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::unlock() {
|
||||||
|
m_mutex->unlock();
|
||||||
|
setUnlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::setLocked() {
|
||||||
|
m_isLocked = true;
|
||||||
|
emit locked();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::setUnlocked() {
|
||||||
|
m_isLocked = false;
|
||||||
|
emit unlocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mutex::isLocked() const {
|
||||||
|
return m_isLocked;
|
||||||
|
}
|
56
src/miscellaneous/mutex.h
Normal file
56
src/miscellaneous/mutex.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// This file is part of RSS Guard.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2011-2015 by Martin Rotter <rotter.martinos@gmail.com>
|
||||||
|
//
|
||||||
|
// RSS Guard is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// RSS Guard is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef MUTEX_H
|
||||||
|
#define MUTEX_H
|
||||||
|
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
|
||||||
|
class Mutex : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructors.
|
||||||
|
explicit Mutex(QMutex::RecursionMode mode = QMutex::NonRecursive, QObject *parent = 0);
|
||||||
|
virtual ~Mutex();
|
||||||
|
|
||||||
|
// Main methods.
|
||||||
|
void lock();
|
||||||
|
bool tryLock();
|
||||||
|
bool tryLock(int timeout);
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
// Identifies if mutes is locked or not.
|
||||||
|
bool isLocked() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// These methods set proper value for m_isLocked and emit signals.
|
||||||
|
void setLocked();
|
||||||
|
void setUnlocked();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void locked();
|
||||||
|
void unlocked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMutex *m_mutex;
|
||||||
|
bool m_isLocked;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MUTEX_H
|
@ -294,7 +294,7 @@ class Settings : public QSettings {
|
|||||||
return m_initializationStatus;
|
return m_initializationStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getter/setter for settings values.
|
// Getters/setters for settings values.
|
||||||
inline QVariant value(const QString §ion, const QString &key, const QVariant &default_value = QVariant()) {
|
inline QVariant value(const QString §ion, const QString &key, const QVariant &default_value = QVariant()) {
|
||||||
return QSettings::value(QString("%1/%2").arg(section, key), default_value);
|
return QSettings::value(QString("%1/%2").arg(section, key), default_value);
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,7 @@ class SystemFactory : public QObject {
|
|||||||
// Tries to download list with new updates.
|
// Tries to download list with new updates.
|
||||||
QPair<UpdateInfo, QNetworkReply::NetworkError> checkForUpdates();
|
QPair<UpdateInfo, QNetworkReply::NetworkError> checkForUpdates();
|
||||||
|
|
||||||
|
// Checks if update is newer than current application version.
|
||||||
static bool isUpdateNewer(const QString &update_version);
|
static bool isUpdateNewer(const QString &update_version);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -132,6 +132,8 @@ class WebBrowser : public TabContent {
|
|||||||
void onTitleChanged(const QString &new_title);
|
void onTitleChanged(const QString &new_title);
|
||||||
void onIconChanged();
|
void onIconChanged();
|
||||||
|
|
||||||
|
// User selected any feed from website to add to reader.
|
||||||
|
// This copies feed link to clipboard and triggers "add feed" dialog.
|
||||||
void addFeedFromWebsite(const QString &feed_link);
|
void addFeedFromWebsite(const QString &feed_link);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -74,6 +74,7 @@ bool WebPage::acceptNavigationRequest(QWebFrame *frame,
|
|||||||
QString scheme = request.url().scheme();
|
QString scheme = request.url().scheme();
|
||||||
|
|
||||||
if (scheme == "mailto" || scheme == "ftp") {
|
if (scheme == "mailto" || scheme == "ftp") {
|
||||||
|
qWarning("Received request with scheme '%s', blocking it.", qPrintable(scheme));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +86,5 @@ bool WebPage::acceptNavigationRequest(QWebFrame *frame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
qDebug("Accepting request '%s'.", qPrintable(request.url().toString()));
|
qDebug("Accepting request '%s'.", qPrintable(request.url().toString()));
|
||||||
|
|
||||||
return QWebPage::acceptNavigationRequest(frame, request, type);
|
return QWebPage::acceptNavigationRequest(frame, request, type);
|
||||||
}
|
}
|
||||||
|
@ -66,12 +66,11 @@ class WebView : public QWebView {
|
|||||||
void openImageInNewTab();
|
void openImageInNewTab();
|
||||||
void searchTextViaGoogle();
|
void searchTextViaGoogle();
|
||||||
void saveCurrentPageToFile();
|
void saveCurrentPageToFile();
|
||||||
|
void printCurrentPage();
|
||||||
|
|
||||||
// Provides custom context menu.
|
// Provides custom context menu.
|
||||||
void popupContextMenu(const QPoint &pos);
|
void popupContextMenu(const QPoint &pos);
|
||||||
|
|
||||||
void printCurrentPage();
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void downloadLink(const QNetworkRequest &request);
|
void downloadLink(const QNetworkRequest &request);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user