From c90b2cb3ce51bfcd614b72c98b0bb97ae83c3523 Mon Sep 17 00:00:00 2001 From: Atul R Date: Wed, 18 Dec 2019 17:36:44 +0530 Subject: [PATCH] QTreeWidget PR (#277) * Added the beginning of QTreeWidget and QTreeWidgetItem * Fixed garbage collection * Fixed garbage collection * Rewrote the constructor for QTreeWidgetItem * Code cleanup * Fixed up the QTreeWidgetItem constructor to accept only a string list of columns. Code cleanup * Add setHeaderHidden to QTreeWidget * Started adding signals to QTreeWidget * Started adding signals to QTreeWidget * Started adding signals to QTreeWidget * Added TreeWidget back to main.cpp * Added more functions to QTreeWidgetItem and QPlainTextEdit * linting and cleanup * parenting fix * Fixes garbage collection for treewidget items --- CMakeLists.txt | 4 + .../QPlainTextEdit/qplaintextedit_wrap.h | 1 + .../QtWidgets/QTreeWidget/ntreewidget.hpp | 22 +++ .../QtWidgets/QTreeWidget/qtreewidget_wrap.h | 36 ++++ .../QTreeWidgetItem/qtreewidgetitem_wrap.h | 37 ++++ .../QPlainTextEdit/qplaintextedit_wrap.cpp | 10 + .../QTreeWidget/qtreewidget_wrap.cpp | 76 +++++++ .../QTreeWidgetItem/qtreewidgetitem_wrap.cpp | 187 ++++++++++++++++++ .../lib/QtWidgets/QWidget/qwidget_wrap.cpp | 6 +- src/cpp/main.cpp | 6 +- src/demo.ts | 29 ++- src/index.ts | 3 + src/lib/QtCore/QObject.ts | 2 +- src/lib/QtWidgets/QAbstractScrollArea.ts | 7 + src/lib/QtWidgets/QBoxLayout.ts | 2 +- src/lib/QtWidgets/QCheckBox.ts | 2 +- src/lib/QtWidgets/QComboBox.ts | 2 +- src/lib/QtWidgets/QDial.ts | 2 +- src/lib/QtWidgets/QFileDialog.ts | 2 +- src/lib/QtWidgets/QGridLayout.ts | 2 +- src/lib/QtWidgets/QGroupBox.ts | 2 +- src/lib/QtWidgets/QLabel.ts | 2 +- src/lib/QtWidgets/QLineEdit.ts | 2 +- src/lib/QtWidgets/QMainWindow.ts | 2 +- src/lib/QtWidgets/QMenu.ts | 2 +- src/lib/QtWidgets/QMenuBar.ts | 2 +- src/lib/QtWidgets/QPlainTextEdit.ts | 5 +- src/lib/QtWidgets/QProgressBar.ts | 2 +- src/lib/QtWidgets/QPushButton.ts | 2 +- src/lib/QtWidgets/QRadioButton.ts | 2 +- src/lib/QtWidgets/QScrollArea.ts | 2 +- src/lib/QtWidgets/QSpinBox.ts | 2 +- src/lib/QtWidgets/QStackedWidget.ts | 2 +- src/lib/QtWidgets/QTabWidget.ts | 2 +- src/lib/QtWidgets/QTableWidget.ts | 2 +- src/lib/QtWidgets/QToolButton.ts | 2 +- src/lib/QtWidgets/QTreeWidget.ts | 43 ++++ src/lib/QtWidgets/QTreeWidgetItem.ts | 55 ++++++ src/lib/QtWidgets/QWidget.ts | 2 +- src/lib/core/Component.ts | 8 +- 40 files changed, 543 insertions(+), 38 deletions(-) create mode 100644 src/cpp/include/nodegui/QtWidgets/QTreeWidget/ntreewidget.hpp create mode 100644 src/cpp/include/nodegui/QtWidgets/QTreeWidget/qtreewidget_wrap.h create mode 100644 src/cpp/include/nodegui/QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.h create mode 100644 src/cpp/lib/QtWidgets/QTreeWidget/qtreewidget_wrap.cpp create mode 100644 src/cpp/lib/QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.cpp create mode 100644 src/lib/QtWidgets/QTreeWidget.ts create mode 100644 src/lib/QtWidgets/QTreeWidgetItem.ts diff --git a/CMakeLists.txt b/CMakeLists.txt index ad414f486..11444c6bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,8 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${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/QtWidgets/QGroupBox/qgroupbox_wrap.cpp" + "${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/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" @@ -112,6 +114,8 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QBoxLayout/nboxlayout.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QComboBox/ncombobox.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QGroupBox/ngroupbox.hpp" + "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QTreeWidget/ntreewidget.hpp" + ) AddCommonConfig(${CORE_WIDGETS_ADDON}) diff --git a/src/cpp/include/nodegui/QtWidgets/QPlainTextEdit/qplaintextedit_wrap.h b/src/cpp/include/nodegui/QtWidgets/QPlainTextEdit/qplaintextedit_wrap.h index 61b21a401..0d3545892 100644 --- a/src/cpp/include/nodegui/QtWidgets/QPlainTextEdit/qplaintextedit_wrap.h +++ b/src/cpp/include/nodegui/QtWidgets/QPlainTextEdit/qplaintextedit_wrap.h @@ -32,4 +32,5 @@ class QPlainTextEditWrap : public Napi::ObjectWrap { Napi::Value wordWrapMode(const Napi::CallbackInfo &info); Napi::Value setLineWrapMode(const Napi::CallbackInfo &info); Napi::Value lineWrapMode(const Napi::CallbackInfo &info); + Napi::Value insertPlainText(const Napi::CallbackInfo &info); }; diff --git a/src/cpp/include/nodegui/QtWidgets/QTreeWidget/ntreewidget.hpp b/src/cpp/include/nodegui/QtWidgets/QTreeWidget/ntreewidget.hpp new file mode 100644 index 000000000..f70dfc228 --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QTreeWidget/ntreewidget.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include "core/NodeWidget/nodewidget.h" +#include "napi.h" + +class NTreeWidget : public QTreeWidget, public NodeWidget { + Q_OBJECT + NODEWIDGET_IMPLEMENTATIONS(QTreeWidget) + + public: + using QTreeWidget::QTreeWidget; // inherit all constructors of QTreeWidget + + void connectWidgetSignalsToEventEmitter() { + QObject::connect(this, &QTreeWidget::itemSelectionChanged, [=]() { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call({Napi::String::New(env, "itemSelectionChanged")}); + }); + } +}; diff --git a/src/cpp/include/nodegui/QtWidgets/QTreeWidget/qtreewidget_wrap.h b/src/cpp/include/nodegui/QtWidgets/QTreeWidget/qtreewidget_wrap.h new file mode 100644 index 000000000..5d13812a3 --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QTreeWidget/qtreewidget_wrap.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include + +#include "QtWidgets/QWidget/qwidget_macro.h" +#include "ntreewidget.hpp" + +class QTreeWidgetWrap : public Napi::ObjectWrap { + private: + QPointer instance; + + public: + static Napi::Object init(Napi::Env env, Napi::Object exports); + + QTreeWidgetWrap(const Napi::CallbackInfo &info); + + ~QTreeWidgetWrap(); + + NTreeWidget *getInternalInstance(); + + // class constructor + static Napi::FunctionReference constructor; + + Napi::Value addTopLevelItem(const Napi::CallbackInfo &info); + Napi::Value selectedItems(const Napi::CallbackInfo &info); + + // Napi::Value addTopLevelItems(const Napi::CallbackInfo& info); + // Napi::Value setHorizontalScrollBarPolicy(const Napi::CallbackInfo& info); + // Napi::Value setVerticalScrollBarPolicy(const Napi::CallbackInfo& info); + // Napi::Value takeTopLevelItem(const Napi::CallbackInfo& info); + // Napi::Value findItems(const Napi::CallbackInfo& info); + QWIDGET_WRAPPED_METHODS_DECLARATION +}; diff --git a/src/cpp/include/nodegui/QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.h b/src/cpp/include/nodegui/QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.h new file mode 100644 index 000000000..9f3181d1f --- /dev/null +++ b/src/cpp/include/nodegui/QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +#include + +#include "Extras/Utils/nutils.h" +#include "core/Component/component_wrap.h" + +class QTreeWidgetItemWrap : public Napi::ObjectWrap { + private: + QTreeWidgetItem *instance; + bool disableDeletion; + + public: + static Napi::Object init(Napi::Env env, Napi::Object exports); + + QTreeWidgetItemWrap(const Napi::CallbackInfo &info); + + ~QTreeWidgetItemWrap(); + + QTreeWidgetItem *getInternalInstance(); + + // class constructor + static Napi::FunctionReference constructor; + + // wrapped methods + Napi::Value setText(const Napi::CallbackInfo &info); + Napi::Value parent(const Napi::CallbackInfo &info); + Napi::Value childCount(const Napi::CallbackInfo &info); + Napi::Value child(const Napi::CallbackInfo &info); + Napi::Value text(const Napi::CallbackInfo &info); + Napi::Value setSelected(const Napi::CallbackInfo &info); + Napi::Value setExpanded(const Napi::CallbackInfo &info); + COMPONENT_WRAPPED_METHODS_DECLARATION +}; \ No newline at end of file diff --git a/src/cpp/lib/QtWidgets/QPlainTextEdit/qplaintextedit_wrap.cpp b/src/cpp/lib/QtWidgets/QPlainTextEdit/qplaintextedit_wrap.cpp index 9ea2b7f56..a4cde7770 100644 --- a/src/cpp/lib/QtWidgets/QPlainTextEdit/qplaintextedit_wrap.cpp +++ b/src/cpp/lib/QtWidgets/QPlainTextEdit/qplaintextedit_wrap.cpp @@ -23,6 +23,7 @@ Napi::Object QPlainTextEditWrap::init(Napi::Env env, Napi::Object exports) { InstanceMethod("wordWrapMode", &QPlainTextEditWrap::wordWrapMode), InstanceMethod("setLineWrapMode", &QPlainTextEditWrap::setLineWrapMode), InstanceMethod("lineWrapMode", &QPlainTextEditWrap::lineWrapMode), + InstanceMethod("insertPlainText", &QPlainTextEditWrap::insertPlainText), QWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QPlainTextEditWrap) QABSTRACTSCROLLAREA_WRAPPED_METHODS_EXPORT_DEFINE( QPlainTextEditWrap)}); @@ -132,3 +133,12 @@ Napi::Value QPlainTextEditWrap::lineWrapMode(const Napi::CallbackInfo &info) { int value = static_cast(this->instance->lineWrapMode()); return Napi::Number::From(env, value); } + +Napi::Value QPlainTextEditWrap::insertPlainText( + const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::String plainText = info[0].As(); + this->instance->insertPlainText(plainText.Utf8Value().c_str()); + return env.Null(); +} diff --git a/src/cpp/lib/QtWidgets/QTreeWidget/qtreewidget_wrap.cpp b/src/cpp/lib/QtWidgets/QTreeWidget/qtreewidget_wrap.cpp new file mode 100644 index 000000000..67c8b6a50 --- /dev/null +++ b/src/cpp/lib/QtWidgets/QTreeWidget/qtreewidget_wrap.cpp @@ -0,0 +1,76 @@ +#include "QtWidgets/QTreeWidget/qtreewidget_wrap.h" + +#include + +#include "Extras/Utils/nutils.h" +#include "QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.h" +#include "QtWidgets/QWidget/qwidget_wrap.h" + +Napi::FunctionReference QTreeWidgetWrap::constructor; + +Napi::Object QTreeWidgetWrap::init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + char CLASSNAME[] = "QTreeWidget"; + Napi::Function func = DefineClass( + env, CLASSNAME, + {InstanceMethod("addTopLevelItem", &QTreeWidgetWrap::addTopLevelItem), + InstanceMethod("selectedItems", &QTreeWidgetWrap::selectedItems), + QWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QTreeWidgetWrap)}); + constructor = Napi::Persistent(func); + exports.Set(CLASSNAME, func); + return exports; +} + +NTreeWidget* QTreeWidgetWrap::getInternalInstance() { return this->instance; } + +QTreeWidgetWrap::QTreeWidgetWrap(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 NTreeWidget(parentWidgetWrap->getInternalInstance()); + } else if (info.Length() == 0) { + this->instance = new NTreeWidget(); + } else { + Napi::TypeError::New(env, "Wrong number of arguments") + .ThrowAsJavaScriptException(); + } + this->rawData = extrautils::configureQWidget( + this->getInternalInstance(), this->getInternalInstance()->getFlexNode(), + true); +} + +QTreeWidgetWrap::~QTreeWidgetWrap() { extrautils::safeDelete(this->instance); } + +Napi::Value QTreeWidgetWrap::addTopLevelItem(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object itemObject = info[0].As(); + QTreeWidgetItemWrap* itemWrap = + Napi::ObjectWrap::Unwrap(itemObject); + QTreeWidgetItem* item = itemWrap->getInternalInstance(); + this->instance->addTopLevelItem(item); + return env.Null(); +} +Napi::Value QTreeWidgetWrap::selectedItems(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + QList items = this->instance->selectedItems(); + Napi::Array napiItems = Napi::Array::New(env, items.size()); + for (int i = 0; i < items.size(); i++) { + QTreeWidgetItem* item = items[i]; + // disable deletion of the native instance for these by passing true + Napi::Object val = QTreeWidgetItemWrap::constructor.New( + {Napi::External::New(env, item), + Napi::Boolean::New(env, true)}); + napiItems[i] = val; + } + + return napiItems; +} diff --git a/src/cpp/lib/QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.cpp b/src/cpp/lib/QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.cpp new file mode 100644 index 000000000..3a943fe1c --- /dev/null +++ b/src/cpp/lib/QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.cpp @@ -0,0 +1,187 @@ +#include "QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.h" + +#include + +#include "Extras/Utils/nutils.h" +#include "QtWidgets/QTreeWidget/qtreewidget_wrap.h" +#include "QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.h" +#include "core/Component/component_wrap.h" + +Napi::FunctionReference QTreeWidgetItemWrap::constructor; + +Napi::Object QTreeWidgetItemWrap::init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + char CLASSNAME[] = "QTreeWidgetItem"; + Napi::Function func = DefineClass( + env, CLASSNAME, + {InstanceMethod("setText", &QTreeWidgetItemWrap::setText), + InstanceMethod("parent", &QTreeWidgetItemWrap::parent), + InstanceMethod("child", &QTreeWidgetItemWrap::child), + InstanceMethod("text", &QTreeWidgetItemWrap::text), + InstanceMethod("childCount", &QTreeWidgetItemWrap::childCount), + InstanceMethod("setSelected", &QTreeWidgetItemWrap::setSelected), + InstanceMethod("setExpanded", &QTreeWidgetItemWrap::setExpanded), + COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE}); + constructor = Napi::Persistent(func); + exports.Set(CLASSNAME, func); + return exports; +} + +QTreeWidgetItem *QTreeWidgetItemWrap::getInternalInstance() { + return this->instance; +} + +QTreeWidgetItemWrap::~QTreeWidgetItemWrap() { + if (!this->disableDeletion) { + delete this->instance; + } +} +QTreeWidgetItemWrap::QTreeWidgetItemWrap(const Napi::CallbackInfo &info) + : Napi::ObjectWrap(info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + if (info.Length() > 0 && info[0].IsExternal()) { + // --- if external --- + this->instance = info[0].As>().Data(); + if (info.Length() == 2) { + this->disableDeletion = info[1].As().Value(); + } + } else { + // --- regular cases --- + if (info.Length() == 3) { + Napi::Array stringsNapi = info[1].As(); + QList list; + for (int i = 0; i < stringsNapi.Length(); i++) { + Napi::Value stringNapi = stringsNapi[i]; + list.append(stringNapi.As().Utf8Value().c_str()); + } + QStringList strings = QStringList(list); + + std::string parentType = info[2].As().Utf8Value(); + if (parentType == "tree") { + Napi::Object parentObject = info[0].As(); + QTreeWidgetWrap *parentWidgetWrap = + Napi::ObjectWrap::Unwrap(parentObject); + QTreeWidget *parent = parentWidgetWrap->getInternalInstance(); + this->instance = new QTreeWidgetItem(parent, strings); + } else if (parentType == "item") { + Napi::Object itemObject = info[0].As(); + QTreeWidgetItemWrap *itemWidgetWrap = + Napi::ObjectWrap::Unwrap(itemObject); + QTreeWidgetItem *item = itemWidgetWrap->getInternalInstance(); + this->instance = new QTreeWidgetItem(item, strings); + } else { + Napi::TypeError::New(env, "Invalid parent type") + .ThrowAsJavaScriptException(); + } + } else if (info.Length() == 2) { + std::string parentType = info[1].As().Utf8Value(); + if (parentType == "tree") { + Napi::Object parentObject = info[0].As(); + QTreeWidgetWrap *parentWidgetWrap = + Napi::ObjectWrap::Unwrap(parentObject); + QTreeWidget *parent = parentWidgetWrap->getInternalInstance(); + this->instance = new QTreeWidgetItem(parent); + } else if (parentType == "item") { + Napi::Object itemObject = info[0].As(); + QTreeWidgetItemWrap *itemWidgetWrap = + Napi::ObjectWrap::Unwrap(itemObject); + QTreeWidgetItem *item = itemWidgetWrap->getInternalInstance(); + this->instance = new QTreeWidgetItem(item); + } else { + Napi::TypeError::New(env, "Invalid parent type") + .ThrowAsJavaScriptException(); + } + } else if (info.Length() == 1) { + Napi::Array stringsNapi = info[0].As(); + QList list; + for (int i = 0; i < stringsNapi.Length(); i++) { + Napi::Value stringNapi = stringsNapi[i]; + list.append(stringNapi.As().Utf8Value().c_str()); + } + QStringList strings = QStringList(list); + this->instance = new QTreeWidgetItem(strings); + } else if (info.Length() == 0) { + this->instance = new QTreeWidgetItem(); + } else { + Napi::TypeError::New(env, "Wrong number of arguments") + .ThrowAsJavaScriptException(); + } + } + this->rawData = extrautils::configureComponent(this->getInternalInstance()); +} + +Napi::Value QTreeWidgetItemWrap::setText(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + int column = info[0].As().Int32Value(); + Napi::String napiText = info[1].As(); + std::string text = napiText.Utf8Value(); + this->instance->setText(column, QString::fromUtf8(text.c_str())); + return env.Null(); +} +Napi::Value QTreeWidgetItemWrap::parent(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + if (this->instance->parent() == nullptr) { + return env.Null(); + } else { + QTreeWidgetItem *item = this->instance->parent(); + // disable deletion of the native instance for these by passing true + Napi::Object val = QTreeWidgetItemWrap::constructor.New( + {Napi::External::New(env, item), + Napi::Boolean::New(env, true)}); + return val; + } +} +Napi::Value QTreeWidgetItemWrap::childCount(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + int value = static_cast(this->instance->childCount()); + return Napi::Number::From(env, value); +} + +Napi::Value QTreeWidgetItemWrap::child(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Number index = info[0].As(); + + if (this->instance->child(index) == nullptr) { + return env.Null(); + } else { + QTreeWidgetItem *item = this->instance->child(index); + // disable deletion of the native instance for these by passing true + Napi::Object val = QTreeWidgetItemWrap::constructor.New( + {Napi::External::New(env, item), + Napi::Boolean::New(env, true)}); + return val; + } +} +Napi::Value QTreeWidgetItemWrap::text(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Number column = info[0].As(); + + if (this->instance->text(column) == nullptr) { + return env.Null(); + } else { + return Napi::Value::From(env, this->instance->text(column).toStdString()); + } +} +Napi::Value QTreeWidgetItemWrap::setSelected(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Boolean selected = info[0].As(); + this->instance->setSelected(selected.Value()); + return env.Null(); +} +Napi::Value QTreeWidgetItemWrap::setExpanded(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + Napi::Boolean expanded = info[0].As(); + this->instance->setExpanded(expanded.Value()); + return env.Null(); +} diff --git a/src/cpp/lib/QtWidgets/QWidget/qwidget_wrap.cpp b/src/cpp/lib/QtWidgets/QWidget/qwidget_wrap.cpp index 33c822dc7..3cd8ca20d 100644 --- a/src/cpp/lib/QtWidgets/QWidget/qwidget_wrap.cpp +++ b/src/cpp/lib/QtWidgets/QWidget/qwidget_wrap.cpp @@ -15,11 +15,11 @@ Napi::Object QWidgetWrap::init(Napi::Env env, Napi::Object exports) { return exports; } -NWidget* QWidgetWrap::getInternalInstance() { return this->instance; } +NWidget *QWidgetWrap::getInternalInstance() { return this->instance; } QWidgetWrap::~QWidgetWrap() { extrautils::safeDelete(this->instance); } -QWidgetWrap::QWidgetWrap(const Napi::CallbackInfo& info) +QWidgetWrap::QWidgetWrap(const Napi::CallbackInfo &info) : Napi::ObjectWrap(info) { Napi::Env env = info.Env(); Napi::HandleScope scope(env); @@ -29,7 +29,7 @@ QWidgetWrap::QWidgetWrap(const Napi::CallbackInfo& info) new NWidget(info[0].As>().Data()); } else { Napi::Object parentObject = info[0].As(); - QWidgetWrap* parentWidgetWrap = + QWidgetWrap *parentWidgetWrap = Napi::ObjectWrap::Unwrap(parentObject); this->instance = new NWidget(parentWidgetWrap->getInternalInstance()); } diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index fe0dbedb7..499fb491d 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -43,6 +43,8 @@ #include "QtWidgets/QTableWidget/qtablewidget_wrap.h" #include "QtWidgets/QTableWidgetItem/qtablewidgetitem_wrap.h" #include "QtWidgets/QToolButton/qtoolbutton_wrap.h" +#include "QtWidgets/QTreeWidget/qtreewidget_wrap.h" +#include "QtWidgets/QTreeWidgetItem/qtreewidgetitem_wrap.h" #include "QtWidgets/QWidget/qwidget_wrap.h" #include "core/FlexLayout/flexlayout_wrap.h" // These cant be instantiated in JS Side @@ -73,6 +75,8 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) { QFileDialogWrap::init(env, exports); QTableWidgetWrap::init(env, exports); QTableWidgetItemWrap::init(env, exports); + QTreeWidgetWrap::init(env, exports); + QTreeWidgetItemWrap::init(env, exports); QGridLayoutWrap::init(env, exports); QGroupBoxWrap::init(env, exports); FlexLayoutWrap::init(env, exports); @@ -100,4 +104,4 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) { return exports; } -NODE_API_MODULE(NODE_GYP_MODULE_NAME, Main) +NODE_API_MODULE(NODE_GYP_MODULE_NAME, Main) \ No newline at end of file diff --git a/src/demo.ts b/src/demo.ts index 6a3256efc..c550510c9 100644 --- a/src/demo.ts +++ b/src/demo.ts @@ -1,17 +1,30 @@ -import { QMainWindow, QPushButton, QLabel, QWidget, FlexLayout } from './index'; +import { FlexLayout, QMainWindow, QTreeWidget, QTreeWidgetItem, QWidget } from './index'; const win = new QMainWindow(); const center = new QWidget(); -const button = new QPushButton(); -button.setText('World'); - -const hello = new QLabel(); -hello.setText('Hello'); +const tree = new QTreeWidget(); +const item1 = new QTreeWidgetItem(tree, ['Hello item1!']); +const item2 = new QTreeWidgetItem(item1, ['Hello item2!']); +const item3 = new QTreeWidgetItem(['Hello item3!!']); +tree.addTopLevelItem(item3); +tree.addEventListener('itemSelectionChanged', () => { + const items = tree.selectedItems(); + items.forEach(function(item) { + const parent = item.parent(); + if (parent) { + const child = parent.child(0); + if (child) { + console.log(child.text(0)); + } + } + console.log(item.childCount()); + (global as any).gc(); + }); +}); center.setLayout(new FlexLayout()); -center.layout?.addWidget(button); -center.layout?.addWidget(hello); +center.layout?.addWidget(tree); win.setCentralWidget(center); win.show(); diff --git a/src/index.ts b/src/index.ts index ad831a5b6..db7e9bc79 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,6 +45,9 @@ export { QMenu, QMenuEvents } from './lib/QtWidgets/QMenu'; export { QMenuBar, QMenuBarEvents } from './lib/QtWidgets/QMenuBar'; export { QPlainTextEdit, QPlainTextEditEvents, LineWrapMode } from './lib/QtWidgets/QPlainTextEdit'; export { QScrollArea, QScrollAreaEvents } from './lib/QtWidgets/QScrollArea'; +export { QTreeWidget, QTreeWidgetEvents } from './lib/QtWidgets/QTreeWidget'; +export { QTreeWidgetItem } from './lib/QtWidgets/QTreeWidgetItem'; + export { QSystemTrayIcon, QSystemTrayIconEvents, diff --git a/src/lib/QtCore/QObject.ts b/src/lib/QtCore/QObject.ts index 33bd9c599..3e8f91dd8 100644 --- a/src/lib/QtCore/QObject.ts +++ b/src/lib/QtCore/QObject.ts @@ -38,7 +38,7 @@ export class QObject extends NodeObject { native = new addon.QObject(); } super(native); - this.nodeParent = parent; + this.setNodeParent(parent); this.native = native; } } diff --git a/src/lib/QtWidgets/QAbstractScrollArea.ts b/src/lib/QtWidgets/QAbstractScrollArea.ts index e5822d5d7..45b0c2fd2 100644 --- a/src/lib/QtWidgets/QAbstractScrollArea.ts +++ b/src/lib/QtWidgets/QAbstractScrollArea.ts @@ -1,4 +1,5 @@ import { NodeWidget, QWidget } from './QWidget'; +import { ScrollBarPolicy } from '../QtEnums/ScrollBarPolicy'; export abstract class QAbstractScrollArea extends NodeWidget { viewportWidget?: NodeWidget; @@ -12,4 +13,10 @@ export abstract class QAbstractScrollArea extends NodeWidget { } return this.viewportWidget; } + setHorizontalScrollBarPolicy(policy: ScrollBarPolicy): void { + this.native.setProperty('horizontalScrollBarPolicy', policy); + } + setVerticalScrollBarPolicy(policy: ScrollBarPolicy): void { + this.native.setProperty('verticalScrollBarPolicy', policy); + } } diff --git a/src/lib/QtWidgets/QBoxLayout.ts b/src/lib/QtWidgets/QBoxLayout.ts index 8c9e6787d..92d489184 100644 --- a/src/lib/QtWidgets/QBoxLayout.ts +++ b/src/lib/QtWidgets/QBoxLayout.ts @@ -15,7 +15,7 @@ export class QBoxLayout extends NodeLayout { native = new addon.QBoxLayout(dir); } super(native); - this.nodeParent = parent; + this.setNodeParent(parent); this.native = native; this.childLayouts = new Set(); } diff --git a/src/lib/QtWidgets/QCheckBox.ts b/src/lib/QtWidgets/QCheckBox.ts index 644118d37..fa68bb8cb 100644 --- a/src/lib/QtWidgets/QCheckBox.ts +++ b/src/lib/QtWidgets/QCheckBox.ts @@ -19,7 +19,7 @@ export class QCheckBox extends QAbstractButton { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } setChecked(check: boolean): void { this.native.setChecked(check); diff --git a/src/lib/QtWidgets/QComboBox.ts b/src/lib/QtWidgets/QComboBox.ts index 000ae6b80..f774174fe 100644 --- a/src/lib/QtWidgets/QComboBox.ts +++ b/src/lib/QtWidgets/QComboBox.ts @@ -23,7 +23,7 @@ export class QComboBox extends NodeWidget { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } addItem(icon: QIcon | undefined, text: string, userData: QVariant = new QVariant()): void { if (icon) { diff --git a/src/lib/QtWidgets/QDial.ts b/src/lib/QtWidgets/QDial.ts index b43787dc4..fb9eb4bbf 100644 --- a/src/lib/QtWidgets/QDial.ts +++ b/src/lib/QtWidgets/QDial.ts @@ -23,7 +23,7 @@ export class QDial extends QAbstractSlider { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } setNotchesVisible(visible: boolean): void { // react:✓ diff --git a/src/lib/QtWidgets/QFileDialog.ts b/src/lib/QtWidgets/QFileDialog.ts index aa01691c1..7ba432fe6 100644 --- a/src/lib/QtWidgets/QFileDialog.ts +++ b/src/lib/QtWidgets/QFileDialog.ts @@ -27,7 +27,7 @@ export class QFileDialog extends NodeWidget { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } open(): void { this.native.open(); diff --git a/src/lib/QtWidgets/QGridLayout.ts b/src/lib/QtWidgets/QGridLayout.ts index f42b30fec..582f91b2d 100644 --- a/src/lib/QtWidgets/QGridLayout.ts +++ b/src/lib/QtWidgets/QGridLayout.ts @@ -13,7 +13,7 @@ export class QGridLayout extends NodeLayout { native = new addon.QGridLayout(); } super(native); - this.nodeParent = parent; + this.setNodeParent(parent); this.native = native; } addWidget(widget: NodeWidget, row = 0, col = 0, rowSpan = 1, colSpan = 1): void { diff --git a/src/lib/QtWidgets/QGroupBox.ts b/src/lib/QtWidgets/QGroupBox.ts index fcc64e137..ce25af406 100644 --- a/src/lib/QtWidgets/QGroupBox.ts +++ b/src/lib/QtWidgets/QGroupBox.ts @@ -20,7 +20,7 @@ export class QGroupBox extends NodeWidget { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } alignment(): AlignmentFlag { return this.native.alignment(); diff --git a/src/lib/QtWidgets/QLabel.ts b/src/lib/QtWidgets/QLabel.ts index 6baad2393..ac92f7f31 100644 --- a/src/lib/QtWidgets/QLabel.ts +++ b/src/lib/QtWidgets/QLabel.ts @@ -23,7 +23,7 @@ export class QLabel extends NodeWidget { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } setAlignment(alignment: AlignmentFlag): void { this.native.setAlignment(alignment); diff --git a/src/lib/QtWidgets/QLineEdit.ts b/src/lib/QtWidgets/QLineEdit.ts index e78415277..16ac53f87 100644 --- a/src/lib/QtWidgets/QLineEdit.ts +++ b/src/lib/QtWidgets/QLineEdit.ts @@ -31,7 +31,7 @@ export class QLineEdit extends NodeWidget { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } setText(text: string): void { // react:✓ diff --git a/src/lib/QtWidgets/QMainWindow.ts b/src/lib/QtWidgets/QMainWindow.ts index c2075f10b..b302e28bb 100644 --- a/src/lib/QtWidgets/QMainWindow.ts +++ b/src/lib/QtWidgets/QMainWindow.ts @@ -21,7 +21,7 @@ export class QMainWindow extends NodeWidget { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); this.setLayout = (parentLayout: NodeLayout): void => { if (this.centralWidget) { diff --git a/src/lib/QtWidgets/QMenu.ts b/src/lib/QtWidgets/QMenu.ts index 739996f6a..0891e3248 100644 --- a/src/lib/QtWidgets/QMenu.ts +++ b/src/lib/QtWidgets/QMenu.ts @@ -19,7 +19,7 @@ export class QMenu extends NodeWidget { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); this.actions = new Set(); } setTitle(title: string): void { diff --git a/src/lib/QtWidgets/QMenuBar.ts b/src/lib/QtWidgets/QMenuBar.ts index 374383c60..b716e8283 100644 --- a/src/lib/QtWidgets/QMenuBar.ts +++ b/src/lib/QtWidgets/QMenuBar.ts @@ -26,7 +26,7 @@ export class QMenuBar extends NodeWidget { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } addMenu(menu: QMenu): void { diff --git a/src/lib/QtWidgets/QPlainTextEdit.ts b/src/lib/QtWidgets/QPlainTextEdit.ts index d22f1e0e0..c760fdd38 100644 --- a/src/lib/QtWidgets/QPlainTextEdit.ts +++ b/src/lib/QtWidgets/QPlainTextEdit.ts @@ -33,7 +33,7 @@ export class QPlainTextEdit extends QAbstractScrollArea { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } setPlainText(text: string | number): void { // react:✓ @@ -68,4 +68,7 @@ export class QPlainTextEdit extends QAbstractScrollArea { lineWrapMode(): LineWrapMode { return this.native.lineWrapMode(); } + insertPlainText(text: string | number): void { + this.native.insertPlainText(`${text}`); + } } diff --git a/src/lib/QtWidgets/QProgressBar.ts b/src/lib/QtWidgets/QProgressBar.ts index 4a2b294b8..fb1319d36 100644 --- a/src/lib/QtWidgets/QProgressBar.ts +++ b/src/lib/QtWidgets/QProgressBar.ts @@ -18,7 +18,7 @@ export class QProgressBar extends NodeWidget { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } setValue(value: number): void { // react:✓ diff --git a/src/lib/QtWidgets/QPushButton.ts b/src/lib/QtWidgets/QPushButton.ts index ba0b97894..a80ac4ba2 100644 --- a/src/lib/QtWidgets/QPushButton.ts +++ b/src/lib/QtWidgets/QPushButton.ts @@ -22,7 +22,7 @@ export class QPushButton extends QAbstractButton { native = new addon.QPushButton(); } super(native); - this.nodeParent = parent; + this.setNodeParent(parent); this.native = native; } setFlat(isFlat: boolean): void { diff --git a/src/lib/QtWidgets/QRadioButton.ts b/src/lib/QtWidgets/QRadioButton.ts index 6eace9806..0eb46c52f 100644 --- a/src/lib/QtWidgets/QRadioButton.ts +++ b/src/lib/QtWidgets/QRadioButton.ts @@ -18,6 +18,6 @@ export class QRadioButton extends QAbstractButton { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); } } diff --git a/src/lib/QtWidgets/QScrollArea.ts b/src/lib/QtWidgets/QScrollArea.ts index b4808c7c6..576695492 100644 --- a/src/lib/QtWidgets/QScrollArea.ts +++ b/src/lib/QtWidgets/QScrollArea.ts @@ -19,7 +19,7 @@ export class QScrollArea extends QAbstractScrollArea { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); this.setWidgetResizable(true); } setWidget(widget: NodeWidget): void { diff --git a/src/lib/QtWidgets/QSpinBox.ts b/src/lib/QtWidgets/QSpinBox.ts index f1893d086..7db48c31f 100644 --- a/src/lib/QtWidgets/QSpinBox.ts +++ b/src/lib/QtWidgets/QSpinBox.ts @@ -18,7 +18,7 @@ export class QSpinBox extends NodeWidget { native = new addon.QSpinBox(); } super(native); - this.nodeParent = parent; + this.setNodeParent(parent); this.native = native; } setPrefix(prefix: string): void { diff --git a/src/lib/QtWidgets/QStackedWidget.ts b/src/lib/QtWidgets/QStackedWidget.ts index 6cadcc7e8..5e31c0c26 100644 --- a/src/lib/QtWidgets/QStackedWidget.ts +++ b/src/lib/QtWidgets/QStackedWidget.ts @@ -18,7 +18,7 @@ export class QStackedWidget extends NodeWidget { native = new addon.QStackedWidget(); } super(native); - this.nodeParent = parent; + this.setNodeParent(parent); this.native = native; } diff --git a/src/lib/QtWidgets/QTabWidget.ts b/src/lib/QtWidgets/QTabWidget.ts index 91196ae03..61825c619 100644 --- a/src/lib/QtWidgets/QTabWidget.ts +++ b/src/lib/QtWidgets/QTabWidget.ts @@ -24,7 +24,7 @@ export class QTabWidget extends NodeWidget { native = new addon.QTabWidget(); } super(native); - this.nodeParent = parent; + this.setNodeParent(parent); this.tabs = []; this.native = native; } diff --git a/src/lib/QtWidgets/QTableWidget.ts b/src/lib/QtWidgets/QTableWidget.ts index 8fa89e92a..b1a0c591a 100644 --- a/src/lib/QtWidgets/QTableWidget.ts +++ b/src/lib/QtWidgets/QTableWidget.ts @@ -38,7 +38,7 @@ export class QTableWidget extends QAbstractScrollArea { } super(native); this.native = native; - this.nodeParent = parent; + this.setNodeParent(parent); this.items = new Set(); } selectedRanges(): Range[] { diff --git a/src/lib/QtWidgets/QToolButton.ts b/src/lib/QtWidgets/QToolButton.ts index 8a52708d8..101d8314a 100644 --- a/src/lib/QtWidgets/QToolButton.ts +++ b/src/lib/QtWidgets/QToolButton.ts @@ -33,7 +33,7 @@ export class QToolButton extends QAbstractButton { native = new addon.QToolButton(); } super(native); - this.nodeParent = parent; + this.setNodeParent(parent); this.native = native; } setArrowType(type: ArrowType): void { diff --git a/src/lib/QtWidgets/QTreeWidget.ts b/src/lib/QtWidgets/QTreeWidget.ts new file mode 100644 index 000000000..2fc6519a9 --- /dev/null +++ b/src/lib/QtWidgets/QTreeWidget.ts @@ -0,0 +1,43 @@ +import addon from '../utils/addon'; +import { NodeWidget } from './QWidget'; +import { BaseWidgetEvents } from '../core/EventWidget'; +import { NativeElement } from '../core/Component'; +import { QAbstractScrollArea, QTreeWidgetItem } from '../..'; + +export const QTreeWidgetEvents = Object.freeze({ + ...BaseWidgetEvents, + itemSelectionChanged: 'itemSelectionChanged', +}); + +export class QTreeWidget extends QAbstractScrollArea { + native: NativeElement; + topLevelItems: Set; + constructor(parent?: NodeWidget) { + let native; + if (parent) { + native = new addon.QTreeWidget(parent.native); + } else { + native = new addon.QTreeWidget(); + } + super(native); + this.native = native; + this.setNodeParent(parent); + this.topLevelItems = new Set(); + } + + addTopLevelItem(item: QTreeWidgetItem): void { + this.topLevelItems.add(item); + this.native.addTopLevelItem(item.native); + } + + setHeaderHidden(hide: boolean): void { + this.native.setProperty('headerHidden', hide); + } + + selectedItems(): QTreeWidgetItem[] { + const nativeItems = this.native.selectedItems(); + return nativeItems.map(function(eachItem: QTreeWidgetItem) { + return new QTreeWidgetItem(eachItem); + }); + } +} diff --git a/src/lib/QtWidgets/QTreeWidgetItem.ts b/src/lib/QtWidgets/QTreeWidgetItem.ts new file mode 100644 index 000000000..61c998660 --- /dev/null +++ b/src/lib/QtWidgets/QTreeWidgetItem.ts @@ -0,0 +1,55 @@ +import addon from '../utils/addon'; +import { Component, NativeElement } from '../core/Component'; +import { checkIfNativeElement, QTreeWidget } from '../..'; + +export class QTreeWidgetItem extends Component { + native: NativeElement; + + constructor(parent?: NativeElement | QTreeWidgetItem | QTreeWidget | string[], strings?: string[]) { + super(); + if (checkIfNativeElement(parent)) { + this.native = parent as NativeElement; + } else { + if (parent instanceof QTreeWidgetItem || parent instanceof QTreeWidget) { + this.setNodeParent(parent); + const type = parent instanceof QTreeWidgetItem ? 'item' : 'tree'; + if (strings) { + this.native = new addon.QTreeWidgetItem(parent.native, strings, type); + } else { + this.native = new addon.QTreeWidgetItem(parent.native, type); + } + } else if (Array.isArray(parent)) { + const strings = parent; + this.native = new addon.QTreeWidgetItem(strings); + } else { + this.native = new addon.QTreeWidgetItem(); + } + } + } + setText(column: number, text: string): void { + this.native.setText(column, text); + } + parent(): QTreeWidgetItem | undefined { + const parent = this.native.parent(); + if (parent) { + return new QTreeWidgetItem(parent); + } else { + return undefined; + } + } + childCount(): number { + return this.native.childCount(); + } + child(index: number): QTreeWidgetItem | undefined { + return this.native.child(index); + } + text(column: number): string { + return this.native.text(column); + } + setSelected(selected: boolean): void { + this.native.setSelected(selected); + } + setExpanded(expanded: boolean): void { + this.native.setExpanded(expanded); + } +} diff --git a/src/lib/QtWidgets/QWidget.ts b/src/lib/QtWidgets/QWidget.ts index 6f39ac163..b8fcd5a03 100644 --- a/src/lib/QtWidgets/QWidget.ts +++ b/src/lib/QtWidgets/QWidget.ts @@ -193,7 +193,7 @@ export class QWidget extends NodeWidget { native = new addon.QWidget(); } super(native); - this.nodeParent = parent; + this.setNodeParent(parent); this.native = native; } } diff --git a/src/lib/core/Component.ts b/src/lib/core/Component.ts index 75cef676a..49ee1cd44 100644 --- a/src/lib/core/Component.ts +++ b/src/lib/core/Component.ts @@ -1,6 +1,10 @@ export type NativeElement = { type: 'native'; [key: string]: any }; export abstract class Component { - protected nodeChildren = new Set(); - protected nodeParent?: Component; + nodeChildren = new Set(); + nodeParent?: Component; + setNodeParent(parent?: Component): void { + this.nodeParent = parent; + parent?.nodeChildren.add(this); + } abstract native: NativeElement; }