From 6b92bc567616962fe0b21f6c9b01279097e70086 Mon Sep 17 00:00:00 2001 From: mspencer92 Date: Wed, 8 Jan 2020 10:48:27 -0500 Subject: [PATCH] Add QButtonGroup (#336) * Added QButtonGroup * Update * Update * Update demo.ts * Updates Changed buttonClicked for QButtonGroup to return the id of the button and updated the demo. * Update QButtonGroup.ts * Format main.cpp * Fixes button qgroups Co-authored-by: Atul R --- CMakeLists.txt | 2 + .../QtWidgets/QButtonGroup/nbuttongroup.hpp | 26 ++++ .../QButtonGroup/qbuttongroup_wrap.h | 31 ++++ .../QButtonGroup/qbuttongroup_wrap.cpp | 139 ++++++++++++++++++ src/cpp/main.cpp | 2 + src/demo.ts | 61 ++------ src/index.ts | 1 + src/lib/QtWidgets/QButtonGroup.ts | 58 ++++++++ 8 files changed, 275 insertions(+), 45 deletions(-) create mode 100644 src/cpp/include/nodegui/QtWidgets/QButtonGroup/nbuttongroup.hpp create mode 100644 src/cpp/include/nodegui/QtWidgets/QButtonGroup/qbuttongroup_wrap.h create mode 100644 src/cpp/lib/QtWidgets/QButtonGroup/qbuttongroup_wrap.cpp create mode 100644 src/lib/QtWidgets/QButtonGroup.ts diff --git a/CMakeLists.txt b/CMakeLists.txt index c06019977..b608b2609 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QTreeWidget/qtreewidget_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QMessageBox/qmessagebox_wrap.cpp" + "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QButtonGroup/qbuttongroup_wrap.cpp" "${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" @@ -138,6 +139,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QGroupBox/ngroupbox.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QTimeEdit/ntimeedit.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QTreeWidget/ntreewidget.hpp" + "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QButtonGroup/nbuttongroup.hpp" ) diff --git a/src/cpp/include/nodegui/QtWidgets/QButtonGroup/nbuttongroup.hpp b/src/cpp/include/nodegui/QtWidgets/QButtonGroup/nbuttongroup.hpp new file mode 100644 index 000000000..73dffdcec --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QButtonGroup/nbuttongroup.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include "QtCore/QObject/qobject_macro.h" +#include "core/NodeWidget/nodewidget.h" +#include "napi.h" + +class NButtonGroup : public QButtonGroup, public EventWidget { + Q_OBJECT + EVENTWIDGET_IMPLEMENTATIONS(QButtonGroup) + public: + using QButtonGroup::QButtonGroup; // inherit all constructors of QButtonGroup + void connectSignalsToEventEmitter() { + QOBJECT_SIGNALS + // Qt Connects: Implement all signal connects here + connect(this, QOverload::of(&QButtonGroup::buttonClicked), + [=](int id) { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call({Napi::String::New(env, "buttonClicked"), + Napi::Number::New(env, id)}); + }); + } +}; diff --git a/src/cpp/include/nodegui/QtWidgets/QButtonGroup/qbuttongroup_wrap.h b/src/cpp/include/nodegui/QtWidgets/QButtonGroup/qbuttongroup_wrap.h new file mode 100644 index 000000000..cdd3dbd39 --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QButtonGroup/qbuttongroup_wrap.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include + +#include "Extras/Utils/nutils.h" +#include "QtCore/QObject/qobject_macro.h" +#include "nbuttongroup.hpp" +class QButtonGroupWrap : public Napi::ObjectWrap { + private: + QPointer instance; + + public: + static Napi::Object init(Napi::Env env, Napi::Object exports); + QButtonGroupWrap(const Napi::CallbackInfo& info); + ~QButtonGroupWrap(); + NButtonGroup* getInternalInstance(); + // class constructor + static Napi::FunctionReference constructor; + // wrapped methods + Napi::Value addButton(const Napi::CallbackInfo& info); + Napi::Value checkedId(const Napi::CallbackInfo& info); + Napi::Value id(const Napi::CallbackInfo& info); + Napi::Value button(const Napi::CallbackInfo& info); + Napi::Value removeButton(const Napi::CallbackInfo& info); + Napi::Value buttons(const Napi::CallbackInfo& info); + Napi::Value setId(const Napi::CallbackInfo& info); + Napi::Value checkedButton(const Napi::CallbackInfo& info); + QOBJECT_WRAPPED_METHODS_DECLARATION +}; diff --git a/src/cpp/lib/QtWidgets/QButtonGroup/qbuttongroup_wrap.cpp b/src/cpp/lib/QtWidgets/QButtonGroup/qbuttongroup_wrap.cpp new file mode 100644 index 000000000..dd5c159fc --- /dev/null +++ b/src/cpp/lib/QtWidgets/QButtonGroup/qbuttongroup_wrap.cpp @@ -0,0 +1,139 @@ +#include "QtWidgets/QButtonGroup/qbuttongroup_wrap.h" + +#include +#include + +#include "Extras/Utils/nutils.h" +#include "QtCore/QObject/qobject_wrap.h" +#include "QtGui/QIcon/qicon_wrap.h" +#include "QtWidgets/QMenu/qmenu_wrap.h" +#include "QtWidgets/QWidget/qwidget_wrap.h" + +Napi::FunctionReference QButtonGroupWrap::constructor; + +Napi::Object QButtonGroupWrap::init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + char CLASSNAME[] = "QButtonGroup"; + Napi::Function func = DefineClass( + env, CLASSNAME, + {InstanceMethod("addButton", &QButtonGroupWrap::addButton), + InstanceMethod("checkedId", &QButtonGroupWrap::checkedId), + InstanceMethod("setId", &QButtonGroupWrap::setId), + InstanceMethod("removeButton", &QButtonGroupWrap::removeButton), + InstanceMethod("id", &QButtonGroupWrap::id), + InstanceMethod("checkedButton", &QButtonGroupWrap::checkedButton), + InstanceMethod("buttons", &QButtonGroupWrap::buttons), + InstanceMethod("button", &QButtonGroupWrap::button), + QOBJECT_WRAPPED_METHODS_EXPORT_DEFINE(QButtonGroupWrap)}); + constructor = Napi::Persistent(func); + exports.Set(CLASSNAME, func); + return exports; +} + +NButtonGroup* QButtonGroupWrap::getInternalInstance() { return this->instance; } + +QButtonGroupWrap::QButtonGroupWrap(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 NButtonGroup( + parentWidgetWrap + ->getInternalInstance()); // this sets the parent to current widget + } else if (info.Length() == 0) { + this->instance = new NButtonGroup(); + } else { + Napi::TypeError::New(env, "Wrong number of arguments") + .ThrowAsJavaScriptException(); + } + this->rawData = extrautils::configureQObject(this->getInternalInstance()); +} + +QButtonGroupWrap::~QButtonGroupWrap() { + extrautils::safeDelete(this->instance); +} + +Napi::Value QButtonGroupWrap::addButton(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Object buttonObject = info[0].As(); + QObjectWrap* objectWrap = Napi::ObjectWrap::Unwrap(buttonObject); + QAbstractButton* button = + qobject_cast(objectWrap->getInternalInstance()); + Napi::Number id = info[1].As(); + + this->instance->addButton(button, id.Int32Value()); + return env.Null(); +} +Napi::Value QButtonGroupWrap::removeButton(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Object buttonObject = info[0].As(); + QObjectWrap* objectWrap = Napi::ObjectWrap::Unwrap(buttonObject); + QAbstractButton* button = + qobject_cast(objectWrap->getInternalInstance()); + this->instance->removeButton(button); + return env.Null(); +} +Napi::Value QButtonGroupWrap::checkedId(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + int value = static_cast(this->instance->checkedId()); + return Napi::Number::From(env, value); +} +Napi::Value QButtonGroupWrap::checkedButton(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + auto value = Napi::External::New( + env, this->instance->checkedButton()); + return Napi::Value::From(env, value); +} +Napi::Value QButtonGroupWrap::id(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Object buttonObject = info[0].As(); + QObjectWrap* objectWrap = Napi::ObjectWrap::Unwrap(buttonObject); + QAbstractButton* button = + qobject_cast(objectWrap->getInternalInstance()); + int value = static_cast(this->instance->id(button)); + return Napi::Number::From(env, value); +} +Napi::Value QButtonGroupWrap::setId(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Object buttonObject = info[0].As(); + QObjectWrap* objectWrap = Napi::ObjectWrap::Unwrap(buttonObject); + QAbstractButton* button = + qobject_cast(objectWrap->getInternalInstance()); + Napi::Number id = info[1].As(); + + this->instance->setId(button, id.Int32Value()); + return env.Null(); +} +Napi::Value QButtonGroupWrap::buttons(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + QList items = this->instance->buttons(); + Napi::Array napiItems = Napi::Array::New(env, items.size()); + for (int i = 0; i < items.size(); i++) { + QAbstractButton* item = items[i]; + auto value = Napi::External::New(env, item); + napiItems[i] = value; + } + + return napiItems; +} +Napi::Value QButtonGroupWrap::button(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Number id = info[0].As(); + + auto value = + Napi::External::New(env, this->instance->button(id)); + return Napi::Value::From(env, value); +} \ No newline at end of file diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index 30f522582..0e1aec75a 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -26,6 +26,7 @@ #include "QtGui/QStyle/qstyle_wrap.h" #include "QtWidgets/QAction/qaction_wrap.h" #include "QtWidgets/QBoxLayout/qboxlayout_wrap.h" +#include "QtWidgets/QButtonGroup/qbuttongroup_wrap.h" #include "QtWidgets/QCalendarWidget/qcalendarwidget_wrap.h" #include "QtWidgets/QCheckBox/qcheckbox_wrap.h" #include "QtWidgets/QComboBox/qcombobox_wrap.h" @@ -135,6 +136,7 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) { QMenuBarWrap::init(env, exports); QMessageBoxWrap::init(env, exports); QTimeEditWrap::init(env, exports); + QButtonGroupWrap::init(env, exports); return exports; } diff --git a/src/demo.ts b/src/demo.ts index eec5e1d5d..9657f3a71 100644 --- a/src/demo.ts +++ b/src/demo.ts @@ -1,54 +1,25 @@ -import { FlexLayout, QMainWindow, QWidget } from './index'; -import { QLabel } from './lib/QtWidgets/QLabel'; -import { QFont, QFontCapitalization } from './lib/QtGui/QFont'; -import { QPushButton } from './lib/QtWidgets/QPushButton'; -import { QDateTimeEdit } from './lib/QtWidgets/QDateTimeEdit'; -import { QCalendarWidget } from './lib/QtWidgets/QCalendarWidget'; -import { QDate } from './lib/QtCore/QDate'; -import { QDateTime } from './lib/QtCore/QDateTime'; -import { QTime } from './lib/QtCore/QTime'; +import { QWidget, QMainWindow, FlexLayout, QRadioButton, QButtonGroup } from './index'; const win = new QMainWindow(); const center = new QWidget(); const layout = new FlexLayout(); center.setLayout(layout); -const label = new QLabel(); -const font = new QFont('Mono', 14); -label.setFont(font); -label.setText('label 1'); -const btn = new QPushButton(); -btn.setText('Change font'); -btn.setFont(new QFont('Helvetica', 20)); -btn.addEventListener('clicked', () => { - const font2 = label.font(); - font2.setCapitalization(QFontCapitalization.AllUppercase); - font2.setItalic(true); - font2.setFamily('Times'); - console.log('point', font2.pointSize()); - label.setFont(font2); -}); -const dtEdit = new QDateTimeEdit(); -const calendar = new QCalendarWidget(); -const date = QDate.currentDate(); -const time = QTime.currentTime(); -const datetime = QDateTime.currentDateTime(); -const strDate = date.toString('dd.MM.yyyy'); -const strTime = time.toString('hh:mm:ss.zzz'); -const strDt = datetime.toString('dd.MM.yyyy hh:mm:ss.zzz'); -console.log(strDate); -console.log(strTime); -console.log(strDt); -dtEdit.setDate(date); -dtEdit.setTime(time); -dtEdit.setCalendarPopup(true); -dtEdit.setCalendarWidget(calendar); - -layout.addWidget(label); -layout.addWidget(btn); -layout.addWidget(dtEdit); - win.setCentralWidget(center); -win.resize(400, 400); +const buttonGroup = new QButtonGroup(center); +const t: any[] = []; +for (let i = 0; i < 4; i++) { + const radioButton = new QRadioButton(); + radioButton.setText('Button #' + (i + 1)); + center.layout?.addWidget(radioButton); + t.push(radioButton); + buttonGroup.addButton(radioButton, i); +} win.show(); +buttonGroup.addEventListener('buttonClicked', (id: number) => { + console.log('Button #' + (id + 1) + ' clicked!'); + buttonGroup.removeButton(t[0]); +}); (global as any).win = win; + +setInterval(() => null, 1000); diff --git a/src/index.ts b/src/index.ts index 7eaa4d3a5..915f9cafc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -58,6 +58,7 @@ export { QTreeWidgetItem } from './lib/QtWidgets/QTreeWidgetItem'; export { QPainter, RenderHint } from './lib/QtWidgets/QPainter'; export { QDialog, QDialogSignals } from './lib/QtWidgets/QDialog'; export { QMessageBox, StandardButton, Icon, ButtonRole } from './lib/QtWidgets/QMessageBox'; +export { QButtonGroup, QButtonGroupSignals } from './lib/QtWidgets/QButtonGroup'; export { QSystemTrayIcon, diff --git a/src/lib/QtWidgets/QButtonGroup.ts b/src/lib/QtWidgets/QButtonGroup.ts new file mode 100644 index 000000000..817aaaed9 --- /dev/null +++ b/src/lib/QtWidgets/QButtonGroup.ts @@ -0,0 +1,58 @@ +import addon from '../utils/addon'; +import { NodeWidget } from './QWidget'; +import { NativeElement, NativeRawPointer } from '../core/Component'; +import { NodeObject, QObjectSignals } from '../QtCore/QObject'; +import { QAbstractButton, QAbstractButtonSignals } from './QAbstractButton'; + +export interface QButtonGroupSignals extends QObjectSignals { + buttonClicked: (id?: number) => void; +} + +export class QButtonGroup extends NodeObject { + native: NativeElement; + constructor(); + constructor(parent: NodeWidget); + constructor(parent?: NodeWidget) { + let native; + if (parent) { + native = new addon.QButtonGroup(parent.native); + } else { + native = new addon.QButtonGroup(); + } + super(native); + this.native = native; + parent && parent.nodeChildren.add(this); + } + addButton(button: QAbstractButton, id = -1): void { + this.native.addButton(button.native, id); + this.nodeChildren.add(button); + } + removeButton(button: QAbstractButton): void { + this.native.removeButton(button.native); + this.nodeChildren.delete(button); + } + setExclusive(exculsive: boolean): void { + this.native.setProperty('exclusive', exculsive); + } + checkedId(): number { + return this.native.checkedId(); + } + exclusive(): boolean { + return this.property('exclusive').toBool(); + } + setId(button: QAbstractButton, id: number): void { + this.native.setId(button.native, id); + } + id(button: QAbstractButton): number { + return this.native.id(button.native); + } + buttons(): QAbstractButton[] { + return this.native.buttons(); + } + checkedButton(): NativeRawPointer<'QAbstractButton*'> { + return this.native.checkedButton(); + } + button(id: number): NativeRawPointer<'QAbstractButton*'> { + return this.native.button(id); + } +}