More random methods and events (#847)

* Add `maximumViewportSize()`, `setHorizontalScrollBar()` & `setVerticalScrollBar()` to `QAbstractScrollArea`

* Log any JS exceptions thrown during Qt event dispatch

* Add `setData()` & `data()` to `QAction`

* Add `clear()` to `QMenu`

* Add `triggered` event support to `QMenu`

* Code style fixes

* Add `focusWindowChanged` event to `QApplication`

* Add `isActiveWindow()` to `QWidget`
This commit is contained in:
Simon Edwards 2021-07-04 12:55:41 +02:00 committed by GitHub
parent b5d7e957cf
commit f4e0ca1677
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 173 additions and 36 deletions

View File

@ -1,5 +1,7 @@
#pragma once
#include <QApplication>
#include <QGuiApplication>
#include <QWindow>
#include "Extras/Export/export.h"
#include "QtCore/QObject/qobject_macro.h"
@ -13,5 +15,12 @@ class DLL_EXPORT NApplication : public QApplication, public EventWidget {
void connectSignalsToEventEmitter() {
// Qt Connects: Implement all signal connects here
QOBJECT_SIGNALS
QObject::connect(
this, &QGuiApplication::focusWindowChanged, [=](QWindow* focusWindow) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call({Napi::String::New(env, "focusWindowChanged")});
});
}
};

View File

@ -1,6 +1,8 @@
#pragma once
#include "QtCore/QSize/qsize_wrap.h"
#include "QtWidgets/QFrame/qframe_macro.h"
#include "QtWidgets/QScrollBar/qscrollbar_wrap.h"
#include "QtWidgets/QWidget/qwidget_wrap.h"
/*
@ -11,39 +13,75 @@
*/
#ifndef QABSTRACTSCROLLAREA_WRAPPED_METHODS_DECLARATION
#define QABSTRACTSCROLLAREA_WRAPPED_METHODS_DECLARATION \
\
QFRAME_WRAPPED_METHODS_DECLARATION \
\
Napi::Value setViewport(const Napi::CallbackInfo& info) { \
Napi::Env env = info.Env(); \
Napi::HandleScope scope(env); \
Napi::Object viewPortObject = info[0].As<Napi::Object>(); \
NodeWidgetWrap* viewPortWidgetWrap = \
Napi::ObjectWrap<NodeWidgetWrap>::Unwrap(viewPortObject); \
QWidget* viewPort = viewPortWidgetWrap->getInternalInstance(); \
this->instance->setViewport(viewPort); \
return env.Null(); \
} \
\
Napi::Value viewport(const Napi::CallbackInfo& info) { \
Napi::Env env = info.Env(); \
Napi::HandleScope scope(env); \
QWidget* viewPort = this->instance->viewport(); \
NWidget* nviewPort = reinterpret_cast<NWidget*>(viewPort); \
auto instance = QWidgetWrap::constructor.New( \
{Napi::External<NWidget>::New(env, nviewPort)}); \
return instance; \
#define QABSTRACTSCROLLAREA_WRAPPED_METHODS_DECLARATION \
\
QFRAME_WRAPPED_METHODS_DECLARATION \
\
Napi::Value maximumViewportSize(const Napi::CallbackInfo& info) { \
Napi::Env env = info.Env(); \
Napi::HandleScope scope(env); \
QSize size = this->instance->maximumViewportSize(); \
auto instance = QSizeWrap::constructor.New( \
{Napi::External<QSize>::New(env, new QSize(size))}); \
return instance; \
} \
\
Napi::Value setHorizontalScrollBar(const Napi::CallbackInfo& info) { \
Napi::Env env = info.Env(); \
Napi::HandleScope scope(env); \
Napi::Object scrollBarObject = info[0].As<Napi::Object>(); \
QScrollBarWrap* scrollBarWrap = \
Napi::ObjectWrap<QScrollBarWrap>::Unwrap(scrollBarObject); \
QScrollBar* scrollBar = scrollBarWrap->getInternalInstance(); \
this->instance->setHorizontalScrollBar(scrollBar); \
return env.Null(); \
} \
\
Napi::Value setVerticalScrollBar(const Napi::CallbackInfo& info) { \
Napi::Env env = info.Env(); \
Napi::HandleScope scope(env); \
Napi::Object scrollBarObject = info[0].As<Napi::Object>(); \
QScrollBarWrap* scrollBarWrap = \
Napi::ObjectWrap<QScrollBarWrap>::Unwrap(scrollBarObject); \
QScrollBar* scrollBar = scrollBarWrap->getInternalInstance(); \
this->instance->setVerticalScrollBar(scrollBar); \
return env.Null(); \
} \
\
Napi::Value setViewport(const Napi::CallbackInfo& info) { \
Napi::Env env = info.Env(); \
Napi::HandleScope scope(env); \
Napi::Object viewPortObject = info[0].As<Napi::Object>(); \
NodeWidgetWrap* viewPortWidgetWrap = \
Napi::ObjectWrap<NodeWidgetWrap>::Unwrap(viewPortObject); \
QWidget* viewPort = viewPortWidgetWrap->getInternalInstance(); \
this->instance->setViewport(viewPort); \
return env.Null(); \
} \
\
Napi::Value viewport(const Napi::CallbackInfo& info) { \
Napi::Env env = info.Env(); \
Napi::HandleScope scope(env); \
QWidget* viewPort = this->instance->viewport(); \
NWidget* nviewPort = reinterpret_cast<NWidget*>(viewPort); \
auto instance = QWidgetWrap::constructor.New( \
{Napi::External<NWidget>::New(env, nviewPort)}); \
return instance; \
}
#endif // QABSTRACTSCROLLAREA_WRAPPED_METHODS_DECLARATION
#ifndef QABSTRACTSCROLLAREA_WRAPPED_METHODS_EXPORT_DEFINE
#define QABSTRACTSCROLLAREA_WRAPPED_METHODS_EXPORT_DEFINE(WidgetWrapName) \
\
QFRAME_WRAPPED_METHODS_EXPORT_DEFINE(WidgetWrapName) \
\
InstanceMethod("setViewport", &WidgetWrapName::setViewport), \
#define QABSTRACTSCROLLAREA_WRAPPED_METHODS_EXPORT_DEFINE(WidgetWrapName) \
\
QFRAME_WRAPPED_METHODS_EXPORT_DEFINE(WidgetWrapName) \
\
InstanceMethod("maximumViewportSize", &WidgetWrapName::maximumViewportSize), \
InstanceMethod("setHorizontalScrollBar", \
&WidgetWrapName::setVerticalScrollBar), \
InstanceMethod("setVerticalScrollBar", \
&WidgetWrapName::setVerticalScrollBar), \
InstanceMethod("setViewport", &WidgetWrapName::setViewport), \
InstanceMethod("viewport", &WidgetWrapName::viewport),
#endif // QABSTRACTSCROLLAREA_WRAPPED_METHODS_EXPORT_DEFINE

View File

@ -35,4 +35,6 @@ class DLL_EXPORT QActionWrap : public Napi::ObjectWrap<QActionWrap> {
Napi::Value isSeparator(const Napi::CallbackInfo& info);
Napi::Value setSeparator(const Napi::CallbackInfo& info);
Napi::Value setFont(const Napi::CallbackInfo& info);
Napi::Value data(const Napi::CallbackInfo& info);
Napi::Value setData(const Napi::CallbackInfo& info);
};

View File

@ -11,5 +11,16 @@ class DLL_EXPORT NMenu : public QMenu, public NodeWidget {
NODEWIDGET_IMPLEMENTATIONS(QMenu)
public:
using QMenu::QMenu; // inherit all constructors of QMenu
void connectSignalsToEventEmitter() { QWIDGET_SIGNALS }
void connectSignalsToEventEmitter() {
QWIDGET_SIGNALS
QObject::connect(this, &QMenu::triggered, [=](QAction* action) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
auto actionInstance = QActionWrap::constructor.New(
{Napi::External<QAction>::New(env, action)});
this->emitOnNode.Call(
{Napi::String::New(env, "triggered"), actionInstance});
});
}
};

View File

@ -19,6 +19,7 @@ class DLL_EXPORT QMenuWrap : public Napi::ObjectWrap<QMenuWrap> {
NMenu* getInternalInstance();
static Napi::FunctionReference constructor;
// wrapped methods
Napi::Value clear(const Napi::CallbackInfo& info);
Napi::Value setTitle(const Napi::CallbackInfo& info);
Napi::Value addSeparator(const Napi::CallbackInfo& info);
Napi::Value exec(const Napi::CallbackInfo& info);

View File

@ -29,6 +29,8 @@ Napi::Object QActionWrap::init(Napi::Env env, Napi::Object exports) {
InstanceMethod("isSeparator", &QActionWrap::isSeparator),
InstanceMethod("setSeparator", &QActionWrap::setSeparator),
InstanceMethod("setFont", &QActionWrap::setFont),
InstanceMethod("data", &QActionWrap::data),
InstanceMethod("setData", &QActionWrap::setData),
QOBJECT_WRAPPED_METHODS_EXPORT_DEFINE(QActionWrap)});
constructor = Napi::Persistent(func);
exports.Set(CLASSNAME, func);
@ -204,4 +206,32 @@ Napi::Value QActionWrap::setFont(const Napi::CallbackInfo& info) {
this->instance->setFont(*font);
return env.Null();
}
}
Napi::Value QActionWrap::setData(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::Object variantObject = info[0].As<Napi::Object>();
QVariantWrap* variantWrap =
Napi::ObjectWrap<QVariantWrap>::Unwrap(variantObject);
QVariant* variant = variantWrap->getInternalInstance();
this->instance->setData(*variant);
return env.Null();
}
Napi::Value QActionWrap::data(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
QVariant variant = this->instance->data();
if (variant.isNull()) {
return env.Null();
}
auto instance = QVariantWrap::constructor.New(
{Napi::External<QVariant>::New(env, new QVariant(variant))});
return instance;
}

View File

@ -16,6 +16,7 @@ Napi::Object QMenuWrap::init(Napi::Env env, Napi::Object exports) {
Napi::Function func =
DefineClass(env, CLASSNAME,
{InstanceMethod("setTitle", &QMenuWrap::setTitle),
InstanceMethod("clear", &QMenuWrap::clear),
InstanceMethod("addSeparator", &QMenuWrap::addSeparator),
InstanceMethod("exec", &QMenuWrap::exec),
InstanceMethod("popup", &QMenuWrap::popup),
@ -50,6 +51,14 @@ QMenuWrap::QMenuWrap(const Napi::CallbackInfo& info)
QMenuWrap::~QMenuWrap() { extrautils::safeDelete(this->instance); }
Napi::Value QMenuWrap::clear(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
this->instance->clear();
return env.Null();
}
Napi::Value QMenuWrap::setTitle(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);

View File

@ -70,4 +70,6 @@ export class QApplication extends NodeObject<QApplicationSignals> {
}
}
export type QApplicationSignals = QObjectSignals;
export interface QApplicationSignals extends QObjectSignals {
focusWindowChanged: () => void;
}

View File

@ -1,9 +1,11 @@
import { NodeWidget, QWidget } from './QWidget';
import { NodeFrame, QFrameSignals } from './QFrame';
import { ScrollBarPolicy } from '../QtEnums/ScrollBarPolicy';
import { QSize } from '../QtCore/QSize';
import { QScrollBar } from './QScrollBar';
/**
> Abstract class to add functionalities common to all scrollarea based widgets.
**This class implements all methods, properties of Qt's [QAbstractScrollArea class](https://doc.qt.io/qt-5/qabstractscrollarea.html) so that it can be inherited by all scroll based widgets**
@ -27,9 +29,18 @@ export abstract class QAbstractScrollArea<Signals extends QAbstractScrollAreaSig
}
return this.viewportWidget;
}
maximumViewportSize(): QSize {
return this.native.maximumViewportSize();
}
setHorizontalScrollBar(scrollBar: QScrollBar): void {
this.native.setHorizontalScrollBar(scrollBar.native);
}
setHorizontalScrollBarPolicy(policy: ScrollBarPolicy): void {
this.native.setProperty('horizontalScrollBarPolicy', policy);
}
setVerticalScrollBar(scrollBar: QScrollBar): void {
this.native.setVerticalScrollBar(scrollBar.native);
}
setVerticalScrollBarPolicy(policy: ScrollBarPolicy): void {
this.native.setProperty('verticalScrollBarPolicy', policy);
}

View File

@ -8,9 +8,10 @@ import { QKeySequence } from '../QtGui/QKeySequence';
import { ShortcutContext } from '../QtEnums';
import { NodeObject, QObjectSignals } from '../QtCore/QObject';
import { checkIfNativeElement } from '../utils/helpers';
import { QVariant } from '../QtCore/QVariant';
/**
> The QAction class provides an abstract user interface action that can be inserted into widgets.
* **This class is a JS wrapper around Qt's [QAction class](https://doc.qt.io/qt-5/qaction.html)**
@ -92,6 +93,12 @@ export class QAction extends NodeObject<QActionSignals> {
font(): QFont {
return QFont.fromQVariant(this.property('font'));
}
setData(value: QVariant): void {
this.native.setData(value.native);
}
data(): QVariant {
return new QVariant(this.native.data());
}
}
export interface QActionSignals extends QObjectSignals {

View File

@ -5,7 +5,7 @@ import { QAction } from './QAction';
import { QPoint } from '../QtCore/QPoint';
/**
> The QMenu class provides a menu widget for use in menu bars, context menus, and other popup menus.
* **This class is a JS wrapper around Qt's [QMenu class](https://doc.qt.io/qt-5/qmenu.html)**
@ -33,6 +33,9 @@ export class QMenu extends NodeWidget<QMenuSignals> {
this.native = native;
this.setNodeParent(parent);
}
clear(): void {
this.native.clear();
}
setTitle(title: string): void {
this.native.setTitle(title);
}
@ -53,4 +56,6 @@ export class QMenu extends NodeWidget<QMenuSignals> {
}
}
export type QMenuSignals = QWidgetSignals;
export interface QMenuSignals extends QWidgetSignals {
triggered: (action: NativeElement) => void;
}

View File

@ -220,6 +220,9 @@ export abstract class NodeWidget<Signals extends QWidgetSignals> extends YogaWid
activateWindow(): void {
this.native.activateWindow();
}
isActiveWindow(): boolean {
return this.property('isActiveWindow').toBool();
}
raise(): void {
this.native.raise();
}

View File

@ -40,7 +40,16 @@ export abstract class EventWidget<Signals extends unknown> extends Component {
if (native.initNodeEventEmitter) {
this.emitter = new EventEmitter();
this.emitter.emit = wrapWithActivateUvLoop(this.emitter.emit.bind(this.emitter));
native.initNodeEventEmitter(this.emitter.emit);
const logExceptions = (event: string | symbol, ...args: any[]): boolean => {
try {
return this.emitter.emit(event, ...args);
} catch (e) {
console.log(`An exception was thrown while dispatching an event of type '${event.toString()}':`);
console.log(e);
}
return false;
};
native.initNodeEventEmitter(logExceptions);
} else {
throw new Error('initNodeEventEmitter not implemented on native side');
}