diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f8ffbb82..ec749f7fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QPixmap/qpixmap_wrap.cpp" "${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/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" @@ -57,6 +58,8 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QPlainTextEdit/qplaintextedit_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QScrollArea/qscrollarea_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QSystemTrayIcon/qsystemtrayicon_wrap.cpp" + "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QAction/qaction_wrap.cpp" + "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QShortcut/qshortcut_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QMenuBar/qmenubar_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QMenu/qmenu_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/core/FlexLayout/flexlayout_wrap.cpp" @@ -75,6 +78,8 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QScrollArea/nscrollarea.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QTabWidget/ntabwidget.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QSystemTrayIcon/nsystemtrayicon.hpp" + "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QAction/naction.hpp" + "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QShortcut/nshortcut.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QMenuBar/nmenubar.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QMenu/nmenu.hpp" ) diff --git a/package.json b/package.json index f2e538002..c846838c1 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "dev": "npm run build && qode 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 compile", + "build:addon": "cross-env CMAKE_BUILD_PARALLEL_LEVEL=8 cmake-js build", "test": "qode ./node_modules/.bin/jest" }, "dependencies": { diff --git a/src/cpp/include/nodegui/QtGui/QKeySequence/qkeysequence_wrap.h b/src/cpp/include/nodegui/QtGui/QKeySequence/qkeysequence_wrap.h new file mode 100644 index 000000000..a91040cc1 --- /dev/null +++ b/src/cpp/include/nodegui/QtGui/QKeySequence/qkeysequence_wrap.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include +#include "core/Component/component_macro.h" + +class QKeySequenceWrap : public Napi::ObjectWrap +{ +private: + std::unique_ptr instance; + +public: + static Napi::FunctionReference constructor; + static Napi::Object init(Napi::Env env, Napi::Object exports); + QKeySequenceWrap(const Napi::CallbackInfo &info); + ~QKeySequenceWrap(); + QKeySequence *getInternalInstance(); + // Wrapped methods + Napi::Value count(const Napi::CallbackInfo& info); +}; diff --git a/src/cpp/include/nodegui/QtWidgets/QAction/naction.hpp b/src/cpp/include/nodegui/QtWidgets/QAction/naction.hpp new file mode 100644 index 000000000..37a87f09f --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QAction/naction.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include "core/NodeWidget/nodewidget.h" +#include "napi.h" + +class NAction: public QAction, public EventWidget +{ + Q_OBJECT + EVENTWIDGET_IMPLEMENTATIONS(QAction) +public: + using QAction::QAction; //inherit all constructors of QAction + void connectWidgetSignalsToEventEmitter() { + // Qt Connects: Implement all signal connects here + QObject::connect(this, &QAction::triggered, [=](bool checked) { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call({ Napi::String::New(env, "triggered"), Napi::Value::From(env, checked) }); + }); + QObject::connect(this, &QAction::changed, [=]() { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call({ Napi::String::New(env, "changed") }); + }); + QObject::connect(this, &QAction::hovered, [=]() { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call({ Napi::String::New(env, "hovered") }); + }); + QObject::connect(this, &QAction::toggled, [=](bool checked) { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call({ Napi::String::New(env, "toggled"), Napi::Value::From(env, checked) }); + }); + } +}; + + diff --git a/src/cpp/include/nodegui/QtWidgets/QAction/qaction_wrap.h b/src/cpp/include/nodegui/QtWidgets/QAction/qaction_wrap.h new file mode 100644 index 000000000..a016f1627 --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QAction/qaction_wrap.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include "naction.hpp" +#include "QtWidgets/QWidget/qwidget_macro.h" + +class QActionWrap : public Napi::ObjectWrap{ + private: + NAction* instance; + public: + static Napi::Object init(Napi::Env env, Napi::Object exports); + QActionWrap(const Napi::CallbackInfo& info); + ~QActionWrap(); + NAction* getInternalInstance(); + //class constructor + static Napi::FunctionReference constructor; + //wrapped methods + Napi::Value setText(const Napi::CallbackInfo& info); + Napi::Value setEnabled(const Napi::CallbackInfo& info); + Napi::Value setIcon(const Napi::CallbackInfo& info); + Napi::Value setMenu(const Napi::CallbackInfo& info); + Napi::Value setShortcut(const Napi::CallbackInfo& info); + Napi::Value setShortcutContext(const Napi::CallbackInfo& info); + + EVENTWIDGET_WRAPPED_METHODS_DECLARATION +}; + diff --git a/src/cpp/include/nodegui/QtWidgets/QMenu/qmenu_wrap.h b/src/cpp/include/nodegui/QtWidgets/QMenu/qmenu_wrap.h index 25a7702b1..9263b8fd0 100644 --- a/src/cpp/include/nodegui/QtWidgets/QMenu/qmenu_wrap.h +++ b/src/cpp/include/nodegui/QtWidgets/QMenu/qmenu_wrap.h @@ -15,6 +15,7 @@ class QMenuWrap : public Napi::ObjectWrap{ static Napi::FunctionReference constructor; //wrapped methods Napi::Value setTitle(const Napi::CallbackInfo& info); + Napi::Value addAction(const Napi::CallbackInfo& info); QWIDGET_WRAPPED_METHODS_DECLARATION }; diff --git a/src/cpp/include/nodegui/QtWidgets/QShortcut/nshortcut.hpp b/src/cpp/include/nodegui/QtWidgets/QShortcut/nshortcut.hpp new file mode 100644 index 000000000..36ad581d9 --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QShortcut/nshortcut.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include "core/NodeWidget/nodewidget.h" +#include "napi.h" + +class NShortcut: public QShortcut, public EventWidget +{ + Q_OBJECT + EVENTWIDGET_IMPLEMENTATIONS(QShortcut) +public: + using QShortcut::QShortcut; //inherit all constructors of QShortcut + void connectWidgetSignalsToEventEmitter() { + // Qt Connects: Implement all signal connects here + QObject::connect(this, &QShortcut::activated, [=]() { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call({ Napi::String::New(env, "activated") }); + }); + QObject::connect(this, &QShortcut::activatedAmbiguously, [=]() { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call({ Napi::String::New(env, "activatedAmbiguously") }); + }); + } +}; + + diff --git a/src/cpp/include/nodegui/QtWidgets/QShortcut/qshortcut_wrap.h b/src/cpp/include/nodegui/QtWidgets/QShortcut/qshortcut_wrap.h new file mode 100644 index 000000000..de4ec7c63 --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QShortcut/qshortcut_wrap.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include "nshortcut.hpp" +#include "QtWidgets/QWidget/qwidget_macro.h" + +class QShortcutWrap : public Napi::ObjectWrap{ + private: + NShortcut* instance; + public: + static Napi::Object init(Napi::Env env, Napi::Object exports); + QShortcutWrap(const Napi::CallbackInfo& info); + ~QShortcutWrap(); + NShortcut* getInternalInstance(); + //class constructor + static Napi::FunctionReference constructor; + //wrapped methods + Napi::Value setEnabled(const Napi::CallbackInfo& info); + Napi::Value setAutoRepeat(const Napi::CallbackInfo& info); + Napi::Value setKey(const Napi::CallbackInfo& info); + Napi::Value setContext(const Napi::CallbackInfo& info); + + EVENTWIDGET_WRAPPED_METHODS_DECLARATION +}; + diff --git a/src/cpp/include/nodegui/QtWidgets/QSystemTrayIcon/qsystemtrayicon_wrap.h b/src/cpp/include/nodegui/QtWidgets/QSystemTrayIcon/qsystemtrayicon_wrap.h index fb115d45e..fd0c81ebf 100644 --- a/src/cpp/include/nodegui/QtWidgets/QSystemTrayIcon/qsystemtrayicon_wrap.h +++ b/src/cpp/include/nodegui/QtWidgets/QSystemTrayIcon/qsystemtrayicon_wrap.h @@ -19,6 +19,8 @@ class QSystemTrayIconWrap : public Napi::ObjectWrap{ Napi::Value hide(const Napi::CallbackInfo& info); Napi::Value setIcon(const Napi::CallbackInfo& info); Napi::Value isVisible(const Napi::CallbackInfo& info); + Napi::Value setToolTip(const Napi::CallbackInfo& info); + Napi::Value setContextMenu(const Napi::CallbackInfo& info); EVENTWIDGET_WRAPPED_METHODS_DECLARATION }; diff --git a/src/cpp/lib/QtGui/QApplication/qapplication_wrap.cpp b/src/cpp/lib/QtGui/QApplication/qapplication_wrap.cpp index fd9da8413..6c1ebe182 100644 --- a/src/cpp/lib/QtGui/QApplication/qapplication_wrap.cpp +++ b/src/cpp/lib/QtGui/QApplication/qapplication_wrap.cpp @@ -15,6 +15,7 @@ Napi::Object QApplicationWrap::init(Napi::Env env, Napi::Object exports) InstanceMethod("processEvents", &QApplicationWrap::processEvents), InstanceMethod("exec", &QApplicationWrap::exec), InstanceMethod("quit", &QApplicationWrap::quit), + InstanceMethod("exit", &QApplicationWrap::exit), InstanceMethod("setQuitOnLastWindowClosed", &QApplicationWrap::setQuitOnLastWindowClosed), InstanceMethod("quitOnLastWindowClosed", &QApplicationWrap::quitOnLastWindowClosed), StaticMethod("instance", &StaticQApplicationWrapMethods::instance), diff --git a/src/cpp/lib/QtGui/QKeySequence/qkeysequence_wrap.cpp b/src/cpp/lib/QtGui/QKeySequence/qkeysequence_wrap.cpp new file mode 100644 index 000000000..c5dfce556 --- /dev/null +++ b/src/cpp/lib/QtGui/QKeySequence/qkeysequence_wrap.cpp @@ -0,0 +1,58 @@ +#include "QtGui/QKeySequence/qkeysequence_wrap.h" +#include "QtGui/QPixmap/qpixmap_wrap.h" +#include "Extras/Utils/nutils.h" +#include "deps/spdlog/spdlog.h" + +Napi::FunctionReference QKeySequenceWrap::constructor; + +Napi::Object QKeySequenceWrap::init(Napi::Env env, Napi::Object exports) +{ + Napi::HandleScope scope(env); + char CLASSNAME[] = "QKeySequence"; + Napi::Function func = DefineClass(env, CLASSNAME, { + InstanceMethod("count", &QKeySequenceWrap::count), + COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE + }); + constructor = Napi::Persistent(func); + exports.Set(CLASSNAME, func); + return exports; +} + +QKeySequenceWrap::QKeySequenceWrap(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) +{ + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + if (info.Length() == 1) + { + Napi::String sequenceString = info[0].As(); + QString keySequence = QString::fromStdString(sequenceString.Utf8Value()); + this->instance = std::make_unique(keySequence); + } + else if (info.Length() == 0) + { + this->instance = std::make_unique(); + } + else + { + Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException(); + } +} + +QKeySequenceWrap::~QKeySequenceWrap() +{ + this->instance.reset(); +} + +QKeySequence *QKeySequenceWrap::getInternalInstance() +{ + return this->instance.get(); +} + +Napi::Value QKeySequenceWrap::count(const Napi::CallbackInfo& info) +{ + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + int count = this->instance->count(); + return Napi::Value::From(env, count); +} diff --git a/src/cpp/lib/QtWidgets/QAction/qaction_wrap.cpp b/src/cpp/lib/QtWidgets/QAction/qaction_wrap.cpp new file mode 100644 index 000000000..458ac2b04 --- /dev/null +++ b/src/cpp/lib/QtWidgets/QAction/qaction_wrap.cpp @@ -0,0 +1,109 @@ +#include "QtWidgets/QAction/qaction_wrap.h" +#include "QtWidgets/QWidget/qwidget_wrap.h" +#include "QtGui/QKeySequence/qkeysequence_wrap.h" +#include "QtWidgets/QMenu/qmenu_wrap.h" +#include "Extras/Utils/nutils.h" +#include +#include + + +Napi::FunctionReference QActionWrap::constructor; + +Napi::Object QActionWrap::init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + char CLASSNAME[] = "QAction"; + Napi::Function func = DefineClass(env, CLASSNAME, { + InstanceMethod("setText", &QActionWrap::setText), + InstanceMethod("setEnabled", &QActionWrap::setEnabled), + InstanceMethod("setIcon", &QActionWrap::setIcon), + InstanceMethod("setMenu", &QActionWrap::setMenu), + InstanceMethod("setShortcut", &QActionWrap::setShortcut), + InstanceMethod("setShortcutContext", &QActionWrap::setShortcutContext), + COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE + EVENTWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QActionWrap) + }); + constructor = Napi::Persistent(func); + exports.Set(CLASSNAME, func); + return exports; +} + +NAction* QActionWrap::getInternalInstance() { + return this->instance; +} + +QActionWrap::QActionWrap(const Napi::CallbackInfo& info): Napi::ObjectWrap(info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + if(info.Length() == 1) { + Napi::Object parentObject = info[0].As(); + QWidgetWrap* parentWidgetWrap = Napi::ObjectWrap::Unwrap(parentObject); + this->instance = new NAction(parentWidgetWrap->getInternalInstance()); //this sets the parent to current widget + }else if (info.Length() == 0){ + this->instance = new NAction(); + }else { + Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException(); + } +} + +QActionWrap::~QActionWrap() { + // delete this->instance; This will be destroyed by the qmenu (since it takes the ownership) +} + +Napi::Value QActionWrap::setText(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::String text = info[0].As(); + this->instance->setText(QString::fromStdString(text.Utf8Value())); + return env.Null(); +} + +Napi::Value QActionWrap::setEnabled(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Boolean enabled = info[0].As(); + this->instance->setEnabled(enabled.Value()); + return env.Null(); +} + +Napi::Value QActionWrap::setIcon(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object iconObject = info[0].As(); + QIconWrap *iconWrap = Napi::ObjectWrap::Unwrap(iconObject); + this->instance->setIcon(*iconWrap->getInternalInstance()); + return env.Null(); +} + +Napi::Value QActionWrap::setMenu(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object menuObject = info[0].As(); + QMenuWrap *menuWrap = Napi::ObjectWrap::Unwrap(menuObject); + this->instance->setMenu(menuWrap->getInternalInstance()); + return env.Null(); +} + +Napi::Value QActionWrap::setShortcut(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object shortcutSequence = info[0].As(); + QKeySequenceWrap *keysequence = Napi::ObjectWrap::Unwrap(shortcutSequence); + this->instance->setShortcut(*keysequence->getInternalInstance()); + return env.Null(); +} + + +Napi::Value QActionWrap::setShortcutContext(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Number shortcutContextEnum = info[0].As(); + int shortCutContext = shortcutContextEnum.Int32Value(); + this->instance->setShortcutContext(static_cast(shortCutContext)); + qDebug()<<"shortCutContext: "< #include +#include "QtWidgets/QAction/qaction_wrap.h" #include Napi::FunctionReference QMenuWrap::constructor; @@ -10,6 +11,7 @@ Napi::Object QMenuWrap::init(Napi::Env env, Napi::Object exports) { char CLASSNAME[] = "QMenu"; Napi::Function func = DefineClass(env, CLASSNAME, { InstanceMethod("setTitle", &QMenuWrap::setTitle), + InstanceMethod("addAction", &QMenuWrap::addAction), QWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QMenuWrap) }); constructor = Napi::Persistent(func); @@ -51,3 +53,14 @@ Napi::Value QMenuWrap::setTitle(const Napi::CallbackInfo& info) { return env.Null(); } + +Napi::Value QMenuWrap::addAction(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object actionObject = info[0].As(); + QActionWrap *actionWrap = Napi::ObjectWrap::Unwrap(actionObject); + this->instance->addAction(actionWrap->getInternalInstance()); + //TODO: see if we need to return from here an pointer to qaction or not. + return env.Null(); +} diff --git a/src/cpp/lib/QtWidgets/QShortcut/qshortcut_wrap.cpp b/src/cpp/lib/QtWidgets/QShortcut/qshortcut_wrap.cpp new file mode 100644 index 000000000..e235f783e --- /dev/null +++ b/src/cpp/lib/QtWidgets/QShortcut/qshortcut_wrap.cpp @@ -0,0 +1,84 @@ +#include "QtWidgets/QShortcut/qshortcut_wrap.h" +#include "QtWidgets/QWidget/qwidget_wrap.h" +#include "QtGui/QKeySequence/qkeysequence_wrap.h" +#include "QtWidgets/QMenu/qmenu_wrap.h" +#include "Extras/Utils/nutils.h" +#include +#include + + +Napi::FunctionReference QShortcutWrap::constructor; + +Napi::Object QShortcutWrap::init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + char CLASSNAME[] = "QShortcut"; + Napi::Function func = DefineClass(env, CLASSNAME, { + InstanceMethod("setEnabled", &QShortcutWrap::setEnabled), + InstanceMethod("setAutoRepeat", &QShortcutWrap::setAutoRepeat), + InstanceMethod("setKey", &QShortcutWrap::setKey), + InstanceMethod("setContext", &QShortcutWrap::setContext), + COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE + EVENTWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QShortcutWrap) + }); + constructor = Napi::Persistent(func); + exports.Set(CLASSNAME, func); + return exports; +} + +NShortcut* QShortcutWrap::getInternalInstance() { + return this->instance; +} + +QShortcutWrap::QShortcutWrap(const Napi::CallbackInfo& info): Napi::ObjectWrap(info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + if(info.Length() == 1) { + Napi::Object parentObject = info[0].As(); + QWidgetWrap* parentWidgetWrap = Napi::ObjectWrap::Unwrap(parentObject); + this->instance = new NShortcut(parentWidgetWrap->getInternalInstance()); //this sets the parent to current widget + } else { + Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException(); + } +} + +QShortcutWrap::~QShortcutWrap() { + // delete this->instance; This will be destroyed by the qmenu (since it takes the ownership) +} + +Napi::Value QShortcutWrap::setEnabled(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Boolean enabled = info[0].As(); + this->instance->setEnabled(enabled.Value()); + return env.Null(); +} + +Napi::Value QShortcutWrap::setAutoRepeat(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Boolean enabled = info[0].As(); + this->instance->setAutoRepeat(enabled.Value()); + return env.Null(); +} + +Napi::Value QShortcutWrap::setKey(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object shortcutSequence = info[0].As(); + QKeySequenceWrap *keysequence = Napi::ObjectWrap::Unwrap(shortcutSequence); + this->instance->setKey(*keysequence->getInternalInstance()); + return env.Null(); +} + +Napi::Value QShortcutWrap::setContext(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Number shortcutContextEnum = info[0].As(); + int shortCutContext = shortcutContextEnum.Int32Value(); + this->instance->setContext(static_cast(shortCutContext)); + qDebug()<<"shortCutContext: "< #include @@ -15,6 +16,8 @@ Napi::Object QSystemTrayIconWrap::init(Napi::Env env, Napi::Object exports) { InstanceMethod("hide", &QSystemTrayIconWrap::hide), InstanceMethod("setIcon", &QSystemTrayIconWrap::setIcon), InstanceMethod("isVisible", &QSystemTrayIconWrap::isVisible), + InstanceMethod("setToolTip", &QSystemTrayIconWrap::setToolTip), + InstanceMethod("setContextMenu", &QSystemTrayIconWrap::setContextMenu), COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE EVENTWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QSystemTrayIconWrap) @@ -81,3 +84,21 @@ Napi::Value QSystemTrayIconWrap::isVisible(const Napi::CallbackInfo& info) { return Napi::Boolean::New(env, visibility); } +Napi::Value QSystemTrayIconWrap::setToolTip(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::String toolTip = info[0].As(); + this->instance->setToolTip(QString::fromStdString(toolTip.Utf8Value())); + return env.Null(); +} + +Napi::Value QSystemTrayIconWrap::setContextMenu(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object menuObject = info[0].As(); + QMenuWrap *menuWrap = Napi::ObjectWrap::Unwrap(menuObject); + this->instance->setContextMenu(menuWrap->getInternalInstance()); + return env.Null(); +} \ No newline at end of file diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index 90b0d5a4c..714a41ddb 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -3,6 +3,7 @@ #include "QtWidgets/QWidget/qwidget_wrap.h" #include "QtGui/QPixmap/qpixmap_wrap.h" #include "QtGui/QIcon/qicon_wrap.h" +#include "QtGui/QKeySequence/qkeysequence_wrap.h" #include "QtGui/QCursor/qcursor_wrap.h" #include "QtWidgets/QGridLayout/qgridlayout_wrap.h" #include "QtWidgets/QLayout/qlayout_wrap.h" @@ -21,6 +22,8 @@ #include "QtGui/QEvent/QKeyEvent/qkeyevent_wrap.h" #include "QtWidgets/QScrollArea/qscrollarea_wrap.h" #include "QtWidgets/QSystemTrayIcon/qsystemtrayicon_wrap.h" +#include "QtWidgets/QAction/qaction_wrap.h" +#include "QtWidgets/QShortcut/qshortcut_wrap.h" #include "QtWidgets/QMenu/qmenu_wrap.h" #include "QtWidgets/QMenuBar/qmenubar_wrap.h" #include @@ -35,6 +38,7 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) { QClipboardWrap::init(env, exports); QWidgetWrap::init(env, exports); QPixmapWrap::init(env, exports); + QKeySequenceWrap::init(env, exports); QIconWrap::init(env, exports); QCursorWrap::init(env, exports); QGridLayoutWrap::init(env, exports); @@ -53,6 +57,8 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) { QLabelWrap::init(env, exports); QScrollAreaWrap::init(env, exports); QSystemTrayIconWrap::init(env, exports); + QActionWrap::init(env, exports); + QShortcutWrap::init(env, exports); QMenuWrap::init(env, exports); QMenuBarWrap::init(env, exports); return exports; diff --git a/src/demo.ts b/src/demo.ts index 5ff432a4a..24cf8bbad 100644 --- a/src/demo.ts +++ b/src/demo.ts @@ -1,172 +1,80 @@ -import { - QMainWindow, - QLabel, - QCheckBox, - QLineEdit, - QPushButton, - QProgressBar, - QRadioButton, - FlexLayout, - QWidget, - QIcon, - QDial, - QPlainTextEdit, - QTabWidget, - QGridLayout, - QScrollArea, - QPixmap, - CursorShape, - WindowState, - QTextOptionWrapMode, - QCheckBoxEvents, - QSystemTrayIcon, - ReadWriteImageFormats, - QPushButtonEvents -} from "./index"; -import { ok, equal } from "assert"; -import { existsSync, unlinkSync, readFileSync } from "fs"; -import { resolve } from "path"; -import { QMenuBar } from "./lib/QtWidgets/QMenuBar"; +import { QMainWindow } from "./index"; import { QMenu } from "./lib/QtWidgets/QMenu"; +import path from "path"; +import { QIcon } from "./lib/QtGui/QIcon"; +import { QSystemTrayIcon } from "./lib/QtWidgets/QSystemTrayIcon"; +import { QAction } from "./lib/QtWidgets/QAction"; +import { QApplication } from "./lib/QtGui/QApplication"; +import { QKeySequence } from "./lib/QtGui/QKeySequence"; +import { ShortcutContext } from "./lib/QtEnums"; +import { QMenuBar } from "./lib/QtWidgets/QMenuBar"; +import { QShortcut, QShortcutEvents } from "./lib/QtWidgets/QShortcut"; const win = new QMainWindow(); - -const label1 = new QLabel(); -label1.setText("Hello world 1 🧙"); -label1.setInlineStyle("font-size: 20px;"); -label1.setCursor(CursorShape.ForbiddenCursor); - -const label2 = new QLabel(); -label2.setText("Hello world 2 💻"); -label2.setInlineStyle("font-size: 20px;"); -label2.setCursor(CursorShape.ForbiddenCursor); - -const checkbox = new QCheckBox(); -checkbox.setText("Check me out?"); -checkbox.setObjectName("check"); -checkbox.setChecked(true); -checkbox.addEventListener(QCheckBoxEvents.toggled, checked => { - console.log(`${checked ? "checked" : "unchecked"}`); - label1.setInlineStyle(`color: ${checked ? "green" : "red"}`); +const shortcut = new QShortcut(win); +shortcut.setKey(new QKeySequence("Ctrl+M")); +shortcut.setEnabled(true); +shortcut.addEventListener(QShortcutEvents.activated, () => { + console.log("Shortcut Activated"); }); - -const dial = new QDial(); -checkbox.setObjectName("dial"); - -const lineEdit = new QLineEdit(); -lineEdit.setPlaceholderText("Enter your thoughts here"); -lineEdit.setObjectName("editable"); - -const button = new QPushButton(); -button.setText("Push Push Push!"); -button.setObjectName("btn"); - -const nodeguiLogo = new QIcon( - resolve(__dirname, "../extras/assets/nodegui.png") -); - -const icon = new QIcon(resolve(__dirname, "../extras/assets/start_icon.png")); -button.setIcon(icon); - -const tabs = new QTabWidget(); -tabs.setTabsClosable(true); -const tab1 = new QWidget(); -const tab2 = new QWidget(); -tab1.setLayout(new QGridLayout()); -tab2.setLayout(new QGridLayout()); - -if (tab1.layout && tab2.layout) { - tab1.layout.addWidget(label1); - tab2.layout.addWidget(label2); -} - -tabs.addTab(tab1, icon, "Tab 1"); -tabs.addTab(tab2, icon, "Tab 2"); - -const progressBar = new QProgressBar(); -progressBar.setValue(6); -equal(progressBar.value(), 6); -progressBar.setMinimum(1); -progressBar.setMaximum(15); - -const radioButton = new QRadioButton(); -radioButton.setText("Roger that!"); - -const rootView = new QWidget(); -rootView.setObjectName("root"); -rootView.setLayout(new FlexLayout()); - -const textEdit = new QPlainTextEdit(); -textEdit.setPlainText("Hello"); -textEdit.setWordWrapMode(QTextOptionWrapMode.NoWrap); - -const scrollArea = new QScrollArea(); -scrollArea.setInlineStyle("flex: 1; width:'100%';"); - -const imageLabel = new QLabel(); -const pixmap = new QPixmap(resolve(__dirname, "../extras/assets/kitchen.png")); -imageLabel.setPixmap(pixmap); -scrollArea.setWidget(imageLabel); - -function testQPixmapSave(fileName: string, format?: ReadWriteImageFormats) { - try { - existsSync(fileName) && unlinkSync(fileName); - ok(!existsSync(fileName)); - equal(pixmap.save(fileName, format), true); - ok(existsSync(fileName)); - // ideally we want to use file-type, jimp or magica to verify tmp.png has the correct encoding and/or is identical to source img. - ok(readFileSync(fileName).byteLength > 1000); - } catch (error) { - console.error("QPixmap.save test failed", error, error.stack); - } finally { - unlinkSync(fileName); - } -} -testQPixmapSave("tmp.png"); -testQPixmapSave("tmp.jpg"); -testQPixmapSave("tmp_jpg", "JPG"); -testQPixmapSave("tmp_bmp", "BMP"); - +(global as any).shortcut = shortcut; const trayIcon = new QIcon( - resolve(__dirname, "../extras/assets/nodegui_white.png") + path.resolve(__dirname, "../extras/assets/nodegui_white.png") ); + const tray = new QSystemTrayIcon(); tray.setIcon(trayIcon); tray.show(); - -if (rootView.layout) { - rootView.layout.addWidget(tabs); - rootView.layout.addWidget(checkbox); - rootView.layout.addWidget(radioButton); - rootView.layout.addWidget(lineEdit); - rootView.layout.addWidget(button); - rootView.layout.addWidget(progressBar); - rootView.layout.addWidget(textEdit); - rootView.layout.addWidget(scrollArea); - rootView.layout.addWidget(dial); -} - -const menuBar = new QMenuBar(); +tray.setToolTip("hello"); const menu = new QMenu(); +const menuBar = new QMenuBar(); win.setMenuBar(menuBar); -menu.setTitle("hello"); -menuBar.addMenu(menu); -menuBar.setNativeMenuBar(false); -win.setCentralWidget(rootView); -win.setStyleSheet(` - #root { - flex: 1; - height: '100%'; - align-items: 'center'; - justify-content: 'space-around'; +tray.setContextMenu(menu); + +const showHideAction = new QAction(); +showHideAction.setText("Hide"); +showHideAction.setIcon(trayIcon); +showHideAction.addEventListener("triggered", () => { + console.log("Hide called"); + if (win.isVisible()) { + win.hide(); + showHideAction.setText("Show"); + } else { + win.show(); + showHideAction.setText("Hide"); } -`); -win.setWindowIcon(nodeguiLogo); +}); +showHideAction.setShortcut(new QKeySequence("Ctrl+L")); +showHideAction.setShortcutContext(ShortcutContext.ApplicationShortcut); +menu.addAction(showHideAction); + +const subMenu = new QMenu(); +const subMenuAction = new QAction(); +subMenuAction.setText("subAction"); +subMenu.addAction(subMenuAction); +const actionWithSubmenu = new QAction(); +actionWithSubmenu.setMenu(subMenu); +actionWithSubmenu.setText("subMenu"); +menu.addAction(actionWithSubmenu); + +const quitAction = new QAction(); +quitAction.setText("Quit"); +quitAction.addEventListener("triggered", () => { + const app = QApplication.instance(); + app.exit(0); +}); + +menu.addAction(quitAction); + +menu.setTitle("TestMenu"); win.setWindowTitle("NodeGUI Demo"); win.resize(400, 700); win.show(); -win.setWindowState(WindowState.WindowActive); +// menuBar.addMenu(menu); + +const qApp = QApplication.instance(); +qApp.setQuitOnLastWindowClosed(false); (global as any).win = win; // To prevent win from being garbage collected. (global as any).systemTray = tray; // To prevent system tray from being garbage collected. diff --git a/src/index.ts b/src/index.ts index 5260bb96e..4feddd9ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import "./lib/core/bootstrap"; export * from "./lib/QtEnums"; // Gui: export { QApplication } from "./lib/QtGui/QApplication"; +export { QKeySequence } from "./lib/QtGui/QKeySequence"; export { QPixmap, ReadWriteImageFormats, @@ -45,6 +46,8 @@ export { QSystemTrayIcon, QSystemTrayIconEvents } from "./lib/QtWidgets/QSystemTrayIcon"; +export { QAction, QActionEvents } from "./lib/QtWidgets/QAction"; +export { QShortcut, QShortcutEvents } from "./lib/QtWidgets/QShortcut"; // Layouts: export { QGridLayout } from "./lib/QtWidgets/QGridLayout"; export { FlexLayout } from "./lib/core/FlexLayout"; diff --git a/src/lib/QtGui/QKeySequence/index.ts b/src/lib/QtGui/QKeySequence/index.ts new file mode 100644 index 000000000..11deb5379 --- /dev/null +++ b/src/lib/QtGui/QKeySequence/index.ts @@ -0,0 +1,17 @@ +import addon from "../../utils/addon"; +import { Component, NativeElement } from "../../core/Component"; + +export class QKeySequence extends Component { + native: NativeElement; + constructor(keySequence?: string) { + super(); + if (typeof keySequence === "string") { + this.native = new addon.QKeySequence(keySequence); + } else { + this.native = new addon.QKeySequence(); + } + } + count(): number { + return this.native.count(); + } +} diff --git a/src/lib/QtWidgets/QAction/index.ts b/src/lib/QtWidgets/QAction/index.ts new file mode 100644 index 000000000..d305bae59 --- /dev/null +++ b/src/lib/QtWidgets/QAction/index.ts @@ -0,0 +1,50 @@ +import addon from "../../utils/addon"; +import { NodeWidget } from "../QWidget"; +import { EventWidget, BaseWidgetEvents } from "../../core/EventWidget"; +import { NativeElement } from "../../core/Component"; +import { QMenu } from "../QMenu"; +import { QIcon } from "../../QtGui/QIcon"; +import { QKeySequence } from "../../QtGui/QKeySequence"; +import { ShortcutContext } from "../../QtEnums"; + +export const QActionEvents = Object.freeze({ + triggered: "triggered", + changed: "changed", + hovered: "hovered", + toggled: "toggled" +}); +export class QAction extends EventWidget { + native: NativeElement; + icon?: QIcon; + menu?: QMenu; + constructor(parent?: NodeWidget) { + let native; + if (parent) { + native = new addon.QAction(parent.native); + } else { + native = new addon.QAction(); + } + super(native); + this.native = native; + } + setText(text: string) { + this.native.setText(text); + } + setEnabled(enabled: boolean) { + this.native.setEnabled(enabled); + } + setIcon(icon: QIcon) { + this.icon = icon; + this.native.setIcon(icon.native); + } + setMenu(menu: QMenu) { + this.menu = menu; + this.native.setMenu(menu.native); + } + setShortcut(keysequence: QKeySequence) { + this.native.setShortcut(keysequence.native); + } + setShortcutContext(shortcutContext: ShortcutContext) { + this.native.setShortcutContext(shortcutContext); + } +} diff --git a/src/lib/QtWidgets/QMenu.ts b/src/lib/QtWidgets/QMenu.ts index 2e62ee626..ba6c6aa3e 100644 --- a/src/lib/QtWidgets/QMenu.ts +++ b/src/lib/QtWidgets/QMenu.ts @@ -2,12 +2,14 @@ import { BaseWidgetEvents } from "../core/EventWidget"; import { NativeElement } from "../core/Component"; import { NodeWidget } from "./QWidget"; import addon from "../utils/addon"; +import { QAction } from "./QAction"; export const QMenuEvents = Object.freeze({ ...BaseWidgetEvents }); export class QMenu extends NodeWidget { native: NativeElement; + actions: Set; constructor(parent?: NodeWidget) { let native; if (parent) { @@ -18,8 +20,14 @@ export class QMenu extends NodeWidget { super(native); this.native = native; this.parent = parent; + this.actions = new Set(); } setTitle(title: string) { this.native.setTitle(title); } + addAction(action: QAction): QAction { + this.native.addAction(action.native); + this.actions.add(action); + return action; + } } diff --git a/src/lib/QtWidgets/QShortcut/index.ts b/src/lib/QtWidgets/QShortcut/index.ts new file mode 100644 index 000000000..01e797857 --- /dev/null +++ b/src/lib/QtWidgets/QShortcut/index.ts @@ -0,0 +1,32 @@ +import addon from "../../utils/addon"; +import { NodeWidget } from "../QWidget"; +import { EventWidget } from "../../core/EventWidget"; +import { NativeElement } from "../../core/Component"; +import { QKeySequence } from "../../QtGui/QKeySequence"; +import { ShortcutContext } from "../../QtEnums"; + +export const QShortcutEvents = Object.freeze({ + activated: "activated", + activatedAmbiguously: "activatedAmbiguously" +}); + +export class QShortcut extends EventWidget { + native: NativeElement; + constructor(parent: NodeWidget) { + let native = new addon.QShortcut(parent.native); + super(native); + this.native = native; + } + setEnabled(enabled: boolean) { + this.native.setEnabled(enabled); + } + setAutoRepeat(on: boolean) { + this.native.setAutoRepeat(on); + } + setKey(keysequence: QKeySequence) { + this.native.setKey(keysequence.native); + } + setContext(shortcutContext: ShortcutContext) { + this.native.setContext(shortcutContext); + } +} diff --git a/src/lib/QtWidgets/QSystemTrayIcon/index.ts b/src/lib/QtWidgets/QSystemTrayIcon/index.ts index 05d037616..183e49d7e 100644 --- a/src/lib/QtWidgets/QSystemTrayIcon/index.ts +++ b/src/lib/QtWidgets/QSystemTrayIcon/index.ts @@ -3,12 +3,14 @@ import { NodeWidget } from "../QWidget"; import { EventWidget, BaseWidgetEvents } from "../../core/EventWidget"; import { NativeElement } from "../../core/Component"; import { QIcon } from "../../QtGui/QIcon"; +import { QMenu } from "../QMenu"; export const QSystemTrayIconEvents = Object.freeze({ - ...BaseWidgetEvents, + ...BaseWidgetEvents }); export class QSystemTrayIcon extends EventWidget { native: NativeElement; + contextMenu?: QMenu; constructor(parent?: NodeWidget) { let native; if (parent) { @@ -18,11 +20,6 @@ export class QSystemTrayIcon extends EventWidget { } super(native); this.native = native; - // bind member functions - this.show = this.show.bind(this); - this.hide = this.hide.bind(this); - this.setIcon = this.setIcon.bind(this); - this.isVisible = this.isVisible.bind(this); } show() { this.native.show(); @@ -36,4 +33,11 @@ export class QSystemTrayIcon extends EventWidget { isVisible(): boolean { return this.native.isVisible(); } + setToolTip(tooltip: string) { + this.native.setToolTip(tooltip); + } + setContextMenu(menu: QMenu) { + this.contextMenu = menu; + this.native.setContextMenu(this.contextMenu.native); + } }