Add QFileDialog (#256)

* Add QFileDialog

* fix missing return types
This commit is contained in:
slidinghotdog 2019-12-09 16:11:00 -03:00 committed by Atul R
parent d79ba0620d
commit 4703dd4d27
15 changed files with 398 additions and 8 deletions

View File

@ -54,6 +54,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QWidget/qwidget_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QBoxLayout/qboxlayout_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QComboBox/qcombobox_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QFileDialog/qfiledialog_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QGridLayout/qgridlayout_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QDial/qdial_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtWidgets/QLabel/qlabel_wrap.cpp"
@ -83,6 +84,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QLabel/nlabel.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QCheckBox/ncheckbox.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QDial/ndial.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QFileDialog/nfiledialog.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QLineEdit/nlineedit.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QMainWindow/nmainwindow.hpp"
"${PROJECT_SOURCE_DIR}/src/cpp/include/nodegui/QtWidgets/QProgressBar/nprogressbar.hpp"

View File

@ -0,0 +1,98 @@
#pragma once
#include <QFileDialog>
#include "core/NodeWidget/nodewidget.h"
#include "napi.h"
class NFileDialog : public QFileDialog, public NodeWidget {
public:
Q_OBJECT
NODEWIDGET_IMPLEMENTATIONS(QFileDialog)
using QFileDialog::QFileDialog;
void connectWidgetSignalsToEventEmitter() {
// Qt Connects: Implement all signal connects here
QObject::connect(
this, &QFileDialog::currentChanged, [=](const QString &path) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call({Napi::String::New(env, "currentChanged"),
Napi::String::New(env, path.toStdString())});
});
QObject::connect(
this, &QFileDialog::currentUrlChanged, [=](const QUrl &url) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call(
{Napi::String::New(env, "currentUrlChanged"),
Napi::String::New(env, url.toString().toStdString())});
});
QObject::connect(this, &QFileDialog::directoryEntered,
[=](const QString &directory) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call(
{Napi::String::New(env, "directoryEntered"),
Napi::String::New(env, directory.toStdString())});
});
QObject::connect(
this, &QFileDialog::directoryUrlEntered, [=](const QUrl &directory) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call(
{Napi::String::New(env, "directoryUrlEntered"),
Napi::String::New(env, directory.toString().toStdString())});
});
QObject::connect(
this, &QFileDialog::fileSelected, [=](const QString &file) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call({Napi::String::New(env, "fileSelected"),
Napi::String::New(env, file.toStdString())});
});
QObject::connect(
this, &QFileDialog::filesSelected, [=](const QStringList &selected) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
Napi::Array selectedNapi = Napi::Array::New(env, selected.size());
for (int i = 0; i < selected.size(); i++) {
selectedNapi[i] = Napi::String::New(env, selected[i].toStdString());
}
this->emitOnNode.Call(
{Napi::String::New(env, "filesSelected"), selectedNapi});
});
QObject::connect(
this, &QFileDialog::filterSelected, [=](const QString &filter) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call({Napi::String::New(env, "filterSelected"),
Napi::String::New(env, filter.toStdString())});
});
QObject::connect(this, &QFileDialog::urlSelected, [=](const QUrl &url) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
this->emitOnNode.Call(
{Napi::String::New(env, "urlSelected"),
Napi::String::New(env, url.toString().toStdString())});
});
QObject::connect(
this, &QFileDialog::urlsSelected, [=](const QList<QUrl> &urls) {
Napi::Env env = this->emitOnNode.Env();
Napi::HandleScope scope(env);
Napi::Array urlsNapi = Napi::Array::New(env, urls.size());
for (int i = 0; i < urls.size(); i++) {
urlsNapi[i] =
Napi::String::New(env, urls[i].toString().toStdString());
}
this->emitOnNode.Call(
{Napi::String::New(env, "urlsSelected"), urlsNapi});
});
}
};

View File

@ -0,0 +1,32 @@
#pragma once
#include <napi.h>
#include <stdlib.h>
#include <QPointer>
#include "Extras/Utils/nutils.h"
#include "QtWidgets/QFileDialog/nfiledialog.hpp"
#include "QtWidgets/QWidget/qwidget_macro.h"
class QFileDialogWrap : public Napi::ObjectWrap<QFileDialogWrap> {
private:
QPointer<NFileDialog> instance;
public:
static Napi::Object init(Napi::Env env, Napi::Object exports);
QFileDialogWrap(const Napi::CallbackInfo& info);
~QFileDialogWrap();
NFileDialog* getInternalInstance();
// class constructor
static Napi::FunctionReference constructor;
// wrapped methods
Napi::Value open(const Napi::CallbackInfo& info);
Napi::Value supportedSchemes(const Napi::CallbackInfo& info);
Napi::Value setSupportedSchemes(const Napi::CallbackInfo& info);
Napi::Value labelText(const Napi::CallbackInfo& info);
Napi::Value setLabelText(const Napi::CallbackInfo& info);
Napi::Value setOption(const Napi::CallbackInfo& info);
QWIDGET_WRAPPED_METHODS_DECLARATION
};

View File

@ -0,0 +1,132 @@
#include "QtWidgets/QFileDialog/qfiledialog_wrap.h"
#include <QWidget>
#include "Extras/Utils/nutils.h"
#include "QtWidgets/QWidget/qwidget_wrap.h"
Napi::FunctionReference QFileDialogWrap::constructor;
Napi::Object QFileDialogWrap::init(Napi::Env env, Napi::Object exports) {
Napi::HandleScope scope(env);
char CLASSNAME[] = "QFileDialog";
Napi::Function func = DefineClass(
env, CLASSNAME,
{InstanceMethod("open", &QFileDialogWrap::open),
InstanceMethod("supportedSchemes", &QFileDialogWrap::supportedSchemes),
InstanceMethod("setSupportedSchemes",
&QFileDialogWrap::setSupportedSchemes),
InstanceMethod("labelText", &QFileDialogWrap::labelText),
InstanceMethod("setLabelText", &QFileDialogWrap::setLabelText),
InstanceMethod("setOption", &QFileDialogWrap::setOption),
QWIDGET_WRAPPED_METHODS_EXPORT_DEFINE(QFileDialogWrap)});
constructor = Napi::Persistent(func);
exports.Set(CLASSNAME, func);
return exports;
}
NFileDialog* QFileDialogWrap::getInternalInstance() { return this->instance; }
QFileDialogWrap::~QFileDialogWrap() { extrautils::safeDelete(this->instance); }
QFileDialogWrap::QFileDialogWrap(const Napi::CallbackInfo& info)
: Napi::ObjectWrap<QFileDialogWrap>(info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if (info.Length() == 4) {
Napi::Object parentObject = info[0].As<Napi::Object>();
QWidgetWrap* parentWidgetWrap =
Napi::ObjectWrap<QWidgetWrap>::Unwrap(parentObject);
QWidget* parent = parentWidgetWrap->getInternalInstance();
QString caption =
QString::fromUtf8(info[1].As<Napi::String>().Utf8Value().c_str());
QString directory =
QString::fromUtf8(info[2].As<Napi::String>().Utf8Value().c_str());
QString filter =
QString::fromUtf8(info[3].As<Napi::String>().Utf8Value().c_str());
this->instance = new NFileDialog(parent, caption, directory, filter);
} else if (info.Length() == 0) {
this->instance = new NFileDialog();
} else {
Napi::TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
}
this->rawData = extrautils::configureQWidget(
this->getInternalInstance(), this->getInternalInstance()->getFlexNode(),
false);
}
Napi::Value QFileDialogWrap::open(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
this->instance->open();
return env.Null();
}
Napi::Value QFileDialogWrap::supportedSchemes(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
QStringList schemes = this->instance->supportedSchemes();
Napi::Array schemesNapi = Napi::Array::New(env, schemes.size());
for (int i = 0; i < schemes.size(); i++) {
schemesNapi[i] = Napi::String::New(env, schemes[i].toStdString());
}
return schemesNapi;
}
Napi::Value QFileDialogWrap::setSupportedSchemes(
const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::Array schemesNapi = info[0].As<Napi::Array>();
QList<QString> list;
for (int i = 0; i < schemesNapi.Length(); i++) {
Napi::Value schemeNapi = schemesNapi[i];
list.append(schemeNapi.As<Napi::String>().Utf8Value().c_str());
}
QStringList schemes = QStringList(list);
this->instance->setSupportedSchemes(schemes);
return env.Null();
}
Napi::Value QFileDialogWrap::labelText(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
int labelInt = info[0].As<Napi::Number>().Int32Value();
QFileDialog::DialogLabel label =
static_cast<QFileDialog::DialogLabel>(labelInt);
QString labelString = this->instance->labelText(label);
return Napi::String::New(env, labelString.toStdString());
}
Napi::Value QFileDialogWrap::setLabelText(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
int labelInt = info[0].As<Napi::Number>().Int32Value();
QFileDialog::DialogLabel label =
static_cast<QFileDialog::DialogLabel>(labelInt);
std::string textString = info[1].As<Napi::String>().Utf8Value();
QString text = QString::fromUtf8(textString.c_str());
this->instance->setLabelText(label, text);
return env.Null();
}
Napi::Value QFileDialogWrap::setOption(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
int optionInt = info[0].As<Napi::Number>().Int32Value();
QFileDialog::Option option = static_cast<QFileDialog::Option>(optionInt);
bool on = info[1].As<Napi::Boolean>().Value();
this->instance->setOption(option, on);
return env.Null();
}

View File

@ -20,6 +20,7 @@
#include "QtWidgets/QCheckBox/qcheckbox_wrap.h"
#include "QtWidgets/QComboBox/qcombobox_wrap.h"
#include "QtWidgets/QDial/qdial_wrap.h"
#include "QtWidgets/QFileDialog/qfiledialog_wrap.h"
#include "QtWidgets/QGridLayout/qgridlayout_wrap.h"
#include "QtWidgets/QGroupBox/qgroupbox_wrap.h"
#include "QtWidgets/QLabel/qlabel_wrap.h"
@ -64,6 +65,7 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) {
QCursorWrap::init(env, exports);
QComboBoxWrap::init(env, exports);
QBoxLayoutWrap::init(env, exports);
QFileDialogWrap::init(env, exports);
QGridLayoutWrap::init(env, exports);
QGroupBoxWrap::init(env, exports);
FlexLayoutWrap::init(env, exports);

View File

@ -1,23 +1,33 @@
import { QMainWindow, QPushButton, QLabel, QWidget, FlexLayout, QComboBox, QComboBoxEvents } from './index';
import {
QMainWindow,
QPushButton,
QLabel,
QWidget,
FlexLayout,
QFileDialog,
QFileDialogEvents,
FileMode,
DialogLabel,
} from './index';
const win = new QMainWindow();
const center = new QWidget();
const button = new QPushButton();
button.setText('Hello');
button.setText('Open File Dialog');
const hello = new QLabel();
hello.setText('hello text');
const combo = new QComboBox();
combo.addItems(['text1', 'text2', 'text3'])
combo.insertItems(1,['insert1', 'insert2', 'insert3'])
combo.addEventListener(QComboBoxEvents.currentTextChanged, (text)=>hello.setText(text))
const file = new QFileDialog(center, 'Select File', `${process.env.HOME}`);
file.setFileMode(FileMode.ExistingFiles);
file.setLabelText(DialogLabel.Accept, 'New Accept Label!');
file.addEventListener(QFileDialogEvents.filesSelected, (selected: string[]) => console.log('text', selected));
button.addEventListener('clicked', () => file.open());
center.setLayout(new FlexLayout());
center.layout?.addWidget(button);
center.layout?.addWidget(hello);
center.layout?.addWidget(combo);
win.setCentralWidget(center);
win.show();

View File

@ -27,6 +27,7 @@ export { QWidget, QWidgetEvents } from './lib/QtWidgets/QWidget';
export { QCheckBox, QCheckBoxEvents } from './lib/QtWidgets/QCheckBox';
export { QLabel, QLabelEvents } from './lib/QtWidgets/QLabel';
export { QDial, QDialEvents } from './lib/QtWidgets/QDial';
export { QFileDialog, QFileDialogEvents } from './lib/QtWidgets/QFileDialog';
export { QLineEdit, QLineEditEvents, EchoMode } from './lib/QtWidgets/QLineEdit';
export { QMainWindow, QMainWindowEvents } from './lib/QtWidgets/QMainWindow';
export { QProgressBar, QProgressBarEvents } from './lib/QtWidgets/QProgressBar';

View File

@ -0,0 +1,4 @@
export enum AcceptMode {
AcceptOpen = 0,
AcceptSave = 1,
}

View File

@ -0,0 +1,7 @@
export enum DialogLabel {
LookIn = 0,
FileName = 1,
FileType = 2,
Accept = 3,
Reject = 4,
}

View File

@ -0,0 +1,6 @@
export enum FileMode {
AnyFile = 0,
ExistingFile = 1,
Directory = 2,
ExistingFiles = 3,
}

View File

@ -0,0 +1,10 @@
export enum Option {
ShowDirsOnly = 0x00000001,
DontResolveSymlinks = 0x00000002,
DontConfirmOverwrite = 0x00000004,
DontUseNativeDialog = 0x00000010,
ReadOnly = 0x00000020,
HideNameFilterDetails = 0x00000040,
DontUseSheet = 0x00000008,
DontUseCustomDirectoryIcons = 0x00000080,
}

View File

@ -0,0 +1,4 @@
export enum ViewMode {
Detail = 0,
List = 1,
}

View File

@ -1,3 +1,4 @@
export { AcceptMode } from './AcceptMode';
export { AlignmentFlag } from './AlignmentFlag';
export { AnchorPoint } from './AnchorPoint';
export { ApplicationAttribute } from './ApplicationAttribute';
@ -19,12 +20,14 @@ export { CursorMoveStyle } from './CursorMoveStyle';
export { CursorShape } from './CursorShape';
export { DateFormat } from './DateFormat';
export { DayOfWeek } from './DayOfWeek';
export { DialogLabel } from './DialogLabel';
export { Direction } from './Direction';
export { DockWidgetArea } from './DockWidgetArea';
export { DropAction } from './DropAction';
export { Edge } from './Edge';
export { EnterKeyType } from './EnterKeyType';
export { EventPriority } from './EventPriority';
export { FileMode } from './FileMode';
export { FillRule } from './FillRule';
export { FindChildOption } from './FindChildOption';
export { FocusPolicy } from './FocusPolicy';
@ -52,6 +55,7 @@ export { MouseEventFlag } from './MouseEventFlag';
export { MouseEventSource } from './MouseEventSource';
export { NativeGestureType } from './NativeGestureType';
export { NavigationMode } from './NavigationMode';
export { Option } from './Option';
export { Orientation } from './Orientation';
export { ScreenOrientation } from './ScreenOrientation';
export { ScrollBarPolicy } from './ScrollBarPolicy';
@ -75,6 +79,7 @@ export { ToolButtonStyle } from './ToolButtonStyle';
export { TouchPointState } from './TouchPointState';
export { TransformationMode } from './TransformationMode';
export { UIEffect } from './UIEffect';
export { ViewMode } from './ViewMode';
export { WhiteSpaceMode } from './WhiteSpaceMode';
export { WidgetAttribute } from './WidgetAttribute';
export { WindowFrameSection } from './WindowFrameSection';

View File

@ -32,7 +32,7 @@ export class QComboBox extends NodeWidget {
addItems(texts: string[]): void {
this.native.addItems(texts);
}
insertItems(index:number, texts: string[]): void {
insertItems(index: number, texts: string[]): void {
this.native.insertItems(index, texts);
}
currentIndex(): number {

View File

@ -0,0 +1,77 @@
import addon from '../utils/addon';
import { NodeWidget } from './QWidget';
import { BaseWidgetEvents } from '../core/EventWidget';
import { NativeElement } from '../core/Component';
import { AcceptMode, DialogLabel, FileMode, Option, ViewMode } from '../QtEnums';
export const QFileDialogEvents = Object.freeze({
currentChanged: 'currentChanged',
currentUrlChanged: 'currentUrlChanged',
directoryEntered: 'directoryEntered',
directoryUrlEntered: 'directoryUrlEntered',
fileSelected: 'fileSelected',
filesSelected: 'filesSelected',
filterSelected: 'filterSelected',
urlSelected: 'urlSelected',
urlsSelected: 'urlsSelected',
...BaseWidgetEvents,
});
export class QFileDialog extends NodeWidget {
native: NativeElement;
constructor(parent: NodeWidget | undefined = undefined, caption = 'Select File', directory = '', filter = '') {
let native;
if (parent) {
native = new addon.QFileDialog(parent.native, caption, directory, filter);
} else {
native = new addon.QFileDialog();
}
super(native);
this.native = native;
this.nodeParent = parent;
}
open(): void {
this.native.open();
}
supportedSchemes(): string[] {
return this.native.supportedSchemes();
}
setSupportedSchemes(schemes: string[]): void {
this.native.setSupportedSchemes(schemes);
}
labelText(label: DialogLabel): string {
return this.native.labelText(label);
}
setLabelText(label: DialogLabel, text: string): void {
this.native.setLabelText(label, text);
}
setOption(option: Option, on = true): void {
this.native.setOption(option, on);
}
acceptMode(): AcceptMode {
return this.property('acceptMode').toInt();
}
defaultSuffix(): string {
return this.property('defaultSuffix').toString();
}
fileMode(): FileMode {
return this.property('fileMode').toInt();
}
options(): Option {
return this.property('options').toInt();
}
viewMode(): ViewMode {
return this.property('viewMode').toInt();
}
setAcceptMode(acceptMode: AcceptMode): void {
this.setProperty('acceptMode', acceptMode);
}
setDefaultSuffix(defaultSuffix: string): void {
this.setProperty('defaultSuffix', defaultSuffix);
}
setFileMode(fileMode: FileMode): void {
this.setProperty('fileMode', fileMode);
}
setOptions(options: Option): void {
this.setProperty('options', options);
}
}