玉兔远程控制 0.1.0-bate4
载入中...
搜索中...
未找到
FrmWebBrowser.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QMessageBox>
4#include <QMenu>
5#include <QFile>
6#include <QDir>
7#include <QPrinter>
8#include <QInputDialog>
9#include <QSplitter>
10#include <QVBoxLayout>
11#include <QWebEngineProfile>
12#include <QWebEngineHistory>
13#include <QWebEngineSettings>
14#include <QWebEngineFindTextResult>
15#include <QRegularExpression>
16#include <QWebEngineCookieStore>
17#include <QStandardPaths>
18#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
19 #include <QWebEngineProfileBuilder>
20#endif
21#include <QLoggingCategory>
22#include "RabbitCommonDir.h"
23#include "RabbitCommonTools.h"
24#include "FrmWebBrowser.h"
25#include "FrmPopup.h"
26
27static Q_LOGGING_CATEGORY(log, "WebBrowser.Browser")
28CFrmWebBrowser::CFrmWebBrowser(CParameterWebBrowser *pPara, bool bMenuBar, QWidget *parent)
29 : QWidget{parent}
30 , m_pMenuBar(nullptr)
31 , m_pPara(pPara)
32 , m_pToolBar(nullptr)
33 , m_pBack(nullptr)
34 , m_pForward(nullptr)
35 , m_pRefresh(nullptr)
36 , m_pStop(nullptr)
37 , m_pFind(nullptr)
38 , m_pFindNext(nullptr)
39 , m_pFindPrevious(nullptr)
40 , m_pZoomOriginal(nullptr)
41 , m_pZoomIn(nullptr)
42 , m_pZoomOut(nullptr)
43 , m_pFavAction(nullptr)
44 , m_pGo(nullptr)
45 , m_pAddPage(nullptr)
46 , m_pAddPageIncognito(nullptr)
47 , m_pAddWindow(nullptr)
48 , m_pPrint(nullptr)
49 , m_pPrintToPdf(nullptr)
50 , m_pAddWindowIncognito(nullptr)
51 , m_pDownload(nullptr)
52 , m_pInspector(nullptr)
53 , m_pUrl(nullptr)
54 , m_pUrlLineEdit(nullptr)
55 , m_pProgressBar(nullptr)
56 , m_pTab(nullptr)
57 , m_DownloadManager(pPara)
58{
59 qDebug(log) << Q_FUNC_INFO;
60 bool check = false;
61
62 setWindowIcon(QIcon::fromTheme("web-browser"));
63
64 QVBoxLayout* pLayout = new QVBoxLayout(this);
65 if(!pLayout) {
66 return;
67 }
68 pLayout->setSpacing(0);
69 pLayout->setContentsMargins(0, 0, 0, 0);
70 setLayout(pLayout);
71
72 m_pToolBar = new QToolBar(this);
73 if(m_pToolBar) {
74 pLayout->addWidget(m_pToolBar);
75 }
76
77 m_pBack = m_pToolBar->addAction(
78 QIcon::fromTheme("go-previous"), tr("Back"),
79 this, [&](){
80 CFrmWebView* pWeb = CurrentView();
81 if(pWeb && pWeb->page())
82 pWeb->page()->action(QWebEnginePage::Back)->trigger();
83 });
84 m_pBack->setEnabled(false);
85 m_pBack->setStatusTip(m_pBack->text());
86 m_pForward = m_pToolBar->addAction(
87 QIcon::fromTheme("go-next"), tr("Forward"),
88 this, [&](){
89 CFrmWebView* pWeb = CurrentView();
90 if(pWeb && pWeb->page())
91 pWeb->page()->action(QWebEnginePage::Forward)->trigger();
92 });
93 m_pForward->setEnabled(false);
94 m_pForward->setStatusTip(m_pForward->text());
95 m_pRefresh = m_pToolBar->addAction(
96 QIcon::fromTheme("view-refresh"), tr("Refresh"),
97 this, [&](){
98 CFrmWebView* pWeb = CurrentView();
99 if(pWeb && pWeb->page())
100 pWeb->page()->action(QWebEnginePage::Reload)->trigger();
101 });
102 m_pRefresh->setShortcut(QKeySequence(QKeySequence::Refresh));
103 m_pRefresh->setStatusTip(m_pRefresh->text());
104
105 m_pUrlLineEdit = new QLineEdit(this);
106 m_pFavAction = new QAction(m_pUrlLineEdit);
107 m_pUrlLineEdit->addAction(m_pFavAction, QLineEdit::LeadingPosition);
108 m_pUrlLineEdit->setClearButtonEnabled(true);
109 m_pUrl = m_pToolBar->addWidget(m_pUrlLineEdit);
110 check = connect(m_pUrlLineEdit, &QLineEdit::returnPressed,
111 this, &CFrmWebBrowser::slotReturnPressed);
112 Q_ASSERT(check);
113 check = connect(m_pUrlLineEdit, &QLineEdit::editingFinished,
114 this, &CFrmWebBrowser::slotReturnPressed);
115 Q_ASSERT(check);
116 m_pGo = new QAction(QIcon::fromTheme("go-next"), tr("go"), m_pUrlLineEdit);
117 m_pGo->setStatusTip(m_pGo->text());
118 check = connect(m_pGo, &QAction::triggered, this, &CFrmWebBrowser::slotReturnPressed);
119 Q_ASSERT(check);
120 m_pUrlLineEdit->addAction(m_pGo, QLineEdit::TrailingPosition);
121 m_pGo->setVisible(false);
122 check = connect(m_pUrlLineEdit, &QLineEdit::textEdited,
123 this, [&](const QString &text){
124 QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(sender());
125 if(pLineEdit) {
126 if(text.isEmpty()) {
127 if(m_pGo->isVisible())
128 m_pGo->setVisible(false);
129 } else {
130 if(!m_pGo->isVisible())
131 m_pGo->setVisible(true);
132 }
133 }
134 });
135 Q_ASSERT(check);
136
137 m_pAddPage = m_pToolBar->addAction(QIcon::fromTheme("add"), tr("Add tab page"),
138 this, [&](){
139 CreateWindow(QWebEnginePage::WebBrowserTab);
140 if(!m_pPara->GetTabUrl().isEmpty()) {
141 m_pUrlLineEdit->setText(m_pPara->GetTabUrl());
142 slotReturnPressed();
143 }
144 });
145 m_pAddPage->setStatusTip(m_pAddPage->text());
146 Q_ASSERT(check);
147 m_pDownload = m_pToolBar->addAction(
148 QIcon::fromTheme("emblem-downloads"), tr("Download Manager"));
149 m_pDownload->setCheckable(true);
150 m_pDownload->setStatusTip(m_pDownload->text());
151 check = connect(m_pDownload, &QAction::toggled,
152 this, [&](bool checked){
153 if(checked)
154 m_DownloadManager.show();
155 else
156 m_DownloadManager.hide();
157 });
158 Q_ASSERT(check);
159 check = connect(&m_DownloadManager, &CFrmDownloadManager::sigVisible, this,
160 [&](bool visible){
161 if(m_pDownload)
162 m_pDownload->setChecked(visible);
163 });
164 Q_ASSERT(check);
165
166 m_pProgressBar = new QProgressBar(this);
167 if(m_pProgressBar) {
168 pLayout->addWidget(m_pProgressBar);
169 m_pProgressBar->setMaximumHeight(1);
170 m_pProgressBar->setTextVisible(false);
171 m_pProgressBar->show();
172 m_pProgressBar->setStyleSheet("QProgressBar {border: 0px} QProgressBar::chunk {background-color: #da4453}");
173 }
174
175 m_pTab = new QTabWidget(this);
176 if(m_pTab) {
177 m_pTab->setTabsClosable(true);
178 m_pTab->setUsesScrollButtons(true);
179 m_pTab->setMovable(true);
180 m_pTab->setElideMode(Qt::TextElideMode::ElideRight);
181 pLayout->addWidget(m_pTab);
182 }
183 check = connect(m_pTab, &QTabWidget::currentChanged,
184 this, &CFrmWebBrowser::slotTabCurrentChanged);
185 Q_ASSERT(check);
186 check = connect(m_pTab, &QTabWidget::tabCloseRequested,
187 this, &CFrmWebBrowser::slotTabCloseRequested);
188 Q_ASSERT(check);
189
190 m_DownloadManager.hide();
191 QWebEngineProfile::defaultProfile()->setDownloadPath(m_pPara->GetDownloadFolder());
192 check = connect(QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested,
193 &m_DownloadManager, &CFrmDownloadManager::slotDownloadRequested);
194 Q_ASSERT(check);
195 check = connect(m_pPara, &CParameterWebBrowser::sigDownloadFolderChanged,
196 this, [&](){
197 QWebEngineProfile::defaultProfile()->setDownloadPath(m_pPara->GetDownloadFolder());
198 if(m_profile)
199 m_profile->setDownloadPath(m_pPara->GetDownloadFolder());
200 });
201 Q_ASSERT(check);
202
203 InitMenu(&m_Menu);
204 if(bMenuBar)
205 {
206 m_pMenuBar = new QMenuBar(this);
207 if(m_pMenuBar) {
208 m_Menu.setTitle(tr("Operate"));
209 m_pMenuBar->addMenu(&m_Menu);
210 pLayout->setMenuBar(m_pMenuBar);
211 }
212 }
213}
214
215CFrmWebBrowser::~CFrmWebBrowser()
216{
217 qDebug(log) << Q_FUNC_INFO;
218 if(m_pToolBar) {
219 m_pToolBar->deleteLater();
220 m_pToolBar = nullptr;
221 }
222 if(m_pTab) {
223 m_pTab->deleteLater();
224 m_pTab = nullptr;
225 }
226
227 if(m_pPara->GetClearCookie() && m_profile)
228 m_profile->cookieStore()->deleteAllCookies();
229 if(m_pPara->GetClearHttpCache() && m_profile)
230 m_profile->clearHttpCache();
231}
232
233QMenu* CFrmWebBrowser::GetMenu(QWidget *parent)
234{
235 if(m_Menu.actions().isEmpty())
236 return nullptr;
237 return &m_Menu;
238}
239
240QWebEngineView* CFrmWebBrowser::CreateWindow(
241 QWebEnginePage::WebWindowType type, bool offTheRecord)
242{
243 qDebug(log) << "Create window:" << type;
244
245 CFrmWebView* pView = nullptr;
246 switch (type) {
247 case QWebEnginePage::WebBrowserTab: {
248 auto pTab = CreateTab(&pView, offTheRecord);
249 int index = m_pTab->addTab(pTab, pView->favIcon(), tr("New page"));
250 if(-1 < index)
251 m_pTab->setCurrentIndex(index);
252 break;
253 }
254 case QWebEnginePage::WebBrowserBackgroundTab: {
255 auto pTab = CreateTab(&pView, offTheRecord);
256 int index = m_pTab->currentIndex();
257 m_pTab->addTab(pTab, pView->favIcon(), tr("New page"));
258 if(-1 < index && index != m_pTab->currentIndex())
259 m_pTab->setCurrentIndex(index);
260 break;
261 }
262 case QWebEnginePage::WebBrowserWindow: {
263 auto pWin = new CFrmWebBrowser(m_pPara, true);
264 if(pWin) {
265 pView = qobject_cast<CFrmWebView*>(
266 pWin->CreateWindow(QWebEnginePage::WebBrowserTab));
267 pWin->setAttribute(Qt::WA_DeleteOnClose);
268 auto pMainWin = RabbitCommon::CTools::GetMainWindow();
269 if(pMainWin)
270 pWin->resize(pMainWin->frameGeometry().width(),
271 pMainWin->frameGeometry().height());
272 pWin->show();
273 }
274 break;
275 }
276 case QWebEnginePage::WebDialog: {
277 // Test: Resource\html\TestQWebEnginePageWebDialog.html
278 auto popup = new CFrmPopup(GetProfile(offTheRecord), this);
279 pView = popup->GetView();
280 }
281 }
282
283 return pView;
284}
285
286void CFrmWebBrowser::SetConnect(CFrmWebView* pWeb)
287{
288 bool check = false;
289 if(!pWeb) return;
290 check = connect(pWeb, &CFrmWebView::sigDevToolsRequested,
291 this, [&](){
292 if(m_pInspector)
293 m_pInspector->setChecked(true);
294 });
295 Q_ASSERT(check);
296 check = connect(pWeb, &CFrmWebView::sigWebActionEnabledChanged,
297 this, [this, pWeb](QWebEnginePage::WebAction webAction, bool enabled){
298 if(!IsCurrentView(pWeb)) return;
299 switch(webAction){
300 case QWebEnginePage::WebAction::Back:
301 m_pBack->setEnabled(enabled);
302 break;
303 case QWebEnginePage::WebAction::Forward:
304 m_pForward->setEnabled(enabled);
305 break;
306 case QWebEnginePage::WebAction::Reload: {
307 m_pRefresh->setEnabled(enabled);
308 if(m_pRefresh->isEnabled())
309 m_pToolBar->insertAction(m_pUrl, m_pRefresh);
310 else
311 m_pToolBar->removeAction(m_pRefresh);
312 break;
313 }
314 case QWebEnginePage::WebAction::Stop: {
315 m_pStop->setEnabled(enabled);
316 if(m_pStop->isEnabled())
317 m_pToolBar->insertAction(m_pUrl, m_pStop);
318 else
319 m_pToolBar->removeAction(m_pStop);
320 break;
321 }
322 default:
323 break;
324 }
325 });
326 check = connect(pWeb, &QWebEngineView::urlChanged,
327 this, [&](const QUrl &url){
328 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
329 if(IsCurrentView(pWeb))
330 m_pUrlLineEdit->setText(url.toString());
331 });
332 Q_ASSERT(check);
333 check = connect(pWeb, &CFrmWebView::titleChanged,
334 this, [&](const QString &title) {
335 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
336 int index = IndexOfTab(pWeb);
337 if(-1 < index) {
338 m_pTab->setTabText(index, title);
339 setWindowTitle(title);
340 emit sigUpdateTitle();
341 }
342 });
343 Q_ASSERT(check);
344 check = connect(pWeb, &CFrmWebView::favIconChanged,
345 this, [&](const QIcon &icon){
346 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
347 int index = IndexOfTab(pWeb);
348 if(-1 < index) {
349 m_pTab->setTabIcon(index, icon);
350 setWindowIcon(icon);
351 emit sigUpdateTitle();
352 }
353 });
354 Q_ASSERT(check);
355 check = connect(pWeb, &CFrmWebView::sigLinkHovered,
356 this, &CFrmWebBrowser::sigInformation);
357 Q_ASSERT(check);
358 check = connect(pWeb, &CFrmWebView::sigCloseRequested,
359 this, &CFrmWebBrowser::slotViewCloseRequested);
360 Q_ASSERT(check);
361 check = connect(pWeb, &CFrmWebView::loadProgress,
362 this, [&](int progress){
363 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
364 if(IsCurrentView(pWeb))
365 m_pProgressBar->setValue(progress);
366 });
367 Q_ASSERT(check);
368 m_pProgressBar->setValue(pWeb->progress());
369#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
370 check = connect(pWeb, &CFrmWebView::printFinished,
371 this, &CFrmWebBrowser::slotPrintFinished);
372 Q_ASSERT(check);
373 check = connect(pWeb, &CFrmWebView::pdfPrintingFinished,
374 this, &CFrmWebBrowser::slotPdfPrintingFinished);
375 Q_ASSERT(check);
376#endif
377}
378
379QWebEngineProfile* CFrmWebBrowser::GetProfile(bool offTheRecord)
380{
381 if(offTheRecord)
382 return QWebEngineProfile::defaultProfile();
383 if(m_profile)
384 return m_profile.get();
385
386#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
387 const QString name = "io.github.KangLin.RabbitRemoteControl."
388 + QLatin1StringView(qWebEngineChromiumVersion());
389 QWebEngineProfileBuilder profileBuilder;
390 m_profile.reset(profileBuilder.createProfile(name));
391#else
392 const QString name = "io.github.KangLin.RabbitRemoteControl";
393 m_profile.reset(new QWebEngineProfile(name));
394#endif
395 if(!m_profile)
396 return QWebEngineProfile::defaultProfile();
397 m_profile->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
398 m_profile->settings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true);
399 m_profile->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
400 m_profile->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, false);
401 m_profile->settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true);
402 m_profile->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
403#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
404 m_profile->settings()->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, false);
405#endif
406 m_profile->setDownloadPath(m_pPara->GetDownloadFolder());
407 bool check = connect(m_profile.get(), &QWebEngineProfile::downloadRequested,
408 &m_DownloadManager, &CFrmDownloadManager::slotDownloadRequested);
409 Q_ASSERT(check);
410 qDebug(log) << "User agent:" << m_profile->httpUserAgent()
411 << "Persistent path:" << m_profile->persistentStoragePath()
412 << "Cache path:" << m_profile->cachePath()
413 << "Storage name:" << m_profile->storageName()
414 << "Cookie:" << m_profile->cookieStore()
415 << "Is off the Record:" << m_profile->isOffTheRecord()
416 << "Download:" << m_profile->downloadPath();
417 return m_profile.get();
418}
419
420CFrmWebView *CFrmWebBrowser::CreateWebView(bool offTheRecord)
421{
422 auto pView = new CFrmWebView(this);
423 if(pView) {
424 auto profile = GetProfile(offTheRecord);
425// #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
426// profile->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime);
427// #endif
428 auto page = new QWebEnginePage(profile, pView);
429 pView->setPage(page);
430 }
431 return pView;
432}
433
434QWidget* CFrmWebBrowser::CreateTab(CFrmWebView **view, bool offTheRecord)
435{
436 QSplitter *pSplitter = new QSplitter(Qt::Vertical, this);
437 if(pSplitter) {
438 pSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
439 //pSplitter->setContentsMargins(0, 0, 0, 0);
440 CFrmWebView* pWeb = nullptr;
441 if(view) {
442 if(*view) {
443 pWeb = *view;
444 } else {
445 pWeb = CreateWebView(offTheRecord);
446 *view = pWeb;
447 }
448 } else {
449 pWeb = CreateWebView(offTheRecord);
450 }
451 if(pWeb) {
452 pSplitter->addWidget(pWeb);
453 SetConnect(pWeb);
454 }
455 }
456 return pSplitter;
457}
458
459CFrmWebView *CFrmWebBrowser::CurrentView(ViewType type)
460{
461 auto w = m_pTab->currentWidget();
462 if(!w) return nullptr;
463 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
464 if(!pSplitter) return nullptr;
465 int index = (int)type;
466 if(0 > index && pSplitter->count() <= index) return nullptr;
467 return qobject_cast<CFrmWebView*>(pSplitter->widget(index));
468}
469
470CFrmWebView* CFrmWebBrowser::GetView(int index, ViewType type)
471{
472 if(0 > index || m_pTab->count() <= index) return nullptr;
473 auto w = m_pTab->widget(index);
474 if(!w) return nullptr;
475 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
476 if(!pSplitter) return nullptr;
477 int idx = (int)type;
478 if(0 > idx && pSplitter->count() <= idx) return nullptr;
479 return qobject_cast<CFrmWebView*>(pSplitter->widget(idx));
480}
481
482bool CFrmWebBrowser::IsCurrentView(CFrmWebView *pView)
483{
484 auto w = m_pTab->currentWidget();
485 if(!w) return false;
486 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
487 if(!pSplitter) return false;
488 return -1 != pSplitter->indexOf(pView);
489}
490
491int CFrmWebBrowser::IndexOfTab(CFrmWebView *pView)
492{
493 int nRet = -1;
494 if(!pView) return nRet;
495 QWidget* p = qobject_cast<QWidget*>(pView->parent());
496 if(!p) return nRet;
497 nRet = m_pTab->indexOf(p);
498 return nRet;
499}
500
501int CFrmWebBrowser::InitMenu(QMenu *pMenu)
502{
503 bool check = false;
504 if(!pMenu) return 0;
505 pMenu->addAction(m_pBack);
506 pMenu->addAction(m_pForward);
507 pMenu->addAction(m_pRefresh);
508 m_pStop = pMenu->addAction(QIcon::fromTheme("media-playback-stop"), tr("Stop"),
509 this, [&](){
510 CFrmWebView* pWeb = CurrentView();
511 if(pWeb && pWeb->page())
512 pWeb->page()->action(QWebEnginePage::Stop)->trigger();
513 });
514 m_pStop->setEnabled(false);
515
516 pMenu->addSeparator();
517 pMenu->addAction(m_pAddPage);
518 m_pAddPageIncognito = pMenu->addAction(
519 QIcon::fromTheme("add"), tr("Add incognito tab"),
520 this, [&](){
521 CreateWindow(QWebEnginePage::WebBrowserTab, true);
522 if(!m_pPara->GetTabUrl().isEmpty()) {
523 m_pUrlLineEdit->setText(m_pPara->GetTabUrl());
524 slotReturnPressed();
525 }
526 });
527 m_pAddPageIncognito->setStatusTip(m_pAddPageIncognito->text());
528 m_pAddWindow = pMenu->addAction(
529 QIcon::fromTheme("add"), tr("Add window"),
530 this, [&](){
531 CreateWindow(QWebEnginePage::WebBrowserWindow);
532 });
533 m_pAddWindow->setVisible(false);
534 m_pAddWindow->setStatusTip(m_pAddWindow->text());
535 m_pAddWindowIncognito = pMenu->addAction(
536 QIcon::fromTheme("add"), tr("Add Incognito Window"),
537 this, [&](){
538 CreateWindow(QWebEnginePage::WebBrowserWindow, true);
539 });
540 m_pAddWindowIncognito->setVisible(false);
541 m_pAddWindowIncognito->setStatusTip(m_pAddWindowIncognito->text());
542
543 pMenu->addSeparator();
544 m_pFind = pMenu->addAction(
545 QIcon::fromTheme("edit-find"), tr("&Find"), this,
546 [&](){
547 CFrmWebView* pWeb = CurrentView();
548 if(pWeb) {
549 bool ok = false;
550 QString search = QInputDialog::getText(this, tr("Find"),
551 tr("Find:"), QLineEdit::Normal,
552 m_szFindText, &ok);
553 if (ok && !search.isEmpty()) {
554 m_szFindText = search;
555#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
556 pWeb->findText(m_szFindText, QWebEnginePage::FindFlags(),
557 [&](const QWebEngineFindTextResult& result){
558 if (result.numberOfMatches() == 0) {
559 emit sigInformation(tr("\"%1\" not found.").arg(m_szFindText));
560 } else {
561 emit sigInformation(tr("\"%1\" found: %2/%3").arg(m_szFindText, QString::number(result.activeMatch()), QString::number(result.numberOfMatches())));
562 }
563 });
564#else
565 pWeb->findText(m_szFindText, QWebEnginePage::FindFlags(), [this](bool found) {
566 if (!found)
567 emit sigInformation(tr("\"%1\" not found.").arg(m_szFindText));
568 });
569#endif
570 }
571 }
572 });
573 m_pFind->setShortcuts(QKeySequence::Find);
574 m_pFind->setStatusTip(m_pFind->text());
575
576 m_pFindNext = pMenu->addAction(
577 QIcon::fromTheme("go-next"), tr("Find &Next"), this,
578 [this]() {
579 CFrmWebView* pWeb = CurrentView();
580 if(pWeb && !m_szFindText.isEmpty()) {
581 pWeb->findText(m_szFindText);
582 }
583 });
584 m_pFindNext->setShortcut(QKeySequence::FindNext);
585 m_pFindNext->setText(m_pFindNext->text());
586
587 m_pFindPrevious = pMenu->addAction(
588 QIcon::fromTheme("go-previous"), tr("Find &Previous"), this,
589 [&]() {
590 CFrmWebView* pWeb = CurrentView();
591 if(pWeb && !m_szFindText.isEmpty()) {
592 pWeb->findText(m_szFindText, QWebEnginePage::FindBackward);
593 }
594 });
595 m_pFindPrevious->setShortcut(QKeySequence::FindPrevious);
596 m_pFindPrevious->setStatusTip(m_pFindPrevious->text());
597
598 pMenu->addSeparator();
599 m_pZoomOriginal = pMenu->addAction(
600 QIcon::fromTheme("zoom-original"), tr("Original"));
601 m_pZoomOriginal->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
602 m_pZoomOriginal->setStatusTip(tr("Original"));
603 m_pZoomOriginal->setToolTip(tr("Original"));
604 check = connect(m_pZoomOriginal, &QAction::triggered, this,
605 [&](){
606 CFrmWebView* pWeb = CurrentView();
607 if(pWeb)
608 pWeb->setZoomFactor(1.0);
609 });
610 Q_ASSERT(check);
611 m_pZoomIn = pMenu->addAction(QIcon::fromTheme("zoom-in"), tr("Zoom in"));
612 m_pZoomIn->setShortcut(QKeySequence::ZoomIn);
613 m_pZoomIn->setStatusTip(tr("Zoom in"));
614 m_pZoomIn->setToolTip(tr("Zoom in"));
615 check = connect(
616 m_pZoomIn, &QAction::triggered, this,
617 [&](){
618 CFrmWebView* pWeb = CurrentView();
619 if(pWeb)
620 pWeb->setZoomFactor(pWeb->zoomFactor() + 0.1);
621 });
622 Q_ASSERT(check);
623 m_pZoomOut = pMenu->addAction(
624 QIcon::fromTheme("zoom-out"), tr("Zoom out"));
625 m_pZoomOut->setShortcut(QKeySequence::ZoomOut);
626 m_pZoomOut->setStatusTip(tr("Zoom out"));
627 m_pZoomOut->setToolTip(tr("Zoom out"));
628 check = connect(
629 m_pZoomOut, &QAction::triggered, this,
630 [&](){
631 CFrmWebView* pWeb = CurrentView();
632 if(pWeb)
633 pWeb->setZoomFactor(pWeb->zoomFactor() - 0.1);
634 });
635 Q_ASSERT(check);
636
637 pMenu->addSeparator();
638#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
639 m_pPrint = pMenu->addAction(
640 QIcon::fromTheme("document-print"), tr("Print"),
641 this, &CFrmWebBrowser::slotPrint);
642 m_pPrint->setVisible(false);
643 m_pPrintToPdf = pMenu->addAction(
644 QIcon::fromTheme("document-print"), tr("Print to PDF"),
645 this, &CFrmWebBrowser::slotPrintToPdf);
646#endif
647
648 pMenu->addAction(m_pDownload);
649 if(!m_pInspector) {
650 m_pInspector = pMenu->addAction(QIcon::fromTheme("tools"), tr("Inspector"));
651 check = connect(m_pInspector, &QAction::toggled,
652 this, &CFrmWebBrowser::slotInspector);
653 Q_ASSERT(check);
654 m_pInspector->setCheckable(true);
655 m_pInspector->setEnabled(false);
656 }
657
658 EnableAction(false);
659 return 0;
660}
661
662int CFrmWebBrowser::Start()
663{
664 int nRet = 0;
665 if(m_pTab->count() == 0) {
666 // Add new web view
667 m_pAddPage->trigger();
668 }
669 return nRet;
670}
671
672int CFrmWebBrowser::Stop()
673{
674 int nRet = 0;
675
676 for(int i = 0; i < m_pTab->count(); i++) {
677 auto v = GetView(i);
678 if(!v) continue;
679 v->stop();
680 }
681
682 return nRet;
683}
684
685void CFrmWebBrowser::slotTabCurrentChanged(int index)
686{
687 if(-1 == index) return;
688 CFrmWebView* pWeb = CurrentView();
689 if(pWeb) {
690 setWindowTitle(pWeb->title());
691 setWindowIcon(pWeb->icon());
692 m_pUrlLineEdit->setText(pWeb->url().toString());
693 m_pProgressBar->setValue(pWeb->progress());
694 EnableAction(true);
695 auto page = pWeb->page();
696 if(page) {
697 auto action = page->action(QWebEnginePage::Back);
698 if(action && m_pBack) {
699 m_pBack->setEnabled(action->isEnabled());
700 }
701 action = page->action(QWebEnginePage::Forward);
702 if(action && m_pForward) {
703 m_pForward->setEnabled(action->isEnabled());
704 }
705 action = page->action(QWebEnginePage::Reload);
706 if(action && m_pRefresh)
707 m_pRefresh->setEnabled(action->isEnabled());
708 if(m_pRefresh->isEnabled())
709 m_pToolBar->insertAction(m_pUrl, m_pRefresh);
710 else
711 m_pToolBar->removeAction(m_pRefresh);
712 action = page->action(QWebEnginePage::Stop);
713 if(action && m_pStop)
714 m_pStop->setEnabled(action->isEnabled());
715 if(m_pStop->isEnabled())
716 m_pToolBar->insertAction(m_pUrl, m_pStop);
717 else
718 m_pToolBar->removeAction(m_pStop);
719 if(m_pInspector) {
720 m_pInspector->setChecked(CurrentView(ViewType::DevTools));
721 }
722 }
723 } else {
724 setWindowTitle(tr("Web browser"));
725 setWindowIcon(QIcon::fromTheme("web-browser"));
726 m_pUrlLineEdit->setText("");
727 m_pProgressBar->setValue(100);
728 EnableAction(false);
729 if(m_pInspector)
730 m_pInspector->setChecked(false);
731 }
732 emit sigUpdateTitle();
733}
734
735void CFrmWebBrowser::EnableAction(bool enable)
736{
737 if(m_pBack)
738 m_pBack->setEnabled(false);
739 if(m_pForward)
740 m_pForward->setEnabled(false);
741 if(m_pRefresh)
742 m_pRefresh->setEnabled(enable);
743 if(m_pStop)
744 m_pStop->setEnabled(false);
745 if(m_pFind)
746 m_pFind->setEnabled(enable);
747 if(m_pFindNext)
748 m_pFindNext->setEnabled(enable);
749 if(m_pFindPrevious)
750 m_pFindPrevious->setEnabled(enable);
751 if(m_pZoomOriginal)
752 m_pZoomOriginal->setEnabled(enable);
753 if(m_pZoomIn)
754 m_pZoomIn->setEnabled(enable);
755 if(m_pZoomOut)
756 m_pZoomOut->setEnabled(enable);
757 if(m_pInspector)
758 m_pInspector->setEnabled(enable);
759}
760
761void CFrmWebBrowser::slotTabCloseRequested(int index)
762{
763 qDebug(log) << "slotTabCloseRequested:" << index;
764 if(-1 == index) return;
765 auto pView = m_pTab->widget(index);
766 if(pView)
767 pView->deleteLater();
768 m_pTab->removeTab(index);
769}
770
771void CFrmWebBrowser::slotViewCloseRequested()
772{
773 CFrmWebView* p = qobject_cast<CFrmWebView*>(sender());
774 if(!p) return;
775 int index = IndexOfTab(p);
776 slotTabCloseRequested(index);
777}
778
779void CFrmWebBrowser::slotReturnPressed()
780{
781 QUrl u = QUrl::fromUserInput(m_pUrlLineEdit->text());
782 qDebug(log) << u << m_pUrlLineEdit->text();
783 if(u.isEmpty()) {
784 QString szSearch;
785 if(m_pPara) {
786 szSearch = m_pPara->GetSearchEngine();
787 u = szSearch.replace(m_pPara->GetSearchRelaceString(),
788 QUrl::toPercentEncoding(m_pUrlLineEdit->text()));
789 }
790 }
791 qDebug(log) << u << m_pUrlLineEdit->text();
792 emit sigInformation(u.toString());
793 CFrmWebView* pWeb = CurrentView();
794 if(!pWeb)
795 pWeb = qobject_cast<CFrmWebView*>(CreateWindow(QWebEnginePage::WebBrowserTab));
796 pWeb->load(u);
797 if(m_pGo->isVisible())
798 m_pGo->setVisible(false);
799}
800
801void CFrmWebBrowser::slotInspector(bool checked)
802{
803 CFrmWebView* pWeb = CurrentView();
804 auto dev = CurrentView(ViewType::DevTools);
805 if(pWeb && pWeb->page() && checked) {
806 if(!dev) {
807 auto w = m_pTab->currentWidget();
808 if(!w) return;
809 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
810 if(!pSplitter || 1 != pSplitter->count()) return;
811 dev = CreateWebView(pWeb->page()->profile()->isOffTheRecord());
812 if(dev) {
813 dev->show();
814 pSplitter->addWidget(dev);
815 bool check = connect(pWeb, &CFrmWebView::sigDevToolsRequested,
816 this, [&](){
817 if(m_pInspector)
818 m_pInspector->setChecked(true);
819 });
820 Q_ASSERT(check);
821 }
822 }
823 if(dev) {
824 pWeb->page()->setDevToolsPage(dev->page());
825 if(dev->isHidden())
826 dev->show();
827 }
828 } else {
829 pWeb->page()->setDevToolsPage(nullptr);
830 if(dev) {
831 dev->setParent(nullptr);
832 dev->deleteLater();
833 }
834 }
835}
836
837int CFrmWebBrowser::Load(QSettings &set)
838{
839 if(m_pPara && m_pPara->GetOpenPrevious()) {
840 set.beginGroup("OpenPrevious");
841 int nCount = 0;
842 nCount = set.value("Count", 0).toInt();
843 int nCurrent = set.value("Current", -1).toInt();
844 for(int i = 0; i < nCount; i++)
845 {
846 QString u = set.value("Url/" + QString::number(i)).toString();
847 auto pView = CreateWindow(QWebEnginePage::WebBrowserTab);
848 pView->load(QUrl(u));
849
850 QByteArray history;
851 history = set.value("History/" + QString::number(i)).toByteArray();
852 QDataStream d(&history, QIODevice::ReadWrite);
853 d >> *pView->history();
854 }
855 if(-1 < nCurrent && m_pTab->count() > nCurrent)
856 m_pTab->setCurrentIndex(nCurrent);
857 set.endGroup();
858 }
859 return 0;
860}
861
862int CFrmWebBrowser::Save(QSettings &set)
863{
864 if(m_pPara && m_pPara->GetOpenPrevious()) {
865 set.beginGroup("OpenPrevious");
866 set.setValue("Count", m_pTab->count());
867 set.setValue("Current", m_pTab->currentIndex());
868
869 for(int i = 0; i < m_pTab->count(); i++) {
870 auto v = GetView(i);
871 if(v) {
872 set.setValue("Url/" + QString::number(i), v->url().toString());
873 QByteArray history;
874 QDataStream d(&history, QIODevice::ReadWrite);
875 d << *v->history();
876 set.setValue("History/" + QString::number(i), history);
877 }
878 }
879
880 set.endGroup();
881 }
882 return 0;
883}
884
885void CFrmWebBrowser::slotPrint()
886{
887 CFrmWebView* pWeb = CurrentView();
888 if(pWeb) {
889#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
890 QPrinter printer;
891 pWeb->print(&printer);
892#endif
893 }
894}
895
896void CFrmWebBrowser::slotPrintFinished(bool success)
897{
898 if(success && m_pPara->GetPromptPrintFinished()) {
899 QMessageBox::information(this, tr("Print finished"),
900 tr("Successfully printed"));
901 }
902}
903
904void CFrmWebBrowser::slotPrintToPdf()
905{
906 CFrmWebView* pWeb = CurrentView();
907 if(pWeb) {
908 QString szPath;
909 szPath += RabbitCommon::CDir::Instance()->GetDirUserData()
910 + QDir::separator() + "pdf";
911 QDir d(szPath);
912 if(!d.exists())
913 d.mkpath(szPath);
914 szPath += QDir::separator() + pWeb->page()->title() + ".pdf";
915 qDebug(log) << "pdf:" << szPath;
916#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
917 pWeb->printToPdf(szPath);
918#endif
919 }
920}
921
922void CFrmWebBrowser::slotPdfPrintingFinished(const QString& szFile, bool success) {
923 if(success && m_pPara->GetPromptPrintFinished())
924 QMessageBox::information(this, tr("Print to PDF finished"),
925 tr("Successfully printed to PDF.") + "\n"
926 + tr("PDF file: ") + szFile);
927 qDebug(log) << "Print to PDF:" << szFile << success;
928}
void sigUpdateTitle()
Title or icon changed