├── .tag ├── 3rdparty └── qtsingleapplication │ ├── CMakeLists.txt │ ├── QtLockedFile │ ├── QtSingleApplication │ ├── qtlocalpeer.cpp │ ├── qtlocalpeer.h │ ├── qtlockedfile.cpp │ ├── qtlockedfile.h │ ├── qtlockedfile_unix.cpp │ ├── qtlockedfile_win.cpp │ ├── qtsingleapplication.cpp │ ├── qtsingleapplication.h │ ├── qtsinglecoreapplication.cpp │ └── qtsinglecoreapplication.h ├── AUTHORS.md ├── CMakeLists.txt ├── LICENSE.BSD ├── LICENSE.GPLv3 ├── README.md ├── dist └── flatpak │ └── io.liri.Browser.json ├── res ├── CMakeLists.txt ├── icons │ ├── 128x128 │ │ └── apps │ │ │ └── io.liri.Browser.png │ ├── 16x16 │ │ └── apps │ │ │ └── io.liri.Browser.png │ ├── 192x192 │ │ └── apps │ │ │ └── io.liri.Browser.png │ ├── 256x256 │ │ └── apps │ │ │ └── io.liri.Browser.png │ ├── 32x32 │ │ └── apps │ │ │ └── io.liri.Browser.png │ ├── 512x512 │ │ └── apps │ │ │ └── io.liri.Browser.png │ ├── 64x64 │ │ └── apps │ │ │ └── io.liri.Browser.png │ └── scalable │ │ └── apps │ │ └── io.liri.Browser.svg ├── io.liri.Browser.desktop └── translations │ ├── browser.ts │ ├── browser_ar.ts │ ├── browser_ca.ts │ ├── browser_da.ts │ ├── browser_de.ts │ ├── browser_el.ts │ ├── browser_es.ts │ ├── browser_es_MX.ts │ ├── browser_fr.ts │ ├── browser_id.ts │ ├── browser_it.ts │ ├── browser_it_IT.ts │ ├── browser_ja.ts │ ├── browser_lt.ts │ ├── browser_nl.ts │ ├── browser_pl.ts │ ├── browser_pt_BR.ts │ ├── browser_ru.ts │ ├── browser_tr.ts │ ├── browser_zh_CN.ts │ └── browser_zh_TW.ts ├── snap └── snapcraft.yaml └── src ├── 3rdparty └── regex-weburl │ ├── README │ ├── qmldir │ ├── regex-weburl.js │ └── regex-weburl.qrc ├── CMakeLists.txt ├── core ├── global │ └── paths.h ├── models │ ├── downloadsmodel.cpp │ ├── downloadsmodel.h │ ├── tab.cpp │ ├── tab.h │ ├── tabsmodel.cpp │ └── tabsmodel.h ├── session │ ├── session.cpp │ ├── session.h │ ├── tabstate.cpp │ └── tabstate.h ├── settings │ ├── searchconfig.cpp │ ├── searchconfig.h │ ├── settings.cpp │ ├── settings.h │ ├── startconfig.cpp │ ├── startconfig.h │ ├── themeconfig.cpp │ └── themeconfig.h └── utils │ ├── darkthemetimer.cpp │ └── darkthemetimer.h ├── main ├── browserapplication.cpp ├── browserapplication.h ├── mac │ ├── MacOsEventListener.h │ └── MacOsEventListener.mm └── main.cpp └── ui ├── Main.qml ├── components └── ActionBar.qml ├── drawer ├── Drawer.qml ├── DrawerContentItem.qml └── content │ └── downloads │ ├── DownloadItemDelegate.qml │ └── DrawerDownloadsContent.qml ├── expansionbar ├── ExpansionBar.qml └── ExpansionBarItem.qml ├── omnibox └── Omnibox.qml ├── overlay ├── BaseOverlay.qml └── SearchOverlay.qml ├── qmldir ├── tabview ├── TabActionManager.qml ├── TabBar.qml ├── TabBarActionBar.qml ├── TabContent.qml ├── TabContentView.qml ├── TabController.qml ├── TabDelegate.qml ├── TabIndicator.qml ├── TabPage.qml ├── TabType.qml ├── TabView.qml └── content │ ├── SettingsContent.qml │ └── WebContent.qml ├── toolbar └── Toolbar.qml ├── ui.qrc ├── utils ├── ColorUtils.qml ├── UrlUtils.qml └── qmldir └── window ├── BrowserWindow.qml └── ShortcutManager.qml /.tag: -------------------------------------------------------------------------------- 1 | add11f501ce269c1dcf26532d708322bf6a7b72f 2 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(qtsingleapplication STATIC 2 | qtlocalpeer.cpp 3 | qtlocalpeer.h 4 | QtLockedFile 5 | qtlockedfile.h 6 | QtSingleApplication 7 | qtsingleapplication.cpp 8 | qtsingleapplication.h 9 | qtsinglecoreapplication.cpp 10 | qtsinglecoreapplication.h 11 | ) 12 | target_link_libraries(qtsingleapplication 13 | PUBLIC 14 | Qt5::Widgets 15 | Qt5::Network 16 | ) 17 | target_include_directories(qtsingleapplication 18 | PUBLIC 19 | "${CMAKE_CURRENT_SOURCE_DIR}" 20 | ) 21 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/QtLockedFile: -------------------------------------------------------------------------------- 1 | #include "qtlockedfile.h" 2 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/QtSingleApplication: -------------------------------------------------------------------------------- 1 | #include "qtsingleapplication.h" 2 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/qtlocalpeer.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | #include "qtlocalpeer.h" 43 | #include 44 | #include 45 | #include 46 | 47 | #if defined(Q_OS_WIN) 48 | #include 49 | #include 50 | typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); 51 | static PProcessIdToSessionId pProcessIdToSessionId = 0; 52 | #endif 53 | #if defined(Q_OS_UNIX) 54 | #include 55 | #include 56 | #include 57 | #endif 58 | 59 | namespace QtLP_Private { 60 | #include "qtlockedfile.cpp" 61 | #if defined(Q_OS_WIN) 62 | #include "qtlockedfile_win.cpp" 63 | #else 64 | #include "qtlockedfile_unix.cpp" 65 | #endif 66 | } 67 | 68 | const char* QtLocalPeer::ack = "ack"; 69 | 70 | QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) 71 | : QObject(parent), id(appId) 72 | { 73 | QString prefix = id; 74 | if (id.isEmpty()) { 75 | id = QCoreApplication::applicationFilePath(); 76 | #if defined(Q_OS_WIN) 77 | id = id.toLower(); 78 | #endif 79 | prefix = id.section(QLatin1Char('/'), -1); 80 | } 81 | prefix.remove(QRegExp("[^a-zA-Z]")); 82 | prefix.truncate(6); 83 | 84 | QByteArray idc = id.toUtf8(); 85 | quint16 idNum = qChecksum(idc.constData(), idc.size()); 86 | socketName = QLatin1String("qtsingleapp-") + prefix 87 | + QLatin1Char('-') + QString::number(idNum, 16); 88 | 89 | #if defined(Q_OS_WIN) 90 | if (!pProcessIdToSessionId) { 91 | QLibrary lib("kernel32"); 92 | pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); 93 | } 94 | if (pProcessIdToSessionId) { 95 | DWORD sessionId = 0; 96 | pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); 97 | socketName += QLatin1Char('-') + QString::number(sessionId, 16); 98 | } 99 | #else 100 | socketName += QLatin1Char('-') + QString::number(::getuid(), 16); 101 | #endif 102 | 103 | server = new QLocalServer(this); 104 | QString lockName = QDir(QDir::tempPath()).absolutePath() 105 | + QLatin1Char('/') + socketName 106 | + QLatin1String("-lockfile"); 107 | lockFile.setFileName(lockName); 108 | lockFile.open(QIODevice::ReadWrite); 109 | } 110 | 111 | 112 | 113 | bool QtLocalPeer::isClient() 114 | { 115 | if (lockFile.isLocked()) 116 | return false; 117 | 118 | if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) 119 | return true; 120 | 121 | bool res = server->listen(socketName); 122 | #if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) 123 | // ### Workaround 124 | if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { 125 | QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); 126 | res = server->listen(socketName); 127 | } 128 | #endif 129 | if (!res) 130 | qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); 131 | QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); 132 | return false; 133 | } 134 | 135 | 136 | bool QtLocalPeer::sendMessage(const QString &message, int timeout) 137 | { 138 | if (!isClient()) 139 | return false; 140 | 141 | QLocalSocket socket; 142 | bool connOk = false; 143 | for(int i = 0; i < 2; i++) { 144 | // Try twice, in case the other instance is just starting up 145 | socket.connectToServer(socketName); 146 | connOk = socket.waitForConnected(timeout/2); 147 | if (connOk || i) 148 | break; 149 | int ms = 250; 150 | #if defined(Q_OS_WIN) 151 | Sleep(DWORD(ms)); 152 | #else 153 | struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; 154 | nanosleep(&ts, NULL); 155 | #endif 156 | } 157 | if (!connOk) 158 | return false; 159 | 160 | QByteArray uMsg(message.toUtf8()); 161 | QDataStream ds(&socket); 162 | ds.writeBytes(uMsg.constData(), uMsg.size()); 163 | bool res = socket.waitForBytesWritten(timeout); 164 | if (res) { 165 | res &= socket.waitForReadyRead(timeout); // wait for ack 166 | if (res) 167 | res &= (socket.read(qstrlen(ack)) == ack); 168 | } 169 | return res; 170 | } 171 | 172 | 173 | void QtLocalPeer::receiveConnection() 174 | { 175 | QLocalSocket* socket = server->nextPendingConnection(); 176 | if (!socket) 177 | return; 178 | 179 | while (true) { 180 | if (socket->state() == QLocalSocket::UnconnectedState) { 181 | qWarning("QtLocalPeer: Peer disconnected"); 182 | delete socket; 183 | return; 184 | } 185 | if (socket->bytesAvailable() >= qint64(sizeof(quint32))) 186 | break; 187 | socket->waitForReadyRead(); 188 | } 189 | 190 | QDataStream ds(socket); 191 | QByteArray uMsg; 192 | quint32 remaining; 193 | ds >> remaining; 194 | uMsg.resize(remaining); 195 | int got = 0; 196 | char* uMsgBuf = uMsg.data(); 197 | do { 198 | got = ds.readRawData(uMsgBuf, remaining); 199 | remaining -= got; 200 | uMsgBuf += got; 201 | } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); 202 | if (got < 0) { 203 | qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); 204 | delete socket; 205 | return; 206 | } 207 | QString message(QString::fromUtf8(uMsg)); 208 | socket->write(ack, qstrlen(ack)); 209 | socket->waitForBytesWritten(1000); 210 | socket->waitForDisconnected(1000); // make sure client reads ack 211 | delete socket; 212 | emit messageReceived(message); //### (might take a long time to return) 213 | } 214 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/qtlocalpeer.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTLOCALPEER_H 42 | #define QTLOCALPEER_H 43 | 44 | #include 45 | #include 46 | #include 47 | 48 | #include "qtlockedfile.h" 49 | 50 | class QtLocalPeer : public QObject 51 | { 52 | Q_OBJECT 53 | 54 | public: 55 | QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); 56 | bool isClient(); 57 | bool sendMessage(const QString &message, int timeout); 58 | QString applicationId() const 59 | { return id; } 60 | 61 | Q_SIGNALS: 62 | void messageReceived(const QString &message); 63 | 64 | protected Q_SLOTS: 65 | void receiveConnection(); 66 | 67 | protected: 68 | QString id; 69 | QString socketName; 70 | QLocalServer* server; 71 | QtLP_Private::QtLockedFile lockFile; 72 | 73 | private: 74 | static const char* ack; 75 | }; 76 | 77 | #endif // QTLOCALPEER_H 78 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/qtlockedfile.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #include "qtlockedfile.h" 42 | 43 | /*! 44 | \class QtLockedFile 45 | 46 | \brief The QtLockedFile class extends QFile with advisory locking 47 | functions. 48 | 49 | A file may be locked in read or write mode. Multiple instances of 50 | \e QtLockedFile, created in multiple processes running on the same 51 | machine, may have a file locked in read mode. Exactly one instance 52 | may have it locked in write mode. A read and a write lock cannot 53 | exist simultaneously on the same file. 54 | 55 | The file locks are advisory. This means that nothing prevents 56 | another process from manipulating a locked file using QFile or 57 | file system functions offered by the OS. Serialization is only 58 | guaranteed if all processes that access the file use 59 | QLockedFile. Also, while holding a lock on a file, a process 60 | must not open the same file again (through any API), or locks 61 | can be unexpectedly lost. 62 | 63 | The lock provided by an instance of \e QtLockedFile is released 64 | whenever the program terminates. This is true even when the 65 | program crashes and no destructors are called. 66 | */ 67 | 68 | /*! \enum QtLockedFile::LockMode 69 | 70 | This enum describes the available lock modes. 71 | 72 | \value ReadLock A read lock. 73 | \value WriteLock A write lock. 74 | \value NoLock Neither a read lock nor a write lock. 75 | */ 76 | 77 | /*! 78 | Constructs an unlocked \e QtLockedFile object. This constructor 79 | behaves in the same way as \e QFile::QFile(). 80 | 81 | \sa QFile::QFile() 82 | */ 83 | QtLockedFile::QtLockedFile() 84 | : QFile() 85 | { 86 | #ifdef Q_OS_WIN 87 | wmutex = 0; 88 | rmutex = 0; 89 | #endif 90 | m_lock_mode = NoLock; 91 | } 92 | 93 | /*! 94 | Constructs an unlocked QtLockedFile object with file \a name. This 95 | constructor behaves in the same way as \e QFile::QFile(const 96 | QString&). 97 | 98 | \sa QFile::QFile() 99 | */ 100 | QtLockedFile::QtLockedFile(const QString &name) 101 | : QFile(name) 102 | { 103 | #ifdef Q_OS_WIN 104 | wmutex = 0; 105 | rmutex = 0; 106 | #endif 107 | m_lock_mode = NoLock; 108 | } 109 | 110 | /*! 111 | Opens the file in OpenMode \a mode. 112 | 113 | This is identical to QFile::open(), with the one exception that the 114 | Truncate mode flag is disallowed. Truncation would conflict with the 115 | advisory file locking, since the file would be modified before the 116 | write lock is obtained. If truncation is required, use resize(0) 117 | after obtaining the write lock. 118 | 119 | Returns true if successful; otherwise false. 120 | 121 | \sa QFile::open(), QFile::resize() 122 | */ 123 | bool QtLockedFile::open(OpenMode mode) 124 | { 125 | if (mode & QIODevice::Truncate) { 126 | qWarning("QtLockedFile::open(): Truncate mode not allowed."); 127 | return false; 128 | } 129 | return QFile::open(mode); 130 | } 131 | 132 | /*! 133 | Returns \e true if this object has a in read or write lock; 134 | otherwise returns \e false. 135 | 136 | \sa lockMode() 137 | */ 138 | bool QtLockedFile::isLocked() const 139 | { 140 | return m_lock_mode != NoLock; 141 | } 142 | 143 | /*! 144 | Returns the type of lock currently held by this object, or \e 145 | QtLockedFile::NoLock. 146 | 147 | \sa isLocked() 148 | */ 149 | QtLockedFile::LockMode QtLockedFile::lockMode() const 150 | { 151 | return m_lock_mode; 152 | } 153 | 154 | /*! 155 | \fn bool QtLockedFile::lock(LockMode mode, bool block = true) 156 | 157 | Obtains a lock of type \a mode. The file must be opened before it 158 | can be locked. 159 | 160 | If \a block is true, this function will block until the lock is 161 | aquired. If \a block is false, this function returns \e false 162 | immediately if the lock cannot be aquired. 163 | 164 | If this object already has a lock of type \a mode, this function 165 | returns \e true immediately. If this object has a lock of a 166 | different type than \a mode, the lock is first released and then a 167 | new lock is obtained. 168 | 169 | This function returns \e true if, after it executes, the file is 170 | locked by this object, and \e false otherwise. 171 | 172 | \sa unlock(), isLocked(), lockMode() 173 | */ 174 | 175 | /*! 176 | \fn bool QtLockedFile::unlock() 177 | 178 | Releases a lock. 179 | 180 | If the object has no lock, this function returns immediately. 181 | 182 | This function returns \e true if, after it executes, the file is 183 | not locked by this object, and \e false otherwise. 184 | 185 | \sa lock(), isLocked(), lockMode() 186 | */ 187 | 188 | /*! 189 | \fn QtLockedFile::~QtLockedFile() 190 | 191 | Destroys the \e QtLockedFile object. If any locks were held, they 192 | are released. 193 | */ 194 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/qtlockedfile.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTLOCKEDFILE_H 42 | #define QTLOCKEDFILE_H 43 | 44 | #include 45 | #ifdef Q_OS_WIN 46 | #include 47 | #endif 48 | 49 | #if defined(Q_OS_WIN) 50 | # if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) 51 | # define QT_QTLOCKEDFILE_EXPORT 52 | # elif defined(QT_QTLOCKEDFILE_IMPORT) 53 | # if defined(QT_QTLOCKEDFILE_EXPORT) 54 | # undef QT_QTLOCKEDFILE_EXPORT 55 | # endif 56 | # define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) 57 | # elif defined(QT_QTLOCKEDFILE_EXPORT) 58 | # undef QT_QTLOCKEDFILE_EXPORT 59 | # define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) 60 | # endif 61 | #else 62 | # define QT_QTLOCKEDFILE_EXPORT 63 | #endif 64 | 65 | namespace QtLP_Private { 66 | 67 | class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile 68 | { 69 | public: 70 | enum LockMode { NoLock = 0, ReadLock, WriteLock }; 71 | 72 | QtLockedFile(); 73 | QtLockedFile(const QString &name); 74 | ~QtLockedFile(); 75 | 76 | bool open(OpenMode mode); 77 | 78 | bool lock(LockMode mode, bool block = true); 79 | bool unlock(); 80 | bool isLocked() const; 81 | LockMode lockMode() const; 82 | 83 | private: 84 | #ifdef Q_OS_WIN 85 | Qt::HANDLE wmutex; 86 | Qt::HANDLE rmutex; 87 | QVector rmutexes; 88 | QString mutexname; 89 | 90 | Qt::HANDLE getMutexHandle(int idx, bool doCreate); 91 | bool waitMutex(Qt::HANDLE mutex, bool doBlock); 92 | 93 | #endif 94 | LockMode m_lock_mode; 95 | }; 96 | } 97 | #endif 98 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/qtlockedfile_unix.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "qtlockedfile.h" 47 | 48 | bool QtLockedFile::lock(LockMode mode, bool block) 49 | { 50 | if (!isOpen()) { 51 | qWarning("QtLockedFile::lock(): file is not opened"); 52 | return false; 53 | } 54 | 55 | if (mode == NoLock) 56 | return unlock(); 57 | 58 | if (mode == m_lock_mode) 59 | return true; 60 | 61 | if (m_lock_mode != NoLock) 62 | unlock(); 63 | 64 | struct flock fl; 65 | fl.l_whence = SEEK_SET; 66 | fl.l_start = 0; 67 | fl.l_len = 0; 68 | fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; 69 | int cmd = block ? F_SETLKW : F_SETLK; 70 | int ret = fcntl(handle(), cmd, &fl); 71 | 72 | if (ret == -1) { 73 | if (errno != EINTR && errno != EAGAIN) 74 | qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); 75 | return false; 76 | } 77 | 78 | 79 | m_lock_mode = mode; 80 | return true; 81 | } 82 | 83 | 84 | bool QtLockedFile::unlock() 85 | { 86 | if (!isOpen()) { 87 | qWarning("QtLockedFile::unlock(): file is not opened"); 88 | return false; 89 | } 90 | 91 | if (!isLocked()) 92 | return true; 93 | 94 | struct flock fl; 95 | fl.l_whence = SEEK_SET; 96 | fl.l_start = 0; 97 | fl.l_len = 0; 98 | fl.l_type = F_UNLCK; 99 | int ret = fcntl(handle(), F_SETLKW, &fl); 100 | 101 | if (ret == -1) { 102 | qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); 103 | return false; 104 | } 105 | 106 | m_lock_mode = NoLock; 107 | return true; 108 | } 109 | 110 | QtLockedFile::~QtLockedFile() 111 | { 112 | if (isOpen()) 113 | unlock(); 114 | } 115 | 116 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/qtlockedfile_win.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #include "qtlockedfile.h" 42 | #include 43 | #include 44 | 45 | #define MUTEX_PREFIX "QtLockedFile mutex " 46 | // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS 47 | #define MAX_READERS MAXIMUM_WAIT_OBJECTS 48 | 49 | #if QT_VERSION >= 0x050000 50 | #define QT_WA(unicode, ansi) unicode 51 | #endif 52 | 53 | Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) 54 | { 55 | if (mutexname.isEmpty()) { 56 | QFileInfo fi(*this); 57 | mutexname = QString::fromLatin1(MUTEX_PREFIX) 58 | + fi.absoluteFilePath().toLower(); 59 | } 60 | QString mname(mutexname); 61 | if (idx >= 0) 62 | mname += QString::number(idx); 63 | 64 | Qt::HANDLE mutex; 65 | if (doCreate) { 66 | QT_WA( { mutex = CreateMutexW(NULL, FALSE, (TCHAR*)mname.utf16()); }, 67 | { mutex = CreateMutexA(NULL, FALSE, mname.toLocal8Bit().constData()); } ); 68 | if (!mutex) { 69 | qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); 70 | return 0; 71 | } 72 | } 73 | else { 74 | QT_WA( { mutex = OpenMutexW(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, (TCHAR*)mname.utf16()); }, 75 | { mutex = OpenMutexA(SYNCHRONIZE | MUTEX_MODIFY_STATE, FALSE, mname.toLocal8Bit().constData()); } ); 76 | if (!mutex) { 77 | if (GetLastError() != ERROR_FILE_NOT_FOUND) 78 | qErrnoWarning("QtLockedFile::lock(): OpenMutex failed"); 79 | return 0; 80 | } 81 | } 82 | return mutex; 83 | } 84 | 85 | bool QtLockedFile::waitMutex(Qt::HANDLE mutex, bool doBlock) 86 | { 87 | Q_ASSERT(mutex); 88 | DWORD res = WaitForSingleObject(mutex, doBlock ? INFINITE : 0); 89 | switch (res) { 90 | case WAIT_OBJECT_0: 91 | case WAIT_ABANDONED: 92 | return true; 93 | break; 94 | case WAIT_TIMEOUT: 95 | break; 96 | default: 97 | qErrnoWarning("QtLockedFile::lock(): WaitForSingleObject failed"); 98 | } 99 | return false; 100 | } 101 | 102 | 103 | 104 | bool QtLockedFile::lock(LockMode mode, bool block) 105 | { 106 | if (!isOpen()) { 107 | qWarning("QtLockedFile::lock(): file is not opened"); 108 | return false; 109 | } 110 | 111 | if (mode == NoLock) 112 | return unlock(); 113 | 114 | if (mode == m_lock_mode) 115 | return true; 116 | 117 | if (m_lock_mode != NoLock) 118 | unlock(); 119 | 120 | if (!wmutex && !(wmutex = getMutexHandle(-1, true))) 121 | return false; 122 | 123 | if (!waitMutex(wmutex, block)) 124 | return false; 125 | 126 | if (mode == ReadLock) { 127 | int idx = 0; 128 | for (; idx < MAX_READERS; idx++) { 129 | rmutex = getMutexHandle(idx, false); 130 | if (!rmutex || waitMutex(rmutex, false)) 131 | break; 132 | CloseHandle(rmutex); 133 | } 134 | bool ok = true; 135 | if (idx >= MAX_READERS) { 136 | qWarning("QtLockedFile::lock(): too many readers"); 137 | rmutex = 0; 138 | ok = false; 139 | } 140 | else if (!rmutex) { 141 | rmutex = getMutexHandle(idx, true); 142 | if (!rmutex || !waitMutex(rmutex, false)) 143 | ok = false; 144 | } 145 | if (!ok && rmutex) { 146 | CloseHandle(rmutex); 147 | rmutex = 0; 148 | } 149 | ReleaseMutex(wmutex); 150 | if (!ok) 151 | return false; 152 | } 153 | else { 154 | Q_ASSERT(rmutexes.isEmpty()); 155 | for (int i = 0; i < MAX_READERS; i++) { 156 | Qt::HANDLE mutex = getMutexHandle(i, false); 157 | if (mutex) 158 | rmutexes.append(mutex); 159 | } 160 | if (rmutexes.size()) { 161 | DWORD res = WaitForMultipleObjects(rmutexes.size(), rmutexes.constData(), 162 | TRUE, block ? INFINITE : 0); 163 | if (res != WAIT_OBJECT_0 && res != WAIT_ABANDONED) { 164 | if (res != WAIT_TIMEOUT) 165 | qErrnoWarning("QtLockedFile::lock(): WaitForMultipleObjects failed"); 166 | m_lock_mode = WriteLock; // trick unlock() to clean up - semiyucky 167 | unlock(); 168 | return false; 169 | } 170 | } 171 | } 172 | 173 | m_lock_mode = mode; 174 | return true; 175 | } 176 | 177 | bool QtLockedFile::unlock() 178 | { 179 | if (!isOpen()) { 180 | qWarning("QtLockedFile::unlock(): file is not opened"); 181 | return false; 182 | } 183 | 184 | if (!isLocked()) 185 | return true; 186 | 187 | if (m_lock_mode == ReadLock) { 188 | ReleaseMutex(rmutex); 189 | CloseHandle(rmutex); 190 | rmutex = 0; 191 | } 192 | else { 193 | foreach(Qt::HANDLE mutex, rmutexes) { 194 | ReleaseMutex(mutex); 195 | CloseHandle(mutex); 196 | } 197 | rmutexes.clear(); 198 | ReleaseMutex(wmutex); 199 | } 200 | 201 | m_lock_mode = QtLockedFile::NoLock; 202 | return true; 203 | } 204 | 205 | QtLockedFile::~QtLockedFile() 206 | { 207 | if (isOpen()) 208 | unlock(); 209 | if (wmutex) 210 | CloseHandle(wmutex); 211 | } 212 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/qtsingleapplication.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTSINGLEAPPLICATION_H 42 | #define QTSINGLEAPPLICATION_H 43 | 44 | #include 45 | 46 | class QtLocalPeer; 47 | 48 | #if defined(Q_OS_WIN) 49 | # if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) 50 | # define QT_QTSINGLEAPPLICATION_EXPORT 51 | # elif defined(QT_QTSINGLEAPPLICATION_IMPORT) 52 | # if defined(QT_QTSINGLEAPPLICATION_EXPORT) 53 | # undef QT_QTSINGLEAPPLICATION_EXPORT 54 | # endif 55 | # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) 56 | # elif defined(QT_QTSINGLEAPPLICATION_EXPORT) 57 | # undef QT_QTSINGLEAPPLICATION_EXPORT 58 | # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) 59 | # endif 60 | #else 61 | # define QT_QTSINGLEAPPLICATION_EXPORT 62 | #endif 63 | 64 | class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication 65 | { 66 | Q_OBJECT 67 | 68 | public: 69 | QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); 70 | QtSingleApplication(const QString &id, int &argc, char **argv); 71 | #if QT_VERSION < 0x050000 72 | QtSingleApplication(int &argc, char **argv, Type type); 73 | # if defined(Q_WS_X11) 74 | QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); 75 | QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); 76 | QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); 77 | # endif // Q_WS_X11 78 | #endif // QT_VERSION < 0x050000 79 | 80 | bool isRunning(); 81 | QString id() const; 82 | 83 | void setActivationWindow(QWidget* aw, bool activateOnMessage = true); 84 | QWidget* activationWindow() const; 85 | 86 | // Obsolete: 87 | void initialize(bool dummy = true) 88 | { isRunning(); Q_UNUSED(dummy) } 89 | 90 | public Q_SLOTS: 91 | bool sendMessage(const QString &message, int timeout = 5000); 92 | void activateWindow(); 93 | 94 | 95 | Q_SIGNALS: 96 | void messageReceived(const QString &message); 97 | 98 | 99 | private: 100 | void sysInit(const QString &appId = QString()); 101 | QtLocalPeer *peer; 102 | QWidget *actWin; 103 | }; 104 | 105 | #endif // QTSINGLEAPPLICATION_H 106 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | 42 | #include "qtsinglecoreapplication.h" 43 | #include "qtlocalpeer.h" 44 | 45 | /*! 46 | \class QtSingleCoreApplication qtsinglecoreapplication.h 47 | \brief A variant of the QtSingleApplication class for non-GUI applications. 48 | 49 | This class is a variant of QtSingleApplication suited for use in 50 | console (non-GUI) applications. It is an extension of 51 | QCoreApplication (instead of QApplication). It does not require 52 | the QtGui library. 53 | 54 | The API and usage is identical to QtSingleApplication, except that 55 | functions relating to the "activation window" are not present, for 56 | obvious reasons. Please refer to the QtSingleApplication 57 | documentation for explanation of the usage. 58 | 59 | A QtSingleCoreApplication instance can communicate to a 60 | QtSingleApplication instance if they share the same application 61 | id. Hence, this class can be used to create a light-weight 62 | command-line tool that sends commands to a GUI application. 63 | 64 | \sa QtSingleApplication 65 | */ 66 | 67 | /*! 68 | Creates a QtSingleCoreApplication object. The application identifier 69 | will be QCoreApplication::applicationFilePath(). \a argc and \a 70 | argv are passed on to the QCoreAppliation constructor. 71 | */ 72 | 73 | QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv) 74 | : QCoreApplication(argc, argv) 75 | { 76 | peer = new QtLocalPeer(this); 77 | connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); 78 | } 79 | 80 | 81 | /*! 82 | Creates a QtSingleCoreApplication object with the application 83 | identifier \a appId. \a argc and \a argv are passed on to the 84 | QCoreAppliation constructor. 85 | */ 86 | QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv) 87 | : QCoreApplication(argc, argv) 88 | { 89 | peer = new QtLocalPeer(this, appId); 90 | connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&))); 91 | } 92 | 93 | 94 | /*! 95 | Returns true if another instance of this application is running; 96 | otherwise false. 97 | 98 | This function does not find instances of this application that are 99 | being run by a different user (on Windows: that are running in 100 | another session). 101 | 102 | \sa sendMessage() 103 | */ 104 | 105 | bool QtSingleCoreApplication::isRunning() 106 | { 107 | return peer->isClient(); 108 | } 109 | 110 | 111 | /*! 112 | Tries to send the text \a message to the currently running 113 | instance. The QtSingleCoreApplication object in the running instance 114 | will emit the messageReceived() signal when it receives the 115 | message. 116 | 117 | This function returns true if the message has been sent to, and 118 | processed by, the current instance. If there is no instance 119 | currently running, or if the running instance fails to process the 120 | message within \a timeout milliseconds, this function return false. 121 | 122 | \sa isRunning(), messageReceived() 123 | */ 124 | 125 | bool QtSingleCoreApplication::sendMessage(const QString &message, int timeout) 126 | { 127 | return peer->sendMessage(message, timeout); 128 | } 129 | 130 | 131 | /*! 132 | Returns the application identifier. Two processes with the same 133 | identifier will be regarded as instances of the same application. 134 | */ 135 | 136 | QString QtSingleCoreApplication::id() const 137 | { 138 | return peer->applicationId(); 139 | } 140 | 141 | 142 | /*! 143 | \fn void QtSingleCoreApplication::messageReceived(const QString& message) 144 | 145 | This signal is emitted when the current instance receives a \a 146 | message from another instance of this application. 147 | 148 | \sa sendMessage() 149 | */ 150 | -------------------------------------------------------------------------------- /3rdparty/qtsingleapplication/qtsinglecoreapplication.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 4 | ** Contact: http://www.qt-project.org/legal 5 | ** 6 | ** This file is part of the Qt Solutions component. 7 | ** 8 | ** $QT_BEGIN_LICENSE:BSD$ 9 | ** You may use this file under the terms of the BSD license as follows: 10 | ** 11 | ** "Redistribution and use in source and binary forms, with or without 12 | ** modification, are permitted provided that the following conditions are 13 | ** met: 14 | ** * Redistributions of source code must retain the above copyright 15 | ** notice, this list of conditions and the following disclaimer. 16 | ** * Redistributions in binary form must reproduce the above copyright 17 | ** notice, this list of conditions and the following disclaimer in 18 | ** the documentation and/or other materials provided with the 19 | ** distribution. 20 | ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names 21 | ** of its contributors may be used to endorse or promote products derived 22 | ** from this software without specific prior written permission. 23 | ** 24 | ** 25 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 36 | ** 37 | ** $QT_END_LICENSE$ 38 | ** 39 | ****************************************************************************/ 40 | 41 | #ifndef QTSINGLECOREAPPLICATION_H 42 | #define QTSINGLECOREAPPLICATION_H 43 | 44 | #include 45 | 46 | class QtLocalPeer; 47 | 48 | class QtSingleCoreApplication : public QCoreApplication 49 | { 50 | Q_OBJECT 51 | 52 | public: 53 | QtSingleCoreApplication(int &argc, char **argv); 54 | QtSingleCoreApplication(const QString &id, int &argc, char **argv); 55 | 56 | bool isRunning(); 57 | QString id() const; 58 | 59 | public Q_SLOTS: 60 | bool sendMessage(const QString &message, int timeout = 5000); 61 | 62 | 63 | Q_SIGNALS: 64 | void messageReceived(const QString &message); 65 | 66 | 67 | private: 68 | QtLocalPeer* peer; 69 | }; 70 | 71 | #endif // QTSINGLECOREAPPLICATION_H 72 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | Liri Browser 2 | ============ 3 | 4 | # Core Developers 5 | 6 | * Tim Süberkrüb 7 | 8 | # Contributors 9 | 10 | This is the list of contributors to this code base. 11 | 12 | Names are sorted by number of commits at the time of this writing. 13 | Commit data has been generated with: 14 | 15 | ```sh 16 | git shortlog -s -e -n 17 | ``` 18 | 19 | Commit counts have been removed, since they change pretty frequently. 20 | 21 | Remember to update this file before any release is made, also make sure 22 | a .mailmap file is maintained if committer names and email addresses 23 | change over time. 24 | 25 | * Tim Süberkrüb 26 | * Ivan Fateev 27 | * Pier Luigi Fiorini 28 | * Alexander Stefanov-Khryukin 29 | * Simon Peter 30 | 31 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10.0) 2 | 3 | project("Browser" 4 | VERSION "1.2.0" 5 | DESCRIPTION "Web browser" 6 | LANGUAGES CXX C 7 | ) 8 | 9 | ## Shared macros and functions: 10 | if(BROWSER_WITH_FLUID AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/fluid/CMakeLists.txt") 11 | set(LIRI_LOCAL_ECM TRUE) 12 | set(FLUID_WITH_DOCUMENTATION FALSE) 13 | set(FLUID_WITH_DEMO FALSE) 14 | endif() 15 | if(LIRI_LOCAL_ECM) 16 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/fluid/cmake/shared/modules") 17 | else() 18 | find_package(LiriCMakeShared "2.0.0" REQUIRED NO_MODULE) 19 | list(APPEND CMAKE_MODULE_PATH "${LCS_MODULE_PATH}") 20 | endif() 21 | 22 | ## Set minimum versions required. 23 | set(QT_MIN_VERSION "5.10.0") 24 | 25 | ## Liri specific setup common for all modules: 26 | include(LiriSetup) 27 | 28 | ## Features: 29 | option(BROWSER_WITH_FLUID "Build together with Fluid" OFF) 30 | add_feature_info("Browser::WithFluid" BROWSER_WITH_FLUID "Build together with Fluid") 31 | 32 | ## Find Qt 5. 33 | find_package(Qt5 "${QT_MIN_VERSION}" 34 | CONFIG REQUIRED 35 | COMPONENTS 36 | Core 37 | Gui 38 | Svg 39 | Qml 40 | Quick 41 | QuickControls2 42 | WebEngine 43 | LinguistTools 44 | ) 45 | 46 | ## Add subdirectories: 47 | if(BROWSER_WITH_FLUID) 48 | add_subdirectory(fluid) 49 | endif() 50 | add_subdirectory(res) 51 | add_subdirectory(3rdparty/qtsingleapplication) 52 | add_subdirectory(src) 53 | -------------------------------------------------------------------------------- /LICENSE.BSD: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 2 | Contact: http://www.qt-project.org/legal 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Liri Browser 2 | ============ 3 | 4 | [![License](https://img.shields.io/badge/license-GPLv3.0-blue.svg)](https://www.gnu.org/licenses/gpl-3.0.html) 5 | [![GitHub release](https://img.shields.io/github/release/lirios/browser.svg)](https://github.com/lirios/browser) 6 | [![GitHub issues](https://img.shields.io/github/issues/lirios/browser.svg)](https://github.com/lirios/browser/issues) 7 | [![Snap Status](https://build.snapcraft.io/badge/lirios/browser.svg)](https://build.snapcraft.io/user/lirios/browser) 8 | [![CI](https://github.com/lirios/browser/workflows/CI/badge.svg?branch=develop&event=push)](https://github.com/lirios/browser/actions?query=workflow%3ACI) 9 | 10 | A cross-platform Material Design web browser. 11 | 12 | ## Dependencies 13 | 14 | Qt >= 5.10.0 with at least the following modules is required: 15 | 16 | * [qtbase](http://code.qt.io/cgit/qt/qtbase.git) 17 | * [qtdeclarative](http://code.qt.io/cgit/qt/qtdeclarative.git) 18 | * [qtquickcontrols2](http://code.qt.io/cgit/qt/qtquickcontrols2.git) 19 | * [qtwebengine](http://code.qt.io/cgit/qt/qtwebengine.git/) 20 | * [qtsvg](http://code.qt.io/cgit/qt/qtsvg.git/) 21 | * [qtgraphicaleffects](http://code.qt.io/cgit/qt/qtgraphicaleffects.git/) 22 | 23 | The following modules and their dependencies are required: 24 | 25 | * [cmake](https://gitlab.kitware.com/cmake/cmake) >= 3.10.0 26 | * [cmake-shared](https://github.com/lirios/cmake-shared.git) >= 1.0.0 27 | * [fluid](https://github.com/lirios/fluid.git) >= 1.0.0 28 | 29 | ## Installation 30 | 31 | ```sh 32 | mkdir build 33 | cd build 34 | cmake -DCMAKE_INSTALL_PREFIX=/path/to/prefix .. 35 | make 36 | make install # use sudo if necessary 37 | ``` 38 | 39 | Replace `/path/to/prefix` to your installation prefix. 40 | Default is `/usr/local`. 41 | 42 | You can also append the following options to the `cmake` command: 43 | 44 | * `-DBROWSER_WITH_FLUID:BOOL=ON`: Build with a local copy of the Fluid sources. 45 | 46 | ## Documentation 47 | 48 | Find more information in the [Liri Browser documentation](https://docs.liri.io/modules/browser/). 49 | 50 | ## Credits 51 | 52 | Many thanks to ... 53 | 54 | * [Corbin Crutchley](https://github.com/crutchcorn) for creating the application icon 55 | * [Simon Peter](https://github.com/probonopd) for adding AppImage support 56 | 57 | Please refer to [AUTHORS.md](AUTHORS.md) for a list of everyone who directly contributed code via Git. 58 | 59 | ## Licensing 60 | 61 | Contains the [QtSingleApplication](https://github.com/qtproject/qt-solutions/tree/master/qtsingleapplication) 62 | (see the `3rdparty/qtsingleapplication` folder) module which is licensed under the 3-clause BSD license (see `LICENSE.BSD`). 63 | 64 | Liri Browser is licensed under the terms of the GNU General Public License version 3 or, at your option, any later version. 65 | -------------------------------------------------------------------------------- /dist/flatpak/io.liri.Browser.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "io.liri.Browser", 3 | "branch": "master", 4 | "runtime": "org.kde.Platform", 5 | "runtime-version": "5.14", 6 | "base": "io.qt.qtwebengine.BaseApp", 7 | "base-version": "5.14", 8 | "sdk": "org.kde.Sdk", 9 | "command": "liri-browser", 10 | "tags": [ 11 | "nightly" 12 | ], 13 | "desktop-file-name-suffix": " (Nightly)", 14 | "finish-args": [ 15 | "--device=dri", 16 | "--filesystem=host", 17 | "--socket=wayland", 18 | "--socket=x11", 19 | "--socket=pulseaudio", 20 | "--share=ipc", 21 | "--share=network", 22 | "--system-talk-name=org.freedesktop.GeoClue2" 23 | ], 24 | "modules": [ 25 | { 26 | "name": "cmake-shared", 27 | "buildsystem": "cmake-ninja", 28 | "sources": [ 29 | { 30 | "type": "git", 31 | "url": "git://github.com/lirios/cmake-shared.git", 32 | "branch": "develop" 33 | } 34 | ] 35 | }, 36 | { 37 | "name": "fluid", 38 | "buildsystem": "cmake-ninja", 39 | "config-opts": [ 40 | "-DFLUID_USE_SYSTEM_LCS:BOOL=ON", 41 | "-DFLUID_WITH_DOCUMENTATION:BOOL=OFF", 42 | "-DFLUID_WITH_DEMO:BOOL=OFF" 43 | ], 44 | "sources": [ 45 | { 46 | "type": "git", 47 | "url": "git://github.com/lirios/fluid.git", 48 | "branch": "develop" 49 | } 50 | ] 51 | }, 52 | { 53 | "name": "browser", 54 | "buildsystem": "cmake-ninja", 55 | "sources": [ 56 | { 57 | "type": "git", 58 | "url": "git://github.com/lirios/browser.git", 59 | "branch": "develop" 60 | } 61 | ] 62 | } 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /res/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(UNIX AND NOT APPLE AND NOT ANDROID) 2 | file(GLOB png_icons "${CMAKE_CURRENT_SOURCE_DIR}/icons/*/*/*.png") 3 | file(GLOB svg_icons "${CMAKE_CURRENT_SOURCE_DIR}/icons/*/*/*.svg") 4 | foreach(source_path IN LISTS png_icons svg_icons) 5 | string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/icons/" "" icon_basename "${source_path}") 6 | get_filename_component(icon_directory "${icon_basename}" DIRECTORY) 7 | string(REPLACE "${icon_directory}/" "" icon_filename "${icon_basename}") 8 | string(REGEX REPLACE "\.(png|svg)" "" icon_filename "${icon_filename}") 9 | set(dest_path "${INSTALL_DATADIR}/icons/hicolor/${icon_directory}/") 10 | install(FILES "${source_path}" DESTINATION "${dest_path}") 11 | endforeach() 12 | endif() 13 | -------------------------------------------------------------------------------- /res/icons/128x128/apps/io.liri.Browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirios/browser/add11f501ce269c1dcf26532d708322bf6a7b72f/res/icons/128x128/apps/io.liri.Browser.png -------------------------------------------------------------------------------- /res/icons/16x16/apps/io.liri.Browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirios/browser/add11f501ce269c1dcf26532d708322bf6a7b72f/res/icons/16x16/apps/io.liri.Browser.png -------------------------------------------------------------------------------- /res/icons/192x192/apps/io.liri.Browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirios/browser/add11f501ce269c1dcf26532d708322bf6a7b72f/res/icons/192x192/apps/io.liri.Browser.png -------------------------------------------------------------------------------- /res/icons/256x256/apps/io.liri.Browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirios/browser/add11f501ce269c1dcf26532d708322bf6a7b72f/res/icons/256x256/apps/io.liri.Browser.png -------------------------------------------------------------------------------- /res/icons/32x32/apps/io.liri.Browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirios/browser/add11f501ce269c1dcf26532d708322bf6a7b72f/res/icons/32x32/apps/io.liri.Browser.png -------------------------------------------------------------------------------- /res/icons/512x512/apps/io.liri.Browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirios/browser/add11f501ce269c1dcf26532d708322bf6a7b72f/res/icons/512x512/apps/io.liri.Browser.png -------------------------------------------------------------------------------- /res/icons/64x64/apps/io.liri.Browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lirios/browser/add11f501ce269c1dcf26532d708322bf6a7b72f/res/icons/64x64/apps/io.liri.Browser.png -------------------------------------------------------------------------------- /res/io.liri.Browser.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Liri Browser 3 | Comment=Material Design Webbrowser 4 | Exec=liri-browser %U 5 | Terminal=false 6 | Type=Application 7 | Categories=Qt;Network;WebBrowser; 8 | Keywords=Web;Browser; 9 | Icon=io.liri.Browser 10 | 11 | -------------------------------------------------------------------------------- /res/translations/browser_ja.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | BrowserWindow 4 | 5 | New window 6 | 7 | 8 | 9 | Private mode 10 | プライベートモード 11 | 12 | 13 | Private Window 14 | プライベートウィンドウ 15 | 16 | 17 | Find in page 18 | 19 | 20 | 21 | Downloads 22 | ダウンロード 23 | 24 | 25 | Exit fullscreen 26 | 27 | 28 | 29 | Fullscreen 30 | 31 | 32 | 33 | Settings 34 | 設定 35 | 36 | 37 | 38 | DownloadItemDelegate 39 | 40 | Finished 41 | 42 | 43 | 44 | Failed 45 | 46 | 47 | 48 | 49 | DrawerDownloadsContent 50 | 51 | Downloads 52 | ダウンロード 53 | 54 | 55 | No downloads for this session 56 | 57 | 58 | 59 | 60 | SearchOverlay 61 | 62 | Find in page 63 | 64 | 65 | 66 | 67 | SettingsContent 68 | 69 | Settings 70 | 設定 71 | 72 | 73 | Primary 74 | 75 | 76 | 77 | Dark theme 78 | 79 | 80 | 81 | Incognito 82 | 83 | 84 | 85 | Search 86 | 87 | 88 | 89 | Custom 90 | 91 | 92 | 93 | e.g https://example.com/?q= 94 | 95 | 96 | 97 | Theme 98 | テーマ 99 | 100 | 101 | Adapt to website theme colors 102 | 103 | 104 | 105 | Light theme 106 | 107 | 108 | 109 | Dark theme (always on) 110 | 111 | 112 | 113 | Dark between 114 | 115 | 116 | 117 | and 118 | 119 | 120 | 121 | Startup 122 | 123 | 124 | 125 | Start new window with 126 | 127 | 128 | 129 | New page 130 | 131 | 132 | 133 | Continue where you left off 134 | 135 | 136 | 137 | New page url 138 | 139 | 140 | 141 | Privacy 142 | 143 | 144 | 145 | Save cookies 146 | 147 | 148 | 149 | 150 | TabDelegate 151 | 152 | New tab 153 | 154 | 155 | 156 | 157 | WebContent 158 | 159 | Back 160 | 161 | 162 | 163 | Forward 164 | 165 | 166 | 167 | Reload 168 | 169 | 170 | 171 | View page source 172 | 173 | 174 | 175 | Open in new tab 176 | 177 | 178 | 179 | Open in new window 180 | 181 | 182 | 183 | Open in private window 184 | 185 | 186 | 187 | Copy link location 188 | 189 | 190 | 191 | Download link location 192 | 193 | 194 | 195 | Cut 196 | 197 | 198 | 199 | Copy 200 | 201 | 202 | 203 | Paste 204 | 205 | 206 | 207 | Select all 208 | 209 | 210 | 211 | image 212 | 213 | 214 | 215 | video 216 | 217 | 218 | 219 | audio 220 | 221 | 222 | 223 | unknown 224 | 225 | 226 | 227 | Open %1 in new tab 228 | 229 | 230 | 231 | Copy %1 location 232 | 233 | 234 | 235 | Copy image 236 | 237 | 238 | 239 | Download %1 240 | 241 | 242 | 243 | This connection is untrusted 244 | 245 | 246 | 247 | You are about to securely connect to %1 but we can't confirm that your connection is secure: %2 248 | %1 is an URL 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /res/translations/browser_zh_CN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | BrowserWindow 4 | 5 | New window 6 | 新窗口 7 | 8 | 9 | Private mode 10 | 隐私模式 11 | 12 | 13 | Private Window 14 | 隐私窗口 15 | 16 | 17 | Find in page 18 | 在页面中查找 19 | 20 | 21 | Downloads 22 | 下载 23 | 24 | 25 | Exit fullscreen 26 | 退出全屏 27 | 28 | 29 | Fullscreen 30 | 全屏 31 | 32 | 33 | Settings 34 | 设置 35 | 36 | 37 | 38 | DownloadItemDelegate 39 | 40 | Finished 41 | 42 | 43 | 44 | Failed 45 | 46 | 47 | 48 | 49 | DrawerDownloadsContent 50 | 51 | Downloads 52 | 下载 53 | 54 | 55 | No downloads for this session 56 | 没有关于此事项的下载 57 | 58 | 59 | 60 | SearchOverlay 61 | 62 | Find in page 63 | 在页面中查找 64 | 65 | 66 | 67 | SettingsContent 68 | 69 | Settings 70 | 设置 71 | 72 | 73 | Primary 74 | 首要 75 | 76 | 77 | Dark theme 78 | 夜间主题 79 | 80 | 81 | Incognito 82 | 隐身 83 | 84 | 85 | Search 86 | 查找 87 | 88 | 89 | Custom 90 | 自定义 91 | 92 | 93 | e.g https://example.com/?q= 94 | 例:https://example.com/?q= 95 | 96 | 97 | Theme 98 | 主题 99 | 100 | 101 | Adapt to website theme colors 102 | 适应网页主题颜色 103 | 104 | 105 | Light theme 106 | 日间主题 107 | 108 | 109 | Dark theme (always on) 110 | 夜间主题(总是开启) 111 | 112 | 113 | Dark between 114 | 夜间模式在 115 | 116 | 117 | and 118 | 119 | 120 | 121 | Startup 122 | 123 | 124 | 125 | Start new window with 126 | 127 | 128 | 129 | New page 130 | 131 | 132 | 133 | Continue where you left off 134 | 135 | 136 | 137 | New page url 138 | 139 | 140 | 141 | Privacy 142 | 143 | 144 | 145 | Save cookies 146 | 147 | 148 | 149 | 150 | TabDelegate 151 | 152 | New tab 153 | 新标签页 154 | 155 | 156 | 157 | WebContent 158 | 159 | Back 160 | 161 | 162 | 163 | Forward 164 | 165 | 166 | 167 | Reload 168 | 169 | 170 | 171 | View page source 172 | 173 | 174 | 175 | Open in new tab 176 | 177 | 178 | 179 | Open in new window 180 | 181 | 182 | 183 | Open in private window 184 | 185 | 186 | 187 | Copy link location 188 | 189 | 190 | 191 | Download link location 192 | 193 | 194 | 195 | Cut 196 | 197 | 198 | 199 | Copy 200 | 201 | 202 | 203 | Paste 204 | 205 | 206 | 207 | Select all 208 | 209 | 210 | 211 | image 212 | 213 | 214 | 215 | video 216 | 217 | 218 | 219 | audio 220 | 221 | 222 | 223 | unknown 224 | 225 | 226 | 227 | Open %1 in new tab 228 | 229 | 230 | 231 | Copy %1 location 232 | 233 | 234 | 235 | Copy image 236 | 237 | 238 | 239 | Download %1 240 | 241 | 242 | 243 | This connection is untrusted 244 | 245 | 246 | 247 | You are about to securely connect to %1 but we can't confirm that your connection is secure: %2 248 | %1 is an URL 249 | 250 | 251 | 252 | -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: liri-browser 2 | version: git 3 | summary: A cross-platform material web browser 4 | description: A cross-platform material web browser 5 | grade: devel 6 | confinement: strict 7 | architectures: [amd64] 8 | 9 | plugs: 10 | browser-sandbox: 11 | interface: browser-support 12 | allow-sandbox: false 13 | platform: 14 | interface: content 15 | content: liri-platform 16 | target: liri-platform 17 | default-provider: liri-platform-0-9 18 | 19 | apps: 20 | liri-browser: 21 | command: liri-app-launch $SNAP/bin/liri-browser 22 | desktop: share/applications/io.liri.Browser.desktop 23 | environment: 24 | # Workaround QtWebEngine crashing when 25 | # using Nouveau graphic drivers by forcing 26 | # the Qt xcb plugin to use software rendering: 27 | # https://bugreports.qt.io/browse/QTBUG-41242 28 | QT_XCB_FORCE_SOFTWARE_OPENGL: 1 29 | # Disable Chromium sandbox since we're running 30 | # strictly confined anyway. 31 | QTWEBENGINE_DISABLE_SANDBOX: 1 32 | plugs: 33 | - desktop 34 | - desktop-legacy 35 | - wayland 36 | - unity7 37 | - opengl 38 | - browser-sandbox 39 | - network 40 | - network-bind 41 | - pulseaudio 42 | - camera 43 | - screen-inhibit-control 44 | 45 | parts: 46 | liri-browser: 47 | source: . 48 | plugin: qbs 49 | qbs-options: 50 | - modules.lirideployment.prefix:/ 51 | prepare: | 52 | sed -i 's|Icon=.*|Icon=${SNAP}/share/icons/hicolor/256x256/apps/io\.liri\.Browser\.png|g' res/io.liri.Browser.desktop 53 | build-attributes: ["no-system-libraries"] 54 | after: 55 | - liri-platform-0-9 56 | -------------------------------------------------------------------------------- /src/3rdparty/regex-weburl/README: -------------------------------------------------------------------------------- 1 | Regular Expression for URL validation 2 | Author: Diego Perini 3 | Updated: 2010/12/05 4 | License: MIT 5 | 6 | Source: https://gist.github.com/dperini/729294 7 | -------------------------------------------------------------------------------- /src/3rdparty/regex-weburl/qmldir: -------------------------------------------------------------------------------- 1 | module 3rdparty.dperini.regexweburl 2 | 3 | RegexWebUrl 1.0 regex-weburl.js 4 | -------------------------------------------------------------------------------- /src/3rdparty/regex-weburl/regex-weburl.js: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Regular Expression for URL validation 4 | // 5 | // Author: Diego Perini 6 | // Updated: 2010/12/05 7 | // License: MIT 8 | // 9 | // Copyright (c) 2010-2013 Diego Perini (http://www.iport.it) 10 | // 11 | // Permission is hereby granted, free of charge, to any person 12 | // obtaining a copy of this software and associated documentation 13 | // files (the "Software"), to deal in the Software without 14 | // restriction, including without limitation the rights to use, 15 | // copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the 17 | // Software is furnished to do so, subject to the following 18 | // conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be 21 | // included in all copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 25 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 27 | // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 28 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 29 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 30 | // OTHER DEALINGS IN THE SOFTWARE. 31 | // 32 | // the regular expression composed & commented 33 | // could be easily tweaked for RFC compliance, 34 | // it was expressly modified to fit & satisfy 35 | // these test for an URL shortener: 36 | // 37 | // http://mathiasbynens.be/demo/url-regex 38 | // 39 | // Notes on possible differences from a standard/generic validation: 40 | // 41 | // - utf-8 char class take in consideration the full Unicode range 42 | // - TLDs have been made mandatory so single names like "localhost" fails 43 | // - protocols have been restricted to ftp, http and https only as requested 44 | // 45 | // Changes: 46 | // 47 | // - IP address dotted notation validation, range: 1.0.0.0 - 223.255.255.255 48 | // first and last IP address of each class is considered invalid 49 | // (since they are broadcast/network addresses) 50 | // 51 | // - Added exclusion of private, reserved and/or local networks ranges 52 | // 53 | // - Made starting path slash optional (http://example.com?foo=bar) 54 | // 55 | // - Allow a dot (.) at the end of hostnames (http://example.com.) 56 | // 57 | // Compressed one-line versions: 58 | // 59 | // Javascript version 60 | // 61 | // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/i 62 | // 63 | // PHP version 64 | // 65 | // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]-*)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$_iuS 66 | // 67 | var re_weburl = new RegExp( 68 | "^" + 69 | // protocol identifier 70 | "(?:(?:https?|ftp)://)" + 71 | // user:pass authentication 72 | "(?:\\S+(?::\\S*)?@)?" + 73 | "(?:" + 74 | // IP address exclusion 75 | // private & local networks 76 | "(?!(?:10|127)(?:\\.\\d{1,3}){3})" + 77 | "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + 78 | "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + 79 | // IP address dotted notation octets 80 | // excludes loopback network 0.0.0.0 81 | // excludes reserved space >= 224.0.0.0 82 | // excludes network & broacast addresses 83 | // (first & last IP address of each class) 84 | "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + 85 | "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + 86 | "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + 87 | "|" + 88 | // host name 89 | "(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" + 90 | // domain name 91 | "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" + 92 | // TLD identifier 93 | "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" + 94 | // TLD may end with dot 95 | "\\.?" + 96 | ")" + 97 | // port number 98 | "(?::\\d{2,5})?" + 99 | // resource path 100 | "(?:[/?#]\\S*)?" + 101 | "$", "i" 102 | ); 103 | -------------------------------------------------------------------------------- /src/3rdparty/regex-weburl/regex-weburl.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | qmldir 4 | regex-weburl.js 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(APPLE OR WIN32) 2 | set(LiriBrowser_OUTPUT_NAME "LiriBrowser") 3 | else() 4 | set(LiriBrowser_OUTPUT_NAME "liri-browser") 5 | endif() 6 | 7 | set(LiriBrowser_SOURCES 8 | core/global/paths.h 9 | core/models/downloadsmodel.cpp 10 | core/models/downloadsmodel.h 11 | core/models/tab.cpp 12 | core/models/tab.h 13 | core/models/tabsmodel.cpp 14 | core/models/tabsmodel.h 15 | core/session/session.cpp 16 | core/session/session.h 17 | core/session/tabstate.cpp 18 | core/session/tabstate.h 19 | core/settings/searchconfig.cpp 20 | core/settings/searchconfig.h 21 | core/settings/settings.cpp 22 | core/settings/settings.h 23 | core/settings/startconfig.cpp 24 | core/settings/startconfig.h 25 | core/settings/themeconfig.cpp 26 | core/settings/themeconfig.h 27 | core/utils/darkthemetimer.cpp 28 | core/utils/darkthemetimer.h 29 | main/browserapplication.cpp 30 | main/browserapplication.h 31 | main/main.cpp 32 | ) 33 | if(APPLE) 34 | set(LiriBrowser_SOURCES 35 | ${LiriBrowser_SOURCES} 36 | main/mac/MacOsEventListener.h 37 | main/mac/MacOsEventListener.mm) 38 | endif() 39 | 40 | liri_add_executable(LiriBrowser 41 | OUTPUT_NAME 42 | "${LiriBrowser_OUTPUT_NAME}" 43 | SOURCES 44 | ${LiriBrowser_SOURCES} 45 | RESOURCES 46 | 3rdparty/regex-weburl/regex-weburl.qrc 47 | ui/ui.qrc 48 | DEFINES 49 | #QT_NO_CAST_FROM_ASCII 50 | QT_NO_FOREACH 51 | -DPROJECT_VERSION="${PROJECT_VERSION}" 52 | DESKTOP 53 | "${CMAKE_CURRENT_SOURCE_DIR}/../res/io.liri.Browser.desktop" 54 | LIBRARIES 55 | Qt5::Core 56 | Qt5::Gui 57 | Qt5::Qml 58 | Qt5::Quick 59 | Qt5::QuickControls2 60 | Qt5::WebEngine 61 | qtsingleapplication 62 | GUI 63 | ) 64 | if(APPLE) 65 | target_link_libraries(LiriBrowser PUBLIC "-framework AppKit -framework Foundation") 66 | set_target_properties(LiriBrowser PROPERTIES LINK_FLAGS "-Wl,-F/Library/Frameworks") 67 | endif() 68 | set_target_properties(LiriBrowser PROPERTIES 69 | MACOSX_BUNDLE_GUI_IDENTIFIER "io.liri.Browser" 70 | MACOSX_BUNDLE_ICON_FILE "io.liri.Browser" 71 | MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}" 72 | ) 73 | 74 | liri_finalize_executable(LiriBrowser) 75 | -------------------------------------------------------------------------------- /src/core/global/paths.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Tim Süberkrüb 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef PATHS_H 21 | #define PATHS_H 22 | 23 | #include 24 | #include 25 | 26 | namespace Paths { 27 | const QString ConfigLocation = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/liri-browser/"; 28 | const QString DataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/liri-browser/"; 29 | const QString SettingsFile = ConfigLocation + "settings.json"; 30 | const QString SessionDataFile = DataLocation + "session.json"; 31 | } 32 | 33 | #endif // PATHS_H 34 | -------------------------------------------------------------------------------- /src/core/models/downloadsmodel.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Tim Süberkrüb 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "downloadsmodel.h" 21 | 22 | DownloadsModel::DownloadsModel(QObject* parent) 23 | : QAbstractListModel(parent) 24 | { 25 | } 26 | 27 | int DownloadsModel::rowCount(const QModelIndex &parent) const 28 | { 29 | Q_UNUSED(parent); 30 | return m_downloads_list.length(); 31 | } 32 | 33 | int DownloadsModel::count() const 34 | { 35 | return m_downloads_list.length(); 36 | } 37 | 38 | void DownloadsModel::add(QQuickWebEngineDownloadItem* download) 39 | { 40 | beginInsertRows(QModelIndex(), rowCount(), rowCount()); 41 | m_downloads_list.append(download); 42 | countChanged(count()); 43 | endInsertRows(); 44 | } 45 | 46 | QQuickWebEngineDownloadItem* DownloadsModel::get(const int index) const 47 | { 48 | if (index < 0 || index >= rowCount()) { 49 | return nullptr; 50 | } 51 | return m_downloads_list.at(index); 52 | } 53 | 54 | bool DownloadsModel::remove(QQuickWebEngineDownloadItem *download) 55 | { 56 | int index = m_downloads_list.indexOf(download); 57 | if (index == -1) 58 | return false; 59 | beginRemoveRows(QModelIndex(), index, index); 60 | m_downloads_list.removeAt(index); 61 | countChanged(count()); 62 | endRemoveRows(); 63 | return true; 64 | } 65 | 66 | bool DownloadsModel::remove(const int index) 67 | { 68 | return remove(get(index)); 69 | } 70 | -------------------------------------------------------------------------------- /src/core/models/downloadsmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Tim Süberkrüb 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef DOWNLOADSMODEL_H 21 | #define DOWNLOADSMODEL_H 22 | 23 | #include 24 | #include 25 | 26 | class DownloadsModel : public QAbstractListModel 27 | { 28 | Q_OBJECT 29 | Q_PROPERTY(int count READ count NOTIFY countChanged) 30 | public: 31 | explicit DownloadsModel(QObject* parent = nullptr); 32 | 33 | enum DownloadRoles { 34 | Path, 35 | MimeType, 36 | Progress, 37 | Status 38 | }; 39 | 40 | int rowCount(const QModelIndex &parent=QModelIndex()) const; 41 | QHash roleNames() { return QHash(); } 42 | Q_INVOKABLE QVariant data(const QModelIndex &index, int role) const { 43 | Q_UNUSED(index) 44 | Q_UNUSED(role) 45 | return QVariant(); 46 | } 47 | 48 | Q_INVOKABLE int count() const; 49 | Q_INVOKABLE void add(QQuickWebEngineDownloadItem* download); 50 | Q_INVOKABLE QQuickWebEngineDownloadItem* get(const int index) const; 51 | Q_INVOKABLE bool remove(QQuickWebEngineDownloadItem* download); 52 | Q_INVOKABLE bool remove(const int index); 53 | 54 | private: 55 | QList m_downloads_list; 56 | 57 | signals: 58 | void countChanged(int count); 59 | }; 60 | 61 | #endif // DOWNLOADSMODEL_H 62 | -------------------------------------------------------------------------------- /src/core/models/tab.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | 25 | #include "tab.h" 26 | 27 | Tab::Tab(QObject *parent, bool valid) 28 | : QObject(parent) 29 | { 30 | m_uid = -1; 31 | m_canReload = true; 32 | validChanged(m_valid = valid); 33 | m_iconColor = Qt::transparent; 34 | } 35 | 36 | unsigned int Tab::uid() const 37 | { 38 | return m_uid; 39 | } 40 | 41 | void Tab::setUid(int uid) 42 | { 43 | uidChanged(m_uid = uid); 44 | } 45 | 46 | QUrl Tab::url() const 47 | { 48 | return m_url; 49 | } 50 | 51 | void Tab::setUrl(QUrl url) 52 | { 53 | urlChanged(m_url = url); 54 | } 55 | 56 | QString Tab::title() const 57 | { 58 | return m_title; 59 | } 60 | 61 | void Tab::setTitle(QString title) 62 | { 63 | titleChanged(m_title = title); 64 | } 65 | 66 | QUrl Tab::iconUrl() const 67 | { 68 | return m_iconUrl; 69 | } 70 | 71 | void Tab::setIconUrl(QUrl iconUrl) 72 | { 73 | iconUrlChanged(m_iconUrl = iconUrl); 74 | } 75 | 76 | QColor Tab::iconColor() const 77 | { 78 | return m_iconColor; 79 | } 80 | 81 | void Tab::setIconColor(QColor iconColor) 82 | { 83 | iconColorChanged(m_iconColor = iconColor); 84 | } 85 | 86 | bool Tab::adaptIconColor() const 87 | { 88 | return m_adaptIconColor; 89 | } 90 | 91 | void Tab::setAdaptIconColor(bool adaptIconColor) 92 | { 93 | adaptIconColorChanged(m_adaptIconColor = adaptIconColor); 94 | } 95 | 96 | bool Tab::canGoBack() const 97 | { 98 | return m_canGoBack; 99 | } 100 | 101 | void Tab::setCanGoBack(bool canGoBack) 102 | { 103 | canGoBackChanged(m_canGoBack = canGoBack); 104 | } 105 | 106 | bool Tab::canGoForward() const 107 | { 108 | return m_canGoForward; 109 | } 110 | 111 | void Tab::setCanGoForward(bool canGoForward) 112 | { 113 | canGoForwardChanged(m_canGoForward = canGoForward); 114 | } 115 | 116 | bool Tab::canReload() const 117 | { 118 | return m_canReload; 119 | } 120 | 121 | void Tab::setCanReload(bool canReload) 122 | { 123 | canReloadChanged(m_canReload = canReload); 124 | } 125 | 126 | bool Tab::loading() const 127 | { 128 | return m_loading; 129 | } 130 | 131 | void Tab::setLoading(bool loading) 132 | { 133 | loadingChanged(m_loading = loading); 134 | } 135 | 136 | unsigned int Tab::loadProgress() const 137 | { 138 | return m_loadProgress; 139 | } 140 | 141 | void Tab::setLoadProgress(unsigned int loadProgress) 142 | { 143 | loadProgressChanged(m_loadProgress = loadProgress); 144 | } 145 | 146 | bool Tab::valid() const 147 | { 148 | return m_valid; 149 | } 150 | 151 | bool Tab::hasThemeColor() const 152 | { 153 | return m_hasThemeColor; 154 | } 155 | 156 | void Tab::setHasThemeColor(bool hasThemeColor) 157 | { 158 | hasThemeColorChanged(m_hasThemeColor = hasThemeColor); 159 | } 160 | 161 | QColor Tab::themeColor() const 162 | { 163 | return m_themeColor; 164 | } 165 | 166 | void Tab::setThemeColor(QColor themeColor) 167 | { 168 | themeColorChanged(m_themeColor = themeColor); 169 | } 170 | 171 | -------------------------------------------------------------------------------- /src/core/models/tab.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #ifndef TAB_H 25 | #define TAB_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | class Tab : public QObject 32 | { 33 | Q_OBJECT 34 | Q_PROPERTY(unsigned int uid READ uid WRITE setUid NOTIFY uidChanged) 35 | Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) 36 | Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) 37 | Q_PROPERTY(QUrl iconUrl READ iconUrl WRITE setIconUrl NOTIFY iconUrlChanged) 38 | Q_PROPERTY(QColor iconColor READ iconColor WRITE setIconColor NOTIFY iconColorChanged) 39 | Q_PROPERTY(bool adaptIconColor READ adaptIconColor WRITE setAdaptIconColor NOTIFY adaptIconColorChanged) 40 | Q_PROPERTY(bool canGoBack READ canGoBack WRITE setCanGoBack NOTIFY canGoBackChanged) 41 | Q_PROPERTY(bool canGoForward READ canGoForward WRITE setCanGoForward NOTIFY canGoForwardChanged) 42 | Q_PROPERTY(bool canReload READ canReload WRITE setCanReload NOTIFY canReloadChanged) 43 | Q_PROPERTY(bool loading READ loading WRITE setLoading NOTIFY loadingChanged) 44 | Q_PROPERTY(unsigned int loadProgress READ loadProgress WRITE setLoadProgress NOTIFY loadProgressChanged) 45 | Q_PROPERTY(bool valid READ valid NOTIFY validChanged) 46 | Q_PROPERTY(bool hasThemeColor READ hasThemeColor WRITE setHasThemeColor NOTIFY hasThemeColorChanged) 47 | Q_PROPERTY(QColor themeColor READ themeColor WRITE setThemeColor NOTIFY themeColorChanged) 48 | public: 49 | explicit Tab(QObject *parent = nullptr, bool valid = true); 50 | 51 | unsigned int uid() const; 52 | void setUid(int uid); 53 | 54 | QUrl url() const; 55 | void setUrl(QUrl url); 56 | 57 | QString title() const; 58 | void setTitle(QString title); 59 | 60 | QUrl iconUrl() const; 61 | void setIconUrl(QUrl iconUrl); 62 | 63 | QColor iconColor() const; 64 | void setIconColor(QColor iconColor); 65 | 66 | bool adaptIconColor() const; 67 | void setAdaptIconColor(bool adaptIconColor); 68 | 69 | bool canGoBack() const; 70 | void setCanGoBack(bool canGoBack); 71 | 72 | bool canGoForward() const; 73 | void setCanGoForward(bool canGoForward); 74 | 75 | bool canReload() const; 76 | void setCanReload(bool canReload); 77 | 78 | bool loading() const; 79 | void setLoading(bool loading); 80 | 81 | unsigned int loadProgress() const; 82 | void setLoadProgress(unsigned int loadProgress); 83 | 84 | bool valid() const; 85 | 86 | bool hasThemeColor() const; 87 | void setHasThemeColor(bool hasThemeColor); 88 | 89 | QColor themeColor() const; 90 | void setThemeColor(QColor themeColor); 91 | 92 | signals: 93 | void uidChanged(unsigned int uid); 94 | void urlChanged(QUrl url); 95 | void titleChanged(QString title); 96 | void iconUrlChanged(QUrl iconUrl); 97 | void iconColorChanged(QColor iconColor); 98 | void adaptIconColorChanged(bool adaptIconColor); 99 | void canGoBackChanged(bool canGoBack); 100 | void canGoForwardChanged(bool canGoForward); 101 | void canReloadChanged(bool canReload); 102 | void validChanged(bool valid); 103 | void loadingChanged(bool loading); 104 | void loadProgressChanged(unsigned int loadProgress); 105 | void hasThemeColorChanged(bool hasThemeColor); 106 | void themeColorChanged(QColor themeColor); 107 | 108 | void goBack(); 109 | void goForward(); 110 | void reload(); 111 | void stop(); 112 | void findText(QString text, bool backwards, bool caseSensitive); 113 | 114 | public slots: 115 | 116 | private: 117 | unsigned int m_uid; 118 | QUrl m_url; 119 | QString m_title; 120 | QUrl m_iconUrl; 121 | QColor m_iconColor; 122 | bool m_adaptIconColor; 123 | bool m_canGoBack; 124 | bool m_canGoForward; 125 | bool m_canReload; 126 | bool m_loading; 127 | int m_loadProgress; 128 | bool m_hasThemeColor; 129 | QColor m_themeColor; 130 | 131 | bool m_valid; 132 | }; 133 | 134 | #endif // TAB_H 135 | -------------------------------------------------------------------------------- /src/core/models/tabsmodel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #ifndef TABSMODEL_H 25 | #define TABSMODEL_H 26 | 27 | #include 28 | #include "tab.h" 29 | 30 | class TabsModel : public QAbstractListModel 31 | { 32 | Q_OBJECT 33 | Q_PROPERTY(int count READ count NOTIFY countChanged) 34 | Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged) 35 | Q_PROPERTY(Tab* active READ active NOTIFY activeChanged) 36 | Q_PROPERTY(int activeIndex READ activeIndex NOTIFY activeIndexChanged) 37 | public: 38 | explicit TabsModel(QObject *parent = nullptr); 39 | 40 | enum TabRoles { 41 | Uid, 42 | Url, 43 | Title, 44 | IconUrl, 45 | CanGoBack, 46 | CanGoForward, 47 | Loading, 48 | LoadProgress, 49 | Valid 50 | }; 51 | 52 | int rowCount(const QModelIndex &parent=QModelIndex()) const; 53 | QHash roleNames() const; 54 | Q_INVOKABLE QVariant data(const QModelIndex &index, int role) const; 55 | 56 | Q_INVOKABLE Tab* get(const int row) const; 57 | Q_INVOKABLE int row(unsigned int uid); 58 | Q_INVOKABLE int row(Tab* tab); 59 | Q_INVOKABLE void add(unsigned int uid); 60 | Q_INVOKABLE void insert(unsigned int uid, int row=-1); 61 | Q_INVOKABLE bool move(int fromRow, int toRow); 62 | Q_INVOKABLE int count() const; 63 | Q_INVOKABLE bool remove(unsigned int uid); 64 | Q_INVOKABLE bool remove(Tab* tab); 65 | Q_INVOKABLE bool empty() const; 66 | 67 | Q_INVOKABLE Tab* byUID(unsigned int uid); 68 | 69 | Q_INVOKABLE bool setActive(unsigned int uid); 70 | Q_INVOKABLE bool setActive(Tab* tab); 71 | Q_INVOKABLE Tab* active() const; 72 | Q_INVOKABLE int activeIndex() const; 73 | 74 | Q_INVOKABLE void setInactive(Tab* tab); 75 | Q_INVOKABLE void setInactive(); 76 | 77 | Q_INVOKABLE bool setPreviousTabActive(); 78 | Q_INVOKABLE bool setNextTabActive(); 79 | 80 | signals: 81 | void countChanged(int count); 82 | void emptyChanged(bool empty); 83 | void activeChanged(Tab* tab); 84 | void activeIndexChanged(int index); 85 | void beforeTabRemoved(Tab* tab); 86 | 87 | public slots: 88 | 89 | private: // methods 90 | bool activateTabRelativeToCurrent(int offset); 91 | bool setActive(Tab* tab, bool recordToHistory); 92 | 93 | private: // members 94 | QList m_tabsList; 95 | QList m_activeTabHistory; 96 | Tab* m_activeTab; 97 | Tab* m_invalidTab; 98 | }; 99 | 100 | #endif // TABSMODEL_H 101 | -------------------------------------------------------------------------------- /src/core/session/session.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Ivan Fateev 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #include "session.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "../global/paths.h" 33 | #include "../models/tabsmodel.h" 34 | #include "tabstate.h" 35 | 36 | Session::Session(QObject *parent) 37 | : QObject(parent) 38 | , m_activeTab(0) 39 | { 40 | load(); 41 | } 42 | 43 | void Session::save(TabsModel* tabs) 44 | { 45 | if (!QDir(Paths::DataLocation).exists()) { 46 | qDebug() << "DataLocation path doesn't exist."; 47 | qDebug() << "Creating" << Paths::DataLocation << "..."; 48 | QDir().mkpath(Paths::DataLocation); 49 | } 50 | QFile file(Paths::SessionDataFile); 51 | if (!file.open(QIODevice::WriteOnly)) { 52 | qWarning("Couldn't open session file for write!"); 53 | return; 54 | } 55 | QTextStream stream(&file); 56 | stream << json(tabs); 57 | file.close(); 58 | 59 | qDebug() << "Session written to" << Paths::SessionDataFile; 60 | } 61 | 62 | QVariantList Session::getTabsToRestore() 63 | { 64 | QVariantList tabs; 65 | for (TabState* state : m_tabs) { 66 | tabs.append(QVariant::fromValue(state)); 67 | } 68 | m_tabs.clear(); 69 | return tabs; 70 | } 71 | 72 | void Session::load() 73 | { 74 | QFile file(Paths::SessionDataFile); 75 | if (!file.open(QIODevice::ReadOnly)) { 76 | qWarning("Couldn't open session file for read!"); 77 | return; 78 | } 79 | 80 | QByteArray bytes = file.readAll(); 81 | QJsonDocument doc(QJsonDocument::fromJson(bytes)); 82 | 83 | QJsonObject root = doc.object(); 84 | QJsonObject meta = root["meta"].toObject(); 85 | QString metaSchema = meta["schema"].toString(); 86 | if (metaSchema != "0.1") { 87 | qWarning() << "Unknown session schema version " << metaSchema << "!"; 88 | return; 89 | } 90 | QJsonArray tabs = root["tabs"].toArray(); 91 | for (QJsonValue tab : tabs) { 92 | auto tabObj = tab.toObject(); 93 | auto state = new TabState(this); 94 | state->setUrl(tabObj["url"].toString()); 95 | state->setTitle(tabObj["title"].toString()); 96 | state->setIcon(tabObj["icon"].toString()); 97 | m_tabs.append(state); 98 | } 99 | 100 | m_activeTab = std::max(m_tabs.count() - 1, 0); 101 | if (root.find("activeTab") != root.end()) { 102 | m_activeTab = root["activeTab"].toInt(); 103 | } 104 | } 105 | 106 | QByteArray Session::json(TabsModel* tabs) 107 | { 108 | QJsonObject meta { 109 | {"schema", "0.1"} 110 | }; 111 | 112 | QJsonArray tabsArray; 113 | 114 | for (int i = 0; i < tabs->count(); ++i) { 115 | QJsonObject tabObject; 116 | auto tab = tabs->get(i); 117 | tabObject["url"] = tab->url().toString(); 118 | tabObject["title"] = tab->title(); 119 | tabObject["icon"] = tab->iconUrl().toString().replace("image://favicon/" ,""); 120 | tabsArray.append(tabObject); 121 | } 122 | 123 | QJsonObject root { 124 | {"meta", meta}, 125 | {"tabs", tabsArray}, 126 | {"activeTab", tabs->activeIndex()}, 127 | }; 128 | 129 | QJsonDocument doc(root); 130 | return doc.toJson(); 131 | } 132 | -------------------------------------------------------------------------------- /src/core/session/session.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Ivan Fateev 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #ifndef SESSION_H 25 | #define SESSION_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | class TabsModel; 32 | class TabState; 33 | 34 | class Session : public QObject 35 | { 36 | Q_OBJECT 37 | public: 38 | explicit Session(QObject *parent = 0); 39 | 40 | Q_INVOKABLE void save(TabsModel* tabs); 41 | Q_INVOKABLE QVariantList getTabsToRestore(); 42 | Q_PROPERTY(int activeTab READ getActiveTab) 43 | 44 | int getActiveTab() { return m_activeTab; } 45 | private: 46 | void load(); 47 | QByteArray json(TabsModel *tabs); 48 | 49 | private: 50 | QList m_tabs; 51 | int m_activeTab; 52 | }; 53 | 54 | #endif // SESSION_H 55 | -------------------------------------------------------------------------------- /src/core/session/tabstate.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Ivan Fateev 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | 25 | #include "tabstate.h" 26 | 27 | TabState::TabState(QObject *parent) : QObject(parent) 28 | { 29 | 30 | } 31 | 32 | void TabState::setUrl(QString url) 33 | { 34 | if (m_url == url) 35 | return; 36 | 37 | m_url = url; 38 | } 39 | 40 | QString TabState::url() const 41 | { 42 | return m_url; 43 | } 44 | 45 | void TabState::setTitle(QString title) 46 | { 47 | m_title = title; 48 | } 49 | 50 | QString TabState::title() const 51 | { 52 | return m_title; 53 | } 54 | 55 | void TabState::setIcon(QString icon) 56 | { 57 | m_icon = icon; 58 | } 59 | 60 | QString TabState::icon() const 61 | { 62 | return m_icon; 63 | } 64 | -------------------------------------------------------------------------------- /src/core/session/tabstate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Ivan Fateev 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #ifndef TABSTATE_H 25 | #define TABSTATE_H 26 | 27 | #include 28 | 29 | class TabState : public QObject 30 | { 31 | Q_OBJECT 32 | 33 | Q_PROPERTY(QString url READ url WRITE setUrl) 34 | Q_PROPERTY(QString title READ title WRITE setTitle) 35 | Q_PROPERTY(QString icon READ icon WRITE setIcon) 36 | 37 | public: 38 | explicit TabState(QObject *parent = 0); 39 | 40 | void setUrl(QString url); 41 | QString url() const; 42 | void setTitle(QString title); 43 | QString title() const; 44 | void setIcon(QString icon); 45 | QString icon() const; 46 | 47 | private: 48 | QString m_url; 49 | QString m_title; 50 | QString m_icon; 51 | }; 52 | 53 | #endif // TABSTATE_H 54 | -------------------------------------------------------------------------------- /src/core/settings/searchconfig.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #include "searchconfig.h" 25 | 26 | SearchConfig::SearchConfig(QObject *parent) 27 | : QObject(parent) 28 | { 29 | defaultSearchEngineChanged(m_defaultSearchEngine = SearchEngine::DuckDuckGo); 30 | } 31 | -------------------------------------------------------------------------------- /src/core/settings/searchconfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #ifndef SEARCHCONFIG_H 25 | #define SEARCHCONFIG_H 26 | 27 | #include 28 | #include 29 | 30 | class SearchConfig : public QObject 31 | { 32 | Q_OBJECT 33 | Q_PROPERTY(SearchEngine searchEngine READ searchEngine WRITE setSearchEngine NOTIFY searchEngineChanged) 34 | Q_PROPERTY(SearchEngine defaultSearchEngine MEMBER m_defaultSearchEngine NOTIFY defaultSearchEngineChanged) 35 | Q_PROPERTY(QUrl searchUrl READ searchUrl NOTIFY searchUrlChanged) 36 | Q_PROPERTY(QUrl customSearchUrl READ customSearchUrl WRITE setCustomSearchUrl NOTIFY customSearchUrlChanged) 37 | Q_ENUMS(SearchEngine) 38 | public: 39 | explicit SearchConfig(QObject *parent = nullptr); 40 | 41 | enum SearchEngine { 42 | DuckDuckGo, 43 | Google, 44 | Bing, 45 | Yahoo, 46 | StartPage, 47 | Custom 48 | }; 49 | 50 | SearchEngine searchEngine() const { return m_searchEngine; } 51 | void setSearchEngine(SearchEngine searchEngine) { 52 | searchEngineChanged(m_searchEngine = searchEngine); 53 | searchUrlChanged(searchUrl()); 54 | } 55 | 56 | QUrl searchUrl() const { 57 | switch (searchEngine()) { 58 | case SearchEngine::DuckDuckGo: 59 | return QUrl("https://duckduckgo.com/?q="); 60 | case SearchEngine::Google: 61 | return QUrl("https://www.google.com/search?q="); 62 | case SearchEngine::Bing: 63 | return QUrl("https://www.bing.com/search?q="); 64 | case SearchEngine::Yahoo: 65 | return QUrl("https://search.yahoo.com/search?q="); 66 | case SearchEngine::StartPage: 67 | return QUrl("https://www.startpage.com/do/search?query="); 68 | default: 69 | return customSearchUrl(); 70 | } 71 | } 72 | 73 | QUrl customSearchUrl() const { return m_customSearchUrl; } 74 | void setCustomSearchUrl(QUrl customSearchUrl) { customSearchUrlChanged(m_customSearchUrl = customSearchUrl); } 75 | 76 | signals: 77 | void searchEngineChanged(SearchEngine searchEngine); 78 | void defaultSearchEngineChanged(SearchEngine defaultSearchEngine); 79 | void searchUrlChanged(QUrl searchUrl); 80 | void customSearchUrlChanged(QUrl customSearchUrl); 81 | 82 | private: 83 | SearchEngine m_searchEngine; 84 | SearchEngine m_defaultSearchEngine; 85 | QUrl m_searchUrl; 86 | QUrl m_customSearchUrl; 87 | }; 88 | 89 | #endif // SEARCHCONFIG_H 90 | -------------------------------------------------------------------------------- /src/core/settings/settings.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #ifndef SETTINGS_H 25 | #define SETTINGS_H 26 | 27 | #include 28 | #include 29 | 30 | #include "../global/paths.h" 31 | 32 | #include "startconfig.h" 33 | #include "searchconfig.h" 34 | #include "themeconfig.h" 35 | 36 | const QString APP_CONFIG_LOCATION = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + "/liri-browser/"; 37 | const QString SETTINGS_FILENAME = APP_CONFIG_LOCATION + "settings.json"; 38 | 39 | class Settings : public QObject 40 | { 41 | Q_OBJECT 42 | Q_PROPERTY(StartConfig* startConfig MEMBER m_startConfig NOTIFY startConfigChanged) 43 | Q_PROPERTY(SearchConfig* searchConfig MEMBER m_searchConfig NOTIFY searchConfigChanged) 44 | Q_PROPERTY(ThemeConfig* themeConfig MEMBER m_themeConfig NOTIFY themeConfigChanged) 45 | Q_PROPERTY(bool dirty READ dirty WRITE setDirty NOTIFY dirtyChanged) 46 | public: 47 | explicit Settings(QObject *parent = nullptr); 48 | 49 | bool dirty() const { return m_dirty; } 50 | void setDirty(bool dirty) { dirtyChanged(m_dirty = dirty); } 51 | 52 | Q_INVOKABLE void load(); 53 | Q_INVOKABLE void save(); 54 | 55 | QByteArray defaultJSON(); 56 | QByteArray json(); 57 | 58 | private: 59 | StartConfig* m_startConfig; 60 | SearchConfig* m_searchConfig; 61 | ThemeConfig* m_themeConfig; 62 | bool m_dirty; 63 | 64 | signals: 65 | void startConfigChanged(StartConfig* startConfig); 66 | void searchConfigChanged(SearchConfig* searchConfig); 67 | void themeConfigChanged(ThemeConfig* themeConfig); 68 | void dirtyChanged(bool dirty); 69 | }; 70 | 71 | #endif // SETTINGS_H 72 | -------------------------------------------------------------------------------- /src/core/settings/startconfig.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #include "startconfig.h" 25 | 26 | StartConfig::StartConfig(QObject *parent) 27 | : QObject(parent) 28 | { 29 | m_defaultPrimaryStartUrl = QUrl("https://duckduckgo.com"); 30 | m_defaultDarkStartUrl = QUrl("https://duckduckgo.com/?kae=#303030"); 31 | m_defaultIncognitoStartUrl = QUrl("https://duckduckgo.com/?kae=#37474f"); 32 | m_startupType = StartupType::StartFromNewPage; 33 | m_persistentCookies = true; 34 | } 35 | -------------------------------------------------------------------------------- /src/core/settings/startconfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #ifndef STARTCONFIG_H 25 | #define STARTCONFIG_H 26 | 27 | #include 28 | #include 29 | 30 | class StartConfig : public QObject 31 | { 32 | Q_OBJECT 33 | Q_PROPERTY(QUrl primaryStartUrl READ primaryStartUrl WRITE setPrimaryStartUrl NOTIFY primaryStartUrlChanged) 34 | Q_PROPERTY(QUrl defaultPrimaryStartUrl MEMBER m_defaultPrimaryStartUrl NOTIFY defaultPrimaryStartUrlChanged) 35 | Q_PROPERTY(QUrl darkStartUrl READ darkStartUrl WRITE setDarkStartUrl NOTIFY darkStartUrlChanged) 36 | Q_PROPERTY(QUrl defaultDarkStartUrl MEMBER m_defaultDarkStartUrl NOTIFY defaultDarkStartUrlChanged) 37 | Q_PROPERTY(QUrl incognitoStartUrl READ incognitoStartUrl WRITE setIncognitoStartUrl NOTIFY incognitoStartUrlChanged) 38 | Q_PROPERTY(QUrl defaultIncognitoStartUrl MEMBER m_defaultIncognitoStartUrl NOTIFY defaultIncognitoStartUrlChanged) 39 | Q_PROPERTY(StartupType startupType MEMBER m_startupType NOTIFY startupTypeChanged) 40 | Q_PROPERTY(bool persistentCookies MEMBER m_persistentCookies WRITE setPersistentCookies NOTIFY persistentCookiesChanged) 41 | Q_ENUMS(StartupType) 42 | public: 43 | explicit StartConfig(QObject *parent = nullptr); 44 | 45 | enum StartupType { 46 | StartFromNewPage, 47 | StartFromPreviouslyOpenedTabs, 48 | }; 49 | 50 | QUrl primaryStartUrl() const { return m_primaryStartUrl; } 51 | void setPrimaryStartUrl(QUrl url) { primaryStartUrlChanged(m_primaryStartUrl = url); } 52 | 53 | QUrl darkStartUrl() const { return m_darkStartUrl; } 54 | void setDarkStartUrl(QUrl url) { darkStartUrlChanged(m_darkStartUrl = url); } 55 | 56 | QUrl incognitoStartUrl() const { return m_incognitoStartUrl; } 57 | void setIncognitoStartUrl(QUrl url) { incognitoStartUrlChanged(m_incognitoStartUrl = url); } 58 | 59 | QUrl defaultPrimaryStartUrl() const { return m_defaultPrimaryStartUrl; } 60 | QUrl defaultIncognitoStartUrl() const { return m_defaultIncognitoStartUrl; } 61 | QUrl defaultDarkStartUrl() const { return m_defaultDarkStartUrl; } 62 | 63 | StartupType startupType() const { return m_startupType; } 64 | void setStartupType(const StartupType &startupType) { startupTypeChanged(m_startupType = startupType); } 65 | 66 | bool persistentCookies() const { return m_persistentCookies; } 67 | void setPersistentCookies(bool value) { persistentCookiesChanged(m_persistentCookies = value); } 68 | 69 | signals: 70 | void primaryStartUrlChanged(QUrl url); 71 | void defaultPrimaryStartUrlChanged(QUrl url); 72 | void darkStartUrlChanged(QUrl url); 73 | void defaultDarkStartUrlChanged(QUrl url); 74 | void incognitoStartUrlChanged(QUrl url); 75 | void defaultIncognitoStartUrlChanged(QUrl url); 76 | void startupTypeChanged(StartupType url); 77 | void persistentCookiesChanged(bool persistentCookies); 78 | 79 | private: 80 | QUrl m_primaryStartUrl; 81 | QUrl m_defaultPrimaryStartUrl; 82 | QUrl m_incognitoStartUrl; 83 | QUrl m_defaultIncognitoStartUrl; 84 | QUrl m_darkStartUrl; 85 | QUrl m_defaultDarkStartUrl; 86 | StartupType m_startupType; 87 | bool m_persistentCookies; 88 | 89 | }; 90 | 91 | #endif // STARTCONFIG_H 92 | -------------------------------------------------------------------------------- /src/core/settings/themeconfig.cpp: -------------------------------------------------------------------------------- 1 | #include "themeconfig.h" 2 | 3 | ThemeConfig::ThemeConfig(QObject *parent) 4 | : QObject(parent) 5 | { 6 | m_darkThemeStartTime = QTime(21, 0); 7 | m_darkThemeEndTime = QTime(7, 0); 8 | } 9 | -------------------------------------------------------------------------------- /src/core/settings/themeconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef THEMECONFIG_H 2 | #define THEMECONFIG_H 3 | 4 | #include 5 | #include 6 | 7 | class ThemeConfig : public QObject 8 | { 9 | Q_OBJECT 10 | Q_PROPERTY(bool themeColorEnabled READ themeColorEnabled WRITE setThemeColorEnabled NOTIFY themeColorEnabledChanged) 11 | Q_PROPERTY(bool darkThemeEnabled READ darkThemeEnabled WRITE setDarkThemeEnabled NOTIFY darkThemeEnabledChanged) 12 | Q_PROPERTY(QTime darkThemeStartTime READ darkThemeStartTime WRITE setDarkThemeStartTime NOTIFY darkThemeStartTimeChanged) 13 | Q_PROPERTY(QTime darkThemeEndTime READ darkThemeEndTime WRITE setDarkThemeEndTime NOTIFY darkThemeEndTimeChanged) 14 | public: 15 | explicit ThemeConfig(QObject *parent = nullptr); 16 | 17 | bool themeColorEnabled() const { return m_themeColorEnabled; } 18 | void setThemeColorEnabled(bool themeColorEnabled) { themeColorEnabledChanged(m_themeColorEnabled = themeColorEnabled); } 19 | 20 | bool darkThemeEnabled() const { return m_darkThemeEnabled; } 21 | void setDarkThemeEnabled(bool darkThemeEnabled) { darkThemeEnabledChanged(m_darkThemeEnabled = darkThemeEnabled); } 22 | 23 | QTime darkThemeStartTime() const { return m_darkThemeStartTime; } 24 | void setDarkThemeStartTime(QTime darkThemeStartTime) { darkThemeStartTimeChanged(m_darkThemeStartTime = darkThemeStartTime); } 25 | Q_INVOKABLE void setDarkThemeStartTime(QString darkThemeStartTime, QString format) { 26 | darkThemeStartTimeChanged(m_darkThemeStartTime = QTime::fromString(darkThemeStartTime, format)); 27 | } 28 | 29 | QTime darkThemeEndTime() const { return m_darkThemeEndTime; } 30 | void setDarkThemeEndTime(QTime darkThemeEndTime) { darkThemeEndTimeChanged(m_darkThemeEndTime = darkThemeEndTime); } 31 | Q_INVOKABLE void setDarkThemeEndTime(QString darkThemeEndTime, QString format) { 32 | darkThemeEndTimeChanged(m_darkThemeEndTime = QTime::fromString(darkThemeEndTime, format)); 33 | } 34 | 35 | signals: 36 | void themeColorEnabledChanged(bool themeColorEnabled); 37 | void darkThemeEnabledChanged(bool darkThemeEnabled); 38 | void darkThemeStartTimeChanged(QTime darkThemeStartTime); 39 | void darkThemeEndTimeChanged(QTime darkThemeEndTime); 40 | 41 | private: 42 | bool m_themeColorEnabled; 43 | bool m_darkThemeEnabled; 44 | QTime m_darkThemeStartTime; 45 | QTime m_darkThemeEndTime; 46 | }; 47 | 48 | #endif // THEMECONFIG_H 49 | -------------------------------------------------------------------------------- /src/core/utils/darkthemetimer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Tim Süberkrüb 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "darkthemetimer.h" 21 | 22 | DarkThemeTimer::DarkThemeTimer(QObject *parent) 23 | : QObject(parent) 24 | { 25 | m_timer = new QTimer(this); 26 | m_timer->setInterval(60000); 27 | connect(m_timer, &QTimer::timeout, this, &DarkThemeTimer::update); 28 | } 29 | 30 | void DarkThemeTimer::start() 31 | { 32 | m_timer->start(); 33 | } 34 | 35 | void DarkThemeTimer::stop() 36 | { 37 | m_timer->stop(); 38 | } 39 | 40 | void DarkThemeTimer::update() 41 | { 42 | bool isDark = false; 43 | QTime now = QTime::currentTime(); 44 | if (m_endTime > m_startTime) { 45 | isDark = (now > m_startTime && now < m_endTime); 46 | } 47 | else { 48 | isDark = (now > m_startTime || now < m_endTime ); 49 | } 50 | isActiveTimeChanged(m_isActiveTime = isDark); 51 | } 52 | -------------------------------------------------------------------------------- /src/core/utils/darkthemetimer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Tim Süberkrüb 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef DARKTHEMETIMER_H 21 | #define DARKTHEMETIMER_H 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | class DarkThemeTimer : public QObject 28 | { 29 | Q_OBJECT 30 | Q_PROPERTY(QTime startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged) 31 | Q_PROPERTY(QTime endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged) 32 | Q_PROPERTY(bool isActiveTime MEMBER m_isActiveTime NOTIFY isActiveTimeChanged) 33 | public: 34 | explicit DarkThemeTimer(QObject *parent = nullptr); 35 | 36 | QTime startTime() const { return m_startTime; } 37 | void setStartTime(QTime startTime) { startTimeChanged(m_startTime = startTime); } 38 | 39 | QTime endTime() const { return m_endTime; } 40 | void setEndTime(QTime endTime) { endTimeChanged(m_endTime = endTime); } 41 | 42 | Q_INVOKABLE void start(); 43 | Q_INVOKABLE void stop(); 44 | 45 | signals: 46 | void startTimeChanged(QTime startTime); 47 | void endTimeChanged(QTime endTime); 48 | void isActiveTimeChanged(bool isActiveTime); 49 | 50 | private: 51 | QTime m_startTime; 52 | QTime m_endTime; 53 | QTimer* m_timer; 54 | bool m_isActiveTime; 55 | 56 | public slots: 57 | Q_INVOKABLE void update(); 58 | 59 | }; 60 | 61 | #endif // DARKTHEMETIMER_H 62 | -------------------------------------------------------------------------------- /src/main/browserapplication.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2018 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | #include "browserapplication.h" 28 | 29 | BrowserApplication::BrowserApplication(QObject *parent) 30 | : QObject(parent) 31 | { 32 | 33 | } 34 | 35 | void BrowserApplication::load() 36 | { 37 | // Load settings 38 | m_settings.load(); 39 | 40 | // Start dark theme time 41 | m_darkThemeTimer.start(); 42 | 43 | // Load translations 44 | BrowserApplication::loadTranslations(); 45 | 46 | // register core types 47 | qmlRegisterUncreatableType("core", 1, 0, "SearchConfig", "SearchConfig (from module core) may not be created directly."); 48 | qmlRegisterUncreatableType("core", 1, 0, "StartConfig", "StartConfig (from module core) may not be created directly."); 49 | 50 | qmlRegisterUncreatableType("core", 1, 0, "Tab", "Tab (from module core) may not be created directly."); 51 | qmlRegisterType("core", 1, 0, "TabsModel"); 52 | 53 | qmlRegisterType("core", 1, 0, "DownloadsModel"); 54 | 55 | #ifdef Q_OS_MACOS 56 | initMacOsEventListener(&m_evListener); 57 | #endif 58 | 59 | // Register context properties 60 | m_engine.rootContext()->setContextProperty("Settings", &m_settings); 61 | m_engine.rootContext()->setContextProperty("Session", &m_session); 62 | m_engine.rootContext()->setContextProperty("DarkThemeTimer", &m_darkThemeTimer); 63 | #ifdef Q_OS_MACOS 64 | m_engine.rootContext()->setContextProperty("MacEvents", &m_evListener); 65 | #endif 66 | 67 | // setup qml imports 68 | m_engine.addImportPath("qrc:/"); 69 | 70 | // load main ui 71 | m_engine.load(QUrl(QLatin1String("qrc:/ui/Main.qml"))); 72 | 73 | m_loaded = true; 74 | } 75 | 76 | void BrowserApplication::openUrl(const QUrl &url, bool incognito) 77 | { 78 | if (!m_loaded) { 79 | qWarning() << "Ignoring request to open url because the application is not loaded yet"; 80 | return; 81 | } 82 | QMetaObject::invokeMethod(m_engine.rootObjects()[0], "openUrl", 83 | Q_ARG(QVariant, QVariant(url)), Q_ARG(QVariant, QVariant(incognito))); 84 | } 85 | 86 | void BrowserApplication::openStartUrl(bool incognito) 87 | { 88 | if (!m_loaded) { 89 | qCritical() << "Cannot open start url as the application is not loaded yet"; 90 | return; 91 | } 92 | QMetaObject::invokeMethod(m_engine.rootObjects()[0], "openNewWindow", 93 | Q_ARG(QVariant, QVariant(incognito)), Q_ARG(QVariant, QVariant(true))); 94 | } 95 | 96 | void BrowserApplication::onMessageReceived(const QString &message) 97 | { 98 | QStringList fragments = message.split(' '); 99 | 100 | if (fragments[0] == QStringLiteral("open")) { 101 | if (fragments.count() >= 2) { 102 | auto url = QUrl(fragments[1]); 103 | openUrl(url); 104 | } else { 105 | openStartUrl(); 106 | } 107 | } else if (fragments[0] == QStringLiteral("open_incognito")) { 108 | if (fragments.count() >= 2) { 109 | auto url = QUrl(fragments[1]); 110 | openUrl(url, true); 111 | } else { 112 | openStartUrl(true); 113 | } 114 | } else { 115 | qWarning() << "Received invalid message" << message; 116 | } 117 | } 118 | 119 | void BrowserApplication::onAboutToQuit() 120 | { 121 | if (m_settings.dirty()) { 122 | m_settings.save(); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/main/browserapplication.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2018 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #ifndef BROWSERAPPLICATION_H 25 | #define BROWSERAPPLICATION_H 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "../core/models/tabsmodel.h" 36 | #include "../core/models/tab.h" 37 | #include "../core/models/downloadsmodel.h" 38 | #include "../core/settings/settings.h" 39 | #include "../core/session/session.h" 40 | #include "../core/utils/darkthemetimer.h" 41 | 42 | #ifdef Q_OS_MACOS 43 | #include "mac/MacOsEventListener.h" 44 | #endif 45 | 46 | class BrowserApplication : public QObject 47 | { 48 | Q_OBJECT 49 | public: 50 | explicit BrowserApplication(QObject *parent = nullptr); 51 | 52 | static void loadTranslations() 53 | { 54 | #ifndef QT_NO_TRANSLATION 55 | QString locale = QLocale::system().name(); 56 | 57 | // Find the translations directory 58 | const QString path = QLatin1String("liri-browser/translations"); 59 | const QString translationsDir = 60 | QStandardPaths::locate(QStandardPaths::GenericDataLocation, 61 | path, 62 | QStandardPaths::LocateDirectory); 63 | 64 | // Load translations 65 | QTranslator *appTranslator = new QTranslator(qGuiApp); 66 | if (appTranslator->load(QStringLiteral("%1/browser_%3").arg(translationsDir, locale))) { 67 | QCoreApplication::installTranslator(appTranslator); 68 | } else if (locale == QLatin1String("C") || 69 | locale.startsWith(QLatin1String("en"))) { 70 | // English is the default, it's translated anyway 71 | delete appTranslator; 72 | } 73 | #endif 74 | } 75 | 76 | void load(); 77 | void openUrl(const QUrl &url, bool incognito=false); 78 | void openStartUrl(bool incognito=false); 79 | 80 | public slots: 81 | void onMessageReceived(const QString &message); 82 | void onAboutToQuit(); 83 | 84 | private: // members 85 | #ifdef Q_OS_MACOS 86 | MacOsEventListener m_evListener; 87 | #endif 88 | QQmlApplicationEngine m_engine; 89 | Settings m_settings; 90 | Session m_session; 91 | DarkThemeTimer m_darkThemeTimer; 92 | bool m_loaded = false; 93 | 94 | }; 95 | 96 | #endif // BROWSERAPPLICATION_H 97 | -------------------------------------------------------------------------------- /src/main/mac/MacOsEventListener.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Ivan Fateev 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #ifndef MACOSEVENTLISTENER_H 25 | #define MACOSEVENTLISTENER_H 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | enum class TabEvent { 32 | ShiftTab, 33 | CtrlShiftTab 34 | }; 35 | class MacOsEventListener; 36 | 37 | MacOsEventListener* initMacOsEventListener(MacOsEventListener *parent); 38 | 39 | class MacOsEventListener : public QObject { 40 | Q_OBJECT 41 | 42 | public: 43 | MacOsEventListener(QObject* parent = nullptr) : QObject(parent) {} 44 | 45 | signals: 46 | void ctrlShiftTabPressed(); 47 | void ctrlTabPressed(); 48 | 49 | }; 50 | 51 | #endif // MACOSEVENTLISTENER_H 52 | -------------------------------------------------------------------------------- /src/main/mac/MacOsEventListener.mm: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Ivan Fateev 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #include "MacOsEventListener.h" 25 | #import 26 | #import 27 | 28 | #include 29 | 30 | #ifndef MAC_OS_X_VERSION_10_12 31 | # define MAC_OS_X_VERSION_10_12 101200 32 | #endif 33 | 34 | static const unsigned short kTabKey = 0x30; 35 | 36 | MacOsEventListener* initMacOsEventListener(MacOsEventListener* ev) 37 | { 38 | #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12 39 | [NSEvent addLocalMonitorForEventsMatchingMask: 40 | (NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown | NSEventMaskOtherMouseDown | NSEventMaskKeyDown) 41 | handler:^NSEvent*(NSEvent *incomingEvent) { 42 | NSUInteger flags = [incomingEvent modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; 43 | if ([incomingEvent type] == NSEventTypeKeyDown && ([incomingEvent keyCode] == kTabKey) && (flags & NSEventModifierFlagControl)) { 44 | if(flags & NSEventModifierFlagShift) { 45 | emit ev->ctrlShiftTabPressed(); 46 | } else { 47 | emit ev->ctrlTabPressed(); 48 | } 49 | } 50 | return incomingEvent; 51 | }]; 52 | #else 53 | [NSEvent addLocalMonitorForEventsMatchingMask: 54 | (NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask | NSKeyDownMask) 55 | handler:^NSEvent*(NSEvent *incomingEvent) { 56 | NSUInteger flags = [incomingEvent modifierFlags] & NSDeviceIndependentModifierFlagsMask; 57 | if ([incomingEvent type] == NSKeyDown && ([incomingEvent keyCode] == kTabKey) && (flags & NSControlKeyMask)) { 58 | if(flags & NSShiftKeyMask) { 59 | emit ev->ctrlShiftTabPressed(); 60 | } else { 61 | emit ev->ctrlTabPressed(); 62 | } 63 | } 64 | return incomingEvent; 65 | }]; 66 | #endif 67 | } 68 | -------------------------------------------------------------------------------- /src/main/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #ifndef QT_NO_TRANSLATION 32 | #include 33 | #endif 34 | #include 35 | 36 | 37 | #include 38 | 39 | #include "browserapplication.h" 40 | 41 | 42 | int main(int argc, char *argv[]) 43 | { 44 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 45 | QQuickStyle::setStyle(QLatin1String("Material")); 46 | 47 | QtSingleApplication app(argc, argv); 48 | 49 | // Set app info 50 | app.setOrganizationName(QStringLiteral("Liri")); 51 | app.setOrganizationDomain(QStringLiteral("liri.io")); 52 | app.setApplicationName(QStringLiteral("Browser")); 53 | app.setApplicationVersion(QStringLiteral(PROJECT_VERSION)); 54 | app.setDesktopFileName(QStringLiteral("io.liri.Browser.desktop")); 55 | app.setWindowIcon(QIcon(":/res/icons/512x512/io.liri.Browser.png")); 56 | 57 | // Set the X11 WM_CLASS so X11 desktops can find the desktop file 58 | qputenv("RESOURCE_NAME", "io.liri.Browser"); 59 | 60 | QCommandLineParser parser; 61 | parser.setApplicationDescription(QStringLiteral("Liri Browser\n\nA cross-platform Material Design web browser")); 62 | parser.addHelpOption(); 63 | parser.addVersionOption(); 64 | 65 | QCommandLineOption incognitoOption(QStringLiteral("incognito"), QStringLiteral("Open incognito mode")); 66 | parser.addOption(incognitoOption); 67 | 68 | parser.addPositionalArgument("urls", "Space-separated list of urls to open"); 69 | 70 | parser.process(app); 71 | 72 | bool incognito = parser.isSet(incognitoOption); 73 | auto args = parser.positionalArguments(); 74 | 75 | // Send messages to already running instance (if any) 76 | if (app.isRunning()) { 77 | qDebug() << "Already running"; 78 | if (args.count() > 0) { 79 | for (const QString &arg: args) { 80 | QString message = incognito ? QStringLiteral("open_incognito ") 81 | : QStringLiteral("open "); 82 | message.append(QUrl(arg).toString(QUrl::FullyEncoded)); 83 | app.sendMessage(message); 84 | } 85 | } else { 86 | QString message = incognito ? QStringLiteral("open_incognito") 87 | : QStringLiteral("open"); 88 | app.sendMessage(message); 89 | } 90 | return 0; 91 | } 92 | 93 | QtWebEngine::initialize(); 94 | 95 | BrowserApplication browser; 96 | 97 | QObject::connect(&app, &QtSingleApplication::messageReceived, 98 | &browser, &BrowserApplication::onMessageReceived); 99 | 100 | QObject::connect(&app, &QApplication::aboutToQuit, 101 | &browser, &BrowserApplication::onAboutToQuit); 102 | 103 | browser.load(); 104 | 105 | if (args.count() > 0) { 106 | // Open urls from commandline arguments 107 | for (const QString &arg: args) { 108 | browser.openUrl(QUrl(arg), incognito); 109 | } 110 | } else { 111 | browser.openStartUrl(incognito); 112 | } 113 | 114 | return app.exec(); 115 | } 116 | -------------------------------------------------------------------------------- /src/ui/Main.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtWebEngine 1.1 26 | import core 1.0 27 | import "." 28 | 29 | QtObject { 30 | id: root 31 | 32 | property var windows: [] 33 | 34 | property WebEngineProfile defaultProfile: WebEngineProfile { 35 | persistentCookiesPolicy: Settings.startConfig.persistentCookies 36 | ? WebEngineProfile.ForcePersistentCookies 37 | : WebEngineProfile.NoPersistentCookies 38 | storageName: "liri-browser" 39 | onDownloadRequested: { 40 | __handleDownloadRequest(download); 41 | } 42 | } 43 | 44 | property WebEngineProfile incognitoProfile: WebEngineProfile { 45 | offTheRecord: true 46 | onDownloadRequested: { 47 | __handleDownloadRequest(download); 48 | } 49 | } 50 | 51 | property DownloadsModel downloadsModel: DownloadsModel {} 52 | 53 | property Component browserWindowComponent: Component { 54 | BrowserWindow { 55 | profile: root.defaultProfile 56 | downloadsModel: root.downloadsModel 57 | } 58 | } 59 | 60 | property Binding darkStartTimeBinding: Binding { 61 | target: DarkThemeTimer 62 | property: "startTime" 63 | value: Settings.themeConfig.darkThemeStartTime 64 | } 65 | 66 | property Binding darkEndTimeBinding: Binding { 67 | target: DarkThemeTimer 68 | property: "endTime" 69 | value: Settings.themeConfig.darkThemeEndTime 70 | } 71 | 72 | function __handleDownloadRequest(download) { 73 | download.accept(); 74 | downloadsModel.add(download); 75 | } 76 | 77 | function openWindowRequest(request) { 78 | var window = newWindow(false, false); 79 | window.openRequest(request); 80 | window.showNormal(); 81 | } 82 | 83 | function openUrl(url, incognito) { 84 | for (var i=0; i 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtQuick.Controls.Material 2.0 26 | import Fluid.Controls 1.0 27 | import ".." 28 | 29 | Item { 30 | id: actionBar 31 | property list actions 32 | property color foregroundColor: Material.foreground 33 | property bool animationsEnabled: true 34 | property int iconSize: Units.iconSizes.smallMedium 35 | 36 | function itemAt(index) { 37 | return actionRepeater.itemAt(index); 38 | } 39 | 40 | implicitHeight: childrenRect.height 41 | implicitWidth: childrenRect.width 42 | 43 | Row { 44 | Repeater { 45 | id: actionRepeater 46 | model: actions 47 | delegate: ToolButton { 48 | id: iconButton 49 | visible: model.visible 50 | implicitHeight: 40 51 | implicitWidth: 40 52 | icon.name: model.icon.name 53 | icon.source: model.icon.source 54 | icon.width: actionBar.iconSize 55 | icon.height: actionBar.iconSize 56 | enabled: model.enabled 57 | icon.color: enabled ? foregroundColor : ColorUtils.shadeColor(foregroundColor, 0.5) 58 | onClicked: actions[index].triggered(iconButton) 59 | 60 | Behavior on icon.color { 61 | enabled: animationsEnabled 62 | ColorAnimation { 63 | duration: Units.mediumDuration 64 | } 65 | } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/ui/drawer/Drawer.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtQuick.Layouts 1.0 26 | import QtQuick.Controls 2.0 27 | import Fluid.Controls 1.0 28 | 29 | Drawer { 30 | property list contentComponents 31 | property int currentContentIndex: -1 32 | 33 | function loadContent(index) { 34 | currentContentIndex = index; 35 | } 36 | 37 | width: 256 38 | // Disabled dragMargin because Drawer shows different content based 39 | // on which menu item is selected. 40 | // The drag-in gesture also conflicts with the browser webview 41 | // scrollbar on some platforms 42 | dragMargin: 0 43 | 44 | ColumnLayout { 45 | anchors { 46 | fill: parent 47 | margins: 2 * Units.smallSpacing 48 | } 49 | 50 | spacing: 2 * Units.smallSpacing 51 | 52 | TitleLabel { 53 | text: contentLoader.item ? contentLoader.item.title : "" 54 | } 55 | 56 | Loader { 57 | id: contentLoader 58 | Layout.fillHeight: true 59 | Layout.fillWidth: true 60 | sourceComponent: currentContentIndex >= 0 ? contentComponents[currentContentIndex] : null 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/ui/drawer/DrawerContentItem.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb (https://github.com/tim-sueberkrueb) 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | import QtQuick 2.0 21 | 22 | Item { 23 | property string title 24 | } 25 | -------------------------------------------------------------------------------- /src/ui/drawer/content/downloads/DownloadItemDelegate.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtQuick.Layouts 1.0 26 | import QtQuick.Controls 2.0 27 | import Fluid.Controls 1.0 28 | import QtWebEngine 1.1 29 | 30 | 31 | ListItem { 32 | property var downloadsModel 33 | readonly property var download: downloadsModel.get(index) 34 | 35 | readonly property bool finished: download ? download.state === WebEngineDownloadItem.DownloadCompleted : false 36 | readonly property bool failed: download ? download.state === WebEngineDownloadItem.DownloadInterrupted : false 37 | readonly property real progress: download ? download.receivedBytes / download.totalBytes : 0 38 | 39 | implicitHeight: 74 40 | 41 | contentItem: RowLayout { 42 | anchors { 43 | fill: parent 44 | topMargin: Units.smallSpacing 45 | bottomMargin: Units.smallSpacing 46 | } 47 | 48 | spacing: Units.smallSpacing 49 | 50 | Icon { 51 | source: Utils.iconurl("file/file_download") 52 | } 53 | 54 | ColumnLayout { 55 | Layout.fillWidth: true 56 | Layout.fillHeight: true 57 | spacing: Units.smallSpacing 58 | 59 | Label { 60 | Layout.fillWidth: true 61 | text: download ? download.path : "" 62 | elide: Text.ElideLeft 63 | } 64 | 65 | ProgressBar { 66 | Layout.fillWidth: true 67 | visible: !finished 68 | height: finished ? 0 : implicitHeight 69 | value: progress 70 | } 71 | 72 | CaptionLabel { 73 | Layout.fillWidth: true 74 | elide: Text.ElideRight 75 | text: { 76 | if (finished) { 77 | return qsTr("Finished"); 78 | } else if (failed) { 79 | return qsTr("Failed") + ": %1".arg(download.interruptReasonString); 80 | } else { 81 | return "%1%".arg(Math.round(progress * 100).toString()); 82 | } 83 | } 84 | } 85 | } 86 | 87 | ToolButton { 88 | icon.source: Utils.iconUrl("navigation/cancel") 89 | onClicked: { 90 | // Cancel engine download 91 | download.cancel(); 92 | // Remove from model 93 | downloadsModel.remove(index); 94 | } 95 | } 96 | } 97 | 98 | onClicked: { 99 | // Open download file externally 100 | if (finished) 101 | Qt.openUrlExternally("file://" + download.path); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/ui/drawer/content/downloads/DrawerDownloadsContent.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.4 25 | import QtQuick.Layouts 1.0 26 | import QtQuick.Controls 2.0 27 | import Fluid.Controls 1.0 28 | import core 1.0 29 | import "../../.." 30 | 31 | DrawerContentItem { 32 | id: drawerContentItem 33 | title: qsTr("Downloads") 34 | 35 | property DownloadsModel downloadsModel 36 | 37 | ListView { 38 | anchors.fill: parent 39 | clip: true 40 | model: downloadsModel 41 | delegate: DownloadItemDelegate { 42 | downloadsModel: drawerContentItem.downloadsModel 43 | } 44 | } 45 | 46 | Label { 47 | id: lblNoDownloads 48 | anchors.top: parent.top 49 | 50 | visible: downloadsModel.count === 0 51 | text: qsTr("No downloads for this session") 52 | wrapMode: Text.WordWrap 53 | width: Math.min(noDownloadsMetrics.width, parent.width) 54 | 55 | TextMetrics { 56 | id: noDownloadsMetrics 57 | font: lblNoDownloads.font 58 | text: lblNoDownloads.text 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/ui/expansionbar/ExpansionBar.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import Fluid.Controls 1.0 26 | 27 | Item { 28 | id: expansionBar 29 | 30 | property list contentComponents 31 | property int currentContentIndex: -1 32 | property bool showing: false 33 | 34 | signal opened() 35 | signal closed() 36 | 37 | function loadContent(index) { 38 | currentContentIndex = index; 39 | } 40 | 41 | function open() { 42 | showing = true; 43 | showAnimation.start(); 44 | } 45 | 46 | function close() { 47 | showing = false; 48 | closeAnimation.start(); 49 | } 50 | 51 | clip: true 52 | 53 | Rectangle { 54 | id: contentContainer 55 | anchors { 56 | left: parent.left 57 | right: parent.right 58 | bottom: parent.bottom 59 | } 60 | 61 | height: 48 62 | 63 | Loader { 64 | id: contentLoader 65 | anchors { 66 | fill: parent 67 | leftMargin: 2 * Units.smallSpacing 68 | rightMargin: 2 * Units.smallSpacing 69 | } 70 | sourceComponent: currentContentIndex >= 0 ? contentComponents[currentContentIndex] : null 71 | } 72 | } 73 | 74 | NumberAnimation { 75 | id: showAnimation 76 | target: expansionBar 77 | property: "implicitHeight" 78 | duration: Units.mediumDuration 79 | easing.type: Easing.InOutQuad 80 | to: 56 81 | onStopped: opened() 82 | } 83 | 84 | NumberAnimation { 85 | id: closeAnimation 86 | target: expansionBar 87 | property: "implicitHeight" 88 | duration: Units.mediumDuration 89 | easing.type: Easing.InOutQuad 90 | to: 0 91 | onStopped: closed() 92 | } 93 | 94 | Connections { 95 | enabled: currentContentIndex >= 0 && contentLoader.status === Loader.Ready 96 | target: contentLoader.item 97 | onClosed: { 98 | expansionBar.close(); 99 | currentContentIndex = -1; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/ui/expansionbar/ExpansionBarItem.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | 26 | Item { 27 | signal closed() 28 | } 29 | -------------------------------------------------------------------------------- /src/ui/omnibox/Omnibox.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtQuick.Layouts 1.0 26 | import QtQuick.Controls 2.0 27 | import QtQuick.Controls.Material 2.0 28 | import Fluid.Controls 1.0 29 | import Fluid.Core 1.0 30 | import dperini.regexweburl 1.0 31 | import core 1.0 32 | import QtQml.StateMachine 1.0 as DSM 33 | import ".." 34 | 35 | Item { 36 | id: omnibox 37 | property TabController tabController 38 | property TabsModel tabsModel 39 | property string searchUrl 40 | property alias editingUrl: editing.active 41 | property color defaultAccentColor 42 | property bool editingCompleted: idle.active 43 | 44 | signal emptyTabActivated 45 | 46 | function focusUrlField() { 47 | showUrlField.forceActiveFocus(); 48 | textField.selectAll(); 49 | } 50 | 51 | function checkForEmptyTab() { 52 | if (tabsModel.active.url.toString().length === 0) { 53 | emptyTabActivated(); 54 | } 55 | } 56 | 57 | implicitHeight: 40 58 | implicitWidth: 256 59 | 60 | Rectangle { 61 | id: container 62 | anchors.fill: parent 63 | 64 | radius: 2 65 | color: Color.lightDark(Material.background, Material.color(Material.Grey, Material.Shade200), "white") 66 | 67 | RowLayout { 68 | anchors { 69 | fill: parent 70 | leftMargin: Units.smallSpacing 71 | rightMargin: Units.smallSpacing 72 | } 73 | 74 | TextField { 75 | id: showUrlField 76 | 77 | text: editingCompleted ? tabsModel.active.url.toString() : textField.text 78 | 79 | Layout.fillHeight: true 80 | Layout.fillWidth: true 81 | 82 | Material.foreground: Material.color(Material.Grey, Material.Shade900) 83 | Material.accent: Color.lightDark(Material.background, defaultAccentColor, Material.background) 84 | 85 | bottomPadding: Units.smallSpacing 86 | 87 | background: Item {} 88 | font.pixelSize: 14 89 | readOnly: true 90 | 91 | TextField { 92 | id: textField 93 | 94 | anchors.fill: parent 95 | visible: editingUrl 96 | 97 | selectionColor: Material.accent 98 | selectByMouse: true 99 | bottomPadding: Units.smallSpacing 100 | background: Rectangle { color: container.color } 101 | font.pixelSize: 14 102 | 103 | onAccepted: { 104 | var url = UrlUtils.validUrl(text, searchUrl); 105 | if (!tabsModel.active.valid) { 106 | tabController.openUrl(url); 107 | } 108 | else { 109 | var reload = (tabsModel.active.url === url); 110 | tabsModel.active.url = url; 111 | if (reload) 112 | tabsModel.active.reload(); 113 | } 114 | textField.focus = false; 115 | } 116 | } 117 | } 118 | } 119 | 120 | Rectangle { 121 | visible: tabsModel.active.valid && width < parent.width 122 | anchors { 123 | bottom: parent.bottom 124 | left: parent.left 125 | } 126 | 127 | height: 2 128 | width: parent.width * (tabsModel.active.loadProgress / 100) 129 | color: Color.lightDark(Material.background, defaultAccentColor, Material.background) 130 | 131 | Behavior on width { 132 | enabled: tabsModel.active.loading 133 | NumberAnimation { 134 | duration: 200 135 | easing.type: Easing.InOutQuad 136 | } 137 | } 138 | } 139 | 140 | Connections { 141 | target: tabsModel 142 | onActiveChanged: { 143 | textField.text = tabsModel.active.url.toString(); 144 | checkForEmptyTab(); 145 | } 146 | } 147 | 148 | Connections { 149 | target: tabsModel.active 150 | onUrlChanged: { 151 | textField.text = tabsModel.active.url; 152 | } 153 | } 154 | 155 | Binding { 156 | when: tabsModel.empty 157 | target: showUrlField 158 | property: "text" 159 | value: "" 160 | } 161 | 162 | Binding { 163 | when: tabsModel.empty 164 | target: textField 165 | property: "text" 166 | value: "" 167 | } 168 | 169 | Behavior on color { 170 | ColorAnimation { duration: 100 } 171 | } 172 | } 173 | 174 | DSM.StateMachine { 175 | id: stateMachine 176 | initialState: idle 177 | running: true 178 | 179 | DSM.State { 180 | id: idle 181 | 182 | onEntered: { 183 | checkForEmptyTab(); 184 | textField.text = showUrlField.text; 185 | } 186 | 187 | DSM.SignalTransition { 188 | signal: showUrlField.activeFocusChanged 189 | guard: showUrlField.activeFocus === true 190 | targetState: editing 191 | } 192 | 193 | DSM.SignalTransition { 194 | signal: emptyTabActivated 195 | targetState: editing 196 | } 197 | } 198 | 199 | DSM.State { 200 | id: editing 201 | 202 | onEntered: { 203 | textField.forceActiveFocus(); 204 | } 205 | 206 | DSM.SignalTransition { 207 | signal: tabsModel.activeChanged 208 | targetState: idle 209 | } 210 | 211 | DSM.SignalTransition { 212 | signal: textField.activeFocusChanged 213 | guard: textField.activeFocus === false 214 | targetState: canceledEditing 215 | } 216 | } 217 | 218 | DSM.State { 219 | id: canceledEditing 220 | 221 | onEntered: { 222 | checkForEmptyTab(); 223 | } 224 | 225 | DSM.SignalTransition { 226 | signal: emptyTabActivated 227 | targetState: editing 228 | } 229 | 230 | DSM.SignalTransition { 231 | signal: showUrlField.activeFocusChanged 232 | guard: showUrlField.activeFocus === true 233 | targetState: editing 234 | } 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /src/ui/overlay/BaseOverlay.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtQuick.Controls.Material 2.0 26 | import Fluid.Controls 1.0 27 | import Fluid.Effects 1.0 as FluidEffects 28 | 29 | Rectangle { 30 | id: baseOverlay 31 | 32 | property bool showing: false 33 | 34 | signal opened() 35 | signal closed() 36 | 37 | function open() { 38 | showing = true; 39 | openAnimation.start(); 40 | } 41 | 42 | function close() { 43 | showing = false; 44 | closeAnimation.start(); 45 | } 46 | 47 | visible: height > 0 48 | 49 | layer.enabled: true 50 | layer.effect: FluidEffects.Elevation { elevation: 2 } 51 | 52 | implicitWidth: 300 53 | height: 0 54 | 55 | color: Material.background 56 | 57 | NumberAnimation { 58 | id: openAnimation 59 | target: baseOverlay 60 | property: "height" 61 | from: 0 62 | to: 48 63 | duration: Units.mediumDuration 64 | easing.type: Easing.InOutQuad 65 | onStopped: opened() 66 | } 67 | 68 | NumberAnimation { 69 | id: closeAnimation 70 | target: baseOverlay 71 | property: "height" 72 | from: 48 73 | to: 0 74 | duration: Units.mediumDuration 75 | easing.type: Easing.InOutQuad 76 | onStopped: closed() 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/ui/overlay/SearchOverlay.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtQuick.Layouts 1.0 26 | import QtQuick.Controls 2.0 27 | import Fluid.Controls 1.0 28 | 29 | BaseOverlay { 30 | id: searchOverlay 31 | 32 | property bool searchEnabled: true 33 | 34 | signal searchRequested(string text, bool backwards) 35 | 36 | onOpened: { 37 | searchField.forceActiveFocus(); 38 | } 39 | 40 | implicitWidth: childrenRect.width 41 | 42 | RowLayout { 43 | id: rowLayout 44 | 45 | anchors { 46 | top: parent.top 47 | bottom: parent.bottom 48 | } 49 | 50 | Item { implicitWidth: 16 } // Spacer 51 | 52 | TextField { 53 | id: searchField 54 | selectByMouse: true 55 | enabled: searchEnabled 56 | placeholderText: qsTr("Find in page") 57 | onAccepted: { 58 | searchRequested(searchField.text, false); 59 | } 60 | } 61 | 62 | ToolButton { 63 | enabled: searchEnabled 64 | implicitHeight: 40 65 | implicitWidth: 40 66 | icon.source: Utils.iconUrl("hardware/keyboard_arrow_up") 67 | onClicked: { 68 | searchRequested(searchField.text, true); 69 | } 70 | } 71 | 72 | ToolButton { 73 | enabled: searchEnabled 74 | implicitHeight: 40 75 | implicitWidth: 40 76 | icon.source: Utils.iconUrl("hardware/keyboard_arrow_down") 77 | onClicked: { 78 | searchRequested(searchField.text, false); 79 | } 80 | } 81 | 82 | ToolButton { 83 | implicitHeight: 40 84 | implicitWidth: 40 85 | icon.source: Utils.iconUrl("navigation/close") 86 | onClicked: { 87 | searchOverlay.close(); 88 | } 89 | } 90 | 91 | Item { implicitWidth: 8 } // Spacer 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/ui/qmldir: -------------------------------------------------------------------------------- 1 | module ui 2 | 3 | # components 4 | ActionBar 1.0 components/ActionBar.qml 5 | 6 | # tabview 7 | TabView 1.0 tabview/TabView.qml 8 | TabBar 1.0 tabview/TabBar.qml 9 | TabController 1.0 tabview/TabController.qml 10 | TabContentView 1.0 tabview/TabContentView.qml 11 | TabContent 1.0 tabview/TabContent.qml 12 | singleton TabType 1.0 tabview/TabType.qml 13 | 14 | # content 15 | WebContent 1.0 tabview/content/WebContent.qml 16 | SettingsContent 1.0 tabview/content/SettingsContent.qml 17 | LazyWebContent 1.0 tabview/content/LazyWebContent.qml 18 | 19 | # omnibox 20 | Omnibox 1.0 omnibox/Omnibox.qml 21 | 22 | # toolbar 23 | Toolbar 1.0 toolbar/Toolbar.qml 24 | 25 | # expansionbar 26 | ExpansionBar 1.0 expansionbar/ExpansionBar.qml 27 | 28 | # overlays 29 | BaseOverlay 1.0 overlay/BaseOverlay.qml 30 | SearchOverlay 1.0 overlay/SearchOverlay.qml 31 | 32 | # drawer 33 | Drawer 1.0 drawer/Drawer.qml 34 | DrawerContentItem 1.0 drawer/DrawerContentItem.qml 35 | 36 | # drawer content 37 | DrawerDownloadsContent 1.0 drawer/content/downloads/DrawerDownloadsContent.qml 38 | 39 | # window 40 | BrowserWindow 1.0 window/BrowserWindow.qml 41 | 42 | # utils 43 | singleton ColorUtils 1.0 utils/ColorUtils.qml 44 | singleton UrlUtils 1.0 utils/UrlUtils.qml 45 | -------------------------------------------------------------------------------- /src/ui/tabview/TabActionManager.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtWebEngine 1.0 26 | 27 | QtObject { 28 | property QtObject internal: QtObject { 29 | property var uid 30 | property var tabController 31 | } 32 | 33 | signal newWebViewRequested(var request) 34 | signal closeRequested() 35 | signal fullScreenRequested(var request) 36 | signal openUrlInNewTabRequested(var url) 37 | signal openUrlInNewPrivateWindowRequested(var url) 38 | 39 | onFullScreenRequested: { 40 | internal.tabController.fullScreenRequested(request); 41 | } 42 | 43 | onNewWebViewRequested: { 44 | switch (request.destination) { 45 | case WebEngineView.NewViewInTab: 46 | case WebEngineView.NewViewInBackgroundTab: 47 | internal.tabController.openNewViewRequest(request); 48 | break; 49 | case WebEngineView.NewViewInDialog: 50 | case WebEngineView.NewViewInWindow: 51 | internal.tabController.newWindowRequested(request); 52 | break; 53 | } 54 | } 55 | 56 | onOpenUrlInNewTabRequested: { 57 | internal.tabController.openUrl(url); 58 | } 59 | 60 | onOpenUrlInNewPrivateWindowRequested: { 61 | internal.tabController.openUrlInNewPrivateWindowRequested(url); 62 | } 63 | 64 | onCloseRequested: { 65 | tabController.removeTab(internal.uid); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/ui/tabview/TabBarActionBar.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import ".." 26 | 27 | ActionBar {} 28 | -------------------------------------------------------------------------------- /src/ui/tabview/TabContent.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import core 1.0 26 | 27 | Item { 28 | property var tab 29 | property var actionManager 30 | } 31 | -------------------------------------------------------------------------------- /src/ui/tabview/TabContentView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import core 1.0 26 | 27 | Item { 28 | id: tabContentView 29 | property TabsModel tabsModel 30 | property ListModel pages: ListModel {} 31 | readonly property Item container: contentContainer 32 | 33 | function registerPage(uid, item) { 34 | // Make item invisible for now 35 | item.visible = false; 36 | // Reparent and anchor item 37 | item.parent = contentContainer; 38 | item.anchors.fill = contentContainer; 39 | // Create visibility binding 40 | item.visible = Qt.binding(function(){ return tabsModel.active.uid === uid }); 41 | // Append to pages model 42 | pages.append({ 43 | uid: uid, 44 | item: item 45 | }); 46 | } 47 | 48 | function unregisterPage(uid) { 49 | var page = pageByUID(uid); 50 | if (!page) 51 | return false; 52 | // Make item invisible 53 | page.item.visible = false; 54 | // Destroy item 55 | page.item.destroy(); 56 | // Remove page from model 57 | pages.remove(indexByUID(uid)); 58 | return true; 59 | } 60 | 61 | function pageByUID(uid) { 62 | for (var i=0; i 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtWebEngine 1.1 26 | import core 1.0 27 | import ".." 28 | 29 | QtObject { 30 | id: tabController 31 | property TabBar tabBar 32 | property TabContentView tabContentView 33 | property TabsModel tabsModel 34 | property WebEngineProfile profile 35 | property int lastUID: 0 36 | 37 | property Component tabPageComponent: Component { TabPage {} } 38 | property Component actionManagerComponent: Component { TabActionManager {} } 39 | 40 | property QtObject internal: QtObject { 41 | property Connections tabBarCloseConnections: Connections { 42 | target: tabBar 43 | onTabCloseRequested: { 44 | removeTab(uid); 45 | } 46 | } 47 | } 48 | 49 | signal newWindowRequested(var request) 50 | signal fullScreenRequested(var request) 51 | signal openUrlInNewPrivateWindowRequested(var url) 52 | 53 | function completeTabsRestore() { 54 | for (var i = 0; i < tabContentView.pages.count; ++i) { 55 | var tabPage = tabContentView.pages.get(i).item; 56 | tabPage.loadContent = true; 57 | } 58 | } 59 | 60 | function openUrl(url, background, data) { 61 | if (!data) { 62 | data = {} 63 | } 64 | data['url'] = UrlUtils.validUrl(url.toString()); 65 | data['background'] = background; 66 | 67 | addTab(TabType.fromUrl(url), data); 68 | } 69 | 70 | function openNewViewRequest(request) { 71 | addTab ( 72 | TabType.webview, { 73 | background: request.destination === WebEngineView.NewViewInBackgroundTab, 74 | properties: { 75 | profile: profile, 76 | request: request 77 | } 78 | }, 79 | tabsModel.row(tabsModel.active) + 1 // Insert tab next to the current tab 80 | ); 81 | } 82 | 83 | function addTab(type, data, index) { 84 | // Register new unique id 85 | var uid = lastUID++; 86 | var page; 87 | 88 | if (!("properties" in data)) 89 | data["properties"] = {}; 90 | 91 | // Add tab model representation 92 | tabsModel.insert(uid, index || -1); 93 | 94 | // Create page 95 | page = tabPageComponent.createObject(tabContentView.container, { 96 | profile: profile, 97 | tab: tabsModel.byUID(uid), 98 | loadContent: !('loadContent' in data) || data['loadContent'] 99 | }); 100 | 101 | // Load page 102 | page.load(type, data); 103 | 104 | // Create an action manager for this tab 105 | page.actionManager = actionManagerComponent.createObject(page, {}); 106 | page.actionManager.internal.tabController = tabController; 107 | page.actionManager.internal.uid = uid; 108 | page.activeTab = Qt.binding(function () { return tabsModel.active } ); 109 | // Register page to content view 110 | tabContentView.registerPage(uid, page); 111 | 112 | // Set the page active if wanted 113 | if (!data.background) { 114 | tabsModel.setActive(uid); 115 | } 116 | } 117 | 118 | function removeTab(uid) { 119 | // Remove model representation 120 | if (!tabsModel.remove(uid)) 121 | return false; 122 | // Unregister page 123 | tabContentView.unregisterPage(uid); 124 | return true; 125 | } 126 | 127 | function tabByUID(uid) { 128 | return tabsModel.byUID(uid); 129 | } 130 | 131 | function pageByUID(uid) { 132 | return tabContentView.pageByUID(uid); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/ui/tabview/TabDelegate.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtQuick.Layouts 1.0 26 | import QtQuick.Controls 2.0 27 | import QtQuick.Controls.Material 2.0 28 | import QtGraphicalEffects 1.0 29 | import Fluid.Controls 1.0 30 | import ".." 31 | 32 | Rectangle { 33 | property string title 34 | property url iconSource 35 | property color iconColor: "transparent" 36 | property bool adaptIconColor: false 37 | property bool active: false 38 | property color foregroundColor: Material.foreground 39 | property color backgroundColor: Material.background 40 | 41 | signal closeRequested() 42 | 43 | implicitWidth: 200 44 | 45 | color: backgroundColor 46 | 47 | RowLayout { 48 | anchors { 49 | fill: parent 50 | leftMargin: Units.smallSpacing 51 | } 52 | 53 | spacing: Units.smallSpacing 54 | 55 | Image { 56 | id: icon 57 | 58 | property bool ready: status === Image.Ready 59 | 60 | Layout.preferredHeight: height 61 | Layout.preferredWidth: width 62 | 63 | width: icon.ready ? sourceSize.width : 0 64 | height: icon.ready ? sourceSize.height : 0 65 | source: iconSource 66 | clip: true 67 | sourceSize.width: Units.iconSizes.small 68 | sourceSize.height: Units.iconSizes.small 69 | 70 | ColorOverlay { 71 | anchors.fill: icon 72 | visible: iconColor != "transparent" || adaptIconColor 73 | source: icon 74 | color: { 75 | if (adaptIconColor) { 76 | return Color.lightDark(backgroundColor, "transparent", "white"); 77 | } else { 78 | return iconColor; 79 | } 80 | } 81 | } 82 | 83 | Behavior on height { 84 | NumberAnimation { 85 | duration: Units.shortDuration 86 | easing.type: Easing.InOutQuad 87 | } 88 | } 89 | 90 | Behavior on width { 91 | NumberAnimation { 92 | duration: Units.shortDuration 93 | easing.type: Easing.InOutQuad 94 | } 95 | } 96 | } 97 | 98 | Label { 99 | Layout.fillWidth: true 100 | // Use translation id to fix duplicate strings 101 | //= new-tab 102 | text: title || qsTr("New tab") 103 | color: active ? foregroundColor : ColorUtils.shadeColor(foregroundColor, 0.5) 104 | elide: Text.ElideRight 105 | 106 | Behavior on color { 107 | ColorAnimation { 108 | duration: Units.mediumDuration 109 | easing.type: Easing.InOutQuad 110 | } 111 | } 112 | } 113 | 114 | ToolButton { 115 | icon.source: Utils.iconUrl("navigation/close") 116 | onClicked: closeRequested() 117 | icon.color: active ? foregroundColor : ColorUtils.shadeColor(foregroundColor, 0.5) 118 | icon.width: 18 119 | icon.height: 18 120 | implicitHeight: 24 121 | implicitWidth: 24 122 | 123 | Behavior on icon.color { 124 | ColorAnimation { 125 | duration: Units.mediumDuration 126 | easing.type: Easing.InOutQuad 127 | } 128 | } 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/ui/tabview/TabIndicator.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | 26 | Rectangle { 27 | implicitHeight: 2 28 | } 29 | -------------------------------------------------------------------------------- /src/ui/tabview/TabPage.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import ".." 26 | 27 | Item { 28 | id: tabPage 29 | 30 | // binding. should be set from outside 31 | property var activeTab 32 | property var tab 33 | property var actionManager 34 | property var profile 35 | property url previousUrl 36 | property bool loading: false 37 | property bool loadContent: true 38 | property var contentFabric 39 | property var initData 40 | 41 | property Component settingsContentComponent: Component { 42 | SettingsContent { 43 | tab: tabPage.tab 44 | actionManager: tabPage.actionManager 45 | } 46 | } 47 | 48 | property Component webContentComponent: Component { 49 | WebContent { 50 | tab: tabPage.tab 51 | actionManager: tabPage.actionManager 52 | } 53 | } 54 | 55 | property var contentItem 56 | property int tabType 57 | 58 | function tryCreateContent() { 59 | if (contentItem || !loadContent || tab !== activeTab) 60 | return; 61 | 62 | contentFabric(); 63 | } 64 | 65 | function openUrl(url) { 66 | load(TabType.fromUrl(url), { 67 | url: url, 68 | }); 69 | } 70 | 71 | function load(type, data) { 72 | if (loading) 73 | return false; 74 | loading = true; 75 | initData = data; 76 | 77 | contentFabric = function() { 78 | var newContent; 79 | 80 | // Destroy old content if necessary 81 | if (contentItem) 82 | contentItem.destroy(); 83 | 84 | // Finalize properties 85 | if (!("properties" in initData)) 86 | initData["properties"] = {}; 87 | 88 | initData.properties["anchors.fill"] = contentContainer; 89 | initData.properties["profile"] = profile; 90 | initData.properties["url"] = initData.url; 91 | 92 | // Create content item 93 | switch(type) { 94 | case TabType.webview: 95 | newContent = webContentComponent.createObject( 96 | contentContainer, 97 | initData.properties 98 | ); 99 | break; 100 | case TabType.settings: 101 | newContent = settingsContentComponent.createObject( 102 | contentContainer, 103 | initData.properties 104 | ); 105 | break; 106 | } 107 | 108 | tabType = type; 109 | contentItem = newContent; 110 | loading = false; 111 | }; 112 | 113 | if (loadContent) { 114 | contentFabric(); 115 | } 116 | 117 | return true; 118 | } 119 | 120 | onActiveTabChanged: { 121 | tryCreateContent(); 122 | } 123 | 124 | onLoadContentChanged: { 125 | if (contentFabric) 126 | tryCreateContent(); 127 | } 128 | 129 | Binding { 130 | target: tab 131 | property: "title" 132 | value: initData ? initData['title'] : "" 133 | when: !contentItem 134 | } 135 | 136 | Binding { 137 | target: tab 138 | property: "url" 139 | value: initData ? initData['url'] : "" 140 | when: !contentItem 141 | } 142 | 143 | Binding { 144 | target: tab 145 | property: "iconUrl" 146 | value: initData ? initData['iconUrl'] : "" 147 | when: !contentItem 148 | } 149 | 150 | Connections { 151 | target: tab 152 | onUrlChanged: { 153 | if (url !== previousUrl) { 154 | var newType = TabType.fromUrl(url); 155 | if (newType !== tabType) { 156 | load(newType, {url: url}); 157 | } 158 | previousUrl = url; 159 | } 160 | } 161 | } 162 | 163 | Item { 164 | id: contentContainer 165 | anchors.fill: parent 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/ui/tabview/TabType.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | pragma Singleton 25 | import QtQuick 2.0 26 | import "../utils" 27 | 28 | QtObject { 29 | property int unknown: -1 30 | property int webview: 0 31 | property int settings: 1 32 | 33 | function fromUrl(url) { 34 | if (UrlUtils.isLiriUrl(url)) { 35 | if (url == "liri://settings") 36 | return settings; 37 | } else { 38 | return webview; 39 | } 40 | return unknown; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/ui/tabview/TabView.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtQuick.Layouts 1.0 26 | import core 1.0 27 | 28 | Item { 29 | id: tabView 30 | property TabsModel tabsModel 31 | property TabBar tabBar: tabBar 32 | 33 | ColumnLayout { 34 | anchors.fill: parent 35 | spacing: 0 36 | 37 | TabBar { 38 | id: tabBar 39 | Layout.fillWidth: true 40 | tabsModel: tabView.tabsModel 41 | } 42 | 43 | Rectangle { 44 | color: "green" 45 | Layout.fillHeight: true 46 | Layout.fillWidth: true 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ui/toolbar/Toolbar.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.0 25 | import QtQuick.Layouts 1.0 26 | import Fluid.Controls 1.0 27 | import core 1.0 28 | import ".." 29 | 30 | Item { 31 | id: toolbar 32 | property TabController tabController 33 | property TabsModel tabsModel 34 | property string searchUrl 35 | property alias omnibox: omnibox 36 | property color defaultAccentColor 37 | 38 | property list leftActions 39 | property list rightActions 40 | 41 | readonly property ActionBar leftActionBar: leftActionBar 42 | readonly property ActionBar rightActionBar: rightActionBar 43 | 44 | implicitHeight: 56 45 | implicitWidth: 256 46 | 47 | RowLayout { 48 | anchors { 49 | fill: parent 50 | rightMargin: 2 * Units.smallSpacing 51 | } 52 | 53 | Layout.alignment: Qt.AlignLeft | Qt.AlignHCenter 54 | 55 | ActionBar { 56 | id: leftActionBar 57 | actions: leftActions 58 | } 59 | 60 | Omnibox { 61 | id: omnibox 62 | Layout.fillWidth: true 63 | tabsModel: toolbar.tabsModel 64 | tabController: toolbar.tabController 65 | searchUrl: toolbar.searchUrl 66 | defaultAccentColor: toolbar.defaultAccentColor 67 | } 68 | 69 | ActionBar { 70 | id: rightActionBar 71 | actions: rightActions 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/ui/ui.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | components/ActionBar.qml 4 | drawer/content/downloads/DownloadItemDelegate.qml 5 | drawer/content/downloads/DrawerDownloadsContent.qml 6 | drawer/Drawer.qml 7 | drawer/DrawerContentItem.qml 8 | expansionbar/ExpansionBar.qml 9 | expansionbar/ExpansionBarItem.qml 10 | Main.qml 11 | omnibox/Omnibox.qml 12 | overlay/BaseOverlay.qml 13 | overlay/SearchOverlay.qml 14 | tabview/content/SettingsContent.qml 15 | tabview/content/WebContent.qml 16 | tabview/TabActionManager.qml 17 | tabview/TabBar.qml 18 | tabview/TabBarActionBar.qml 19 | tabview/TabContent.qml 20 | tabview/TabContentView.qml 21 | tabview/TabController.qml 22 | tabview/TabDelegate.qml 23 | tabview/TabIndicator.qml 24 | tabview/TabPage.qml 25 | tabview/TabType.qml 26 | tabview/TabView.qml 27 | toolbar/Toolbar.qml 28 | utils/ColorUtils.qml 29 | utils/UrlUtils.qml 30 | window/BrowserWindow.qml 31 | window/ShortcutManager.qml 32 | qmldir 33 | utils/qmldir 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/ui/utils/ColorUtils.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | pragma Singleton 25 | import QtQuick 2.0 26 | //import Fluid.Core 1.0 27 | 28 | QtObject { 29 | function asColor(c) { 30 | return Qt.darker(c, 1); 31 | } 32 | 33 | function shadeColor(color, percent) { 34 | // from http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors 35 | color = asColor(color).toString() 36 | var f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF; 37 | return "#"+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/ui/utils/UrlUtils.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2016 Tim Süberkrüb 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | pragma Singleton 25 | import QtQuick 2.0 26 | import dperini.regexweburl 1.0 27 | 28 | QtObject { 29 | property var webUrlRegex: RegexWebUrl.re_weburl 30 | 31 | function isWebUrl(url) { 32 | return url.match(webUrlRegex) !== null; 33 | } 34 | 35 | function isFileUrl(url) { 36 | return url.toString().indexOf("file://") === 0; 37 | } 38 | 39 | function isLiriUrl(url) { 40 | return url.toString().indexOf("liri://") === 0; 41 | } 42 | 43 | function validUrl(url, searchUrl) { 44 | // Valid web url 45 | var isHttped = (url.indexOf("http://") === 0 || url.indexOf("https://") === 0); 46 | var httpedUrl = isHttped ? url : "http://%1".arg(url); 47 | if (isHttped || isWebUrl(httpedUrl)) { 48 | return httpedUrl; 49 | } 50 | // File url 51 | else if (isFileUrl(url)) { 52 | return url; 53 | } 54 | // Liri url 55 | else if (isLiriUrl(url)) { 56 | return url; 57 | } 58 | // Search term 59 | else { 60 | return searchUrl + encodeURIComponent(url); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/ui/utils/qmldir: -------------------------------------------------------------------------------- 1 | module utils 2 | singleton ColorUtils 1.0 ColorUtils.qml 3 | singleton UrlUtils 1.0 UrlUtils.qml 4 | -------------------------------------------------------------------------------- /src/ui/window/ShortcutManager.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of Liri Browser 3 | * 4 | * Copyright (C) 2017 Ivan Fateev 5 | * 6 | * $BEGIN_LICENSE:GPL3+$ 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | * 21 | * $END_LICENSE$ 22 | */ 23 | 24 | import QtQuick 2.7 25 | import QtQuick.Window 2.0 26 | import core 1.0 27 | import ".." 28 | 29 | Item { 30 | id: shortcutManager 31 | 32 | property var window 33 | property Toolbar toolbar 34 | property TabBar tabBar 35 | property SearchOverlay searchOverlay 36 | property var tabsModel: shortcutManager.window.tabsModel 37 | 38 | function setActiveTabByIndex(idx) { 39 | if (idx < 0 || idx >= tabsModel.count) { 40 | return; 41 | } 42 | 43 | tabsModel.setActive(tabsModel.get(idx)); 44 | } 45 | 46 | Connections { 47 | target: Qt.platform.os === "osx" ? MacEvents : null 48 | enabled: Qt.platform.os === "osx" 49 | ignoreUnknownSignals: true 50 | 51 | onCtrlShiftTabPressed: { 52 | tabsModel.setPreviousTabActive(); 53 | } 54 | 55 | onCtrlTabPressed: { 56 | tabsModel.setNextTabActive(); 57 | } 58 | } 59 | 60 | 61 | Shortcut { 62 | autoRepeat: false 63 | sequence: StandardKey.Back 64 | onActivated: { 65 | tabsModel.active.goBack(); 66 | } 67 | } 68 | 69 | Shortcut { 70 | autoRepeat: false 71 | sequence: StandardKey.Forward 72 | onActivated: { 73 | tabsModel.active.goForward(); 74 | } 75 | } 76 | 77 | Shortcut { 78 | autoRepeat: false 79 | sequence: StandardKey.Close 80 | onActivated: { 81 | tabBar.tabCloseRequested(tabsModel.active.uid); 82 | } 83 | } 84 | 85 | Shortcut { 86 | autoRepeat: false 87 | sequence: "Ctrl+l" 88 | onActivated: { 89 | toolbar.omnibox.focusUrlField(); 90 | } 91 | } 92 | 93 | Shortcut { 94 | autoRepeat: false 95 | sequence: StandardKey.Refresh 96 | onActivated: { 97 | tabsModel.active.reload(); 98 | } 99 | } 100 | 101 | Shortcut { 102 | autoRepeat: false 103 | // Ctrl+t is hard-coded as keyboard shorcut 104 | // for adding new tabs regardless 105 | // of the platform to avoid user confusion. 106 | sequence: "Ctrl+t" 107 | onActivated: { 108 | tabBar.newTab(); 109 | } 110 | } 111 | 112 | Shortcut { 113 | autoRepeat: false 114 | // for Mac it's handled via macEvents 115 | // due to bug https://bugreports.qt.io/browse/QTBUG-8596 116 | sequence: "Ctrl+Shift+Tab" 117 | onActivated: { 118 | tabsModel.setPreviousTabActive(); 119 | } 120 | } 121 | 122 | Shortcut { 123 | autoRepeat: false 124 | // for Mac it's handled via macEvents 125 | // due to bug https://bugreports.qt.io/browse/QTBUG-8596 126 | sequence: "Ctrl+Tab" 127 | onActivated: { 128 | tabsModel.setNextTabActive(); 129 | } 130 | } 131 | 132 | Shortcut { 133 | autoRepeat: false 134 | sequence: "Alt+1" 135 | onActivated: { 136 | setActiveTabByIndex(0); 137 | } 138 | } 139 | 140 | Shortcut { 141 | autoRepeat: false 142 | sequence: "Alt+2" 143 | onActivated: { 144 | setActiveTabByIndex(1); 145 | } 146 | } 147 | 148 | Shortcut { 149 | autoRepeat: false 150 | sequence: "Alt+3" 151 | onActivated: { 152 | setActiveTabByIndex(2); 153 | } 154 | } 155 | 156 | Shortcut { 157 | autoRepeat: false 158 | sequence: "Alt+4" 159 | onActivated: { 160 | setActiveTabByIndex(3); 161 | } 162 | } 163 | 164 | Shortcut { 165 | autoRepeat: false 166 | sequence: "Alt+5" 167 | onActivated: { 168 | setActiveTabByIndex(4); 169 | } 170 | } 171 | 172 | Shortcut { 173 | autoRepeat: false 174 | sequence: "Alt+6" 175 | onActivated: { 176 | setActiveTabByIndex(5); 177 | } 178 | } 179 | 180 | Shortcut { 181 | autoRepeat: false 182 | sequence: "Alt+7" 183 | onActivated: { 184 | setActiveTabByIndex(6); 185 | } 186 | } 187 | 188 | Shortcut { 189 | autoRepeat: false 190 | sequence: "Alt+8" 191 | onActivated: { 192 | setActiveTabByIndex(7); 193 | } 194 | } 195 | 196 | Shortcut { 197 | autoRepeat: false 198 | sequence: "Alt+9" 199 | onActivated: { 200 | setActiveTabByIndex(8); 201 | } 202 | } 203 | 204 | Shortcut { 205 | autoRepeat: false 206 | sequence: "Alt+0" 207 | onActivated: { 208 | setActiveTabByIndex(tabsModel.count - 1); 209 | } 210 | } 211 | 212 | Shortcut { 213 | autoRepeat: false 214 | sequence: "Esc" 215 | onActivated: { 216 | if (toolbar.omnibox.editingUrl) { 217 | toolbar.forceActiveFocus(); 218 | } else if (tabsModel.active.loading) { 219 | tabsModel.active.stop(); 220 | } else if (searchOverlay.showing) { 221 | searchOverlay.close(); 222 | } 223 | } 224 | } 225 | 226 | Shortcut { 227 | autoRepeat: false 228 | sequence: "Ctrl+f" 229 | onActivated: { 230 | searchOverlay.open(); 231 | } 232 | } 233 | 234 | Shortcut { 235 | autoRepeat: false 236 | sequence: "Ctrl+n" 237 | onActivated: { 238 | window.root.newWindow().showNormal(); 239 | } 240 | } 241 | 242 | Shortcut { 243 | autoRepeat: false 244 | sequence: "Ctrl+Shift+n" 245 | onActivated: { 246 | window.root.newIncognitoWindow().showNormal(); 247 | } 248 | } 249 | 250 | Shortcut { 251 | autoRepeat: false 252 | sequence: Qt.platform.os == "osx" ? "Ctrl+Meta+F" : "F11" 253 | onActivated: { 254 | window.toggleFullScreen(); 255 | } 256 | } 257 | 258 | } 259 | --------------------------------------------------------------------------------