Rabbit Remote Control 0.1.0-bate8
Loading...
Searching...
No Matches
FrmWebBrowser.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include <QPainter>
4#include <QTabBar>
5#include <QMessageBox>
6#include <QMenu>
7#include <QFile>
8#include <QDir>
9#include <QPrinter>
10#include <QInputDialog>
11#include <QSplitter>
12#include <QVBoxLayout>
13#include <QWebEngineProfile>
14#include <QWebEngineHistory>
15#include <QWebEngineSettings>
16#include <QWebEngineFindTextResult>
17#include <QRegularExpression>
18#include <QWebEngineCookieStore>
19#include <QStandardPaths>
20#include <QClipboard>
21#include <QApplication>
22#include <QDesktopServices>
23#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
24 #include <QWebEngineProfileBuilder>
25#endif
26#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
27 #include <QWebEngineExtensionManager>
28#endif
29#include <QLoggingCategory>
30
31#include "RabbitCommonDir.h"
32#include "RabbitCommonTools.h"
33#include "FrmPopup.h"
34#include "CaptureFullPage.h"
35#include "FrmHistory.h"
36#include "AddressCompleter.h"
37#include "AutoCompleteLineEdit.h"
38#include "FrmBookmark.h"
39#include "FrmAddBookmark.h"
40#include "DlgSettings.h"
41#include "FrmWebBrowser.h"
42#include "ParameterGlobal.h"
43
44static Q_LOGGING_CATEGORY(log, "WebBrowser.Browser")
45CFrmWebBrowser::CFrmWebBrowser(CParameterWebBrowser *pPara, bool bMenuBar, QWidget *parent)
46 : QWidget{parent}
47 , m_pPara(pPara)
48 , m_pMenuBar(nullptr)
49 , m_pToolBar(nullptr)
50 , m_pBack(nullptr)
51 , m_pForward(nullptr)
52 , m_pRefresh(nullptr)
53 , m_pStop(nullptr)
54 , m_pAddBookmark(nullptr)
55 , m_pFind(nullptr)
56 , m_pFindNext(nullptr)
57 , m_pFindPrevious(nullptr)
58 , m_pZoomOriginal(nullptr)
59 , m_pZoomIn(nullptr)
60 , m_pZoomOut(nullptr)
61 , m_pFavAction(nullptr)
62 , m_pGo(nullptr)
63 , m_pAddPage(nullptr)
64 , m_pAddPageIncognito(nullptr)
65 , m_pAddWindow(nullptr)
66 , m_pPrint(nullptr)
67 , m_pPrintToPdf(nullptr)
68 , m_pAddWindowIncognito(nullptr)
69 , m_pDownload(nullptr)
70 , m_pInspector(nullptr)
71 , m_pUrl(nullptr)
72 , m_pUrlLineEdit(nullptr)
73 , m_pProgressBar(nullptr)
74 , m_pTab(nullptr)
75 , m_DownloadManager(pPara)
76 , m_pCapturePage(nullptr)
77 , m_pCaptureFulPage(nullptr)
78 , m_pRecord(nullptr)
79 , m_pMultimediaRecord(nullptr)
80{
81 qDebug(log) << Q_FUNC_INFO;
82 bool check = false;
83
84 setWindowIcon(QIcon::fromTheme("web-browser"));
85
86 QVBoxLayout* pLayout = new QVBoxLayout(this);
87 if(!pLayout) {
88 return;
89 }
90 pLayout->setSpacing(0);
91 pLayout->setContentsMargins(0, 0, 0, 0);
92 setLayout(pLayout);
93
94 m_pToolBar = new QToolBar(this);
95 if(m_pToolBar) {
96 pLayout->addWidget(m_pToolBar);
97 }
98
99 m_pBack = m_pToolBar->addAction(
100 QIcon::fromTheme("go-previous"), tr("Back"),
101 this, [&](){
102 CFrmWebView* pWeb = CurrentView();
103 if(pWeb && pWeb->page())
104 pWeb->page()->action(QWebEnginePage::Back)->trigger();
105 });
106 m_pBack->setEnabled(false);
107 m_pBack->setShortcuts(QKeySequence::Back);
108 m_pBack->setStatusTip(m_pBack->text());
109 m_pForward = m_pToolBar->addAction(
110 QIcon::fromTheme("go-next"), tr("Forward"),
111 this, [&](){
112 CFrmWebView* pWeb = CurrentView();
113 if(pWeb && pWeb->page())
114 pWeb->page()->action(QWebEnginePage::Forward)->trigger();
115 });
116 m_pForward->setEnabled(false);
117 m_pForward->setShortcuts(QKeySequence::Forward);
118 m_pForward->setStatusTip(m_pForward->text());
119 m_pRefresh = m_pToolBar->addAction(
120 QIcon::fromTheme("view-refresh"), tr("Refresh"),
121 this, [&](){
122 CFrmWebView* pWeb = CurrentView();
123 if(pWeb && pWeb->page())
124 pWeb->page()->action(QWebEnginePage::Reload)->trigger();
125 });
126 m_pRefresh->setShortcuts(QKeySequence::Refresh);
127 m_pRefresh->setStatusTip(m_pRefresh->text());
128
129 m_pUrlLineEdit = new QLineEdit(this);
130 m_pFavAction = new QAction(m_pUrlLineEdit);
131 m_pUrlLineEdit->addAction(m_pFavAction, QLineEdit::LeadingPosition);
132 m_pUrlLineEdit->setClearButtonEnabled(true);
133 m_pUrl = m_pToolBar->addWidget(m_pUrlLineEdit);
134 m_pGo = new QAction(QIcon::fromTheme("go-next"), tr("go"), m_pUrlLineEdit);
135 m_pGo->setStatusTip(m_pGo->text());
136 check = connect(m_pGo, &QAction::triggered, this, &CFrmWebBrowser::slotReturnPressed);
137 Q_ASSERT(check);
138 m_pUrlLineEdit->addAction(m_pGo, QLineEdit::TrailingPosition);
139 m_pGo->setVisible(false);
140 check = connect(m_pUrlLineEdit, &QLineEdit::textEdited,
141 this, [&](const QString &text){
142 QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(sender());
143 if(pLineEdit) {
144 if(text.isEmpty()) {
145 if(m_pGo->isVisible())
146 m_pGo->setVisible(false);
147 } else {
148 if(!m_pGo->isVisible())
149 m_pGo->setVisible(true);
150 }
151 }
152 });
153 Q_ASSERT(check);
154 // 创建地址栏自动完成器
155 auto pAddressCompleter = new CAddressCompleter(&m_pPara->m_HistoryDatabase, this);
156 pAddressCompleter->attachToLineEdit(m_pUrlLineEdit);
157 if(m_pPara)
158 pAddressCompleter->setMaxVisibleItems(m_pPara->GetAddCompleterLines());
159 check = connect(pAddressCompleter, &CAddressCompleter::urlSelected,
160 this, &CFrmWebBrowser::slotUrlSelected);
161 Q_ASSERT(check);
162 check = connect(pAddressCompleter, &CAddressCompleter::searchRequested,
163 this, [&](const QString& keyword) {
164 qDebug(log) << "CAddressCompleter::searchRequested keyword:" << keyword;
165 QString szSearch;
166 QString szUrl;
167 if(m_pPara) {
168 szSearch = m_pPara->GetSearchEngine();
169 szUrl = szSearch.replace(m_pPara->GetSearchRelaceString(),
170 QUrl::toPercentEncoding(keyword));
171 if(!szUrl.isEmpty())
172 slotUrlSelected(szUrl);
173 }
174 });
175 Q_ASSERT(check);
176 check = connect(pAddressCompleter, &CAddressCompleter::sigCommand,
177 this, [&](const QString& cmd) {
178 if(cmd.startsWith("@setting")) {
179 CDlgSettings dlg(GetProfile(), m_pPara);
180 RC_SHOW_WINDOW(&dlg);
181 } else if(cmd.startsWith("@history")) {
182 slotHistory();
183 } else if(cmd.startsWith("@bookmark")) {
184 slotBookmark();
185 }
186 });
187 Q_ASSERT(check);
188
189 m_pAddBookmark = m_pToolBar->addAction(
190 QIcon::fromTheme("user-bookmarks"),
191 tr("Add bookmark"), this, SLOT(slotAddBookmark()));
192
193 m_pAddPage = m_pToolBar->addAction(QIcon::fromTheme("add"), tr("Add tab page"),
194 this, [&](){
195 CreateWindow(QWebEnginePage::WebBrowserTab);
196 if(!m_pPara->GetTabUrl().isEmpty()) {
197 m_pUrlLineEdit->setText(m_pPara->GetTabUrl());
198 slotReturnPressed();
199 }
200 });
201 m_pAddPage->setStatusTip(m_pAddPage->text());
202 m_pAddPage->setShortcuts(QKeySequence::AddTab);
203 Q_ASSERT(check);
204 m_pDownload = m_pToolBar->addAction(
205 QIcon::fromTheme("emblem-downloads"), tr("Download Manager"));
206 m_pDownload->setCheckable(true);
207 m_pDownload->setStatusTip(m_pDownload->text());
208 m_pDownload->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_D));
209 check = connect(m_pDownload, &QAction::toggled,
210 this, [&](bool checked){
211 if(checked)
212 m_DownloadManager.show();
213 else
214 m_DownloadManager.hide();
215 });
216 Q_ASSERT(check);
217 check = connect(&m_DownloadManager, &CFrmDownloadManager::sigVisible, this,
218 [&](bool visible){
219 if(m_pDownload)
220 m_pDownload->setChecked(visible);
221 });
222 Q_ASSERT(check);
223
224 m_pProgressBar = new QProgressBar(this);
225 if(m_pProgressBar) {
226 pLayout->addWidget(m_pProgressBar);
227 m_pProgressBar->setMaximumHeight(1);
228 m_pProgressBar->setTextVisible(false);
229 m_pProgressBar->show();
230 m_pProgressBar->setStyleSheet("QProgressBar {border: 0px} QProgressBar::chunk {background-color: #da4453}");
231 }
232
233 m_pTab = new QTabWidget(this);
234 if(m_pTab) {
235 m_pTab->setTabsClosable(true);
236 m_pTab->setUsesScrollButtons(true);
237 m_pTab->setMovable(true);
238 m_pTab->setElideMode(Qt::TextElideMode::ElideRight);
239 pLayout->addWidget(m_pTab);
240 }
241 check = connect(m_pTab, &QTabWidget::currentChanged,
242 this, &CFrmWebBrowser::slotTabCurrentChanged);
243 Q_ASSERT(check);
244 check = connect(m_pTab, &QTabWidget::tabCloseRequested,
245 this, &CFrmWebBrowser::slotTabCloseRequested);
246 Q_ASSERT(check);
247
248 m_DownloadManager.hide();
249 QWebEngineProfile::defaultProfile()->setDownloadPath(m_pPara->GetDownloadFolder());
250 check = connect(QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested,
251 &m_DownloadManager, &CFrmDownloadManager::slotDownloadRequested);
252 Q_ASSERT(check);
253 check = connect(m_pPara, &CParameterWebBrowser::sigDownloadFolderChanged,
254 this, [&](){
255 QWebEngineProfile::defaultProfile()->setDownloadPath(m_pPara->GetDownloadFolder());
256 if(m_profile)
257 m_profile->setDownloadPath(m_pPara->GetDownloadFolder());
258 });
259 Q_ASSERT(check);
260
261 InitMenu(&m_Menu);
262 if(bMenuBar)
263 {
264 m_pMenuBar = new QMenuBar(this);
265 if(m_pMenuBar) {
266 m_Menu.setTitle(tr("Operate"));
267 m_pMenuBar->addMenu(&m_Menu);
268 pLayout->setMenuBar(m_pMenuBar);
269 }
270 }
271
272 check = connect(&m_tmRecord, &QTimer::timeout, this, &CFrmWebBrowser::slotRecordTimeout);
273 Q_ASSERT(check);
274}
275
276CFrmWebBrowser::~CFrmWebBrowser()
277{
278 qDebug(log) << Q_FUNC_INFO;
279 if(m_pToolBar) {
280 m_pToolBar->deleteLater();
281 m_pToolBar = nullptr;
282 }
283 if(m_pTab) {
284 m_pTab->deleteLater();
285 m_pTab = nullptr;
286 }
287
288 if(m_pPara->GetClearCookie() && m_profile)
289 m_profile->cookieStore()->deleteAllCookies();
290 if(m_pPara->GetClearHttpCache() && m_profile)
291 m_profile->clearHttpCache();
292}
293
294QMenu* CFrmWebBrowser::GetMenu(QWidget *parent)
295{
296 if(m_Menu.actions().isEmpty())
297 return nullptr;
298 return &m_Menu;
299}
300
301QWebEngineView* CFrmWebBrowser::CreateWindow(
302 QWebEnginePage::WebWindowType type, bool offTheRecord)
303{
304 qDebug(log) << "Create window:" << type;
305
306 CFrmWebView* pView = nullptr;
307 switch (type) {
308 case QWebEnginePage::WebBrowserTab: {
309 auto pTab = CreateTab(&pView, offTheRecord);
310 if(!pTab || !m_pTab) break;
311 int index = m_pTab->addTab(pTab, pView->favIcon(), tr("New page"));
312 if(-1 < index)
313 m_pTab->setCurrentIndex(index);
314 break;
315 }
316 case QWebEnginePage::WebBrowserBackgroundTab: {
317 auto pTab = CreateTab(&pView, offTheRecord);
318 if(!pTab || !m_pTab) break;
319 int index = m_pTab->currentIndex();
320 m_pTab->addTab(pTab, pView->favIcon(), tr("New page"));
321 if(-1 < index && index != m_pTab->currentIndex())
322 m_pTab->setCurrentIndex(index);
323 break;
324 }
325 case QWebEnginePage::WebBrowserWindow: {
326 auto pWin = new CFrmWebBrowser(m_pPara, true);
327 if(pWin) {
328 pView = qobject_cast<CFrmWebView*>(
329 pWin->CreateWindow(QWebEnginePage::WebBrowserTab));
330 pWin->setAttribute(Qt::WA_DeleteOnClose);
331 auto pMainWin = RabbitCommon::CTools::GetMainWindow();
332 if(pMainWin)
333 pWin->resize(pMainWin->frameGeometry().width(),
334 pMainWin->frameGeometry().height());
335 pWin->show();
336 }
337 break;
338 }
339 case QWebEnginePage::WebDialog: {
340 // Test: Resource\html\TestQWebEnginePageWebDialog.html
341 auto popup = new CFrmPopup(GetProfile(offTheRecord), this);
342 pView = popup->GetView();
343 }
344 }
345
346 return pView;
347}
348
349void CFrmWebBrowser::SetConnect(CFrmWebView* pWeb)
350{
351 bool check = false;
352 if(!pWeb) return;
353 check = connect(pWeb, &CFrmWebView::sigDevToolsRequested,
354 this, [&](){
355 if(m_pInspector)
356 m_pInspector->setChecked(true);
357 });
358 Q_ASSERT(check);
359 check = connect(pWeb, &CFrmWebView::sigWebActionEnabledChanged,
360 this, [this, pWeb](QWebEnginePage::WebAction webAction, bool enabled){
361 if(!IsCurrentView(pWeb)) return;
362 switch(webAction){
363 case QWebEnginePage::WebAction::Back:
364 m_pBack->setEnabled(enabled);
365 break;
366 case QWebEnginePage::WebAction::Forward:
367 m_pForward->setEnabled(enabled);
368 break;
369 case QWebEnginePage::WebAction::Reload: {
370 m_pRefresh->setEnabled(enabled);
371 if(m_pRefresh->isEnabled())
372 m_pToolBar->insertAction(m_pUrl, m_pRefresh);
373 else
374 m_pToolBar->removeAction(m_pRefresh);
375 break;
376 }
377 case QWebEnginePage::WebAction::Stop: {
378 m_pStop->setEnabled(enabled);
379 if(m_pStop->isEnabled())
380 m_pToolBar->insertAction(m_pUrl, m_pStop);
381 else
382 m_pToolBar->removeAction(m_pStop);
383 break;
384 }
385 default:
386 break;
387 }
388 });
389 check = connect(pWeb, &QWebEngineView::urlChanged,
390 this, [&](const QUrl &url) {
391 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
392 if(IsCurrentView(pWeb))
393 m_pUrlLineEdit->setText(url.toString());
394 if(m_pPara) {
395 m_pPara->m_HistoryDatabase.addHistoryEntry(url.toString());
396 }
397 });
398 Q_ASSERT(check);
399 check = connect(pWeb, &CFrmWebView::titleChanged,
400 this, [&](const QString &title) {
401 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
402 int index = IndexOfTab(pWeb);
403 if(-1 < index) {
404 if(m_pTab)
405 m_pTab->setTabText(index, title);
406 setWindowTitle(title);
407 emit sigUpdateTitle();
408 }
409 if(m_pPara) {
410 m_pPara->m_HistoryDatabase.updateHistoryEntry(pWeb->url().toString(), title);
411 }
412 });
413 Q_ASSERT(check);
414 check = connect(pWeb, &CFrmWebView::favIconChanged,
415 this, [&](const QIcon &icon){
416 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
417 int index = IndexOfTab(pWeb);
418 if(-1 < index) {
419 if(m_pTab)
420 m_pTab->setTabIcon(index, icon);
421 m_pFavAction->setIcon(icon);
422 setWindowIcon(icon);
423 emit sigUpdateTitle();
424 }
425 if(m_pPara) {
426 m_pPara->m_HistoryDatabase.updateHistoryEntry(pWeb->url().toString(), QString(), icon);
427 }
428 });
429 Q_ASSERT(check);
430 check = connect(pWeb, &CFrmWebView::sigLinkHovered,
431 this, &CFrmWebBrowser::sigInformation);
432 Q_ASSERT(check);
433 check = connect(pWeb, &CFrmWebView::sigCloseRequested,
434 this, &CFrmWebBrowser::slotViewCloseRequested);
435 Q_ASSERT(check);
436 check = connect(pWeb, &CFrmWebView::loadProgress,
437 this, [&](int progress){
438 CFrmWebView* pWeb = qobject_cast<CFrmWebView*>(sender());
439 if(IsCurrentView(pWeb))
440 m_pProgressBar->setValue(progress);
441 });
442 Q_ASSERT(check);
443 m_pProgressBar->setValue(pWeb->progress());
444#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
445 check = connect(pWeb, &CFrmWebView::printFinished,
446 this, &CFrmWebBrowser::slotPrintFinished);
447 Q_ASSERT(check);
448 check = connect(pWeb, &CFrmWebView::pdfPrintingFinished,
449 this, &CFrmWebBrowser::slotPdfPrintingFinished);
450 Q_ASSERT(check);
451#endif
452}
453
454QWebEngineProfile* CFrmWebBrowser::GetProfile(bool offTheRecord)
455{
456 if(offTheRecord)
457 return QWebEngineProfile::defaultProfile();
458 if(m_profile)
459 return m_profile.get();
460
461 QSettings set(RabbitCommon::CDir::Instance()->GetDirUserConfig()
462 + QDir::separator() + "WebBrowser.ini",
463 QSettings::IniFormat);
464 QString name = "io.github.KangLin.RabbitRemoteControl";
465#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
466 name += "_" + QLatin1StringView(qWebEngineChromiumVersion());
467 name = set.value("Profile/Name", name).toString();
468 QWebEngineProfileBuilder profileBuilder;
469 m_profile.reset(profileBuilder.createProfile(name));
470#else
471 name = set.value("Profile/Name", name).toString();
472 m_profile.reset(new QWebEngineProfile(name));
473#endif
474 if(!m_profile)
475 return QWebEngineProfile::defaultProfile();
476
477 set.setValue("Profile/Name", name);
478
479 m_profile->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
480 m_profile->settings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true);
481 m_profile->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
482 m_profile->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, false);
483#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
484 m_profile->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
485#endif
486#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
487 m_profile->settings()->setAttribute(QWebEngineSettings::ScreenCaptureEnabled, true);
488#endif
489#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
490 m_profile->settings()->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true);
491#endif
492#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
493 m_profile->settings()->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, false);
494#endif
495 m_profile->setDownloadPath(m_pPara->GetDownloadFolder());
496 bool check = connect(m_profile.get(), &QWebEngineProfile::downloadRequested,
497 &m_DownloadManager, &CFrmDownloadManager::slotDownloadRequested);
498 Q_ASSERT(check);
499 //m_profile->setPersistentCookiesPolicy(QWebEngineProfile::ForcePersistentCookies);
500 //m_profile->setPersistentStoragePath(m_profile->cachePath() + QDir::separator() + "Persistent");
501 //m_profile->setHttpCacheMaximumSize(50);
502 qDebug(log) << "User agent:" << m_profile->httpUserAgent()
503 << "Persistent path:" << m_profile->persistentStoragePath()
504 << "Cache path:" << m_profile->cachePath()
505 << "Storage name:" << m_profile->storageName()
506 << "Cookie:" << m_profile->cookieStore()
507 << "Is off the Record:" << m_profile->isOffTheRecord()
508 << "Download:" << m_profile->downloadPath()
509#if QT_VERSION > QT_VERSION_CHECK(6, 10, 0)
510 << "Extension path:" << m_profile->extensionManager()->installPath()
511#endif
512#if QT_VERSION > QT_VERSION_CHECK(6, 8, 0)
513 //<< "AllPermissions:" << m_profile->listAllPermissions()
514 << "persistentPermissionsPolicy:" << m_profile->persistentPermissionsPolicy()
515#endif
516 << "persistentCookiesPolicy:" << m_profile->persistentCookiesPolicy()
517 << "httpCacheMaximumSize:" << m_profile->httpCacheMaximumSize()
518 ;
519 return m_profile.get();
520}
521
522CFrmWebView *CFrmWebBrowser::CreateWebView(bool offTheRecord)
523{
524 auto pView = new CFrmWebView(this);
525 if(pView) {
526 auto profile = GetProfile(offTheRecord);
527// #if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
528// profile->setPersistentPermissionsPolicy(QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime);
529// #endif
530 auto page = new QWebEnginePage(profile, pView);
531 pView->setPage(page);
532 }
533 return pView;
534}
535
536QWidget* CFrmWebBrowser::CreateTab(CFrmWebView **view, bool offTheRecord)
537{
538 QSplitter *pSplitter = new QSplitter(Qt::Vertical, this);
539 if(pSplitter) {
540 pSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
541 //pSplitter->setContentsMargins(0, 0, 0, 0);
542 CFrmWebView* pWeb = nullptr;
543 if(view) {
544 if(*view) {
545 pWeb = *view;
546 } else {
547 pWeb = CreateWebView(offTheRecord);
548 *view = pWeb;
549 }
550 } else {
551 pWeb = CreateWebView(offTheRecord);
552 }
553 if(pWeb) {
554 pSplitter->addWidget(pWeb);
555 SetConnect(pWeb);
556 }
557 }
558 return pSplitter;
559}
560
561CFrmWebView *CFrmWebBrowser::CurrentView(ViewType type)
562{
563 if(!m_pTab) return nullptr;
564 auto w = m_pTab->currentWidget();
565 if(!w) return nullptr;
566 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
567 if(!pSplitter) return nullptr;
568 int index = (int)type;
569 if(0 > index && pSplitter->count() <= index) return nullptr;
570 return qobject_cast<CFrmWebView*>(pSplitter->widget(index));
571}
572
573CFrmWebView* CFrmWebBrowser::GetView(int index, ViewType type)
574{
575 if(0 > index || !m_pTab || m_pTab->count() <= index) return nullptr;
576 auto w = m_pTab->widget(index);
577 if(!w) return nullptr;
578 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
579 if(!pSplitter) return nullptr;
580 int idx = (int)type;
581 if(0 > idx && pSplitter->count() <= idx) return nullptr;
582 return qobject_cast<CFrmWebView*>(pSplitter->widget(idx));
583}
584
585bool CFrmWebBrowser::IsCurrentView(CFrmWebView *pView)
586{
587 if(!m_pTab) return false;
588 auto w = m_pTab->currentWidget();
589 if(!w) return false;
590 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
591 if(!pSplitter) return false;
592 return -1 != pSplitter->indexOf(pView);
593}
594
595int CFrmWebBrowser::IndexOfTab(CFrmWebView *pView)
596{
597 int nRet = -1;
598 if(!pView) return nRet;
599 QWidget* p = qobject_cast<QWidget*>(pView->parent());
600 if(!p) return nRet;
601 if(m_pTab)
602 nRet = m_pTab->indexOf(p);
603 return nRet;
604}
605
606int CFrmWebBrowser::InitMenu(QMenu *pMenu)
607{
608 bool check = false;
609 if(!pMenu) return 0;
610 pMenu->addAction(m_pBack);
611 pMenu->addAction(m_pForward);
612 pMenu->addAction(m_pRefresh);
613 m_pStop = pMenu->addAction(
614 QIcon::fromTheme("media-playback-stop"), tr("Stop"), this, [&]() {
615 CFrmWebView* pWeb = CurrentView();
616 if(pWeb && pWeb->page())
617 pWeb->page()->action(QWebEnginePage::Stop)->trigger();
618 });
619 m_pStop->setEnabled(false);
620 m_pStop->setShortcuts(QKeySequence::Cancel);
621 m_pStop->setStatusTip(m_pStop->text());
622
623 pMenu->addSeparator();
624 pMenu->addAction(m_pAddPage);
625 m_pAddPageIncognito = pMenu->addAction(
626 QIcon::fromTheme("add"), tr("Add incognito tab"),
627 this, [&]() {
628 CreateWindow(QWebEnginePage::WebBrowserTab, true);
629 if(!m_pPara->GetTabUrl().isEmpty()) {
630 m_pUrlLineEdit->setText(m_pPara->GetTabUrl());
631 slotReturnPressed();
632 }
633 });
634 m_pAddPageIncognito->setStatusTip(m_pAddPageIncognito->text());
635 m_pAddWindow = pMenu->addAction(
636 QIcon::fromTheme("add"), tr("Add window"),
637 this, [&]() {
638 CreateWindow(QWebEnginePage::WebBrowserWindow);
639 });
640 m_pAddWindow->setVisible(false);
641 m_pAddWindow->setStatusTip(m_pAddWindow->text());
642 m_pAddWindowIncognito = pMenu->addAction(
643 QIcon::fromTheme("add"), tr("Add Incognito Window"),
644 this, [&]() {
645 CreateWindow(QWebEnginePage::WebBrowserWindow, true);
646 });
647 m_pAddWindowIncognito->setVisible(false);
648 m_pAddWindowIncognito->setStatusTip(m_pAddWindowIncognito->text());
649
650 pMenu->addSeparator();
651 m_pFind = pMenu->addAction(
652 QIcon::fromTheme("edit-find"), tr("&Find"), this,
653 [&]() {
654 CFrmWebView* pWeb = CurrentView();
655 if(pWeb) {
656 bool ok = false;
657 if(pWeb->selectedText().isEmpty()) {
658 if(QApplication::clipboard()
659 && !QApplication::clipboard()->text().isEmpty())
660 m_szFindText = QApplication::clipboard()->text();
661 } else {
662 m_szFindText = pWeb->selectedText();
663 }
664 QString search = QInputDialog::getText(
665 this, tr("Find"),
666 tr("Find:"), QLineEdit::Normal,
667 m_szFindText, &ok);
668 if (ok && !search.isEmpty()) {
669 m_szFindText = search;
670#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
671 pWeb->findText(m_szFindText, QWebEnginePage::FindFlags(),
672 [&](const QWebEngineFindTextResult& result){
673 if (result.numberOfMatches() == 0) {
674 emit sigInformation(tr("\"%1\" not found.").arg(m_szFindText));
675 } else {
676 emit sigInformation(tr("\"%1\" found: %2/%3").arg(m_szFindText, QString::number(result.activeMatch()), QString::number(result.numberOfMatches())));
677 }
678 });
679#else
680 pWeb->findText(m_szFindText, QWebEnginePage::FindFlags(), [this](bool found) {
681 if (!found)
682 emit sigInformation(tr("\"%1\" not found.").arg(m_szFindText));
683 });
684#endif
685 }
686 }
687 });
688 m_pFind->setShortcuts(QKeySequence::Find);
689 m_pFind->setStatusTip(m_pFind->text());
690
691 m_pFindNext = pMenu->addAction(
692 QIcon::fromTheme("go-next"), tr("Find &Next"), this,
693 [this]() {
694 CFrmWebView* pWeb = CurrentView();
695 if(pWeb && !m_szFindText.isEmpty()) {
696 pWeb->findText(m_szFindText);
697 }
698 });
699 m_pFindNext->setShortcuts(QKeySequence::FindNext);
700 m_pFindNext->setText(m_pFindNext->text());
701
702 m_pFindPrevious = pMenu->addAction(
703 QIcon::fromTheme("go-previous"), tr("Find &Previous"), this,
704 [&]() {
705 CFrmWebView* pWeb = CurrentView();
706 if(pWeb && !m_szFindText.isEmpty()) {
707 pWeb->findText(m_szFindText, QWebEnginePage::FindBackward);
708 }
709 });
710 m_pFindPrevious->setShortcuts(QKeySequence::FindPrevious);
711 m_pFindPrevious->setStatusTip(m_pFindPrevious->text());
712
713 pMenu->addSeparator();
714 m_pZoomOriginal = pMenu->addAction(
715 QIcon::fromTheme("zoom-original"), tr("Original"));
716 m_pZoomOriginal->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
717 m_pZoomOriginal->setStatusTip(tr("Original"));
718 m_pZoomOriginal->setToolTip(tr("Original"));
719 check = connect(m_pZoomOriginal, &QAction::triggered, this,
720 [&](){
721 CFrmWebView* pWeb = CurrentView();
722 if(pWeb)
723 pWeb->setZoomFactor(1.0);
724 });
725 Q_ASSERT(check);
726 m_pZoomIn = pMenu->addAction(QIcon::fromTheme("zoom-in"), tr("Zoom in"));
727 m_pZoomIn->setShortcuts(QKeySequence::ZoomIn);
728 m_pZoomIn->setStatusTip(tr("Zoom in"));
729 m_pZoomIn->setToolTip(tr("Zoom in"));
730 check = connect(
731 m_pZoomIn, &QAction::triggered, this,
732 [&](){
733 CFrmWebView* pWeb = CurrentView();
734 if(pWeb)
735 pWeb->setZoomFactor(pWeb->zoomFactor() + 0.1);
736 });
737 Q_ASSERT(check);
738 m_pZoomOut = pMenu->addAction(
739 QIcon::fromTheme("zoom-out"), tr("Zoom out"));
740 m_pZoomOut->setShortcuts(QKeySequence::ZoomOut);
741 m_pZoomOut->setStatusTip(tr("Zoom out"));
742 m_pZoomOut->setToolTip(tr("Zoom out"));
743 check = connect(
744 m_pZoomOut, &QAction::triggered, this,
745 [&](){
746 CFrmWebView* pWeb = CurrentView();
747 if(pWeb)
748 pWeb->setZoomFactor(pWeb->zoomFactor() - 0.1);
749 });
750 Q_ASSERT(check);
751
752 pMenu->addSeparator();
753#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
754 m_pPrint = pMenu->addAction(
755 QIcon::fromTheme("document-print"), tr("Print"),
756 this, &CFrmWebBrowser::slotPrint);
757 m_pPrint->setVisible(false);
758 m_pPrint->setShortcuts(QKeySequence::Print);
759 m_pPrintToPdf = pMenu->addAction(
760 QIcon::fromTheme("document-print"), tr("Print to PDF"),
761 this, &CFrmWebBrowser::slotPrintToPdf);
762#endif
763
764 pMenu->addAction(m_pDownload);
765 if(!m_pInspector) {
766 m_pInspector = pMenu->addAction(QIcon::fromTheme("tools"), tr("Inspector"));
767 check = connect(m_pInspector, &QAction::toggled,
768 this, &CFrmWebBrowser::slotInspector);
769 Q_ASSERT(check);
770 m_pInspector->setStatusTip(tr("Inspector"));
771 m_pInspector->setCheckable(true);
772 m_pInspector->setEnabled(false);
773 m_pInspector->setShortcuts({
774 QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_I),
775 QKeySequence(Qt::Key_F12)
776 });
777 }
778
779 pMenu->addSeparator();
780 QMenu* pMenuBookmark = new QMenu(tr("Bookmark"), pMenu);
781 pMenuBookmark->setIcon(QIcon::fromTheme("user-bookmarks"));
782 pMenu->addMenu(pMenuBookmark);
783 pMenuBookmark->addAction(m_pAddBookmark);
784 pMenuBookmark->addAction(tr("Manage Bookmark "), this, &CFrmWebBrowser::slotBookmark);
785 pMenu->addAction(tr("History"), this, &CFrmWebBrowser::slotHistory);
786
787 pMenu->addSeparator();
788 m_pCapturePage = pMenu->addAction(
789 QIcon::fromTheme("screen-shot"), tr("Capture page"),
790 this, &CFrmWebBrowser::slotCapturePage);
791 m_pCapturePage->setStatusTip(tr("Capture page"));
792 m_pCaptureFulPage = pMenu->addAction(
793 QIcon::fromTheme("screen-shot"), tr("Capture full page"),
794 this, &CFrmWebBrowser::slotCaptureFullPage);
795 m_pCaptureFulPage->setStatusTip(tr("Capture full page"));
796 m_pRecord = pMenu->addAction(QIcon::fromTheme("media-record"), tr("Record"),
797 this, &CFrmWebBrowser::slotRecord);
798 m_pRecord->setCheckable(true);
799 m_pRecord->setStatusTip(tr("Record"));
800#ifdef HAVE_QT6_RECORD
801 m_pRecord->setEnabled(true);
802#else
803 m_pRecord->setEnabled(false);
804#endif
805
806 EnableAction(false);
807 return 0;
808}
809
810int CFrmWebBrowser::Start()
811{
812 int nRet = 0;
813
814 if(m_pTab && m_pTab->count() == 0) {
815 // Add new web view
816 m_pAddPage->trigger();
817 }
818
819 return nRet;
820}
821
822int CFrmWebBrowser::Stop()
823{
824 int nRet = 0;
825
826 if(m_pRecord && m_pRecord->isChecked())
827 slotRecord();
828 if(m_pTab) {
829 for(int i = 0; i < m_pTab->count(); i++) {
830 auto v = GetView(i);
831 if(!v) continue;
832 v->stop();
833 }
834 }
835 return nRet;
836}
837
838void CFrmWebBrowser::slotTabCurrentChanged(int index)
839{
840 if(-1 == index) return;
841 CFrmWebView* pWeb = CurrentView();
842 if(pWeb) {
843 setWindowTitle(pWeb->title());
844 setWindowIcon(pWeb->icon());
845 m_pUrlLineEdit->setText(pWeb->url().toString());
846 m_pProgressBar->setValue(pWeb->progress());
847 EnableAction(true);
848 auto page = pWeb->page();
849 if(page) {
850 auto action = page->action(QWebEnginePage::Back);
851 if(action && m_pBack) {
852 m_pBack->setEnabled(action->isEnabled());
853 }
854 action = page->action(QWebEnginePage::Forward);
855 if(action && m_pForward) {
856 m_pForward->setEnabled(action->isEnabled());
857 }
858 action = page->action(QWebEnginePage::Reload);
859 if(action && m_pRefresh)
860 m_pRefresh->setEnabled(action->isEnabled());
861 if(m_pRefresh->isEnabled())
862 m_pToolBar->insertAction(m_pUrl, m_pRefresh);
863 else
864 m_pToolBar->removeAction(m_pRefresh);
865 action = page->action(QWebEnginePage::Stop);
866 if(action && m_pStop)
867 m_pStop->setEnabled(action->isEnabled());
868 if(m_pStop->isEnabled())
869 m_pToolBar->insertAction(m_pUrl, m_pStop);
870 else
871 m_pToolBar->removeAction(m_pStop);
872 if(m_pInspector) {
873 m_pInspector->setChecked(CurrentView(ViewType::DevTools));
874 }
875 }
876 } else {
877 setWindowTitle(tr("Web browser"));
878 setWindowIcon(QIcon::fromTheme("web-browser"));
879 m_pUrlLineEdit->setText("");
880 m_pProgressBar->setValue(100);
881 EnableAction(false);
882 if(m_pInspector)
883 m_pInspector->setChecked(false);
884 }
885 emit sigUpdateTitle();
886}
887
888void CFrmWebBrowser::EnableAction(bool enable)
889{
890 if(m_pBack)
891 m_pBack->setEnabled(false);
892 if(m_pForward)
893 m_pForward->setEnabled(false);
894 if(m_pRefresh)
895 m_pRefresh->setEnabled(enable);
896 if(m_pStop)
897 m_pStop->setEnabled(false);
898 if(m_pFind)
899 m_pFind->setEnabled(enable);
900 if(m_pFindNext)
901 m_pFindNext->setEnabled(enable);
902 if(m_pFindPrevious)
903 m_pFindPrevious->setEnabled(enable);
904 if(m_pZoomOriginal)
905 m_pZoomOriginal->setEnabled(enable);
906 if(m_pZoomIn)
907 m_pZoomIn->setEnabled(enable);
908 if(m_pZoomOut)
909 m_pZoomOut->setEnabled(enable);
910 if(m_pInspector)
911 m_pInspector->setEnabled(enable);
912 if(m_pRecord)
913 m_pRecord->setEnabled(enable);
914}
915
916void CFrmWebBrowser::slotTabCloseRequested(int index)
917{
918 qDebug(log) << "slotTabCloseRequested:" << index;
919 if(-1 == index || !m_pTab) return;
920 auto pView = m_pTab->widget(index);
921 if(pView)
922 pView->deleteLater();
923 m_pTab->removeTab(index);
924}
925
926void CFrmWebBrowser::slotViewCloseRequested()
927{
928 CFrmWebView* p = qobject_cast<CFrmWebView*>(sender());
929 if(!p) return;
930 int index = IndexOfTab(p);
931 slotTabCloseRequested(index);
932}
933
934void CFrmWebBrowser::slotReturnPressed()
935{
936 slotUrlSelected(m_pUrlLineEdit->text());
937}
938
939void CFrmWebBrowser::slotUrlSelected(const QString &szUrl)
940{
941 if(szUrl.isEmpty()) return;
942 QUrl url = QUrl::fromUserInput(szUrl);
943 qDebug(log) << url << szUrl << url.isValid();
944 if(szUrl.startsWith("@search:", Qt::CaseInsensitive)) {
945 QString szSearch;
946 QString keyword = szUrl.mid(8);
947 if(m_pPara) {
948 szSearch = m_pPara->GetSearchEngine();
949 url = szSearch.replace(m_pPara->GetSearchRelaceString(),
950 QUrl::toPercentEncoding(keyword));
951 }
952 }
953 emit sigInformation(url.toString());
954 CFrmWebView* pWeb = CurrentView();
955 if(!pWeb)
956 pWeb = qobject_cast<CFrmWebView*>(CreateWindow(QWebEnginePage::WebBrowserTab));
957 pWeb->load(url);
958 if(m_pGo->isVisible())
959 m_pGo->setVisible(false);
960}
961
962void CFrmWebBrowser::slotInspector(bool checked)
963{
964 CFrmWebView* pWeb = CurrentView();
965 if(!pWeb || !m_pTab) return;
966 auto dev = CurrentView(ViewType::DevTools);
967 if(pWeb && pWeb->page() && checked) {
968 if(!dev) {
969 auto w = m_pTab->currentWidget();
970 if(!w) return;
971 QSplitter *pSplitter = qobject_cast<QSplitter*>(w);
972 if(!pSplitter || 1 != pSplitter->count()) return;
973 dev = CreateWebView(pWeb->page()->profile()->isOffTheRecord());
974 if(dev) {
975 dev->show();
976 pSplitter->addWidget(dev);
977 bool check = connect(pWeb, &CFrmWebView::sigDevToolsRequested,
978 this, [&](){
979 if(m_pInspector)
980 m_pInspector->setChecked(true);
981 });
982 Q_ASSERT(check);
983 check = connect(dev, &CFrmWebView::sigCloseRequested,
984 this, [this]() {
985 m_pInspector->setChecked(false);
986 });
987 Q_ASSERT(check);
988 }
989 }
990 if(dev) {
991 pWeb->page()->setDevToolsPage(dev->page());
992 if(dev->isHidden())
993 dev->show();
994 }
995 } else {
996 pWeb->page()->setDevToolsPage(nullptr);
997 if(dev) {
998 dev->setParent(nullptr);
999 dev->deleteLater();
1000 }
1001 }
1002}
1003
1004int CFrmWebBrowser::Load(QSettings &set)
1005{
1006 if(m_pPara && m_pPara->GetOpenPrevious()) {
1007 set.beginGroup("OpenPrevious");
1008 int nCount = 0;
1009 nCount = set.value("Count", 0).toInt();
1010 int nCurrent = set.value("Current", -1).toInt();
1011 for(int i = 0; i < nCount; i++)
1012 {
1013 QString u = set.value("Url/" + QString::number(i)).toString();
1014 auto pView = CreateWindow(QWebEnginePage::WebBrowserTab);
1015 pView->load(QUrl(u));
1016
1017 QByteArray history;
1018 history = set.value("History/" + QString::number(i)).toByteArray();
1019 QDataStream d(&history, QIODevice::ReadWrite);
1020 d >> *pView->history();
1021 }
1022 if(-1 < nCurrent && m_pTab->count() > nCurrent)
1023 m_pTab->setCurrentIndex(nCurrent);
1024 set.endGroup();
1025 }
1026 return 0;
1027}
1028
1029int CFrmWebBrowser::Save(QSettings &set)
1030{
1031 if(m_pPara && m_pPara->GetOpenPrevious()) {
1032 set.beginGroup("OpenPrevious");
1033 set.setValue("Count", m_pTab->count());
1034 set.setValue("Current", m_pTab->currentIndex());
1035
1036 for(int i = 0; i < m_pTab->count(); i++) {
1037 auto v = GetView(i);
1038 if(v) {
1039 set.setValue("Url/" + QString::number(i), v->url().toString());
1040 QByteArray history;
1041 QDataStream d(&history, QIODevice::ReadWrite);
1042 d << *v->history();
1043 set.setValue("History/" + QString::number(i), history);
1044 }
1045 }
1046
1047 set.endGroup();
1048 }
1049 return 0;
1050}
1051
1052void CFrmWebBrowser::slotPrint()
1053{
1054 CFrmWebView* pWeb = CurrentView();
1055 if(pWeb) {
1056#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
1057 QPrinter printer;
1058 pWeb->print(&printer);
1059#endif
1060 }
1061}
1062
1063void CFrmWebBrowser::slotPrintFinished(bool success)
1064{
1065 if(success && m_pPara->GetPromptPrintFinished()) {
1066 QMessageBox::information(this, tr("Print finished"),
1067 tr("Successfully printed"));
1068 }
1069}
1070
1071void CFrmWebBrowser::slotPrintToPdf()
1072{
1073 CFrmWebView* pWeb = CurrentView();
1074 if(pWeb) {
1075 QString szPath;
1076 szPath += RabbitCommon::CDir::Instance()->GetDirUserData()
1077 + QDir::separator() + "pdf";
1078 QDir d(szPath);
1079 if(!d.exists())
1080 d.mkpath(szPath);
1081 szPath += QDir::separator() + pWeb->page()->title() + ".pdf";
1082 qDebug(log) << "pdf:" << szPath;
1083#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
1084 pWeb->printToPdf(szPath);
1085#endif
1086 }
1087}
1088
1089void CFrmWebBrowser::slotPdfPrintingFinished(const QString& szFile, bool success) {
1090 if(success && m_pPara->GetPromptPrintFinished())
1091 QMessageBox::information(this, tr("Print to PDF finished"),
1092 tr("Successfully printed to PDF.") + "\n"
1093 + tr("PDF file: ") + szFile);
1094 qDebug(log) << "Print to PDF:" << szFile << success;
1095}
1096
1097void CFrmWebBrowser::slotFullScreen(bool bFullScreen)
1098{
1099 if(sender() == this)
1100 return;
1101 if(bFullScreen) {
1102 m_pToolBar->hide();
1103 m_pProgressBar->hide();
1104 m_pTab->tabBar()->setVisible(false);
1105 m_szStyleSheet = m_pTab->styleSheet();
1106 m_pTab->setStyleSheet("QTabWidget::pane{top:0px;left:0px;border:none;}");
1107 } else {
1108 m_pToolBar->show();
1109 m_pProgressBar->show();
1110 m_pTab->tabBar()->setVisible(true);
1111 m_pTab->setStyleSheet(m_szStyleSheet);
1112 if(CurrentView() && CurrentView()->page() && CurrentView()->page()->action(QWebEnginePage::ExitFullScreen))
1113 CurrentView()->page()->action(QWebEnginePage::ExitFullScreen)->toggle();
1114 }
1115 emit sigFullScreen(bFullScreen);
1116}
1117
1118void CFrmWebBrowser::slotCapturePage()
1119{
1120 auto pWeb = CurrentView();
1121 if(!pWeb) return;
1122
1123 QString szMsg;
1124 QPixmap pixmap = pWeb->grab();
1125 QImage image = pixmap.toImage();
1126 QString szFile = m_pPara->m_Record.GetImageFile(true);
1127 if(szFile.isEmpty() && image.isNull()) return;
1128 if(!image.save(szFile, "PNG"))
1129 {
1130 QString szErr;
1131 szErr = tr("Fail: Save capture page to the file: ") + szFile;
1132 qCritical(log) << szErr;
1133 emit sigError(RV::FailCapturePage, szErr);
1134 return;
1135 }
1136 szMsg = tr("Save capture page to the file:") + szFile;
1137 qInfo(log) << szMsg;
1138 emit sigInformation(szMsg);
1139 qDebug(log) << "End action:" << m_pPara->m_Record.GetEndAction();
1140 switch(m_pPara->m_Record.GetEndAction())
1141 {
1142 case CParameterRecord::ENDACTION::OpenFile: {
1143 bool bRet = QDesktopServices::openUrl(QUrl::fromLocalFile(szFile));
1144 if(!bRet)
1145 qCritical(log) << "Fail: Open capture page the file:" << szFile;
1146 break;
1147 }
1148 case CParameterRecord::ENDACTION::OpenFolder: {
1149 QFileInfo fi(szFile);
1150 QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absolutePath()));
1151 break;
1152 }
1153 default:
1154 break;
1155 }
1156}
1157
1158void CFrmWebBrowser::slotCaptureFullPage()
1159{
1160 auto pWeb = CurrentView();
1161 if(!pWeb) return;
1162 qDebug(log) << "contents size:" << pWeb->page()->contentsSize();
1163 QString szFile = m_pPara->m_Record.GetImageFile(true);
1164 CCaptureFullPage *pCapture = new CCaptureFullPage();
1165 if(szFile.isEmpty() || !pCapture)
1166 return;
1167 bool check = connect(pCapture, &CCaptureFullPage::sigFinished,
1168 this, [this, pWeb, szFile, pCapture](){
1169 pWeb->setEnabled(true);
1170 qDebug(log) << "End action:" << m_pPara->m_Record.GetEndAction();
1171 QFileInfo fi(szFile);
1172 if(!fi.exists()) {
1173 QString szErr = tr("Fail: capture full page");
1174 qCritical(log) << szErr;
1175 emit sigError(FailCaptureFullPage, szErr);
1176 } else {
1177 QString szMsg = tr("Capture full page to") + " " + szFile;
1178 qInfo(log) << szMsg;
1179 emit sigInformation(szMsg);
1180 switch(m_pPara->m_Record.GetEndAction())
1181 {
1182 case CParameterRecord::ENDACTION::OpenFile: {
1183 bool bRet = QDesktopServices::openUrl(QUrl::fromLocalFile(szFile));
1184 if(!bRet)
1185 qCritical(log) << "Fail: Open capture page the file:" << szFile;
1186 break;
1187 }
1188 case CParameterRecord::ENDACTION::OpenFolder: {
1189 QFileInfo fi(szFile);
1190 QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absolutePath()));
1191 break;
1192 }
1193 default:
1194 break;
1195 }
1196 pCapture->deleteLater();
1197 }
1198 });
1199 Q_ASSERT(check);
1200 pWeb->setEnabled(false);
1201 pCapture->Start(pWeb, pWeb->url(), szFile);
1202
1203 emit sigInformation(tr("Start capture full page"));
1204}
1205
1206void CFrmWebBrowser::slotRecord()
1207{
1208 if(m_pRecord->isChecked()) {
1209 m_pRecord->setText(tr("Stop record"));
1210 m_pRecord->setIcon(QIcon::fromTheme("media-stop"));
1211
1212 Q_ASSERT(!m_pMultimediaRecord);
1213 // Note: It automatically releases memory when exiting.
1214 // See: CMultimediaRecordThread::CMultimediaRecordThread()
1215 m_pMultimediaRecord = new CMultimediaRecordThread(m_pPara);
1216 if(m_pMultimediaRecord) {
1217 connect(m_pMultimediaRecord, &CMultimediaRecordThread::finished,
1218 this, [this]() {
1219 m_pMultimediaRecord = nullptr;
1220 if(m_pRecord->isChecked()) {
1221 m_pRecord->activate(QAction::Trigger);
1222 emit sigError(RV::FailRecordPage, tr("Fail record web page"));
1223 }
1224 });
1225 m_pMultimediaRecord->start();
1226 }
1227
1228 // modify interval
1229 qreal rate = m_pPara->m_Record.GetVideoFrameRate();
1230 if(rate <= 0)
1231 rate = 24;
1232 m_tmRecord.start(qreal(1000) / rate);
1233 emit sigInformation(tr("Start record web page"));
1234 } else {
1235 m_pRecord->setIcon(QIcon::fromTheme("media-record"));
1236 m_pRecord->setText(tr("Record"));
1237 m_tmRecord.stop();
1238 if(m_pMultimediaRecord) {
1239 QMetaObject::invokeMethod(m_pMultimediaRecord,
1240 "slotQuit",
1241 Qt::AutoConnection);
1242 m_pMultimediaRecord = nullptr;
1243 emit sigInformation(tr("Record web page is stopped"));
1244 }
1245 }
1246 m_pRecord->setStatusTip(m_pRecord->text());
1247}
1248
1249void CFrmWebBrowser::slotRecordTimeout()
1250{
1251 //qDebug(log) << Q_FUNC_INFO;
1252 if(!m_pMultimediaRecord) return;
1253 auto pWeb = CurrentView();
1254 if(!pWeb) return;
1255 QPixmap pixmap = pWeb->grab();
1256 QImage image = pixmap.toImage();
1257 if(image.isNull()) return;
1258 QMetaObject::invokeMethod(m_pMultimediaRecord,
1259 "slotUpdateVideoFrame",
1260 Qt::AutoConnection,
1261 Q_ARG(QImage, image));
1262}
1263
1264void CFrmWebBrowser::slotAddBookmark()
1265{
1266 auto pView = CurrentView();
1267 if(!pView) return;
1268
1269 QUrl url = pView->url();
1270 if(url.isEmpty())
1271 url = m_pUrlLineEdit->text();
1272 CFrmAddBookmark* pAdd = new CFrmAddBookmark(
1273 pView->title(), url, pView->favIcon(),
1274 m_pPara);
1275 bool check = connect(this, &CFrmWebBrowser::destroyed, pAdd, &CFrmAddBookmark::close);
1276 Q_ASSERT(check);
1277 RC_SHOW_WINDOW(pAdd);
1278}
1279
1280void CFrmWebBrowser::slotBookmark()
1281{
1282 CFrmBookmark* pBookmark = new CFrmBookmark(m_pPara);
1283 if(!pBookmark) return;
1284 pBookmark->setAttribute(Qt::WA_DeleteOnClose);
1285 connect(this, &CFrmWebBrowser::destroyed, pBookmark, &CFrmBookmark::close);
1286 connect(pBookmark, &CFrmBookmark::openUrlRequested, this, [&](const QString& url) {
1287 CFrmWebView* pWeb = CurrentView();
1288 if(!pWeb) {
1289 pWeb = qobject_cast<CFrmWebView*>(CreateWindow(QWebEnginePage::WebBrowserTab));
1290 }
1291 if(pWeb)
1292 pWeb->load(url);
1293 });
1294 RC_SHOW_WINDOW(pBookmark);
1295}
1296
1297void CFrmWebBrowser::slotHistory()
1298{
1299 CFrmHistory* pHistory = new CFrmHistory(m_pPara);
1300 if(!pHistory) return;
1301 pHistory->setAttribute(Qt::WA_DeleteOnClose);
1302 connect(this, &CFrmWebBrowser::destroyed, pHistory, &CFrmHistory::close);
1303 connect(pHistory, &CFrmHistory::sigOpenUrl, this, [&](const QString& url) {
1304 CFrmWebView* pWeb = CurrentView();
1305 if(!pWeb) {
1306 pWeb = qobject_cast<CFrmWebView*>(CreateWindow(QWebEnginePage::WebBrowserTab));
1307 }
1308 if(pWeb)
1309 pWeb->load(url);
1310 });
1311 connect(pHistory, &CFrmHistory::sigOpenUrlInNewTab,
1312 this, [&](const QString& url) {
1313 auto pWeb = qobject_cast<CFrmWebView*>(CreateWindow(QWebEnginePage::WebBrowserTab));
1314 if(pWeb)
1315 pWeb->load(url);
1316 });
1317 RC_SHOW_WINDOW(pHistory);
1318}
void sigUpdateTitle()
Title or icon changed.
The CMultimediaRecordThread class.