Add qvariant object translation (#189)

* working - translation of any wrapped object

* clang format

* Adds QVariant and Qbject property. Also adds QPixmap fromQVariant

* fixes breaking test cases

* Adds build to prepush hook aswell
This commit is contained in:
Atul R 2019-11-10 20:48:41 +01:00 committed by GitHub
parent 88cd9d430f
commit ece01d3803
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 259 additions and 31 deletions

View File

@ -43,6 +43,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QCursor/qcursor_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QKeySequence/qkeysequence_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtCore/QObject/qobject_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtCore/QVariant/qvariant_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QWidget/qwidget_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QGridLayout/qgridlayout_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QDial/qdial_wrap.cpp"

View File

@ -1,5 +1,5 @@
const { QApplication } = require("../../dist");
const { QApplication } = require('../../dist');
module.exports = async () => {
global.qApp = QApplication.instance();
qApp.setQuitOnLastWindowClosed(false);
global.qApp = QApplication.instance();
qApp.setQuitOnLastWindowClosed(false);
};

View File

@ -1,3 +1,3 @@
module.exports = async () => {
global.qApp.quit();
global.qApp.quit();
};

View File

@ -1,16 +1,16 @@
// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.html
module.exports = {
clearMocks: true,
coverageDirectory: "coverage",
collectCoverageFrom: ["**/*.{js,jsx,ts,tsx}", "!**/node_modules/**"],
forceCoverageMatch: ["**/*.{ts,tsx,js,jsx}", "!**/*.test.{ts,tsx,js,jsx}"],
moduleFileExtensions: ["js", "json", "jsx", "ts", "tsx", "node"],
roots: ["<rootDir>/src/lib"],
testEnvironment: "node",
transform: {
"^.+\\.tsx?$": "ts-jest"
},
globalSetup: "./config/tests/setup.js",
globalTeardown: "./config/tests/teardown.js"
clearMocks: true,
coverageDirectory: 'coverage',
collectCoverageFrom: ['**/*.{js,jsx,ts,tsx}', '!**/node_modules/**'],
forceCoverageMatch: ['**/*.{ts,tsx,js,jsx}', '!**/*.test.{ts,tsx,js,jsx}'],
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
roots: ['<rootDir>/src/lib'],
testEnvironment: 'node',
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
globalSetup: './config/tests/setup.js',
globalTeardown: './config/tests/teardown.js',
};

View File

@ -19,8 +19,8 @@
"dev": "npm run build && qode --inspect dist/demo.js",
"postinstall": "npm run build:addon",
"build": "tsc && npm run build:addon",
"build:addon": "cross-env CMAKE_BUILD_PARALLEL_LEVEL=8 cmake-js build",
"test": "qode ./node_modules/.bin/jest",
"build:addon": "cross-env CMAKE_BUILD_PARALLEL_LEVEL=8 cmake-js compile",
"test": "qode ./node_modules/.bin/jest -i",
"lint:cpp": "clang-format -i --glob=src/cpp/**/*.[h,c]*",
"lint:ts": "tsc --noEmit && eslint './src/**/*.{ts,tsx,js,jsx}' --fix"
},
@ -50,7 +50,7 @@
},
"husky": {
"hooks": {
"pre-push": "npm run lint:ts && npm run lint:cpp && npm run test"
"pre-push": "npm run build && npm run lint:ts && npm run lint:cpp && npm run test"
}
}
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "Extras/Utils/nutils.h"
#include "QtCore/QVariant/qvariant_wrap.h"
#include "core/Events/eventwidget_macro.h"
/*
@ -31,6 +32,17 @@
this->instance->setProperty(name.Utf8Value().c_str(), *variant); \
return env.Null(); \
} \
Napi::Value property(const Napi::CallbackInfo& info) { \
Napi::Env env = info.Env(); \
Napi::HandleScope scope(env); \
Napi::String name = info[0].As<Napi::String>(); \
Napi::Value value = info[1]; \
QVariant* variant = \
new QVariant(this->instance->property(name.Utf8Value().c_str())); \
auto variantWrap = QVariantWrap::constructor.New( \
{Napi::External<QVariant>::New(env, variant)}); \
return variantWrap; \
} \
Napi::Value setObjectName(const Napi::CallbackInfo& info) { \
Napi::Env env = info.Env(); \
Napi::HandleScope scope(env); \
@ -55,6 +67,7 @@
\
InstanceMethod("inherits", &ComponentWrapName::inherits), \
InstanceMethod("setProperty", &ComponentWrapName::setProperty), \
InstanceMethod("property", &ComponentWrapName::property), \
InstanceMethod("setObjectName", &ComponentWrapName::setObjectName), \
InstanceMethod("objectName", &ComponentWrapName::objectName),

View File

@ -0,0 +1,25 @@
#pragma once
#include <napi.h>
#include <QSharedPointer>
#include "core/Component/component_macro.h"
class QVariantWrap : public Napi::ObjectWrap<QVariantWrap> {
private:
QSharedPointer<QVariant> instance;
public:
static Napi::Object init(Napi::Env env, Napi::Object exports);
QVariantWrap(const Napi::CallbackInfo& info);
QVariant* getInternalInstance();
// class constructor
static Napi::FunctionReference constructor;
Napi::Value toString(const Napi::CallbackInfo& info);
Napi::Value toInt(const Napi::CallbackInfo& info);
Napi::Value toDouble(const Napi::CallbackInfo& info);
Napi::Value toBool(const Napi::CallbackInfo& info);
// wrapped methods
COMPONENT_WRAPPED_METHODS_DECLARATION
};

View File

@ -21,6 +21,12 @@ class QPixmapWrap : public Napi::ObjectWrap<QPixmapWrap> {
Napi::Value load(const Napi::CallbackInfo& info);
Napi::Value save(const Napi::CallbackInfo& info);
Napi::Value scaled(const Napi::CallbackInfo& info);
Napi::Value height(const Napi::CallbackInfo& info);
Napi::Value width(const Napi::CallbackInfo& info);
COMPONENT_WRAPPED_METHODS_DECLARATION
};
namespace StaticQPixmapWrapMethods {
Napi::Value fromQVariant(const Napi::CallbackInfo& info);
} // namespace StaticQPixmapWrapMethods

View File

@ -1,6 +1,5 @@
#include "Extras/Utils/nutils.h"
#include <QDebug>
#include <QMetaType>
#include <QWidget>
#include <string>
@ -91,8 +90,8 @@ QVariant* extrautils::convertToQVariant(Napi::Env& env, Napi::Value& value) {
// TODO: fix this
return new QVariant();
} else if (value.IsExternal()) {
// TODO: fix this
return new QVariant();
QVariant* variant = value.As<Napi::External<QVariant>>().Data();
return variant;
} else {
return new QVariant();
}

View File

@ -0,0 +1,61 @@
#include "QtCore/QVariant/qvariant_wrap.h"
#include "Extras/Utils/nutils.h"
Napi::FunctionReference QVariantWrap::constructor;
Napi::Object QVariantWrap::init(Napi::Env env, Napi::Object exports) {
Napi::HandleScope scope(env);
char CLASSNAME[] = "QVariant";
Napi::Function func =
DefineClass(env, CLASSNAME,
{InstanceMethod("toString", &QVariantWrap::toString),
InstanceMethod("toInt", &QVariantWrap::toInt),
InstanceMethod("toDouble", &QVariantWrap::toDouble),
InstanceMethod("toBool", &QVariantWrap::toBool),
COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE});
constructor = Napi::Persistent(func);
exports.Set(CLASSNAME, func);
return exports;
}
QVariant* QVariantWrap::getInternalInstance() { return this->instance.data(); }
QVariantWrap::QVariantWrap(const Napi::CallbackInfo& info)
: Napi::ObjectWrap<QVariantWrap>(info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if (info.Length() == 1) {
Napi::Value value = info[0].As<Napi::Value>();
this->instance =
QSharedPointer<QVariant>(extrautils::convertToQVariant(env, value));
} else {
this->instance = QSharedPointer<QVariant>(new QVariant());
}
this->rawData = this->getInternalInstance();
}
Napi::Value QVariantWrap::toString(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
QString value = this->instance->value<QString>();
return Napi::Value::From(env, value.toStdString());
}
Napi::Value QVariantWrap::toInt(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
int value = this->instance->value<int>();
return Napi::Value::From(env, value);
}
Napi::Value QVariantWrap::toDouble(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
double value = this->instance->value<double>();
return Napi::Value::From(env, value);
}
Napi::Value QVariantWrap::toBool(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
bool value = this->instance->value<bool>();
return Napi::Value::From(env, value);
}

View File

@ -1,19 +1,22 @@
#include "QtGui/QPixmap/qpixmap_wrap.h"
#include "Extras/Utils/nutils.h"
#include "deps/spdlog/spdlog.h"
#include "QtCore/QVariant/qvariant_wrap.h"
Napi::FunctionReference QPixmapWrap::constructor;
Napi::Object QPixmapWrap::init(Napi::Env env, Napi::Object exports) {
Napi::HandleScope scope(env);
char CLASSNAME[] = "QPixmap";
Napi::Function func =
DefineClass(env, CLASSNAME,
{InstanceMethod("load", &QPixmapWrap::load),
InstanceMethod("save", &QPixmapWrap::save),
InstanceMethod("scaled", &QPixmapWrap::scaled),
COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE});
Napi::Function func = DefineClass(
env, CLASSNAME,
{InstanceMethod("load", &QPixmapWrap::load),
InstanceMethod("save", &QPixmapWrap::save),
InstanceMethod("scaled", &QPixmapWrap::scaled),
InstanceMethod("height", &QPixmapWrap::height),
InstanceMethod("width", &QPixmapWrap::width),
StaticMethod("fromQVariant", &StaticQPixmapWrapMethods::fromQVariant),
COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE});
constructor = Napi::Persistent(func);
exports.Set(CLASSNAME, func);
return exports;
@ -98,3 +101,28 @@ Napi::Value QPixmapWrap::scaled(const Napi::CallbackInfo& info) {
{Napi::External<QPixmap>::New(env, updatedPixMap)});
return instance;
}
Napi::Value QPixmapWrap::height(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->height());
}
Napi::Value QPixmapWrap::width(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->width());
}
Napi::Value StaticQPixmapWrapMethods::fromQVariant(
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();
QPixmap pixmap = variant->value<QPixmap>();
auto instance = QPixmapWrap::constructor.New(
{Napi::External<QPixmap>::New(env, new QPixmap(pixmap))});
return instance;
}

View File

@ -1,6 +1,7 @@
#include <napi.h>
#include "QtCore/QObject/qobject_wrap.h"
#include "QtCore/QVariant/qvariant_wrap.h"
#include "QtGui/QApplication/qapplication_wrap.h"
#include "QtGui/QClipboard/qclipboard_wrap.h"
#include "QtGui/QCursor/qcursor_wrap.h"
@ -38,6 +39,7 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) {
InitPrivateHelpers(env);
QApplicationWrap::init(env, exports);
QObjectWrap::init(env, exports);
QVariantWrap::init(env, exports);
QClipboardWrap::init(env, exports);
QWidgetWrap::init(env, exports);
QPixmapWrap::init(env, exports);

View File

@ -39,6 +39,7 @@ export { QAction, QActionEvents } from './lib/QtWidgets/QAction';
export { QShortcut, QShortcutEvents } from './lib/QtWidgets/QShortcut';
// Core
export { QObject, NodeObject } from './lib/QtCore/QObject';
export { QVariant } from './lib/QtCore/QVariant';
// Layouts:
export { QGridLayout } from './lib/QtWidgets/QGridLayout';
export { FlexLayout } from './lib/core/FlexLayout';

View File

@ -2,6 +2,7 @@ import { EventWidget } from '../core/EventWidget';
import { NativeElement } from '../core/Component';
import { checkIfNativeElement } from '../utils/helpers';
import addon from '../utils/addon';
import { QVariant } from './QVariant';
export abstract class NodeObject extends EventWidget {
inherits(className: string): boolean {
@ -11,6 +12,10 @@ export abstract class NodeObject extends EventWidget {
const finalValue = value.native || value;
return this.native.setProperty(name, finalValue);
}
property(name: string): QVariant {
const nativeVariant = this.native.property(name);
return new QVariant(nativeVariant);
}
setObjectName(objectName: string): void {
this.native.setObjectName(objectName);
}

View File

@ -0,0 +1,32 @@
import { NativeElement, Component } from '../core/Component';
import addon from '../utils/addon';
import { checkIfNativeElement } from '../utils/helpers';
type QVariantType = NativeElement | Component | string | number | boolean;
export class QVariant extends Component {
native: NativeElement;
constructor(arg?: QVariantType) {
super();
if (checkIfNativeElement(arg)) {
this.native = arg as NativeElement;
} else if (arg) {
const component = (arg as Component).native || arg;
this.native = new addon.QVariant(component);
} else {
this.native = new addon.QVariant();
}
}
toString(): string {
return this.native.toString();
}
toInt(): string {
return this.native.toInt();
}
toDouble(): string {
return this.native.toDouble();
}
toBool(): string {
return this.native.toBool();
}
}

View File

@ -9,4 +9,9 @@ describe('QObject', () => {
component.setObjectName('hello');
expect(component.objectName()).toEqual('hello');
});
it('setProperty', () => {
component.setProperty('objectName', 'testObjName');
const variant = component.property('objectName');
expect(variant.toString()).toEqual('testObjName');
});
});

View File

@ -0,0 +1,40 @@
import { QVariant } from '../../../index';
import { QPixmap } from '../../QtGui/QPixmap';
import path from 'path';
describe('QVariant', () => {
it('inherits from QVariant', () => {
const variant = new QVariant();
expect(variant.constructor.name).toEqual('QVariant');
});
it('initialize empty', () => {
const variant = new QVariant();
expect(variant.constructor.name).toEqual('QVariant');
});
it('initialize with string', () => {
const variant = new QVariant('hello');
expect(variant.constructor.name).toBe('QVariant');
expect(variant.toString()).toEqual('hello');
});
it('initialize with int', () => {
const variant = new QVariant(123);
expect(variant.constructor.name).toBe('QVariant');
expect(variant.toInt()).toEqual(123);
});
it('initialize with double', () => {
const variant = new QVariant(12.33);
expect(variant.constructor.name).toBe('QVariant');
expect(variant.toDouble()).toEqual(12.33);
});
it('initialize with boolean', () => {
const variant = new QVariant(true);
expect(variant.constructor.name).toBe('QVariant');
expect(variant.toBool()).toEqual(true);
});
it('initialize with complex objects', () => {
const pixmap = new QPixmap(path.resolve(__dirname, 'nodegui.png'));
const variant = new QVariant(pixmap);
expect(variant.constructor.name).toBe('QVariant');
expect(QPixmap.fromQVariant(variant).height()).toBe(pixmap.height());
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -2,6 +2,7 @@ import addon from '../utils/addon';
import { Component, NativeElement } from '../core/Component';
import { AspectRatioMode } from '../QtEnums';
import { checkIfNativeElement } from '../utils/helpers';
import { QVariant } from '../QtCore/QVariant';
export type ImageFormats = 'BMP' | 'GIF' | 'JPG' | 'JPEG' | 'PNG' | 'PBM' | 'PGM' | 'PPM' | 'XBM' | 'XPM';
export type ReadWriteImageFormats = 'BMP' | 'JPG' | 'JPEG' | 'PNG' | 'PBM' | 'XBM' | 'XPM';
@ -36,4 +37,13 @@ export class QPixmap extends Component {
}
return new QPixmap(nativePixmap);
};
height(): number {
return this.native.height();
}
width(): number {
return this.native.width();
}
static fromQVariant(variant: QVariant): QPixmap {
return addon.QPixmap.fromQVariant(variant.native);
}
}

View File

@ -7,8 +7,8 @@ export enum EchoMode {
Normal,
NoEcho,
Password,
PasswordEchoOnEdit,
};
PasswordEchoOnEdit,
}
export const QLineEditEvents = Object.freeze({
...BaseWidgetEvents,
cursorPositionChanged: 'cursorPositionChanged',