Falkon Develop
Cross-platform Qt-based web browser
qmltabs.cpp
Go to the documentation of this file.
1/* ============================================================
2* Falkon - Qt web browser
3* Copyright (C) 2018 Anmol Gautam <tarptaeya@gmail.com>
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation, either version 3 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17* ============================================================ */
18#include "qmltabs.h"
19#include "tabwidget.h"
20#include "pluginproxy.h"
21#include "qml/qmlstaticdata.h"
22#include <QQmlEngine>
23
24QmlTabs::QmlTabs(QObject *parent)
25 : QObject(parent)
26{
27 const QList<BrowserWindow*> windows = mApp->windows();
28 for (BrowserWindow *window : windows) {
29 windowCreated(window);
30 }
31
32 connect(mApp->plugins(), &PluginProxy::mainWindowCreated, this, &QmlTabs::windowCreated);
33}
34
35bool QmlTabs::setCurrentIndex(const QVariantMap &map)
36{
37 if (!map.contains(QSL("index"))) {
38 qWarning() << "Unable to set current index:" << "index not defined";
39 return false;
40 }
41
42 const int index = map.value(QSL("index")).toInt();
43
44 const auto window = getWindow(map);
45 if (!window) {
46 return false;
47 }
48 window->tabWidget()->setCurrentIndex(index);
49 return true;
50}
51
52bool QmlTabs::nextTab(int windowId)
53{
54 const auto window = getWindow(windowId);
55 if (!window) {
56 return false;
57 }
58 window->tabWidget()->nextTab();
59 return true;
60}
61
62bool QmlTabs::previousTab(int windowId)
63{
64 const auto window = getWindow(windowId);
65 if (!window) {
66 return false;
67 }
68 window->tabWidget()->previousTab();
69 return true;
70}
71
72bool QmlTabs::moveTab(const QVariantMap &map)
73{
74 if (!map.contains(QSL("from"))) {
75 qWarning() << "Unable to move tab:" << "from not defined";
76 return false;
77 }
78 if (!map.contains(QSL("to"))) {
79 qWarning() << "Unable to move tab:" << "to not defined";
80 return false;
81 }
82
83 const int from = map.value(QSL("from")).toInt();
84 const int to = map.value(QSL("to")).toInt();
85
86 const auto window = getWindow(map);
87 if (!window) {
88 return false;
89 }
90 window->tabWidget()->moveTab(from, to);
91 return true;
92}
93
94bool QmlTabs::pinTab(const QVariantMap &map)
95{
96 if (!map.contains(QSL("index"))) {
97 qWarning() << "Unable to pin tab:" << "index not defined";
98 return false;
99 }
100
101 const int index = map.value(QSL("index")).toInt();
102
103 const auto window = getWindow(map);
104 if (!window) {
105 return false;
106 }
107
108 WebTab *webTab = window->tabWidget()->webTab(index);
109
110 if (webTab->isPinned()) {
111 return false;
112 }
113
114 webTab->togglePinned();
115 return true;
116}
117
118bool QmlTabs::unpinTab(const QVariantMap &map)
119{
120 if (!map.contains(QSL("index"))) {
121 qWarning() << "Unable to unpin tab:" << "index not defined";
122 return false;
123 }
124
125 const int index = map.value(QSL("index")).toInt();
126
127 const auto window = getWindow(map);
128 if (!window) {
129 return false;
130 }
131
132 WebTab *webTab = window->tabWidget()->webTab(index);
133
134 if (!webTab->isPinned()) {
135 return false;
136 }
137
138 webTab->togglePinned();
139 return true;
140}
141
142bool QmlTabs::detachTab(const QVariantMap &map)
143{
144 if (!map.contains(QSL("index"))) {
145 qWarning() << "Unable to detatch tab:" << "index not defined";
146 return false;
147 }
148
149 const int index = map.value(QSL("index")).toInt();
150
151 const auto window = getWindow(map);
152 if (!window) {
153 return false;
154 }
155 window->tabWidget()->detachTab(index);
156 return true;
157}
158
159bool QmlTabs::duplicate(const QVariantMap &map)
160{
161 if (!map.contains(QSL("index"))) {
162 qWarning() << "Unable to duplicate:" << "index not defined";
163 return false;
164 }
165
166 const int index = map.value(QSL("index")).toInt();
167
168 const auto window = getWindow(map);
169 if (!window) {
170 return false;
171 }
172 window->tabWidget()->duplicateTab(index);
173 return true;
174}
175
176bool QmlTabs::closeTab(const QVariantMap &map)
177{
178 if (!map.contains(QSL("index"))) {
179 qWarning() << "Unable to close tab:" << "index not defined";
180 return false;
181 }
182
183 const int index = map.value(QSL("index")).toInt();
184
185 const auto window = getWindow(map);
186 if (!window) {
187 return false;
188 }
189 window->tabWidget()->closeTab(index);
190 return true;
191}
192
193bool QmlTabs::reloadTab(const QVariantMap &map)
194{
195 if (!map.contains(QSL("index"))) {
196 qWarning() << "Unable to reload tab:" << "index not defined";
197 return false;
198 }
199
200 const int index = map.value(QSL("index")).toInt();
201
202 const auto window = getWindow(map);
203 if (!window) {
204 return false;
205 }
206 window->tabWidget()->reloadTab(index);
207 return true;
208}
209
210bool QmlTabs::stopTab(const QVariantMap &map)
211{
212 if (!map.contains(QSL("index"))) {
213 qWarning() << "Unable to close tab:" << "index not defined";
214 return false;
215 }
216
217 const int index = map.value(QSL("index")).toInt();
218
219 const auto window = getWindow(map);
220 if (!window) {
221 return false;
222 }
223 window->tabWidget()->stopTab(index);
224 return true;
225}
226
227QmlTab *QmlTabs::get(const QVariantMap &map) const
228{
229 if (!map.contains(QSL("index"))) {
230 qWarning() << "Unable to set current index:" << "index not defined";
231 return nullptr;
232 }
233
234 const int index = map.value(QSL("index")).toInt();
235
236 const auto window = getWindow(map);
237 if (!window) {
238 return nullptr;
239 }
240 const auto webTab = window->tabWidget()->webTab(index);
241 return QmlStaticData::instance().getTab(webTab);
242}
243
244int QmlTabs::normalTabsCount(int windowId) const
245{
246 const auto window = getWindow(windowId);
247 if (!window) {
248 return -1;
249 }
250 return window->tabWidget()->normalTabsCount();
251}
252
253int QmlTabs::pinnedTabsCount(int windowId) const
254{
255 const auto window = getWindow(windowId);
256 if (!window) {
257 return -1;
258 }
259 return window->tabWidget()->pinnedTabsCount();
260}
261
262QList<QObject*> QmlTabs::getAll(const QVariantMap &map) const
263{
264 const auto window = getWindow(map);
265 if (!window) {
266 return {};
267 }
268
269 const bool withPinned = map.value(QSL("withPinned")).toBool();
270 const QList<WebTab*> tabList = window->tabWidget()->allTabs(withPinned);
271
272 QList<QObject*> list;
273 list.reserve(tabList.size());
274 for (WebTab *tab : tabList) {
275 list.append(QmlStaticData::instance().getTab(tab));
276 }
277
278 return list;
279}
280
281QList<QObject*> QmlTabs::search(const QVariantMap &map)
282{
283 const QString title = map.value(QSL("title")).toString();
284 const QString url = map.value(QSL("url")).toString();
285 const bool withPinned = map.value(QSL("withPinned")).toBool();
286 QList<QObject*> list;
287 for (BrowserWindow *window : mApp->windows()) {
288 for (WebTab *webTab : window->tabWidget()->allTabs(withPinned)) {
289 if (webTab->title().contains(title, Qt::CaseInsensitive)
290 || QString::fromUtf8(webTab->url().toEncoded()).contains(url, Qt::CaseInsensitive)) {
291 list.append(QmlStaticData::instance().getTab(webTab));
292 }
293 }
294 }
295 return list;
296}
297
298bool QmlTabs::addTab(const QVariantMap &map)
299{
300 const QString urlString = map.value(QSL("url")).toString();
301 const auto window = getWindow(map);
302 if (!window) {
303 qDebug() << "Unable to add tab:" << "window not found";
304 return false;
305 }
306 LoadRequest req(QUrl::fromEncoded(urlString.toUtf8()));
307 const int ret = window->tabWidget()->addView(req);
308 return ret != -1 ? true : false;
309}
310
311BrowserWindow *QmlTabs::getWindow(const QVariantMap &map) const
312{
313 const int windowId = map.value(QSL("windowId"), -1).toInt();
314 return getWindow(windowId);
315}
316
317BrowserWindow *QmlTabs::getWindow(int windowId) const
318{
319 if (windowId == -1) {
320 return mApp->getWindow();
321 }
322
323 auto windowIdHash = QmlStaticData::instance().windowIdHash();
324 for (auto it = windowIdHash.cbegin(); it != windowIdHash.cend(); it++) {
325 BrowserWindow *window = it.key();
326 if (QmlStaticData::instance().windowIdHash().value(window, -1) == windowId) {
327 return window;
328 }
329 }
330 qWarning() << "Unable to get window with given windowId";
331 return nullptr;
332}
333
334void QmlTabs::windowCreated(BrowserWindow *window)
335{
336 const int windowId = QmlStaticData::instance().windowIdHash().value(window, -1);
337
338 connect(window->tabWidget(), &TabWidget::changed, this, [this, windowId]{
339 Q_EMIT changed(windowId);
340 });
341
342 connect(window->tabWidget(), &TabWidget::tabInserted, this, [this, windowId](int index){
343 QVariantMap map;
344 map.insert(QSL("windowId"), windowId);
345 map.insert(QSL("index"), index);
346 Q_EMIT tabInserted(map);
347 });
348
349 connect(window->tabWidget(), &TabWidget::tabRemoved, this, [this, windowId](int index){
350 QVariantMap map;
351 map.insert(QSL("windowId"), windowId);
352 map.insert(QSL("index"), index);
353 Q_EMIT tabRemoved(map);
354 });
355
356 connect(window->tabWidget(), &TabWidget::tabMoved, this, [this, windowId](int from, int to){
357 QVariantMap map;
358 map.insert(QSL("windowId"), windowId);
359 map.insert(QSL("from"), from);
360 map.insert(QSL("to"), to);
361 Q_EMIT tabMoved(map);
362 });
363}
TabWidget * tabWidget() const
void mainWindowCreated(BrowserWindow *window)
QHash< BrowserWindow *, int > windowIdHash()
QmlTab * getTab(WebTab *webTab)
static QmlStaticData & instance()
The class exposing a browser tab to QML.
Definition: qmltab.h:32
Q_INVOKABLE bool unpinTab(const QVariantMap &map)
Un-pins a tab.
Definition: qmltabs.cpp:118
Q_INVOKABLE bool addTab(const QVariantMap &map)
Adds a tab.
Definition: qmltabs.cpp:298
Q_INVOKABLE bool closeTab(const QVariantMap &map)
Close a tab.
Definition: qmltabs.cpp:176
Q_INVOKABLE bool stopTab(const QVariantMap &map)
Stops a tab.
Definition: qmltabs.cpp:210
Q_INVOKABLE bool moveTab(const QVariantMap &map)
Moves a tab.
Definition: qmltabs.cpp:72
Q_INVOKABLE bool duplicate(const QVariantMap &map)
Duplicates a tab.
Definition: qmltabs.cpp:159
Q_INVOKABLE QList< QObject * > getAll(const QVariantMap &map=QVariantMap()) const
Gets all the tabs of a window.
Definition: qmltabs.cpp:262
Q_INVOKABLE int pinnedTabsCount(int windowId=-1) const
Get the pinned tabs count in a window.
Definition: qmltabs.cpp:253
QmlTabs(QObject *parent=nullptr)
Definition: qmltabs.cpp:24
Q_INVOKABLE bool setCurrentIndex(const QVariantMap &map)
Sets the current tab in a window.
Definition: qmltabs.cpp:35
Q_INVOKABLE bool nextTab(int windowId=-1)
Sets the next tab as current tab.
Definition: qmltabs.cpp:52
Q_INVOKABLE bool detachTab(const QVariantMap &map)
Detaches a tab.
Definition: qmltabs.cpp:142
Q_INVOKABLE bool previousTab(int windowId=-1)
Sets the previous tab as current tab.
Definition: qmltabs.cpp:62
Q_INVOKABLE bool reloadTab(const QVariantMap &map)
Reloads a tab.
Definition: qmltabs.cpp:193
Q_INVOKABLE QmlTab * get(const QVariantMap &map) const
Gets a tab.
Definition: qmltabs.cpp:227
Q_INVOKABLE bool pinTab(const QVariantMap &map)
Pins a tab.
Definition: qmltabs.cpp:94
Q_INVOKABLE int normalTabsCount(int windowId=-1) const
Get the normal tabs count in a window.
Definition: qmltabs.cpp:244
Q_INVOKABLE QList< QObject * > search(const QVariantMap &map)
Searches tabs against a criteria.
Definition: qmltabs.cpp:281
void changed()
void tabInserted(int index)
void tabRemoved(int index)
void tabMoved(int from, int to)
Definition: webtab.h:40
bool isPinned() const
Definition: webtab.cpp:414
void togglePinned()
Definition: webtab.cpp:715
#define mApp
int value(const QColor &c)
Definition: colors.cpp:238
#define QSL(x)
Definition: qzcommon.h:40