diff --git a/main.cpp b/main.cpp index 18cca1e..24e1acb 100644 --- a/main.cpp +++ b/main.cpp @@ -10,5 +10,7 @@ int main(int argc, char *argv[]) a.setApplicationVersion(QString::number(APP_VERSION)); MainWindow w; w.show(); - return a.exec(); + int res = a.exec(); + MainWindow::cleanup(); + return res; } diff --git a/mainwindow.cpp b/mainwindow.cpp index dc07749..624af23 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -155,18 +155,9 @@ QUrl MainWindow::sanitizeUrl(const QUrl &url) if (!url.isValid()) return QUrl("about:blank"); if (url.isRelative()) { - if (url.toString().endsWith(".com") || - url.toString().endsWith(".net") || - url.toString().endsWith(".org") || - url.toString().endsWith(".info") || - url.toString().endsWith(".co") || - url.toString().endsWith(".uk") || - url.toString().endsWith(".de") || - url.toString().endsWith(".fr") || - url.toString().endsWith(".pl") || - url.toString().endsWith(".io")) { - return QUrl("http://" + url.toEncoded()); - } + QString s = url.toString(); + if (s.contains('.') && !s.contains(' ')) + return QUrl::fromUserInput(s); return QUrl(_searchPage.toString().replace("[query]", url.toEncoded())); } return url; @@ -200,6 +191,14 @@ WEBVIEW_IMPL *MainWindow::currentWebView() const return nullptr; } +void MainWindow::cleanup() +{ + delete _historyManager; + _historyManager = nullptr; + delete _bookmarksManager; + _bookmarksManager = nullptr; +} + void MainWindow::closeEvent(QCloseEvent* event) { saveSettings(); @@ -260,7 +259,7 @@ void MainWindow::removeWorkspace() QAction *a = _ui->workspaces->checkedAction(); QMessageBox *confirmBox = new QMessageBox(this); - confirmBox->setText("Do you want to remove the current workspace " + a->text() + "?"); + confirmBox->setText(tr("Do you want to remove the current workspace %1?").arg(a->text())); confirmBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No); confirmBox->setDefaultButton(QMessageBox::No); if(confirmBox->exec() != QMessageBox::Yes) @@ -369,7 +368,6 @@ bool MainWindow::clearData() QString path(QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/.cache/" + QFileInfo(QApplication::applicationFilePath()).fileName() + "/WebKitCache"); #endif qDebug() << "Removing" << path; - QThread::msleep(500); return QDir(path).removeRecursively(); } @@ -415,7 +413,7 @@ void MainWindow::on_tabAreas_triggered() void MainWindow::on_actionAbout_triggered() { - QMessageBox::about(this, "About " + QApplication::applicationName(), + QMessageBox::about(this, tr("About %1").arg(QApplication::applicationName()), QApplication::applicationName() + " version " + QApplication::applicationVersion() + #if USE_WEBKIT "\nPlaywright WebKit revision " + QString::number(WEBKIT_VERSION) + @@ -468,7 +466,8 @@ void MainWindow::on_actionFullscreen_toggled(bool checked) if (checked) { showFullScreen(); #if USE_NATIVE - currentWebView()->findChild("wvtoolbar")->hide(); + if (currentWebView()) + currentWebView()->findChild("wvtoolbar")->hide(); #endif } else { if (isMinimized()) @@ -477,13 +476,16 @@ void MainWindow::on_actionFullscreen_toggled(bool checked) showMaximized(); else showNormal(); #if USE_NATIVE - currentWebView()->findChild("wvtoolbar")->show(); + if (currentWebView()) + currentWebView()->findChild("wvtoolbar")->show(); #endif } } void MainWindow::onShowBookmarksDialog() { + if (!currentWebView()) + return; BookmarksDialog *dialog = new BookmarksDialog(this); connect(dialog, SIGNAL(openUrl(QUrl)), currentWebView(), SLOT(load(QUrl))); @@ -493,6 +495,8 @@ void MainWindow::onShowBookmarksDialog() void MainWindow::onAddBookmark() { IQWebView *webView = currentWebView(); + if (!webView) + return; QString url = webView->url().toString(); QString title = webView->title(); AddBookmarkDialog dialog(url, title); diff --git a/mainwindow.h b/mainwindow.h index 57d6b17..3a86ec2 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -38,6 +38,7 @@ class MainWindow : public QMainWindow static BookmarksManager *bookmarksManager(); QSize sizeHint() const override; WEBVIEW_IMPL *currentWebView() const; + static void cleanup(); protected: virtual void closeEvent(QCloseEvent*) override; private: diff --git a/qnativewebview.cpp b/qnativewebview.cpp index df4c944..6ba7e8b 100644 --- a/qnativewebview.cpp +++ b/qnativewebview.cpp @@ -18,9 +18,9 @@ QNativeWebView::QNativeWebView(QWidget *parent, QUrl url) : QWidget(parent) { _wv = new webview::webview(false, nullptr); if (!WEBVIEW->window()) { - QMessageBox::critical(this, QApplication::applicationName(), "Cannot initialize native webview!" + QMessageBox::critical(this, QApplication::applicationName(), tr("Cannot initialize native webview!") #ifdef _WIN32 - "\nInstall Edge WebView2 from https://developer.microsoft.com/en-us/microsoft-edge/webview2/consumer/" + + "\n" + tr("Install Edge WebView2 from https://developer.microsoft.com/en-us/microsoft-edge/webview2/consumer/") #endif ); exit(1); @@ -44,25 +44,25 @@ QNativeWebView::QNativeWebView(QWidget *parent, QUrl url) : QWidget(parent) QAction *backAction = new QAction(QIcon(":/icons/back.svg"), tr("&Back"), this); backAction->setShortcut(QKeySequence("Alt+Left")); - backAction->setToolTip("Go back"); + backAction->setToolTip(tr("Go back")); connect(backAction, &QAction::triggered, this, &QNativeWebView::back); toolbar->addAction(backAction); QAction *forwardAction = new QAction(QIcon(":/icons/forward.svg"), tr("&Forward"), this); forwardAction->setShortcut(QKeySequence("Alt+Right")); - forwardAction->setToolTip("Go forward"); + forwardAction->setToolTip(tr("Go forward")); connect(forwardAction, &QAction::triggered, this, &QNativeWebView::forward); toolbar->addAction(forwardAction); QAction *refreshAction = new QAction(QIcon(":/icons/refresh.svg"), tr("&Refresh"), this); refreshAction->setShortcuts(QKeySequence::Refresh); - refreshAction->setToolTip("Refresh"); + refreshAction->setToolTip(tr("Refresh")); connect(refreshAction, &QAction::triggered, this, &QNativeWebView::reload); toolbar->addAction(refreshAction); QAction *stopAction = new QAction(QIcon(":/icons/close.svg"), tr("&Stop"), this); stopAction->setShortcuts(QKeySequence::Cancel); - stopAction->setToolTip("Stop"); + stopAction->setToolTip(tr("Stop")); refreshAction->setVisible(false); connect(stopAction, &QAction::triggered, this, &QNativeWebView::stop); toolbar->addAction(stopAction); @@ -136,7 +136,7 @@ QString QNativeWebView::title() const bool QNativeWebView::eventFilter(QObject *obj, QEvent *event) { - if (obj == _addressBar && event->type() == 8 /* QEvent::FocusIn */) + if (obj == _addressBar && event->type() == QEvent::FocusIn) QTimer::singleShot(0, _addressBar, &QLineEdit::selectAll); return QWidget::eventFilter(obj, event); } diff --git a/webview.h b/webview.h index 55112d8..e661e41 100644 --- a/webview.h +++ b/webview.h @@ -170,6 +170,7 @@ WEBVIEW_API void webview_return(webview_t w, const char *seq, int status, #include #include #include +#include #include #include #include @@ -1166,19 +1167,23 @@ class win32_edge_engine { char *get_title() { LPWSTR wtitle; m_webview->get_DocumentTitle(&wtitle); + if (!wtitle) return (char*)""; int length = WideCharToMultiByte(CP_UTF8, 0, wtitle, -1, 0, 0, NULL, NULL); - char *title = new char[length]; - WideCharToMultiByte(CP_UTF8, 0, wtitle, -1, title, length, NULL, NULL); - return title; + m_title.resize(length); + WideCharToMultiByte(CP_UTF8, 0, wtitle, -1, &m_title[0], length, NULL, NULL); + CoTaskMemFree(wtitle); + return (char *)m_title.c_str(); } char *get_url() { LPWSTR wurl; m_webview->get_Source(&wurl); + if (!wurl) return (char*)""; int length = WideCharToMultiByte(CP_UTF8, 0, wurl, -1, 0, 0, NULL, NULL); - char *url = new char[length]; - WideCharToMultiByte(CP_UTF8, 0, wurl, -1, url, length, NULL, NULL); - return url; + m_url.resize(length); + WideCharToMultiByte(CP_UTF8, 0, wurl, -1, &m_url[0], length, NULL, NULL); + CoTaskMemFree(wurl); + return (char *)m_url.c_str(); } void init(const std::string &js) { @@ -1245,6 +1250,8 @@ class win32_edge_engine { virtual void on_message(const std::string &msg) = 0; + std::string m_title; + std::string m_url; HWND m_window; POINT m_minsz = POINT{0, 0}; POINT m_maxsz = POINT{0, 0}; @@ -1330,6 +1337,16 @@ class webview : public browser_engine { webview(bool debug = false, void *wnd = nullptr) : browser_engine(debug, wnd) {} + virtual ~webview() { + for (auto const& [name, ctx] : bindings) { + delete ctx->first; + if (m_sync_bindings.count(ctx->second)) { + delete static_cast(ctx->second); + } + delete ctx; + } + } + void navigate(const std::string &url) { if (url == "") { browser_engine::navigate("about:blank"); @@ -1345,13 +1362,15 @@ class webview : public browser_engine { using sync_binding_ctx_t = std::pair; void bind(const std::string &name, sync_binding_t fn) { + auto sync_ctx = new sync_binding_ctx_t(this, fn); + m_sync_bindings.insert(sync_ctx); bind( name, [](const std::string &seq, const std::string &req, void *arg) { auto pair = static_cast(arg); pair->first->resolve(seq, 0, pair->second(req)); }, - new sync_binding_ctx_t(this, fn)); + sync_ctx); } void bind(const std::string &name, binding_t f, void *arg) { @@ -1375,6 +1394,7 @@ class webview : public browser_engine { })())"; init(js); eval(js); + unbind(name); bindings[name] = new binding_ctx_t(new binding_t(f), arg); } @@ -1383,9 +1403,13 @@ class webview : public browser_engine { auto js = "delete window['" + name + "'];"; init(js); eval(js); - delete bindings[name]->first; - delete static_cast(bindings[name]->second); - delete bindings[name]; + auto ctx = bindings[name]; + delete ctx->first; + if (m_sync_bindings.count(ctx->second)) { + delete static_cast(ctx->second); + m_sync_bindings.erase(ctx->second); + } + delete ctx; bindings.erase(name); } } @@ -1414,6 +1438,7 @@ class webview : public browser_engine { (*fn->first)(seq, args, fn->second); } std::map bindings; + std::set m_sync_bindings; }; } // namespace webview