Asynchronous messages, file dialogs and call/cc stuff

This commit is contained in:
2026-03-12 17:08:20 +01:00
parent d99c5a1725
commit 2cbf6fb98b
11 changed files with 363 additions and 199 deletions

View File

@@ -15,6 +15,8 @@
#include <QWebEngineScript>
#include "command.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QAbstractButton>
static inline char *copyString(const char *s)
{
@@ -425,7 +427,6 @@ rkt_wv_context_t Rktwebview_qt::newContext(const char *boilerplate_js, const cha
QWebEngineScriptCollection *c = p->scripts();
QList<QWebEngineScript> l = c->toList();
printf("%d\n", l.size());
_contexts[_context_counter] = p;
@@ -595,85 +596,72 @@ window_state_t Rktwebview_qt::rktWindowState(rktwebview_t w)
return ws;
}
rkt_data_t *Rktwebview_qt::rktChooseDir(rktwebview_t w, const char *title, const char *base_dir)
result_t Rktwebview_qt::fileDlg(rktwebview_t w, const char *title, const char *base, const char *filters,QFileDialog::FileMode mode, QFileDialog::AcceptMode am, QString evt_ok, QString evt_cancel)
{
Command c(COMMAND_CHOOSE_DIR);
c.args.push_back(w);
if (_views.contains(w)) {
WebviewWindow *win = _views[w];
QString t(title);
c.args.push_back(t);
QFileDialog *dlg = new QFileDialog(win, title, base);
dlg->setFileMode(mode);
dlg->setAcceptMode(am);
QString dir(base_dir);
c.args.push_back(dir);
QString pe = filters;
QStringList p = pe.split(";;");
postCommand(&c);
dlg->setNameFilters(p);
dlg->setProperty("rktwebview", w);
dlg->setProperty("evt-ok", evt_ok);
dlg->setProperty("evt-cancel", evt_cancel);
while(!c.done) { doEvents(); }
connect(dlg, &QFileDialog::accepted, this, [this]() {
QFileDialog *dlg = static_cast<QFileDialog *>(sender());
bool oke = c.js_result_ok;
rktwebview_t w = dlg->property("rktwebview").toInt();
QString evt_ok = dlg->property("evt-ok").toString();
rkt_data_t *r = static_cast<rkt_data_t *>(malloc(sizeof(rkt_js_result_t)));
r->kind = js_result;
r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
r->data.js_result.value = copyString(c.result.toString().toUtf8());
QStringList l = dlg->selectedFiles();
QString file;
if (l.size() > 0) {
file = dlg->selectedFiles().first();
}
return r;
EventContainer e(evt_ok);
e["choosen"] = file;
e["filter"] = dlg->selectedNameFilter();
e["dir"] = dlg->directory().path();
this->triggerEvent(w, e);
});
connect(dlg, &QDialog::rejected, this, [this]() {
QFileDialog *dlg = static_cast<QFileDialog *>(sender());
rktwebview_t w = dlg->property("rktwebview").toInt();
QString evt_cancel = dlg->property("evt-cancel").toString();
EventContainer e(evt_cancel);
this->triggerEvent(w, e);
});
dlg->show();
return result_t::oke;
} else {
return result_t::failed;
}
}
rkt_data_t *Rktwebview_qt::rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
result_t Rktwebview_qt::rktChooseDir(rktwebview_t w, const char *title, const char *base_dir)
{
Command c(COMMAND_FILE_OPEN);
c.args.push_back(w);
QString t(title);
c.args.push_back(t);
QString dir(base_dir);
c.args.push_back(dir);
QString exts(permitted_exts);
c.args.push_back(exts);
postCommand(&c);
while(!c.done) { doEvents(); }
bool oke = c.js_result_ok;
rkt_data_t *r = static_cast<rkt_data_t *>(malloc(sizeof(rkt_data_t)));
r->kind = js_result;
r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
return fileDlg(w, title, base_dir, "", QFileDialog::Directory, QFileDialog::AcceptOpen, "choose-dir-ok", "choose-dir-cancel");
}
rkt_data_t *Rktwebview_qt::rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
result_t Rktwebview_qt::rktFileOpen(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
Command c(COMMAND_FILE_SAVE);
c.args.push_back(w);
return fileDlg(w, title, base_dir, permitted_exts, QFileDialog::ExistingFile, QFileDialog::AcceptOpen, "file-open-ok", "file-open-cancel");
}
QString t(title);
c.args.push_back(t);
QString dir(base_dir);
c.args.push_back(dir);
QString exts(permitted_exts);
c.args.push_back(exts);
postCommand(&c);
while(!c.done) { doEvents(); }
bool oke = c.js_result_ok;
rkt_data_t *r = static_cast<rkt_data_t *>(malloc(sizeof(rkt_data_t)));
r->kind = js_result;
r->data.js_result.result = c.js_result_ok ? result_t::oke : result_t::choose_dir_failed;
r->data.js_result.value = copyString(c.result.toString().toUtf8());
return r;
result_t Rktwebview_qt::rktFileSave(rktwebview_t w, const char *title, const char *base_dir, const char *permitted_exts)
{
return fileDlg(w, title, base_dir, permitted_exts, QFileDialog::AnyFile, QFileDialog::AcceptSave, "file-save-ok", "file-save-cancel");
}
result_t Rktwebview_qt::rktWindowSetTitle(rktwebview_t wv, const char *title)
@@ -687,6 +675,67 @@ result_t Rktwebview_qt::rktWindowSetTitle(rktwebview_t wv, const char *title)
return r ? result_t::oke : result_t::failed;
}
result_t Rktwebview_qt::rktMessageBox(rktwebview_t w, const char *title, const char *message, const char *submessage, rkt_messagetype_t type)
{
if (_views.contains(w)) {
WebviewWindow *win = _views[w];
QMessageBox *msg = new QMessageBox(win);
auto prepButton = [msg, w, this](QMessageBox::StandardButton b, QString event) {
msg->addButton(b);
QAbstractButton *btn = msg->button(b);
QVariant v = QVariant::fromValue(msg);
btn->setProperty("messagebox", v);
btn->setProperty("event", event);
btn->setProperty("rktwebview", w);
connect(btn, &QAbstractButton::clicked, this, [this]() {
QAbstractButton *btn = static_cast<QAbstractButton *>(sender());
QMessageBox *mb = btn->property("messagebox").value<QMessageBox *>();
rktwebview_t w = btn->property("rktwebview").toInt();
EventContainer e(btn->property("event").toString());
this->triggerEvent(w, e);
mb->close();
});
};
msg->setWindowTitle(title);
QString m = QString("<p>") + message + "</p>";
m += QString::asprintf("<p><small>%s</small></p>", submessage);
msg->setInformativeText(m);
QMessageBox::Icon icn;
if (type == rkt_messagetype_t::error) {
icn = QMessageBox::Icon::Critical;
prepButton(QMessageBox::StandardButton::Ok, "msgbox-ok");
} else if (type == rkt_messagetype_t::warning) {
icn = QMessageBox::Icon::Warning;
prepButton(QMessageBox::StandardButton::Ok, "msgbox-ok");
} else if (type == rkt_messagetype_t::yes_no || type == rkt_messagetype_t::oke_cancel) {
icn = QMessageBox::Icon::Question;
if (type == rkt_messagetype_t::yes_no) {
prepButton(QMessageBox::StandardButton::No, "msgbox-no");
prepButton(QMessageBox::StandardButton::Yes, "msgbox-yes");
} else {
prepButton(QMessageBox::StandardButton::Cancel, "msgbox-cancel");
prepButton(QMessageBox::StandardButton::Ok, "msgbox-ok");
}
} else { // informatio
icn = QMessageBox::Icon::Information;
prepButton(QMessageBox::StandardButton::Ok, "msgbox-ok");
}
msg->setIcon(icn);
msg->show();
return result_t::oke;
} else {
return result_t::failed;
}
}
result_t Rktwebview_qt::doWindow(rktwebview_t w, int cmd, result_t on_error)
{
Command c(cmd);