10#include <QInputDialog>
13#include <QWebEngineProfile>
14#include <QWebEngineHistory>
15#include <QWebEngineSettings>
16#include <QWebEngineFindTextResult>
17#include <QRegularExpression>
18#include <QWebEngineCookieStore>
19#include <QStandardPaths>
21#include <QApplication>
22#include <QDesktopServices>
23#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
24 #include <QWebEngineProfileBuilder>
26#include <QLoggingCategory>
27#include "RabbitCommonDir.h"
28#include "RabbitCommonTools.h"
29#include "FrmWebBrowser.h"
31#include "CaptureFullPage.h"
33static Q_LOGGING_CATEGORY(log,
"WebBrowser.Browser")
44 , m_pFindNext(
nullptr)
45 , m_pFindPrevious(
nullptr)
46 , m_pZoomOriginal(
nullptr)
49 , m_pFavAction(
nullptr)
52 , m_pAddPageIncognito(
nullptr)
53 , m_pAddWindow(
nullptr)
55 , m_pPrintToPdf(
nullptr)
56 , m_pAddWindowIncognito(
nullptr)
57 , m_pDownload(
nullptr)
58 , m_pInspector(
nullptr)
60 , m_pUrlLineEdit(
nullptr)
61 , m_pProgressBar(
nullptr)
63 , m_DownloadManager(pPara)
64 , m_pCapturePage(
nullptr)
65 , m_pCaptureFulPage(
nullptr)
67 , m_pMultimediaRecord(
nullptr)
69 qDebug(log) << Q_FUNC_INFO;
72 setWindowIcon(QIcon::fromTheme(
"web-browser"));
74 QVBoxLayout* pLayout =
new QVBoxLayout(
this);
78 pLayout->setSpacing(0);
79 pLayout->setContentsMargins(0, 0, 0, 0);
82 m_pToolBar =
new QToolBar(
this);
84 pLayout->addWidget(m_pToolBar);
87 m_pBack = m_pToolBar->addAction(
88 QIcon::fromTheme(
"go-previous"), tr(
"Back"),
91 if(pWeb && pWeb->page())
92 pWeb->page()->action(QWebEnginePage::Back)->trigger();
94 m_pBack->setEnabled(
false);
95 m_pBack->setShortcuts(QKeySequence::Back);
96 m_pBack->setStatusTip(m_pBack->text());
97 m_pForward = m_pToolBar->addAction(
98 QIcon::fromTheme(
"go-next"), tr(
"Forward"),
101 if(pWeb && pWeb->page())
102 pWeb->page()->action(QWebEnginePage::Forward)->trigger();
104 m_pForward->setEnabled(
false);
105 m_pForward->setShortcuts(QKeySequence::Forward);
106 m_pForward->setStatusTip(m_pForward->text());
107 m_pRefresh = m_pToolBar->addAction(
108 QIcon::fromTheme(
"view-refresh"), tr(
"Refresh"),
111 if(pWeb && pWeb->page())
112 pWeb->page()->action(QWebEnginePage::Reload)->trigger();
114 m_pRefresh->setShortcuts(QKeySequence::Refresh);
115 m_pRefresh->setStatusTip(m_pRefresh->text());
117 m_pUrlLineEdit =
new QLineEdit(
this);
118 m_pFavAction =
new QAction(m_pUrlLineEdit);
119 m_pUrlLineEdit->addAction(m_pFavAction, QLineEdit::LeadingPosition);
120 m_pUrlLineEdit->setClearButtonEnabled(
true);
121 m_pUrl = m_pToolBar->addWidget(m_pUrlLineEdit);
122 check = connect(m_pUrlLineEdit, &QLineEdit::returnPressed,
123 this, &CFrmWebBrowser::slotReturnPressed);
125 check = connect(m_pUrlLineEdit, &QLineEdit::editingFinished,
126 this, &CFrmWebBrowser::slotReturnPressed);
128 m_pGo =
new QAction(QIcon::fromTheme(
"go-next"), tr(
"go"), m_pUrlLineEdit);
129 m_pGo->setStatusTip(m_pGo->text());
130 check = connect(m_pGo, &QAction::triggered,
this, &CFrmWebBrowser::slotReturnPressed);
132 m_pUrlLineEdit->addAction(m_pGo, QLineEdit::TrailingPosition);
133 m_pGo->setVisible(
false);
134 check = connect(m_pUrlLineEdit, &QLineEdit::textEdited,
135 this, [&](
const QString &text){
136 QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(sender());
139 if(m_pGo->isVisible())
140 m_pGo->setVisible(
false);
142 if(!m_pGo->isVisible())
143 m_pGo->setVisible(
true);
149 m_pAddPage = m_pToolBar->addAction(QIcon::fromTheme(
"add"), tr(
"Add tab page"),
151 CreateWindow(QWebEnginePage::WebBrowserTab);
152 if(!m_pPara->GetTabUrl().isEmpty()) {
153 m_pUrlLineEdit->setText(m_pPara->GetTabUrl());
157 m_pAddPage->setStatusTip(m_pAddPage->text());
158 m_pAddPage->setShortcuts(QKeySequence::AddTab);
160 m_pDownload = m_pToolBar->addAction(
161 QIcon::fromTheme(
"emblem-downloads"), tr(
"Download Manager"));
162 m_pDownload->setCheckable(
true);
163 m_pDownload->setStatusTip(m_pDownload->text());
164 m_pDownload->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_D));
165 check = connect(m_pDownload, &QAction::toggled,
166 this, [&](
bool checked){
168 m_DownloadManager.show();
170 m_DownloadManager.hide();
173 check = connect(&m_DownloadManager, &CFrmDownloadManager::sigVisible,
this,
176 m_pDownload->setChecked(visible);
180 m_pProgressBar =
new QProgressBar(
this);
182 pLayout->addWidget(m_pProgressBar);
183 m_pProgressBar->setMaximumHeight(1);
184 m_pProgressBar->setTextVisible(
false);
185 m_pProgressBar->show();
186 m_pProgressBar->setStyleSheet(
"QProgressBar {border: 0px} QProgressBar::chunk {background-color: #da4453}");
189 m_pTab =
new QTabWidget(
this);
191 m_pTab->setTabsClosable(
true);
192 m_pTab->setUsesScrollButtons(
true);
193 m_pTab->setMovable(
true);
194 m_pTab->setElideMode(Qt::TextElideMode::ElideRight);
195 pLayout->addWidget(m_pTab);
197 check = connect(m_pTab, &QTabWidget::currentChanged,
198 this, &CFrmWebBrowser::slotTabCurrentChanged);
200 check = connect(m_pTab, &QTabWidget::tabCloseRequested,
201 this, &CFrmWebBrowser::slotTabCloseRequested);
204 m_DownloadManager.hide();
205 QWebEngineProfile::defaultProfile()->setDownloadPath(m_pPara->GetDownloadFolder());
206 check = connect(QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested,
207 &m_DownloadManager, &CFrmDownloadManager::slotDownloadRequested);
209 check = connect(m_pPara, &CParameterWebBrowser::sigDownloadFolderChanged,
211 QWebEngineProfile::defaultProfile()->setDownloadPath(m_pPara->GetDownloadFolder());
213 m_profile->setDownloadPath(m_pPara->GetDownloadFolder());
220 m_pMenuBar =
new QMenuBar(
this);
222 m_Menu.setTitle(tr(
"Operate"));
223 m_pMenuBar->addMenu(&m_Menu);
224 pLayout->setMenuBar(m_pMenuBar);
228 check = connect(&m_tmRecord, &QTimer::timeout,
this, &CFrmWebBrowser::slotRecordTimeout);
232CFrmWebBrowser::~CFrmWebBrowser()
234 qDebug(log) << Q_FUNC_INFO;
236 m_pToolBar->deleteLater();
237 m_pToolBar =
nullptr;
240 m_pTab->deleteLater();
244 if(m_pPara->GetClearCookie() && m_profile)
245 m_profile->cookieStore()->deleteAllCookies();
246 if(m_pPara->GetClearHttpCache() && m_profile)
247 m_profile->clearHttpCache();
250QMenu* CFrmWebBrowser::GetMenu(QWidget *parent)
252 if(m_Menu.actions().isEmpty())
257QWebEngineView* CFrmWebBrowser::CreateWindow(
258 QWebEnginePage::WebWindowType type,
bool offTheRecord)
260 qDebug(log) <<
"Create window:" << type;
264 case QWebEnginePage::WebBrowserTab: {
265 auto pTab = CreateTab(&pView, offTheRecord);
266 if(!pTab || !m_pTab)
break;
267 int index = m_pTab->addTab(pTab, pView->favIcon(), tr(
"New page"));
269 m_pTab->setCurrentIndex(index);
272 case QWebEnginePage::WebBrowserBackgroundTab: {
273 auto pTab = CreateTab(&pView, offTheRecord);
274 if(!pTab || !m_pTab)
break;
275 int index = m_pTab->currentIndex();
276 m_pTab->addTab(pTab, pView->favIcon(), tr(
"New page"));
277 if(-1 < index && index != m_pTab->currentIndex())
278 m_pTab->setCurrentIndex(index);
281 case QWebEnginePage::WebBrowserWindow: {
284 pView = qobject_cast<CFrmWebView*>(
285 pWin->CreateWindow(QWebEnginePage::WebBrowserTab));
286 pWin->setAttribute(Qt::WA_DeleteOnClose);
287 auto pMainWin = RabbitCommon::CTools::GetMainWindow();
289 pWin->resize(pMainWin->frameGeometry().width(),
290 pMainWin->frameGeometry().height());
295 case QWebEnginePage::WebDialog: {
297 auto popup =
new CFrmPopup(GetProfile(offTheRecord),
this);
298 pView = popup->GetView();
309 check = connect(pWeb, &CFrmWebView::sigDevToolsRequested,
312 m_pInspector->setChecked(
true);
315 check = connect(pWeb, &CFrmWebView::sigWebActionEnabledChanged,
316 this, [
this, pWeb](QWebEnginePage::WebAction webAction,
bool enabled){
317 if(!IsCurrentView(pWeb))
return;
319 case QWebEnginePage::WebAction::Back:
320 m_pBack->setEnabled(enabled);
322 case QWebEnginePage::WebAction::Forward:
323 m_pForward->setEnabled(enabled);
325 case QWebEnginePage::WebAction::Reload: {
326 m_pRefresh->setEnabled(enabled);
327 if(m_pRefresh->isEnabled())
328 m_pToolBar->insertAction(m_pUrl, m_pRefresh);
330 m_pToolBar->removeAction(m_pRefresh);
333 case QWebEnginePage::WebAction::Stop: {
334 m_pStop->setEnabled(enabled);
335 if(m_pStop->isEnabled())
336 m_pToolBar->insertAction(m_pUrl, m_pStop);
338 m_pToolBar->removeAction(m_pStop);
345 check = connect(pWeb, &QWebEngineView::urlChanged,
346 this, [&](
const QUrl &url){
347 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
348 if(IsCurrentView(pWeb))
349 m_pUrlLineEdit->setText(url.toString());
352 check = connect(pWeb, &CFrmWebView::titleChanged,
353 this, [&](
const QString &title) {
354 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
355 int index = IndexOfTab(pWeb);
358 m_pTab->setTabText(index, title);
359 setWindowTitle(title);
364 check = connect(pWeb, &CFrmWebView::favIconChanged,
365 this, [&](
const QIcon &icon){
366 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
367 int index = IndexOfTab(pWeb);
370 m_pTab->setTabIcon(index, icon);
376 check = connect(pWeb, &CFrmWebView::sigLinkHovered,
377 this, &CFrmWebBrowser::sigInformation);
379 check = connect(pWeb, &CFrmWebView::sigCloseRequested,
380 this, &CFrmWebBrowser::slotViewCloseRequested);
382 check = connect(pWeb, &CFrmWebView::loadProgress,
383 this, [&](
int progress){
384 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
385 if(IsCurrentView(pWeb))
386 m_pProgressBar->setValue(progress);
389 m_pProgressBar->setValue(pWeb->progress());
390#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
391 check = connect(pWeb, &CFrmWebView::printFinished,
392 this, &CFrmWebBrowser::slotPrintFinished);
394 check = connect(pWeb, &CFrmWebView::pdfPrintingFinished,
395 this, &CFrmWebBrowser::slotPdfPrintingFinished);
400QWebEngineProfile* CFrmWebBrowser::GetProfile(
bool offTheRecord)
403 return QWebEngineProfile::defaultProfile();
405 return m_profile.get();
407 QSettings set(RabbitCommon::CDir::Instance()->GetDirUserData()
408 + QDir::separator() +
"WebBrowser.ini",
409 QSettings::IniFormat);
410 QString name =
"io.github.KangLin.RabbitRemoteControl";
411#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
412 name += QLatin1StringView(qWebEngineChromiumVersion());
413 name = set.value(
"Profile/Name", name).toString();
414 QWebEngineProfileBuilder profileBuilder;
415 m_profile.reset(profileBuilder.createProfile(name));
417 name = set.value(
"Profile/Name", name).toString();
418 m_profile.reset(
new QWebEngineProfile(name));
421 return QWebEngineProfile::defaultProfile();
423 set.setValue(
"Profile/Name", name);
425 m_profile->settings()->setAttribute(QWebEngineSettings::PluginsEnabled,
true);
426 m_profile->settings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled,
true);
427 m_profile->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls,
true);
428 m_profile->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls,
false);
429#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
430 m_profile->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled,
true);
432#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
433 m_profile->settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled,
true);
435#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
436 m_profile->settings()->setAttribute(QWebEngineSettings::AllowRunningInsecureContent,
true);
438#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
439 m_profile->settings()->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture,
false);
441 m_profile->setDownloadPath(m_pPara->GetDownloadFolder());
442 bool check = connect(m_profile.get(), &QWebEngineProfile::downloadRequested,
443 &m_DownloadManager, &CFrmDownloadManager::slotDownloadRequested);
445 qDebug(log) <<
"User agent:" << m_profile->httpUserAgent()
446 <<
"Persistent path:" << m_profile->persistentStoragePath()
447 <<
"Cache path:" << m_profile->cachePath()
448 <<
"Storage name:" << m_profile->storageName()
449 <<
"Cookie:" << m_profile->cookieStore()
450 <<
"Is off the Record:" << m_profile->isOffTheRecord()
451 <<
"Download:" << m_profile->downloadPath();
452 return m_profile.get();
455CFrmWebView *CFrmWebBrowser::CreateWebView(
bool offTheRecord)
459 auto profile = GetProfile(offTheRecord);
463 auto page =
new QWebEnginePage(profile, pView);
464 pView->setPage(page);
469QWidget* CFrmWebBrowser::CreateTab(
CFrmWebView **view,
bool offTheRecord)
471 QSplitter *pSplitter =
new QSplitter(Qt::Vertical,
this);
473 pSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
480 pWeb = CreateWebView(offTheRecord);
484 pWeb = CreateWebView(offTheRecord);
487 pSplitter->addWidget(pWeb);
494CFrmWebView *CFrmWebBrowser::CurrentView(ViewType type)
496 if(!m_pTab)
return nullptr;
497 auto w = m_pTab->currentWidget();
498 if(!w)
return nullptr;
499 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
500 if(!pSplitter)
return nullptr;
501 int index = (int)type;
502 if(0 > index && pSplitter->count() <= index)
return nullptr;
503 return qobject_cast<CFrmWebView*>(pSplitter->widget(index));
506CFrmWebView* CFrmWebBrowser::GetView(
int index, ViewType type)
508 if(0 > index || !m_pTab || m_pTab->count() <= index)
return nullptr;
509 auto w = m_pTab->widget(index);
510 if(!w)
return nullptr;
511 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
512 if(!pSplitter)
return nullptr;
514 if(0 > idx && pSplitter->count() <= idx)
return nullptr;
515 return qobject_cast<CFrmWebView*>(pSplitter->widget(idx));
518bool CFrmWebBrowser::IsCurrentView(
CFrmWebView *pView)
520 if(!m_pTab)
return false;
521 auto w = m_pTab->currentWidget();
523 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
524 if(!pSplitter)
return false;
525 return -1 != pSplitter->indexOf(pView);
531 if(!pView)
return nRet;
532 QWidget* p = qobject_cast<QWidget*>(pView->parent());
535 nRet = m_pTab->indexOf(p);
539int CFrmWebBrowser::InitMenu(QMenu *pMenu)
543 pMenu->addAction(m_pBack);
544 pMenu->addAction(m_pForward);
545 pMenu->addAction(m_pRefresh);
546 m_pStop = pMenu->addAction(
547 QIcon::fromTheme(
"media-playback-stop"), tr(
"Stop"),
this, [&](){
549 if(pWeb && pWeb->page())
550 pWeb->page()->action(QWebEnginePage::Stop)->trigger();
552 m_pStop->setEnabled(
false);
553 m_pStop->setShortcuts(QKeySequence::Cancel);
554 m_pStop->setStatusTip(m_pStop->text());
556 pMenu->addSeparator();
557 pMenu->addAction(m_pAddPage);
558 m_pAddPageIncognito = pMenu->addAction(
559 QIcon::fromTheme(
"add"), tr(
"Add incognito tab"),
561 CreateWindow(QWebEnginePage::WebBrowserTab,
true);
562 if(!m_pPara->GetTabUrl().isEmpty()) {
563 m_pUrlLineEdit->setText(m_pPara->GetTabUrl());
567 m_pAddPageIncognito->setStatusTip(m_pAddPageIncognito->text());
568 m_pAddWindow = pMenu->addAction(
569 QIcon::fromTheme(
"add"), tr(
"Add window"),
571 CreateWindow(QWebEnginePage::WebBrowserWindow);
573 m_pAddWindow->setVisible(
false);
574 m_pAddWindow->setStatusTip(m_pAddWindow->text());
575 m_pAddWindowIncognito = pMenu->addAction(
576 QIcon::fromTheme(
"add"), tr(
"Add Incognito Window"),
578 CreateWindow(QWebEnginePage::WebBrowserWindow,
true);
580 m_pAddWindowIncognito->setVisible(
false);
581 m_pAddWindowIncognito->setStatusTip(m_pAddWindowIncognito->text());
583 pMenu->addSeparator();
584 m_pFind = pMenu->addAction(
585 QIcon::fromTheme(
"edit-find"), tr(
"&Find"),
this,
590 if(pWeb->selectedText().isEmpty()) {
591 if(QApplication::clipboard()
592 && !QApplication::clipboard()->text().isEmpty())
593 m_szFindText = QApplication::clipboard()->text();
595 m_szFindText = pWeb->selectedText();
597 QString search = QInputDialog::getText(
599 tr(
"Find:"), QLineEdit::Normal,
601 if (ok && !search.isEmpty()) {
602 m_szFindText = search;
603#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
604 pWeb->findText(m_szFindText, QWebEnginePage::FindFlags(),
605 [&](
const QWebEngineFindTextResult& result){
606 if (result.numberOfMatches() == 0) {
607 emit sigInformation(tr(
"\"%1\" not found.").arg(m_szFindText));
609 emit sigInformation(tr(
"\"%1\" found: %2/%3").arg(m_szFindText, QString::number(result.activeMatch()), QString::number(result.numberOfMatches())));
613 pWeb->findText(m_szFindText, QWebEnginePage::FindFlags(), [
this](
bool found) {
615 emit sigInformation(tr(
"\"%1\" not found.").arg(m_szFindText));
621 m_pFind->setShortcuts(QKeySequence::Find);
622 m_pFind->setStatusTip(m_pFind->text());
624 m_pFindNext = pMenu->addAction(
625 QIcon::fromTheme(
"go-next"), tr(
"Find &Next"),
this,
628 if(pWeb && !m_szFindText.isEmpty()) {
629 pWeb->findText(m_szFindText);
632 m_pFindNext->setShortcuts(QKeySequence::FindNext);
633 m_pFindNext->setText(m_pFindNext->text());
635 m_pFindPrevious = pMenu->addAction(
636 QIcon::fromTheme(
"go-previous"), tr(
"Find &Previous"),
this,
639 if(pWeb && !m_szFindText.isEmpty()) {
640 pWeb->findText(m_szFindText, QWebEnginePage::FindBackward);
643 m_pFindPrevious->setShortcuts(QKeySequence::FindPrevious);
644 m_pFindPrevious->setStatusTip(m_pFindPrevious->text());
646 pMenu->addSeparator();
647 m_pZoomOriginal = pMenu->addAction(
648 QIcon::fromTheme(
"zoom-original"), tr(
"Original"));
649 m_pZoomOriginal->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
650 m_pZoomOriginal->setStatusTip(tr(
"Original"));
651 m_pZoomOriginal->setToolTip(tr(
"Original"));
652 check = connect(m_pZoomOriginal, &QAction::triggered,
this,
656 pWeb->setZoomFactor(1.0);
659 m_pZoomIn = pMenu->addAction(QIcon::fromTheme(
"zoom-in"), tr(
"Zoom in"));
660 m_pZoomIn->setShortcuts(QKeySequence::ZoomIn);
661 m_pZoomIn->setStatusTip(tr(
"Zoom in"));
662 m_pZoomIn->setToolTip(tr(
"Zoom in"));
664 m_pZoomIn, &QAction::triggered,
this,
668 pWeb->setZoomFactor(pWeb->zoomFactor() + 0.1);
671 m_pZoomOut = pMenu->addAction(
672 QIcon::fromTheme(
"zoom-out"), tr(
"Zoom out"));
673 m_pZoomOut->setShortcuts(QKeySequence::ZoomOut);
674 m_pZoomOut->setStatusTip(tr(
"Zoom out"));
675 m_pZoomOut->setToolTip(tr(
"Zoom out"));
677 m_pZoomOut, &QAction::triggered,
this,
681 pWeb->setZoomFactor(pWeb->zoomFactor() - 0.1);
685 pMenu->addSeparator();
686#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
687 m_pPrint = pMenu->addAction(
688 QIcon::fromTheme(
"document-print"), tr(
"Print"),
689 this, &CFrmWebBrowser::slotPrint);
690 m_pPrint->setVisible(
false);
691 m_pPrint->setShortcuts(QKeySequence::Print);
692 m_pPrintToPdf = pMenu->addAction(
693 QIcon::fromTheme(
"document-print"), tr(
"Print to PDF"),
694 this, &CFrmWebBrowser::slotPrintToPdf);
697 pMenu->addAction(m_pDownload);
699 m_pInspector = pMenu->addAction(QIcon::fromTheme(
"tools"), tr(
"Inspector"));
700 check = connect(m_pInspector, &QAction::toggled,
701 this, &CFrmWebBrowser::slotInspector);
703 m_pInspector->setStatusTip(tr(
"Inspector"));
704 m_pInspector->setCheckable(
true);
705 m_pInspector->setEnabled(
false);
706 m_pInspector->setShortcuts({
707 QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_I),
708 QKeySequence(Qt::Key_F12)
712 pMenu->addSeparator();
713 m_pCapturePage = pMenu->addAction(
714 QIcon::fromTheme(
"screen-shot"), tr(
"Capture page"),
715 this, &CFrmWebBrowser::slotCapturePage);
716 m_pCapturePage->setStatusTip(tr(
"Capture page"));
717 m_pCaptureFulPage = pMenu->addAction(
718 QIcon::fromTheme(
"screen-shot"), tr(
"Capture full page"),
719 this, &CFrmWebBrowser::slotCaptureFullPage);
720 m_pCaptureFulPage->setStatusTip(tr(
"Capture full page"));
721 m_pRecord = pMenu->addAction(QIcon::fromTheme(
"media-record"), tr(
"Record"),
722 this, &CFrmWebBrowser::slotRecord);
723 m_pRecord->setCheckable(
true);
724 m_pRecord->setStatusTip(tr(
"Record"));
725#ifdef HAVE_QT6_RECORD
726 m_pRecord->setEnabled(
true);
728 m_pRecord->setEnabled(
false);
735int CFrmWebBrowser::Start()
738 if(m_pTab && m_pTab->count() == 0) {
740 m_pAddPage->trigger();
745int CFrmWebBrowser::Stop()
749 if(m_pRecord && m_pRecord->isChecked())
752 for(
int i = 0; i < m_pTab->count(); i++) {
761void CFrmWebBrowser::slotTabCurrentChanged(
int index)
763 if(-1 == index)
return;
766 setWindowTitle(pWeb->title());
767 setWindowIcon(pWeb->icon());
768 m_pUrlLineEdit->setText(pWeb->url().toString());
769 m_pProgressBar->setValue(pWeb->progress());
771 auto page = pWeb->page();
773 auto action = page->action(QWebEnginePage::Back);
774 if(action && m_pBack) {
775 m_pBack->setEnabled(action->isEnabled());
777 action = page->action(QWebEnginePage::Forward);
778 if(action && m_pForward) {
779 m_pForward->setEnabled(action->isEnabled());
781 action = page->action(QWebEnginePage::Reload);
782 if(action && m_pRefresh)
783 m_pRefresh->setEnabled(action->isEnabled());
784 if(m_pRefresh->isEnabled())
785 m_pToolBar->insertAction(m_pUrl, m_pRefresh);
787 m_pToolBar->removeAction(m_pRefresh);
788 action = page->action(QWebEnginePage::Stop);
789 if(action && m_pStop)
790 m_pStop->setEnabled(action->isEnabled());
791 if(m_pStop->isEnabled())
792 m_pToolBar->insertAction(m_pUrl, m_pStop);
794 m_pToolBar->removeAction(m_pStop);
796 m_pInspector->setChecked(CurrentView(ViewType::DevTools));
800 setWindowTitle(tr(
"Web browser"));
801 setWindowIcon(QIcon::fromTheme(
"web-browser"));
802 m_pUrlLineEdit->setText(
"");
803 m_pProgressBar->setValue(100);
806 m_pInspector->setChecked(
false);
811void CFrmWebBrowser::EnableAction(
bool enable)
814 m_pBack->setEnabled(
false);
816 m_pForward->setEnabled(
false);
818 m_pRefresh->setEnabled(enable);
820 m_pStop->setEnabled(
false);
822 m_pFind->setEnabled(enable);
824 m_pFindNext->setEnabled(enable);
826 m_pFindPrevious->setEnabled(enable);
828 m_pZoomOriginal->setEnabled(enable);
830 m_pZoomIn->setEnabled(enable);
832 m_pZoomOut->setEnabled(enable);
834 m_pInspector->setEnabled(enable);
836 m_pRecord->setEnabled(enable);
839void CFrmWebBrowser::slotTabCloseRequested(
int index)
841 qDebug(log) <<
"slotTabCloseRequested:" << index;
842 if(-1 == index || !m_pTab)
return;
843 auto pView = m_pTab->widget(index);
845 pView->deleteLater();
846 m_pTab->removeTab(index);
849void CFrmWebBrowser::slotViewCloseRequested()
851 CFrmWebView* p = qobject_cast<CFrmWebView*>(sender());
853 int index = IndexOfTab(p);
854 slotTabCloseRequested(index);
857void CFrmWebBrowser::slotReturnPressed()
859 QUrl u = QUrl::fromUserInput(m_pUrlLineEdit->text());
860 qDebug(log) << u << m_pUrlLineEdit->text();
864 szSearch = m_pPara->GetSearchEngine();
865 u = szSearch.replace(m_pPara->GetSearchRelaceString(),
866 QUrl::toPercentEncoding(m_pUrlLineEdit->text()));
869 qDebug(log) << u << m_pUrlLineEdit->text();
870 emit sigInformation(u.toString());
873 pWeb = qobject_cast<CFrmWebView*>(CreateWindow(QWebEnginePage::WebBrowserTab));
875 if(m_pGo->isVisible())
876 m_pGo->setVisible(
false);
879void CFrmWebBrowser::slotInspector(
bool checked)
882 if(!pWeb || !m_pTab)
return;
883 auto dev = CurrentView(ViewType::DevTools);
884 if(pWeb && pWeb->page() && checked) {
886 auto w = m_pTab->currentWidget();
888 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
889 if(!pSplitter || 1 != pSplitter->count())
return;
890 dev = CreateWebView(pWeb->page()->profile()->isOffTheRecord());
893 pSplitter->addWidget(dev);
894 bool check = connect(pWeb, &CFrmWebView::sigDevToolsRequested,
897 m_pInspector->setChecked(
true);
900 check = connect(dev, &CFrmWebView::sigCloseRequested,
902 m_pInspector->setChecked(
false);
908 pWeb->page()->setDevToolsPage(dev->page());
913 pWeb->page()->setDevToolsPage(
nullptr);
915 dev->setParent(
nullptr);
921int CFrmWebBrowser::Load(QSettings &set)
923 if(m_pPara && m_pPara->GetOpenPrevious()) {
924 set.beginGroup(
"OpenPrevious");
926 nCount = set.value(
"Count", 0).toInt();
927 int nCurrent = set.value(
"Current", -1).toInt();
928 for(
int i = 0; i < nCount; i++)
930 QString u = set.value(
"Url/" + QString::number(i)).toString();
931 auto pView = CreateWindow(QWebEnginePage::WebBrowserTab);
932 pView->load(QUrl(u));
935 history = set.value(
"History/" + QString::number(i)).toByteArray();
936 QDataStream d(&history, QIODevice::ReadWrite);
937 d >> *pView->history();
939 if(-1 < nCurrent && m_pTab->count() > nCurrent)
940 m_pTab->setCurrentIndex(nCurrent);
946int CFrmWebBrowser::Save(QSettings &set)
948 if(m_pPara && m_pPara->GetOpenPrevious()) {
949 set.beginGroup(
"OpenPrevious");
950 set.setValue(
"Count", m_pTab->count());
951 set.setValue(
"Current", m_pTab->currentIndex());
953 for(
int i = 0; i < m_pTab->count(); i++) {
956 set.setValue(
"Url/" + QString::number(i), v->url().toString());
958 QDataStream d(&history, QIODevice::ReadWrite);
960 set.setValue(
"History/" + QString::number(i), history);
969void CFrmWebBrowser::slotPrint()
973#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
975 pWeb->print(&printer);
980void CFrmWebBrowser::slotPrintFinished(
bool success)
982 if(success && m_pPara->GetPromptPrintFinished()) {
983 QMessageBox::information(
this, tr(
"Print finished"),
984 tr(
"Successfully printed"));
988void CFrmWebBrowser::slotPrintToPdf()
993 szPath += RabbitCommon::CDir::Instance()->GetDirUserData()
994 + QDir::separator() +
"pdf";
998 szPath += QDir::separator() + pWeb->page()->title() +
".pdf";
999 qDebug(log) <<
"pdf:" << szPath;
1000#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
1001 pWeb->printToPdf(szPath);
1006void CFrmWebBrowser::slotPdfPrintingFinished(
const QString& szFile,
bool success) {
1007 if(success && m_pPara->GetPromptPrintFinished())
1008 QMessageBox::information(
this, tr(
"Print to PDF finished"),
1009 tr(
"Successfully printed to PDF.") +
"\n"
1010 + tr(
"PDF file: ") + szFile);
1011 qDebug(log) <<
"Print to PDF:" << szFile << success;
1014void CFrmWebBrowser::slotFullScreen(
bool bFullScreen)
1016 if(sender() ==
this)
1020 m_pProgressBar->hide();
1021 m_pTab->tabBar()->setVisible(
false);
1022 m_szStyleSheet = m_pTab->styleSheet();
1023 m_pTab->setStyleSheet(
"QTabWidget::pane{top:0px;left:0px;border:none;}");
1026 m_pProgressBar->show();
1027 m_pTab->tabBar()->setVisible(
true);
1028 m_pTab->setStyleSheet(m_szStyleSheet);
1029 if(CurrentView() && CurrentView()->page() && CurrentView()->page()->action(QWebEnginePage::ExitFullScreen))
1030 CurrentView()->page()->action(QWebEnginePage::ExitFullScreen)->toggle();
1032 emit sigFullScreen(bFullScreen);
1035void CFrmWebBrowser::slotCapturePage()
1037 auto pWeb = CurrentView();
1041 QPixmap pixmap = pWeb->grab();
1042 QImage image = pixmap.toImage();
1043 QString szFile = m_pPara->m_Record.GetImageFile(
true);
1044 if(szFile.isEmpty() && image.isNull())
return;
1045 if(!image.save(szFile,
"PNG"))
1048 szErr = tr(
"Fail: Save capture page to the file: ") + szFile;
1049 qCritical(log) << szErr;
1050 emit sigError(RV::FailCapturePage, szErr);
1053 szMsg = tr(
"Save capture page to the file:") + szFile;
1054 qInfo(log) << szMsg;
1055 emit sigInformation(szMsg);
1056 qDebug(log) <<
"End action:" << m_pPara->m_Record.GetEndAction();
1057 switch(m_pPara->m_Record.GetEndAction())
1059 case CParameterRecord::ENDACTION::OpenFile: {
1060 bool bRet = QDesktopServices::openUrl(QUrl::fromLocalFile(szFile));
1062 qCritical(log) <<
"Fail: Open capture page the file:" << szFile;
1065 case CParameterRecord::ENDACTION::OpenFolder: {
1066 QFileInfo fi(szFile);
1067 QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absolutePath()));
1075void CFrmWebBrowser::slotCaptureFullPage()
1077 auto pWeb = CurrentView();
1079 qDebug(log) <<
"contents size:" << pWeb->page()->contentsSize();
1080 QString szFile = m_pPara->m_Record.GetImageFile(
true);
1082 if(szFile.isEmpty() || !pCapture)
1084 bool check = connect(pCapture, &CCaptureFullPage::sigFinished,
1085 this, [
this, pWeb, szFile, pCapture](){
1086 pWeb->setEnabled(
true);
1087 qDebug(log) <<
"End action:" << m_pPara->m_Record.GetEndAction();
1088 QFileInfo fi(szFile);
1090 QString szErr = tr(
"Fail: capture full page");
1091 qCritical(log) << szErr;
1092 emit sigError(FailCaptureFullPage, szErr);
1094 QString szMsg = tr(
"Capture full page to") +
" " + szFile;
1095 qInfo(log) << szMsg;
1096 emit sigInformation(szMsg);
1097 switch(m_pPara->m_Record.GetEndAction())
1099 case CParameterRecord::ENDACTION::OpenFile: {
1100 bool bRet = QDesktopServices::openUrl(QUrl::fromLocalFile(szFile));
1102 qCritical(log) <<
"Fail: Open capture page the file:" << szFile;
1105 case CParameterRecord::ENDACTION::OpenFolder: {
1106 QFileInfo fi(szFile);
1107 QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absolutePath()));
1113 pCapture->deleteLater();
1117 pWeb->setEnabled(
false);
1118 pCapture->Start(pWeb, pWeb->url(), szFile);
1120 emit sigInformation(tr(
"Start capture full page"));
1123void CFrmWebBrowser::slotRecord()
1125 if(m_pRecord->isChecked()) {
1126 m_pRecord->setText(tr(
"Stop record"));
1127 m_pRecord->setIcon(QIcon::fromTheme(
"media-stop"));
1129 Q_ASSERT(!m_pMultimediaRecord);
1133 if(m_pMultimediaRecord) {
1134 connect(m_pMultimediaRecord, &CMultimediaRecordThread::finished,
1136 m_pMultimediaRecord =
nullptr;
1137 if(m_pRecord->isChecked()) {
1138 m_pRecord->activate(QAction::Trigger);
1139 emit sigError(RV::FailRecordPage, tr(
"Fail record web page"));
1142 m_pMultimediaRecord->start();
1146 qreal rate = m_pPara->m_Record.GetVideoFrameRate();
1149 m_tmRecord.start(qreal(1000) / rate);
1150 emit sigInformation(tr(
"Start record web page"));
1152 m_pRecord->setIcon(QIcon::fromTheme(
"media-record"));
1153 m_pRecord->setText(tr(
"Record"));
1155 if(m_pMultimediaRecord) {
1156 QMetaObject::invokeMethod(m_pMultimediaRecord,
1158 Qt::AutoConnection);
1159 m_pMultimediaRecord =
nullptr;
1160 emit sigInformation(tr(
"Record web page is stopped"));
1163 m_pRecord->setStatusTip(m_pRecord->text());
1166void CFrmWebBrowser::slotRecordTimeout()
1169 if(!m_pMultimediaRecord)
return;
1170 auto pWeb = CurrentView();
1172 QPixmap pixmap = pWeb->grab();
1173 QImage image = pixmap.toImage();
1174 if(image.isNull())
return;
1175 QMetaObject::invokeMethod(m_pMultimediaRecord,
1176 "slotUpdateVideoFrame",
1178 Q_ARG(QImage, image));
void sigUpdateTitle()
Title or icon changed