#include "BrowserTab.h" #include #include #include #include #include #include #include #include #include #include "PasswordHelper.h" #include "ThemeConfig.h" BrowserTab::BrowserTab(QWidget *parent) : QSplitter(Qt::Vertical, parent) { view = new BrowserView; devtools = new QWebEngineView; passwordHelper = new PasswordHelper(this); auto *channel = new QWebChannel(this); channel->registerObject("passwordHelper", passwordHelper); view->page()->setWebChannel(channel); view->page()->setDevToolsPage(devtools->page()); devtools->hide(); addWidget(view); addWidget(devtools); // Initial layout ratio setStretchFactor(0, 3); setStretchFactor(1, 1); setOpaqueResize(false); view->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); // Visual handle for resizing handle(1)->setAttribute(Qt::WA_Hover); setStyleSheet(QString("QSplitter::handle { background: %1; height: 4px; }").arg(ThemeConfig::SplitterHandleColorLight)); // Close devtools if requested by the page (e.g. clicking 'x') connect(devtools->page(), &QWebEnginePage::windowCloseRequested, [this]() { setDevToolsVisible(false); }); setupScripts(); } void BrowserTab::setupScripts() { QWebEngineScript qwebchannel; QFile file(":/js/qwebchannel.js"); if (file.open(QIODevice::ReadOnly)) { qwebchannel.setSourceCode(file.readAll()); qwebchannel.setName("qwebchannel.js"); qwebchannel.setWorldId(QWebEngineScript::MainWorld); qwebchannel.setInjectionPoint(QWebEngineScript::DocumentCreation); qwebchannel.setRunsOnSubFrames(true); view->page()->scripts().insert(qwebchannel); } else { qCritical() << "Failed to load bundled qwebchannel.js from resources!"; } QWebEngineScript passwordScript; QFile scriptFile(":/js/capture.js"); if (scriptFile.open(QIODevice::ReadOnly)) { passwordScript.setSourceCode(scriptFile.readAll()); passwordScript.setName("passwordScript"); passwordScript.setWorldId(QWebEngineScript::MainWorld); passwordScript.setInjectionPoint(QWebEngineScript::DocumentReady); passwordScript.setRunsOnSubFrames(true); view->page()->scripts().insert(passwordScript); } else { qCritical() << "Failed to load capture.js from resources!"; } } void BrowserTab::setDevToolsVisible(bool visible) { devtools->setVisible(visible); if (visible) { int h = height(); setSizes({static_cast(h * 0.7), static_cast(h * 0.3)}); } else { setSizes({height(), 0}); } } void BrowserTab::updateTabTheme(bool dark) { view->settings()->setAttribute(QWebEngineSettings::ForceDarkMode, false); devtools->settings()->setAttribute(QWebEngineSettings::ForceDarkMode, false); view->page()->setBackgroundColor(dark ? QColor(45, 45, 45) : Qt::white); devtools->page()->setBackgroundColor(dark ? QColor(45, 45, 45) : Qt::white); // Keep the view palette default to allow it to inherit from the application view->setPalette(QPalette()); devtools->setPalette(QPalette()); QString handleColor = dark ? ThemeConfig::SplitterHandleColorDark : ThemeConfig::SplitterHandleColorLight; setStyleSheet(QString("QSplitter::handle { background: %1; height: 4px; }").arg(handleColor)); }