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