diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f1bae2ba..cdd10e847 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QColor/qcolor_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QApplication/qapplication_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QClipboard/qclipboard_wrap.cpp" + "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QDrag/qdrag_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QEvent/QKeyEvent/qkeyevent_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QEvent/QMouseEvent/qmouseevent_wrap.cpp" "${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QEvent/QWheelEvent/qwheelevent_wrap.cpp" @@ -141,6 +142,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/core/FlexLayout/flexlayout.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtGui/QMovie/nmovie.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtGui/QApplication/napplication.hpp" + "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtGui/QDrag/ndrag.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QWidget/nwidget.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QDialog/ndialog.hpp" "${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QLabel/nlabel.hpp" diff --git a/src/cpp/include/nodegui/QtGui/QDrag/ndrag.hpp b/src/cpp/include/nodegui/QtGui/QDrag/ndrag.hpp new file mode 100644 index 000000000..c2d41846e --- /dev/null +++ b/src/cpp/include/nodegui/QtGui/QDrag/ndrag.hpp @@ -0,0 +1,25 @@ +#pragma once +#include + +#include "Extras/Export/export.h" +#include "QtCore/QObject/qobject_macro.h" +#include "core/Events/eventwidget.h" +#include "core/Events/eventwidget_macro.h" + +class DLL_EXPORT NDrag : public QDrag, public EventWidget { + Q_OBJECT + EVENTWIDGET_IMPLEMENTATIONS(QDrag) + public: + using QDrag::QDrag; + + void connectSignalsToEventEmitter() { + QOBJECT_SIGNALS + QObject::connect(this, &QDrag::actionChanged, [=](Qt::DropAction action) { + Napi::Env env = this->emitOnNode.Env(); + Napi::HandleScope scope(env); + this->emitOnNode.Call( + {Napi::String::New(env, "actionChanged"), + Napi::Number::From(env, static_cast(action))}); + }); + } +}; diff --git a/src/cpp/include/nodegui/QtGui/QDrag/qdrag_wrap.h b/src/cpp/include/nodegui/QtGui/QDrag/qdrag_wrap.h new file mode 100644 index 000000000..da688bd08 --- /dev/null +++ b/src/cpp/include/nodegui/QtGui/QDrag/qdrag_wrap.h @@ -0,0 +1,53 @@ +#pragma once + +#include + +#include + +#include "Extras/Export/export.h" +#include "QtGui/QDrag/ndrag.hpp" +#include "core/Component/component_macro.h" + +/* +- Note that setMimeData() assigns ownership of the QMimeData object to the QDrag +object. +- The QDrag must be constructed on the heap with a parent QObject to ensure that +Qt can clean up after the drag and drop operation has been completed +*/ +class DLL_EXPORT QDragWrap : public Napi::ObjectWrap { + COMPONENT_WRAPPED_METHODS_DECLARATION + + private: + // A guarded pointer, QPointer, behaves like a normal C++ pointer T *, + // except that it is automatically cleared when the referenced object is + // destroyed (unlike normal C++ pointers, which become "dangling pointers" in + // such cases). T must be a subclass of QObject. + QPointer instance; + + public: + static Napi::Object init(Napi::Env env, Napi::Object exports); + QDragWrap(const Napi::CallbackInfo& info); + ~QDragWrap(); + NDrag* getInternalInstance(); + // class constructor + static Napi::FunctionReference constructor; + + // wrapped methods + Napi::Value defaultAction(const Napi::CallbackInfo& info); + Napi::Value dragCursor(const Napi::CallbackInfo& info); + Napi::Value exec(const Napi::CallbackInfo& info); + Napi::Value hotSpot(const Napi::CallbackInfo& info); + Napi::Value pixmap(const Napi::CallbackInfo& info); + Napi::Value setDragCursor(const Napi::CallbackInfo& info); + Napi::Value setHotSpot(const Napi::CallbackInfo& info); + Napi::Value setPixmap(const Napi::CallbackInfo& info); + Napi::Value supportedActions(const Napi::CallbackInfo& info); + Napi::Value mimeData(const Napi::CallbackInfo& info); + Napi::Value setMimeData(const Napi::CallbackInfo& info); + Napi::Value source(const Napi::CallbackInfo& info); + Napi::Value target(const Napi::CallbackInfo& info); +}; + +namespace StaticQDragWrapMethods { +DLL_EXPORT Napi::Value cancel(const Napi::CallbackInfo& info); +} diff --git a/src/cpp/lib/QtGui/QDrag/qdrag_wrap.cpp b/src/cpp/lib/QtGui/QDrag/qdrag_wrap.cpp new file mode 100644 index 000000000..f6ea1a6be --- /dev/null +++ b/src/cpp/lib/QtGui/QDrag/qdrag_wrap.cpp @@ -0,0 +1,221 @@ +#include "QtGui/QDrag/qdrag_wrap.h" + +#include "Extras/Utils/nutils.h" +#include "QtCore/QMimeData/qmimedata_wrap.h" +#include "QtCore/QObject/qobject_wrap.h" +#include "QtCore/QPoint/qpoint_wrap.h" +#include "QtGui/QPixmap/qpixmap_wrap.h" + +Napi::FunctionReference QDragWrap::constructor; + +Napi::Object QDragWrap::init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + char CLASSNAME[] = "QDrag"; + Napi::Function func = DefineClass( + env, CLASSNAME, + + {InstanceMethod("defaultAction", &QDragWrap::defaultAction), + InstanceMethod("dragCursor", &QDragWrap::dragCursor), + InstanceMethod("exec", &QDragWrap::exec), + InstanceMethod("hotSpot", &QDragWrap::hotSpot), + InstanceMethod("pixmap", &QDragWrap::pixmap), + InstanceMethod("setDragCursor", &QDragWrap::setDragCursor), + InstanceMethod("setHotSpot", &QDragWrap::setHotSpot), + InstanceMethod("setPixmap", &QDragWrap::setPixmap), + InstanceMethod("supportedActions", &QDragWrap::supportedActions), + InstanceMethod("mimeData", &QDragWrap::mimeData), + InstanceMethod("setMimeData", &QDragWrap::setMimeData), + InstanceMethod("source", &QDragWrap::source), + InstanceMethod("target", &QDragWrap::target), + StaticMethod("cancel", &StaticQDragWrapMethods::cancel), + + COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE(QDragWrap)}); + constructor = Napi::Persistent(func); + exports.Set(CLASSNAME, func); + return exports; +} + +NDrag* QDragWrap::getInternalInstance() { return this->instance; } + +QDragWrap::QDragWrap(const Napi::CallbackInfo& info) + : Napi::ObjectWrap(info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + if (info.Length() == 1) { + Napi::Object wrap0_0 = info[0].As(); + QObjectWrap* wrap0_1 = Napi::ObjectWrap::Unwrap(wrap0_0); + QObject* dragSource = wrap0_1->getInternalInstance(); + this->instance = new NDrag(dragSource); + } else { + Napi::TypeError::New(env, "Wrong number of arguments") + .ThrowAsJavaScriptException(); + } + this->rawData = extrautils::configureComponent(this->getInternalInstance()); +} + +QDragWrap::~QDragWrap() { + // Do not destroy instance here. It will be done by Qt Event loop. + extrautils::safeDelete(this->instance); +} + +// Instance Methods Here + +Napi::Value QDragWrap::defaultAction(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + return Napi::Number::New(env, this->instance->defaultAction()); +} + +Napi::Value QDragWrap::dragCursor(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Qt::DropAction input0 = + (Qt::DropAction)info[0].As().Int32Value(); + + QPixmap ret = this->instance->dragCursor(input0); + auto instance = QPixmapWrap::constructor.New( + {Napi::External::New(env, new QPixmap(ret))}); + return instance; +} + +Napi::Value QDragWrap::exec(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + if (info.Length() < 2) { + Qt::DropActions input0 = + (Qt::DropActions)info[0].As().Int32Value(); + return Napi::Number::New(env, this->instance->exec(input0)); + } + Qt::DropActions input0 = + (Qt::DropActions)info[0].As().Int32Value(); + Qt::DropAction input1 = + (Qt::DropAction)info[1].As().Int32Value(); + return Napi::Number::New(env, this->instance->exec(input0, input1)); +} + +Napi::Value QDragWrap::hotSpot(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + QPoint ret = this->instance->hotSpot(); + auto instance = QPointWrap::constructor.New( + {Napi::External::New(env, new QPoint(ret))}); + return instance; +} + +Napi::Value QDragWrap::pixmap(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + QPixmap ret = this->instance->pixmap(); + auto instance = QPixmapWrap::constructor.New( + {Napi::External::New(env, new QPixmap(ret))}); + return instance; +} + +Napi::Value QDragWrap::setDragCursor(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object wrap0_0 = info[0].As(); + QPixmapWrap* wrap0_1 = Napi::ObjectWrap::Unwrap(wrap0_0); + QPixmap* input0 = wrap0_1->getInternalInstance(); + Qt::DropAction input1 = + (Qt::DropAction)info[1].As().Int32Value(); + this->instance->setDragCursor(*input0, input1); + return env.Null(); +} + +Napi::Value QDragWrap::setHotSpot(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object wrap0_0 = info[0].As(); + QPointWrap* wrap0_1 = Napi::ObjectWrap::Unwrap(wrap0_0); + QPoint* input0 = wrap0_1->getInternalInstance(); + this->instance->setHotSpot(*input0); + return env.Null(); +} + +Napi::Value QDragWrap::setPixmap(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object wrap0_0 = info[0].As(); + QPixmapWrap* wrap0_1 = Napi::ObjectWrap::Unwrap(wrap0_0); + QPixmap* input0 = wrap0_1->getInternalInstance(); + this->instance->setPixmap(*input0); + return env.Null(); +} + +Napi::Value QDragWrap::supportedActions(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + return Napi::Number::New(env, this->instance->supportedActions()); +} + +// Static Methods here +Napi::Value StaticQDragWrapMethods::cancel(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + QDrag::cancel(); + return env.Null(); +} + +Napi::Value QDragWrap::mimeData(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + const QMimeData* ret = this->instance->mimeData(); + + QMimeData* clone = new QMimeData(); + // QMimeData has no copy constructor so I do this + QMimeDataWrap::cloneFromMimeDataToData((QMimeData*)ret, clone); + auto instance = QMimeDataWrap::constructor.New( + {Napi::External::New(env, clone)}); + return instance; +} + +Napi::Value QDragWrap::setMimeData(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + Napi::Object wrap0_0 = info[0].As(); + QMimeDataWrap* wrap0_1 = Napi::ObjectWrap::Unwrap(wrap0_0); + QMimeData* input0 = wrap0_1->getInternalInstance(); + + QMimeData* clone = new QMimeData(); + // QMimeData has no copy constructor so I do this + QMimeDataWrap::cloneFromMimeDataToData((QMimeData*)input0, clone); + // Ownership of the data (the clone) is transferred to the QDrag object + // While our original QMimeData should be garbage collected.. I guessss? + this->instance->setMimeData(clone); + return env.Null(); +} + +// This function crashes the application +Napi::Value QDragWrap::source(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + QObject* source = this->instance->source(); + // We can likely call a wrap directly since QObjectWrap is smart and uses + // QPointer? + auto instance = + QObjectWrap::constructor.New({Napi::External::New(env, source)}); + return instance; +} + +// This function crashes the application +Napi::Value QDragWrap::target(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + Napi::HandleScope scope(env); + + QObject* target = this->instance->target(); + // We can likely call a wrap directly since QObjectWrap is smart and uses + // QPointer? + auto instance = + QObjectWrap::constructor.New({Napi::External::New(env, target)}); + return instance; +} \ No newline at end of file diff --git a/src/cpp/main.cpp b/src/cpp/main.cpp index 519dcea0d..5bd101b22 100644 --- a/src/cpp/main.cpp +++ b/src/cpp/main.cpp @@ -20,6 +20,7 @@ #include "QtGui/QClipboard/qclipboard_wrap.h" #include "QtGui/QColor/qcolor_wrap.h" #include "QtGui/QCursor/qcursor_wrap.h" +#include "QtGui/QDrag/qdrag_wrap.h" #include "QtGui/QEvent/QDragLeaveEvent/qdragleaveevent_wrap.h" #include "QtGui/QEvent/QDragMoveEvent/qdragmoveevent_wrap.h" #include "QtGui/QEvent/QDropEvent/qdropevent_wrap.h" @@ -180,6 +181,7 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) { QMouseEventWrap::init(env, exports); QWheelEventWrap::init(env, exports); QTabletEventWrap::init(env, exports); + QDragWrap::init(env, exports); QDropEventWrap::init(env, exports); QDragMoveEventWrap::init(env, exports); QDragLeaveEventWrap::init(env, exports); diff --git a/src/index.ts b/src/index.ts index 6290af347..be2c500ac 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,7 @@ export { QMouseEvent } from './lib/QtGui/QEvent/QMouseEvent'; export { QWheelEvent } from './lib/QtGui/QEvent/QWheelEvent'; export { QNativeGestureEvent } from './lib/QtGui/QEvent/QNativeGestureEvent'; export { QTabletEvent } from './lib/QtGui/QEvent/QTabletEvent'; +export { QDrag } from './lib/QtGui/QDrag'; export { QDropEvent } from './lib/QtGui/QEvent/QDropEvent'; export { QDragMoveEvent } from './lib/QtGui/QEvent/QDragMoveEvent'; export { QDragLeaveEvent } from './lib/QtGui/QEvent/QDragLeaveEvent'; diff --git a/src/lib/QtGui/QDrag.ts b/src/lib/QtGui/QDrag.ts new file mode 100644 index 000000000..869ac640e --- /dev/null +++ b/src/lib/QtGui/QDrag.ts @@ -0,0 +1,137 @@ +import { NativeElement, Component } from '../core/Component'; +import addon from '../utils/addon'; +import { checkIfNativeElement } from '../utils/helpers'; +import { QObject } from '../QtCore/QObject'; +import { DropAction } from '../QtEnums'; +import { QPixmap } from './QPixmap'; +import { QPoint } from '../QtCore/QPoint'; +import { QMimeData } from '../QtCore/QMimeData'; + +/** + * description + */ +export class QDrag extends Component { + native: NativeElement; + constructor(arg?: NativeElement | QObject) { + super(); + if (!arg) { + this.native = new addon.QDrag(); + } else { + const isNative = checkIfNativeElement(arg); + if (isNative) { + this.native = arg as NativeElement; + } else if (arg.native) { + this.native = new addon.QDrag(arg.native); + } else { + this.native = new addon.QDrag(); + } + } + } + + /** + Returns the default proposed drop action for this drag operation. + */ + defaultAction(): DropAction { + return this.native.defaultAction(); + } + + /** + Returns the drag cursor for the action. + */ + dragCursor(action: DropAction): QPixmap { + return new QPixmap(this.native.dragCursor(action)); + } + + /** + Starts the drag and drop operation and returns a value indicating the requested drop action when it is completed. The drop actions that the user can choose from are specified in supportedActions. The default proposed action will be selected among the allowed actions in the following order: Move, Copy and Link. + */ + exec(supportedActions: number = DropAction.MoveAction, defaultDropAction?: DropAction): DropAction { + if (defaultDropAction) { + return this.native.exec(supportedActions, defaultDropAction); + } else { + return this.native.exec(supportedActions); + } + } + + /** + Returns the position of the hot spot relative to the top-left corner of the cursor. + */ + hotSpot(): QPoint { + return new QPoint(this.native.hotSpot()); + } + + /** + Returns the pixmap used to represent the data in a drag and drop operation. + */ + pixmap(): QPixmap { + return new QPixmap(this.native.pixmap()); + } + + /** + Sets the drag cursor for the action. This allows you to override the default native cursors. To revert to using the native cursor for action pass in a null QPixmap as cursor. + */ + setDragCursor(cursor: QPixmap, action: DropAction): void { + return this.native.setDragCursor(cursor.native, action); + } + + /** + Sets the position of the hot spot relative to the top-left corner of the pixmap used to the point specified by hotspot. + */ + setHotSpot(hotspot: QPoint): void { + return this.native.setHotSpot(hotspot.native); + } + + /** + Sets pixmap as the pixmap used to represent the data in a drag and drop operation. You can only set a pixmap before the drag is started. + */ + setPixmap(pixmap: QPixmap): void { + return this.native.setPixmap(pixmap.native); + } + + /** + Returns the set of possible drop actions for this drag operation. + */ + supportedActions(): number { + return this.native.supportedActions(); + } + + /** + Cancels a drag operation initiated by Qt. + */ + static cancel(): void { + return addon.QDrag.cancel(); + } + + //Manaully implemented methods + /** + * Returns the MIME data that is encapsulated by the drag object. + */ + mimeData(): QMimeData { + return new QMimeData(this.native.mimeData()); + } + /** + * Sets the data to be sent to the given MIME data. + * Ownership of the data is transferred to the QDrag object. + */ + setMimeData(data: QMimeData): void { + return this.native.setMimeData(data.native); + } + + /* + * Returns the source of the drag object. This is the widget where the drag and drop operation originated. + + THIS FUNCTION CRASHES THE APPLICATION, NEEDS REIMPLEMENTATION + */ + // source(): QObject { + // return new QObject(this.native.source()); + // } + + /* + * Returns the target of the drag and drop operation. This is the widget where the drag object was dropped. + + THIS FUNCTION CRASHES THE APPLICATION, NEEDS REIMPLEMENTATION + */ + // target(): QObject { + // return new QObject(this.native.target()); + // } +}