├── debian ├── docs ├── compat ├── source │ └── format ├── README ├── rules ├── control.qt4 ├── control.qt48-sergey ├── control.qt5 ├── copyright └── changelog ├── README.md ├── resources ├── link-clicked.mp3 ├── link-clicked.ogg ├── link-clicked.wav ├── window-clicked.mp3 ├── window-clicked.ogg ├── window-clicked.wav ├── qt-webkit-kiosk.ico ├── qt-webkit-kiosk.png ├── qt-webkit-kiosk.desktop ├── default.html └── qt-webkit-kiosk.ini ├── .gitignore ├── src ├── player │ ├── null.cpp │ ├── null.h │ ├── multimedia.cpp │ ├── phonon.h │ ├── multimedia.h │ └── phonon.cpp ├── qinfo.h ├── qplayer.h ├── config.h ├── cachingnm.h ├── cachingnm.cpp ├── persistentcookiejar.h ├── fakewebview.h ├── qwk_webpage.h ├── qwk_settings.h ├── socketpair.h ├── fakewebview.cpp ├── unixsignals.h ├── socketpair.cpp ├── webview.h ├── persistentcookiejar.cpp ├── qwk_webpage.cpp ├── main.cpp ├── qt-webkit-kiosk.pro ├── mainwindow.h ├── unixsignals.cpp ├── anyoption.h ├── webview.cpp ├── qwk_settings.cpp ├── anyoption.cpp └── mainwindow.cpp ├── setup.pro └── doc ├── README.md ├── README.ru.md ├── lgpl.txt └── lgpl.html /debian/docs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Qt WebKit Kiosk-mode browser 2 | 3 | About project: [en](doc/README.md) [ru](doc/README.ru.md). 4 | -------------------------------------------------------------------------------- /resources/link-clicked.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergey-dryabzhinsky/qt-webkit-kiosk/HEAD/resources/link-clicked.mp3 -------------------------------------------------------------------------------- /resources/link-clicked.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergey-dryabzhinsky/qt-webkit-kiosk/HEAD/resources/link-clicked.ogg -------------------------------------------------------------------------------- /resources/link-clicked.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergey-dryabzhinsky/qt-webkit-kiosk/HEAD/resources/link-clicked.wav -------------------------------------------------------------------------------- /resources/window-clicked.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergey-dryabzhinsky/qt-webkit-kiosk/HEAD/resources/window-clicked.mp3 -------------------------------------------------------------------------------- /resources/window-clicked.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergey-dryabzhinsky/qt-webkit-kiosk/HEAD/resources/window-clicked.ogg -------------------------------------------------------------------------------- /resources/window-clicked.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergey-dryabzhinsky/qt-webkit-kiosk/HEAD/resources/window-clicked.wav -------------------------------------------------------------------------------- /resources/qt-webkit-kiosk.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergey-dryabzhinsky/qt-webkit-kiosk/HEAD/resources/qt-webkit-kiosk.ico -------------------------------------------------------------------------------- /resources/qt-webkit-kiosk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sergey-dryabzhinsky/qt-webkit-kiosk/HEAD/resources/qt-webkit-kiosk.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | 3 | # Build artefacts 4 | *.o 5 | moc_*.cpp 6 | Makefile* 7 | .qmake.stash 8 | src/moc_predefs.h 9 | # Main binary 10 | src/qt-webkit-kiosk 11 | -------------------------------------------------------------------------------- /src/player/null.cpp: -------------------------------------------------------------------------------- 1 | #include "../config.h" 2 | #include "null.h" 3 | 4 | QPlayer::QPlayer() 5 | { 6 | } 7 | 8 | void QPlayer::play(QString soundFile) 9 | { 10 | Q_UNUSED(soundFile); 11 | } 12 | -------------------------------------------------------------------------------- /debian/README: -------------------------------------------------------------------------------- 1 | The Debian Package qt-webkit-kiosk 2 | ---------------------------- 3 | 4 | Comments regarding the Package 5 | 6 | -- Дрябжинский Сергей Mon, 12 Dec 2011 02:36:28 +0400 7 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | 4 | # Uncomment this to turn on verbose mode. 5 | #export DH_VERBOSE=1 6 | 7 | export PKG_CONFIG_PATH = $(shell qmake -query QT_INSTALL_LIBS)/pkgconfig 8 | 9 | %: 10 | dh $@ 11 | -------------------------------------------------------------------------------- /resources/qt-webkit-kiosk.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=QtWebkitKiosk 3 | Comment=Simple browser with kiosk mode 4 | Exec=qt-webkit-kiosk 5 | Categories=Network;WebBrowser; 6 | Icon=qt-webkit-kiosk 7 | Type=Application 8 | Terminal=false 9 | StartupNotify=true 10 | -------------------------------------------------------------------------------- /src/player/null.h: -------------------------------------------------------------------------------- 1 | #ifndef QPLAYER_NULL_H 2 | #define QPLAYER_NULL_H 3 | 4 | #include 5 | 6 | class QPlayer : public QObject 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | QPlayer(); 12 | 13 | void play(QString soundFile); 14 | 15 | }; 16 | 17 | #endif // QPLAYER_NULL_H 18 | -------------------------------------------------------------------------------- /src/qinfo.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Add debug macros for QT < 5.5.0 3 | */ 4 | 5 | #ifndef __QINFO_H 6 | #define __QINFO_H 7 | 8 | #if QT_VERSION < 0x050500 9 | #define qInfo qDebug 10 | #define qWarning qDebug 11 | #define qFatal qDebug 12 | #define qCritical qDebug 13 | #endif 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/qplayer.h: -------------------------------------------------------------------------------- 1 | #ifndef QPLAYER_H 2 | #define QPLAYER_H 3 | 4 | #ifdef PLAYER_MULTIMEDIA 5 | #include "player/multimedia.h" 6 | #endif 7 | 8 | #ifdef PLAYER_PHONON 9 | #include "player/phonon.h" 10 | #endif 11 | 12 | #ifdef PLAYER_NULL 13 | #include "player/null.h" 14 | #endif 15 | 16 | #endif // QPLAYER_H 17 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * All package definitions here 3 | */ 4 | 5 | #ifndef __CONFIG_H 6 | #define __CONFIG_H 7 | 8 | #ifndef RESOURCES 9 | #define RESOURCES "./resources" 10 | #endif 11 | 12 | #ifndef ICON 13 | #define ICON "./qt-webkit-kiosk.png" 14 | #endif 15 | 16 | #ifndef VERSION 17 | #define VERSION "1.99.11-dev" 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/cachingnm.h: -------------------------------------------------------------------------------- 1 | #ifndef CACHINGNM_H 2 | #define CACHINGNM_H 3 | 4 | #include 5 | 6 | class CachingNetworkManager : public QNetworkAccessManager 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | explicit CachingNetworkManager(QObject* parent = 0); 12 | 13 | QNetworkReply *createRequest( Operation op, const QNetworkRequest & req, QIODevice * outgoingData); 14 | }; 15 | 16 | 17 | #endif // CACHINGNM_H 18 | -------------------------------------------------------------------------------- /src/player/multimedia.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "multimedia.h" 3 | 4 | QPlayer::QPlayer() 5 | { 6 | player = NULL; 7 | } 8 | 9 | void QPlayer::play(QString soundFile) 10 | { 11 | if (player == NULL) { 12 | player = new QMediaPlayer(); 13 | } 14 | 15 | if (soundFile.length()) { 16 | player->stop(); 17 | player->setMedia(QUrl::fromLocalFile(soundFile)); 18 | player->play(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/player/phonon.h: -------------------------------------------------------------------------------- 1 | #ifndef QPLAYER_PHONON_H 2 | #define QPLAYER_PHONON_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class QPlayer : public QObject 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | QPlayer(); 15 | 16 | void play(QString soundFile); 17 | 18 | protected: 19 | 20 | private: 21 | 22 | Phonon::MediaObject *player; 23 | Phonon::AudioOutput *audioOutput; 24 | 25 | }; 26 | 27 | #endif // QPLAYER_PHONON_H 28 | -------------------------------------------------------------------------------- /src/cachingnm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | CachingNetworkManager::CachingNetworkManager(QObject *parent) : QNetworkAccessManager(parent) 4 | { 5 | } 6 | 7 | QNetworkReply *CachingNetworkManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData) 8 | { 9 | QNetworkRequest request(req); 10 | request.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache); 11 | return QNetworkAccessManager::createRequest(op, request, outgoingData); 12 | } 13 | -------------------------------------------------------------------------------- /src/player/multimedia.h: -------------------------------------------------------------------------------- 1 | #ifndef QPLAYER_MULTIMEDIA_H 2 | #define QPLAYER_MULTIMEDIA_H 3 | 4 | /** 5 | * Sould be used only with Qt-5.0+ 6 | * Qt 4 don't have MediaPlayer 7 | */ 8 | 9 | #include 10 | #ifdef QT5 11 | #include 12 | #endif 13 | 14 | class QPlayer : public QObject 15 | { 16 | Q_OBJECT 17 | 18 | public: 19 | explicit QPlayer(); 20 | 21 | void play(QString soundFile); 22 | 23 | protected: 24 | 25 | private: 26 | 27 | QMediaPlayer *player; 28 | 29 | }; 30 | 31 | #endif // QPLAYER_MULTIMEDIA_H 32 | -------------------------------------------------------------------------------- /src/persistentcookiejar.h: -------------------------------------------------------------------------------- 1 | #ifndef PERSISTENTCOOKIEJAR_H 2 | #define PERSISTENTCOOKIEJAR_H 3 | 4 | #include 5 | 6 | class PersistentCookieJar : public QNetworkCookieJar 7 | { 8 | Q_OBJECT 9 | public: 10 | explicit PersistentCookieJar(QObject *parent = 0); 11 | 12 | bool setCookiesFromUrl(const QList &cookieList, const QUrl &url); 13 | void store(); 14 | void load(); 15 | private: 16 | QString cookiejar_location; 17 | static const char *line_separator; 18 | signals: 19 | 20 | public slots: 21 | 22 | }; 23 | 24 | #endif // PERSISTENTCOOKIEJAR_H 25 | -------------------------------------------------------------------------------- /src/fakewebview.h: -------------------------------------------------------------------------------- 1 | #ifndef FAKEWEBVIEW_H 2 | #define FAKEWEBVIEW_H 3 | 4 | #include 5 | 6 | #ifdef QT5 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | class FakeWebView : public QWebView 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit FakeWebView(QWidget* parent = 0); 18 | 19 | void load(const QUrl& url); 20 | void load(const QNetworkRequest& request, QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, const QByteArray &body = QByteArray()); 21 | void setUrl(const QUrl &url); 22 | 23 | }; 24 | 25 | #endif // FAKEWEBVIEW_H 26 | -------------------------------------------------------------------------------- /src/player/phonon.cpp: -------------------------------------------------------------------------------- 1 | #include "../config.h" 2 | #include "phonon.h" 3 | 4 | QPlayer::QPlayer() 5 | { 6 | player = NULL; 7 | } 8 | 9 | void QPlayer::play(QString soundFile) 10 | { 11 | if (player == NULL) { 12 | audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this); 13 | player = new Phonon::MediaObject(this); 14 | 15 | player->setTickInterval(1000); 16 | 17 | Phonon::createPath(player, audioOutput); 18 | } 19 | 20 | if (soundFile.length()) { 21 | player->stop(); 22 | player->clearQueue(); 23 | 24 | Phonon::MediaSource source(soundFile); 25 | 26 | player->setCurrentSource(source); 27 | player->play(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/qwk_webpage.h: -------------------------------------------------------------------------------- 1 | #ifndef QWK_WEBPAGE_H 2 | #define QWK_WEBPAGE_H 3 | 4 | #include 5 | #include "qwk_settings.h" 6 | 7 | #ifdef QT5 8 | #include 9 | #endif 10 | 11 | class QwkWebPage : public QWebPage 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit QwkWebPage(QWidget* parent = 0); 17 | 18 | QwkSettings* getSettings(); 19 | 20 | static QString userAgent; 21 | 22 | private: 23 | qint64 javascriptHangStarted; 24 | 25 | public Q_SLOTS: 26 | bool shouldInterruptJavaScript(); 27 | 28 | protected: 29 | void javaScriptConsoleMessage( const QString & message, int lineNumber, const QString & sourceID ); 30 | 31 | virtual QString userAgentForUrl(const QUrl & url) const; 32 | 33 | }; 34 | 35 | #endif // QWK_WEBPAGE_H 36 | -------------------------------------------------------------------------------- /src/qwk_settings.h: -------------------------------------------------------------------------------- 1 | #ifndef QWK_SETTINGS_H 2 | #define QWK_SETTINGS_H 3 | 4 | #include 5 | 6 | class QwkSettings : public QObject 7 | { 8 | Q_OBJECT 9 | 10 | public: 11 | explicit QwkSettings(QObject* parent = 0); 12 | 13 | void loadSettings(QString ini_file); 14 | 15 | bool getBool(QString key, bool defval=false); 16 | int getInt(QString key, int defval=0); 17 | uint getUInt(QString key, uint defval=0); 18 | qreal getReal(QString key, qreal defval=0); 19 | QString getQString(QString key, QString defval=QString()); 20 | QStringList getQStringList(QString key, QStringList defval=QStringList()); 21 | 22 | void setValue(QString key, QVariant value); 23 | 24 | protected: 25 | 26 | QSettings *qsettings; 27 | }; 28 | 29 | #endif // QWK_SETTINGS_H 30 | -------------------------------------------------------------------------------- /src/socketpair.h: -------------------------------------------------------------------------------- 1 | #ifndef SOCKETPAIR_H 2 | #define SOCKETPAIR_H 3 | 4 | /** 5 | * Unix socketpair function emulation 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class SocketPair: public QObject 14 | { 15 | Q_OBJECT 16 | public: 17 | SocketPair(QObject *parent = 0); 18 | 19 | bool create(); 20 | void close(); 21 | QTcpSocket* input(); 22 | QTcpSocket* output(); 23 | 24 | Q_SIGNALS: 25 | void sigData(QByteArray); 26 | 27 | public slots: 28 | void newConnection(); 29 | void readServerData(); 30 | 31 | private: 32 | QTimer *dataCheck; 33 | QTcpSocket *serverConnection; 34 | QTcpSocket clientConnection; 35 | QTcpServer server; 36 | }; 37 | 38 | #endif // SOCKETPAIR_H 39 | -------------------------------------------------------------------------------- /src/fakewebview.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | FakeWebView::FakeWebView(QWidget *parent) : QWebView(parent) 4 | { 5 | this->settings()->setAttribute(QWebSettings::JavascriptEnabled, false); 6 | this->settings()->setAttribute(QWebSettings::WebGLEnabled, false); 7 | this->settings()->setAttribute(QWebSettings::JavaEnabled, false); 8 | this->settings()->setAttribute(QWebSettings::PluginsEnabled, false); 9 | } 10 | 11 | void FakeWebView::setUrl(const QUrl &url) 12 | { 13 | emit ( urlChanged( url ) ); 14 | } 15 | 16 | 17 | void FakeWebView::load(const QUrl &url) 18 | { 19 | emit ( urlChanged( url ) ); 20 | } 21 | 22 | void FakeWebView::load(const QNetworkRequest &request, 23 | QNetworkAccessManager::Operation operation, 24 | const QByteArray &body) 25 | { 26 | Q_UNUSED(operation); 27 | Q_UNUSED(body); 28 | emit ( urlChanged( request.url() ) ); 29 | } 30 | -------------------------------------------------------------------------------- /debian/control.qt4: -------------------------------------------------------------------------------- 1 | Source: qt-webkit-kiosk 2 | Section: web 3 | Priority: extra 4 | Maintainer: Sergey Dryabzginsky 5 | Build-Depends: debhelper (>= 7.0.0), libqt4-dev (>=4.7.0), libqtwebkit-dev, libphonon-dev, libqt4-test 6 | Standards-Version: 3.9.2 7 | Homepage: https://github.com/sergey-dryabzhinsky/qt-webkit-kiosk 8 | 9 | Package: qt-webkit-kiosk 10 | Architecture: any 11 | Depends: ${shlibs:Depends}, ${misc:Depends}, phonon-backend-gstreamer 12 | Description: It's one-window browser writen on Qt4 & QtWebkit 13 | This is simple browser written on Qt4 & QtWebkit. 14 | Usualy runing in fullscreen mode, but supports maximized and fixed size window mode. 15 | This browser uses only one, "main" window. So, no popups, no plugins in separate processes, like Chrome do. 16 | Supports several parameters via configuration file: proxy, user-agent, click sound. 17 | Also supports hiding printer dialog and uses default or defined printer. 18 | -------------------------------------------------------------------------------- /src/unixsignals.h: -------------------------------------------------------------------------------- 1 | #ifndef UNIXSIGNALS_H 2 | #define UNIXSIGNALS_H 3 | 4 | /** 5 | * Realy ugly QSocketNotifier behaviour... 6 | * I can't send signal number through socket 7 | * So I create socket pair for every signal I listen to... 8 | * Damn... 9 | */ 10 | 11 | #include 12 | #include 13 | #include "socketpair.h" 14 | 15 | class UnixSignals : public QObject 16 | { 17 | Q_OBJECT 18 | public: 19 | UnixSignals( QObject *parent = 0 ); 20 | 21 | void start(); 22 | void stop(); 23 | 24 | static void signalHandler(int number); 25 | 26 | static SocketPair sockPair; 27 | 28 | Q_SIGNALS: 29 | void sigBREAK(); 30 | void sigTERM(); 31 | void sigHUP(); 32 | void sigINT(); 33 | void sigUSR1(); 34 | void sigUSR2(); 35 | 36 | private slots: 37 | void handleSig(QByteArray); 38 | 39 | private: 40 | void handleSignal(int); 41 | }; 42 | 43 | #endif // UNIXSIGNALS_H 44 | -------------------------------------------------------------------------------- /debian/control.qt48-sergey: -------------------------------------------------------------------------------- 1 | Source: qt-webkit-kiosk 2 | Section: web 3 | Priority: extra 4 | Maintainer: Sergey Dryabzginsky 5 | Build-Depends: debhelper (>= 7.0.0), libqt48-webkit4-dev | libqt48-webkit-dev, libqt48-phonon-dev, libqt48-test-dev, qt48-qmake, qt48-dev-tools 6 | Standards-Version: 3.9.2 7 | Homepage: https://github.com/sergey-dryabzhinsky/qt-webkit-kiosk 8 | 9 | Package: qt-webkit-kiosk 10 | Architecture: any 11 | Depends: ${shlibs:Depends}, ${misc:Depends}, qt48-plugins-phonon-backend 12 | Description: It's one-window browser writen on Qt4 & QtWebkit 13 | This is simple browser written on Qt4 & QtWebkit. 14 | Usualy runing in fullscreen mode, but supports maximized and fixed size window mode. 15 | This browser uses only one, "main" window. So, no popups, no plugins in separate processes, like Chrome do. 16 | Supports several parameters via configuration file: proxy, user-agent, click sound. 17 | Also supports hiding printer dialog and uses default or defined printer. 18 | -------------------------------------------------------------------------------- /debian/control.qt5: -------------------------------------------------------------------------------- 1 | Source: qt-webkit-kiosk 2 | Section: web 3 | Priority: extra 4 | Maintainer: Sergey Dryabzginsky 5 | Build-Depends: debhelper (>= 7), qt5-qmake, qt5-default, qtbase5-dev (>= 5.0.0), libqt5webkit5-dev, qtmultimedia5-dev, qtdeclarative5-dev, qtsystems5-dev | qtbase5-dev (>= 5.3.0), qtscript5-dev, libpulse-dev, libsqlite3-dev 6 | Standards-Version: 3.9.2 7 | Homepage: https://github.com/sergey-dryabzhinsky/qt-webkit-kiosk 8 | 9 | Package: qt-webkit-kiosk 10 | Architecture: any 11 | Depends: ${shlibs:Depends}, ${misc:Depends} 12 | Description: It's one-window browser writen on Qt5 & QtWebkit 13 | This is simple browser written on Qt5 & QtWebkit. 14 | Usualy runing in fullscreen mode, but supports maximized and fixed size window mode. 15 | This browser uses only one, "main" window. So, no popups, no plugins in separate processes, like Chrome do. 16 | Supports several parameters via configuration file: proxy, user-agent, click sound. 17 | Also supports hiding printer dialog and uses default or defined printer. 18 | -------------------------------------------------------------------------------- /resources/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Qt WebKit browser for Kiosk 4 | 18 | 19 | 20 |
21 |

Hello, World!

22 |

This is your kiosk browser, written in Qt/C++ & WebKit!

23 |
24 |

Check link click sound.

25 |

Check print via Javascript

26 |

Try Close window via Javascript (tag a).

27 |

Try via Javascript (tag button).

28 |

Try and wait for Qt to interrupt.

29 |

Fullscreen mode switched by <F11>

30 |

Toggle Developer Tools by <F12> if enabled

31 |

To reload page press <F5>

32 |

To reload page with cache clean up press <CTRL+R>

33 |

To Quit press <CTRL+Q>

34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /setup.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2010-07-22T01:54:24 4 | # 5 | #------------------------------------------------- 6 | 7 | TEMPLATE = subdirs 8 | CONFIG += ordered warn_on 9 | 10 | CONFIG(debug, debug|release) { 11 | # here comes debug specific statements 12 | message(Debug build) 13 | } else { 14 | # here comes release specific statements 15 | message(Release build) 16 | CONFIG -= debug 17 | DEFINES += QT_NO_DEBUG_OUTPUT 18 | } 19 | 20 | SUBDIRS += src/qt-webkit-kiosk.pro 21 | 22 | # INSTALL 23 | 24 | target.path = $${PREFIX}/bin 25 | 26 | desktop.files = resources/qt-webkit-kiosk.desktop 27 | desktop.path = $${PREFIX}/share/applications 28 | 29 | config.files = resources/qt-webkit-kiosk.ini 30 | config.path = $${PREFIX}/share/qt-webkit-kiosk 31 | 32 | sound.files = \ 33 | resources/window-clicked.wav resources/window-clicked.ogg resources/window-clicked.mp3 \ 34 | resources/link-clicked.wav resources/link-clicked.ogg resources/link-clicked.mp3 35 | sound.path = $${PREFIX}/share/qt-webkit-kiosk 36 | 37 | html.files = resources/default.html 38 | html.path = $${PREFIX}/share/qt-webkit-kiosk 39 | 40 | doc.files = doc/lgpl.html doc/README.md 41 | doc.path = $${PREFIX}/share/doc/qt-webkit-kiosk 42 | 43 | INSTALLS += target desktop config sound html doc 44 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://dep.debian.net/deps/dep5 2 | Upstream-Name: qt-webkit-kiosk 3 | Source: https://code.google.com/p/qt-webkit-kiosk/ 4 | 5 | Files: * 6 | Copyright: 2011-2014 Sergey Dryabzhinsky 7 | License: LGPL-3.0+ 8 | 9 | Files: debian/* 10 | Copyright: 2011-2014 Sergey Dryabzhinsky 11 | License: GPL-3.0+ 12 | 13 | License: LGPL-3.0+ 14 | This program is free software: you can redistribute it and/or modify 15 | it under the terms of the GNU Lesser General Public License as published by 16 | the Free Software Foundation, either version 3 of the License, or 17 | (at your option) any later version. 18 | . 19 | This package is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | . 24 | You should have received a copy of the GNU Lesser General Public License 25 | along with this program. If not, see . 26 | . 27 | On Debian systems, the complete text of the GNU Lesser General 28 | Public License version 3 can be found in "/usr/share/common-licenses/LGPL-3". 29 | 30 | # Please also look if there are files or directories which have a 31 | # different copyright/license attached and list them here. 32 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | Qt WebKit Kiosk-mode browser 2 | =============== 3 | 4 | This is simple browser application written on Qt & QtWebkit. 5 | 6 | Qt versions `4.[78]` and `5.[2-5]` are supported. 7 | 8 | Note: if you use libqt5webkit5-dev (>= 5.212~) package - you should build project with Qt >= 5.7. 9 | 10 | Usualy runing in fullscreen mode, but supports maximized and fixed size window mode. 11 | 12 | This browser uses only one application window. So, no popups, no plugins in separate processes, like Chromium do. And no tabs. 13 | 14 | Support several parameters via configuration file: proxy, user-agent, click sound, plugins, etc. 15 | 16 | Also hides printer dialog, uses default or defined printer, adds custom js/css files to every loaded page, disables text selection. 17 | 18 | ## Release Build 19 | ``` 20 | qmake 21 | make -j$(nproc) all 22 | ``` 23 | 24 | ## Debug Build 25 | ``` 26 | qmake CONFIG+=debug 27 | make -j$(nproc) all 28 | ``` 29 | 30 | ## TODO 31 | 32 | - Support QtWebEngine instead of QtWebkit. 33 | 34 | ## Downloads 35 | 36 | Downloads now on public [gDrive Folder](https://drive.google.com/folderview?id=0B6CU04AyADvoV19PMlhJSVA2TDQ&usp=sharing). 37 | 38 | For Windows available [Qt bundles](https://drive.google.com/folderview?id=0B6CU04AyADvoXzUxdW5KeEt5cW8&usp=sharing) public folder. It needed by project installer without Qt. 39 | 40 | All "installers" are just [7-zip](https://7-zip.org) self-extracting archives. 41 | 42 | ### Launchpad 43 | 44 | - Main PPA: ppa:sergey-dryabzhinsky/qt-webkit-kiosk 45 | - Additional: ppa:sergey-dryabzhinsky/qt48 46 | -------------------------------------------------------------------------------- /doc/README.ru.md: -------------------------------------------------------------------------------- 1 | Qt WebKit Kiosk-mode browser 2 | =============== 3 | 4 | Это простое приложение-браузер, написанное с использованием Qt & QtWebkit. 5 | 6 | Поддерживаются версии Qt - `4.[78]` и `5.[2-5]`. 7 | 8 | Замечание: если воспользуетесь пакетом libqt5webkit5-dev (>= 5.212~) - то сможете собрать проект с Qt >= 5.7. 9 | 10 | Обычно запускается в полноэкранном режиме, но так же поддерживается запуск 11 | в максимизированном окне или в окне фиксированного размера. 12 | 13 | Этот браузер использует только одно окно-процесс для работы приложения. 14 | Так что никаких поп-апов, плагинов в отдельных процессах, как это делает Хромиум. И никаких табов. 15 | 16 | Поддерживает небольшой набор параметров, заданных в конфигурационном файле: 17 | прокси, заголовок User-Agent, звуки клика, включение плагинов, и др. 18 | 19 | Так же умеет: прятать диалог принтера, использовать принтер по-умолчанию, или указанный специально; 20 | добавлять заданные js/css файлы в каждую загруженную страницу; отключать выделение текста. 21 | 22 | ## TODO 23 | 24 | - Поддержка QtWebEngine вместо QtWebkit. 25 | 26 | ## Загрузки 27 | 28 | Загрузки на публичном [каталоге в gDrive](https://drive.google.com/folderview?id=0B6CU04AyADvoV19PMlhJSVA2TDQ&usp=sharing). 29 | 30 | Для Windows доступны [наборы Qt](https://drive.google.com/folderview?id=0B6CU04AyADvoXzUxdW5KeEt5cW8&usp=sharing). Они нужны для установки QWK без Qt. 31 | 32 | Все "инсталяторы" просто самораспаковывающиеся [7-zip](https://7-zip.org) архивы. 33 | 34 | ### Launchpad 35 | 36 | - Основной PPA: ppa:sergey-dryabzhinsky/qt-webkit-kiosk 37 | - Дополнительный: ppa:sergey-dryabzhinsky/qt48 38 | -------------------------------------------------------------------------------- /src/socketpair.cpp: -------------------------------------------------------------------------------- 1 | #include "socketpair.h" 2 | #include 3 | #include 4 | 5 | SocketPair::SocketPair(QObject *parent) 6 | : QObject(parent) 7 | { 8 | dataCheck = new QTimer(); 9 | dataCheck->setInterval(100); 10 | } 11 | 12 | bool SocketPair::create() 13 | { 14 | connect(dataCheck, SIGNAL(timeout()), this, SLOT(readServerData())); 15 | connect(&server, SIGNAL(newConnection()), this, SLOT(newConnection())); 16 | 17 | int tries = 5; 18 | while (tries) { 19 | if (!server.isListening()) { 20 | if (server.listen(QHostAddress::LocalHost)) { 21 | break; 22 | } 23 | } else { 24 | break; 25 | } 26 | tries--; 27 | } 28 | if (!server.isListening()) { 29 | qDebug() << "Can't start tcpServer:" << server.errorString(); 30 | return false; 31 | } 32 | 33 | clientConnection.setSocketOption( QAbstractSocket::LowDelayOption, 1 ); 34 | clientConnection.setSocketOption( QAbstractSocket::KeepAliveOption, 1 ); 35 | 36 | clientConnection.connectToHost(QHostAddress::LocalHost, server.serverPort(), QIODevice::WriteOnly); 37 | return true; 38 | } 39 | 40 | void SocketPair::newConnection() 41 | { 42 | serverConnection = server.nextPendingConnection(); 43 | 44 | serverConnection->setSocketOption( QAbstractSocket::LowDelayOption, 1 ); 45 | serverConnection->setSocketOption( QAbstractSocket::KeepAliveOption, 1 ); 46 | serverConnection->setReadBufferSize( 1 ); 47 | 48 | dataCheck->start(); 49 | 50 | // connect(serverConnection, SIGNAL(readyRead()), this, SLOT(readServerData())); 51 | server.close(); 52 | } 53 | 54 | void SocketPair::readServerData() 55 | { 56 | QByteArray data = serverConnection->readAll(); 57 | if (data.length()) { 58 | emit sigData(data); 59 | } 60 | } 61 | 62 | void SocketPair::close() 63 | { 64 | dataCheck->stop(); 65 | clientConnection.close(); 66 | if (serverConnection) { 67 | serverConnection->close(); 68 | delete serverConnection; 69 | serverConnection = 0; 70 | } 71 | server.close(); 72 | } 73 | 74 | QTcpSocket* SocketPair::input() 75 | { 76 | return &clientConnection; 77 | } 78 | 79 | QTcpSocket* SocketPair::output() 80 | { 81 | return serverConnection; 82 | } 83 | -------------------------------------------------------------------------------- /src/webview.h: -------------------------------------------------------------------------------- 1 | #ifndef WEBVIEW_H 2 | #define WEBVIEW_H 3 | 4 | #include 5 | 6 | #ifdef QT5 7 | #include 8 | #include 9 | #endif 10 | 11 | #include 12 | #include "qplayer.h" 13 | #include "qwk_webpage.h" 14 | #include "fakewebview.h" 15 | #include "qwk_settings.h" 16 | 17 | class WebView : public QWebView 18 | { 19 | Q_OBJECT 20 | 21 | public: 22 | explicit WebView(QWidget* parent = 0); 23 | 24 | void setSettings(QwkSettings *settings); 25 | QwkSettings* getSettings(); 26 | 27 | void loadCustomPage(QString uri); 28 | void loadHomepage(); 29 | void initSignals(); 30 | 31 | void setPage(QwkWebPage* page); 32 | void resetLoadTimer(); 33 | void stopLoadTimer(); 34 | 35 | QWebView *createWindow(QWebPage::WebWindowType type); 36 | 37 | void playSound(QString soundSetting); 38 | 39 | // http://slow-tone.blogspot.com/2011/04/qt-hide-scrollbars-qwebview.html?showComment=1318404188431#c5258624438625837585 40 | void scrollUp(); 41 | void scrollDown(); 42 | void scrollPageUp(); 43 | void scrollPageDown(); 44 | void scrollHome(); 45 | void scrollEnd(); 46 | 47 | public slots: 48 | void handlePrintRequested(QWebFrame *); 49 | void handleFakeviewUrlChanged(const QUrl &); 50 | void handleFakeviewLoadFinished(bool); 51 | 52 | protected: 53 | void mousePressEvent(QMouseEvent *event); 54 | QPlayer *getPlayer(); 55 | QWebView *getFakeLoader(); 56 | QTimer *getLoadTimer(); 57 | 58 | signals: 59 | 60 | void qwkNetworkError(QNetworkReply::NetworkError error, QString message); 61 | void qwkNetworkReplyUrl(QUrl url); 62 | 63 | private: 64 | QPlayer *player; 65 | QwkSettings *qwkSettings; 66 | FakeWebView *loader; 67 | QPrinter *printer; 68 | QTimer *loadTimer; 69 | 70 | private slots: 71 | #ifndef QT_NO_SSL 72 | void handleSslErrors(QNetworkReply* reply, const QList &errors); 73 | #endif 74 | void handleWindowCloseRequested(); 75 | 76 | void handleNetworkReply(QNetworkReply *reply); 77 | void handleAuthReply(QNetworkReply *aReply, QAuthenticator *aAuth); 78 | void handleProxyAuthReply(const QNetworkProxy &proxy, QAuthenticator *aAuth); 79 | 80 | void handleLoadTimerTimeout(); 81 | }; 82 | 83 | #endif // WEBVIEW_H 84 | -------------------------------------------------------------------------------- /src/persistentcookiejar.cpp: -------------------------------------------------------------------------------- 1 | #include "persistentcookiejar.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | const char *PersistentCookieJar::line_separator = "\n"; 11 | 12 | PersistentCookieJar::PersistentCookieJar(QObject *parent) : 13 | QNetworkCookieJar(parent) 14 | { 15 | #ifdef QT5 16 | QString cookiejar_path = QStandardPaths::writableLocation(QStandardPaths::DataLocation); 17 | #else 18 | QString cookiejar_path = QDesktopServices::storageLocation(QDesktopServices::DataLocation); 19 | #endif 20 | 21 | if (cookiejar_path.length() == 0) { 22 | qDebug() << "No data locations available; not storing any cookies."; 23 | cookiejar_location = ""; 24 | return; 25 | } 26 | 27 | QDir cookiejar_dir(cookiejar_path); 28 | if (!cookiejar_dir.exists()) { 29 | cookiejar_dir.mkpath("."); 30 | } 31 | 32 | cookiejar_location = cookiejar_path + QDir::toNativeSeparators("/cookiejar.txt"); 33 | 34 | load(); 35 | } 36 | 37 | bool PersistentCookieJar::setCookiesFromUrl(const QList &cookieList, const QUrl &url) 38 | { 39 | bool answer = QNetworkCookieJar::setCookiesFromUrl(cookieList, url); 40 | if (cookiejar_location.length() != 0) { 41 | store(); 42 | } 43 | return answer; 44 | } 45 | 46 | void PersistentCookieJar::store() { 47 | qDebug() << "Writing cookies to " << cookiejar_location; 48 | 49 | QFile storage(cookiejar_location); 50 | storage.open(QIODevice::WriteOnly); 51 | 52 | QList cookies = allCookies(); 53 | 54 | for (int i=0; i < cookies.length(); i++) 55 | { 56 | qDebug() << "Writing cookie " << i; 57 | storage.write(cookies[i].toRawForm()); 58 | storage.write(line_separator); 59 | } 60 | 61 | qDebug() << "Wrote" << cookies.length() << "cookies to the cookiejar."; 62 | 63 | storage.flush(); 64 | storage.close(); 65 | } 66 | 67 | void PersistentCookieJar::load() { 68 | qDebug() << "Loading cookies from" << cookiejar_location; 69 | 70 | QFile storage(cookiejar_location); 71 | storage.open(QIODevice::ReadOnly); 72 | QByteArray bytes = storage.readAll(); 73 | QList cookies = bytes.split(*line_separator); 74 | 75 | QList all_cookies = QNetworkCookie::parseCookies(";"); 76 | 77 | for (int i=0; i < cookies.length(); i++) { 78 | all_cookies += QNetworkCookie::parseCookies(cookies[i]); 79 | } 80 | 81 | setAllCookies(all_cookies); 82 | 83 | qDebug() << "Read" << all_cookies.length() << "valid cookies from the cookiejar."; 84 | storage.close(); 85 | } 86 | -------------------------------------------------------------------------------- /src/qwk_webpage.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Qt Webkit Kiosk version of QWebPage 3 | * With custom JS interrupt slot 4 | */ 5 | 6 | 7 | #include "config.h" 8 | 9 | #include 10 | #include "qinfo.h" 11 | 12 | #include 13 | #include 14 | #include "webview.h" 15 | #include "qwk_webpage.h" 16 | 17 | 18 | QwkWebPage::QwkWebPage(QWidget* parent): QWebPage(parent) 19 | { 20 | javascriptHangStarted = 0; 21 | } 22 | 23 | QwkSettings* QwkWebPage::getSettings() 24 | { 25 | if (this->view() != NULL) { 26 | WebView* v = (WebView *)(this->view()); 27 | return v->getSettings(); 28 | } 29 | return NULL; 30 | } 31 | 32 | bool QwkWebPage::shouldInterruptJavaScript() 33 | { 34 | qWarning() << QDateTime::currentDateTime().toString() << "shouldInterruptJavaScript: Handle JavaScript Interrupt..."; 35 | QwkSettings *s = this->getSettings(); 36 | 37 | if (s != NULL) { 38 | if (s->getBool("browser/interrupt_javascript")) { 39 | 40 | qint64 now = QDateTime::currentMSecsSinceEpoch(); 41 | if (!javascriptHangStarted) { 42 | // hang started 30s back 43 | qDebug() << "-- first interrupt attempt?"; 44 | // In Qt4 - hang interval check - 10 sec 45 | javascriptHangStarted = now - 10*1000; 46 | qDebug() << "-- hang start time in msec:" << javascriptHangStarted; 47 | } 48 | 49 | qDebug() << "-- current time in msec:" << now; 50 | 51 | qint64 interval = s->getInt("browser/interrupt_javascript_interval") * 1000; 52 | qDebug() << "-- max hang interval in msec:" << interval; 53 | qDebug() << "-- current hang interval in msec:" << now - javascriptHangStarted; 54 | 55 | if (now - javascriptHangStarted >= interval) { 56 | qWarning() << QDateTime::currentDateTime().toString() << "shouldInterruptJavaScript: Stop javascript! Executed too long!"; 57 | return true; 58 | } 59 | } 60 | 61 | qApp->processEvents(QEventLoop::AllEvents, 50); 62 | // No interrupt, ever 63 | return false; 64 | } 65 | 66 | // Interrupt, by default 67 | return QWebPage::shouldInterruptJavaScript(); 68 | } 69 | 70 | void QwkWebPage::javaScriptConsoleMessage( const QString & message, int lineNumber, const QString & sourceID ) 71 | { 72 | QwkSettings *s = this->getSettings(); 73 | 74 | if (s != NULL) { 75 | if (s->getBool("browser/show_js_console_messages")) { 76 | //do something! 77 | qInfo() << QDateTime::currentDateTime().toString() << "JS Console message:" << message << "Line:" << lineNumber << "Source:" << sourceID; 78 | } 79 | } 80 | } 81 | 82 | 83 | QString QwkWebPage::userAgent = ""; 84 | 85 | QString QwkWebPage::userAgentForUrl(const QUrl & url) const 86 | { 87 | if (QwkWebPage::userAgent.length()) { 88 | return QwkWebPage::userAgent; 89 | } 90 | 91 | return QWebPage::userAgentForUrl(url); 92 | } 93 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2011 Sergey Dryabzhinsky 4 | ** All rights reserved. 5 | ** Contact: Sergey Dryabzhinsky (sergey.dryabzhinsky@gmail.com) 6 | ** 7 | ** This file is part of the examples of the Qt Toolkit. 8 | ** 9 | ** GNU Lesser General Public License Usage 10 | ** Alternatively, this file may be used under the terms of the GNU Lesser 11 | ** General Public License version 2.1 as published by the Free Software 12 | ** Foundation and appearing in the file LICENSE.LGPL included in the 13 | ** packaging of this file. Please review the following information to 14 | ** ensure the GNU Lesser General Public License version 2.1 requirements 15 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 16 | ** 17 | ** In addition, as a special exception, Nokia gives you certain additional 18 | ** rights. These rights are described in the Nokia Qt LGPL Exception 19 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 20 | ** 21 | ** GNU General Public License Usage 22 | ** Alternatively, this file may be used under the terms of the GNU 23 | ** General Public License version 3.0 as published by the Free Software 24 | ** Foundation and appearing in the file LICENSE.GPL included in the 25 | ** packaging of this file. Please review the following information to 26 | ** ensure the GNU General Public License version 3.0 requirements will be 27 | ** met: http://www.gnu.org/copyleft/gpl.html. 28 | ** 29 | ** If you have questions regarding the use of this file, please contact 30 | ** Nokia at qt-info@nokia.com. 31 | ** $QT_END_LICENSE$ 32 | ** 33 | ****************************************************************************/ 34 | 35 | #include 36 | #include "mainwindow.h" 37 | #include "anyoption.h" 38 | 39 | bool setupOptions(AnyOption *cmdopts) 40 | { 41 | cmdopts->addUsage("This is a simple web-browser working in fullscreen kiosk-mode."); 42 | cmdopts->addUsage(""); 43 | cmdopts->addUsage("Usage: "); 44 | cmdopts->addUsage(""); 45 | cmdopts->addUsage(" -h --help Print usage and exit"); 46 | cmdopts->addUsage(" -v --version Print version and exit"); 47 | cmdopts->addUsage(" -c --config options.ini Configuration INI-file"); 48 | cmdopts->addUsage(" -u --uri http://www.example.com/ Open this URI, home page"); 49 | cmdopts->addUsage(" -C --clear-cache Clear cached request data"); 50 | cmdopts->addUsage(" -R --rotate Rotate display 90 degrees"); 51 | cmdopts->addUsage(""); 52 | cmdopts->addUsage("Build with:"); 53 | cmdopts->addUsage(" Qt: " QT_VERSION_STR); 54 | cmdopts->addUsage(" WebKit: library v" QTWEBKIT_VERSION_STR); 55 | cmdopts->addUsage(""); 56 | cmdopts->addUsage("Runing with:"); 57 | 58 | QString qtv = QString(" Qt: ") + QString(qVersion()); 59 | QByteArray qtvb = qtv.toLocal8Bit(); 60 | const char * qtvch = qtvb.constData(); 61 | cmdopts->addUsage(qtvch); 62 | 63 | QString qtwv = QString(" WebKit: engine v") + qWebKitVersion(); 64 | QByteArray qtwvb = qtwv.toLocal8Bit(); 65 | const char * qtwvch = qtwvb.constData(); 66 | cmdopts->addUsage(qtwvch); 67 | cmdopts->addUsage(""); 68 | 69 | qDebug() << "Build with: Qt = " QT_VERSION_STR << "; WebKit = " QTWEBKIT_VERSION_STR; 70 | qDebug() << "Runing with: Qt =" << qVersion() << "; WebKit =" << qWebKitVersion(); 71 | 72 | cmdopts->setFlag("help", 'h'); 73 | cmdopts->setFlag("version", 'v'); 74 | cmdopts->setFlag("clear-cache", 'C'); 75 | cmdopts->setFlag("rotate", 'R'); 76 | 77 | cmdopts->setOption("config", 'c'); 78 | cmdopts->setOption("uri", 'u'); 79 | 80 | cmdopts->setVersion(VERSION); 81 | 82 | #ifdef QT5 83 | cmdopts->processCommandArgs( QCoreApplication::arguments().length(), QCoreApplication::arguments() ); 84 | #else 85 | cmdopts->processCommandArgs( QCoreApplication::argc(), QCoreApplication::argv() ); 86 | #endif 87 | 88 | if (cmdopts->getFlag('h') || cmdopts->getFlag("help")) { 89 | qDebug(">> Help option in command prompt..."); 90 | cmdopts->printUsage(); 91 | return false; 92 | } 93 | 94 | if (cmdopts->getFlag('v') || cmdopts->getFlag("version")) { 95 | qDebug(">> Version option in command prompt..."); 96 | cmdopts->printVersion(); 97 | return false; 98 | } 99 | 100 | return true; 101 | } 102 | 103 | int main(int argc, char * argv[]) 104 | { 105 | QApplication app(argc, argv); 106 | 107 | AnyOption *cmdopts = new AnyOption(); 108 | if (!setupOptions(cmdopts)) { 109 | return 0; 110 | } 111 | 112 | MainWindow *browser = new MainWindow(); 113 | browser->init(cmdopts); 114 | 115 | // executes browser.cleanupSlot() when the Qt framework emits aboutToQuit() signal. 116 | QObject::connect(qApp, SIGNAL(aboutToQuit()), 117 | browser, SLOT(cleanupSlot())); 118 | 119 | int ret = app.exec(); 120 | qDebug() << "Application return: " << ret; 121 | } 122 | -------------------------------------------------------------------------------- /resources/qt-webkit-kiosk.ini: -------------------------------------------------------------------------------- 1 | [browser] 2 | ; Full URI or full path to HTML file 3 | ;homepage=http://www.example.com/ 4 | homepage=default.html 5 | 6 | ; Delay load homepage on startup 7 | startup_load_delayed=true 8 | ; Delay in msec 9 | startup_load_delay=100 10 | 11 | ; Delay in msec, default 15 sec 12 | ; Set to -1 to disable 13 | network_error_reload_delay=15000 14 | 15 | ; Delay in msec, default 15 sec 16 | page_load_timeout=15000 17 | ; Show some error messages, like network errors 18 | ; Messages text box will appear above page 19 | ; For debug purpose mostly 20 | show_error_messaged=false 21 | 22 | ; When you enable the cookiejar your cookies will be remembered between runs. 23 | ; When you disable the cookiejar your cookies will disappear when you quit the program. 24 | cookiejar=false 25 | 26 | java=false 27 | javascript=true 28 | ; handle window.open? 29 | ; catch link and follow. no new windows. 30 | javascript_can_open_windows=true 31 | ; handle window.close ? 32 | javascript_can_close_windows=false 33 | webgl=false 34 | plugins=true 35 | 36 | ; Custom User-Agent header 37 | ; Default value: Mozilla/5.0 (%Platform%%Security%%Subplatform%) AppleWebKit/%WebKitVersion% (KHTML, like Gecko) %AppVersion Safari/%WebKitVersion% 38 | ; Set it to empty value to use defaults 39 | custom_user_agent_header= 40 | 41 | ; Don't show any javascript console messages by default 42 | ; For debug purpose mostly 43 | show_js_console_messages=false 44 | 45 | ; Trust any certificate by default 46 | ignore_ssl_errors=true 47 | 48 | ; Don't close application, show default homepage. Used with javascript window.close() 49 | show_homepage_on_window_close=true 50 | 51 | ; Disable reaction on keyboard 52 | disable_hotkeys=false 53 | 54 | 55 | ; Interrupt long running javascript ever 56 | interrupt_javascript=true 57 | 58 | ; Interrupt long running javascript after this time in seconds 59 | ; By defaults in Qt first check will be after 10s of hang and every 10s 60 | interrupt_javascript_interval=30 61 | 62 | 63 | [signals] 64 | enable=true 65 | 66 | ; Warning! 67 | ; Some signals dont' exists on some systems... 68 | ; Windows - SIGUSR1, SIGUSR2 69 | 70 | ; Empty by default 71 | ; SIGUSR1 - reload config and load homepage URI 72 | ; If set - try to load defined URI 73 | SIGUSR1= 74 | ; SIGUSR2 - load homepage URI from current config 75 | ; If set - try to load defined URI 76 | SIGUSR2= 77 | 78 | [rpc] 79 | ; @TODO 80 | ; May be JSON-RPC 81 | enable=false 82 | ; Do not forget to allow access in your firewall 83 | listen=127.0.0.1:9000 84 | 85 | [inspector] 86 | ; Call web-inspector by F12 87 | enable=false 88 | ; Visible on browser start 89 | visible=false 90 | 91 | [attach] 92 | ; Attach files content then page loaded. Styles goes first 93 | ; Define each file full path and split with comma 94 | styles= 95 | javascripts= 96 | 97 | [event-sounds] 98 | enable=false 99 | ; full-path to sound file 100 | ; format - supported by Qt or system 101 | ; Sound for click anywhere in window 102 | ;window-clicked=window-clicked.wav 103 | ; Sound for click on a link 104 | ;link-clicked=link-clicked.wav 105 | 106 | [cache] 107 | enable=true 108 | ; Full path to cache directory 109 | location=cache 110 | ; Max cache size in bytes, default 100Mb 111 | size=100000000 112 | ; cache clean up 113 | clean-on-start=false 114 | clean-on-exit=false 115 | 116 | [application] 117 | ; Used in User-Agent header 118 | organization=Organization 119 | organization-domain=www.example.com 120 | name=QtWebkitKiosk 121 | version=1.99.11-dev 122 | 123 | [printing] 124 | enable=false 125 | show-printer-dialog=false 126 | printer=default 127 | page_margin_left=0 128 | page_margin_top=0 129 | page_margin_right=0 130 | page_margin_bottom=0 131 | 132 | [proxy] 133 | enable=false 134 | system=true 135 | host=proxy.example.com 136 | port=3128 137 | auth=false 138 | username=username 139 | password=password 140 | 141 | [view] 142 | fullscreen=true 143 | maximized=false 144 | fixed-size=false 145 | fixed-width=800 146 | fixed-height=600 147 | fixed-centered=true 148 | ; if not centered 149 | fixed-x=0 150 | fixed-y=0 151 | 152 | ; Another window manager hint to prevent showing other windows or taskbar 153 | stay_on_top=false 154 | 155 | ;; Minimum window size, default - 320x200 156 | ;minimum-width=320 157 | ;minimum-height=200 158 | 159 | ; Try to avoid some bogus Windows behaviour when taskbar become visible after window fullscreened... 160 | startup_resize_delayed=true 161 | ; Delay in msec 162 | startup_resize_delay=200 163 | 164 | ; Try to hide window scrollbars for any content overflow. Scrolling works only with keyboard keys. If they not disabled. 165 | hide_scrollbars=true 166 | 167 | ; Try to hide selection 168 | disable_selection=true 169 | 170 | ; Show progress bar at page top then web-page loading 171 | show_load_progress=true 172 | 173 | ; Page scale factor 174 | page_scale=1.0 175 | 176 | ; If you use this program without a mouse it can be nice to hide the mouse. 177 | ; This does not disable the mouse itself: you can still interact with websites 178 | ; using the mouse, you just won't be able to see the mouse pointer. 179 | hide_mouse_cursor=false 180 | 181 | [localstorage] 182 | enable=true 183 | 184 | [security] 185 | ; Locally loaded documents are allowed to access remote urls. 186 | local_content_can_access_remote_urls=false 187 | -------------------------------------------------------------------------------- /src/qt-webkit-kiosk.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2010-07-22T01:54:24 4 | # 5 | #------------------------------------------------- 6 | 7 | QT = core gui network webkit 8 | 9 | contains(QT_VERSION, ^5\\.[0-9]+\\..*) { 10 | QT += widgets webkitwidgets printsupport 11 | DEFINES += QT5 12 | } 13 | 14 | CONFIG += console link_pkgconfig 15 | TARGET = qt-webkit-kiosk 16 | TEMPLATE = app 17 | VERSION = 1.99.11-dev 18 | 19 | CONFIG(debug, debug|release) { 20 | # here comes debug specific statements 21 | message(Debug build) 22 | } else { 23 | # here comes release specific statements 24 | CONFIG -= debug 25 | DEFINES += QT_NO_DEBUG_OUTPUT 26 | } 27 | 28 | DEFINES += VERSION=\\\"$${VERSION}\\\" 29 | 30 | PLAYER = NONE 31 | 32 | !win32 { 33 | isEmpty( PREFIX ) { 34 | PREFIX = /usr/local 35 | } 36 | 37 | ICON = $${PREFIX}/share/icons/$${TARGET}.png 38 | DEFINES += RESOURCES=\\\"$${PREFIX}/share/$${TARGET}/\\\" 39 | DEFINES += ICON=\\\"$${ICON}\\\" 40 | 41 | PKG_TEST=QtTest 42 | 43 | contains(QT_VERSION, ^5\\.[0-9]+\\..*) { 44 | 45 | PKG_TEST=Qt5Test 46 | 47 | packagesExist(Qt5Multimedia) { 48 | message('Multimedia framework found. Using Multimedia-player.') 49 | DEFINES += PLAYER_MULTIMEDIA 50 | QT += multimedia 51 | PLAYER = MULTIMEDIA 52 | SOURCES += player/multimedia.cpp 53 | HEADERS += player/multimedia.h 54 | } 55 | 56 | contains(PLAYER, NONE) { 57 | # Ubuntu / Debian version? 58 | packagesExist(phonon4qt5) { 59 | message('Phonon framework found. Using Phonon-player.') 60 | DEFINES += PLAYER_PHONON 61 | QT += phonon4qt5 62 | PLAYER = PHONON 63 | SOURCES += player/phonon.cpp 64 | HEADERS += player/phonon.h 65 | } 66 | } 67 | } 68 | 69 | contains(PLAYER, NONE) { 70 | 71 | packagesExist(phonon) { 72 | message('Phonon framework found. Using Phonon-player.') 73 | DEFINES += PLAYER_PHONON 74 | QT += phonon 75 | PLAYER = PHONON 76 | SOURCES += player/phonon.cpp 77 | HEADERS += player/phonon.h 78 | } 79 | 80 | } 81 | 82 | packagesExist($${PKG_TEST}) { 83 | message('Test framework found.') 84 | DEFINES += USE_TESTLIB 85 | QT += testlib 86 | } else { 87 | warning('No QtTest framework found! Will not do hacks with window...') 88 | } 89 | } 90 | win32 { 91 | ICON = ./$${TARGET}.png 92 | DEFINES += RESOURCES=\\\"./\\\" 93 | DEFINES += ICON=\\\"$${ICON}\\\" 94 | 95 | # Windows don't have pkg-config 96 | # So we check generic paths... 97 | 98 | contains(QT_VERSION, ^5\\.[0-9]+\\..*) { 99 | exists($$[QT_INSTALL_PREFIX]\\bin\\Qt*Multimedia*) { 100 | message('Multimedia framework found. Using Multimedia-player.') 101 | DEFINES += PLAYER_MULTIMEDIA 102 | QT += multimedia 103 | PLAYER = MULTIMEDIA 104 | SOURCES += player/multimedia.cpp 105 | HEADERS += player/multimedia.h 106 | } 107 | } 108 | contains(PLAYER, NONE) { 109 | exists($$[QT_INSTALL_PREFIX]\\bin\\phonon*) { 110 | message('Phonon framework found. Using Phonon-player.') 111 | DEFINES += PLAYER_PHONON 112 | QT += phonon 113 | PLAYER = PHONON 114 | SOURCES += player/phonon.cpp 115 | HEADERS += player/phonon.h 116 | } 117 | } 118 | exists($$[QT_INSTALL_PREFIX]\\bin\\Qt*Test*) { 119 | message('Test framework found.') 120 | DEFINES += USE_TESTLIB 121 | QT += testlib 122 | } else { 123 | warning('No QtTest framework found! Will not do hacks with window...') 124 | } 125 | } 126 | 127 | message(Qt player: $${PLAYER}) 128 | 129 | contains(PLAYER, NONE) { 130 | warning('No multimedia framework found! Using NULL-player.') 131 | DEFINES += PLAYER_NULL 132 | SOURCES += player/null.cpp 133 | HEADERS += player/null.h 134 | } 135 | 136 | message(Qt version: $$[QT_VERSION]) 137 | message(Qt is installed in $$[QT_INSTALL_PREFIX]) 138 | message(Settings:) 139 | message(- QT : $${QT}) 140 | message(- PREFIX : $${PREFIX}) 141 | message(- TARGET : $${TARGET}) 142 | message(- VERSION: $${VERSION}) 143 | 144 | SOURCES += main.cpp\ 145 | mainwindow.cpp \ 146 | qwk_webpage.cpp \ 147 | webview.cpp \ 148 | anyoption.cpp \ 149 | fakewebview.cpp \ 150 | cachingnm.cpp \ 151 | unixsignals.cpp \ 152 | socketpair.cpp \ 153 | persistentcookiejar.cpp \ 154 | qwk_settings.cpp 155 | 156 | HEADERS += mainwindow.h \ 157 | qwk_webpage.h \ 158 | webview.h \ 159 | anyoption.h \ 160 | config.h \ 161 | qplayer.h \ 162 | fakewebview.h \ 163 | cachingnm.h \ 164 | unixsignals.h \ 165 | socketpair.h \ 166 | persistentcookiejar.h \ 167 | qwk_settings.h 168 | 169 | # DEBUG 170 | #message(- SOURCES: $${SOURCES}) 171 | #message(- HEADERS: $${HEADERS}) 172 | 173 | # INSTALL 174 | 175 | target.path = $${PREFIX}/bin 176 | 177 | icon.files = ../resources/$${TARGET}.png 178 | icon.path = $${PREFIX}/share/icons 179 | 180 | INSTALLS += target icon 181 | -------------------------------------------------------------------------------- /src/mainwindow.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** Contact: Nokia Corporation (qt-info@nokia.com) 6 | ** 7 | ** This file is part of the examples of the Qt Toolkit. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL$ 10 | ** Commercial Usage 11 | ** Licensees holding valid Qt Commercial licenses may use this file in 12 | ** accordance with the Qt Commercial License Agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and Nokia. 15 | ** 16 | ** GNU Lesser General Public License Usage 17 | ** Alternatively, this file may be used under the terms of the GNU Lesser 18 | ** General Public License version 2.1 as published by the Free Software 19 | ** Foundation and appearing in the file LICENSE.LGPL included in the 20 | ** packaging of this file. Please review the following information to 21 | ** ensure the GNU Lesser General Public License version 2.1 requirements 22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 23 | ** 24 | ** In addition, as a special exception, Nokia gives you certain additional 25 | ** rights. These rights are described in the Nokia Qt LGPL Exception 26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 | ** 28 | ** GNU General Public License Usage 29 | ** Alternatively, this file may be used under the terms of the GNU 30 | ** General Public License version 3.0 as published by the Free Software 31 | ** Foundation and appearing in the file LICENSE.GPL included in the 32 | ** packaging of this file. Please review the following information to 33 | ** ensure the GNU General Public License version 3.0 requirements will be 34 | ** met: http://www.gnu.org/copyleft/gpl.html. 35 | ** 36 | ** If you have questions regarding the use of this file, please contact 37 | ** Nokia at qt-info@nokia.com. 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | #ifndef QWK_MAINWINDOW_H 42 | #define QWK_MAINWINDOW_H 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #ifdef USE_TESTLIB 56 | #include 57 | #endif 58 | 59 | #ifdef QT5 60 | #include 61 | #endif 62 | 63 | #include "webview.h" 64 | #include "anyoption.h" 65 | #include "unixsignals.h" 66 | #include "qwk_settings.h" 67 | 68 | class MainWindow : public QMainWindow 69 | { 70 | Q_OBJECT 71 | 72 | public: 73 | explicit MainWindow(); 74 | 75 | void init(AnyOption *cmdopts); 76 | 77 | void clearCache(); 78 | void clearCacheOnExit(); 79 | 80 | protected slots: 81 | 82 | void cleanupSlot(); 83 | 84 | void adjustTitle(QString); 85 | void setProgress(int p); 86 | void startLoading(); 87 | void urlChanged(const QUrl &); 88 | void finishLoading(bool); 89 | void pageIconLoaded(); 90 | 91 | void desktopResized(int p); 92 | 93 | void delayedWindowResize(); 94 | void delayedPageLoad(); 95 | void delayedPageReload(); 96 | 97 | void handleQwkNetworkError(QNetworkReply::NetworkError, QString); 98 | void handleQwkNetworkReplyUrl(QUrl); 99 | 100 | void networkStateChanged(QNetworkSession::State state); 101 | 102 | // TERM or INT - Quit from App 103 | void unixSignalQuit(); 104 | // HUP - Reload config 105 | void unixSignalHup(); 106 | // USR1 - Reload config and back to homepage, or load page from config 107 | void unixSignalUsr1(); 108 | // USR2 - Back to homepage, or load page from config 109 | void unixSignalUsr2(); 110 | 111 | protected: 112 | 113 | void centerFixedSizeWindow(); 114 | void attachJavascripts(); 115 | void attachStyles(); 116 | void putWindowUp(); 117 | bool hideScrollbars(); 118 | bool disableSelection(); 119 | void keyPressEvent(QKeyEvent *event); 120 | void keyReleaseEvent(QKeyEvent *event); 121 | void resizeEvent(QResizeEvent* event); 122 | 123 | private: 124 | bool rotated; // Are we rotating 90 degrees? 125 | 126 | WebView *view; // Webkit Page View 127 | QHBoxLayout *topBox; // Box for progress and messages 128 | QProgressBar *loadProgress; // progress bar to display page loading 129 | QLabel *messagesBox; // error messages 130 | 131 | QwkSettings *qwkSettings; 132 | QNetworkDiskCache *diskCache; 133 | QWebInspector *inspector; 134 | 135 | QCursor *hiddenCurdor; 136 | QKeyEvent *eventExit; 137 | 138 | AnyOption *cmdopts; 139 | UnixSignals *handler; 140 | 141 | QGraphicsView *graphicsView; 142 | QGraphicsScene *graphicsScene; 143 | QGraphicsProxyWidget *proxyWidget; 144 | 145 | #ifdef USE_TESTLIB 146 | QTestEventList *simulateClick; 147 | #endif 148 | 149 | int progress; 150 | bool isScrollBarsHidden; 151 | bool isSelectionDisabled; 152 | bool isUrlRealyChanged; 153 | 154 | QNetworkSession *n_session; 155 | QNetworkInterface *network_interface; 156 | 157 | QTimer *delayedResize; 158 | QTimer *delayedLoad; 159 | }; 160 | 161 | #endif // QWK_MAINWINDOW_H 162 | -------------------------------------------------------------------------------- /src/unixsignals.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "unixsignals.h" 5 | 6 | SocketPair UnixSignals::sockPair; 7 | 8 | /** 9 | * It should be created only ones 10 | * 11 | * @brief UnixSignals::UnixSignals 12 | * @param parent 13 | */ 14 | UnixSignals::UnixSignals( QObject *parent ) 15 | : QObject(parent) 16 | { 17 | if (!UnixSignals::sockPair.create()) 18 | qFatal("Unable to create signal socket pair"); 19 | 20 | connect(&UnixSignals::sockPair, SIGNAL(sigData(QByteArray)), this, SLOT(handleSig(QByteArray))); 21 | } 22 | 23 | void UnixSignals::start() 24 | { 25 | #ifdef SIGBREAK 26 | // Available on Windows 27 | if (receivers(SIGNAL(sigBREAK())) > 0) { 28 | if (signal(SIGBREAK, UnixSignals::signalHandler) == SIG_ERR) { 29 | qFatal("Unable to set signal handler on BREAK"); 30 | } 31 | } else { 32 | qDebug("No listeners for signal BREAK"); 33 | } 34 | #else 35 | qWarning("No signal BREAK defined"); 36 | #endif 37 | 38 | #ifdef SIGTERM 39 | if (receivers(SIGNAL(sigTERM())) > 0) { 40 | if (signal(SIGTERM, UnixSignals::signalHandler) == SIG_ERR) { 41 | qFatal("Unable to set signal handler on TERM"); 42 | } 43 | } else { 44 | qDebug("No listeners for signal TERM"); 45 | } 46 | #else 47 | qWarning("No signal TERM defined"); 48 | #endif 49 | 50 | #ifdef SIGINT 51 | if (receivers(SIGNAL(sigINT())) > 0) { 52 | if (signal(SIGINT, UnixSignals::signalHandler) == SIG_ERR) { 53 | qFatal("Unable to set signal handler on INT"); 54 | } 55 | } else { 56 | qDebug("No listeners for signal INT"); 57 | } 58 | #else 59 | qWarning("No signal INT defined"); 60 | #endif 61 | 62 | #ifdef SIGHUP 63 | // Unavailable on Windows 64 | if (receivers(SIGNAL(sigHUP())) > 0) { 65 | if (signal(SIGHUP, UnixSignals::signalHandler) == SIG_ERR) { 66 | qFatal("Unable to set signal handler on HUP"); 67 | } 68 | } else { 69 | qDebug("No listeners for signal HUP"); 70 | } 71 | #else 72 | qWarning("No signal HUP defined"); 73 | #endif 74 | 75 | #ifdef SIGUSR1 76 | // Unavailable on Windows 77 | if (receivers(SIGNAL(sigUSR1())) > 0) { 78 | if (signal(SIGUSR1, UnixSignals::signalHandler) == SIG_ERR) { 79 | qFatal("Unable to set signal handler on USR1"); 80 | } 81 | } else { 82 | qDebug("No listeners for signal USR1"); 83 | } 84 | #else 85 | qWarning("No signal USR1 defined"); 86 | #endif 87 | 88 | #ifdef SIGUSR2 89 | // Unavailable on Windows 90 | if (receivers(SIGNAL(sigUSR2())) > 0) { 91 | if (signal(SIGUSR2, UnixSignals::signalHandler) == SIG_ERR) { 92 | qFatal("Unable to set signal handler on USR2"); 93 | } 94 | } else { 95 | qDebug("No listeners for signal USR1"); 96 | } 97 | #else 98 | qWarning("No signal USR2 defined"); 99 | #endif 100 | } 101 | 102 | void UnixSignals::stop() 103 | { 104 | UnixSignals::sockPair.close(); 105 | } 106 | 107 | void UnixSignals::signalHandler(int number) 108 | { 109 | char tmp = number; 110 | qDebug() << "UnixSignals::signalHandler -- pass signal" << number; 111 | UnixSignals::sockPair.input()->write(&tmp, sizeof(tmp)); 112 | } 113 | 114 | void UnixSignals::handleSig(QByteArray data) 115 | { 116 | qDebug() << "Got data:" << data.toHex(); 117 | int number = 0, lastNumber = 0; 118 | if (data.length()) { 119 | qDebug() << " signals in data:" << data.length(); 120 | 121 | // Socket can be filled with several signals 122 | // If they come too fast... 123 | while (data.length()) { 124 | number = data[0]; 125 | data.remove(0, 1); 126 | 127 | // Skeep repeated signals 128 | if (number != lastNumber) { 129 | handleSignal(number); 130 | lastNumber = number; 131 | } 132 | } 133 | 134 | } 135 | } 136 | 137 | void UnixSignals::handleSignal(int number) 138 | { 139 | qDebug() << "Got signal:" << number; 140 | switch (number) { 141 | #ifdef SIGBREAK 142 | case SIGBREAK: 143 | qDebug() << "Got SIGBREAK! emit event!"; 144 | emit sigBREAK(); 145 | break; 146 | #endif 147 | #ifdef SIGHUP 148 | case SIGHUP: 149 | qDebug() << "Got SIGHUP! emit event!"; 150 | emit sigHUP(); 151 | break; 152 | #endif 153 | #ifdef SIGINT 154 | case SIGINT: 155 | qDebug() << "Got SIGINT! emit event!"; 156 | emit sigINT(); 157 | break; 158 | #endif 159 | #ifdef SIGTERM 160 | case SIGTERM: 161 | qDebug() << "Got SIGTERM! emit event!"; 162 | emit sigTERM(); 163 | break; 164 | #endif 165 | #ifdef SIGUSR1 166 | case SIGUSR1: 167 | qDebug() << "Got SIGUSR1! emit event!"; 168 | emit sigUSR1(); 169 | break; 170 | #endif 171 | #ifdef SIGUSR2 172 | case SIGUSR2: 173 | qDebug() << "Got SIGUSR2! emit event!"; 174 | emit sigUSR2(); 175 | break; 176 | #endif 177 | default: 178 | qDebug() << "Got something? Dunno what to do..."; 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /doc/lgpl.txt: -------------------------------------------------------------------------------- 1 | http://www.gnu.org/licenses/lgpl-3.0.txt 2 | GNU LESSER GENERAL PUBLIC LICENSE 3 | Version 3, 29 June 2007 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | 10 | This version of the GNU Lesser General Public License incorporates 11 | the terms and conditions of version 3 of the GNU General Public 12 | License, supplemented by the additional permissions listed below. 13 | 14 | 0. Additional Definitions. 15 | 16 | As used herein, "this License" refers to version 3 of the GNU Lesser 17 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 18 | General Public License. 19 | 20 | "The Library" refers to a covered work governed by this License, 21 | other than an Application or a Combined Work as defined below. 22 | 23 | An "Application" is any work that makes use of an interface provided 24 | by the Library, but which is not otherwise based on the Library. 25 | Defining a subclass of a class defined by the Library is deemed a mode 26 | of using an interface provided by the Library. 27 | 28 | A "Combined Work" is a work produced by combining or linking an 29 | Application with the Library. The particular version of the Library 30 | with which the Combined Work was made is also called the "Linked 31 | Version". 32 | 33 | The "Minimal Corresponding Source" for a Combined Work means the 34 | Corresponding Source for the Combined Work, excluding any source code 35 | for portions of the Combined Work that, considered in isolation, are 36 | based on the Application, and not on the Linked Version. 37 | 38 | The "Corresponding Application Code" for a Combined Work means the 39 | object code and/or source code for the Application, including any data 40 | and utility programs needed for reproducing the Combined Work from the 41 | Application, but excluding the System Libraries of the Combined Work. 42 | 43 | 1. Exception to Section 3 of the GNU GPL. 44 | 45 | You may convey a covered work under sections 3 and 4 of this License 46 | without being bound by section 3 of the GNU GPL. 47 | 48 | 2. Conveying Modified Versions. 49 | 50 | If you modify a copy of the Library, and, in your modifications, a 51 | facility refers to a function or data to be supplied by an Application 52 | that uses the facility (other than as an argument passed when the 53 | facility is invoked), then you may convey a copy of the modified 54 | version: 55 | 56 | a) under this License, provided that you make a good faith effort to 57 | ensure that, in the event an Application does not supply the 58 | function or data, the facility still operates, and performs 59 | whatever part of its purpose remains meaningful, or 60 | 61 | b) under the GNU GPL, with none of the additional permissions of 62 | this License applicable to that copy. 63 | 64 | 3. Object Code Incorporating Material from Library Header Files. 65 | 66 | The object code form of an Application may incorporate material from 67 | a header file that is part of the Library. You may convey such object 68 | code under terms of your choice, provided that, if the incorporated 69 | material is not limited to numerical parameters, data structure 70 | layouts and accessors, or small macros, inline functions and templates 71 | (ten or fewer lines in length), you do both of the following: 72 | 73 | a) Give prominent notice with each copy of the object code that the 74 | Library is used in it and that the Library and its use are 75 | covered by this License. 76 | 77 | b) Accompany the object code with a copy of the GNU GPL and this license 78 | document. 79 | 80 | 4. Combined Works. 81 | 82 | You may convey a Combined Work under terms of your choice that, 83 | taken together, effectively do not restrict modification of the 84 | portions of the Library contained in the Combined Work and reverse 85 | engineering for debugging such modifications, if you also do each of 86 | the following: 87 | 88 | a) Give prominent notice with each copy of the Combined Work that 89 | the Library is used in it and that the Library and its use are 90 | covered by this License. 91 | 92 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 93 | document. 94 | 95 | c) For a Combined Work that displays copyright notices during 96 | execution, include the copyright notice for the Library among 97 | these notices, as well as a reference directing the user to the 98 | copies of the GNU GPL and this license document. 99 | 100 | d) Do one of the following: 101 | 102 | 0) Convey the Minimal Corresponding Source under the terms of this 103 | License, and the Corresponding Application Code in a form 104 | suitable for, and under terms that permit, the user to 105 | recombine or relink the Application with a modified version of 106 | the Linked Version to produce a modified Combined Work, in the 107 | manner specified by section 6 of the GNU GPL for conveying 108 | Corresponding Source. 109 | 110 | 1) Use a suitable shared library mechanism for linking with the 111 | Library. A suitable mechanism is one that (a) uses at run time 112 | a copy of the Library already present on the user's computer 113 | system, and (b) will operate properly with a modified version 114 | of the Library that is interface-compatible with the Linked 115 | Version. 116 | 117 | e) Provide Installation Information, but only if you would otherwise 118 | be required to provide such information under section 6 of the 119 | GNU GPL, and only to the extent that such information is 120 | necessary to install and execute a modified version of the 121 | Combined Work produced by recombining or relinking the 122 | Application with a modified version of the Linked Version. (If 123 | you use option 4d0, the Installation Information must accompany 124 | the Minimal Corresponding Source and Corresponding Application 125 | Code. If you use option 4d1, you must provide the Installation 126 | Information in the manner specified by section 6 of the GNU GPL 127 | for conveying Corresponding Source.) 128 | 129 | 5. Combined Libraries. 130 | 131 | You may place library facilities that are a work based on the 132 | Library side by side in a single library together with other library 133 | facilities that are not Applications and are not covered by this 134 | License, and convey such a combined library under terms of your 135 | choice, if you do both of the following: 136 | 137 | a) Accompany the combined library with a copy of the same work based 138 | on the Library, uncombined with any other library facilities, 139 | conveyed under the terms of this License. 140 | 141 | b) Give prominent notice with the combined library that part of it 142 | is a work based on the Library, and explaining where to find the 143 | accompanying uncombined form of the same work. 144 | 145 | 6. Revised Versions of the GNU Lesser General Public License. 146 | 147 | The Free Software Foundation may publish revised and/or new versions 148 | of the GNU Lesser General Public License from time to time. Such new 149 | versions will be similar in spirit to the present version, but may 150 | differ in detail to address new problems or concerns. 151 | 152 | Each version is given a distinguishing version number. If the 153 | Library as you received it specifies that a certain numbered version 154 | of the GNU Lesser General Public License "or any later version" 155 | applies to it, you have the option of following the terms and 156 | conditions either of that published version or of any later version 157 | published by the Free Software Foundation. If the Library as you 158 | received it does not specify a version number of the GNU Lesser 159 | General Public License, you may choose any version of the GNU Lesser 160 | General Public License ever published by the Free Software Foundation. 161 | 162 | If the Library as you received it specifies that a proxy can decide 163 | whether future versions of the GNU Lesser General Public License shall 164 | apply, that proxy's public statement of acceptance of any version is 165 | permanent authorization for you to choose that version for the 166 | Library. -------------------------------------------------------------------------------- /src/anyoption.h: -------------------------------------------------------------------------------- 1 | #ifndef _ANYOPTION_H 2 | #define _ANYOPTION_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define COMMON_OPT 1 11 | #define COMMAND_OPT 2 12 | #define FILE_OPT 3 13 | #define COMMON_FLAG 4 14 | #define COMMAND_FLAG 5 15 | #define FILE_FLAG 6 16 | 17 | #define COMMAND_OPTION_TYPE 1 18 | #define COMMAND_FLAG_TYPE 2 19 | #define FILE_OPTION_TYPE 3 20 | #define FILE_FLAG_TYPE 4 21 | #define UNKNOWN_TYPE 5 22 | 23 | #define DEFAULT_MAXOPTS 10 24 | #define MAX_LONG_PREFIX_LENGTH 2 25 | 26 | #define DEFAULT_MAXUSAGE 3 27 | #define DEFAULT_MAXHELP 10 28 | 29 | #define TRUE_FLAG "true" 30 | 31 | using namespace std; 32 | 33 | class AnyOption 34 | { 35 | 36 | public: /* the public interface */ 37 | AnyOption(); 38 | AnyOption(int maxoptions ); 39 | AnyOption(int maxoptions , int maxcharoptions); 40 | ~AnyOption(); 41 | 42 | /* 43 | * following set methods specifies the 44 | * special characters and delimiters 45 | * if not set traditional defaults will be used 46 | */ 47 | 48 | void setCommandPrefixChar( char _prefix ); /* '-' in "-w" */ 49 | void setCommandLongPrefix( char *_prefix ); /* '--' in "--width" */ 50 | void setFileCommentChar( char _comment ); /* '#' in shellscripts */ 51 | void setFileDelimiterChar( char _delimiter );/* ':' in "width : 100" */ 52 | 53 | /* 54 | * provide the input for the options 55 | * like argv[] for commndline and the 56 | * option file name to use; 57 | */ 58 | 59 | void useCommandArgs( int _argc, char **_argv ); 60 | void useCommandArgs( int _argc, QStringList _argv ); 61 | void useFileName( const char *_filename ); 62 | 63 | /* 64 | * turn off the POSIX style options 65 | * this means anything starting with a '-' or "--" 66 | * will be considered a valid option 67 | * which alo means you cannot add a bunch of 68 | * POIX options chars together like "-lr" for "-l -r" 69 | * 70 | */ 71 | 72 | void noPOSIX(); 73 | 74 | /* 75 | * prints warning verbose if you set anything wrong 76 | */ 77 | void setVerbose(); 78 | 79 | 80 | /* 81 | * there are two types of options 82 | * 83 | * Option - has an associated value ( -w 100 ) 84 | * Flag - no value, just a boolean flag ( -nogui ) 85 | * 86 | * the options can be either a string ( GNU style ) 87 | * or a character ( traditional POSIX style ) 88 | * or both ( --width, -w ) 89 | * 90 | * the options can be common to the commandline and 91 | * the optionfile, or can belong only to either of 92 | * commandline and optionfile 93 | * 94 | * following set methods, handle all the aboove 95 | * cases of options. 96 | */ 97 | 98 | /* options comman to command line and option file */ 99 | void setOption( const char *opt_string ); 100 | void setOption( char opt_char ); 101 | void setOption( const char *opt_string , char opt_char ); 102 | void setFlag( const char *opt_string ); 103 | void setFlag( char opt_char ); 104 | void setFlag( const char *opt_string , char opt_char ); 105 | 106 | /* options read from commandline only */ 107 | void setCommandOption( const char *opt_string ); 108 | void setCommandOption( char opt_char ); 109 | void setCommandOption( const char *opt_string , char opt_char ); 110 | void setCommandFlag( const char *opt_string ); 111 | void setCommandFlag( char opt_char ); 112 | void setCommandFlag( const char *opt_string , char opt_char ); 113 | 114 | /* options read from an option file only */ 115 | void setFileOption( const char *opt_string ); 116 | void setFileOption( char opt_char ); 117 | void setFileOption( const char *opt_string , char opt_char ); 118 | void setFileFlag( const char *opt_string ); 119 | void setFileFlag( char opt_char ); 120 | void setFileFlag( const char *opt_string , char opt_char ); 121 | 122 | /* 123 | * process the options, registerd using 124 | * useCommandArgs() and useFileName(); 125 | */ 126 | void processOptions(); 127 | void processCommandArgs(); 128 | void processCommandArgs( int max_args ); 129 | bool processFile(); 130 | 131 | /* 132 | * process the specified options 133 | */ 134 | void processCommandArgs( int _argc, char **_argv ); 135 | void processCommandArgs( int _argc, char **_argv, int max_args ); 136 | void processCommandArgs( int _argc, QStringList _argv ); 137 | bool processFile( const char *_filename ); 138 | 139 | /* 140 | * get the value of the options 141 | * will return NULL if no value is set 142 | */ 143 | char *getValue( const char *_option ); 144 | bool getFlag( const char *_option ); 145 | char *getValue( char _optchar ); 146 | bool getFlag( char _optchar ); 147 | 148 | /* 149 | * Print Usage 150 | */ 151 | void printUsage(); 152 | void printVersion(); 153 | void setVersion( const char *ver ); 154 | void printAutoUsage(); 155 | void addUsage( const char *line ); 156 | void printHelp(); 157 | /* print auto usage printing for unknown options or flag */ 158 | void autoUsagePrint(bool flag); 159 | 160 | /* 161 | * get the argument count and arguments sans the options 162 | */ 163 | int getArgc(); 164 | char* getArgv( int index ); 165 | bool hasOptions(); 166 | 167 | private: /* the hidden data structure */ 168 | int argc; /* commandline arg count */ 169 | char **argv; /* commndline args */ 170 | const char* filename; /* the option file */ 171 | char* appname; /* the application name from argv[0] */ 172 | 173 | int *new_argv; /* arguments sans options (index to argv) */ 174 | int new_argc; /* argument count sans the options */ 175 | int max_legal_args; /* ignore extra arguments */ 176 | 177 | 178 | /* option strings storage + indexing */ 179 | int max_options; /* maximum number of options */ 180 | const char **options; /* storage */ 181 | int *optiontype; /* type - common, command, file */ 182 | int *optionindex; /* index into value storage */ 183 | int option_counter; /* counter for added options */ 184 | 185 | /* option chars storage + indexing */ 186 | int max_char_options; /* maximum number options */ 187 | char *optionchars; /* storage */ 188 | int *optchartype; /* type - common, command, file */ 189 | int *optcharindex; /* index into value storage */ 190 | int optchar_counter; /* counter for added options */ 191 | 192 | /* values */ 193 | char **values; /* common value storage */ 194 | int g_value_counter; /* globally updated value index LAME! */ 195 | 196 | /* help and usage */ 197 | const char **usage; /* usage */ 198 | const char *version; /* version string */ 199 | int max_usage_lines; /* max usage lines reseverd */ 200 | int usage_lines; /* number of usage lines */ 201 | 202 | bool command_set; /* if argc/argv were provided */ 203 | bool file_set; /* if a filename was provided */ 204 | bool mem_allocated; /* if memory allocated in init() */ 205 | bool posix_style; /* enables to turn off POSIX style options */ 206 | bool verbose; /* silent|verbose */ 207 | bool print_usage; /* usage verbose */ 208 | bool print_help; /* help verbose */ 209 | 210 | char opt_prefix_char; /* '-' in "-w" */ 211 | char long_opt_prefix[MAX_LONG_PREFIX_LENGTH + 1]; /* '--' in "--width" */ 212 | char file_delimiter_char; /* ':' in width : 100 */ 213 | char file_comment_char; /* '#' in "#this is a comment" */ 214 | char equalsign; 215 | char comment; 216 | char delimiter; 217 | char endofline; 218 | char whitespace; 219 | char nullterminate; 220 | 221 | bool set; //was static member 222 | bool once; //was static member 223 | 224 | bool hasoptions; 225 | bool autousage; 226 | 227 | private: /* the hidden utils */ 228 | void init(); 229 | void init(int maxopt, int maxcharopt ); 230 | bool alloc(); 231 | void cleanup(); 232 | bool valueStoreOK(); 233 | 234 | /* grow storage arrays as required */ 235 | bool doubleOptStorage(); 236 | bool doubleCharStorage(); 237 | bool doubleUsageStorage(); 238 | 239 | bool setValue( const char *option , char *value ); 240 | bool setFlagOn( const char *option ); 241 | bool setValue( char optchar , char *value); 242 | bool setFlagOn( char optchar ); 243 | 244 | void addOption( const char* option , int type ); 245 | void addOption( char optchar , int type ); 246 | void addOptionError( const char *opt); 247 | void addOptionError( char opt); 248 | bool findFlag( char* value ); 249 | void addUsageError( const char *line ); 250 | bool CommandSet(); 251 | bool FileSet(); 252 | bool POSIX(); 253 | 254 | char parsePOSIX( char* arg ); 255 | int parseGNU( char *arg ); 256 | bool matchChar( char c ); 257 | int matchOpt( char *opt ); 258 | 259 | /* dot file methods */ 260 | char *readFile(); 261 | char *readFile( const char* fname ); 262 | bool consumeFile( char *buffer ); 263 | void processLine( char *theline, int length ); 264 | char *chomp( char *str ); 265 | void valuePairs( char *type, char *value ); 266 | void justValue( char *value ); 267 | 268 | void printVerbose( const char *msg ); 269 | void printVerbose( char *msg ); 270 | void printVerbose( char ch ); 271 | void printVerbose( ); 272 | 273 | 274 | }; 275 | 276 | #endif /* ! _ANYOPTION_H */ 277 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | qt-webkit-kiosk (1.99.10-1sergey1) unstable; urgency=medium 2 | 3 | * Fix event to view passthrough by @therealjumbo 4 | * Fix use of qInfo macros with Qt4 5 | * Security option - local content access to remote urls by @knowack1 6 | 7 | -- Sergey Dryabzhinsky Thu, 06 Oct 2020 02:12:00 +0300 8 | 9 | qt-webkit-kiosk (1.99.9-1sergey1) unstable; urgency=medium 10 | 11 | * LocalStorage support by @BrandonLWhite 12 | * fix conflict with std::launch by @joufella 13 | * support for js infinite run interruption 14 | - sould work everywhere but not - only with Windows Qt4 msvc2010 build 15 | - new ini-file options: browser/interrupt_javascript, browser/interrupt_javascript_interval 16 | * drop use of c++11 features - not supported by old GCC 17 | 18 | -- Sergey Dryabzhinsky Sat, 12 Mar 2016 20:46:00 +0400 19 | 20 | qt-webkit-kiosk (1.99.6-1sergey1) unstable; urgency=medium 21 | 22 | * better network errors handling 23 | * add messages box to output network errors and ini-file option for this 24 | * better webview signal handling - use mainFrame for main page loading status to not overflow with signals 25 | * checkout for network availability and reset qt network session if something going on 26 | * delayed page reload if network state changes 27 | * new ini-file options: browser/network_error_reload_delay, browser/page_load_timeout, browser/show_error_messaged 28 | 29 | -- Sergey Dryabzhinsky Sat, 12 Mar 2016 20:46:00 +0400 30 | 31 | qt-webkit-kiosk (1.99.5-1sergey1) unstable; urgency=medium 32 | 33 | * Activate more settings for WebView - acceleration 34 | * Don't leak by FakeLoader - just stop load 35 | 36 | -- Sergey Dryabzhinsky Sat, 12 Mar 2016 20:46:00 +0400 37 | 38 | qt-webkit-kiosk (1.99.4-1sergey1) unstable; urgency=medium 39 | 40 | * move code with hidding mouse cursor after main window show 41 | * fix qt-5 version detection 42 | 43 | -- Sergey Dryabzhinsky Mon, 27 Jul 2015 22:25:00 +0400 44 | 45 | qt-webkit-kiosk (1.99.3-1sergey1) unstable; urgency=medium 46 | 47 | * Add persistent cookie storage. Thanks to quinox. 48 | * Add 'Backspace' hot-key to go back through page history. 49 | 50 | -- Sergey Dryabzhinsky Mon, 26 Aug 2014 02:13:00 +0400 51 | 52 | qt-webkit-kiosk (1.99.2-1sergey1) unstable; urgency=medium 53 | 54 | * Fixed dependencies checks for *nix 55 | 56 | -- Sergey Dryabzhinsky Sun, 06 Jul 2014 01:16:15 +0400 57 | 58 | qt-webkit-kiosk (1.99.1-1sergey1) unstable; urgency=medium 59 | 60 | * Version 1.99.1 61 | * Combined Qt4 and Qt5 code 62 | * Fixed dependencies checks for win32 63 | * Removed unused embedded-server application 64 | 65 | -- Sergey Dryabzhinsky Sat, 05 Jul 2014 21:57:00 +0400 66 | 67 | qt-webkit-kiosk (1.99.0-1sergey1) unstable; urgency=medium 68 | 69 | * Version 1.99.0 70 | * Try to combine Qt4 and Qt5 code 71 | 72 | -- Sergey Dryabzhinsky Sat, 05 Jul 2014 18:59:18 +0400 73 | 74 | qt-webkit-kiosk (1.05.15-1sergey1) unstable; urgency=low 75 | 76 | * Version 1.05.15: 77 | + Merge changes from 1.4.11 78 | - Fixed signal handling - use socketpair for every listening signal... 79 | 80 | -- Sergey Dryabzhinsky Wed, 19 Mar 2014 02:20:00 +0400 81 | 82 | qt-webkit-kiosk (1.05.14-1sergey1) unstable; urgency=low 83 | 84 | * Version 1.05.14: 85 | + Update project build files 86 | + Rewrite unix signal handling 87 | + Add confguration options for actions on USR1 and USR2 signals 88 | 89 | -- Sergey Dryabzhinsky Sun, 16 Mar 2014 01:34:00 +0400 90 | 91 | qt-webkit-kiosk (1.05.13sergey1) unstable; urgency=low 92 | 93 | * Version 1.05.13: 94 | + Fix turning off text selection after next page load 95 | + Add page load indication with progress bar 96 | + Add option to scale pages 97 | 98 | -- Sergey Dryabzhinsky Sun, 19 Jan 2014 19:15:00 +0400 99 | 100 | qt-webkit-kiosk (1.05.12sergey1) unstable; urgency=low 101 | 102 | * Version 1.05.12: 103 | + Fix styles and scripts inserting into page after it's loaded 104 | + Add option to disable text selection 105 | 106 | -- Sergey Dryabzhinsky Sat, 18 Jan 2014 21:44:00 +0400 107 | 108 | qt-webkit-kiosk (1.05.11ubuntu1) unstable; urgency=low 109 | 110 | * Version 1.05.11: 111 | + Fix scroll to the bottom of page 112 | 113 | -- Sergey Dryabzhinsky Sat, 18 Jan 2014 19:02:00 +0400 114 | 115 | qt-webkit-kiosk (1.05.10ubuntu1) unstable; urgency=low 116 | 117 | * Version 1.05.10: 118 | + Add new hotkeys for page scrolling 119 | + Add new options: 120 | - hide scroll bars 121 | - window on top 122 | - disable hotkeys 123 | 124 | -- Sergey Dryabzhinsky Sat, 18 Jan 2014 17:45:00 +0400 125 | 126 | qt-webkit-kiosk (1.05.09ubuntu1) unstable; urgency=low 127 | 128 | * Version 1.05.09: 129 | + Add startup delay for window resize and page load 130 | + Add minimum window size options 131 | 132 | -- Sergey Dryabzhinsky Sun, 12 Jan 2014 21:16:00 +0400 133 | 134 | qt-webkit-kiosk (1.05.08ubuntu1) unstable; urgency=low 135 | 136 | * Version 1.05.08: 137 | * Qt project files clean up and fix 138 | 139 | -- Sergey Dryabzhinsky Thu, 23 Jul 2013 10:46:00 +0400 140 | 141 | qt-webkit-kiosk (1.05.07ubuntu1) unstable; urgency=low 142 | 143 | * Version 1.05.07: 144 | * + Fix handle link click and sound play 145 | * + New sounds 146 | 147 | -- Sergey Dryabzhinsky Mon, 22 Jul 2013 22:57:00 +0400 148 | 149 | qt-webkit-kiosk (1.05.06ubuntu1) unstable; urgency=low 150 | 151 | * Version 1.05.06: 152 | * + Fix handle link click and sound play 153 | * + Fix handle window.close() 154 | 155 | -- Sergey Dryabzhinsky Sun, 21 Jul 2013 23:05:00 +0400 156 | 157 | qt-webkit-kiosk (1.05.05ubuntu1) unstable; urgency=low 158 | 159 | * Version 1.05.05: 160 | * Merged changes from 1.04.04 161 | * + Fix segfault on exit 162 | * + Disable printing by default 163 | 164 | -- Sergey Dryabzhinsky Sat, 06 Jul 2013 03:31:42 +0400 165 | 166 | qt-webkit-kiosk (1.05.04ubuntu1) unstable; urgency=low 167 | 168 | * Version 1.05.04: 169 | * Handle SIGTERM signals 170 | * Cache cleanup on start or exit 171 | * New commandline option -C 172 | * Fix cache use - tune request objects 173 | 174 | -- Sergey Dryabzhinsky Sat, 06 Jul 2013 00:09:43 +0400 175 | 176 | qt-webkit-kiosk (1.05.03ubuntu1) unstable; urgency=low 177 | 178 | * Version 1.05.03 179 | * Use fake webview to catch new window URL 180 | * Disable console output 181 | 182 | -- Sergey Dryabzhinsky Fri, 05 Jul 2013 12:12:17 +0400 183 | 184 | qt-webkit-kiosk (1.05.02ubuntu1) unstable; urgency=low 185 | 186 | * Version 1.05.02 187 | * Add support of opening links from new windows into main 188 | * Add support of ignoring SSL errors 189 | 190 | -- Sergey Dryabzhinsky Fri, 05 Jul 2013 06:18:22 +0400 191 | 192 | qt-webkit-kiosk (1.05.01ubuntu1) unstable; urgency=low 193 | 194 | * Version 1.05.01 195 | 196 | -- Sergey Dryabzhinsky Fri, 05 Jul 2013 00:53:17 +0400 197 | 198 | qt-webkit-kiosk (1.04.01ubuntu1) unstable; urgency=low 199 | 200 | * New hot keys - page reload, developer tools 201 | * Add sound file for windows (wav) 202 | * Add sound event for link click 203 | * Put user scripts into bottom of page 204 | 205 | -- Sergey Dryabzhinsky Fri, 05 Jul 2013 00:09:17 +0400 206 | 207 | qt-webkit-kiosk (1.03.01) unstable; urgency=low 208 | 209 | * Fixed build version number 210 | * Skip empty scripts and styles attach lists 211 | * User config stored in user home directory: ~/.config/QtWebkitKiosk/config.ini 212 | 213 | -- Sergey Dryabzhinsky Thu, 19 Apr 2012 23:03:00 +0400 214 | 215 | qt-webkit-kiosk (1.03.00) unstable; urgency=low 216 | 217 | * Remove debug output in release build 218 | * Attach user scripts and styles when page loaded 219 | 220 | -- Sergey Dryabzhinsky Thu, 19 Apr 2012 00:36:00 +0400 221 | 222 | qt-webkit-kiosk (1.02.01) unstable; urgency=low 223 | 224 | * Fixed startup issue with only one command prompt parameter defined. 225 | 226 | -- Sergey Dryabzhinsky Thu, 18 Apr 2012 22:10:00 +0400 227 | 228 | qt-webkit-kiosk (1.02.00) unstable; urgency=low 229 | 230 | * Fixed startup issue with only one command prompt parameter defined. 231 | * Fixed issue with window size and position when screen resolution changed. 232 | * Fixed build issues on older than Ununtu 11.10 systems. 233 | 234 | -- Sergey Dryabzhinsky Thu, 17 Apr 2012 23:28:00 +0400 235 | 236 | qt-webkit-kiosk (1.01.00) unstable; urgency=low 237 | 238 | * Initial Release. 239 | 240 | -- Sergey Dryabzhinsky Mon, 12 Dec 2011 02:36:28 +0400 241 | -------------------------------------------------------------------------------- /src/webview.cpp: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include "webview.h" 7 | #include 8 | #include "unixsignals.h" 9 | 10 | #ifdef QT5 11 | #include 12 | #ifndef QT_NO_SSL 13 | #include 14 | #endif 15 | #endif 16 | 17 | 18 | WebView::WebView(QWidget* parent): QWebView(parent) 19 | { 20 | player = NULL; 21 | loader = NULL; 22 | loadTimer = NULL; 23 | } 24 | 25 | /** 26 | * Call after setPage 27 | * @brief WebView::initSignals 28 | */ 29 | void WebView::initSignals() 30 | { 31 | #ifndef QT_NO_SSL 32 | connect(page()->networkAccessManager(), 33 | SIGNAL(sslErrors(QNetworkReply*, const QList & )), 34 | this, 35 | SLOT(handleSslErrors(QNetworkReply*, const QList & ))); 36 | #endif 37 | 38 | connect(page(), 39 | SIGNAL(windowCloseRequested()), 40 | this, 41 | SLOT(handleWindowCloseRequested())); 42 | 43 | connect(page(), 44 | SIGNAL(printRequested(QWebFrame*)), 45 | this, 46 | SLOT(handlePrintRequested(QWebFrame*))); 47 | 48 | /*handle network reply*/ 49 | connect(page()->networkAccessManager(), 50 | SIGNAL(finished(QNetworkReply*)), 51 | this, 52 | SLOT(handleNetworkReply(QNetworkReply*))); 53 | 54 | /*handle auth request to be in stable state*/ 55 | connect(page()->networkAccessManager(), 56 | SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), 57 | this, 58 | SLOT(handleAuthReply(QNetworkReply*,QAuthenticator*))); 59 | 60 | /*handle proxy auth request to be in stable state*/ 61 | connect(page()->networkAccessManager(), 62 | SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), 63 | this, 64 | SLOT(handleProxyAuthReply(QNetworkProxy,QAuthenticator*))); 65 | 66 | } 67 | 68 | void WebView::setPage(QwkWebPage *page) 69 | { 70 | QString ua = qwkSettings->getQString("browser/custom_user_agent_header"); 71 | if (ua.length()) { 72 | QwkWebPage::userAgent = ua; 73 | } 74 | 75 | QWebView::setPage(page); 76 | initSignals(); 77 | } 78 | 79 | 80 | void WebView::setSettings(QwkSettings *settings) 81 | { 82 | qwkSettings = settings; 83 | 84 | if (qwkSettings->getBool("printing/enable")) { 85 | if (!qwkSettings->getBool("printing/show-printer-dialog")) { 86 | if (!printer) { 87 | printer = new QPrinter(); 88 | } 89 | printer->setPrinterName(qwkSettings->getQString("printing/printer")); 90 | printer->setPageMargins( 91 | qwkSettings->getReal("printing/page_margin_left"), 92 | qwkSettings->getReal("printing/page_margin_top"), 93 | qwkSettings->getReal("printing/page_margin_right"), 94 | qwkSettings->getReal("printing/page_margin_bottom"), 95 | QPrinter::Millimeter 96 | ); 97 | } 98 | } 99 | 100 | } 101 | 102 | QwkSettings* WebView::getSettings() 103 | { 104 | return qwkSettings; 105 | } 106 | 107 | void WebView::loadHomepage() 108 | { 109 | loadCustomPage(qwkSettings->getQString("browser/homepage")); 110 | } 111 | 112 | void WebView::loadCustomPage(QString uri) 113 | { 114 | QFileInfo finfo = QFileInfo(); 115 | finfo.setFile(uri); 116 | 117 | qDebug() << "Page: check local file = " << 118 | uri << 119 | ", absolute path = " << 120 | finfo.absoluteFilePath() << 121 | ", local uri = " << 122 | QUrl::fromLocalFile( 123 | uri 124 | ).toString(); 125 | 126 | if (finfo.isFile()) { 127 | qDebug() << "Page: Local FILE"; 128 | this->stop(); 129 | this->load(QUrl::fromLocalFile( 130 | finfo.absoluteFilePath() 131 | )); 132 | } else { 133 | qDebug() << "Page: Remote URI"; 134 | this->stop(); 135 | this->load(QUrl(uri)); 136 | } 137 | if (this->getLoadTimer()) { 138 | this->getLoadTimer()->start(qwkSettings->getInt("browser/page_load_timeout")); 139 | } 140 | } 141 | 142 | #ifndef QT_NO_SSL 143 | void WebView::handleSslErrors(QNetworkReply* reply, const QList &errors) 144 | { 145 | qDebug() << QDateTime::currentDateTime().toString() << "handleSslErrors: "; 146 | QString errStr = ""; 147 | foreach (QSslError e, errors) { 148 | qDebug() << "ssl error: " << e.errorString(); 149 | errStr += " " + e.errorString(); 150 | } 151 | 152 | if (qwkSettings->getBool("browser/ignore_ssl_errors")) { 153 | reply->ignoreSslErrors(); 154 | } else { 155 | reply->abort(); 156 | emit qwkNetworkError(reply->error(), QString("Network SSL errors: ") + errStr); 157 | } 158 | } 159 | #endif 160 | 161 | void WebView::handleNetworkReply(QNetworkReply* reply) 162 | { 163 | if ( reply ) { 164 | qDebug() << QDateTime::currentDateTime().toString() << "handleNetworkReply URL:" << reply->request().url().toString(); 165 | if( reply->error()) { 166 | QString errStr = reply->errorString(); 167 | qWarning() << QDateTime::currentDateTime().toString() << "handleNetworkReply ERROR:" << reply->error() << "=" << errStr; 168 | qWarning() << QDateTime::currentDateTime().toString() << "on URL:" << reply->request().url().toString(); 169 | emit qwkNetworkError(reply->error(), reply->errorString()); 170 | } else { 171 | qDebug() << QDateTime::currentDateTime().toString() << "handleNetworkReply OK"; 172 | // emit qwkNetworkReplyUrl(reply->request().url()); 173 | } 174 | } 175 | } 176 | 177 | void WebView::handleAuthReply(QNetworkReply* aReply, QAuthenticator* aAuth) 178 | { 179 | if( aReply && aAuth ) { 180 | qDebug() << QDateTime::currentDateTime().toString() << "handleAuthReply, need authorization, do nothing for now"; 181 | emit qwkNetworkError(QNetworkReply::AuthenticationRequiredError, QString("Web-site need authorization! Nothing to do for now :(")); 182 | } 183 | } 184 | 185 | void WebView::handleProxyAuthReply(const QNetworkProxy &proxy, QAuthenticator* aAuth) 186 | { 187 | Q_UNUSED(proxy); 188 | if( aAuth ) { 189 | qDebug() << QDateTime::currentDateTime().toString() << "handleProxyAuthReply, need proxy authorization, do nothing for now"; 190 | emit qwkNetworkError(QNetworkReply::AuthenticationRequiredError, QString("Proxy need authorization! Check your proxy auth settings!")); 191 | } 192 | } 193 | 194 | void WebView::handleWindowCloseRequested() 195 | { 196 | qDebug() << QDateTime::currentDateTime().toString() << "Handle windowCloseRequested: " << qwkSettings->getQString("browser/show_homepage_on_window_close"); 197 | if (qwkSettings->getBool("browser/show_homepage_on_window_close")) { 198 | qDebug() << "-- load homepage"; 199 | loadHomepage(); 200 | } else { 201 | qDebug() << "-- exit application"; 202 | UnixSignals::signalHandler(SIGINT); 203 | } 204 | } 205 | 206 | void WebView::mousePressEvent(QMouseEvent *event) 207 | { 208 | if (event->button() == Qt::LeftButton) { 209 | qDebug() << QDateTime::currentDateTime().toString() << "Window Clicked!"; 210 | playSound("event-sounds/window-clicked"); 211 | } 212 | QWebView::mousePressEvent(event); 213 | } 214 | 215 | 216 | /** 217 | * @brief WebView::getFakeLoader 218 | * Fake window handler for 'window.open()' and '_blank' target 219 | * Just need to catch url setup 220 | * @return FakeWebView 221 | */ 222 | QWebView *WebView::getFakeLoader() 223 | { 224 | if (!loader) { 225 | qDebug() << QDateTime::currentDateTime().toString() << "New fake webview loader"; 226 | loader = new FakeWebView(this); 227 | loader->hide(); 228 | QWebPage *newWeb = new QWebPage(loader); 229 | loader->setPage(newWeb); 230 | 231 | connect(loader, SIGNAL(urlChanged(const QUrl&)), SLOT(handleFakeviewUrlChanged(const QUrl&))); 232 | connect(loader, SIGNAL(loadFinished(bool)), SLOT(handleFakeviewLoadFinished(bool))); 233 | } 234 | return loader; 235 | } 236 | 237 | void WebView::handleFakeviewUrlChanged(const QUrl &url) 238 | { 239 | qDebug() << QDateTime::currentDateTime().toString() << "WebView::handleFakeviewUrlChanged"; 240 | Q_UNUSED(url); 241 | if (loader) { 242 | loader->stop(); 243 | } 244 | } 245 | 246 | void WebView::handleFakeviewLoadFinished(bool ok) 247 | { 248 | qDebug() << QDateTime::currentDateTime().toString() << "WebView::handleFakeviewLoadFinished: ok=" << (int)ok; 249 | if (loader) { 250 | QUrl url = loader->url(); 251 | if (this->url().toString() != url.toString()) { 252 | qDebug() << "url Changed!" << url.toString(); 253 | this->loadCustomPage(url.toString()); 254 | qDebug() << "-- load url"; 255 | } 256 | } 257 | } 258 | 259 | 260 | QPlayer *WebView::getPlayer() 261 | { 262 | if (qwkSettings->getBool("event-sounds/enable")) { 263 | if (player == NULL) { 264 | player = new QPlayer(); 265 | } 266 | } 267 | return player; 268 | } 269 | 270 | 271 | QTimer *WebView::getLoadTimer() 272 | { 273 | if (qwkSettings->getUInt("browser/page_load_timeout")) { 274 | if (loadTimer == NULL) { 275 | loadTimer = new QTimer(); 276 | connect(loadTimer, SIGNAL(timeout()), SLOT(handleLoadTimerTimeout())); 277 | } 278 | } 279 | return loadTimer; 280 | } 281 | 282 | void WebView::handleLoadTimerTimeout() 283 | { 284 | loadTimer->stop(); 285 | this->stop(); 286 | if (loader) { 287 | loader->stop(); 288 | } 289 | emit qwkNetworkError(QNetworkReply::TimeoutError, QString("Page load timed out! Connection problems?")); 290 | } 291 | 292 | 293 | /** 294 | * @brief WebView::resetLoadTimer 295 | * If page loading, progress event emited 296 | * And we reset timer 297 | * If page not loading - timer will be triggered 298 | */ 299 | void WebView::resetLoadTimer() 300 | { 301 | if (getLoadTimer()) { 302 | getLoadTimer()->stop(); 303 | getLoadTimer()->start(qwkSettings->getInt("browser/page_load_timeout")); 304 | } 305 | } 306 | 307 | 308 | /** 309 | * @brief WebView::stopLoadTimer 310 | * If page loaded, we stop timer 311 | */ 312 | void WebView::stopLoadTimer() 313 | { 314 | if (getLoadTimer()) { 315 | getLoadTimer()->stop(); 316 | } 317 | } 318 | 319 | 320 | void WebView::playSound(QString soundSetting) 321 | { 322 | if (getPlayer()) { 323 | QString sound = qwkSettings->getQString(soundSetting); 324 | QFileInfo finfo = QFileInfo(); 325 | finfo.setFile(sound); 326 | if (finfo.exists()) { 327 | qDebug() << "Play sound: " << sound; 328 | getPlayer()->play(sound); 329 | } else { 330 | qDebug() << "Sound file '" << sound << "' not found!"; 331 | } 332 | } 333 | } 334 | 335 | QWebView *WebView::createWindow(QWebPage::WebWindowType type) 336 | { 337 | if (type != QWebPage::WebBrowserWindow) { 338 | return NULL; 339 | } 340 | qDebug() << QDateTime::currentDateTime().toString() << "Handle createWindow..."; 341 | 342 | return getFakeLoader(); 343 | } 344 | 345 | void WebView::handlePrintRequested(QWebFrame *wf) 346 | { 347 | qDebug() << QDateTime::currentDateTime().toString() << "Handle printRequested..."; 348 | if (qwkSettings->getBool("printing/enable")) { 349 | if (!qwkSettings->getBool("printing/show-printer-dialog")) { 350 | if (printer->printerState() != QPrinter::Error) { 351 | qDebug() << "... got printer, try use it"; 352 | wf->print(printer); 353 | } 354 | } 355 | } 356 | } 357 | 358 | void WebView::scrollDown() 359 | { 360 | QWebFrame* frame = this->page()->mainFrame(); 361 | QPoint point = frame->scrollPosition(); 362 | frame->setScrollPosition(point + QPoint(0, 100)); 363 | } 364 | 365 | void WebView::scrollPageDown() 366 | { 367 | QWebFrame* frame = this->page()->mainFrame(); 368 | QPoint point = frame->scrollPosition(); 369 | frame->setScrollPosition(point + QPoint(0, this->page()->mainFrame()->geometry().height())); 370 | } 371 | 372 | void WebView::scrollEnd() 373 | { 374 | QWebFrame* frame = this->page()->mainFrame(); 375 | frame->setScrollPosition(QPoint(0, frame->contentsSize().height())); 376 | } 377 | 378 | void WebView::scrollUp() 379 | { 380 | QWebFrame* frame = this->page()->mainFrame(); 381 | QPoint point = frame->scrollPosition(); 382 | frame->setScrollPosition(point - QPoint(0, 100)); 383 | } 384 | 385 | void WebView::scrollPageUp() 386 | { 387 | QWebFrame* frame = this->page()->mainFrame(); 388 | QPoint point = frame->scrollPosition(); 389 | frame->setScrollPosition(point - QPoint(0, this->page()->mainFrame()->geometry().height())); 390 | } 391 | 392 | void WebView::scrollHome() 393 | { 394 | QWebFrame* frame = this->page()->mainFrame(); 395 | frame->setScrollPosition(QPoint(0, 0)); 396 | } 397 | -------------------------------------------------------------------------------- /src/qwk_settings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #ifdef QT5 5 | #include 6 | #endif 7 | 8 | QwkSettings::QwkSettings(QObject *parent) : QObject(parent) 9 | { 10 | qsettings = NULL; 11 | } 12 | 13 | /** 14 | * @brief QwkSettings::loadSettings 15 | * @param ini_file 16 | */ 17 | void QwkSettings::loadSettings(QString ini_file) 18 | { 19 | if (qsettings != NULL) { 20 | delete qsettings; 21 | } 22 | if (!ini_file.length()) { 23 | qsettings = new QSettings(QSettings::IniFormat, QSettings::UserScope, "QtWebkitKiosk", "config", this); 24 | } else { 25 | qsettings = new QSettings(ini_file, QSettings::IniFormat, this); 26 | } 27 | qDebug() << "Ini file: " << qsettings->fileName(); 28 | 29 | if (!qsettings->contains("application/organization")) { 30 | qsettings->setValue("application/organization", "Organization" ); 31 | } 32 | if (!qsettings->contains("application/organization-domain")) { 33 | qsettings->setValue("application/organization-domain", "www.example.com" ); 34 | } 35 | if (!qsettings->contains("application/name")) { 36 | qsettings->setValue("application/name", "QtWebkitKiosk" ); 37 | } 38 | if (!qsettings->contains("application/version")) { 39 | qsettings->setValue("application/version", VERSION ); 40 | } 41 | if (!qsettings->contains("application/icon")) { 42 | qsettings->setValue("application/icon", ICON ); 43 | } 44 | 45 | if (!qsettings->contains("proxy/enable")) { 46 | qsettings->setValue("proxy/enable", false); 47 | } 48 | if (!qsettings->contains("proxy/system")) { 49 | qsettings->setValue("proxy/system", true); 50 | } 51 | if (!qsettings->contains("proxy/host")) { 52 | qsettings->setValue("proxy/host", "proxy.example.com"); 53 | } 54 | if (!qsettings->contains("proxy/port")) { 55 | qsettings->setValue("proxy/port", 3128); 56 | } 57 | if (!qsettings->contains("proxy/auth")) { 58 | qsettings->setValue("proxy/auth", false); 59 | } 60 | if (!qsettings->contains("proxy/username")) { 61 | qsettings->setValue("proxy/username", "username"); 62 | } 63 | if (!qsettings->contains("proxy/password")) { 64 | qsettings->setValue("proxy/password", "password"); 65 | } 66 | 67 | if (!qsettings->contains("view/fullscreen")) { 68 | qsettings->setValue("view/fullscreen", true); 69 | } 70 | if (!qsettings->contains("view/maximized")) { 71 | qsettings->setValue("view/maximized", false); 72 | } 73 | if (!qsettings->contains("view/fixed-size")) { 74 | qsettings->setValue("view/fixed-size", false); 75 | } 76 | if (!qsettings->contains("view/fixed-width")) { 77 | qsettings->setValue("view/fixed-width", 800); 78 | } 79 | if (!qsettings->contains("view/fixed-height")) { 80 | qsettings->setValue("view/fixed-height", 600); 81 | } 82 | if (!qsettings->contains("view/minimal-width")) { 83 | qsettings->setValue("view/minimal-width", 320); 84 | } 85 | if (!qsettings->contains("view/minimal-height")) { 86 | qsettings->setValue("view/minimal-height", 200); 87 | } 88 | if (!qsettings->contains("view/fixed-centered")) { 89 | qsettings->setValue("view/fixed-centered", true); 90 | } 91 | if (!qsettings->contains("view/fixed-x")) { 92 | qsettings->setValue("view/fixed-x", 0); 93 | } 94 | if (!qsettings->contains("view/fixed-y")) { 95 | qsettings->setValue("view/fixed-y", 0); 96 | } 97 | 98 | if (!qsettings->contains("view/startup_resize_delayed")) { 99 | qsettings->setValue("view/startup_resize_delayed", true); 100 | } 101 | if (!qsettings->contains("view/startup_resize_delay")) { 102 | qsettings->setValue("view/startup_resize_delay", 200); 103 | } 104 | 105 | if (!qsettings->contains("view/hide_scrollbars")) { 106 | qsettings->setValue("view/hide_scrollbars", true); 107 | } 108 | 109 | if (!qsettings->contains("view/stay_on_top")) { 110 | qsettings->setValue("view/stay_on_top", false); 111 | } 112 | 113 | if (!qsettings->contains("view/disable_selection")) { 114 | qsettings->setValue("view/disable_selection", true); 115 | } 116 | 117 | if (!qsettings->contains("view/show_load_progress")) { 118 | qsettings->setValue("view/show_load_progress", true); 119 | } 120 | 121 | if (!qsettings->contains("view/page_scale")) { 122 | qsettings->setValue("view/page_scale", 1.0); 123 | } 124 | 125 | 126 | if (!qsettings->contains("browser/homepage")) { 127 | qsettings->setValue("browser/homepage", RESOURCES"default.html"); 128 | } 129 | if (!qsettings->contains("browser/custom_user_agent_header")) { 130 | qsettings->setValue("browser/custom_user_agent_header",""); 131 | } 132 | if (!qsettings->contains("browser/javascript")) { 133 | qsettings->setValue("browser/javascript", true); 134 | } 135 | if (!qsettings->contains("browser/javascript_can_open_windows")) { 136 | qsettings->setValue("browser/javascript_can_open_windows", false); 137 | } 138 | if (!qsettings->contains("browser/javascript_can_close_windows")) { 139 | qsettings->setValue("browser/javascript_can_close_windows", false); 140 | } 141 | if (!qsettings->contains("browser/webgl")) { 142 | qsettings->setValue("browser/webgl", false); 143 | } 144 | if (!qsettings->contains("browser/java")) { 145 | qsettings->setValue("browser/java", false); 146 | } 147 | if (!qsettings->contains("browser/plugins")) { 148 | qsettings->setValue("browser/plugins", true); 149 | } 150 | // Don't output javascript console messages 151 | if (!qsettings->contains("browser/show_js_console_messages")) { 152 | qsettings->setValue("browser/show_js_console_messages", false); 153 | } 154 | // Don't break on SSL errors 155 | if (!qsettings->contains("browser/ignore_ssl_errors")) { 156 | qsettings->setValue("browser/ignore_ssl_errors", true); 157 | } 158 | if (!qsettings->contains("browser/cookiejar")) { 159 | qsettings->setValue("browser/cookiejar", false); 160 | } 161 | // Show default homepage if window closed by javascript 162 | if (!qsettings->contains("browser/show_homepage_on_window_close")) { 163 | qsettings->setValue("browser/show_homepage_on_window_close", true); 164 | } 165 | 166 | if (!qsettings->contains("browser/startup_load_delayed")) { 167 | qsettings->setValue("browser/startup_load_delayed", true); 168 | } 169 | if (!qsettings->contains("browser/startup_load_delay")) { 170 | qsettings->setValue("browser/startup_load_delay", 100); 171 | } 172 | 173 | if (!qsettings->contains("browser/disable_hotkeys")) { 174 | qsettings->setValue("browser/disable_hotkeys", false); 175 | } 176 | 177 | if (!qsettings->contains("browser/page_load_timeout")) { 178 | qsettings->setValue("browser/page_load_timeout", 15000); 179 | } 180 | if (!qsettings->contains("browser/network_error_reload_delay")) { 181 | qsettings->setValue("browser/network_error_reload_delay", 15000); 182 | } 183 | 184 | if (!qsettings->contains("browser/show_error_messages")) { 185 | qsettings->setValue("browser/show_error_messages", false); 186 | } 187 | 188 | if (!qsettings->contains("browser/interrupt_javascript")) { 189 | qsettings->setValue("browser/interrupt_javascript", true); 190 | } 191 | if (!qsettings->contains("browser/interrupt_javascript_interval")) { 192 | qsettings->setValue("browser/interrupt_javascript_interval", 30); 193 | } 194 | 195 | 196 | if (!qsettings->contains("signals/enable")) { 197 | qsettings->setValue("signals/enable", true); 198 | } 199 | if (!qsettings->contains("signals/SIGUSR1")) { 200 | qsettings->setValue("signals/SIGUSR1", ""); 201 | } 202 | if (!qsettings->contains("signals/SIGUSR2")) { 203 | qsettings->setValue("signals/SIGUSR2", ""); 204 | } 205 | 206 | 207 | if (!qsettings->contains("inspector/enable")) { 208 | qsettings->setValue("inspector/enable", false); 209 | } 210 | if (!qsettings->contains("inspector/visible")) { 211 | qsettings->setValue("inspector/visible", false); 212 | } 213 | 214 | 215 | if (!qsettings->contains("event-sounds/enable")) { 216 | qsettings->setValue("event-sounds/enable", false); 217 | } 218 | if (!qsettings->contains("event-sounds/window-clicked")) { 219 | qsettings->setValue("event-sounds/window-clicked", RESOURCES"window-clicked.ogg"); 220 | } 221 | if (!qsettings->contains("event-sounds/link-clicked")) { 222 | qsettings->setValue("event-sounds/link-clicked", RESOURCES"window-clicked.ogg"); 223 | } 224 | 225 | if (!qsettings->contains("cache/enable")) { 226 | qsettings->setValue("cache/enable", false); 227 | } 228 | if (!qsettings->contains("cache/location")) { 229 | #ifdef QT5 230 | QString location = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); 231 | #else 232 | QString location = QDesktopServices::storageLocation(QDesktopServices::CacheLocation); 233 | #endif 234 | QDir d = QDir(location); 235 | location += d.separator(); 236 | location += qsettings->value("application/name").toString(); 237 | d.setPath(location); 238 | qsettings->setValue("cache/location", d.absolutePath()); 239 | } 240 | if (!qsettings->contains("cache/size")) { 241 | qsettings->setValue("cache/size", 100*1000*1000); 242 | } 243 | if (!qsettings->contains("cache/clear-on-start")) { 244 | qsettings->setValue("cache/clear-on-start", false); 245 | } 246 | if (!qsettings->contains("cache/clear-on-exit")) { 247 | qsettings->setValue("cache/clear-on-exit", false); 248 | } 249 | 250 | if (!qsettings->contains("printing/enable")) { 251 | qsettings->setValue("printing/enable", false); 252 | } 253 | if (!qsettings->contains("printing/show-printer-dialog")) { 254 | qsettings->setValue("printing/show-printer-dialog", false); 255 | } 256 | if (!qsettings->contains("printing/printer")) { 257 | qsettings->setValue("printing/printer", "default"); 258 | } 259 | if (!qsettings->contains("printing/page_margin_left")) { 260 | qsettings->setValue("printing/page_margin_left", 5); 261 | } 262 | if (!qsettings->contains("printing/page_margin_top")) { 263 | qsettings->setValue("printing/page_margin_top", 5); 264 | } 265 | if (!qsettings->contains("printing/page_margin_right")) { 266 | qsettings->setValue("printing/page_margin_right", 5); 267 | } 268 | if (!qsettings->contains("printing/page_margin_bottom")) { 269 | qsettings->setValue("printing/page_margin_bottom", 5); 270 | } 271 | 272 | if (!qsettings->contains("attach/javascripts")) { 273 | qsettings->setValue("attach/javascripts", ""); 274 | } 275 | if (!qsettings->contains("attach/styles")) { 276 | qsettings->setValue("attach/styles", ""); 277 | } 278 | if (!qsettings->contains("view/hide_mouse_cursor")) { 279 | qsettings->setValue("view/hide_mouse_cursor", false); 280 | } 281 | 282 | if (!qsettings->contains("localstorage/enable")) { 283 | qsettings->setValue("localstorage/enable", false); 284 | } 285 | 286 | if (!qsettings->contains("security/local_content_can_access_remote_urls")) { 287 | qsettings->setValue("security/local_content_can_access_remote_urls", false); 288 | } 289 | 290 | if (qsettings->fileName().length()) { 291 | qsettings->sync(); 292 | } 293 | } 294 | 295 | 296 | bool QwkSettings::getBool(QString key, bool defval) 297 | { 298 | if (qsettings) { 299 | if (qsettings->contains(key)) { 300 | return qsettings->value(key).toBool(); 301 | } 302 | } 303 | return defval; 304 | } 305 | 306 | int QwkSettings::getInt(QString key, int defval) 307 | { 308 | if (qsettings) { 309 | if (qsettings->contains(key)) { 310 | return qsettings->value(key).toInt(); 311 | } 312 | } 313 | return defval; 314 | } 315 | 316 | uint QwkSettings::getUInt(QString key, uint defval) 317 | { 318 | if (qsettings) { 319 | if (qsettings->contains(key)) { 320 | return qsettings->value(key).toUInt(); 321 | } 322 | } 323 | return defval; 324 | } 325 | 326 | qreal QwkSettings::getReal(QString key, qreal defval) 327 | { 328 | if (qsettings) { 329 | if (qsettings->contains(key)) { 330 | return qsettings->value(key).toReal(); 331 | } 332 | } 333 | return defval; 334 | } 335 | 336 | QString QwkSettings::getQString(QString key, QString defval) 337 | { 338 | if (qsettings) { 339 | if (qsettings->contains(key)) { 340 | return qsettings->value(key).toString(); 341 | } 342 | } 343 | return defval; 344 | } 345 | 346 | QStringList QwkSettings::getQStringList(QString key, QStringList defval) 347 | { 348 | if (qsettings) { 349 | if (qsettings->contains(key)) { 350 | return qsettings->value(key).toStringList(); 351 | } 352 | } 353 | return defval; 354 | } 355 | 356 | void QwkSettings::setValue(QString key, QVariant value) 357 | { 358 | if (qsettings) { 359 | qsettings->setValue(key, value); 360 | } 361 | return; 362 | } 363 | -------------------------------------------------------------------------------- /doc/lgpl.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | GNU Lesser General Public License v3.0 - GNU Project - Free Software Foundation (FSF) 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 | 64 | 65 | 90 | 91 | 92 | 93 |
94 | 95 | 96 | 97 |
98 | 104 |
105 | 106 | 107 |

GNU Lesser General Public License

108 | 109 | 110 | 111 | 133 | 134 |

This license is a set of additional permissions added to version 3 of the GNU General Public 136 | License. For more information about how to release your own software 137 | under this license, please see our page 138 | of instructions.

139 | 140 |
141 | 142 | 145 |
146 |

GNU LESSER GENERAL PUBLIC LICENSE

147 |

Version 3, 29 June 2007

148 | 149 |

Copyright © 2007 Free Software Foundation, Inc. 150 | <http://fsf.org/>

151 | Everyone is permitted to copy and distribute verbatim copies 152 | of this license document, but changing it is not allowed.

153 | 154 |

This version of the GNU Lesser General Public License incorporates 155 | the terms and conditions of version 3 of the GNU General Public 156 | License, supplemented by the additional permissions listed below.

157 | 158 |

0. Additional Definitions.

159 | 160 |

As used herein, “this License” refers to version 3 of the GNU Lesser 161 | General Public License, and the “GNU GPL” refers to version 3 of the GNU 162 | General Public License.

163 | 164 |

“The Library” refers to a covered work governed by this License, 165 | other than an Application or a Combined Work as defined below.

166 | 167 |

An “Application” is any work that makes use of an interface provided 168 | by the Library, but which is not otherwise based on the Library. 169 | Defining a subclass of a class defined by the Library is deemed a mode 170 | of using an interface provided by the Library.

171 | 172 |

A “Combined Work” is a work produced by combining or linking an 173 | Application with the Library. The particular version of the Library 174 | with which the Combined Work was made is also called the “Linked 175 | Version”.

176 | 177 |

The “Minimal Corresponding Source” for a Combined Work means the 178 | Corresponding Source for the Combined Work, excluding any source code 179 | for portions of the Combined Work that, considered in isolation, are 180 | based on the Application, and not on the Linked Version.

181 | 182 |

The “Corresponding Application Code” for a Combined Work means the 183 | object code and/or source code for the Application, including any data 184 | and utility programs needed for reproducing the Combined Work from the 185 | Application, but excluding the System Libraries of the Combined Work.

186 | 187 |

1. Exception to Section 3 of the GNU GPL.

188 | 189 |

You may convey a covered work under sections 3 and 4 of this License 190 | without being bound by section 3 of the GNU GPL.

191 | 192 |

2. Conveying Modified Versions.

193 | 194 |

If you modify a copy of the Library, and, in your modifications, a 195 | facility refers to a function or data to be supplied by an Application 196 | that uses the facility (other than as an argument passed when the 197 | facility is invoked), then you may convey a copy of the modified 198 | version:

199 | 200 |
    201 |
  • a) under this License, provided that you make a good faith effort to 202 | ensure that, in the event an Application does not supply the 203 | function or data, the facility still operates, and performs 204 | whatever part of its purpose remains meaningful, or
  • 205 | 206 |
  • b) under the GNU GPL, with none of the additional permissions of 207 | this License applicable to that copy.
  • 208 |
209 | 210 |

3. Object Code Incorporating Material from Library Header Files.

211 | 212 |

The object code form of an Application may incorporate material from 213 | a header file that is part of the Library. You may convey such object 214 | code under terms of your choice, provided that, if the incorporated 215 | material is not limited to numerical parameters, data structure 216 | layouts and accessors, or small macros, inline functions and templates 217 | (ten or fewer lines in length), you do both of the following:

218 | 219 |
    220 |
  • a) Give prominent notice with each copy of the object code that the 221 | Library is used in it and that the Library and its use are 222 | covered by this License.
  • 223 | 224 |
  • b) Accompany the object code with a copy of the GNU GPL and this license 225 | document.
  • 226 |
227 | 228 |

4. Combined Works.

229 | 230 |

You may convey a Combined Work under terms of your choice that, 231 | taken together, effectively do not restrict modification of the 232 | portions of the Library contained in the Combined Work and reverse 233 | engineering for debugging such modifications, if you also do each of 234 | the following:

235 | 236 |
    237 |
  • a) Give prominent notice with each copy of the Combined Work that 238 | the Library is used in it and that the Library and its use are 239 | covered by this License.
  • 240 | 241 |
  • b) Accompany the Combined Work with a copy of the GNU GPL and this license 242 | document.
  • 243 | 244 |
  • c) For a Combined Work that displays copyright notices during 245 | execution, include the copyright notice for the Library among 246 | these notices, as well as a reference directing the user to the 247 | copies of the GNU GPL and this license document.
  • 248 | 249 |
  • d) Do one of the following: 250 | 251 |
      252 |
    • 0) Convey the Minimal Corresponding Source under the terms of this 253 | License, and the Corresponding Application Code in a form 254 | suitable for, and under terms that permit, the user to 255 | recombine or relink the Application with a modified version of 256 | the Linked Version to produce a modified Combined Work, in the 257 | manner specified by section 6 of the GNU GPL for conveying 258 | Corresponding Source.
    • 259 | 260 |
    • 1) Use a suitable shared library mechanism for linking with the 261 | Library. A suitable mechanism is one that (a) uses at run time 262 | a copy of the Library already present on the user's computer 263 | system, and (b) will operate properly with a modified version 264 | of the Library that is interface-compatible with the Linked 265 | Version.
    • 266 |
  • 267 | 268 |
  • e) Provide Installation Information, but only if you would otherwise 269 | be required to provide such information under section 6 of the 270 | GNU GPL, and only to the extent that such information is 271 | necessary to install and execute a modified version of the 272 | Combined Work produced by recombining or relinking the 273 | Application with a modified version of the Linked Version. (If 274 | you use option 4d0, the Installation Information must accompany 275 | the Minimal Corresponding Source and Corresponding Application 276 | Code. If you use option 4d1, you must provide the Installation 277 | Information in the manner specified by section 6 of the GNU GPL 278 | for conveying Corresponding Source.)
  • 279 |
280 | 281 |

5. Combined Libraries.

282 | 283 |

You may place library facilities that are a work based on the 284 | Library side by side in a single library together with other library 285 | facilities that are not Applications and are not covered by this 286 | License, and convey such a combined library under terms of your 287 | choice, if you do both of the following:

288 | 289 |
    290 |
  • a) Accompany the combined library with a copy of the same work based 291 | on the Library, uncombined with any other library facilities, 292 | conveyed under the terms of this License.
  • 293 | 294 |
  • b) Give prominent notice with the combined library that part of it 295 | is a work based on the Library, and explaining where to find the 296 | accompanying uncombined form of the same work.
  • 297 |
298 | 299 |

6. Revised Versions of the GNU Lesser General Public License.

300 | 301 |

The Free Software Foundation may publish revised and/or new versions 302 | of the GNU Lesser General Public License from time to time. Such new 303 | versions will be similar in spirit to the present version, but may 304 | differ in detail to address new problems or concerns.

305 | 306 |

Each version is given a distinguishing version number. If the 307 | Library as you received it specifies that a certain numbered version 308 | of the GNU Lesser General Public License “or any later version” 309 | applies to it, you have the option of following the terms and 310 | conditions either of that published version or of any later version 311 | published by the Free Software Foundation. If the Library as you 312 | received it does not specify a version number of the GNU Lesser 313 | General Public License, you may choose any version of the GNU Lesser 314 | General Public License ever published by the Free Software Foundation.

315 | 316 |

If the Library as you received it specifies that a proxy can decide 317 | whether future versions of the GNU Lesser General Public License shall 318 | apply, that proxy's public statement of acceptance of any version is 319 | permanent authorization for you to choose that version for the 320 | Library.

321 | 322 |
323 |
324 | 325 | 326 |
327 | 328 | 339 | 340 |
341 | 342 |

The Free Software 343 | Foundation is the principal organizational sponsor of the GNU Operating System. Our 345 | mission is to preserve, protect and promote the freedom to use, study, 346 | copy, modify, and redistribute computer software, and to defend the 347 | rights of Free Software users. Support GNU and the FSF by buying manuals and gear, joining the FSF as an associate 350 | member or by making a 351 | donation, either directly to the FSF 352 | or via Flattr.

353 | 354 |

back to top

355 | 356 | 357 | 358 | 359 |
360 | 361 | 362 |
363 | 364 | 365 | 366 | 367 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 |
427 | 428 | 429 | -------------------------------------------------------------------------------- /src/anyoption.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * AnyOption 1.3 3 | * 4 | * kishan at hackorama dot com www.hackorama.com JULY 2001 5 | * 6 | * + Acts as a common facade class for reading 7 | * commandline options as well as options from 8 | * an optionfile with delimited type value pairs 9 | * 10 | * + Handles the POSIX style single character options ( -w ) 11 | * as well as the newer GNU long options ( --width ) 12 | * 13 | * + The option file assumes the traditional format of 14 | * first character based comment lines and type value 15 | * pairs with a delimiter , and flags which are not pairs 16 | * 17 | * # this is a coment 18 | * # next line is an option value pair 19 | * width : 100 20 | * # next line is a flag 21 | * noimages 22 | * 23 | * + Supports printing out Help and Usage 24 | * 25 | * + Why not just use getopt() ? 26 | * 27 | * getopt() Its a POSIX standard not part of ANSI-C. 28 | * So it may not be available on platforms like Windows. 29 | * 30 | * + Why it is so long ? 31 | * 32 | * The actual code which does command line parsing 33 | * and option file parsing are done in few methods. 34 | * Most of the extra code are for providing a flexible 35 | * common public interface to both a resourcefile and 36 | * and command line supporting POSIX style and 37 | * GNU long option as well as mixing of both. 38 | * 39 | * + Please see "anyoption.h" for public method descriptions 40 | * 41 | */ 42 | 43 | /* Updated Auguest 2004 44 | * Fix from Michael D Peters (mpeters at sandia.gov) 45 | * to remove static local variables, allowing multiple instantiations 46 | * of the reader (for using multiple configuration files). There is 47 | * an error in the destructor when using multiple instances, so you 48 | * cannot delete your objects (it will crash), but not calling the 49 | * destructor only introduces a small memory leak, so I 50 | * have not bothered tracking it down. 51 | * 52 | * Also updated to use modern C++ style headers, rather than 53 | * depricated iostream.h (it was causing my compiler problems) 54 | */ 55 | 56 | /* 57 | * Updated September 2006 58 | * Fix from Boyan Asenov for a bug in mixing up option indexes 59 | * leading to exception when mixing different options types 60 | */ 61 | 62 | #include "anyoption.h" 63 | 64 | AnyOption::AnyOption() 65 | { 66 | init(); 67 | } 68 | 69 | AnyOption::AnyOption(int maxopt) 70 | { 71 | init( maxopt , maxopt ); 72 | } 73 | 74 | AnyOption::AnyOption(int maxopt, int maxcharopt) 75 | { 76 | init( maxopt , maxcharopt ); 77 | } 78 | 79 | AnyOption::~AnyOption() 80 | { 81 | if( mem_allocated ) 82 | cleanup(); 83 | } 84 | 85 | void 86 | AnyOption::init() 87 | { 88 | init( DEFAULT_MAXOPTS , DEFAULT_MAXOPTS ); 89 | } 90 | 91 | void 92 | AnyOption::init(int maxopt, int maxcharopt ) 93 | { 94 | 95 | max_options = maxopt; 96 | max_char_options = maxcharopt; 97 | max_usage_lines = DEFAULT_MAXUSAGE; 98 | usage_lines = 0 ; 99 | argc = 0; 100 | argv = NULL; 101 | posix_style = true; 102 | verbose = false; 103 | filename = NULL; 104 | appname = NULL; 105 | option_counter = 0; 106 | optchar_counter = 0; 107 | new_argv = NULL; 108 | new_argc = 0 ; 109 | max_legal_args = 0 ; 110 | command_set = false; 111 | file_set = false; 112 | values = NULL; 113 | g_value_counter = 0; 114 | mem_allocated = false; 115 | command_set = false; 116 | file_set = false; 117 | opt_prefix_char = '-'; 118 | file_delimiter_char = ':'; 119 | file_comment_char = '#'; 120 | equalsign = '='; 121 | comment = '#' ; 122 | delimiter = ':' ; 123 | endofline = '\n'; 124 | whitespace = ' ' ; 125 | nullterminate = '\0'; 126 | set = false; 127 | once = true; 128 | hasoptions = false; 129 | autousage = false; 130 | 131 | strcpy( long_opt_prefix , "--" ); 132 | 133 | if( alloc() == false ){ 134 | cout << endl << "OPTIONS ERROR : Failed allocating memory" ; 135 | cout << endl ; 136 | cout << "Exiting." << endl ; 137 | exit (0); 138 | } 139 | } 140 | 141 | bool 142 | AnyOption::alloc() 143 | { 144 | int i = 0 ; 145 | int size = 0 ; 146 | 147 | if( mem_allocated ) 148 | return true; 149 | 150 | size = (max_options+1) * sizeof(const char*); 151 | options = (const char**)malloc( size ); 152 | optiontype = (int*) malloc( (max_options+1)*sizeof(int) ); 153 | optionindex = (int*) malloc( (max_options+1)*sizeof(int) ); 154 | if( options == NULL || optiontype == NULL || optionindex == NULL ) 155 | return false; 156 | else 157 | mem_allocated = true; 158 | for( i = 0 ; i < max_options ; i++ ){ 159 | options[i] = NULL; 160 | optiontype[i] = 0 ; 161 | optionindex[i] = -1 ; 162 | } 163 | optionchars = (char*) malloc( (max_char_options+1)*sizeof(char) ); 164 | optchartype = (int*) malloc( (max_char_options+1)*sizeof(int) ); 165 | optcharindex = (int*) malloc( (max_char_options+1)*sizeof(int) ); 166 | if( optionchars == NULL || 167 | optchartype == NULL || 168 | optcharindex == NULL ) 169 | { 170 | mem_allocated = false; 171 | return false; 172 | } 173 | for( i = 0 ; i < max_char_options ; i++ ){ 174 | optionchars[i] = '0'; 175 | optchartype[i] = 0 ; 176 | optcharindex[i] = -1 ; 177 | } 178 | 179 | size = (max_usage_lines+1) * sizeof(const char*) ; 180 | usage = (const char**) malloc( size ); 181 | 182 | if( usage == NULL ){ 183 | mem_allocated = false; 184 | return false; 185 | } 186 | for( i = 0 ; i < max_usage_lines ; i++ ) 187 | usage[i] = NULL; 188 | 189 | return true; 190 | } 191 | 192 | bool 193 | AnyOption::doubleOptStorage() 194 | { 195 | options = (const char**)realloc( options, 196 | ((2*max_options)+1) * sizeof( const char*) ); 197 | optiontype = (int*) realloc( optiontype , 198 | ((2 * max_options)+1)* sizeof(int) ); 199 | optionindex = (int*) realloc( optionindex, 200 | ((2 * max_options)+1) * sizeof(int) ); 201 | if( options == NULL || optiontype == NULL || optionindex == NULL ) 202 | return false; 203 | /* init new storage */ 204 | for( int i = max_options ; i < 2*max_options ; i++ ){ 205 | options[i] = NULL; 206 | optiontype[i] = 0 ; 207 | optionindex[i] = -1 ; 208 | } 209 | max_options = 2 * max_options ; 210 | return true; 211 | } 212 | 213 | bool 214 | AnyOption::doubleCharStorage() 215 | { 216 | optionchars = (char*) realloc( optionchars, 217 | ((2*max_char_options)+1)*sizeof(char) ); 218 | optchartype = (int*) realloc( optchartype, 219 | ((2*max_char_options)+1)*sizeof(int) ); 220 | optcharindex = (int*) realloc( optcharindex, 221 | ((2*max_char_options)+1)*sizeof(int) ); 222 | if( optionchars == NULL || 223 | optchartype == NULL || 224 | optcharindex == NULL ) 225 | return false; 226 | /* init new storage */ 227 | for( int i = max_char_options ; i < 2*max_char_options ; i++ ){ 228 | optionchars[i] = '0'; 229 | optchartype[i] = 0 ; 230 | optcharindex[i] = -1 ; 231 | } 232 | max_char_options = 2 * max_char_options; 233 | return true; 234 | } 235 | 236 | bool 237 | AnyOption::doubleUsageStorage() 238 | { 239 | usage = (const char**)realloc( usage, 240 | ((2*max_usage_lines)+1) * sizeof( const char*) ); 241 | if ( usage == NULL ) 242 | return false; 243 | for( int i = max_usage_lines ; i < 2*max_usage_lines ; i++ ) 244 | usage[i] = NULL; 245 | max_usage_lines = 2 * max_usage_lines ; 246 | return true; 247 | 248 | } 249 | 250 | 251 | void 252 | AnyOption::cleanup() 253 | { 254 | free (options); 255 | free (optiontype); 256 | free (optionindex); 257 | free (optionchars); 258 | free (optchartype); 259 | free (optcharindex); 260 | free (usage); 261 | if( values != NULL ) 262 | free (values); 263 | if( new_argv != NULL ) 264 | free (new_argv); 265 | } 266 | 267 | void 268 | AnyOption::setCommandPrefixChar( char _prefix ) 269 | { 270 | opt_prefix_char = _prefix; 271 | } 272 | 273 | void 274 | AnyOption::setCommandLongPrefix( char *_prefix ) 275 | { 276 | if( strlen( _prefix ) > MAX_LONG_PREFIX_LENGTH ){ 277 | *( _prefix + MAX_LONG_PREFIX_LENGTH ) = '\0'; 278 | } 279 | 280 | strcpy (long_opt_prefix, _prefix); 281 | } 282 | 283 | void 284 | AnyOption::setFileCommentChar( char _comment ) 285 | { 286 | file_delimiter_char = _comment; 287 | } 288 | 289 | 290 | void 291 | AnyOption::setFileDelimiterChar( char _delimiter ) 292 | { 293 | file_comment_char = _delimiter ; 294 | } 295 | 296 | bool 297 | AnyOption::CommandSet() 298 | { 299 | return( command_set ); 300 | } 301 | 302 | bool 303 | AnyOption::FileSet() 304 | { 305 | return( file_set ); 306 | } 307 | 308 | void 309 | AnyOption::noPOSIX() 310 | { 311 | posix_style = false; 312 | } 313 | 314 | bool 315 | AnyOption::POSIX() 316 | { 317 | return posix_style; 318 | } 319 | 320 | 321 | void 322 | AnyOption::setVerbose() 323 | { 324 | verbose = true ; 325 | } 326 | 327 | void 328 | AnyOption::printVerbose() 329 | { 330 | if( verbose ) 331 | cout << endl ; 332 | } 333 | void 334 | AnyOption::printVerbose( const char *msg ) 335 | { 336 | if( verbose ) 337 | cout << msg ; 338 | } 339 | 340 | void 341 | AnyOption::printVerbose( char *msg ) 342 | { 343 | if( verbose ) 344 | cout << msg ; 345 | } 346 | 347 | void 348 | AnyOption::printVerbose( char ch ) 349 | { 350 | if( verbose ) 351 | cout << ch ; 352 | } 353 | 354 | bool 355 | AnyOption::hasOptions() 356 | { 357 | return hasoptions; 358 | } 359 | 360 | void 361 | AnyOption::autoUsagePrint(bool _autousage) 362 | { 363 | autousage = _autousage; 364 | } 365 | 366 | void 367 | AnyOption::useCommandArgs( int _argc, char **_argv ) 368 | { 369 | argc = _argc; 370 | argv = _argv; 371 | command_set = true; 372 | appname = argv[0]; 373 | if(argc > 1) hasoptions = true; 374 | } 375 | 376 | void 377 | AnyOption::useCommandArgs( int _argc, QStringList _argv) 378 | { 379 | // Copy input to output 380 | argv = new char*[_argv.size() + 1]; 381 | for (int i = 0; i < _argv.size(); i++) { 382 | argv[i] = new char[strlen(_argv.at(i).toStdString().c_str())+1]; 383 | memcpy(argv[i], _argv.at(i).toStdString().c_str(), strlen(_argv.at(i).toStdString().c_str())+1); 384 | } 385 | argv[_argv.size()] = (char*)NULL; 386 | 387 | argc = _argc; 388 | command_set = true; 389 | appname = argv[0]; 390 | if(argc > 1) hasoptions = true; 391 | } 392 | 393 | void 394 | AnyOption::useFileName( const char *_filename ) 395 | { 396 | filename = _filename; 397 | file_set = true; 398 | } 399 | 400 | /* 401 | * set methods for options 402 | */ 403 | 404 | void 405 | AnyOption::setCommandOption( const char *opt ) 406 | { 407 | addOption( opt , COMMAND_OPT ); 408 | g_value_counter++; 409 | } 410 | 411 | void 412 | AnyOption::setCommandOption( char opt ) 413 | { 414 | addOption( opt , COMMAND_OPT ); 415 | g_value_counter++; 416 | } 417 | 418 | void 419 | AnyOption::setCommandOption( const char *opt , char optchar ) 420 | { 421 | addOption( opt , COMMAND_OPT ); 422 | addOption( optchar , COMMAND_OPT ); 423 | g_value_counter++; 424 | } 425 | 426 | void 427 | AnyOption::setCommandFlag( const char *opt ) 428 | { 429 | addOption( opt , COMMAND_FLAG ); 430 | g_value_counter++; 431 | } 432 | 433 | void 434 | AnyOption::setCommandFlag( char opt ) 435 | { 436 | addOption( opt , COMMAND_FLAG ); 437 | g_value_counter++; 438 | } 439 | 440 | void 441 | AnyOption::setCommandFlag( const char *opt , char optchar ) 442 | { 443 | addOption( opt , COMMAND_FLAG ); 444 | addOption( optchar , COMMAND_FLAG ); 445 | g_value_counter++; 446 | } 447 | 448 | void 449 | AnyOption::setFileOption( const char *opt ) 450 | { 451 | addOption( opt , FILE_OPT ); 452 | g_value_counter++; 453 | } 454 | 455 | void 456 | AnyOption::setFileOption( char opt ) 457 | { 458 | addOption( opt , FILE_OPT ); 459 | g_value_counter++; 460 | } 461 | 462 | void 463 | AnyOption::setFileOption( const char *opt , char optchar ) 464 | { 465 | addOption( opt , FILE_OPT ); 466 | addOption( optchar, FILE_OPT ); 467 | g_value_counter++; 468 | } 469 | 470 | void 471 | AnyOption::setFileFlag( const char *opt ) 472 | { 473 | addOption( opt , FILE_FLAG ); 474 | g_value_counter++; 475 | } 476 | 477 | void 478 | AnyOption::setFileFlag( char opt ) 479 | { 480 | addOption( opt , FILE_FLAG ); 481 | g_value_counter++; 482 | } 483 | 484 | void 485 | AnyOption::setFileFlag( const char *opt , char optchar ) 486 | { 487 | addOption( opt , FILE_FLAG ); 488 | addOption( optchar , FILE_FLAG ); 489 | g_value_counter++; 490 | } 491 | 492 | void 493 | AnyOption::setOption( const char *opt ) 494 | { 495 | addOption( opt , COMMON_OPT ); 496 | g_value_counter++; 497 | } 498 | 499 | void 500 | AnyOption::setOption( char opt ) 501 | { 502 | addOption( opt , COMMON_OPT ); 503 | g_value_counter++; 504 | } 505 | 506 | void 507 | AnyOption::setOption( const char *opt , char optchar ) 508 | { 509 | addOption( opt , COMMON_OPT ); 510 | addOption( optchar , COMMON_OPT ); 511 | g_value_counter++; 512 | } 513 | 514 | void 515 | AnyOption::setFlag( const char *opt ) 516 | { 517 | addOption( opt , COMMON_FLAG ); 518 | g_value_counter++; 519 | } 520 | 521 | void 522 | AnyOption::setFlag( const char opt ) 523 | { 524 | addOption( opt , COMMON_FLAG ); 525 | g_value_counter++; 526 | } 527 | 528 | void 529 | AnyOption::setFlag( const char *opt , char optchar ) 530 | { 531 | addOption( opt , COMMON_FLAG ); 532 | addOption( optchar , COMMON_FLAG ); 533 | g_value_counter++; 534 | } 535 | 536 | void 537 | AnyOption::addOption( const char *opt, int type ) 538 | { 539 | if( option_counter >= max_options ){ 540 | if( doubleOptStorage() == false ){ 541 | addOptionError( opt ); 542 | return; 543 | } 544 | } 545 | options[ option_counter ] = opt ; 546 | optiontype[ option_counter ] = type ; 547 | optionindex[ option_counter ] = g_value_counter; 548 | option_counter++; 549 | } 550 | 551 | void 552 | AnyOption::addOption( char opt, int type ) 553 | { 554 | if( !POSIX() ){ 555 | printVerbose("Ignoring the option character \""); 556 | printVerbose( opt ); 557 | printVerbose( "\" ( POSIX options are turned off )" ); 558 | printVerbose(); 559 | return; 560 | } 561 | 562 | 563 | if( optchar_counter >= max_char_options ){ 564 | if( doubleCharStorage() == false ){ 565 | addOptionError( opt ); 566 | return; 567 | } 568 | } 569 | optionchars[ optchar_counter ] = opt ; 570 | optchartype[ optchar_counter ] = type ; 571 | optcharindex[ optchar_counter ] = g_value_counter; 572 | optchar_counter++; 573 | } 574 | 575 | void 576 | AnyOption::addOptionError( const char *opt ) 577 | { 578 | cout << endl ; 579 | cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ; 580 | cout << "While adding the option : \""<< opt << "\"" << endl; 581 | cout << "Exiting." << endl ; 582 | cout << endl ; 583 | exit(0); 584 | } 585 | 586 | void 587 | AnyOption::addOptionError( char opt ) 588 | { 589 | cout << endl ; 590 | cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ; 591 | cout << "While adding the option: \""<< opt << "\"" << endl; 592 | cout << "Exiting." << endl ; 593 | cout << endl ; 594 | exit(0); 595 | } 596 | 597 | void 598 | AnyOption::processOptions() 599 | { 600 | if( ! valueStoreOK() ) 601 | return; 602 | } 603 | 604 | void 605 | AnyOption::processCommandArgs(int max_args) 606 | { 607 | max_legal_args = max_args; 608 | processCommandArgs(); 609 | } 610 | 611 | void 612 | AnyOption::processCommandArgs( int _argc, char **_argv) 613 | { 614 | useCommandArgs( _argc, _argv ); 615 | processCommandArgs(); 616 | } 617 | 618 | void 619 | AnyOption::processCommandArgs( int _argc, char **_argv, int max_args ) 620 | { 621 | max_legal_args = max_args; 622 | processCommandArgs( _argc, _argv ); 623 | } 624 | 625 | void 626 | AnyOption::processCommandArgs( int _argc, QStringList _argv) 627 | { 628 | useCommandArgs( _argc, _argv ); 629 | processCommandArgs(); 630 | } 631 | 632 | void 633 | AnyOption::processCommandArgs() 634 | { 635 | if( ! ( valueStoreOK() && CommandSet() ) ) 636 | return; 637 | 638 | if( max_legal_args == 0 ) 639 | max_legal_args = argc; 640 | new_argv = (int*) malloc( (max_legal_args+1) * sizeof(int) ); 641 | for( int i = 1 ; i < argc ; i++ ){/* ignore first argv */ 642 | if( argv[i][0] == long_opt_prefix[0] && 643 | argv[i][1] == long_opt_prefix[1] ) { /* long GNU option */ 644 | int match_at = parseGNU( argv[i]+2 ); /* skip -- */ 645 | if( match_at >= 0 && i < argc-1 ) /* found match */ 646 | setValue( options[match_at] , argv[++i] ); 647 | }else if( argv[i][0] == opt_prefix_char ) { /* POSIX char */ 648 | if( POSIX() ){ 649 | char ch = parsePOSIX( argv[i]+1 );/* skip - */ 650 | if( ch != '0' && i < argc-1 ) /* matching char */ 651 | setValue( ch , argv[++i] ); 652 | } else { /* treat it as GNU option with a - */ 653 | int match_at = parseGNU( argv[i]+1 ); /* skip - */ 654 | if( match_at >= 0 && i < argc-1 ) /* found match */ 655 | setValue( options[match_at] , argv[++i] ); 656 | } 657 | }else { /* not option but an argument keep index */ 658 | if( new_argc < max_legal_args ){ 659 | new_argv[ new_argc ] = i ; 660 | new_argc++; 661 | }else{ /* ignore extra arguments */ 662 | printVerbose( "Ignoring extra argument: " ); 663 | printVerbose( argv[i] ); 664 | printVerbose( ); 665 | printAutoUsage(); 666 | } 667 | printVerbose( "Unknown command argument option : " ); 668 | printVerbose( argv[i] ); 669 | printVerbose( ); 670 | printAutoUsage(); 671 | } 672 | } 673 | } 674 | 675 | char 676 | AnyOption::parsePOSIX( char* arg ) 677 | { 678 | 679 | for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ 680 | char ch = arg[i] ; 681 | if( matchChar(ch) ) { /* keep matching flags till an option */ 682 | /*if last char argv[++i] is the value */ 683 | if( i == strlen(arg)-1 ){ 684 | return ch; 685 | }else{/* else the rest of arg is the value */ 686 | i++; /* skip any '=' and ' ' */ 687 | while( arg[i] == whitespace 688 | || arg[i] == equalsign ) 689 | i++; 690 | setValue( ch , arg+i ); 691 | return '0'; 692 | } 693 | } 694 | } 695 | printVerbose( "Unknown command argument option : " ); 696 | printVerbose( arg ); 697 | printVerbose( ); 698 | printAutoUsage(); 699 | return '0'; 700 | } 701 | 702 | int 703 | AnyOption::parseGNU( char *arg ) 704 | { 705 | int split_at = 0; 706 | /* if has a '=' sign get value */ 707 | for( unsigned int i = 0 ; i < strlen(arg) ; i++ ){ 708 | if(arg[i] == equalsign ){ 709 | split_at = i ; /* store index */ 710 | i = strlen(arg); /* get out of loop */ 711 | } 712 | } 713 | if( split_at > 0 ){ /* it is an option value pair */ 714 | char* tmp = (char*) malloc( (split_at+1)*sizeof(char) ); 715 | for( int i = 0 ; i < split_at ; i++ ) 716 | tmp[i] = arg[i]; 717 | tmp[split_at] = '\0'; 718 | 719 | if ( matchOpt( tmp ) >= 0 ){ 720 | setValue( options[matchOpt(tmp)] , arg+split_at+1 ); 721 | free (tmp); 722 | }else{ 723 | printVerbose( "Unknown command argument option : " ); 724 | printVerbose( arg ); 725 | printVerbose( ); 726 | printAutoUsage(); 727 | free (tmp); 728 | return -1; 729 | } 730 | }else{ /* regular options with no '=' sign */ 731 | return matchOpt(arg); 732 | } 733 | return -1; 734 | } 735 | 736 | 737 | int 738 | AnyOption::matchOpt( char *opt ) 739 | { 740 | for( int i = 0 ; i < option_counter ; i++ ){ 741 | if( strcmp( options[i], opt ) == 0 ){ 742 | if( optiontype[i] == COMMON_OPT || 743 | optiontype[i] == COMMAND_OPT ) 744 | { /* found option return index */ 745 | return i; 746 | }else if( optiontype[i] == COMMON_FLAG || 747 | optiontype[i] == COMMAND_FLAG ) 748 | { /* found flag, set it */ 749 | setFlagOn( opt ); 750 | return -1; 751 | } 752 | } 753 | } 754 | printVerbose( "Unknown command argument option : " ); 755 | printVerbose( opt ) ; 756 | printVerbose( ); 757 | printAutoUsage(); 758 | return -1; 759 | } 760 | bool 761 | AnyOption::matchChar( char c ) 762 | { 763 | for( int i = 0 ; i < optchar_counter ; i++ ){ 764 | if( optionchars[i] == c ) { /* found match */ 765 | if(optchartype[i] == COMMON_OPT || 766 | optchartype[i] == COMMAND_OPT ) 767 | { /* an option store and stop scanning */ 768 | return true; 769 | }else if( optchartype[i] == COMMON_FLAG || 770 | optchartype[i] == COMMAND_FLAG ) { /* a flag store and keep scanning */ 771 | setFlagOn( c ); 772 | return false; 773 | } 774 | } 775 | } 776 | printVerbose( "Unknown command argument option : " ); 777 | printVerbose( c ) ; 778 | printVerbose( ); 779 | printAutoUsage(); 780 | return false; 781 | } 782 | 783 | bool 784 | AnyOption::valueStoreOK( ) 785 | { 786 | int size= 0; 787 | if( !set ){ 788 | if( g_value_counter > 0 ){ 789 | size = g_value_counter * sizeof(char*); 790 | values = (char**)malloc( size ); 791 | for( int i = 0 ; i < g_value_counter ; i++) 792 | values[i] = NULL; 793 | set = true; 794 | } 795 | } 796 | return set; 797 | } 798 | 799 | /* 800 | * public get methods 801 | */ 802 | char* 803 | AnyOption::getValue( const char *option ) 804 | { 805 | if( !valueStoreOK() ) 806 | return NULL; 807 | 808 | for( int i = 0 ; i < option_counter ; i++ ){ 809 | if( strcmp( options[i], option ) == 0 ) 810 | return values[ optionindex[i] ]; 811 | } 812 | return NULL; 813 | } 814 | 815 | bool 816 | AnyOption::getFlag( const char *option ) 817 | { 818 | if( !valueStoreOK() ) 819 | return false; 820 | for( int i = 0 ; i < option_counter ; i++ ){ 821 | if( strcmp( options[i], option ) == 0 ) 822 | return findFlag( values[ optionindex[i] ] ); 823 | } 824 | return false; 825 | } 826 | 827 | char* 828 | AnyOption::getValue( char option ) 829 | { 830 | if( !valueStoreOK() ) 831 | return NULL; 832 | for( int i = 0 ; i < optchar_counter ; i++ ){ 833 | if( optionchars[i] == option ) 834 | return values[ optcharindex[i] ]; 835 | } 836 | return NULL; 837 | } 838 | 839 | bool 840 | AnyOption::getFlag( char option ) 841 | { 842 | if( !valueStoreOK() ) 843 | return false; 844 | for( int i = 0 ; i < optchar_counter ; i++ ){ 845 | if( optionchars[i] == option ) 846 | return findFlag( values[ optcharindex[i] ] ) ; 847 | } 848 | return false; 849 | } 850 | 851 | bool 852 | AnyOption::findFlag( char* val ) 853 | { 854 | if( val == NULL ) 855 | return false; 856 | 857 | if( strcmp( TRUE_FLAG , val ) == 0 ) 858 | return true; 859 | 860 | return false; 861 | } 862 | 863 | /* 864 | * private set methods 865 | */ 866 | bool 867 | AnyOption::setValue( const char *option , char *value ) 868 | { 869 | if( !valueStoreOK() ) 870 | return false; 871 | for( int i = 0 ; i < option_counter ; i++ ){ 872 | if( strcmp( options[i], option ) == 0 ){ 873 | values[ optionindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char)); 874 | strcpy( values[ optionindex[i] ], value ); 875 | return true; 876 | } 877 | } 878 | return false; 879 | } 880 | 881 | bool 882 | AnyOption::setFlagOn( const char *option ) 883 | { 884 | if( !valueStoreOK() ) 885 | return false; 886 | for( int i = 0 ; i < option_counter ; i++ ){ 887 | if( strcmp( options[i], option ) == 0 ){ 888 | values[ optionindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char)); 889 | strcpy( values[ optionindex[i] ] , TRUE_FLAG ); 890 | return true; 891 | } 892 | } 893 | return false; 894 | } 895 | 896 | bool 897 | AnyOption::setValue( char option , char *value ) 898 | { 899 | if( !valueStoreOK() ) 900 | return false; 901 | for( int i = 0 ; i < optchar_counter ; i++ ){ 902 | if( optionchars[i] == option ){ 903 | values[ optcharindex[i] ] = (char*) malloc((strlen(value)+1)*sizeof(char)); 904 | strcpy( values[ optcharindex[i] ], value ); 905 | return true; 906 | } 907 | } 908 | return false; 909 | } 910 | 911 | bool 912 | AnyOption::setFlagOn( char option ) 913 | { 914 | if( !valueStoreOK() ) 915 | return false; 916 | for( int i = 0 ; i < optchar_counter ; i++ ){ 917 | if( optionchars[i] == option ){ 918 | values[ optcharindex[i] ] = (char*) malloc((strlen(TRUE_FLAG)+1)*sizeof(char)); 919 | strcpy( values[ optcharindex[i] ] , TRUE_FLAG ); 920 | return true; 921 | } 922 | } 923 | return false; 924 | } 925 | 926 | 927 | int 928 | AnyOption::getArgc( ) 929 | { 930 | return new_argc; 931 | } 932 | 933 | char* 934 | AnyOption::getArgv( int index ) 935 | { 936 | if( index < new_argc ){ 937 | return ( argv[ new_argv[ index ] ] ); 938 | } 939 | return NULL; 940 | } 941 | 942 | /* dotfile sub routines */ 943 | 944 | bool 945 | AnyOption::processFile() 946 | { 947 | if( ! (valueStoreOK() && FileSet()) ) 948 | return false; 949 | return ( consumeFile(readFile()) ); 950 | } 951 | 952 | bool 953 | AnyOption::processFile( const char *filename ) 954 | { 955 | useFileName(filename ); 956 | return ( processFile() ); 957 | } 958 | 959 | char* 960 | AnyOption::readFile() 961 | { 962 | return ( readFile(filename) ); 963 | } 964 | 965 | /* 966 | * read the file contents to a character buffer 967 | */ 968 | 969 | char* 970 | AnyOption::readFile( const char* fname ) 971 | { 972 | int length; 973 | char *buffer; 974 | ifstream is; 975 | is.open ( fname , ifstream::in ); 976 | if( ! is.good() ){ 977 | is.close(); 978 | return NULL; 979 | } 980 | is.seekg (0, ios::end); 981 | length = is.tellg(); 982 | is.seekg (0, ios::beg); 983 | buffer = (char*) malloc(length*sizeof(char)); 984 | is.read (buffer,length); 985 | is.close(); 986 | return buffer; 987 | } 988 | 989 | /* 990 | * scans a char* buffer for lines that does not 991 | * start with the specified comment character. 992 | */ 993 | bool 994 | AnyOption::consumeFile( char *buffer ) 995 | { 996 | 997 | if( buffer == NULL ) 998 | return false; 999 | 1000 | char *cursor = buffer;/* preserve the ptr */ 1001 | char *pline = NULL ; 1002 | int linelength = 0; 1003 | bool newline = true; 1004 | for( unsigned int i = 0 ; i < strlen( buffer ) ; i++ ){ 1005 | if( *cursor == endofline ) { /* end of line */ 1006 | if( pline != NULL ) /* valid line */ 1007 | processLine( pline, linelength ); 1008 | pline = NULL; 1009 | newline = true; 1010 | }else if( newline ){ /* start of line */ 1011 | newline = false; 1012 | if( (*cursor != comment ) ){ /* not a comment */ 1013 | pline = cursor ; 1014 | linelength = 0 ; 1015 | } 1016 | } 1017 | cursor++; /* keep moving */ 1018 | linelength++; 1019 | } 1020 | free (buffer); 1021 | return true; 1022 | } 1023 | 1024 | 1025 | /* 1026 | * find a valid type value pair separated by a delimiter 1027 | * character and pass it to valuePairs() 1028 | * any line which is not valid will be considered a value 1029 | * and will get passed on to justValue() 1030 | * 1031 | * assuming delimiter is ':' the behaviour will be, 1032 | * 1033 | * width:10 - valid pair valuePairs( width, 10 ); 1034 | * width : 10 - valid pair valuepairs( width, 10 ); 1035 | * 1036 | * :::: - not valid 1037 | * width - not valid 1038 | * :10 - not valid 1039 | * width: - not valid 1040 | * :: - not valid 1041 | * : - not valid 1042 | * 1043 | */ 1044 | 1045 | void 1046 | AnyOption::processLine( char *theline, int length ) 1047 | { 1048 | bool found = false; 1049 | char *pline = (char*) malloc( (length+1)*sizeof(char) ); 1050 | for( int i = 0 ; i < length ; i ++ ) 1051 | pline[i]= *(theline++); 1052 | pline[length] = nullterminate; 1053 | char *cursor = pline ; /* preserve the ptr */ 1054 | if( *cursor == delimiter || *(cursor+length-1) == delimiter ){ 1055 | justValue( pline );/* line with start/end delimiter */ 1056 | }else{ 1057 | for( int i = 1 ; i < length-1 && !found ; i++){/* delimiter */ 1058 | if( *cursor == delimiter ){ 1059 | *(cursor-1) = nullterminate; /* two strings */ 1060 | found = true; 1061 | valuePairs( pline , cursor+1 ); 1062 | } 1063 | cursor++; 1064 | } 1065 | cursor++; 1066 | if( !found ) /* not a pair */ 1067 | justValue( pline ); 1068 | } 1069 | free (pline); 1070 | } 1071 | 1072 | /* 1073 | * removes trailing and preceeding whitespaces from a string 1074 | */ 1075 | char* 1076 | AnyOption::chomp( char *str ) 1077 | { 1078 | while( *str == whitespace ) 1079 | str++; 1080 | char *end = str+strlen(str)-1; 1081 | while( *end == whitespace ) 1082 | end--; 1083 | *(end+1) = nullterminate; 1084 | return str; 1085 | } 1086 | 1087 | void 1088 | AnyOption::valuePairs( char *type, char *value ) 1089 | { 1090 | if ( strlen(chomp(type)) == 1 ){ /* this is a char option */ 1091 | for( int i = 0 ; i < optchar_counter ; i++ ){ 1092 | if( optionchars[i] == type[0] ){ /* match */ 1093 | if( optchartype[i] == COMMON_OPT || 1094 | optchartype[i] == FILE_OPT ) 1095 | { 1096 | setValue( type[0] , chomp(value) ); 1097 | return; 1098 | } 1099 | } 1100 | } 1101 | } 1102 | /* if no char options matched */ 1103 | for( int i = 0 ; i < option_counter ; i++ ){ 1104 | if( strcmp( options[i], type ) == 0 ){ /* match */ 1105 | if( optiontype[i] == COMMON_OPT || 1106 | optiontype[i] == FILE_OPT ) 1107 | { 1108 | setValue( type , chomp(value) ); 1109 | return; 1110 | } 1111 | } 1112 | } 1113 | printVerbose( "Unknown option in resourcefile : " ); 1114 | printVerbose( type ); 1115 | printVerbose( ); 1116 | } 1117 | 1118 | void 1119 | AnyOption::justValue( char *type ) 1120 | { 1121 | 1122 | if ( strlen(chomp(type)) == 1 ){ /* this is a char option */ 1123 | for( int i = 0 ; i < optchar_counter ; i++ ){ 1124 | if( optionchars[i] == type[0] ){ /* match */ 1125 | if( optchartype[i] == COMMON_FLAG || 1126 | optchartype[i] == FILE_FLAG ) 1127 | { 1128 | setFlagOn( type[0] ); 1129 | return; 1130 | } 1131 | } 1132 | } 1133 | } 1134 | /* if no char options matched */ 1135 | for( int i = 0 ; i < option_counter ; i++ ){ 1136 | if( strcmp( options[i], type ) == 0 ){ /* match */ 1137 | if( optiontype[i] == COMMON_FLAG || 1138 | optiontype[i] == FILE_FLAG ) 1139 | { 1140 | setFlagOn( type ); 1141 | return; 1142 | } 1143 | } 1144 | } 1145 | printVerbose( "Unknown option in resourcefile : " ); 1146 | printVerbose( type ); 1147 | printVerbose( ); 1148 | } 1149 | 1150 | /* 1151 | * usage and help 1152 | */ 1153 | 1154 | 1155 | void 1156 | AnyOption::printAutoUsage() 1157 | { 1158 | if( autousage ) printUsage(); 1159 | } 1160 | 1161 | void 1162 | AnyOption::printUsage() 1163 | { 1164 | 1165 | if( once ) { 1166 | once = false ; 1167 | cout << endl ; 1168 | for( int i = 0 ; i < usage_lines ; i++ ) 1169 | cout << usage[i] << endl ; 1170 | cout << endl ; 1171 | } 1172 | } 1173 | 1174 | 1175 | void 1176 | AnyOption::addUsage( const char *line ) 1177 | { 1178 | if( usage_lines >= max_usage_lines ){ 1179 | if( doubleUsageStorage() == false ){ 1180 | addUsageError( line ); 1181 | exit(1); 1182 | } 1183 | } 1184 | usage[ usage_lines ] = line ; 1185 | usage_lines++; 1186 | } 1187 | 1188 | void 1189 | AnyOption::addUsageError( const char *line ) 1190 | { 1191 | cout << endl ; 1192 | cout << "OPTIONS ERROR : Failed allocating extra memory " << endl ; 1193 | cout << "While adding the usage/help : \""<< line << "\"" << endl; 1194 | cout << "Exiting." << endl ; 1195 | cout << endl ; 1196 | exit(0); 1197 | 1198 | } 1199 | 1200 | void 1201 | AnyOption::setVersion( const char *ver ) 1202 | { 1203 | version = ver; 1204 | } 1205 | 1206 | void 1207 | AnyOption::printVersion() 1208 | { 1209 | 1210 | if( once ) { 1211 | once = false ; 1212 | cout << endl ; 1213 | cout << version << endl; 1214 | cout << endl ; 1215 | } 1216 | } 1217 | 1218 | -------------------------------------------------------------------------------- /src/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** Contact: Nokia Corporation (qt-info@nokia.com) 6 | ** 7 | ** This file is part of the examples of the Qt Toolkit. 8 | ** 9 | ** $QT_BEGIN_LICENSE:LGPL$ 10 | ** Commercial Usage 11 | ** Licensees holding valid Qt Commercial licenses may use this file in 12 | ** accordance with the Qt Commercial License Agreement provided with the 13 | ** Software or, alternatively, in accordance with the terms contained in 14 | ** a written agreement between you and Nokia. 15 | ** 16 | ** GNU Lesser General Public License Usage 17 | ** Alternatively, this file may be used under the terms of the GNU Lesser 18 | ** General Public License version 2.1 as published by the Free Software 19 | ** Foundation and appearing in the file LICENSE.LGPL included in the 20 | ** packaging of this file. Please review the following information to 21 | ** ensure the GNU Lesser General Public License version 2.1 requirements 22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. 23 | ** 24 | ** In addition, as a special exception, Nokia gives you certain additional 25 | ** rights. These rights are described in the Nokia Qt LGPL Exception 26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. 27 | ** 28 | ** GNU General Public License Usage 29 | ** Alternatively, this file may be used under the terms of the GNU 30 | ** General Public License version 3.0 as published by the Free Software 31 | ** Foundation and appearing in the file LICENSE.GPL included in the 32 | ** packaging of this file. Please review the following information to 33 | ** ensure the GNU General Public License version 3.0 requirements will be 34 | ** met: http://www.gnu.org/copyleft/gpl.html. 35 | ** 36 | ** If you have questions regarding the use of this file, please contact 37 | ** Nokia at qt-info@nokia.com. 38 | ** $QT_END_LICENSE$ 39 | ** 40 | ****************************************************************************/ 41 | 42 | #include 43 | #include "config.h" 44 | #include "qinfo.h" 45 | #include "mainwindow.h" 46 | #include "qwk_webpage.h" 47 | 48 | #ifdef QT5 49 | #include 50 | #include 51 | #include 52 | #include 53 | #endif 54 | 55 | #include "cachingnm.h" 56 | #include "persistentcookiejar.h" 57 | 58 | MainWindow::MainWindow() : QMainWindow() 59 | { 60 | progress = 0; 61 | diskCache = NULL; 62 | topBox = NULL; 63 | loadProgress = NULL; 64 | messagesBox = NULL; 65 | 66 | qwkSettings = new QwkSettings(); 67 | 68 | isUrlRealyChanged = false; 69 | 70 | handler = new UnixSignals(); 71 | connect(handler, SIGNAL(sigBREAK()), SLOT(unixSignalQuit())); 72 | connect(handler, SIGNAL(sigTERM()), SLOT(unixSignalQuit())); 73 | connect(handler, SIGNAL(sigINT()), SLOT(unixSignalQuit())); 74 | connect(handler, SIGNAL(sigHUP()), SLOT(unixSignalHup())); 75 | 76 | network_interface = new QNetworkInterface(); 77 | 78 | delayedResize = new QTimer(); 79 | delayedLoad = new QTimer(); 80 | 81 | #ifdef USE_TESTLIB 82 | simulateClick = new QTestEventList(); 83 | #endif 84 | 85 | } 86 | 87 | void MainWindow::init(AnyOption *opts) 88 | { 89 | cmdopts = opts; 90 | 91 | if (cmdopts->getValue("config") || cmdopts->getValue('c')) { 92 | qDebug(">> Config option in command prompt..."); 93 | QString cfgPath = cmdopts->getValue('c'); 94 | if (cfgPath.isEmpty()) { 95 | cfgPath = cmdopts->getValue("config"); 96 | } 97 | qwkSettings->loadSettings(cfgPath); 98 | } else { 99 | qwkSettings->loadSettings(QString("")); 100 | } 101 | 102 | if (qwkSettings->getBool("signals/enable")) { 103 | connect(handler, SIGNAL(sigUSR1()), SLOT(unixSignalUsr1())); 104 | connect(handler, SIGNAL(sigUSR2()), SLOT(unixSignalUsr2())); 105 | } 106 | handler->start(); 107 | 108 | setMinimumWidth(320); 109 | setMinimumHeight(200); 110 | 111 | quint16 minimalWidth = qwkSettings->getUInt("view/minimal-width"); 112 | quint16 minimalHeight = qwkSettings->getUInt("view/minimal-height"); 113 | if (minimalWidth) { 114 | setMinimumWidth(minimalWidth); 115 | } 116 | if (minimalHeight) { 117 | setMinimumHeight(minimalHeight); 118 | } 119 | 120 | hiddenCurdor = new QCursor(Qt::BlankCursor); 121 | 122 | qDebug() << "Application icon: " << qwkSettings->getQString("application/icon"); 123 | setWindowIcon(QIcon( 124 | qwkSettings->getQString("application/icon") 125 | )); 126 | 127 | if (cmdopts->getValue("uri") || cmdopts->getValue('u')) { 128 | qDebug(">> Uri option in command prompt..."); 129 | QString uri = cmdopts->getValue('u'); 130 | if (uri.isEmpty()) { 131 | uri = cmdopts->getValue("uri"); 132 | } 133 | qwkSettings->setValue("browser/homepage", uri); 134 | } 135 | 136 | QCoreApplication::setOrganizationName( 137 | qwkSettings->getQString("application/organization") 138 | ); 139 | QCoreApplication::setOrganizationDomain( 140 | qwkSettings->getQString("application/organization-domain") 141 | ); 142 | QCoreApplication::setApplicationName( 143 | qwkSettings->getQString("application/name") 144 | ); 145 | QCoreApplication::setApplicationVersion( 146 | qwkSettings->getQString("application/version") 147 | ); 148 | 149 | // --- Network --- // 150 | 151 | if (qwkSettings->getBool("proxy/enable")) { 152 | bool system = qwkSettings->getBool("proxy/system"); 153 | if (system) { 154 | QNetworkProxyFactory::setUseSystemConfiguration(system); 155 | } else { 156 | QNetworkProxy proxy; 157 | proxy.setType(QNetworkProxy::HttpProxy); 158 | proxy.setHostName( 159 | qwkSettings->getQString("proxy/host") 160 | ); 161 | proxy.setPort(qwkSettings->getUInt("proxy/port")); 162 | if (qwkSettings->getBool("proxy/auth")) { 163 | proxy.setUser(qwkSettings->getQString("proxy/username")); 164 | proxy.setPassword(qwkSettings->getQString("proxy/password")); 165 | } 166 | QNetworkProxy::setApplicationProxy(proxy); 167 | } 168 | } 169 | 170 | // --- Web View --- // 171 | view = new WebView(); 172 | 173 | QPalette paletteG = this->palette(); 174 | paletteG.setColor(QPalette::Window, QColor(220,240,220,127)); 175 | 176 | QPalette paletteR = this->palette(); 177 | paletteR.setColor(QPalette::Window, QColor(240,220,220,127)); 178 | 179 | topBox = new QHBoxLayout(view); 180 | topBox->setContentsMargins(2, 2, 2, 2); 181 | 182 | if (qwkSettings->getBool("view/show_load_progress")) { 183 | // --- Progress Bar --- // 184 | loadProgress = new QProgressBar(); 185 | loadProgress->setContentsMargins(2, 2, 2, 2); 186 | loadProgress->setMinimumSize(100, 16); 187 | loadProgress->setMaximumSize(100, 16); 188 | loadProgress->setAutoFillBackground(true); 189 | loadProgress->setPalette(paletteG); 190 | 191 | // Do not work... Need Layout... 192 | loadProgress->setAlignment(Qt::AlignTop | Qt::AlignLeft); 193 | loadProgress->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); 194 | 195 | loadProgress->hide(); 196 | 197 | topBox->addWidget(loadProgress, 0, Qt::AlignTop | Qt::AlignLeft); 198 | } 199 | 200 | if (qwkSettings->getBool("browser/show_error_messages")) { 201 | // --- Messages Box --- // 202 | messagesBox = new QLabel(); 203 | messagesBox->setContentsMargins(2, 2, 2, 2); 204 | // messagesBox->setWordWrap(true); 205 | messagesBox->setAutoFillBackground(true); 206 | messagesBox->setPalette(paletteR); 207 | 208 | // Do not work... Need Layout... 209 | messagesBox->setAlignment(Qt::AlignVCenter); 210 | messagesBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding); 211 | 212 | messagesBox->hide(); 213 | 214 | topBox->addStretch(2); 215 | topBox->addWidget(messagesBox, 1, Qt::AlignTop | Qt::AlignLeft); 216 | } 217 | 218 | view->setSettings(qwkSettings); 219 | view->setPage(new QwkWebPage(view)); 220 | 221 | // --- Disk cache --- // 222 | if (qwkSettings->getBool("cache/enable")) { 223 | diskCache = new QNetworkDiskCache(this); 224 | QString location = qwkSettings->getQString("cache/location"); 225 | if (!location.length()) { 226 | #ifdef QT5 227 | location = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); 228 | #else 229 | location = QDesktopServices::storageLocation(QDesktopServices::CacheLocation); 230 | #endif 231 | } 232 | diskCache->setCacheDirectory(location); 233 | diskCache->setMaximumCacheSize(qwkSettings->getUInt("cache/size")); 234 | 235 | if (qwkSettings->getBool("cache/clear-on-start")) { 236 | diskCache->clear(); 237 | } 238 | else if (cmdopts->getFlag('C') || cmdopts->getFlag("clear-cache")) { 239 | diskCache->clear(); 240 | } 241 | 242 | CachingNetworkManager *nm = new CachingNetworkManager(); 243 | nm->setCache(diskCache); 244 | view->page()->setNetworkAccessManager(nm); 245 | } 246 | rotated = cmdopts->getFlag("rotate"); 247 | 248 | if (qwkSettings->getBool("browser/cookiejar")) { 249 | view->page()->networkAccessManager()->setCookieJar(new PersistentCookieJar()); 250 | } 251 | 252 | view->settings()->setAttribute(QWebSettings::JavascriptEnabled, 253 | qwkSettings->getBool("browser/javascript") 254 | ); 255 | 256 | view->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, 257 | qwkSettings->getBool("browser/javascript_can_open_windows") 258 | ); 259 | 260 | view->settings()->setAttribute(QWebSettings::JavascriptCanCloseWindows, 261 | qwkSettings->getBool("browser/javascript_can_close_windows") 262 | ); 263 | 264 | view->settings()->setAttribute(QWebSettings::WebGLEnabled, 265 | qwkSettings->getBool("browser/webgl") 266 | ); 267 | 268 | view->settings()->setAttribute(QWebSettings::JavaEnabled, 269 | qwkSettings->getBool("browser/java") 270 | ); 271 | 272 | view->settings()->setAttribute(QWebSettings::PluginsEnabled, 273 | qwkSettings->getBool("browser/plugins") 274 | ); 275 | 276 | view->settings()->setAttribute(QWebSettings::LocalStorageEnabled, 277 | qwkSettings->getBool("localstorage/enable") 278 | ); 279 | 280 | #if QT_VERSION >= 0x050400 281 | view->settings()->setAttribute(QWebSettings::Accelerated2dCanvasEnabled, true); 282 | #endif 283 | view->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, true); 284 | #if QT_VERSION >= 0x050200 285 | view->settings()->setAttribute(QWebSettings::CSSRegionsEnabled, true); 286 | view->settings()->setAttribute(QWebSettings::CSSGridLayoutEnabled, true); 287 | #endif 288 | view->settings()->setAttribute(QWebSettings::SiteSpecificQuirksEnabled, true); 289 | 290 | if (qwkSettings->getBool("inspector/enable")) { 291 | view->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); 292 | 293 | inspector = new QWebInspector(); 294 | inspector->setVisible(qwkSettings->getBool("inspector/visible")); 295 | inspector->setMinimumSize(800, 600); 296 | inspector->setWindowTitle(qwkSettings->getQString("application/name") + " - WebInspector"); 297 | inspector->setWindowIcon(this->windowIcon()); 298 | inspector->setPage(view->page()); 299 | } 300 | 301 | view->settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, 302 | qwkSettings->getBool("security/local_content_can_access_remote_urls") 303 | ); 304 | 305 | connect(view->page()->mainFrame(), SIGNAL(titleChanged(QString)), SLOT(adjustTitle(QString))); 306 | connect(view->page()->mainFrame(), SIGNAL(loadStarted()), SLOT(startLoading())); 307 | connect(view->page()->mainFrame(), SIGNAL(urlChanged(const QUrl &)), SLOT(urlChanged(const QUrl &))); 308 | connect(view->page(), SIGNAL(loadProgress(int)), SLOT(setProgress(int))); 309 | connect(view->page()->mainFrame(), SIGNAL(loadFinished(bool)), SLOT(finishLoading(bool))); 310 | connect(view->page()->mainFrame(), SIGNAL(iconChanged()), SLOT(pageIconLoaded())); 311 | connect(view, SIGNAL(qwkNetworkError(QNetworkReply::NetworkError,QString)), SLOT(handleQwkNetworkError(QNetworkReply::NetworkError,QString))); 312 | connect(view, SIGNAL(qwkNetworkReplyUrl(QUrl)), SLOT(handleQwkNetworkReplyUrl(QUrl))); 313 | 314 | QNetworkConfigurationManager manager; 315 | QNetworkConfiguration cfg = manager.defaultConfiguration(); 316 | 317 | n_session = new QNetworkSession(cfg); 318 | connect(n_session, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(networkStateChanged(QNetworkSession::State))); 319 | n_session->open(); 320 | 321 | QDesktopWidget *desktop = QApplication::desktop(); 322 | connect(desktop, SIGNAL(resized(int)), SLOT(desktopResized(int))); 323 | 324 | // Window show, start events loop 325 | show(); 326 | 327 | view->setFocusPolicy(Qt::StrongFocus); 328 | 329 | if (qwkSettings->getBool("view/hide_mouse_cursor")) { 330 | QApplication::setOverrideCursor(Qt::BlankCursor); 331 | view->setCursor(*hiddenCurdor); 332 | QApplication::processEvents(); //process events to force cursor update before press 333 | } 334 | 335 | int delay_resize = 1; 336 | if (qwkSettings->getBool("view/startup_resize_delayed")) { 337 | delay_resize = qwkSettings->getUInt("view/startup_resize_delay"); 338 | } 339 | delayedResize->singleShot(delay_resize, this, SLOT(delayedWindowResize())); 340 | 341 | int delay_load = 1; 342 | if (qwkSettings->getBool("browser/startup_load_delayed")) { 343 | delay_load = qwkSettings->getUInt("browser/startup_load_delay"); 344 | } 345 | delayedLoad->singleShot(delay_load, this, SLOT(delayedPageLoad())); 346 | 347 | graphicsView = new QGraphicsView(this); 348 | graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 349 | graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 350 | graphicsScene = new QGraphicsScene(graphicsView); 351 | proxyWidget = graphicsScene->addWidget(view); 352 | graphicsView->fitInView(proxyWidget); 353 | if (rotated) 354 | proxyWidget->setRotation(90); 355 | graphicsView->setScene(graphicsScene); 356 | graphicsView->setVisible(true); 357 | proxyWidget->setVisible(true); 358 | setCentralWidget(graphicsView); 359 | } 360 | 361 | 362 | void MainWindow::delayedWindowResize() 363 | { 364 | qDebug("Setting focus policy, window size"); 365 | this->setFocusPolicy(Qt::StrongFocus); 366 | 367 | if (qwkSettings->getBool("view/stay_on_top")) { 368 | setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint); 369 | } 370 | 371 | if (qwkSettings->getBool("view/fullscreen")) { 372 | showFullScreen(); 373 | } else if (qwkSettings->getBool("view/maximized")) { 374 | showMaximized(); 375 | } else if (qwkSettings->getBool("view/fixed-size")) { 376 | centerFixedSizeWindow(); 377 | } 378 | QApplication::processEvents(); //process events to force update 379 | 380 | } 381 | 382 | void MainWindow::resizeEvent(QResizeEvent* event) 383 | { 384 | QMainWindow::resizeEvent(event); 385 | if (graphicsView && view) { 386 | auto size = event->size(); 387 | if (rotated) 388 | view->resize(size.height(), size.width()); 389 | else 390 | view->resize(size); 391 | } 392 | } 393 | 394 | void MainWindow::delayedPageLoad() 395 | { 396 | // Wait 1 second. May be not here? 397 | n_session->waitForOpened(1000); 398 | 399 | view->loadHomepage(); 400 | } 401 | 402 | void MainWindow::delayedPageReload() 403 | { 404 | // Wait 1 second. May be not here? 405 | n_session->waitForOpened(1000); 406 | 407 | view->reload(); 408 | } 409 | 410 | void MainWindow::clearCache() 411 | { 412 | if (qwkSettings->getBool("cache/enable")) { 413 | if (diskCache) { 414 | diskCache->clear(); 415 | } 416 | } 417 | } 418 | 419 | void MainWindow::clearCacheOnExit() 420 | { 421 | if (qwkSettings->getBool("cache/enable")) { 422 | if (qwkSettings->getBool("cache/clear-on-exit")) { 423 | if (diskCache) { 424 | diskCache->clear(); 425 | } 426 | } 427 | } 428 | } 429 | 430 | void MainWindow::cleanupSlot() 431 | { 432 | qDebug("Cleanup Slot (application exit)"); 433 | handler->stop(); 434 | clearCacheOnExit(); 435 | QWebSettings::clearMemoryCaches(); 436 | } 437 | 438 | 439 | void MainWindow::centerFixedSizeWindow() 440 | { 441 | quint16 widowWidth = qwkSettings->getUInt("view/fixed-width"); 442 | quint16 widowHeight = qwkSettings->getUInt("view/fixed-height"); 443 | 444 | quint16 screenWidth = QApplication::desktop()->screenGeometry().width(); 445 | quint16 screenHeight = QApplication::desktop()->screenGeometry().height(); 446 | 447 | qDebug() << "Screen size: " << screenWidth << "x" << screenHeight; 448 | 449 | quint16 x = 0; 450 | quint16 y = 0; 451 | 452 | if (qwkSettings->getUInt("view/fixed-centered")) { 453 | x = (screenWidth - widowWidth) / 2; 454 | y = (screenHeight - widowHeight) / 2; 455 | } else { 456 | x = qwkSettings->getUInt("view/fixed-x"); 457 | y = qwkSettings->getUInt("view/fixed-y"); 458 | } 459 | 460 | qDebug() << "Move window to: (" << x << ";" << y << ")"; 461 | 462 | move ( x, y ); 463 | setFixedSize( widowWidth, widowHeight ); 464 | } 465 | 466 | 467 | void MainWindow::keyPressEvent(QKeyEvent *event) 468 | { 469 | qDebug(">> MainWindow received keyPressEvent..."); 470 | 471 | if (qwkSettings->getUInt("browser/disable_hotkeys")) { 472 | if (! view->hasFocus()) { 473 | view->event(event); 474 | } 475 | return; 476 | } 477 | 478 | switch (event->key()) { 479 | case Qt::Key_Up: 480 | view->scrollUp(); 481 | if (! view->hasFocus()) { 482 | view->event(event); 483 | } 484 | break; 485 | case Qt::Key_Down: 486 | view->scrollDown(); 487 | if (! view->hasFocus()) { 488 | view->event(event); 489 | } 490 | break; 491 | case Qt::Key_PageUp: 492 | view->scrollPageUp(); 493 | break; 494 | case Qt::Key_PageDown: 495 | view->scrollPageDown(); 496 | break; 497 | case Qt::Key_End: 498 | view->scrollEnd(); 499 | break; 500 | case Qt::Key_HomePage: 501 | view->loadHomepage(); 502 | break; 503 | case Qt::Key_Home: 504 | if (int(event->modifiers()) == Qt::CTRL) { 505 | view->loadHomepage(); 506 | } else { 507 | view->scrollHome(); 508 | } 509 | break; 510 | case Qt::Key_Backspace: 511 | view->page()->triggerAction(QWebPage::Back); 512 | break; 513 | case Qt::Key_Q: 514 | if (int(event->modifiers()) == Qt::CTRL) { 515 | clearCacheOnExit(); 516 | QApplication::exit(0); 517 | } 518 | else if (! view->hasFocus()) { 519 | view->event(event); 520 | } 521 | break; 522 | case Qt::Key_R: 523 | if (int(event->modifiers()) == Qt::CTRL) { 524 | clearCache(); 525 | view->reload(); 526 | } 527 | else if (! view->hasFocus()) { 528 | view->event(event); 529 | } 530 | break; 531 | case Qt::Key_F5: 532 | view->reload(); 533 | break; 534 | case Qt::Key_F8: 535 | view->stop(); 536 | break; 537 | case Qt::Key_F12: 538 | if (qwkSettings->getUInt("inspector/enable")) { 539 | if (!inspector->isVisible()) { 540 | inspector->setVisible(true); 541 | } else { 542 | inspector->setVisible(false); 543 | } 544 | } 545 | break; 546 | case Qt::Key_F11: 547 | if (isFullScreen()) { 548 | showNormal(); 549 | } else { 550 | showFullScreen(); 551 | } 552 | break; 553 | default: 554 | if (! view->hasFocus()) { 555 | view->event(event); 556 | } 557 | break; 558 | } 559 | } 560 | 561 | void MainWindow::keyReleaseEvent(QKeyEvent *event) 562 | { 563 | qDebug(">> MainWindow received keyReleaseEvent..."); 564 | 565 | if (! view->hasFocus()) { 566 | view->event(event); 567 | } 568 | } 569 | 570 | void MainWindow::handleQwkNetworkError(QNetworkReply::NetworkError error, QString message) 571 | { 572 | qDebug() << QDateTime::currentDateTime().toString() 573 | << "MainWindow::handleQwkNetworkError" 574 | ; 575 | if (message.contains("Host ") && message.contains(" not found")) { 576 | // Don't give a damn 577 | qDebug() << "Don't give a damn"; 578 | return; 579 | } 580 | /* if (message.contains("Error downloading ") && message.contains("server replied: Not Found")) { 581 | // Don't give a damn 582 | qDebug() << "Don't give a damn"; 583 | return; 584 | }*/ 585 | 586 | // Unknown error if eth0 if up but cable out 587 | if (error == QNetworkReply::UnknownNetworkError) { 588 | if (message.contains("Network access is disabled")) { 589 | // Check all interfaces if them has link up 590 | 591 | bool hasLinkUp = false; 592 | foreach (QNetworkInterface interface, network_interface->allInterfaces()) { 593 | if ((interface.flags() & QNetworkInterface::IsUp) && 594 | (interface.flags() & QNetworkInterface::IsRunning) 595 | ) 596 | hasLinkUp = true; 597 | } 598 | 599 | if (hasLinkUp && view->page()->networkAccessManager()->networkAccessible() != QNetworkAccessManager::Accessible) { 600 | 601 | qDebug() << QDateTime::currentDateTime().toString() 602 | << "MainWindow::networkStateChanged -" 603 | << "Has interfaces Up and network not Accessible? Force Accessible state and NetworkSession restart!" 604 | ; 605 | 606 | // force network accessibility to get local content 607 | view->page()->networkAccessManager()->setNetworkAccessible(QNetworkAccessManager::Accessible); 608 | // force NetSession restart 609 | n_session->close(); 610 | n_session->open(); 611 | message += QString("\nNetwork session restarted!"); 612 | 613 | qint32 delay_reload = qwkSettings->getInt("browser/network_error_reload_delay", 15000); 614 | 615 | if (delay_reload >= 0) { 616 | qDebug() << QDateTime::currentDateTime().toString() 617 | << "MainWindow::networkStateChanged -" 618 | << "Delay WebView reload by" << delay_reload/1000. << "sec." 619 | ; 620 | message += QString("\nPage reload queued! Plase wait ") + QVariant(delay_reload / 1000.).toString() + QString(" seconds..."); 621 | // Try reload broken view downloads 622 | delayedLoad->singleShot( 623 | delay_reload, 624 | this, SLOT(delayedPageReload()) 625 | ); 626 | } 627 | } 628 | 629 | } 630 | } 631 | 632 | if (messagesBox) { 633 | messagesBox->show(); 634 | QString txt = messagesBox->text(); 635 | if (txt.length()) { 636 | txt += "\n"; 637 | } 638 | messagesBox->setText(txt + QDateTime::currentDateTime().toString() + " :: " + message); 639 | } 640 | } 641 | 642 | void MainWindow::desktopResized(int p) 643 | { 644 | qDebug() << "Desktop resized event: " << p; 645 | if (qwkSettings->getBool("view/fullscreen")) { 646 | showFullScreen(); 647 | } else if (qwkSettings->getBool("view/maximized")) { 648 | showMaximized(); 649 | } else if (qwkSettings->getBool("view/fixed-size")) { 650 | centerFixedSizeWindow(); 651 | } 652 | } 653 | 654 | /** 655 | * @brief MainWindow::pageIconLoaded 656 | * This is triggered by WebView->page()->mainFrame now 657 | */ 658 | void MainWindow::pageIconLoaded() 659 | { 660 | setWindowIcon(view->icon()); 661 | } 662 | 663 | /** 664 | * @brief MainWindow::startLoading 665 | * This is triggered by WebView->page()->mainFrame now 666 | */ 667 | void MainWindow::startLoading() 668 | { 669 | qDebug() << QDateTime::currentDateTime().toString() << "Start loading..."; 670 | 671 | progress = 0; 672 | 673 | isUrlRealyChanged = false; 674 | 675 | adjustTitle(view->title()); 676 | 677 | QWebSettings::clearMemoryCaches(); 678 | 679 | if (loadProgress) { 680 | loadProgress->show(); 681 | } 682 | 683 | if (messagesBox) { 684 | messagesBox->setText(""); 685 | messagesBox->hide(); 686 | } 687 | 688 | } 689 | 690 | void MainWindow::adjustTitle(QString title) 691 | { 692 | if (progress <= 0 || progress >= 100) { 693 | setWindowTitle(title); 694 | } else { 695 | setWindowTitle(QString("%1 (%2%)").arg(title).arg(progress)); 696 | } 697 | } 698 | 699 | /** 700 | * @brief MainWindow::setProgress 701 | * This is triggered every resource loaded by WebView->page->all frames 702 | * @param p 703 | */ 704 | void MainWindow::setProgress(int p) 705 | { 706 | progress = p; 707 | adjustTitle(view->title()); 708 | 709 | qDebug() << QDateTime::currentDateTime().toString() << "Loading progress: " << p; 710 | 711 | if (loadProgress) { 712 | loadProgress->setValue(p); 713 | if (p != 100) { 714 | loadProgress->show(); 715 | view->resetLoadTimer(); 716 | } else { 717 | loadProgress->hide(); 718 | view->stopLoadTimer(); 719 | } 720 | } 721 | 722 | // 1. Hide scrollbars (and add some styles) 723 | // If there complete head and body start loaded... 724 | if (!isScrollBarsHidden && isUrlRealyChanged) { 725 | isScrollBarsHidden = hideScrollbars(); 726 | } 727 | } 728 | 729 | /** 730 | * @brief MainWindow::urlChanged 731 | * This is triggered by WebView->page()->mainFrame now 732 | * @param url 733 | */ 734 | void MainWindow::urlChanged(const QUrl &url) 735 | { 736 | qDebug() << QDateTime::currentDateTime().toString() << "URL changes: " << url.toString(); 737 | 738 | // Where is a real change in webframe! Drop flags. 739 | isScrollBarsHidden = false; 740 | isSelectionDisabled = false; 741 | isUrlRealyChanged = true; 742 | 743 | if (qwkSettings->getReal("view/page_scale")) { 744 | view->page()->mainFrame()->setZoomFactor(qwkSettings->getReal("view/page_scale")); 745 | } 746 | 747 | view->resetLoadTimer(); 748 | 749 | // This is real link clicked 750 | view->playSound("event-sounds/link-clicked"); 751 | } 752 | 753 | /** 754 | * @brief MainWindow::finishLoading 755 | * This is triggered by WebView->page()->mainFrame now 756 | * @param ok 757 | */ 758 | void MainWindow::finishLoading(bool ok) 759 | { 760 | qDebug() << QDateTime::currentDateTime().toString() 761 | << "MainWindow::finishLoading - " 762 | << "ok =" << (int)ok 763 | ; 764 | 765 | view->stopLoadTimer(); 766 | 767 | if (!ok) { 768 | if (messagesBox) { 769 | messagesBox->show(); 770 | QString txt = messagesBox->text(); 771 | if (txt.length()) { 772 | txt += "\n"; 773 | } 774 | messagesBox->setText(txt + QDateTime::currentDateTime().toString() + " :: Page not fully loaded! Loosed network connection or page load timeout."); 775 | } 776 | 777 | // Don't do any action 778 | return; 779 | } 780 | 781 | progress = 100; 782 | adjustTitle(view->title()); 783 | 784 | if (messagesBox) { 785 | if (!messagesBox->text().length() && !messagesBox->isHidden() ) { 786 | messagesBox->hide(); 787 | } 788 | } 789 | 790 | if (loadProgress) { 791 | loadProgress->hide(); 792 | } 793 | 794 | // On AJAX it's triggered too? 795 | if (isUrlRealyChanged) { 796 | // 1. Hide scrollbars (and add some styles) 797 | if (!isScrollBarsHidden) { 798 | isScrollBarsHidden = hideScrollbars(); 799 | } 800 | if (!isSelectionDisabled) { 801 | isSelectionDisabled = disableSelection(); 802 | } 803 | // 2. Add more styles which can override previous styles... 804 | attachStyles(); 805 | attachJavascripts(); 806 | 807 | view->page()->mainFrame()->evaluateJavaScript("console.log('Test console log catchup by Qwk');"); 808 | 809 | // 3. Focus window and click into it to stimulate event loop after signal handling 810 | putWindowUp(); 811 | } 812 | } 813 | 814 | /** 815 | * @return bool - true - if don't need to hide scrollbars or hide them, false - if need, but there is no html body loaded. 816 | * @brief MainWindow::hideScrollbars 817 | */ 818 | bool MainWindow::hideScrollbars() 819 | { 820 | qDebug("MainWindow::hideScrollbars"); 821 | 822 | if (qwkSettings->getBool("view/hide_scrollbars")) { 823 | qDebug("Try to hide scrollbars..."); 824 | 825 | view->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff ); 826 | view->page()->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff ); 827 | } 828 | 829 | return true; 830 | } 831 | 832 | bool MainWindow::disableSelection() 833 | { 834 | qDebug("MainWindow::disableSelection"); 835 | 836 | if (qwkSettings->getBool("view/disable_selection")) { 837 | qDebug("Try to disable text selection..."); 838 | 839 | // Then webkit loads page and it's "empty" - empty html DOM loaded... 840 | // So we wait before real page DOM loaded... 841 | QWebElement bodyElem = view->page()->mainFrame()->findFirstElement("body"); 842 | if (!bodyElem.isNull() && !bodyElem.toInnerXml().trimmed().isEmpty()) { 843 | QWebElement headElem = view->page()->mainFrame()->findFirstElement("head"); 844 | if (headElem.isNull() || headElem.toInnerXml().trimmed().isEmpty()) { 845 | qDebug("... html head not loaded ... wait..."); 846 | return false; 847 | } 848 | 849 | //qDebug() << "... head element content:\n" << headElem.toInnerXml(); 850 | 851 | // http://stackoverflow.com/a/5313735 852 | QString content; 853 | content = "\n"; 861 | 862 | // Ugly hack, but it's works... 863 | if (!headElem.toInnerXml().contains(content)) { 864 | headElem.setInnerXml(headElem.toInnerXml() + content); 865 | qDebug("... html head loaded ... hack inserted..."); 866 | } else { 867 | qDebug("... html head loaded ... hack already inserted..."); 868 | } 869 | 870 | //headElem = view->page()->mainFrame()->findFirstElement("head"); 871 | //qDebug() << "... head element content after:\n" << headElem.toInnerXml() ; 872 | 873 | } else { 874 | qDebug("... html body not loaded ... wait..."); 875 | return false; 876 | } 877 | } 878 | 879 | return true; 880 | } 881 | 882 | void MainWindow::attachJavascripts() 883 | { 884 | qDebug("MainWindow::attachJavascripts"); 885 | 886 | QStringList scripts = qwkSettings->getQStringList("attach/javascripts"); 887 | if (!scripts.length()) { 888 | return; 889 | } 890 | 891 | QWebElement bodyElem = view->page()->mainFrame()->findFirstElement("body"); 892 | if (bodyElem.isNull() || bodyElem.toInnerXml().trimmed().isEmpty()) { 893 | // No body here... We need something in to interact with? 894 | return; 895 | } 896 | 897 | QString content = ""; 898 | QStringListIterator scriptsIterator(scripts); 899 | QFileInfo finfo = QFileInfo(); 900 | QString file_name; 901 | quint32 countScripts = 0; 902 | 903 | while (scriptsIterator.hasNext()) { 904 | file_name = scriptsIterator.next(); 905 | 906 | if (!file_name.trimmed().length()) continue; 907 | 908 | qDebug() << "-- attach " << file_name; 909 | 910 | countScripts++; 911 | 912 | finfo.setFile(file_name); 913 | if (finfo.isFile()) { 914 | qDebug("-- it's local file"); 915 | QFile f(file_name); 916 | content += "\n\n"; 919 | f.close(); 920 | } else { 921 | qDebug("-- it's remote file"); 922 | content += "\n\n"; 925 | } 926 | } 927 | if (countScripts > 0 && content.trimmed().length() > 0) { 928 | bodyElem.setInnerXml(bodyElem.toInnerXml() + content); 929 | 930 | qDebug() << "Page loaded, found " << countScripts << " user javascript files..."; 931 | } 932 | } 933 | 934 | void MainWindow::attachStyles() 935 | { 936 | qDebug("MainWindow::attachStyles"); 937 | 938 | QStringList styles = qwkSettings->getQStringList("attach/styles"); 939 | if (!styles.length()) { 940 | return; 941 | } 942 | 943 | QWebElement headElem = view->page()->mainFrame()->findFirstElement("head"); 944 | if (headElem.isNull() || headElem.toInnerXml().trimmed().isEmpty()) { 945 | // Page without head... We need something in to interact with? 946 | return; 947 | } 948 | 949 | QString content = ""; 950 | QStringListIterator stylesIterator(styles); 951 | QString file_name; 952 | QFileInfo finfo = QFileInfo(); 953 | quint32 countStyles = 0; 954 | 955 | while (stylesIterator.hasNext()) { 956 | file_name = stylesIterator.next(); 957 | 958 | if (!file_name.trimmed().length()) continue; 959 | 960 | qDebug() << "-- attach " << file_name; 961 | countStyles++; 962 | 963 | finfo.setFile(file_name); 964 | 965 | if (finfo.isFile()) { 966 | qDebug("-- it's local file"); 967 | QFile f(file_name); 968 | content += "\n\n"; 971 | f.close(); 972 | } else { 973 | qDebug("-- it's remote file"); 974 | content += "\n\n"; 977 | } 978 | } 979 | 980 | if (countStyles > 0 && content.trimmed().length() > 0) { 981 | headElem.setInnerXml(headElem.toInnerXml() + content); 982 | 983 | qDebug() << "Page loaded, found " << countStyles << " user style files..."; 984 | } 985 | } 986 | 987 | // ----------------------- SIGNALS ----------------------------- 988 | 989 | /** 990 | * Force quit on Unix SIGTERM or SIGINT signals 991 | * @brief MainWindow::unixSignalQuit 992 | */ 993 | void MainWindow::unixSignalQuit() 994 | { 995 | // No cache clean - quick exit 996 | qDebug(">> Quit Signal catched. Exiting..."); 997 | QApplication::exit(0); 998 | } 999 | 1000 | /** 1001 | * Activate window after signal 1002 | */ 1003 | void MainWindow::putWindowUp() 1004 | { 1005 | qDebug("Try to activate window..."); 1006 | 1007 | QApplication::setActiveWindow(this); 1008 | this->focusWidget(); 1009 | 1010 | #ifdef USE_TESTLIB 1011 | qDebug("... by click simulation..."); 1012 | simulateClick->clear(); 1013 | simulateClick->addMouseClick(Qt::LeftButton, 0, this->pos(), -1); 1014 | simulateClick->simulate(this); 1015 | #endif 1016 | 1017 | } 1018 | 1019 | /** 1020 | * Do something on Unix SIGHUP signal 1021 | * Usualy: 1022 | * 1. Reload config 1023 | * 1024 | * @brief MainWindow::unixSignalHup 1025 | */ 1026 | void MainWindow::unixSignalHup() 1027 | { 1028 | if (cmdopts->getValue("config") || cmdopts->getValue('c')) { 1029 | qDebug(">> Config option in command prompt..."); 1030 | QString cfgPath = cmdopts->getValue('c'); 1031 | if (cfgPath.isEmpty()) { 1032 | cfgPath = cmdopts->getValue("config"); 1033 | } 1034 | qwkSettings->loadSettings(cfgPath); 1035 | } else { 1036 | qwkSettings->loadSettings(QString("")); 1037 | } 1038 | } 1039 | 1040 | /** 1041 | * Do something on Unix SIGUSR1 signal 1042 | * Usualy: 1043 | * 1. Reload config and load home page URI 1044 | * 2. If option 'signals/SIGUSR1' defined and not empty - try to load defined URI 1045 | * 1046 | * @brief MainWindow::unixSignalUsr1 1047 | */ 1048 | void MainWindow::unixSignalUsr1() 1049 | { 1050 | if (!qwkSettings->getQString("signals/SIGUSR1").isEmpty()) { 1051 | qDebug(">> SIGUSR1 >> Load URI from config file..."); 1052 | view->loadCustomPage(qwkSettings->getQString("signals/SIGUSR1")); 1053 | } else { 1054 | qDebug(">> SIGUSR1 >> Load config file..."); 1055 | if (cmdopts->getValue("config") || cmdopts->getValue('c')) { 1056 | qDebug(">> Config option in command prompt..."); 1057 | QString cfgPath = cmdopts->getValue('c'); 1058 | if (cfgPath.isEmpty()) { 1059 | cfgPath = cmdopts->getValue("config"); 1060 | } 1061 | qwkSettings->loadSettings(cfgPath); 1062 | } else { 1063 | qwkSettings->loadSettings(QString("")); 1064 | } 1065 | view->loadHomepage(); 1066 | } 1067 | } 1068 | 1069 | /** 1070 | * Do something on Unix SIGUSR2 signal 1071 | * Usualy: 1072 | * 1. Load home page URI 1073 | * 2. If option 'signals/SIGUSR2' defined and not empty - try to load defined URI 1074 | * 1075 | * @brief MainWindow::unixSignalUsr2 1076 | */ 1077 | void MainWindow::unixSignalUsr2() 1078 | { 1079 | if (!qwkSettings->getQString("signals/SIGUSR2").isEmpty()) { 1080 | qDebug(">> SIGUSR2 >> Load URI from config file..."); 1081 | view->loadCustomPage(qwkSettings->getQString("signals/SIGUSR2")); 1082 | } else { 1083 | qDebug(">> SIGUSR2 >> Load homepage URI..."); 1084 | view->loadHomepage(); 1085 | } 1086 | } 1087 | 1088 | // ----------------------- NETWORK ----------------------------- 1089 | 1090 | /** 1091 | * @brief MainWindow::networkStateChanged 1092 | * It's triggered if global network online status changed 1093 | * @param state 1094 | */ 1095 | void MainWindow::networkStateChanged(QNetworkSession::State state) 1096 | { 1097 | qDebug() << QDateTime::currentDateTime().toString() 1098 | << "MainWindow::networkStateChanged -" 1099 | << state 1100 | ; 1101 | bool doReload = false; 1102 | if (state == QNetworkSession::Connected) { 1103 | // Reload current page, network here again! 1104 | doReload = true; 1105 | } 1106 | QString errStr = ""; 1107 | switch (state) { 1108 | case QNetworkSession::NotAvailable: 1109 | errStr = "Network not available! Check your cable!"; 1110 | doReload = true; 1111 | break; 1112 | case QNetworkSession::Disconnected: 1113 | errStr = "Network is down! Check your network settings!"; 1114 | doReload = true; 1115 | break; 1116 | default: 1117 | break; 1118 | } 1119 | if (doReload) { 1120 | 1121 | bool hasLoFace = false; 1122 | foreach (QNetworkInterface interface, network_interface->allInterfaces()) { 1123 | if ((interface.flags() & QNetworkInterface::IsUp) && 1124 | (interface.flags() & QNetworkInterface::IsRunning) && 1125 | (interface.flags() & QNetworkInterface::IsLoopBack) 1126 | ) 1127 | hasLoFace = true; 1128 | } 1129 | 1130 | if (hasLoFace && view->page()->networkAccessManager()->networkAccessible() != QNetworkAccessManager::Accessible) { 1131 | 1132 | qDebug() << QDateTime::currentDateTime().toString() 1133 | << "MainWindow::networkStateChanged -" 1134 | << "Has loopBack interface and network not accessible? Force accessible state!" 1135 | ; 1136 | 1137 | // force network accessibility to get local content 1138 | view->page()->networkAccessManager()->setNetworkAccessible(QNetworkAccessManager::Accessible); 1139 | // force NetSession restart 1140 | n_session->close(); 1141 | n_session->open(); 1142 | errStr += QString("\nNetwork session restarted!"); 1143 | } 1144 | 1145 | qint32 delay_reload = qwkSettings->getInt("browser/network_error_reload_delay", 15000); 1146 | 1147 | if (delay_reload >= 0) { 1148 | qDebug() << QDateTime::currentDateTime().toString() 1149 | << "MainWindow::networkStateChanged -" 1150 | << "Delay WebView reload by" << delay_reload/1000. << "msec." 1151 | ; 1152 | 1153 | errStr += QString("\nPage reload queued! Plase wait ") + QVariant(delay_reload / 1000.).toString() + QString(" seconds..."); 1154 | delayedLoad->singleShot(delay_reload, this, SLOT(delayedPageReload())); 1155 | } 1156 | } 1157 | if (errStr.length()) { 1158 | if (messagesBox) { 1159 | messagesBox->show(); 1160 | QString txt = messagesBox->text(); 1161 | if (txt.length()) { 1162 | txt += "\n"; 1163 | } 1164 | messagesBox->setText(txt + QDateTime::currentDateTime().toString() + " :: " + errStr); 1165 | } 1166 | } 1167 | } 1168 | 1169 | void MainWindow::handleQwkNetworkReplyUrl(QUrl url) 1170 | { 1171 | qDebug() << QDateTime::currentDateTime().toString() 1172 | << "MainWindow::handleQwkNetworkReplyUrl - " 1173 | << "url=" << url.toString() 1174 | ; 1175 | } 1176 | --------------------------------------------------------------------------------