Load image from buffer, QMovie and QRect (#232)

* Adds qpixmap load from data

* Adds basic qrect and qmovie

* Adds more methods to QMovie and QLabel

* Adds QMovie, QRect and qlabel methods

* Adds custom method load from data to load from buffer easily

* Adds loading from buffer for qmovie
This commit is contained in:
Atul R 2019-11-29 00:39:35 +01:00 committed by GitHub
parent 06a787bedf
commit 6e6495f948
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 776 additions and 4 deletions

View File

@ -44,9 +44,11 @@ add_library(${CORE_WIDGETS_ADDON} SHARED
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QIcon/qicon_wrap.cpp"
"${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/QtGui/QMovie/qmovie_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/QtCore/QSize/qsize_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtCore/QRect/qrect_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtCore/QUrl/qurl_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QWidget/qwidget_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QGridLayout/qgridlayout_wrap.cpp"
@ -71,6 +73,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED
"${PROJECT_SOURCE_DIR}/src/cpp/lib/core/FlexLayout/flexlayout_wrap.cpp"
# Custom widgets (include them for automoc since they contain Q_OBJECT)
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtCore/QObject/nobject.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtGui/QMovie/nmovie.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QWidget/nwidget.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QLabel/nlabel.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QCheckBox/ncheckbox.hpp"

View File

@ -0,0 +1,35 @@
#pragma once
#include <napi.h>
#include <stdlib.h>
#include <QRect>
#include "core/Component/component_macro.h"
class QRectWrap : public Napi::ObjectWrap<QRectWrap> {
private:
std::unique_ptr<QRect> instance;
public:
static Napi::FunctionReference constructor;
static Napi::Object init(Napi::Env env, Napi::Object exports);
QRectWrap(const Napi::CallbackInfo& info);
~QRectWrap();
QRect* getInternalInstance();
// Wrapped methods
Napi::Value setHeight(const Napi::CallbackInfo& info);
Napi::Value setWidth(const Napi::CallbackInfo& info);
Napi::Value setLeft(const Napi::CallbackInfo& info);
Napi::Value setTop(const Napi::CallbackInfo& info);
Napi::Value height(const Napi::CallbackInfo& info);
Napi::Value width(const Napi::CallbackInfo& info);
Napi::Value left(const Napi::CallbackInfo& info);
Napi::Value top(const Napi::CallbackInfo& info);
COMPONENT_WRAPPED_METHODS_DECLARATION
};
namespace StaticQRectWrapMethods {
Napi::Value fromQVariant(const Napi::CallbackInfo& info);
} // namespace StaticQRectWrapMethods

View File

@ -0,0 +1,64 @@
#pragma once
#include <QMovie>
#include "QtCore/QRect/qrect_wrap.h"
#include "QtCore/QSize/qsize_wrap.h"
#include "core/Events/eventwidget.h"
#include "core/Events/eventwidget_macro.h"
class NMovie : public QMovie, public EventWidget {
Q_OBJECT
EVENTWIDGET_IMPLEMENTATIONS(QMovie)
public:
using QMovie::QMovie;
void connectWidgetSignalsToEventEmitter() {
// Qt Connects: Implement all signal connects here
QObject::connect(this, &QMovie::error,
[=](QImageReader::ImageReaderError error) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call(
{Napi::String::New(env, "error"),
Napi::Number::New(env, static_cast<int>(error))});
});
QObject::connect(this, &QMovie::finished, [=]() {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call({Napi::String::New(env, "finished")});
});
QObject::connect(this, &QMovie::frameChanged, [=](int frameNumber) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call({Napi::String::New(env, "frameChanged"),
Napi::Number::New(env, frameNumber)});
});
QObject::connect(this, &QMovie::started, [=]() {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call({Napi::String::New(env, "started")});
});
QObject::connect(this, &QMovie::resized, [=](const QSize &size) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
auto instance = QSizeWrap::constructor.New({Napi::External<QSize>::New(
env, new QSize(size.width(), size.height()))});
this->emitOnNode.Call({Napi::String::New(env, "resized"), instance});
});
QObject::connect(this, &QMovie::stateChanged,
[=](QMovie::MovieState state) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call(
{Napi::String::New(env, "stateChanged"),
Napi::Number::New(env, static_cast<int>(state))});
});
QObject::connect(this, &QMovie::updated, [=](const QRect &rect) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
auto instance = QRectWrap::constructor.New(
{Napi::External<QRect>::New(env, new QRect(rect))});
this->emitOnNode.Call({Napi::String::New(env, "updated"), instance});
});
}
};

View File

@ -0,0 +1,38 @@
#pragma once
#include <napi.h>
#include <stdlib.h>
#include <QPointer>
#include "QtCore/QObject/qobject_macro.h"
#include "nmovie.hpp"
class QMovieWrap : public Napi::ObjectWrap<QMovieWrap> {
private:
QPointer<NMovie> instance;
public:
static Napi::Object init(Napi::Env env, Napi::Object exports);
QMovieWrap(const Napi::CallbackInfo& info);
~QMovieWrap();
NMovie* getInternalInstance();
// class constructor
static Napi::FunctionReference constructor;
// wrapped methods
Napi::Value setFileName(const Napi::CallbackInfo& info);
Napi::Value fileName(const Napi::CallbackInfo& info);
Napi::Value setFormat(const Napi::CallbackInfo& info);
Napi::Value format(const Napi::CallbackInfo& info);
Napi::Value setScaledSize(const Napi::CallbackInfo& info);
Napi::Value start(const Napi::CallbackInfo& info);
Napi::Value stop(const Napi::CallbackInfo& info);
Napi::Value setPaused(const Napi::CallbackInfo& info);
Napi::Value jumpToNextFrame(const Napi::CallbackInfo& info);
Napi::Value jumpToFrame(const Napi::CallbackInfo& info);
Napi::Value state(const Napi::CallbackInfo& info);
Napi::Value currentFrameNumber(const Napi::CallbackInfo& info);
Napi::Value currentPixmap(const Napi::CallbackInfo& info);
Napi::Value loadFromData(const Napi::CallbackInfo& info);
QOBJECT_WRAPPED_METHODS_DECLARATION
};

View File

@ -19,6 +19,7 @@ class QPixmapWrap : public Napi::ObjectWrap<QPixmapWrap> {
QPixmap* getInternalInstance();
// Wrapped methods
Napi::Value load(const Napi::CallbackInfo& info);
Napi::Value loadFromData(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);

View File

@ -25,5 +25,6 @@ class QLabelWrap : public Napi::ObjectWrap<QLabelWrap> {
Napi::Value setText(const Napi::CallbackInfo& info);
Napi::Value text(const Napi::CallbackInfo& info);
Napi::Value setPixmap(const Napi::CallbackInfo& info);
Napi::Value setMovie(const Napi::CallbackInfo& info);
Napi::Value setOpenExternalLinks(const Napi::CallbackInfo& info);
};

View File

@ -0,0 +1,117 @@
#include "QtCore/QRect/qrect_wrap.h"
#include "Extras/Utils/nutils.h"
#include "QtCore/QVariant/qvariant_wrap.h"
Napi::FunctionReference QRectWrap::constructor;
Napi::Object QRectWrap::init(Napi::Env env, Napi::Object exports) {
Napi::HandleScope scope(env);
char CLASSNAME[] = "QRect";
Napi::Function func = DefineClass(
env, CLASSNAME,
{InstanceMethod("setHeight", &QRectWrap::setHeight),
InstanceMethod("setWidth", &QRectWrap::setWidth),
InstanceMethod("setLeft", &QRectWrap::setLeft),
InstanceMethod("setTop", &QRectWrap::setTop),
InstanceMethod("height", &QRectWrap::height),
InstanceMethod("width", &QRectWrap::width),
InstanceMethod("left", &QRectWrap::left),
InstanceMethod("top", &QRectWrap::top),
StaticMethod("fromQVariant", &StaticQRectWrapMethods::fromQVariant),
COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE});
constructor = Napi::Persistent(func);
exports.Set(CLASSNAME, func);
return exports;
}
QRectWrap::QRectWrap(const Napi::CallbackInfo& info)
: Napi::ObjectWrap<QRectWrap>(info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if (info.Length() == 4) {
int x = info[0].As<Napi::Number>().Int32Value();
int y = info[1].As<Napi::Number>().Int32Value();
int width = info[2].As<Napi::Number>().Int32Value();
int height = info[3].As<Napi::Number>().Int32Value();
this->instance = std::make_unique<QRect>(x, y, width, height);
} else if (info.Length() == 1) {
this->instance =
std::unique_ptr<QRect>(info[0].As<Napi::External<QRect>>().Data());
} else if (info.Length() == 0) {
this->instance = std::make_unique<QRect>();
} else {
Napi::TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
}
this->rawData = extrautils::configureComponent(this->getInternalInstance());
}
QRectWrap::~QRectWrap() { this->instance.reset(); }
QRect* QRectWrap::getInternalInstance() { return this->instance.get(); }
Napi::Value QRectWrap::setHeight(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
int height = info[0].As<Napi::Number>().Int32Value();
this->instance->setHeight(height);
return env.Null();
}
Napi::Value QRectWrap::setWidth(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
int width = info[0].As<Napi::Number>().Int32Value();
this->instance->setWidth(width);
return env.Null();
}
Napi::Value QRectWrap::setLeft(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
int value = info[0].As<Napi::Number>().Int32Value();
this->instance->setLeft(value);
return env.Null();
}
Napi::Value QRectWrap::setTop(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
int value = info[0].As<Napi::Number>().Int32Value();
this->instance->setTop(value);
return env.Null();
}
Napi::Value QRectWrap::height(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->height());
}
Napi::Value QRectWrap::width(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->width());
}
Napi::Value QRectWrap::left(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->left());
}
Napi::Value QRectWrap::top(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->top());
}
Napi::Value StaticQRectWrapMethods::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();
QRect rect = variant->value<QRect>();
auto instance = QRectWrap::constructor.New(
{Napi::External<QRect>::New(env, new QRect(rect))});
return instance;
}

View File

@ -0,0 +1,174 @@
#include "QtGui/QMovie/qmovie_wrap.h"
#include <QBuffer>
#include <QByteArray>
#include <QDebug>
#include "Extras/Utils/nutils.h"
#include "QtGui/QPixmap/qpixmap_wrap.h"
Napi::FunctionReference QMovieWrap::constructor;
Napi::Object QMovieWrap::init(Napi::Env env, Napi::Object exports) {
Napi::HandleScope scope(env);
char CLASSNAME[] = "QMovie";
Napi::Function func = DefineClass(
env, CLASSNAME,
{InstanceMethod("setFileName", &QMovieWrap::setFileName),
InstanceMethod("fileName", &QMovieWrap::fileName),
InstanceMethod("setFormat", &QMovieWrap::setFormat),
InstanceMethod("format", &QMovieWrap::format),
InstanceMethod("setScaledSize", &QMovieWrap::setScaledSize),
InstanceMethod("start", &QMovieWrap::start),
InstanceMethod("stop", &QMovieWrap::stop),
InstanceMethod("setPaused", &QMovieWrap::setPaused),
InstanceMethod("jumpToNextFrame", &QMovieWrap::jumpToNextFrame),
InstanceMethod("jumpToFrame", &QMovieWrap::jumpToFrame),
InstanceMethod("state", &QMovieWrap::state),
InstanceMethod("currentFrameNumber", &QMovieWrap::currentFrameNumber),
InstanceMethod("currentPixmap", &QMovieWrap::currentPixmap),
InstanceMethod("loadFromData", &QMovieWrap::loadFromData),
QOBJECT_WRAPPED_METHODS_EXPORT_DEFINE(QMovieWrap)});
constructor = Napi::Persistent(func);
exports.Set(CLASSNAME, func);
return exports;
}
NMovie* QMovieWrap::getInternalInstance() { return this->instance; }
QMovieWrap::~QMovieWrap() { extrautils::safeDelete(this->instance); }
QMovieWrap::QMovieWrap(const Napi::CallbackInfo& info)
: Napi::ObjectWrap<QMovieWrap>(info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if (info.Length() == 1) {
if (info[0].IsExternal()) {
this->instance = new NMovie(info[0].As<Napi::External<NMovie>>().Data());
} else {
Napi::Object parentObject = info[0].As<Napi::Object>();
QMovieWrap* parentWidgetWrap =
Napi::ObjectWrap<QMovieWrap>::Unwrap(parentObject);
this->instance = new NMovie(parentWidgetWrap->getInternalInstance());
}
} else if (info.Length() == 0) {
this->instance = new NMovie();
} else {
Napi::TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
}
this->rawData = extrautils::configureQObject(this->getInternalInstance());
}
Napi::Value QMovieWrap::setFileName(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::String fileName = info[0].As<Napi::String>();
this->instance->setFileName(QString::fromStdString(fileName.Utf8Value()));
return env.Null();
}
Napi::Value QMovieWrap::fileName(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
QString fileName = this->instance->fileName();
return Napi::Value::From(env, fileName.toStdString());
}
Napi::Value QMovieWrap::setFormat(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::String formatName = info[0].As<Napi::String>();
std::string format = formatName.Utf8Value();
QByteArray byteArray(format.c_str(), format.length());
this->instance->setFormat(byteArray);
return env.Null();
}
Napi::Value QMovieWrap::format(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
QByteArray format = this->instance->format();
return Napi::Value::From(env, format.toStdString());
}
Napi::Value QMovieWrap::setScaledSize(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::Object sizeObject = info[0].As<Napi::Object>();
QSizeWrap* sizeWrap = Napi::ObjectWrap<QSizeWrap>::Unwrap(sizeObject);
this->instance->setScaledSize(*sizeWrap->getInternalInstance());
return env.Null();
}
Napi::Value QMovieWrap::start(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
this->instance->start();
return env.Null();
}
Napi::Value QMovieWrap::stop(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
this->instance->stop();
return env.Null();
}
Napi::Value QMovieWrap::setPaused(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::Boolean paused = info[0].As<Napi::Boolean>();
this->instance->setPaused(paused.Value());
return env.Null();
}
Napi::Value QMovieWrap::jumpToNextFrame(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
bool jumped = this->instance->jumpToNextFrame();
return Napi::Value::From(env, jumped);
}
Napi::Value QMovieWrap::jumpToFrame(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::Number frameNo = info[0].As<Napi::Number>();
bool jumped = this->instance->jumpToFrame(frameNo.Int32Value());
return Napi::Value::From(env, jumped);
}
Napi::Value QMovieWrap::state(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
QMovie::MovieState state = this->instance->state();
return Napi::Value::From(env, static_cast<int>(state));
}
Napi::Value QMovieWrap::currentFrameNumber(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
int currentFrameNumber = this->instance->currentFrameNumber();
return Napi::Value::From(env, currentFrameNumber);
}
Napi::Value QMovieWrap::currentPixmap(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
QPixmap pixmap = this->instance->currentPixmap();
auto instance = QPixmapWrap::constructor.New(
{Napi::External<QPixmap>::New(env, new QPixmap(pixmap))});
return instance;
}
Napi::Value QMovieWrap::loadFromData(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::Buffer<const char> buffer = info[0].As<Napi::Buffer<const char>>();
QByteArray byteArray = QByteArray(buffer.Data(), buffer.Length());
QBuffer* bufferDevice = new QBuffer();
bufferDevice->setData(byteArray);
this->instance->setDevice(bufferDevice);
return env.Null();
}

View File

@ -11,6 +11,7 @@ Napi::Object QPixmapWrap::init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(
env, CLASSNAME,
{InstanceMethod("load", &QPixmapWrap::load),
InstanceMethod("loadFromData", &QPixmapWrap::loadFromData),
InstanceMethod("save", &QPixmapWrap::save),
InstanceMethod("scaled", &QPixmapWrap::scaled),
InstanceMethod("height", &QPixmapWrap::height),
@ -63,6 +64,29 @@ Napi::Value QPixmapWrap::load(const Napi::CallbackInfo& info) {
return Napi::Boolean::New(env, loadSuccess);
}
Napi::Value QPixmapWrap::loadFromData(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
bool loadSuccess = false;
if (info.Length() > 0 && info.Length() < 3) {
Napi::Buffer<uchar> buffer = info[0].As<Napi::Buffer<uchar>>();
if (info.Length() > 1) {
Napi::String format = info[1].As<Napi::String>();
loadSuccess = this->instance->loadFromData(buffer.Data(), buffer.Length(),
format.Utf8Value().c_str());
} else {
loadSuccess =
this->instance->loadFromData(buffer.Data(), buffer.Length());
}
} else {
Napi::TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
}
return Napi::Boolean::New(env, loadSuccess);
}
Napi::Value QPixmapWrap::save(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);

View File

@ -3,6 +3,7 @@
#include <QWidget>
#include "Extras/Utils/nutils.h"
#include "QtGui/QMovie/qmovie_wrap.h"
#include "QtGui/QPixmap/qpixmap_wrap.h"
#include "QtWidgets/QWidget/qwidget_wrap.h"
Napi::FunctionReference QLabelWrap::constructor;
@ -17,6 +18,7 @@ Napi::Object QLabelWrap::init(Napi::Env env, Napi::Object exports) {
InstanceMethod("setText", &QLabelWrap::setText),
InstanceMethod("text", &QLabelWrap::text),
InstanceMethod("setPixmap", &QLabelWrap::setPixmap),
InstanceMethod("setMovie", &QLabelWrap::setMovie),
InstanceMethod("setOpenExternalLinks",
&QLabelWrap::setOpenExternalLinks),
QWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QLabelWrap)});
@ -97,6 +99,16 @@ Napi::Value QLabelWrap::setPixmap(const Napi::CallbackInfo& info) {
return env.Null();
}
Napi::Value QLabelWrap::setMovie(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::Object movieObject = info[0].As<Napi::Object>();
QMovieWrap* movieWrap = Napi::ObjectWrap<QMovieWrap>::Unwrap(movieObject);
this->instance->setMovie(movieWrap->getInternalInstance());
return env.Null();
}
Napi::Value QLabelWrap::setOpenExternalLinks(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);

View File

@ -1,6 +1,7 @@
#include <napi.h>
#include "QtCore/QObject/qobject_wrap.h"
#include "QtCore/QRect/qrect_wrap.h"
#include "QtCore/QSize/qsize_wrap.h"
#include "QtCore/QUrl/qurl_wrap.h"
#include "QtCore/QVariant/qvariant_wrap.h"
@ -11,6 +12,7 @@
#include "QtGui/QEvent/QMouseEvent/qmouseevent_wrap.h"
#include "QtGui/QIcon/qicon_wrap.h"
#include "QtGui/QKeySequence/qkeysequence_wrap.h"
#include "QtGui/QMovie/qmovie_wrap.h"
#include "QtGui/QPixmap/qpixmap_wrap.h"
#include "QtWidgets/QAction/qaction_wrap.h"
#include "QtWidgets/QCheckBox/qcheckbox_wrap.h"
@ -45,12 +47,14 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) {
QObjectWrap::init(env, exports);
QVariantWrap::init(env, exports);
QSizeWrap::init(env, exports);
QRectWrap::init(env, exports);
QUrlWrap::init(env, exports);
QClipboardWrap::init(env, exports);
QWidgetWrap::init(env, exports);
QPixmapWrap::init(env, exports);
QKeySequenceWrap::init(env, exports);
QIconWrap::init(env, exports);
QMovieWrap::init(env, exports);
QCursorWrap::init(env, exports);
QGridLayoutWrap::init(env, exports);
FlexLayoutWrap::init(env, exports);

View File

@ -5,8 +5,9 @@ export * from './lib/QtEnums';
// Gui:
export { QApplication } from './lib/QtGui/QApplication';
export { QKeySequence } from './lib/QtGui/QKeySequence';
export { QPixmap, ReadWriteImageFormats, ImageFormats } from './lib/QtGui/QPixmap';
export { QPixmap, ImageFormats } from './lib/QtGui/QPixmap';
export { QIcon, QIconMode, QIconState } from './lib/QtGui/QIcon';
export { QMovie, CacheMode, MovieState, QMovieEvents } from './lib/QtGui/QMovie';
export { QCursor } from './lib/QtGui/QCursor';
export { QTextOptionWrapMode } from './lib/QtGui/QTextOption';
export { QClipboard, QClipboardMode } from './lib/QtGui/QClipboard';
@ -43,6 +44,7 @@ export { QShortcut, QShortcutEvents } from './lib/QtWidgets/QShortcut';
export { QObject, NodeObject } from './lib/QtCore/QObject';
export { QVariant } from './lib/QtCore/QVariant';
export { QSize } from './lib/QtCore/QSize';
export { QRect } from './lib/QtCore/QRect';
export { QUrl, ParsingMode } from './lib/QtCore/QUrl';
// Layouts:
export { QGridLayout } from './lib/QtWidgets/QGridLayout';

47
src/lib/QtCore/QRect.ts Normal file
View File

@ -0,0 +1,47 @@
import { NativeElement, Component } from '../core/Component';
import addon from '../utils/addon';
import { checkIfNativeElement } from '../utils/helpers';
import { QVariant } from './QVariant';
export class QRect extends Component {
native: NativeElement;
//eslint-disable-next-line @typescript-eslint/no-inferrable-types
constructor(arg?: NativeElement | number, y: number = 0, width: number = 0, height: number = 0) {
super();
const count = arguments.length;
if (count > 1) {
this.native = new addon.QRect(arg, y, width, height);
} else if (count == 1 && checkIfNativeElement(arg)) {
this.native = arg as NativeElement;
} else {
this.native = new addon.QRect();
}
}
setWidth(width: number): void {
return this.native.setWidth(width);
}
width(): number {
return this.native.width();
}
setHeight(height: number): void {
return this.native.setHeight(height);
}
height(): number {
return this.native.height();
}
left(): number {
return this.native.left();
}
setLeft(height: number): void {
return this.native.setLeft(height);
}
top(): number {
return this.native.top();
}
setTop(height: number): void {
return this.native.setTop(height);
}
static fromQVariant(variant: QVariant): QRect {
return new QRect(addon.QRect.fromQVariant(variant.native));
}
}

View File

@ -0,0 +1,39 @@
import { QRect } from '../QRect';
import { QVariant } from '../QVariant';
describe('QRect', () => {
it('initialize empty', () => {
const rect = new QRect();
expect(rect).toBeTruthy();
});
it('initialize with x, y, width, height', () => {
const rect = new QRect(10, 11, 20, 30);
expect(rect).toBeTruthy();
});
it('width', () => {
const rect = new QRect();
rect.setWidth(300);
expect(rect.width()).toBe(300);
});
it('height', () => {
const rect = new QRect();
rect.setHeight(200);
expect(rect.height()).toBe(200);
});
it('left', () => {
const rect = new QRect();
rect.setHeight(200);
expect(rect.height()).toBe(200);
});
it('top', () => {
const rect = new QRect();
rect.setHeight(200);
expect(rect.height()).toBe(200);
});
it('initialize from QVariant', () => {
const rect = new QRect(10, 10, 300, 200);
const variant = new QVariant(rect);
expect(variant).toBeTruthy();
expect(QRect.fromQVariant(variant).left()).toBe(rect.left());
});
});

96
src/lib/QtGui/QMovie.ts Normal file
View File

@ -0,0 +1,96 @@
import addon from '../utils/addon';
import { NativeElement } from '../core/Component';
import { checkIfNativeElement } from '../utils/helpers';
import { QObject } from '../QtCore/QObject';
import { QSize } from '../QtCore/QSize';
import { BaseWidgetEvents } from '../core/EventWidget';
import { QPixmap } from './QPixmap';
export const QMovieEvents = Object.freeze({
...BaseWidgetEvents,
error: 'error',
finished: 'finished',
frameChanged: 'frameChanged',
resized: 'resized',
started: 'started',
stateChanged: 'stateChanged',
updated: 'updated',
});
type supportedFormats = 'gif' | 'webp';
export class QMovie extends QObject {
native: NativeElement;
constructor(arg?: QObject | NativeElement) {
super();
if (arg) {
if (checkIfNativeElement(arg)) {
this.native = arg as NativeElement;
} else {
this.native = new addon.QMovie(arg);
}
} else {
this.native = new addon.QMovie();
}
}
setFileName(fileName: string): void {
this.native.setFileName(fileName);
this.jumpToFrame(0);
}
loadFromData(buffer: Buffer): void {
this.native.loadFromData(buffer);
}
fileName(): string {
return this.native.fileName();
}
setFormat(formatName: supportedFormats): void {
this.native.setFormat(formatName);
}
format(): string {
return this.native.format();
}
setScaledSize(size: QSize): void {
this.native.setScaledSize(size.native);
}
setSpeed(percentSpeed: number): void {
this.setProperty('speed', percentSpeed);
}
start(): void {
this.native.start();
}
stop(): void {
this.native.stop();
}
setPaused(paused: boolean): void {
this.native.setPaused(paused);
}
jumpToNextFrame(): boolean {
return this.native.jumpToNextFrame();
}
jumpToFrame(frame: number): boolean {
return this.native.jumpToFrame(frame);
}
setCacheMode(cacheMode: CacheMode): void {
this.setProperty('cacheMode', cacheMode);
}
state(): MovieState {
return this.native.state();
}
currentFrameNumber(): number {
return this.native.currentFrameNumber();
}
currentPixmap(): QPixmap {
return new QPixmap(this.native.currentPixmap());
}
}
export enum CacheMode {
CacheNone,
CacheAll,
}
export enum MovieState {
NotRunning,
Paused,
Running,
}

View File

@ -4,8 +4,7 @@ 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';
export type ImageFormats = 'BMP' | 'GIF' | 'JPG' | 'JPEG' | 'PNG' | 'PBM' | 'PGM' | 'PPM' | 'XBM' | 'XPM' | 'SVG';
type arg = string | NativeElement;
export class QPixmap extends Component {
@ -24,7 +23,10 @@ export class QPixmap extends Component {
load(imageUrl: string): boolean {
return this.native.load(imageUrl);
}
save(fileName: string, format?: ReadWriteImageFormats): boolean {
loadFromData(buffer: Buffer, format?: ImageFormats): boolean {
return format ? this.native.loadFromData(buffer, format) : this.native.loadFromData(buffer);
}
save(fileName: string, format?: ImageFormats): boolean {
return format ? this.native.save(fileName, format) : this.native.save(fileName);
}
scaled(width: number, height: number, aspectRatioMode?: AspectRatioMode): QPixmap {

View File

@ -0,0 +1,89 @@
import { QMovie, MovieState } from '../QMovie';
import path from 'path';
import { QPixmap } from '../QPixmap';
import { QSize } from '../../QtCore/QSize';
import fs from 'fs';
const testImagePath = path.resolve(__dirname, 'assets', 'fine.gif');
describe('QMovie', () => {
it('initialize empty', () => {
const movie = new QMovie();
expect(movie).toBeTruthy();
});
it('setFileName', () => {
const movie = new QMovie();
movie.setFileName(testImagePath);
expect(movie.fileName()).toBe(testImagePath);
});
it('setFormat', () => {
const movie = new QMovie();
movie.setFileName(testImagePath);
// movie.setFormat('GIF');
expect(movie.format()).toBe('gif');
});
it('start', () => {
const movie = new QMovie();
movie.setFileName(testImagePath);
movie.start();
expect(movie.state()).toBe(MovieState.Running);
});
it('setPaused', () => {
const movie = new QMovie();
movie.setFileName(testImagePath);
movie.start();
movie.setPaused(true);
expect(movie.state()).toBe(MovieState.Paused);
movie.setPaused(false);
expect(movie.state()).toBe(MovieState.Running);
});
it('stop', () => {
const movie = new QMovie();
movie.setFileName(testImagePath);
movie.start();
movie.stop();
expect(movie.state()).toBe(MovieState.NotRunning);
});
it('jumpToFrame and jumpToNextFrame', () => {
const movie = new QMovie();
movie.setFileName(testImagePath);
movie.start();
movie.stop();
movie.jumpToFrame(2);
expect(movie.currentFrameNumber()).toBe(2);
movie.jumpToNextFrame();
expect(movie.currentFrameNumber()).toBe(3);
});
it('currentPixmap', () => {
const movie = new QMovie();
movie.setFileName(testImagePath);
movie.start();
movie.stop();
movie.jumpToFrame(2);
const pixmap = movie.currentPixmap();
expect(pixmap).toBeInstanceOf(QPixmap);
expect(pixmap.height()).toBe(270);
});
it('setScaledSize', () => {
const movie = new QMovie();
movie.setFileName(testImagePath);
movie.start();
movie.stop();
movie.jumpToFrame(2);
movie.setScaledSize(new QSize(200, 200));
movie.jumpToNextFrame();
const pixmap = movie.currentPixmap();
expect(pixmap.height()).toBe(200);
});
it('custom: loadFromData', () => {
const movie = new QMovie();
const arrayBuffer = fs.readFileSync(testImagePath, null).buffer;
movie.loadFromData(Buffer.from(arrayBuffer));
movie.start();
movie.stop();
movie.jumpToFrame(2);
const pixmap = movie.currentPixmap();
expect(pixmap).toBeInstanceOf(QPixmap);
expect(pixmap.height()).toBe(270);
});
});

View File

@ -47,6 +47,14 @@ describe('QPixmap', () => {
expect(isLoaded).toBe(true);
expect(pixmap.height()).toBe(1083);
});
it('load from data', () => {
const pixmap = new QPixmap();
expect(pixmap.height()).toBe(0);
const arrayBuffer = fs.readFileSync(testImagePath, null).buffer;
const isLoaded = pixmap.loadFromData(Buffer.from(arrayBuffer));
expect(isLoaded).toBe(true);
expect(pixmap.height()).toBe(1083);
});
it('save to a file', async () => {
const outputFilePath = path.resolve(__dirname, 'assets', 'nodegui_save.png');
await new Promise(resolve => fs.unlink(outputFilePath, resolve));

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

View File

@ -3,6 +3,7 @@ import { NodeWidget } from './QWidget';
import { BaseWidgetEvents } from '../core/EventWidget';
import { NativeElement } from '../core/Component';
import { QPixmap } from '../QtGui/QPixmap';
import { QMovie } from '../QtGui/QMovie';
export const QLabelEvents = Object.freeze({
...BaseWidgetEvents,
@ -10,6 +11,7 @@ export const QLabelEvents = Object.freeze({
export class QLabel extends NodeWidget {
native: NativeElement;
private _pixmap?: QPixmap;
private _movie?: QMovie;
constructor(parent?: NodeWidget) {
let native;
if (parent) {
@ -40,6 +42,13 @@ export class QLabel extends NodeWidget {
pixmap(): QPixmap | undefined {
return this._pixmap;
}
setMovie(movie: QMovie): void {
this.native.setMovie(movie.native);
this._movie = movie;
}
movie(): QMovie | undefined {
return this._movie;
}
setOpenExternalLinks(open: boolean): void {
this.native.setOpenExternalLinks(open);
}

View File

@ -1,5 +1,6 @@
import { QLabel } from '../QLabel';
import { QPixmap } from '../../QtGui/QPixmap';
import { QMovie } from '../../QtGui/QMovie';
describe('QLabel', () => {
const label = new QLabel();
@ -28,4 +29,10 @@ describe('QLabel', () => {
label.setPixmap(pixMap);
expect(label.pixmap()).toEqual(pixMap);
});
it('setMovie', () => {
const label = new QLabel();
const movie = new QMovie();
label.setMovie(movie);
expect(label.movie()).toEqual(movie);
});
});