Finish 0.4.5
This commit is contained in:
commit
719dceef69
|
@ -18,12 +18,6 @@ install:
|
||||||
- wget http://www.cmake.org/files/v3.3/cmake-3.3.1-Linux-x86_64.tar.gz
|
- wget http://www.cmake.org/files/v3.3/cmake-3.3.1-Linux-x86_64.tar.gz
|
||||||
- tar xf cmake-3.3.1-Linux-x86_64.tar.gz
|
- tar xf cmake-3.3.1-Linux-x86_64.tar.gz
|
||||||
- export CMAKE_EXECUTABLE=/tmp/cmake-3.3.1-Linux-x86_64/bin/cmake
|
- export CMAKE_EXECUTABLE=/tmp/cmake-3.3.1-Linux-x86_64/bin/cmake
|
||||||
- wget http://downloads.dlang.org/releases/2015/dmd_2.068.0-0_amd64.deb
|
|
||||||
- echo "Installing D"
|
|
||||||
- sudo dpkg -i dmd_2.068.0-0_amd64.deb
|
|
||||||
- echo "Installing Nim"
|
|
||||||
- wget http://cz.archive.ubuntu.com/ubuntu/pool/universe/n/nim/nim_0.11.2+dfsg1-4_amd64.deb
|
|
||||||
- sudo dpkg -i nim_0.11.2+dfsg1-4_amd64.deb
|
|
||||||
- cd -
|
- cd -
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
# Version 0.4.5
|
||||||
|
* Removed the D bindings
|
||||||
|
* Removed the Nim bindings
|
||||||
|
|
||||||
# Version 0.4.2
|
# Version 0.4.2
|
||||||
* [DOtherSide] Code cleanup and little refactoring
|
* [DOtherSide] Code cleanup and little refactoring
|
||||||
* [NimQml] Made nim compiles with the "cpp" option by default. This should fix C/C++ interop problems
|
* [NimQml] Made nim compiles with the "cpp" option by default. This should fix C/C++ interop problems
|
||||||
|
|
||||||
# Version 0.4.1
|
# Version 0.4.1
|
||||||
* [DQml] Added support for code generation of slots, signals and properties by using custom UDAs
|
* [DQml] Added support for code generation of slots, signals and properties by using custom UDAs
|
||||||
|
|
|
@ -1,4 +1,2 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
add_subdirectory(DOtherSide)
|
add_subdirectory(src)
|
||||||
add_subdirectory(Nim)
|
|
||||||
add_subdirectory(D)
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/D)
|
|
||||||
add_subdirectory(DQml)
|
|
||||||
add_subdirectory(Examples)
|
|
|
@ -1,17 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
project (DQml C D )
|
|
||||||
add_library(${PROJECT_NAME} STATIC
|
|
||||||
dqml.d
|
|
||||||
qobject.d
|
|
||||||
qvariant.d
|
|
||||||
qmetatype.d
|
|
||||||
qquickview.d
|
|
||||||
qqmlapplicationengine.d
|
|
||||||
qqmlcontext.d
|
|
||||||
qguiapplication.d
|
|
||||||
qapplication.d
|
|
||||||
qmodelindex.d
|
|
||||||
qabstractlistmodel.d
|
|
||||||
qobjectgenerators.d
|
|
||||||
)
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
|
|
@ -1,126 +0,0 @@
|
||||||
extern(C)
|
|
||||||
{
|
|
||||||
// QApplication
|
|
||||||
void dos_qapplication_create();
|
|
||||||
void dos_qapplication_exec();
|
|
||||||
void dos_qapplication_delete();
|
|
||||||
void dos_qapplication_quit();
|
|
||||||
|
|
||||||
// QGuiApplication
|
|
||||||
void dos_qguiapplication_create();
|
|
||||||
void dos_qguiapplication_exec();
|
|
||||||
void dos_qguiapplication_delete();
|
|
||||||
void dos_qguiapplication_quit();
|
|
||||||
|
|
||||||
// QQmlApplicationEngine
|
|
||||||
void dos_qqmlapplicationengine_create(ref void*);
|
|
||||||
void dos_qqmlapplicationengine_load(void*, immutable (char)* filename);
|
|
||||||
void dos_qqmlapplicationengine_context(void*, ref void*);
|
|
||||||
void dos_qqmlapplicationengine_delete(void*);
|
|
||||||
|
|
||||||
// QQuickView
|
|
||||||
void dos_qquickview_create(ref void*);
|
|
||||||
void dos_qquickview_show(void*);
|
|
||||||
void dos_qquickview_source(void*, ref char *);
|
|
||||||
void dos_qquickview_set_source(void*, immutable (char)* filename);
|
|
||||||
void dos_qquickview_rootContext(void*, ref void*);
|
|
||||||
void dos_qquickview_delete(void*);
|
|
||||||
|
|
||||||
// CharArray
|
|
||||||
void dos_chararray_delete(char*);
|
|
||||||
|
|
||||||
// QQmlContext
|
|
||||||
void dos_qqmlcontext_baseUrl(void*, ref char*);
|
|
||||||
void dos_qqmlcontext_setcontextproperty(void*, immutable (char)*, void*);
|
|
||||||
|
|
||||||
// QVariant
|
|
||||||
void dos_qvariant_create(ref void*);
|
|
||||||
void dos_qvariant_create_int(ref void*, int);
|
|
||||||
void dos_qvariant_create_bool(ref void*, bool);
|
|
||||||
void dos_qvariant_create_string(ref void*, immutable(char)*);
|
|
||||||
void dos_qvariant_create_qobject(ref void*, void*);
|
|
||||||
void dos_qvariant_create_float(ref void*, float);
|
|
||||||
void dos_qvariant_create_double(ref void*, double);
|
|
||||||
void dos_qvariant_toInt(void*, ref int);
|
|
||||||
void dos_qvariant_setInt(void*, int);
|
|
||||||
void dos_qvariant_toBool(void*, ref bool);
|
|
||||||
void dos_qvariant_setBool(void*, bool);
|
|
||||||
void dos_qvariant_toString(void*, ref char*);
|
|
||||||
void dos_qvariant_setString(void*, immutable(char)*);
|
|
||||||
void dos_qvariant_toFloat(void*, ref float);
|
|
||||||
void dos_qvariant_setFloat(void*, float);
|
|
||||||
void dos_qvariant_toDouble(void*, ref double);
|
|
||||||
void dos_qvariant_setDouble(void*, double);
|
|
||||||
void dos_qvariant_isnull(void*, ref bool);
|
|
||||||
void dos_qvariant_delete(void*);
|
|
||||||
void dos_qvariant_assign(void*, void*);
|
|
||||||
void dos_qvariant_setQObject(void*, void*);
|
|
||||||
|
|
||||||
// QObject
|
|
||||||
void dos_qobject_create(ref void*,
|
|
||||||
void* dobject,
|
|
||||||
void function (void*, void*, int , void**));
|
|
||||||
|
|
||||||
void dos_qobject_slot_create(void*,
|
|
||||||
immutable (char)* name,
|
|
||||||
int parametersCount,
|
|
||||||
int* parametersMetaTypes,
|
|
||||||
ref int slotIndex);
|
|
||||||
|
|
||||||
void dos_qobject_signal_create(void*,
|
|
||||||
immutable(char)* name,
|
|
||||||
int parametersCount,
|
|
||||||
int* parametersMetaTypes,
|
|
||||||
ref int signalIndex);
|
|
||||||
|
|
||||||
void dos_qobject_signal_emit(void*, immutable(char)* name,
|
|
||||||
int parametersCount,
|
|
||||||
void** parameters);
|
|
||||||
|
|
||||||
void dos_qobject_property_create(void*,
|
|
||||||
immutable(char)* name,
|
|
||||||
int propertyMetaType,
|
|
||||||
immutable(char)* readSlot,
|
|
||||||
immutable(char)* writeSlot,
|
|
||||||
immutable(char)* notifySignal);
|
|
||||||
|
|
||||||
void dos_qobject_delete(void*);
|
|
||||||
|
|
||||||
// QModelIndex
|
|
||||||
void dos_qmodelindex_create(ref void* index);
|
|
||||||
void dos_qmodelindex_delete(void* index);
|
|
||||||
void dos_qmodelindex_row(void*, ref int result);
|
|
||||||
void dos_qmodelindex_column(void*, ref int result);
|
|
||||||
void dos_qmodelindex_isValid(void* index, ref bool result);
|
|
||||||
void dos_qmodelindex_data(void* index, int role, void* variant);
|
|
||||||
void dos_qmodelindex_parent(void* index, void* parent);
|
|
||||||
void dos_qmodelindex_child(void* index, int r, int c, void* child);
|
|
||||||
void dos_qmodelindex_sibling(void* index, int r, int c, void* sibling);
|
|
||||||
|
|
||||||
// QHashIntByteArray
|
|
||||||
void dos_qhash_int_qbytearray_create(ref void*);
|
|
||||||
void dos_qhash_int_qbytearray_delete(void*);
|
|
||||||
void dos_qhash_int_qbytearray_insert(void*, int, immutable(char)*);
|
|
||||||
void dos_qhash_int_qbytearray_value(void*, int, ref char*);
|
|
||||||
|
|
||||||
// QAbstractListModel
|
|
||||||
void dos_qabstractlistmodel_create(ref void*,
|
|
||||||
void*,
|
|
||||||
void function (void*, void*, int, void**),
|
|
||||||
void function (void*, void*, ref int),
|
|
||||||
void function (void*, void*, ref int),
|
|
||||||
void function (void*, void*, int, void*),
|
|
||||||
void function (void*, void*, void*, int, ref bool),
|
|
||||||
void function (void*, void*),
|
|
||||||
void function (void*, void*, ref int),
|
|
||||||
void function (void*, int, int, int, void*));
|
|
||||||
void dos_qabstractlistmodel_beginInsertRows(void* vptr, void* parent, int first, int last);
|
|
||||||
void dos_qabstractlistmodel_endInsertRows(void* vptr);
|
|
||||||
void dos_qabstractlistmodel_beginRemoveRows(void* vptr, void* parent, int first, int last);
|
|
||||||
void dos_qabstractlistmodel_endRemoveRows(void* vptr);
|
|
||||||
void dos_qabstractlistmodel_beginResetModel(void* vptr);
|
|
||||||
void dos_qabstractlistmodel_endResetModel(void* vptr);
|
|
||||||
void dos_qabstractlistmodel_dataChanged(void* vptr, void* topLeft, void* bottomRight, int* rolesPtr, int rolesLength);
|
|
||||||
void dos_qabstractlistmodel_delete(void*);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
public import qvariant;
|
|
||||||
public import qguiapplication;
|
|
||||||
public import qapplication;
|
|
||||||
public import qqmlcontext;
|
|
||||||
public import qobject;
|
|
||||||
public import qqmlapplicationengine;
|
|
||||||
public import qquickview;
|
|
||||||
public import qmetatype;
|
|
||||||
public import qmodelindex;
|
|
||||||
public import qabstractlistmodel;
|
|
||||||
public import qobjectgenerators;
|
|
||||||
public import std.traits;
|
|
||||||
public import std.algorithm;
|
|
||||||
public import std.stdio;
|
|
|
@ -1,184 +0,0 @@
|
||||||
import dothersideinterface;
|
|
||||||
import qobject;
|
|
||||||
import qmodelindex;
|
|
||||||
import qvariant;
|
|
||||||
import std.string;
|
|
||||||
|
|
||||||
class QAbstractListModel : QObject
|
|
||||||
{
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
super(true);
|
|
||||||
dos_qabstractlistmodel_create(this.vptr,
|
|
||||||
cast(void*)this,
|
|
||||||
&staticSlotCallback,
|
|
||||||
&rowCountCallback,
|
|
||||||
&columnCountCallback,
|
|
||||||
&dataCallback,
|
|
||||||
&setDataCallback,
|
|
||||||
&roleNamesCallback,
|
|
||||||
&flagsCallback,
|
|
||||||
&headerDataCallback);
|
|
||||||
qobjectInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
dos_qabstractlistmodel_delete(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int rowCount(QModelIndex parentIndex)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int columnCount(QModelIndex parentIndex)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QVariant data(QModelIndex index, int role)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool setData(QModelIndex index, QVariant value, int role)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string[int] roleNames()
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int flags(QModelIndex index)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QVariant headerData(int section, int orienation, int role)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void beginInsertRows(QModelIndex parent, int first, int last)
|
|
||||||
{
|
|
||||||
dos_qabstractlistmodel_beginInsertRows(this.vptr,
|
|
||||||
parent.voidPointer(),
|
|
||||||
first,
|
|
||||||
last);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void endInsertRows()
|
|
||||||
{
|
|
||||||
dos_qabstractlistmodel_endInsertRows(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void beginRemoveRows(QModelIndex parent, int first, int last)
|
|
||||||
{
|
|
||||||
dos_qabstractlistmodel_beginRemoveRows(this.vptr,
|
|
||||||
parent.voidPointer(),
|
|
||||||
first,
|
|
||||||
last);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void endRemoveRows()
|
|
||||||
{
|
|
||||||
dos_qabstractlistmodel_endRemoveRows(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void beginResetModel()
|
|
||||||
{
|
|
||||||
dos_qabstractlistmodel_beginResetModel(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void endResetModel()
|
|
||||||
{
|
|
||||||
dos_qabstractlistmodel_endResetModel(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void dataChanged(QModelIndex topLeft, QModelIndex bottomRight, int[] roles)
|
|
||||||
{
|
|
||||||
dos_qabstractlistmodel_dataChanged(this.vptr,
|
|
||||||
topLeft.voidPointer(),
|
|
||||||
bottomRight.voidPointer(),
|
|
||||||
roles.ptr,
|
|
||||||
cast(int)(roles.length));
|
|
||||||
}
|
|
||||||
|
|
||||||
private extern (C) static void rowCountCallback(void* modelPtr,
|
|
||||||
void* indexPtr,
|
|
||||||
ref int result)
|
|
||||||
{
|
|
||||||
auto model = cast(QAbstractListModel)(modelPtr);
|
|
||||||
auto index = new QModelIndex(indexPtr);
|
|
||||||
result = model.rowCount(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
private extern (C) static void columnCountCallback(void* modelPtr,
|
|
||||||
void* indexPtr,
|
|
||||||
ref int result)
|
|
||||||
{
|
|
||||||
auto model = cast(QAbstractListModel)(modelPtr);
|
|
||||||
auto index = new QModelIndex(indexPtr);
|
|
||||||
result = model.columnCount(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
private extern (C) static void dataCallback(void* modelPtr,
|
|
||||||
void* indexPtr,
|
|
||||||
int role,
|
|
||||||
void* result)
|
|
||||||
{
|
|
||||||
auto model = cast(QAbstractListModel)(modelPtr);
|
|
||||||
auto index = new QModelIndex(indexPtr);
|
|
||||||
auto value = model.data(index, role);
|
|
||||||
if (value is null)
|
|
||||||
return;
|
|
||||||
dos_qvariant_assign(result, value.voidPointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
private extern (C) static void setDataCallback(void* modelPtr,
|
|
||||||
void* indexPtr,
|
|
||||||
void* valuePtr,
|
|
||||||
int role,
|
|
||||||
ref bool result)
|
|
||||||
{
|
|
||||||
auto model = cast(QAbstractListModel)(modelPtr);
|
|
||||||
auto index = new QModelIndex(indexPtr);
|
|
||||||
auto value = new QVariant(valuePtr);
|
|
||||||
result = model.setData(index, value, role);
|
|
||||||
}
|
|
||||||
|
|
||||||
private extern (C) static void roleNamesCallback(void* modelPtr,
|
|
||||||
void* result)
|
|
||||||
{
|
|
||||||
auto model = cast(QAbstractListModel)(modelPtr);
|
|
||||||
auto roles = model.roleNames();
|
|
||||||
foreach(int key; roles.keys) {
|
|
||||||
dos_qhash_int_qbytearray_insert(result, key, roles[key].toStringz());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extern (C) static void flagsCallback(void* modelPtr,
|
|
||||||
void* indexPtr,
|
|
||||||
ref int result)
|
|
||||||
{
|
|
||||||
auto model = cast(QAbstractListModel)(modelPtr);
|
|
||||||
auto index = new QModelIndex(indexPtr);
|
|
||||||
result = model.flags(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
private extern (C) static void headerDataCallback(void* modelPtr,
|
|
||||||
int section,
|
|
||||||
int orientation,
|
|
||||||
int role,
|
|
||||||
void* result)
|
|
||||||
{
|
|
||||||
auto model = cast(QAbstractListModel)(modelPtr);
|
|
||||||
QVariant value = model.headerData(section, orientation, role);
|
|
||||||
if (value is null)
|
|
||||||
return;
|
|
||||||
dos_qvariant_assign(result, value.voidPointer());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import dothersideinterface;
|
|
||||||
|
|
||||||
class QApplication
|
|
||||||
{
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
dos_qapplication_create();
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
dos_qapplication_delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void exec()
|
|
||||||
{
|
|
||||||
dos_qapplication_exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
void quit()
|
|
||||||
{
|
|
||||||
dos_qapplication_quit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import dothersideinterface;
|
|
||||||
|
|
||||||
class QGuiApplication
|
|
||||||
{
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
dos_qguiapplication_create();
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
dos_qguiapplication_delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
void exec()
|
|
||||||
{
|
|
||||||
dos_qguiapplication_exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
void quit()
|
|
||||||
{
|
|
||||||
dos_qguiapplication_quit();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
import dothersideinterface;
|
|
||||||
import qvariant;
|
|
||||||
import std.string;
|
|
||||||
|
|
||||||
class QHashIntByteArray
|
|
||||||
{
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
dos_qhash_int_qbytearray_create(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
this(void* vptr)
|
|
||||||
{
|
|
||||||
this.vptr = vptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
dos_qhash_int_qbytearray_delete(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void* voidPointer()
|
|
||||||
{
|
|
||||||
return vptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void insert(int key, string value)
|
|
||||||
{
|
|
||||||
dos_qhash_int_qbytearray_insert(this.vptr, key, value.toStringz());
|
|
||||||
}
|
|
||||||
|
|
||||||
public string value(int key)
|
|
||||||
{
|
|
||||||
char* array;
|
|
||||||
dos_qhash_int_qbytearray_value(this.vptr, key, array);
|
|
||||||
string result = fromStringz(array).dup;
|
|
||||||
dos_chararray_delete(array);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void* vptr;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
import qobject;
|
|
||||||
import qvariant;
|
|
||||||
|
|
||||||
/*
|
|
||||||
enum Type {
|
|
||||||
UnknownType = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5,
|
|
||||||
Double = 6, Long = 32, Short = 33, Char = 34, ULong = 35, UShort = 36,
|
|
||||||
UChar = 37, Float = 38,
|
|
||||||
VoidStar = 31,
|
|
||||||
QChar = 7, QString = 10, QStringList = 11, QByteArray = 12,
|
|
||||||
QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17,
|
|
||||||
QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22,
|
|
||||||
QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26, QRegExp = 27,
|
|
||||||
QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42,
|
|
||||||
QRegularExpression = 44,
|
|
||||||
QJsonValue = 45, QJsonObject = 46, QJsonArray = 47, QJsonDocument = 48,
|
|
||||||
QObjectStar = 39, SChar = 40,
|
|
||||||
Void = 43,
|
|
||||||
QVariantMap = 8, QVariantList = 9, QVariantHash = 28,
|
|
||||||
QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68,
|
|
||||||
QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73,
|
|
||||||
QCursor = 74, QKeySequence = 75, QPen = 76, QTextLength = 77, QTextFormat = 78,
|
|
||||||
QMatrix = 79, QTransform = 80, QMatrix4x4 = 81, QVector2D = 82,
|
|
||||||
QVector3D = 83, QVector4D = 84, QQuaternion = 85, QPolygonF = 86,
|
|
||||||
QSizePolicy = 121,
|
|
||||||
User = 1024
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
public enum QMetaType
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
Bool = 1,
|
|
||||||
Int = 2,
|
|
||||||
Double = 6,
|
|
||||||
String = 10,
|
|
||||||
VoidStr = 31,
|
|
||||||
Float = 38,
|
|
||||||
QObject = 39,
|
|
||||||
QVariant = 41,
|
|
||||||
Void = 43
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
import dothersideinterface;
|
|
||||||
import qvariant;
|
|
||||||
|
|
||||||
class QModelIndex
|
|
||||||
{
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
dos_qmodelindex_create(this.ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
this(void* ptr)
|
|
||||||
{
|
|
||||||
this.ptr = ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
dos_qmodelindex_delete(this.ptr);
|
|
||||||
ptr = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void* voidPointer()
|
|
||||||
{
|
|
||||||
return this.ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int row()
|
|
||||||
{
|
|
||||||
int result = -1;
|
|
||||||
dos_qmodelindex_row(this.ptr, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int column()
|
|
||||||
{
|
|
||||||
int result = -1;
|
|
||||||
dos_qmodelindex_column(this.ptr, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool isValid()
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
dos_qmodelindex_isValid(this.ptr, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QVariant data(int role)
|
|
||||||
{
|
|
||||||
auto result = new QVariant();
|
|
||||||
dos_qmodelindex_data(this.ptr, role, result.voidPointer());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QModelIndex parent()
|
|
||||||
{
|
|
||||||
auto result = new QModelIndex();
|
|
||||||
dos_qmodelindex_parent(this.ptr, result.ptr);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QModelIndex child(int row, int column)
|
|
||||||
{
|
|
||||||
auto result = new QModelIndex();
|
|
||||||
dos_qmodelindex_child(this.ptr, row, column, result.ptr);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QModelIndex sibling(int row, int column)
|
|
||||||
{
|
|
||||||
auto result = new QModelIndex();
|
|
||||||
dos_qmodelindex_sibling(this.ptr, row, column, result.ptr);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void* ptr;
|
|
||||||
}
|
|
129
D/DQml/qobject.d
129
D/DQml/qobject.d
|
@ -1,129 +0,0 @@
|
||||||
import std.stdio;
|
|
||||||
import std.format;
|
|
||||||
import std.conv;
|
|
||||||
import std.container;
|
|
||||||
import std.traits;
|
|
||||||
import std.string;
|
|
||||||
import std.algorithm;
|
|
||||||
import dothersideinterface;
|
|
||||||
import qmetatype;
|
|
||||||
import qvariant;
|
|
||||||
|
|
||||||
public class QObject
|
|
||||||
{
|
|
||||||
public this()
|
|
||||||
{
|
|
||||||
this(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected this(bool disableDosCalls)
|
|
||||||
{
|
|
||||||
this.disableDosCalls = disableDosCalls;
|
|
||||||
if (!this.disableDosCalls)
|
|
||||||
{
|
|
||||||
dos_qobject_create(this.vptr, cast(void*)this, &staticSlotCallback);
|
|
||||||
qobjectInit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
if (!this.disableDosCalls)
|
|
||||||
{
|
|
||||||
dos_qobject_delete(this.vptr);
|
|
||||||
this.vptr = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void* voidPointer()
|
|
||||||
{
|
|
||||||
return this.vptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void qobjectInit()
|
|
||||||
{}
|
|
||||||
|
|
||||||
protected void onSlotCalled(QVariant slotName, QVariant[] parameters)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void registerSlot(string name, QMetaType[] types)
|
|
||||||
{
|
|
||||||
int index = -1;
|
|
||||||
int length = cast(int)types.length;
|
|
||||||
int[] array = to!(int[])(types);
|
|
||||||
dos_qobject_slot_create(this.vptr,
|
|
||||||
name.toStringz(),
|
|
||||||
length,
|
|
||||||
array.ptr,
|
|
||||||
index);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void registerSignal(string name, QMetaType[] types)
|
|
||||||
{
|
|
||||||
int index = -1;
|
|
||||||
int length = cast(int)types.length;
|
|
||||||
int[] array = length > 0 ? to!(int[])(types) : null;
|
|
||||||
dos_qobject_signal_create(this.vptr,
|
|
||||||
name.toStringz(),
|
|
||||||
length,
|
|
||||||
array.ptr,
|
|
||||||
index);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void registerProperty(string name,
|
|
||||||
QMetaType type,
|
|
||||||
string readSlotName,
|
|
||||||
string writeSlotName,
|
|
||||||
string notifySignalName)
|
|
||||||
{
|
|
||||||
dos_qobject_property_create(this.vptr,
|
|
||||||
name.toStringz(),
|
|
||||||
type,
|
|
||||||
readSlotName.toStringz(),
|
|
||||||
writeSlotName.toStringz(),
|
|
||||||
notifySignalName.toStringz());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void emit(T)(string signalName, T t)
|
|
||||||
{
|
|
||||||
emit(signalName, new QVariant(t));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void emit(string signalName, QVariant value)
|
|
||||||
{
|
|
||||||
QVariant[] array = [value];
|
|
||||||
emit(signalName, array);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void emit(string signalName, QVariant[] arguments = null)
|
|
||||||
{
|
|
||||||
int length = cast(int)arguments.length;
|
|
||||||
void*[] array = null;
|
|
||||||
if (length > 0) {
|
|
||||||
array = new void*[length];
|
|
||||||
foreach (int i, QVariant v; arguments)
|
|
||||||
array[i] = v.voidPointer();
|
|
||||||
}
|
|
||||||
dos_qobject_signal_emit(this.vptr,
|
|
||||||
signalName.toStringz(),
|
|
||||||
length,
|
|
||||||
array.ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected extern (C) static void staticSlotCallback(void* qObjectPtr,
|
|
||||||
void* rawSlotName,
|
|
||||||
int numParameters,
|
|
||||||
void** parametersArray)
|
|
||||||
{
|
|
||||||
QVariant[] parameters = new QVariant[numParameters];
|
|
||||||
for (int i = 0; i < numParameters; ++i)
|
|
||||||
parameters[i] = new QVariant(parametersArray[i]);
|
|
||||||
QObject qObject = cast(QObject) qObjectPtr;
|
|
||||||
QVariant slotName = new QVariant(rawSlotName);
|
|
||||||
qObject.onSlotCalled(slotName, parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void* vptr;
|
|
||||||
protected bool disableDosCalls;
|
|
||||||
}
|
|
|
@ -1,265 +0,0 @@
|
||||||
import std.traits;
|
|
||||||
import std.algorithm;
|
|
||||||
import std.string;
|
|
||||||
import std.stdio;
|
|
||||||
|
|
||||||
struct QtProperty
|
|
||||||
{
|
|
||||||
public string type;
|
|
||||||
public string name;
|
|
||||||
public string read;
|
|
||||||
public string write;
|
|
||||||
public string notify;
|
|
||||||
|
|
||||||
this(string type, string name, string read, string write, string notify)
|
|
||||||
{
|
|
||||||
this.type = type;
|
|
||||||
this.name = name;
|
|
||||||
this.read = read;
|
|
||||||
this.write = write;
|
|
||||||
this.notify = notify;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
struct QtSlot {};
|
|
||||||
struct QtSignal {};
|
|
||||||
|
|
||||||
|
|
||||||
string GenerateVariantConversionCall(string typeName)
|
|
||||||
{
|
|
||||||
switch (typeName)
|
|
||||||
{
|
|
||||||
case "string":
|
|
||||||
return ".toString()";
|
|
||||||
case "int":
|
|
||||||
return ".toInt()";
|
|
||||||
case "bool":
|
|
||||||
return ".toBool()";
|
|
||||||
case "float":
|
|
||||||
return ".toFloat()";
|
|
||||||
case "double":
|
|
||||||
return ".toDouble()";
|
|
||||||
case "QVariant":
|
|
||||||
return "";
|
|
||||||
default:
|
|
||||||
throw new Exception("Unknown conversion function from Qvariant to " ~ typeName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateArgumentList(string[] typeNames)
|
|
||||||
{
|
|
||||||
string result = "";
|
|
||||||
for (int i = 0; i < typeNames.length; ++i)
|
|
||||||
{
|
|
||||||
auto typeName = typeNames[i];
|
|
||||||
auto variantCall = GenerateVariantConversionCall(typeName);
|
|
||||||
result ~= i > 0 ? "," : "";
|
|
||||||
result ~= format("arguments[%d]%s", i+1, variantCall);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateSlotCall(FunctionInfo info)
|
|
||||||
{
|
|
||||||
auto args = GenerateArgumentList(info.parameterTypes);
|
|
||||||
auto call = format("%s(%s)", info.name, args);
|
|
||||||
auto formatStr = info.returnType != "void" ? "arguments[0].setValue(%s)" : "%s";
|
|
||||||
return format(formatStr, call);
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateCaseBlock(FunctionInfo info)
|
|
||||||
{
|
|
||||||
string result = "";
|
|
||||||
result ~= format("case \"%s\":\n", info.name);
|
|
||||||
result ~= format("%s;\n", GenerateSlotCall(info));
|
|
||||||
result ~= "break;\n";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateOnSlotCalled(QtInfo info)
|
|
||||||
{
|
|
||||||
string result = "protected override void onSlotCalled(QVariant slotName, QVariant[] arguments)\n";
|
|
||||||
result ~= "{\n";
|
|
||||||
result ~= "switch(slotName.toString())\n";
|
|
||||||
result ~= "{\n";
|
|
||||||
foreach (slot; info.slots)
|
|
||||||
result ~= GenerateCaseBlock(slot);
|
|
||||||
result ~= "default: super.onSlotCalled(slotName, arguments);\n";
|
|
||||||
result ~= "}\n"; //
|
|
||||||
result ~= "}";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateSignalCall(FunctionInfo info)
|
|
||||||
{
|
|
||||||
string args = "";
|
|
||||||
string vars = "";
|
|
||||||
for (int i = 0; i < info.parameterTypes.length; ++i) {
|
|
||||||
if (i > 0) {
|
|
||||||
args ~= ",";
|
|
||||||
vars ~= ",";
|
|
||||||
}
|
|
||||||
args ~= format("%s val%d", info.parameterTypes[i], i);
|
|
||||||
vars ~= format("val%d", i);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto result = format("public %s %s(%s) { emit(\"%s\", %s); }", info.returnType, info.name, args, info.name, vars);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateQtSignals(QtInfo info)
|
|
||||||
{
|
|
||||||
string result = "";
|
|
||||||
foreach (signal; info.signals)
|
|
||||||
result ~= GenerateSignalCall(signal) ~ "\n";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateMetaType(string typeName)
|
|
||||||
{
|
|
||||||
switch(typeName)
|
|
||||||
{
|
|
||||||
case "void":
|
|
||||||
return "QMetaType.Void";
|
|
||||||
case "int":
|
|
||||||
return "QMetaType.Int";
|
|
||||||
case "string":
|
|
||||||
return "QMetaType.String";
|
|
||||||
case "QObject":
|
|
||||||
return "QMetaType.QObject";
|
|
||||||
case "QVariant":
|
|
||||||
return "QMetaType.QVariant";
|
|
||||||
case "bool":
|
|
||||||
return "QMetaType.Bool";
|
|
||||||
case "float":
|
|
||||||
return "QMetaType.Float";
|
|
||||||
case "double":
|
|
||||||
return "QMetaType.Double";
|
|
||||||
default:
|
|
||||||
throw new Exception(format("Unknown conversion from %s to QMetaType", typeName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateMetaTypesListForSlot(FunctionInfo info)
|
|
||||||
{
|
|
||||||
string result = GenerateMetaType(info.returnType);
|
|
||||||
result ~= ", ";
|
|
||||||
result ~= GenerateMetaTypesListForSignal(info);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateMetaTypesListForSignal(FunctionInfo info)
|
|
||||||
{
|
|
||||||
string result = "";
|
|
||||||
for (int i = 0; i < info.parameterTypes.length; ++i)
|
|
||||||
{
|
|
||||||
if (i > 0)
|
|
||||||
result ~= ", ";
|
|
||||||
result ~= GenerateMetaType(info.parameterTypes[i]);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
string GenerateQObjectInit(QtInfo info)
|
|
||||||
{
|
|
||||||
string result = "";
|
|
||||||
result ~= "protected override void qobjectInit()\n";
|
|
||||||
result ~= "{\n";
|
|
||||||
foreach (slot; info.slots)
|
|
||||||
{
|
|
||||||
auto metaTypes = GenerateMetaTypesListForSlot(slot);
|
|
||||||
result ~= format("registerSlot(\"%s\", [%s]);\n", slot.name, metaTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (signal; info.signals)
|
|
||||||
{
|
|
||||||
auto metaTypes = GenerateMetaTypesListForSignal(signal);
|
|
||||||
result ~= format("registerSignal(\"%s\", [%s]);\n", signal.name, metaTypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (property; info.properties)
|
|
||||||
{
|
|
||||||
result ~= format("registerProperty(\"%s\", %s, \"%s\", \"%s\", \"%s\");\n", property.name, GenerateMetaType(property.type), property.read, property.write, property.notify);
|
|
||||||
}
|
|
||||||
|
|
||||||
result ~= "super.qobjectInit();\n";
|
|
||||||
|
|
||||||
result ~= "}";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FunctionInfo
|
|
||||||
{
|
|
||||||
string name;
|
|
||||||
string returnType;
|
|
||||||
string[] parameterTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct QtInfo
|
|
||||||
{
|
|
||||||
FunctionInfo[] slots;
|
|
||||||
FunctionInfo[] signals;
|
|
||||||
QtProperty[] properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
mixin template InjectQObjectMacro()
|
|
||||||
{
|
|
||||||
private static QtInfo GetQtUDA(T)()
|
|
||||||
{
|
|
||||||
QtInfo result;
|
|
||||||
|
|
||||||
foreach (attribute; __traits(getAttributes, T)) {
|
|
||||||
static if (is (typeof(attribute) == QtProperty)) {
|
|
||||||
result.properties ~= attribute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (member; __traits(allMembers, T))
|
|
||||||
{
|
|
||||||
static if (__traits(compiles, __traits(getMember, T, member))
|
|
||||||
&& isSomeFunction!(__traits(getMember, T, member)))
|
|
||||||
{
|
|
||||||
// Retrieve the UDA
|
|
||||||
auto attributes = __traits(getAttributes, __traits(getMember, T, member));
|
|
||||||
|
|
||||||
// Turn the tuple in an array of strings
|
|
||||||
string[] attributeNames;
|
|
||||||
foreach (attribute; attributes)
|
|
||||||
attributeNames ~= typeof(attribute).stringof;
|
|
||||||
|
|
||||||
bool isSlot = attributeNames.canFind("QtSlot");
|
|
||||||
bool isSignal = attributeNames.canFind("QtSignal");
|
|
||||||
|
|
||||||
// Extract the Function Return Type and Arguments
|
|
||||||
if (isSlot || isSignal)
|
|
||||||
{
|
|
||||||
FunctionInfo info;
|
|
||||||
info.name = member;
|
|
||||||
info.returnType = ReturnType!(__traits(getMember, T, member)).stringof;
|
|
||||||
|
|
||||||
foreach (param; ParameterTypeTuple!(__traits(getMember, T, member)))
|
|
||||||
info.parameterTypes ~= param.stringof;
|
|
||||||
|
|
||||||
if (isSlot)
|
|
||||||
result.slots ~= info;
|
|
||||||
|
|
||||||
if (isSignal)
|
|
||||||
result.signals ~= info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string Q_OBJECT(T)()
|
|
||||||
{
|
|
||||||
string result = "";
|
|
||||||
auto info = T.GetQtUDA!(T);
|
|
||||||
result ~= GenerateOnSlotCalled(info) ~ "\n";
|
|
||||||
result ~= GenerateQObjectInit(info) ~ "\n";
|
|
||||||
result ~= GenerateQtSignals(info) ~ "\n";
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
import dothersideinterface;
|
|
||||||
import qqmlcontext;
|
|
||||||
import std.string;
|
|
||||||
|
|
||||||
class QQmlApplicationEngine
|
|
||||||
{
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
dos_qqmlapplicationengine_create(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
dos_qqmlapplicationengine_delete(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void* voidPointer()
|
|
||||||
{
|
|
||||||
return this.vptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public QQmlContext rootContext()
|
|
||||||
{
|
|
||||||
void* contextVPtr;
|
|
||||||
dos_qqmlapplicationengine_context(this.vptr, contextVPtr);
|
|
||||||
return new QQmlContext(contextVPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load(string filename)
|
|
||||||
{
|
|
||||||
dos_qqmlapplicationengine_load(this.vptr, filename.toStringz());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void* vptr;
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
import dothersideinterface;
|
|
||||||
import qvariant;
|
|
||||||
import std.string;
|
|
||||||
|
|
||||||
class QQmlContext
|
|
||||||
{
|
|
||||||
this(void* vptr)
|
|
||||||
{
|
|
||||||
this.vptr = vptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void* voidPointer()
|
|
||||||
{
|
|
||||||
return vptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string baseUrl()
|
|
||||||
{
|
|
||||||
char* array;
|
|
||||||
dos_qqmlcontext_baseUrl(this.vptr, array);
|
|
||||||
string result = fromStringz(array).dup;
|
|
||||||
dos_chararray_delete(array);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContextProperty(string name, QVariant value)
|
|
||||||
{
|
|
||||||
dos_qqmlcontext_setcontextproperty(this.vptr, name.ptr, value.voidPointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void* vptr;
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
import dothersideinterface;
|
|
||||||
import qqmlcontext;
|
|
||||||
import std.string;
|
|
||||||
|
|
||||||
class QQuickView
|
|
||||||
{
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
dos_qquickview_create(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
dos_qquickview_delete(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void* voidPointer()
|
|
||||||
{
|
|
||||||
return this.vptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void show()
|
|
||||||
{
|
|
||||||
dos_qquickview_show(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public QQmlContext rootContext()
|
|
||||||
{
|
|
||||||
void* contextData;
|
|
||||||
dos_qquickview_rootContext(this.vptr, contextData);
|
|
||||||
return new QQmlContext(contextData);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string source()
|
|
||||||
{
|
|
||||||
char* array;
|
|
||||||
dos_qquickview_source(this.vptr, array);
|
|
||||||
string result = fromStringz(array).dup;
|
|
||||||
dos_chararray_delete(array);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSource(string filename)
|
|
||||||
{
|
|
||||||
immutable(char)* filenameAsCString = filename.toStringz();
|
|
||||||
dos_qquickview_set_source(this.vptr, filenameAsCString);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void* vptr;
|
|
||||||
}
|
|
|
@ -1,160 +0,0 @@
|
||||||
import dothersideinterface;
|
|
||||||
import qobject;
|
|
||||||
import std.string;
|
|
||||||
|
|
||||||
class QVariant
|
|
||||||
{
|
|
||||||
public this()
|
|
||||||
{
|
|
||||||
dos_qvariant_create(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(int value)
|
|
||||||
{
|
|
||||||
dos_qvariant_create_int(this.vptr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(bool value)
|
|
||||||
{
|
|
||||||
dos_qvariant_create_bool(this.vptr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(string value)
|
|
||||||
{
|
|
||||||
dos_qvariant_create_string(this.vptr, value.toStringz());
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(float value)
|
|
||||||
{
|
|
||||||
dos_qvariant_create_float(this.vptr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(double value)
|
|
||||||
{
|
|
||||||
dos_qvariant_create_double(this.vptr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(QObject value)
|
|
||||||
{
|
|
||||||
dos_qvariant_create_qobject(this.vptr, value.voidPointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
public this(void* vptr, bool hasOwnership = false)
|
|
||||||
{
|
|
||||||
this.vptr = vptr;
|
|
||||||
this.hasOwnership = hasOwnership;
|
|
||||||
}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
if (this.hasOwnership)
|
|
||||||
dos_qvariant_delete(this.vptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void* voidPointer()
|
|
||||||
{
|
|
||||||
return this.vptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(int value)
|
|
||||||
{
|
|
||||||
dos_qvariant_setInt(this.vptr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(bool value)
|
|
||||||
{
|
|
||||||
dos_qvariant_setBool(this.vptr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(string value)
|
|
||||||
{
|
|
||||||
dos_qvariant_setString(this.vptr, value.toStringz());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(QObject value)
|
|
||||||
{
|
|
||||||
dos_qvariant_setQObject(this.vptr, value.voidPointer());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(float value)
|
|
||||||
{
|
|
||||||
dos_qvariant_setFloat(this.vptr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(double value)
|
|
||||||
{
|
|
||||||
dos_qvariant_setDouble(this.vptr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getValue(ref int value)
|
|
||||||
{
|
|
||||||
value = toInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getValue(ref bool value)
|
|
||||||
{
|
|
||||||
value = toBool();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getValue(ref string value)
|
|
||||||
{
|
|
||||||
value = toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getValue(ref float value)
|
|
||||||
{
|
|
||||||
value = toFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void getValue(ref double value)
|
|
||||||
{
|
|
||||||
value = toDouble();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool isNull()
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
dos_qvariant_isnull(this.vptr, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool toBool()
|
|
||||||
{
|
|
||||||
bool result;
|
|
||||||
dos_qvariant_toBool(this.vptr, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int toInt()
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
dos_qvariant_toInt(this.vptr, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float toFloat()
|
|
||||||
{
|
|
||||||
float result;
|
|
||||||
dos_qvariant_toFloat(this.vptr, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double toDouble()
|
|
||||||
{
|
|
||||||
double result;
|
|
||||||
dos_qvariant_toDouble(this.vptr, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string toString()
|
|
||||||
{
|
|
||||||
char* array;
|
|
||||||
dos_qvariant_toString(this.vptr, array);
|
|
||||||
string result = fromStringz(array).dup;
|
|
||||||
dos_chararray_delete(array);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void* vptr = null;
|
|
||||||
private bool hasOwnership = true;
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
project (DQmlAbstractItemModel C D )
|
|
||||||
add_executable(${PROJECT_NAME} main.d model.d)
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../DQml"
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../../DOtherSide/libDOtherSide.so"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../DQml/libDQml.a"
|
|
||||||
)
|
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
|
@ -1,26 +0,0 @@
|
||||||
import dqml;
|
|
||||||
import model;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto app = new QGuiApplication();
|
|
||||||
scope(exit) destroy(app);
|
|
||||||
|
|
||||||
auto model = new ListModel();
|
|
||||||
scope(exit) destroy(model);
|
|
||||||
|
|
||||||
auto variant = new QVariant();
|
|
||||||
variant.setValue(model);
|
|
||||||
|
|
||||||
auto engine = new QQmlApplicationEngine();
|
|
||||||
scope(exit) destroy(engine);
|
|
||||||
|
|
||||||
engine.rootContext().setContextProperty("myListModel", variant);
|
|
||||||
engine.load("main.qml");
|
|
||||||
app.exec();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow
|
|
||||||
{
|
|
||||||
width: 400
|
|
||||||
height: 300
|
|
||||||
title: "AbstractItemModel"
|
|
||||||
Component.onCompleted: visible = true
|
|
||||||
|
|
||||||
Component
|
|
||||||
{
|
|
||||||
id: myListModelDelegate
|
|
||||||
Label { text: "Name:" + name }
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView
|
|
||||||
{
|
|
||||||
anchors.fill: parent
|
|
||||||
model: myListModel
|
|
||||||
delegate: myListModelDelegate
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
import dqml;
|
|
||||||
import std.stdio;
|
|
||||||
|
|
||||||
|
|
||||||
class ListModel : QAbstractListModel
|
|
||||||
{
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
this.names = ["John", "Max", "Paul", "Anna"];
|
|
||||||
this.roles[Roles.Name] = "name";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int rowCount(QModelIndex parent = null)
|
|
||||||
{
|
|
||||||
if (parent && parent.isValid())
|
|
||||||
return 0;
|
|
||||||
return cast(int)(names.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override QVariant data(QModelIndex index, int role)
|
|
||||||
{
|
|
||||||
if (index is null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (!index.isValid())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (index.row() < 0 || index.row() >= rowCount())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
switch(role)
|
|
||||||
{
|
|
||||||
case Roles.Name:
|
|
||||||
return new QVariant(names[index.row]);
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string[int] roleNames()
|
|
||||||
{
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string[] names;
|
|
||||||
private string[int] roles;
|
|
||||||
private enum Roles : int { Name = 0 };
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
add_subdirectory(HelloWorld)
|
|
||||||
add_subdirectory(SimpleData)
|
|
||||||
add_subdirectory(SlotsAndProperties)
|
|
||||||
add_subdirectory(AbstractItemModel)
|
|
||||||
add_subdirectory(ContactApp)
|
|
|
@ -1,11 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
project (DQmlContactApp C D )
|
|
||||||
add_executable(${PROJECT_NAME} main.d applicationlogic.d contact.d contactlist.d)
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../DQml"
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../../DOtherSide/libDOtherSide.so"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../DQml/libDQml.a"
|
|
||||||
)
|
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
|
@ -1,44 +0,0 @@
|
||||||
import dqml;
|
|
||||||
import contactlist;
|
|
||||||
import std.stdio;
|
|
||||||
|
|
||||||
@QtProperty(QObject.stringof, "contactList", "contactList", null, null)
|
|
||||||
class ApplicationLogic : QObject
|
|
||||||
{
|
|
||||||
mixin InjectQObjectMacro;
|
|
||||||
mixin(Q_OBJECT!(ApplicationLogic));
|
|
||||||
|
|
||||||
this(QApplication app)
|
|
||||||
{
|
|
||||||
this.m_app = app;
|
|
||||||
this.m_contactList = new ContactList();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public QObject contactList()
|
|
||||||
{
|
|
||||||
return this.m_contactList;
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public void onLoadTriggered()
|
|
||||||
{
|
|
||||||
writefln("Load Triggered");
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public void onSaveTriggered()
|
|
||||||
{
|
|
||||||
writefln("Save Triggered");
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public void onExitTriggered()
|
|
||||||
{
|
|
||||||
this.m_app.quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private QApplication m_app;
|
|
||||||
private ContactList m_contactList;
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
import dqml;
|
|
||||||
|
|
||||||
@QtProperty(string.stringof, "firstName", "firstName", "setFirstName", "firstNameChanged")
|
|
||||||
@QtProperty(string.stringof, "lastName", "lastName", "setLastName", "lastNameChanged")
|
|
||||||
class Contact : QObject
|
|
||||||
{
|
|
||||||
mixin InjectQObjectMacro;
|
|
||||||
mixin(Q_OBJECT!(Contact));
|
|
||||||
|
|
||||||
this(string firstName = "", string lastName = "")
|
|
||||||
{
|
|
||||||
this.m_firstName = firstName;
|
|
||||||
this.m_lastName = lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public string firstName()
|
|
||||||
{
|
|
||||||
return this.m_firstName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public void setFirstName(string firstName)
|
|
||||||
{
|
|
||||||
if (this.m_firstName != firstName)
|
|
||||||
{
|
|
||||||
this.m_firstName = firstName;
|
|
||||||
firstNameChanged(firstName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSignal()
|
|
||||||
public void firstNameChanged(string);
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public string lastName()
|
|
||||||
{
|
|
||||||
return this.m_lastName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public void setLastName(string lastName)
|
|
||||||
{
|
|
||||||
if (this.m_lastName != lastName)
|
|
||||||
{
|
|
||||||
this.m_lastName = lastName;
|
|
||||||
lastNameChanged(lastName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSignal()
|
|
||||||
public void lastNameChanged(string);
|
|
||||||
|
|
||||||
private string m_firstName;
|
|
||||||
private string m_lastName;
|
|
||||||
}
|
|
|
@ -1,80 +0,0 @@
|
||||||
import dqml;
|
|
||||||
import contact;
|
|
||||||
import std.stdio;
|
|
||||||
import std.algorithm;
|
|
||||||
|
|
||||||
class ContactList : QAbstractListModel
|
|
||||||
{
|
|
||||||
mixin InjectQObjectMacro;
|
|
||||||
mixin(Q_OBJECT!(ContactList));
|
|
||||||
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
this.m_contacts = [];
|
|
||||||
this.m_roleNames[Roles.FirstName] = "firstName";
|
|
||||||
this.m_roleNames[Roles.LastName] = "lastName";
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int rowCount(QModelIndex parent = null)
|
|
||||||
{
|
|
||||||
if (parent && parent.isValid())
|
|
||||||
return 0;
|
|
||||||
return cast(int)(this.m_contacts.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override QVariant data(QModelIndex index, int role)
|
|
||||||
{
|
|
||||||
if (index is null)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (!index.isValid())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
if (index.row() < 0 || index.row() >= rowCount())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
auto contact = this.m_contacts[index.row];
|
|
||||||
|
|
||||||
switch(role)
|
|
||||||
{
|
|
||||||
case Roles.FirstName:
|
|
||||||
return new QVariant(contact.firstName());
|
|
||||||
case Roles.LastName:
|
|
||||||
return new QVariant(contact.lastName());
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string[int] roleNames()
|
|
||||||
{
|
|
||||||
return this.m_roleNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public void add(string firstName, string lastName)
|
|
||||||
{
|
|
||||||
auto index = new QModelIndex();
|
|
||||||
auto pos = rowCount();
|
|
||||||
writefln("Adding %s %s in pos %d", firstName, lastName, pos);
|
|
||||||
beginInsertRows(index, pos, pos);
|
|
||||||
this.m_contacts ~= new Contact(firstName, lastName);
|
|
||||||
endInsertRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public void del(int pos)
|
|
||||||
{
|
|
||||||
if (pos < 0 || pos >= rowCount())
|
|
||||||
return;
|
|
||||||
auto index = new QModelIndex();
|
|
||||||
writefln("Removing at pos %d", pos);
|
|
||||||
beginRemoveRows(index, pos, pos);
|
|
||||||
this.m_contacts = remove(this.m_contacts, pos);
|
|
||||||
endRemoveRows();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Contact[] m_contacts;
|
|
||||||
private string[int] m_roleNames;
|
|
||||||
private enum Roles : int { FirstName = 0, LastName};
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
import dqml;
|
|
||||||
import applicationlogic;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto app = new QApplication();
|
|
||||||
scope(exit) destroy(app);
|
|
||||||
|
|
||||||
auto logic = new ApplicationLogic(app);
|
|
||||||
scope(exit) destroy(logic);
|
|
||||||
|
|
||||||
auto variant = new QVariant();
|
|
||||||
variant.setValue(logic);
|
|
||||||
|
|
||||||
auto engine = new QQmlApplicationEngine();
|
|
||||||
scope(exit) destroy(engine);
|
|
||||||
|
|
||||||
engine.rootContext().setContextProperty("logic", variant);
|
|
||||||
engine.load("main.qml");
|
|
||||||
app.exec();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{}
|
|
||||||
}
|
|
|
@ -1,93 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow {
|
|
||||||
|
|
||||||
width: 500
|
|
||||||
height: 300
|
|
||||||
title: "ContactApp"
|
|
||||||
visible: true
|
|
||||||
|
|
||||||
menuBar: MenuBar {
|
|
||||||
Menu {
|
|
||||||
title: "&File"
|
|
||||||
MenuItem { text: "&Load"; onTriggered: logic.onLoadTriggered() }
|
|
||||||
MenuItem { text: "&Save"; onTriggered: logic.onSaveTriggered() }
|
|
||||||
MenuItem { text: "&Exit"; onTriggered: logic.onExitTriggered() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: tableTextDelegate
|
|
||||||
Label {
|
|
||||||
id: tableTextDelegateInstance
|
|
||||||
property var styleData: undefined
|
|
||||||
states: State {
|
|
||||||
when: styleData !== undefined
|
|
||||||
PropertyChanges {
|
|
||||||
target: tableTextDelegateInstance;
|
|
||||||
text: styleData.value;
|
|
||||||
color: styleData.textColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: tableButtonDelegate
|
|
||||||
Button {
|
|
||||||
id: tableButtonDelegateInstance
|
|
||||||
property var styleData: undefined
|
|
||||||
text: "Delete"
|
|
||||||
onClicked: logic.contactList.del(styleData.row)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: tableItemDelegate
|
|
||||||
Loader {
|
|
||||||
id: tableItemDelegateInstance
|
|
||||||
sourceComponent: {
|
|
||||||
if (styleData.column === 0 || styleData.column === 1)
|
|
||||||
return tableTextDelegate
|
|
||||||
else if (styleData.column === 2)
|
|
||||||
return tableButtonDelegate
|
|
||||||
else
|
|
||||||
return tableTextDelegate
|
|
||||||
}
|
|
||||||
Binding {
|
|
||||||
target: tableItemDelegateInstance.item
|
|
||||||
property: "styleData"
|
|
||||||
value: styleData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TableView {
|
|
||||||
model: logic.contactList
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
TableViewColumn { role: "firstName"; title: "FirstName"; width: 200 }
|
|
||||||
TableViewColumn { role: "lastName"; title: "LastName"; width: 200}
|
|
||||||
TableViewColumn { width: 100; }
|
|
||||||
itemDelegate: tableItemDelegate
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Label { text: "FirstName" }
|
|
||||||
TextField { id: nameTextField; Layout.fillWidth: true; text: "" }
|
|
||||||
Label { text: "LastName" }
|
|
||||||
TextField { id: surnameTextField; Layout.fillWidth: true; text: "" }
|
|
||||||
Button {
|
|
||||||
text: "Add"
|
|
||||||
onClicked: logic.contactList.add(nameTextField.text, surnameTextField.text)
|
|
||||||
enabled: nameTextField.text !== "" && surnameTextField.text !== ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
project (DQmlHelloWorld C D )
|
|
||||||
add_executable(${PROJECT_NAME} main.d)
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../DQml"
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../../DOtherSide/libDOtherSide.so"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../DQml/libDQml.a"
|
|
||||||
)
|
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
import std.stdio;
|
|
||||||
import dqml;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto app = new QGuiApplication();
|
|
||||||
scope(exit) destroy(app);
|
|
||||||
|
|
||||||
auto engine = new QQmlApplicationEngine();
|
|
||||||
scope(exit) destroy(engine);
|
|
||||||
engine.load("main.qml");
|
|
||||||
|
|
||||||
app.exec();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow
|
|
||||||
{
|
|
||||||
width: 400
|
|
||||||
height: 300
|
|
||||||
title: "Hello World"
|
|
||||||
Component.onCompleted: visible = true
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
project (DQmlSimpleData C D )
|
|
||||||
add_executable(${PROJECT_NAME} main.d)
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../DQml"
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../../DOtherSide/libDOtherSide.so"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../DQml/libDQml.a"
|
|
||||||
)
|
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
import std.stdio;
|
|
||||||
import dqml;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto app = new QGuiApplication();
|
|
||||||
scope(exit) destroy(app);
|
|
||||||
|
|
||||||
auto engine = new QQmlApplicationEngine();
|
|
||||||
scope(exit) destroy(engine);
|
|
||||||
|
|
||||||
auto qVar1 = new QVariant(10);
|
|
||||||
scope(exit) destroy(qVar1);
|
|
||||||
|
|
||||||
auto qVar2 = new QVariant("Hello World");
|
|
||||||
scope(exit) destroy(qVar1);
|
|
||||||
|
|
||||||
auto qVar3 = new QVariant(false);
|
|
||||||
scope(exit) destroy(qVar1);
|
|
||||||
|
|
||||||
auto qVar4 = new QVariant(3.5f);
|
|
||||||
scope(exit) destroy(qVar1);
|
|
||||||
|
|
||||||
engine.rootContext().setContextProperty("qVar1", qVar1);
|
|
||||||
engine.rootContext().setContextProperty("qVar2", qVar2);
|
|
||||||
engine.rootContext().setContextProperty("qVar3", qVar3);
|
|
||||||
engine.rootContext().setContextProperty("qVar4", qVar4);
|
|
||||||
engine.load("main.qml");
|
|
||||||
|
|
||||||
app.exec();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow
|
|
||||||
{
|
|
||||||
width: 400
|
|
||||||
height: 300
|
|
||||||
title: "SimpleData"
|
|
||||||
Component.onCompleted: visible = true
|
|
||||||
|
|
||||||
ColumnLayout
|
|
||||||
{
|
|
||||||
anchors.fill: parent
|
|
||||||
SpinBox { value: qVar1}
|
|
||||||
TextField { text: qVar2}
|
|
||||||
CheckBox { checked: qVar3}
|
|
||||||
SpinBox { value: qVar4; decimals: 1 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
project (DQmlSlotsAndProperties C D )
|
|
||||||
add_executable(${PROJECT_NAME} main.d contact.d)
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../DQml"
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../../DOtherSide/libDOtherSide.so"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/../../DQml/libDQml.a"
|
|
||||||
)
|
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
import dqml;
|
|
||||||
|
|
||||||
@QtProperty(string.stringof, "name", "getName", "setName", "nameChanged")
|
|
||||||
@QtProperty(string.stringof, "surname", "getSurname", "setSurname", "surnameChanged")
|
|
||||||
class Contact : QObject
|
|
||||||
{
|
|
||||||
mixin InjectQObjectMacro;
|
|
||||||
mixin(Q_OBJECT!(Contact));
|
|
||||||
|
|
||||||
this()
|
|
||||||
{}
|
|
||||||
|
|
||||||
~this()
|
|
||||||
{}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public string getName()
|
|
||||||
{
|
|
||||||
return m_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public void setName(string name)
|
|
||||||
{
|
|
||||||
if (m_name != name)
|
|
||||||
{
|
|
||||||
m_name = name;
|
|
||||||
emit("nameChanged", name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSignal()
|
|
||||||
public void nameChanged(string name);
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public string getSurname()
|
|
||||||
{
|
|
||||||
return m_surname;
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSlot()
|
|
||||||
public void setSurname(string surname)
|
|
||||||
{
|
|
||||||
m_surname = surname;
|
|
||||||
}
|
|
||||||
|
|
||||||
@QtSignal()
|
|
||||||
void surnameChanged(string surname);
|
|
||||||
|
|
||||||
private string m_name;
|
|
||||||
private string m_surname;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
import std.stdio;
|
|
||||||
import dqml;
|
|
||||||
import contact;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto app = new QApplication();
|
|
||||||
scope(exit) destroy(app);
|
|
||||||
|
|
||||||
auto contact = new Contact();
|
|
||||||
scope(exit) destroy(contact);
|
|
||||||
|
|
||||||
auto variant = new QVariant(contact);
|
|
||||||
scope(exit) destroy(variant);
|
|
||||||
|
|
||||||
auto engine = new QQmlApplicationEngine();
|
|
||||||
scope(exit) destroy(engine);
|
|
||||||
|
|
||||||
engine.rootContext().setContextProperty("contact", variant);
|
|
||||||
engine.load("main.qml");
|
|
||||||
app.exec();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow {
|
|
||||||
width: 400
|
|
||||||
height: 300
|
|
||||||
visible: true
|
|
||||||
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Label { text: "Current name is:" + contact.name }
|
|
||||||
|
|
||||||
TextField { id: textField }
|
|
||||||
|
|
||||||
Button{
|
|
||||||
text: "Change Name"
|
|
||||||
onClicked: contact.name = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
# < 2.8.10 backward compatibility
|
|
||||||
if(NOT CMAKE_PLATFORM_INFO_DIR)
|
|
||||||
set(CMAKE_PLATFORM_INFO_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY})
|
|
||||||
endif(NOT CMAKE_PLATFORM_INFO_DIR)
|
|
||||||
|
|
||||||
set(CMAKE_D_COMPILER "@CMAKE_D_COMPILER@")
|
|
||||||
set(CMAKE_D_COMPILER_ARG1 "@CMAKE_D_COMPILER_ARG1@")
|
|
||||||
set(CMAKE_D_COMPILER_ID "@CMAKE_D_COMPILER_ID@")
|
|
||||||
set(CMAKE_D_PLATFORM_ID "@CMAKE_D_PLATFORM_ID@")
|
|
||||||
@SET_MSVC_D_ARCHITECTURE_ID@
|
|
||||||
set(CMAKE_AR "@CMAKE_AR@")
|
|
||||||
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
|
|
||||||
set(CMAKE_LINKER "@CMAKE_LINKER@")
|
|
||||||
set(CMAKE_COMPILER_IS_GDC @CMAKE_COMPILER_IS_GDC@)
|
|
||||||
set(CMAKE_COMPILER_IS_DMD @CMAKE_COMPILER_IS_DMD@)
|
|
||||||
set(CMAKE_D_COMPILER_LOADED 1)
|
|
||||||
set(CMAKE_COMPILER_IS_MINGW @CMAKE_COMPILER_IS_MINGW@)
|
|
||||||
set(CMAKE_COMPILER_IS_CYGWIN @CMAKE_COMPILER_IS_CYGWIN@)
|
|
||||||
if(CMAKE_COMPILER_IS_CYGWIN)
|
|
||||||
set(CYGWIN 1)
|
|
||||||
set(UNIX 1)
|
|
||||||
endif(CMAKE_COMPILER_IS_CYGWIN)
|
|
||||||
|
|
||||||
set(CMAKE_D_COMPILER_ENV_VAR "DC")
|
|
||||||
|
|
||||||
if(CMAKE_COMPILER_IS_MINGW)
|
|
||||||
set(MINGW 1)
|
|
||||||
endif(CMAKE_COMPILER_IS_MINGW)
|
|
||||||
set(CMAKE_D_SOURCE_FILE_EXTENSIONS d;di)
|
|
||||||
set(CMAKE_D_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
|
|
||||||
# Prefer to use D's linker.
|
|
||||||
# The D value 40 beats CXX value of 30 and C value of 10
|
|
||||||
set(CMAKE_D_LINKER_PREFERENCE 40 )
|
|
||||||
set(CMAKE_D_LINKER_PREFERENCE_PROPOGATES 1 )
|
|
||||||
# Save compiler ABI information.
|
|
||||||
set(CMAKE_D_SIZEOF_DATA_PTR "@CMAKE_D_SIZEOF_DATA_PTR@")
|
|
||||||
set(CMAKE_D_COMPILER_ABI "@CMAKE_D_COMPILER_ABI@")
|
|
||||||
|
|
||||||
if(CMAKE_D_SIZEOF_DATA_PTR)
|
|
||||||
set(CMAKE_SIZEOF_VOID_P "${CMAKE_D_SIZEOF_DATA_PTR}")
|
|
||||||
endif(CMAKE_D_SIZEOF_DATA_PTR)
|
|
||||||
|
|
||||||
if(CMAKE_D_COMPILER_ABI)
|
|
||||||
set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_D_COMPILER_ABI}")
|
|
||||||
endif(CMAKE_D_COMPILER_ABI)
|
|
||||||
|
|
||||||
set(CMAKE_D_HAS_ISYSROOT "@CMAKE_D_HAS_ISYSROOT@")
|
|
||||||
@CMAKE_D_OSX_DEPLOYMENT_TARGET_FLAG_CODE@
|
|
||||||
|
|
||||||
set(CMAKE_D_IMPLICIT_LINK_LIBRARIES "@CMAKE_D_IMPLICIT_LINK_LIBRARIES@")
|
|
||||||
set(CMAKE_D_IMPLICIT_LINK_DIRECTORIES "@CMAKE_D_IMPLICIT_LINK_DIRECTORIES@")
|
|
|
@ -1,5 +0,0 @@
|
||||||
int main(string[] args)
|
|
||||||
{
|
|
||||||
int require = 0;
|
|
||||||
return require;
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
version(DigitalMars)
|
|
||||||
{
|
|
||||||
const string COMPILER_ID = "DigitalMars";
|
|
||||||
}
|
|
||||||
else version(GNU)
|
|
||||||
{
|
|
||||||
const string COMPILER_ID = "GNU";
|
|
||||||
}
|
|
||||||
else version(LDC)
|
|
||||||
{
|
|
||||||
const string COMPILER_ID = "LDC";
|
|
||||||
}
|
|
||||||
else version(SDC)
|
|
||||||
{
|
|
||||||
const string COMPILER_ID = "SDC";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const string COMPILER_ID = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Construct the string literal in pieces to prevent the source from
|
|
||||||
getting matched. Store it in a pointer rather than an array
|
|
||||||
because some compilers will just produce instructions to fill the
|
|
||||||
array rather than assigning a pointer to a static array. */
|
|
||||||
string info_compiler = "INFO" ":" "compiler[" ~ COMPILER_ID ~ "]";
|
|
||||||
|
|
||||||
@CMAKE_D_COMPILER_ID_PLATFORM_CONTENT@
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int main(string[] args)
|
|
||||||
{
|
|
||||||
int require = 0;
|
|
||||||
require += info_compiler[args.length];
|
|
||||||
require += info_platform[args.length];
|
|
||||||
require += info_arch[args.length];
|
|
||||||
return require;
|
|
||||||
}
|
|
|
@ -1,280 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2013, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
# Steve King <sk@metrokings.com>
|
|
||||||
# Dragos Carp <dragos.carp@gmail.com>
|
|
||||||
# Konstantin Oblaukhov <oblaukhov.konstantin@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
# Modified from CMake 2.6.5 CMakeCInformation.cmake
|
|
||||||
# See http://www.cmake.org/HTML/Copyright.html for details
|
|
||||||
#
|
|
||||||
|
|
||||||
# This file sets the basic flags for the D language in CMake.
|
|
||||||
# It also loads the available platform file for the system-compiler
|
|
||||||
# if it exists.
|
|
||||||
# It also loads a system - compiler - processor (or target hardware)
|
|
||||||
# specific file, which is mainly useful for crosscompiling and embedded systems.
|
|
||||||
|
|
||||||
# Load compiler-specific information.
|
|
||||||
|
|
||||||
set(_INCLUDED_FILE 0) # reset the indicator if an include occurred.
|
|
||||||
|
|
||||||
if(CMAKE_D_COMPILER_ID)
|
|
||||||
include(Compiler/${CMAKE_D_COMPILER_ID}-D OPTIONAL)
|
|
||||||
endif(CMAKE_D_COMPILER_ID)
|
|
||||||
|
|
||||||
# set(CMAKE_D_OUTPUT_EXTENSION .o)
|
|
||||||
set(CMAKE_C_OUTPUT_EXTENSION_REPLACE TRUE )
|
|
||||||
set(CMAKE_D_OUTPUT_EXTENSION_REPLACE TRUE )
|
|
||||||
|
|
||||||
set(CMAKE_BASE_NAME)
|
|
||||||
get_filename_component(CMAKE_BASE_NAME ${CMAKE_D_COMPILER} NAME_WE)
|
|
||||||
|
|
||||||
set(_INCLUDED_FILE 0) # reset the indicator if an include occurred.
|
|
||||||
|
|
||||||
# load a hardware specific file, mostly useful for embedded compilers
|
|
||||||
if(CMAKE_SYSTEM_PROCESSOR)
|
|
||||||
if(CMAKE_D_COMPILER_ID)
|
|
||||||
include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_D_COMPILER_ID}-D-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
|
|
||||||
endif(CMAKE_D_COMPILER_ID)
|
|
||||||
if(NOT _INCLUDED_FILE)
|
|
||||||
include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
|
|
||||||
endif(NOT _INCLUDED_FILE)
|
|
||||||
endif(CMAKE_SYSTEM_PROCESSOR)
|
|
||||||
|
|
||||||
set(_INCLUDED_FILE 0) # reset the indicator if an include occurred.
|
|
||||||
|
|
||||||
# load the system- and compiler specific files
|
|
||||||
if(CMAKE_D_COMPILER_ID)
|
|
||||||
include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_D_COMPILER_ID}-D
|
|
||||||
OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
|
|
||||||
endif(CMAKE_D_COMPILER_ID)
|
|
||||||
|
|
||||||
# if no high specificity file was included, then try a more general one
|
|
||||||
if(NOT _INCLUDED_FILE)
|
|
||||||
include(Platform/${CMAKE_SYSTEM_NAME}-${CMAKE_BASE_NAME}
|
|
||||||
OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
|
|
||||||
endif(NOT _INCLUDED_FILE)
|
|
||||||
|
|
||||||
# We specify the compiler information in the system file for some
|
|
||||||
# platforms, but this language may not have been enabled when the file
|
|
||||||
# was first included. Include it again to get the language info.
|
|
||||||
# Remove this when all compiler info is removed from system files.
|
|
||||||
if(NOT _INCLUDED_FILE)
|
|
||||||
include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL)
|
|
||||||
endif(NOT _INCLUDED_FILE)
|
|
||||||
|
|
||||||
|
|
||||||
# This should be included before the _INIT variables are
|
|
||||||
# used to initialize the cache. Since the rule variables
|
|
||||||
# have if blocks on them, users can still define them here.
|
|
||||||
# But, it should still be after the platform file so changes can
|
|
||||||
# be made to those values.
|
|
||||||
|
|
||||||
if(CMAKE_USER_MAKE_RULES_OVERRIDE)
|
|
||||||
include(${CMAKE_USER_MAKE_RULES_OVERRIDE})
|
|
||||||
endif(CMAKE_USER_MAKE_RULES_OVERRIDE)
|
|
||||||
|
|
||||||
if(CMAKE_USER_MAKE_RULES_OVERRIDE_D)
|
|
||||||
include(${CMAKE_USER_MAKE_RULES_OVERRIDE_D})
|
|
||||||
endif(CMAKE_USER_MAKE_RULES_OVERRIDE_D)
|
|
||||||
|
|
||||||
# Lines below was taken from CMakeCXXInformation.cmake
|
|
||||||
# Not all of this flags are available on D compilers for now, but some as OPTIONS_PIC are.
|
|
||||||
|
|
||||||
if(NOT CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS)
|
|
||||||
set(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_D_COMPILE_OPTIONS_PIC)
|
|
||||||
set(CMAKE_DCOMPILE_OPTIONS_PIC ${CMAKE_D_COMPILE_OPTIONS_PIC})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_D_COMPILE_OPTIONS_PIE)
|
|
||||||
set(CMAKE_D_COMPILE_OPTIONS_PIE ${CMAKE_D_COMPILE_OPTIONS_PIE})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_D_COMPILE_OPTIONS_DLL)
|
|
||||||
set(CMAKE_D_COMPILE_OPTIONS_DLL ${CMAKE_D_COMPILE_OPTIONS_DLL})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_SHARED_LIBRARY_D_FLAGS)
|
|
||||||
set(CMAKE_SHARED_LIBRARY_D_FLAGS ${CMAKE_SHARED_LIBRARY_D_FLAGS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_D_FLAGS)
|
|
||||||
set(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_D_FLAGS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG)
|
|
||||||
set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP)
|
|
||||||
set(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG)
|
|
||||||
set(CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_EXE_EXPORTS_D_FLAG)
|
|
||||||
set(CMAKE_EXE_EXPORTS_D_FLAG ${CMAKE_EXE_EXPORTS_D_FLAG})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_SHARED_LIBRARY_SONAME_D_FLAG)
|
|
||||||
set(CMAKE_SHARED_LIBRARY_SONAME_D_FLAG ${CMAKE_SHARED_LIBRARY_SONAME_D_FLAG})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_EXECUTABLE_RUNTIME_D_FLAG)
|
|
||||||
set(CMAKE_EXECUTABLE_RUNTIME_D_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_EXECUTABLE_RUNTIME_D_FLAG_SEP)
|
|
||||||
set(CMAKE_EXECUTABLE_RUNTIME_D_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_EXECUTABLE_RPATH_LINK_D_FLAG)
|
|
||||||
set(CMAKE_EXECUTABLE_RPATH_LINK_D_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_D_WITH_RUNTIME_PATH)
|
|
||||||
set(CMAKE_SHARED_LIBRARY_LINK_D_WITH_RUNTIME_PATH ${CMAKE_SHARED_LIBRARY_LINK_D_WITH_RUNTIME_PATH})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_INCLUDE_FLAG_D)
|
|
||||||
set(CMAKE_INCLUDE_FLAG_D ${CMAKE_INCLUDE_FLAG_D})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_INCLUDE_FLAG_SEP_D)
|
|
||||||
set(CMAKE_INCLUDE_FLAG_SEP_D ${CMAKE_INCLUDE_FLAG_SEP_D})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# for most systems a module is the same as a shared library
|
|
||||||
# so unless the variable CMAKE_MODULE_EXISTS is set just
|
|
||||||
# copy the values from the LIBRARY variables
|
|
||||||
if(NOT CMAKE_MODULE_EXISTS)
|
|
||||||
set(CMAKE_SHARED_MODULE_D_FLAGS ${CMAKE_SHARED_LIBRARY_D_FLAGS})
|
|
||||||
set(CMAKE_SHARED_MODULE_CREATE_D_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS})
|
|
||||||
endif(NOT CMAKE_MODULE_EXISTS)
|
|
||||||
|
|
||||||
# repeat for modules
|
|
||||||
if(NOT CMAKE_SHARED_MODULE_CREATE_D_FLAGS)
|
|
||||||
set(CMAKE_SHARED_MODULE_CREATE_D_FLAGS ${CMAKE_SHARED_MODULE_CREATE_D_FLAGS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT CMAKE_SHARED_MODULE_D_FLAGS)
|
|
||||||
set(CMAKE_SHARED_MODULE_D_FLAGS ${CMAKE_SHARED_MODULE_D_FLAGS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_D_FLAGS_INIT "$ENV{DFLAGS} ${CMAKE_D_FLAGS_INIT}")
|
|
||||||
# avoid just having a space as the initial value for the cache
|
|
||||||
if(CMAKE_D_FLAGS_INIT STREQUAL " ")
|
|
||||||
set(CMAKE_D_FLAGS_INIT)
|
|
||||||
endif(CMAKE_D_FLAGS_INIT STREQUAL " ")
|
|
||||||
set(CMAKE_D_FLAGS "${CMAKE_D_FLAGS_INIT}" CACHE STRING
|
|
||||||
"Flags used by the D compiler during all build types.")
|
|
||||||
|
|
||||||
if(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
|
|
||||||
# default build type is none
|
|
||||||
if(NOT CMAKE_NO_BUILD_TYPE)
|
|
||||||
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE_INIT} CACHE STRING
|
|
||||||
"Choose the type of build, options are: None(CMAKE_D_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
|
|
||||||
endif(NOT CMAKE_NO_BUILD_TYPE)
|
|
||||||
set(CMAKE_D_FLAGS_DEBUG "${CMAKE_D_FLAGS_DEBUG_INIT}" CACHE STRING
|
|
||||||
"Flags used by the compiler during debug builds.")
|
|
||||||
set(CMAKE_D_FLAGS_MINSIZEREL "${CMAKE_D_FLAGS_MINSIZEREL_INIT}" CACHE STRING
|
|
||||||
"Flags used by the compiler during release minsize builds.")
|
|
||||||
set(CMAKE_D_FLAGS_RELEASE "${CMAKE_D_FLAGS_RELEASE_INIT}" CACHE STRING
|
|
||||||
"Flags used by the compiler during release builds (/MD /Ob1 /Oi /Ot /Oy /Gs will produce slightly less optimized but smaller files).")
|
|
||||||
set(CMAKE_D_FLAGS_RELWITHDEBINFO "${CMAKE_D_FLAGS_RELWITHDEBINFO_INIT}" CACHE STRING
|
|
||||||
"Flags used by the compiler during Release with Debug Info builds.")
|
|
||||||
endif(NOT CMAKE_NOT_USING_CONFIG_FLAGS)
|
|
||||||
|
|
||||||
if(CMAKE_D_STANDARD_LIBRARIES_INIT)
|
|
||||||
set(CMAKE_D_STANDARD_LIBRARIES "${CMAKE_D_STANDARD_LIBRARIES_INIT}"
|
|
||||||
CACHE STRING "Libraries linked by default with all D applications.")
|
|
||||||
mark_as_advanced(CMAKE_D_STANDARD_LIBRARIES)
|
|
||||||
endif(CMAKE_D_STANDARD_LIBRARIES_INIT)
|
|
||||||
|
|
||||||
include(CMakeCommonLanguageInclude)
|
|
||||||
|
|
||||||
# now define the following rule variables
|
|
||||||
|
|
||||||
# CMAKE_D_CREATE_SHARED_LIBRARY
|
|
||||||
# CMAKE_D_CREATE_SHARED_MODULE
|
|
||||||
# CMAKE_D_CREATE_STATIC_LIBRARY
|
|
||||||
# CMAKE_D_COMPILE_OBJECT
|
|
||||||
# CMAKE_D_LINK_EXECUTABLE
|
|
||||||
|
|
||||||
# variables supplied by the generator at use time
|
|
||||||
# <TARGET>
|
|
||||||
# <TARGET_BASE> the target without the suffix
|
|
||||||
# <OBJECTS>
|
|
||||||
# <OBJECT>
|
|
||||||
# <LINK_LIBRARIES>
|
|
||||||
# <FLAGS>
|
|
||||||
# <LINK_FLAGS>
|
|
||||||
|
|
||||||
# D compiler information
|
|
||||||
# <CMAKE_D_COMPILER>
|
|
||||||
# <CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS>
|
|
||||||
# <CMAKE_SHARED_MODULE_CREATE_D_FLAGS>
|
|
||||||
# <CMAKE_D_LINK_FLAGS>
|
|
||||||
|
|
||||||
# Static library tools
|
|
||||||
# <CMAKE_AR>
|
|
||||||
# <CMAKE_RANLIB>
|
|
||||||
|
|
||||||
# < 2.8.10 backward compatibility
|
|
||||||
if(NOT CMAKE_PLATFORM_INFO_DIR)
|
|
||||||
set(CMAKE_PLATFORM_INFO_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY})
|
|
||||||
endif(NOT CMAKE_PLATFORM_INFO_DIR)
|
|
||||||
|
|
||||||
# create a D shared library
|
|
||||||
if(NOT CMAKE_D_CREATE_SHARED_LIBRARY)
|
|
||||||
set(CMAKE_D_CREATE_SHARED_LIBRARY
|
|
||||||
"<CMAKE_D_COMPILER> <CMAKE_SHARED_LIBRARY_D_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_D_FLAG><TARGET_SONAME> ${CMAKE_D_DASH_O}<TARGET> <OBJECTS> <LINK_LIBRARIES> ${DSTDLIB_FLAGS} ${CMAKE_D_STDLIBS}")
|
|
||||||
endif(NOT CMAKE_D_CREATE_SHARED_LIBRARY)
|
|
||||||
|
|
||||||
# create a D shared module just copy the shared library rule
|
|
||||||
if(NOT CMAKE_D_CREATE_SHARED_MODULE)
|
|
||||||
set(CMAKE_D_CREATE_SHARED_MODULE "${CMAKE_D_CREATE_SHARED_LIBRARY}")
|
|
||||||
endif(NOT CMAKE_D_CREATE_SHARED_MODULE)
|
|
||||||
|
|
||||||
if(NOT CMAKE_D_CREATE_STATIC_LIBRARY AND CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS)
|
|
||||||
set(CMAKE_D_CREATE_STATIC_LIBRARY
|
|
||||||
"<CMAKE_D_COMPILER> ${CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS} <OBJECTS> ${CMAKE_D_DASH_O}<TARGET>")
|
|
||||||
endif(NOT CMAKE_D_CREATE_STATIC_LIBRARY AND CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS)
|
|
||||||
|
|
||||||
# Create a static archive incrementally for large object file counts.
|
|
||||||
# If CMAKE_D_CREATE_STATIC_LIBRARY is set it will override these.
|
|
||||||
set(CMAKE_D_ARCHIVE_CREATE "<CMAKE_AR> cr <TARGET> <LINK_FLAGS> <OBJECTS>")
|
|
||||||
set(CMAKE_D_ARCHIVE_APPEND "<CMAKE_AR> r <TARGET> <LINK_FLAGS> <OBJECTS>")
|
|
||||||
set(CMAKE_D_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
|
|
||||||
|
|
||||||
# compile a D file into an object file
|
|
||||||
if(NOT CMAKE_D_COMPILE_OBJECT)
|
|
||||||
set(CMAKE_D_COMPILE_OBJECT
|
|
||||||
"<CMAKE_D_COMPILER> <FLAGS> ${CMAKE_D_DASH_O}<OBJECT> -c <SOURCE>")
|
|
||||||
endif(NOT CMAKE_D_COMPILE_OBJECT)
|
|
||||||
|
|
||||||
if(NOT CMAKE_D_LINK_EXECUTABLE)
|
|
||||||
set(CMAKE_D_LINK_EXECUTABLE
|
|
||||||
"<CMAKE_D_COMPILER> <FLAGS> <CMAKE_D_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> ${CMAKE_D_DASH_O}<TARGET> <LINK_LIBRARIES> ${CMAKE_D_STDLIBS}")
|
|
||||||
endif(NOT CMAKE_D_LINK_EXECUTABLE)
|
|
||||||
|
|
||||||
mark_as_advanced(
|
|
||||||
CMAKE_D_FLAGS
|
|
||||||
CMAKE_D_FLAGS_DEBUG
|
|
||||||
CMAKE_D_FLAGS_MINSIZEREL
|
|
||||||
CMAKE_D_FLAGS_RELEASE
|
|
||||||
CMAKE_D_FLAGS_RELWITHDEBINFO
|
|
||||||
)
|
|
||||||
set(CMAKE_D_INFORMATION_LOADED 1)
|
|
|
@ -1,163 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2013, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
# Dragos Carp <dragos.carp@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
# Modified from CMake 2.6.5 CMakeDetermineCCompiler.cmake
|
|
||||||
# See http://www.cmake.org/HTML/Copyright.html for details
|
|
||||||
#
|
|
||||||
|
|
||||||
# determine the compiler to use for D programs
|
|
||||||
# NOTE, a generator may set CMAKE_D_COMPILER before
|
|
||||||
# loading this file to force a compiler.
|
|
||||||
# use environment variable DC first if defined by user, next use
|
|
||||||
# the cmake variable CMAKE_GENERATOR_D which can be defined by a generator
|
|
||||||
# as a default compiler
|
|
||||||
|
|
||||||
if(NOT CMAKE_D_COMPILER)
|
|
||||||
set(CMAKE_D_COMPILER_INIT NOTFOUND)
|
|
||||||
# prefer the environment variable DC
|
|
||||||
if($ENV{DC} MATCHES ".+")
|
|
||||||
get_filename_component(CMAKE_D_COMPILER_INIT $ENV{DC} PROGRAM PROGRAM_ARGS CMAKE_D_FLAGS_ENV_INIT)
|
|
||||||
if(CMAKE_D_FLAGS_ENV_INIT)
|
|
||||||
set(CMAKE_D_COMPILER_ARG1 "${CMAKE_D_FLAGS_ENV_INIT}" CACHE STRING "First argument to D compiler")
|
|
||||||
endif(CMAKE_D_FLAGS_ENV_INIT)
|
|
||||||
if(NOT EXISTS ${CMAKE_D_COMPILER_INIT})
|
|
||||||
MESSAGE(FATAL_ERROR "Could not find compiler set in environment variable C:\n$ENV{DC}.")
|
|
||||||
endif(NOT EXISTS ${CMAKE_D_COMPILER_INIT})
|
|
||||||
endif($ENV{DC} MATCHES ".+")
|
|
||||||
|
|
||||||
# next try prefer the compiler specified by the generator
|
|
||||||
if(CMAKE_GENERATOR_D)
|
|
||||||
if(NOT CMAKE_D_COMPILER_INIT)
|
|
||||||
set(CMAKE_D_COMPILER_INIT ${CMAKE_GENERATOR_D})
|
|
||||||
endif(NOT CMAKE_D_COMPILER_INIT)
|
|
||||||
endif(CMAKE_GENERATOR_D)
|
|
||||||
|
|
||||||
# finally list compilers to try
|
|
||||||
if(CMAKE_D_COMPILER_INIT)
|
|
||||||
set(CMAKE_D_COMPILER_LIST ${CMAKE_D_COMPILER_INIT})
|
|
||||||
else(CMAKE_D_COMPILER_INIT)
|
|
||||||
set(CMAKE_D_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}gdc ${_CMAKE_TOOLCHAIN_PREFIX}dmd)
|
|
||||||
endif(CMAKE_D_COMPILER_INIT)
|
|
||||||
|
|
||||||
# Find the compiler.
|
|
||||||
if(_CMAKE_USER_D_COMPILER_PATH)
|
|
||||||
find_program(CMAKE_D_COMPILER NAMES ${CMAKE_D_COMPILER_LIST} PATHS ${_CMAKE_USER_D_COMPILER_PATH} DOC "D compiler" NO_DEFAULT_PATH)
|
|
||||||
endif(_CMAKE_USER_D_COMPILER_PATH)
|
|
||||||
find_program(CMAKE_D_COMPILER NAMES ${CMAKE_D_COMPILER_LIST} DOC "D compiler")
|
|
||||||
|
|
||||||
if(CMAKE_D_COMPILER_INIT AND NOT CMAKE_D_COMPILER)
|
|
||||||
set(CMAKE_D_COMPILER "${CMAKE_D_COMPILER_INIT}" CACHE FILEPATH "D compiler" FORCE)
|
|
||||||
endif(CMAKE_D_COMPILER_INIT AND NOT CMAKE_D_COMPILER)
|
|
||||||
else(NOT CMAKE_D_COMPILER)
|
|
||||||
|
|
||||||
# we only get here if CMAKE_D_COMPILER was specified using -D or a pre-made CMakeCache.txt
|
|
||||||
# (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
|
|
||||||
# if CMAKE_D_COMPILER is a list of length 2, use the first item as
|
|
||||||
# CMAKE_D_COMPILER and the 2nd one as CMAKE_D_COMPILER_ARG1
|
|
||||||
|
|
||||||
list(LENGTH CMAKE_D_COMPILER _CMAKE_D_COMPILER_LIST_LENGTH)
|
|
||||||
if("${_CMAKE_D_COMPILER_LIST_LENGTH}" EQUAL 2)
|
|
||||||
list(GET CMAKE_D_COMPILER 1 CMAKE_D_COMPILER_ARG1)
|
|
||||||
list(GET CMAKE_D_COMPILER 0 CMAKE_D_COMPILER)
|
|
||||||
endif("${_CMAKE_D_COMPILER_LIST_LENGTH}" EQUAL 2)
|
|
||||||
|
|
||||||
# if a compiler was specified by the user but without path,
|
|
||||||
# now try to find it with the full path
|
|
||||||
# if it is found, force it into the cache,
|
|
||||||
# if not, don't overwrite the setting (which was given by the user) with "NOTFOUND"
|
|
||||||
# if the C compiler already had a path, reuse it for searching the CXX compiler
|
|
||||||
get_filename_component(_CMAKE_USER_D_COMPILER_PATH "${CMAKE_D_COMPILER}" PATH)
|
|
||||||
if(NOT _CMAKE_USER_D_COMPILER_PATH)
|
|
||||||
find_program(CMAKE_D_COMPILER_WITH_PATH NAMES ${CMAKE_D_COMPILER})
|
|
||||||
mark_as_advanced(CMAKE_D_COMPILER_WITH_PATH)
|
|
||||||
if(CMAKE_D_COMPILER_WITH_PATH)
|
|
||||||
set(CMAKE_D_COMPILER ${CMAKE_D_COMPILER_WITH_PATH} CACHE STRING "D compiler" FORCE)
|
|
||||||
endif(CMAKE_D_COMPILER_WITH_PATH)
|
|
||||||
endif(NOT _CMAKE_USER_D_COMPILER_PATH)
|
|
||||||
endif(NOT CMAKE_D_COMPILER)
|
|
||||||
mark_as_advanced(CMAKE_D_COMPILER)
|
|
||||||
|
|
||||||
if(NOT _CMAKE_TOOLCHAIN_LOCATION)
|
|
||||||
get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_D_COMPILER}" PATH)
|
|
||||||
endif(NOT _CMAKE_TOOLCHAIN_LOCATION)
|
|
||||||
|
|
||||||
# Build a small source file to identify the compiler.
|
|
||||||
if(${CMAKE_GENERATOR} MATCHES "Visual Studio")
|
|
||||||
set(CMAKE_D_COMPILER_ID_RUN 1)
|
|
||||||
set(CMAKE_D_PLATFORM_ID "Windows")
|
|
||||||
|
|
||||||
# TODO: Set the compiler id. It is probably MSVC but
|
|
||||||
# the user may be using an integrated Intel compiler.
|
|
||||||
# set(CMAKE_D_COMPILER_ID "MSVC")
|
|
||||||
endif(${CMAKE_GENERATOR} MATCHES "Visual Studio")
|
|
||||||
|
|
||||||
if(NOT CMAKE_D_COMPILER_ID_RUN)
|
|
||||||
set(CMAKE_D_COMPILER_ID_RUN 1)
|
|
||||||
|
|
||||||
# Each entry in this list is a set of extra flags to try
|
|
||||||
# adding to the compile line to see if it helps produce
|
|
||||||
# a valid identification file.
|
|
||||||
set(CMAKE_D_COMPILER_ID_TEST_FLAGS
|
|
||||||
# Try compiling to an object file only.
|
|
||||||
"-c"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Try to identify the compiler.
|
|
||||||
set(CMAKE_D_COMPILER_ID)
|
|
||||||
find_file(CMAKE_PLATFORM_ID_CONTENT_FILE CMakePlatformId.di.in PATHS ${CMAKE_ROOT}/Modules
|
|
||||||
${CMAKE_MODULE_PATH} NO_DEFAULT_PATH)
|
|
||||||
file(READ ${CMAKE_PLATFORM_ID_CONTENT_FILE} CMAKE_D_COMPILER_ID_PLATFORM_CONTENT)
|
|
||||||
find_file(CMAKE_D_COMPILER_ID_FILE_IN CMakeDCompilerId.d.in PATHS ${CMAKE_ROOT}/Modules
|
|
||||||
${CMAKE_MODULE_PATH} NO_DEFAULT_PATH)
|
|
||||||
# Workaround for bug http://public.kitware.com/Bug/view.php?id=14481
|
|
||||||
# if CMAKE_MODULE_PATH is used, then patch ${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake
|
|
||||||
get_filename_component(CMAKE_D_COMPILER_ID_FILE_IN_PATH ${CMAKE_D_COMPILER_ID_FILE_IN} PATH)
|
|
||||||
if(CMAKE_MAJOR_VERSION GREATER 2 OR CMAKE_D_COMPILER_ID_FILE_IN_PATH STREQUAL ${CMAKE_ROOT}/Modules)
|
|
||||||
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
|
|
||||||
else(CMAKE_D_COMPILER_ID_FILE_IN_PATH STREQUAL ${CMAKE_ROOT}/Modules)
|
|
||||||
file(READ ${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake CMAKE_DETERMINE_COMPILER_ID_CMAKE_CONTENT)
|
|
||||||
STRING(REPLACE "file(READ \${CMAKE_ROOT}/Modules/\${src}.in ID_CONTENT_IN)"
|
|
||||||
"find_file(src_in \${src}.in PATHS \${CMAKE_ROOT}/Modules \${CMAKE_MODULE_PATH} NO_DEFAULT_PATH)
|
|
||||||
file(READ \${src_in} ID_CONTENT_IN)
|
|
||||||
unset(src_in CACHE)"
|
|
||||||
CMAKE_DETERMINE_COMPILER_ID_CMAKE_CONTENT_PATCHED ${CMAKE_DETERMINE_COMPILER_ID_CMAKE_CONTENT})
|
|
||||||
file(WRITE ${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerId.cmake
|
|
||||||
${CMAKE_DETERMINE_COMPILER_ID_CMAKE_CONTENT_PATCHED})
|
|
||||||
include(${CMAKE_PLATFORM_INFO_DIR}/CMakeDetermineCompilerId.cmake)
|
|
||||||
endif(CMAKE_MAJOR_VERSION GREATER 2 OR CMAKE_D_COMPILER_ID_FILE_IN_PATH STREQUAL ${CMAKE_ROOT}/Modules)
|
|
||||||
CMAKE_DETERMINE_COMPILER_ID(D DFLAGS CMakeDCompilerId.d)
|
|
||||||
unset(CMAKE_D_COMPILER_ID_FILE_IN CACHE)
|
|
||||||
unset(CMAKE_PLATFORM_ID_CONTENT_FILE CACHE)
|
|
||||||
|
|
||||||
# Set old compiler and platform id variables.
|
|
||||||
if("${CMAKE_D_COMPILER_ID}" MATCHES "GNU")
|
|
||||||
set(CMAKE_COMPILER_IS_GDC 1)
|
|
||||||
endif("${CMAKE_D_COMPILER_ID}" MATCHES "GNU")
|
|
||||||
if("${CMAKE_D_PLATFORM_ID}" MATCHES "MinGW")
|
|
||||||
set(CMAKE_COMPILER_IS_MINGW 1)
|
|
||||||
elseif("${CMAKE_D_PLATFORM_ID}" MATCHES "Cygwin")
|
|
||||||
set(CMAKE_COMPILER_IS_CYGWIN 1)
|
|
||||||
endif("${CMAKE_D_PLATFORM_ID}" MATCHES "MinGW")
|
|
||||||
endif(NOT CMAKE_D_COMPILER_ID_RUN)
|
|
||||||
|
|
||||||
include(CMakeFindBinUtils)
|
|
||||||
if(MSVC_D_ARCHITECTURE_ID)
|
|
||||||
set(SET_MSVC_D_ARCHITECTURE_ID
|
|
||||||
"set(MSVC_D_ARCHITECTURE_ID ${MSVC_D_ARCHITECTURE_ID})")
|
|
||||||
endif(MSVC_D_ARCHITECTURE_ID)
|
|
||||||
# configure variables set in this file for fast reload later on
|
|
||||||
find_file(CMAKE_D_COMPILER_CMAKE_IN CMakeDCompiler.cmake.in PATHS ${CMAKE_ROOT}/Modules
|
|
||||||
${CMAKE_MODULE_PATH} NO_DEFAULT_PATH)
|
|
||||||
configure_file(${CMAKE_D_COMPILER_CMAKE_IN}
|
|
||||||
${CMAKE_PLATFORM_INFO_DIR}/CMakeDCompiler.cmake
|
|
||||||
@ONLY IMMEDIATE # IMMEDIATE must be here for compatibility mode <= 2.0
|
|
||||||
)
|
|
||||||
set(CMAKE_D_COMPILER_ENV_VAR "DC")
|
|
|
@ -1,41 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2013, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
# Dragos Carp <dragos.carp@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.1)
|
|
||||||
PROJECT (cmake-d NONE)
|
|
||||||
|
|
||||||
SET (MOD_SRCS
|
|
||||||
CMakeDCompiler.cmake.in
|
|
||||||
CMakeDCompilerId.d.in
|
|
||||||
CMakeDInformation.cmake
|
|
||||||
CMakeDCompilerABI.d
|
|
||||||
CMakeTestDCompiler.cmake
|
|
||||||
CMakeDetermineDCompiler.cmake
|
|
||||||
FindGDCPath.cmake
|
|
||||||
UseDDoc.cmake
|
|
||||||
UseDDeps.cmake
|
|
||||||
UseDub.cmake
|
|
||||||
dependencies.cmake
|
|
||||||
UseDUnittest.cmake
|
|
||||||
FindPhobos.cmake
|
|
||||||
CMakePlatformId.di.in
|
|
||||||
)
|
|
||||||
|
|
||||||
SET (PLAT_SRCS
|
|
||||||
Platform/Linux-dmd.cmake
|
|
||||||
Platform/Linux-gdc.cmake
|
|
||||||
Platform/Linux-ldc2.cmake
|
|
||||||
Platform/Windows-dmd.cmake
|
|
||||||
Platform/Windows-gdc.cmake
|
|
||||||
)
|
|
||||||
|
|
||||||
INSTALL (FILES ${MOD_SRCS} DESTINATION ${CMAKE_ROOT}/Modules)
|
|
||||||
INSTALL (FILES ${PLAT_SRCS} DESTINATION ${CMAKE_ROOT}/Modules/Platform)
|
|
|
@ -1,118 +0,0 @@
|
||||||
/* Identify known platforms by name. */
|
|
||||||
version(linux)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "Linux";
|
|
||||||
}
|
|
||||||
else version(Cygwin)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "Cygwin";
|
|
||||||
}
|
|
||||||
else version(MinGW)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "MinGW";
|
|
||||||
}
|
|
||||||
else version(OSX)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "Darwin";
|
|
||||||
}
|
|
||||||
else version(Windows)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "Windows";
|
|
||||||
}
|
|
||||||
else version(FreeBSD)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "FreeBSD";
|
|
||||||
}
|
|
||||||
else version(NetBSD)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "NetBSD";
|
|
||||||
}
|
|
||||||
else version(OpenBSD)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "OpenBSD";
|
|
||||||
}
|
|
||||||
else version(NetBSD)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "NetBSD";
|
|
||||||
}
|
|
||||||
else version(Solaris)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "SunOS";
|
|
||||||
}
|
|
||||||
else version(AIX)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "AIX";
|
|
||||||
}
|
|
||||||
else version(Haiku)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "Haiku";
|
|
||||||
}
|
|
||||||
else version(AIX)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "BeOS";
|
|
||||||
}
|
|
||||||
else version(AIX)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "QNX";
|
|
||||||
}
|
|
||||||
else version(AIX)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "Tru64";
|
|
||||||
}
|
|
||||||
else version(AIX)
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "RISCos";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const string PLATFORM_ID = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For windows compilers MSVC and Intel we can determine
|
|
||||||
the architecture of the compiler being used. This is because
|
|
||||||
the compilers do not have flags that can change the architecture,
|
|
||||||
but rather depend on which compiler is being used
|
|
||||||
*/
|
|
||||||
version(IA64)
|
|
||||||
{
|
|
||||||
const string ARCHITECTURE_ID = "IA64";
|
|
||||||
}
|
|
||||||
else version(X86_64)
|
|
||||||
{
|
|
||||||
const string ARCHITECTURE_ID = "x64";
|
|
||||||
}
|
|
||||||
else version(X86)
|
|
||||||
{
|
|
||||||
const string ARCHITECTURE_ID = "X86";
|
|
||||||
}
|
|
||||||
else version(ARM)
|
|
||||||
{
|
|
||||||
const string ARCHITECTURE_ID = "ARM";
|
|
||||||
}
|
|
||||||
else version(MIPS32)
|
|
||||||
{
|
|
||||||
const string ARCHITECTURE_ID = "MIPS";
|
|
||||||
}
|
|
||||||
else version(MIPS64)
|
|
||||||
{
|
|
||||||
const string ARCHITECTURE_ID = "MIPS";
|
|
||||||
}
|
|
||||||
else version(SH)
|
|
||||||
{
|
|
||||||
const string ARCHITECTURE_ID = "SHx";
|
|
||||||
}
|
|
||||||
else version(SH64)
|
|
||||||
{
|
|
||||||
const string ARCHITECTURE_ID = "SHx";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const string ARCHITECTURE_ID = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Construct the string literal in pieces to prevent the source from
|
|
||||||
getting matched. Store it in a pointer rather than an array
|
|
||||||
because some compilers will just produce instructions to fill the
|
|
||||||
array rather than assigning a pointer to a static array. */
|
|
||||||
string info_platform = "INFO" ":" "platform[" ~ PLATFORM_ID ~ "]";
|
|
||||||
string info_arch = "INFO" ":" "arch[" ~ ARCHITECTURE_ID ~"]";
|
|
|
@ -1,78 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
# Dragos Carp <dragos.carp@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
# Modified from CMake 2.6.5 CMakeTestCCompiler.cmake
|
|
||||||
# See http://www.cmake.org/HTML/Copyright.html for details
|
|
||||||
#
|
|
||||||
|
|
||||||
include(CMakeTestCompilerCommon)
|
|
||||||
|
|
||||||
# This file is used by EnableLanguage in cmGlobalGenerator to
|
|
||||||
# determine that that selected D compiler can actually compile
|
|
||||||
# and link the most basic of programs. If not, a fatal error
|
|
||||||
# is set and cmake stops processing commands and will not generate
|
|
||||||
# any makefiles or projects.
|
|
||||||
if(NOT CMAKE_D_COMPILER_WORKS)
|
|
||||||
PrintTestCompilerStatus("D" "")
|
|
||||||
file(WRITE ${CMAKE_PLATFORM_INFO_DIR}/CMakeTmp/testDCompiler.d
|
|
||||||
"int main(char[][] args)\n"
|
|
||||||
"{return args.sizeof-1;}\n")
|
|
||||||
try_compile(CMAKE_D_COMPILER_WORKS ${CMAKE_BINARY_DIR}
|
|
||||||
${CMAKE_PLATFORM_INFO_DIR}/CMakeTmp/testDCompiler.d
|
|
||||||
OUTPUT_VARIABLE OUTPUT)
|
|
||||||
set(D_TEST_WAS_RUN 1)
|
|
||||||
endif(NOT CMAKE_D_COMPILER_WORKS)
|
|
||||||
|
|
||||||
if(NOT CMAKE_D_COMPILER_WORKS)
|
|
||||||
PrintTestCompilerStatus("D" " -- broken")
|
|
||||||
message(STATUS "To force a specific D compiler set the DC environment variable")
|
|
||||||
message(STATUS " ie - export DC=\"/usr/bin/dmd\"")
|
|
||||||
file(APPEND ${CMAKE_PLATFORM_INFO_DIR}/CMakeError.log
|
|
||||||
"Determining if the D compiler works failed with "
|
|
||||||
"the following output:\n${OUTPUT}\n\n")
|
|
||||||
# if the compiler is broken make sure to remove the platform file
|
|
||||||
# since Windows-cl configures both c/cxx files both need to be removed
|
|
||||||
# when c or c++ fails
|
|
||||||
file(REMOVE ${CMAKE_PLATFORM_INFO_DIR}/CMakeDPlatform.cmake)
|
|
||||||
message(FATAL_ERROR "The D compiler \"${CMAKE_D_COMPILER}\" "
|
|
||||||
"is not able to compile a simple test program.\nIt fails "
|
|
||||||
"with the following output:\n ${OUTPUT}\n\n"
|
|
||||||
"CMake will not be able to correctly generate this project.")
|
|
||||||
else(NOT CMAKE_D_COMPILER_WORKS)
|
|
||||||
if(D_TEST_WAS_RUN)
|
|
||||||
message(STATUS "Check for working D compiler: ${CMAKE_D_COMPILER} -- works")
|
|
||||||
file(APPEND ${CMAKE_PLATFORM_INFO_DIR}/CMakeOutput.log
|
|
||||||
"Determining if the D compiler works passed with "
|
|
||||||
"the following output:\n${OUTPUT}\n\n")
|
|
||||||
endif(D_TEST_WAS_RUN)
|
|
||||||
set(CMAKE_D_COMPILER_WORKS 1 CACHE INTERNAL "")
|
|
||||||
|
|
||||||
if(CMAKE_D_COMPILER_FORCED)
|
|
||||||
# The compiler configuration was forced by the user.
|
|
||||||
# Assume the user has configured all compiler information.
|
|
||||||
else(CMAKE_D_COMPILER_FORCED)
|
|
||||||
# Try to identify the ABI and configure it into CMakeDCompiler.cmake
|
|
||||||
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
|
|
||||||
find_file(CMAKE_D_COMPILER_ABI_SRC CMakeDCompilerABI.d PATHS ${CMAKE_ROOT}/Modules
|
|
||||||
${CMAKE_MODULE_PATH} NO_DEFAULT_PATH)
|
|
||||||
CMAKE_DETERMINE_COMPILER_ABI(D ${CMAKE_D_COMPILER_ABI_SRC})
|
|
||||||
find_file(CMAKE_D_COMPILER_CMAKE_IN CMakeDCompiler.cmake.in PATHS ${CMAKE_ROOT}/Modules
|
|
||||||
${CMAKE_MODULE_PATH} NO_DEFAULT_PATH)
|
|
||||||
configure_file(
|
|
||||||
${CMAKE_D_COMPILER_CMAKE_IN}
|
|
||||||
${CMAKE_PLATFORM_INFO_DIR}/CMakeDCompiler.cmake
|
|
||||||
@ONLY IMMEDIATE # IMMEDIATE must be here for compatibility mode <= 2.0
|
|
||||||
)
|
|
||||||
include(${CMAKE_PLATFORM_INFO_DIR}/CMakeDCompiler.cmake)
|
|
||||||
unset(CMAKE_D_COMPILER_ABI_SRC CACHE)
|
|
||||||
unset(CMAKE_D_COMPILER_CMAKE_IN CACHE)
|
|
||||||
endif(CMAKE_D_COMPILER_FORCED)
|
|
||||||
endif(NOT CMAKE_D_COMPILER_WORKS)
|
|
|
@ -1,49 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2013, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
# Dragos Carp <dragos.carp@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
# - Find GDC Include Path
|
|
||||||
#
|
|
||||||
# GDC_INCLUDE_PATH = path to where object.d is found
|
|
||||||
#
|
|
||||||
|
|
||||||
set(GDC_POSSIBLE_INCLUDE_PATHS
|
|
||||||
/usr/include/d/4.8.2
|
|
||||||
/usr/include/d/4.8.1
|
|
||||||
/usr/include/d/4.8.0
|
|
||||||
/usr/include/d/4.7.3
|
|
||||||
/usr/include/d/4.7.2
|
|
||||||
/usr/include/d/4.7.1
|
|
||||||
/usr/include/d/4.7.0
|
|
||||||
/usr/include/d/4.2.1
|
|
||||||
/usr/include/d/4.2.0
|
|
||||||
/usr/include/d/4.1.2
|
|
||||||
/usr/include/d/4.1.1
|
|
||||||
/usr/include/d/4.1.0
|
|
||||||
/usr/include/d/4.0.4
|
|
||||||
/usr/include/d/4.0.3
|
|
||||||
/usr/include/d/4.0.2
|
|
||||||
/usr/include/d/4.0.1
|
|
||||||
/usr/include/d/4.0.0
|
|
||||||
/usr/include/d/4.0.6
|
|
||||||
/usr/include/d/4.0.5
|
|
||||||
/usr/include/d/3.4.4
|
|
||||||
/usr/include/d/3.4.3
|
|
||||||
/usr/include/d/3.4.2
|
|
||||||
/usr/include/d/3.4.1
|
|
||||||
/usr/include/d/3.4.0
|
|
||||||
)
|
|
||||||
|
|
||||||
find_path(GDC_INCLUDE_PATH object.d
|
|
||||||
${GDC_POSSIBLE_INCLUDE_PATHS})
|
|
||||||
|
|
||||||
mark_as_advanced(
|
|
||||||
GDC_INCLUDE_PATH
|
|
||||||
)
|
|
|
@ -1,5 +0,0 @@
|
||||||
find_path(PHOBOS_INCLUDE_DIR std/file.d)
|
|
||||||
find_library(PHOBOS_LIBRARY phobos2)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(Phobos DEFAULT_MSG PHOBOS_LIBRARY PHOBOS_INCLUDE_DIR)
|
|
|
@ -1,67 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
# Modified from CMake 2.6.5 gcc.cmake
|
|
||||||
# See http://www.cmake.org/HTML/Copyright.html for details
|
|
||||||
#
|
|
||||||
|
|
||||||
#SET(DSTDLIB_FLAGS "-version=Phobos")
|
|
||||||
IF(CMAKE_D_BUILD_DOCS)
|
|
||||||
SET(DDOC_FLAGS "-D -Dddocumentation")
|
|
||||||
#FOREACH(item ${CMAKE_D_DDOC_FILES})
|
|
||||||
# SET(DDOC_FLAGS "${DDOC_FLAGS} ${item}")
|
|
||||||
#ENDFOREACH(item)
|
|
||||||
ENDIF(CMAKE_D_BUILD_DOCS)
|
|
||||||
|
|
||||||
SET(CMAKE_D_OUTPUT_EXTENSION .o)
|
|
||||||
SET(CMAKE_D_DASH_O "-of")
|
|
||||||
SET(CMAKE_BASE_NAME dmd)
|
|
||||||
|
|
||||||
SET(CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS "-lib")
|
|
||||||
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_D_FLAGS "") # -pic
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared -defaultlib=libphobos2.so") # -shared
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS "") # +s, flag for exe link to use shared lib
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG "") # -rpath
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP "") # : or empty
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_SONAME_D_FLAG "-L-soname=")
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_RPATH_LINK_D_FLAG "-L-rpath=")
|
|
||||||
SET(CMAKE_INCLUDE_FLAG_D "-I") # -I
|
|
||||||
SET(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty
|
|
||||||
SET(CMAKE_LIBRARY_PATH_FLAG "-L-L")
|
|
||||||
SET(CMAKE_LIBRARY_PATH_TERMINATOR "") # for the Digital Mars D compiler the link paths have to be terminated with a "/"
|
|
||||||
SET(CMAKE_LINK_LIBRARY_FLAG "-L-l")
|
|
||||||
|
|
||||||
SET(CMAKE_D_COMPILE_OPTIONS_PIC "-fPIC")
|
|
||||||
|
|
||||||
SET(CMAKE_LINK_LIBRARY_SUFFIX "")
|
|
||||||
SET(CMAKE_STATIC_LIBRARY_PREFIX "lib")
|
|
||||||
SET(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so") # .so
|
|
||||||
SET(CMAKE_EXECUTABLE_SUFFIX "") # .exe
|
|
||||||
SET(CMAKE_DL_LIBS "dl")
|
|
||||||
|
|
||||||
SET(CMAKE_FIND_LIBRARY_PREFIXES "lib")
|
|
||||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
|
|
||||||
|
|
||||||
#SET(CMAKE_D_STDLIBS "-L-lphobos2 -L-lpthread -L-lm -defaultlib=libphobos2.so")
|
|
||||||
|
|
||||||
#SET (CMAKE_D_FLAGS_INIT "-version=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS} ${DSTDLIB_TYPE} -I$ENV{D_PATH}/include -I$ENV{D_PATH}/import -I${CMAKE_PROJECT_SOURCE_DIR}")
|
|
||||||
SET (CMAKE_D_FLAGS_INIT "")
|
|
||||||
|
|
||||||
SET (CMAKE_D_LINK_FLAGS "")
|
|
||||||
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g -debug -L--export-dynamic ${DDOC_FLAGS}")
|
|
||||||
# SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g -L--export-dynamic ${DDOC_FLAGS}")
|
|
||||||
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
|
|
||||||
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -of<ASSEMBLY_SOURCE>")
|
|
||||||
# SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")
|
|
|
@ -1,41 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
# Modified from CMake 2.6.5 gcc.cmake
|
|
||||||
# See http://www.cmake.org/HTML/Copyright.html for details
|
|
||||||
#
|
|
||||||
|
|
||||||
SET(CMAKE_D_DASH_O "-o")
|
|
||||||
SET(CMAKE_BASE_NAME gdc)
|
|
||||||
|
|
||||||
IF(CMAKE_D_USE_TANGO)
|
|
||||||
SET(DSTDLIB_FLAGS "-fversion=Tango")
|
|
||||||
ENDIF(CMAKE_D_USE_TANGO)
|
|
||||||
IF(CMAKE_D_USE_PHOBOS)
|
|
||||||
SET(DSTDLIB_FLAGS "-fversion=Phobos")
|
|
||||||
ENDIF(CMAKE_D_USE_PHOBOS)
|
|
||||||
IF(CMAKE_D_BUILD_DOCS)
|
|
||||||
SET(DDOC_FLAGS "-fdoc -fdoc-dir=documentation")
|
|
||||||
FOREACH(item ${CMAKE_D_DDOC_FILES})
|
|
||||||
SET(DDOC_FLAGS "${DDOC_FLAGS} -fdoc-inc=${item}")
|
|
||||||
ENDFOREACH(item)
|
|
||||||
ENDIF(CMAKE_D_BUILD_DOCS)
|
|
||||||
|
|
||||||
#SET (CMAKE_D_FLAGS_INIT "-fversion=Posix -fversion=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_INIT "")
|
|
||||||
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O3 -fomit-frame-pointer -fweb -frelease -finline-functions ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O2 -g ${DDOC_FLAGS}")
|
|
||||||
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
|
|
||||||
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
|
|
||||||
#SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")
|
|
||||||
|
|
||||||
SET(CMAKE_INCLUDE_FLAG_D "-I") # -I
|
|
|
@ -1,63 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
# Modified from CMake 2.6.5 gcc.cmake
|
|
||||||
# See http://www.cmake.org/HTML/Copyright.html for details
|
|
||||||
#
|
|
||||||
|
|
||||||
#SET(DSTDLIB_FLAGS "-version=Phobos")
|
|
||||||
IF(CMAKE_D_BUILD_DOCS)
|
|
||||||
SET(DDOC_FLAGS "-D -Dddocumentation")
|
|
||||||
#FOREACH(item ${CMAKE_D_DDOC_FILES})
|
|
||||||
# SET(DDOC_FLAGS "${DDOC_FLAGS} ${item}")
|
|
||||||
#ENDFOREACH(item)
|
|
||||||
ENDIF(CMAKE_D_BUILD_DOCS)
|
|
||||||
|
|
||||||
SET(CMAKE_D_OUTPUT_EXTENSION .o)
|
|
||||||
SET(CMAKE_D_DASH_O "-of")
|
|
||||||
SET(CMAKE_BASE_NAME ldc2)
|
|
||||||
|
|
||||||
SET(CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS "-lib")
|
|
||||||
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_D_FLAGS "") # -pic
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared") # -shared
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS "") # +s, flag for exe link to use shared lib
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG "") # -rpath
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP "") # : or empty
|
|
||||||
SET(CMAKE_INCLUDE_FLAG_D "-I") # -I
|
|
||||||
SET(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty
|
|
||||||
SET(CMAKE_LIBRARY_PATH_FLAG "-L-L")
|
|
||||||
SET(CMAKE_LIBRARY_PATH_TERMINATOR "") # for the Digital Mars D compiler the link paths have to be terminated with a "/"
|
|
||||||
SET(CMAKE_LINK_LIBRARY_FLAG "-L-l")
|
|
||||||
|
|
||||||
SET(CMAKE_LINK_LIBRARY_SUFFIX "")
|
|
||||||
SET(CMAKE_STATIC_LIBRARY_PREFIX "lib")
|
|
||||||
SET(CMAKE_STATIC_LIBRARY_SUFFIX ".a")
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".so") # .so
|
|
||||||
SET(CMAKE_EXECUTABLE_SUFFIX "") # .exe
|
|
||||||
SET(CMAKE_DL_LIBS "dl")
|
|
||||||
|
|
||||||
SET(CMAKE_FIND_LIBRARY_PREFIXES "lib")
|
|
||||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
|
|
||||||
|
|
||||||
#SET(CMAKE_D_STDLIBS "-L-lphobos2 -L-lpthread -L-lm" )
|
|
||||||
|
|
||||||
#SET (CMAKE_D_FLAGS_INIT "-version=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS} ${DSTDLIB_TYPE} -I$ENV{D_PATH}/include -I$ENV{D_PATH}/import -I${CMAKE_PROJECT_SOURCE_DIR}")
|
|
||||||
SET (CMAKE_D_FLAGS_INIT "")
|
|
||||||
# DMD can only produce 32-bit binaries for now
|
|
||||||
SET (CMAKE_D_LINK_FLAGS "")
|
|
||||||
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g -debug -L--export-dynamic ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O -release -inline ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g -L--export-dynamic ${DDOC_FLAGS}")
|
|
||||||
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
|
|
||||||
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -of<ASSEMBLY_SOURCE>")
|
|
||||||
# SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")
|
|
|
@ -1,56 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
# Modified from CMake 2.6.5 gcc.cmake
|
|
||||||
# See http://www.cmake.org/HTML/Copyright.html for details
|
|
||||||
#
|
|
||||||
|
|
||||||
#SET(DSTDLIB_FLAGS "-version=Phobos")
|
|
||||||
IF(CMAKE_D_BUILD_DOCS)
|
|
||||||
SET(DDOC_FLAGS "-D -Dddocumentation")
|
|
||||||
#FOREACH(item ${CMAKE_D_DDOC_FILES})
|
|
||||||
# SET(DDOC_FLAGS "${DDOC_FLAGS} ${item}")
|
|
||||||
#ENDFOREACH(item)
|
|
||||||
ENDIF(CMAKE_D_BUILD_DOCS)
|
|
||||||
|
|
||||||
SET(CMAKE_D_OUTPUT_EXTENSION .obj)
|
|
||||||
SET(CMAKE_D_DASH_O "-of")
|
|
||||||
SET(CMAKE_BASE_NAME dmd)
|
|
||||||
|
|
||||||
SET(CMAKE_STATIC_LIBRARY_CREATE_D_FLAGS "-lib")
|
|
||||||
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_D_FLAGS "") # -pic
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_CREATE_D_FLAGS "-shared") # -shared
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_LINK_D_FLAGS "") # +s, flag for exe link to use shared lib
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG "") # -rpath
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_RUNTIME_D_FLAG_SEP "") # : or empty
|
|
||||||
SET(CMAKE_INCLUDE_FLAG_D "-I") # -I
|
|
||||||
SET(CMAKE_INCLUDE_FLAG_D_SEP "") # , or empty
|
|
||||||
SET(CMAKE_LIBRARY_PATH_FLAG "-L-L")
|
|
||||||
SET(CMAKE_LIBRARY_PATH_TERMINATOR "") # for the Digital Mars D compiler the link paths have to be terminated with a "/"
|
|
||||||
|
|
||||||
SET(CMAKE_LINK_LIBRARY_FLAG "-L-l")
|
|
||||||
SET(CMAKE_STATIC_LIBRARY_PREFIX "") #
|
|
||||||
SET(CMAKE_STATIC_LIBRARY_SUFFIX ".lib") # lib
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_PREFIX "") #
|
|
||||||
SET(CMAKE_SHARED_LIBRARY_SUFFIX ".dll") # .dll
|
|
||||||
SET(CMAKE_EXECUTABLE_SUFFIX ".exe") # .exe
|
|
||||||
SET(CMAKE_DL_LIBS "dl")
|
|
||||||
|
|
||||||
SET(CMAKE_FIND_LIBRARY_PREFIXES "")
|
|
||||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll")
|
|
||||||
|
|
||||||
SET (CMAKE_D_FLAGS_INIT "")
|
|
||||||
# DMD can only produce 32-bit binaries for now
|
|
||||||
SET (CMAKE_D_LINK_FLAGS "")
|
|
||||||
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g -debug ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O -release -inline ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O -g ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -of<ASSEMBLY_SOURCE>")
|
|
|
@ -1,35 +0,0 @@
|
||||||
#
|
|
||||||
# CMakeD - CMake module for D Language
|
|
||||||
#
|
|
||||||
# Copyright (c) 2007, Selman Ulug <selman.ulug@gmail.com>
|
|
||||||
# Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
# Modified from CMake 2.6.5 gcc.cmake
|
|
||||||
# See http://www.cmake.org/HTML/Copyright.html for details
|
|
||||||
#
|
|
||||||
|
|
||||||
IF(CMAKE_D_USE_TANGO)
|
|
||||||
SET(DSTDLIB_FLAGS "-fversion=Tango")
|
|
||||||
ENDIF(CMAKE_D_USE_TANGO)
|
|
||||||
IF(CMAKE_D_USE_PHOBOS)
|
|
||||||
SET(DSTDLIB_FLAGS "-fversion=Phobos")
|
|
||||||
ENDIF(CMAKE_D_USE_PHOBOS)
|
|
||||||
IF(CMAKE_D_BUILD_DOCS)
|
|
||||||
SET(DDOC_FLAGS "-fdoc -fdoc-dir=documentation")
|
|
||||||
FOREACH(item ${CMAKE_D_DDOC_FILES})
|
|
||||||
SET(DDOC_FLAGS "${DDOC_FLAGS} -fdoc-inc=${item}")
|
|
||||||
ENDFOREACH(item)
|
|
||||||
ENDIF(CMAKE_D_BUILD_DOCS)
|
|
||||||
|
|
||||||
SET (CMAKE_D_FLAGS_INIT "-fversion=Win -fversion=${CMAKE_BUILD_TYPE}Build ${DSTDLIB_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_DEBUG_INIT "-g ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_MINSIZEREL_INIT "-Os ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELEASE_INIT "-O3 -fomit-frame-pointer -fweb -frelease -finline-functions ${DDOC_FLAGS}")
|
|
||||||
SET (CMAKE_D_FLAGS_RELWITHDEBINFO_INIT "-O2 -g ${DDOC_FLAGS}")
|
|
||||||
# SET (CMAKE_D_CREATE_PREPROCESSED_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -E <SOURCE> > <PREPROCESSED_SOURCE>")
|
|
||||||
SET (CMAKE_D_CREATE_ASSEMBLY_SOURCE "<CMAKE_D_COMPILER> <FLAGS> -S <SOURCE> -o <ASSEMBLY_SOURCE>")
|
|
||||||
#SET (CMAKE_INCLUDE_SYSTEM_FLAG_D "-isystem ")
|
|
|
@ -1,64 +0,0 @@
|
||||||
# Dependency tracking for D
|
|
||||||
#
|
|
||||||
# Copyright (c) 2010 Jens Mueller <jens.k.mueller@gmx.de>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
|
|
||||||
macro(add_executable_with_dependencies _target)
|
|
||||||
# extract D source files from arguments
|
|
||||||
foreach(file ${ARGV})
|
|
||||||
if(${file} MATCHES "\\.d$")
|
|
||||||
list(APPEND d_source_files ${file})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
#message("D files in arguments: ${d_source_files}")
|
|
||||||
|
|
||||||
foreach(file IN LISTS d_source_files)
|
|
||||||
set(source_file "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
|
|
||||||
set(dependency_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${file}-depend.cmake")
|
|
||||||
set(dependency_files ${dependency_files} ${dependency_file})
|
|
||||||
|
|
||||||
#message("Checking dependencies for ${source_file}")
|
|
||||||
#message("Put into ${dependency_file}")
|
|
||||||
# TODO
|
|
||||||
# better way to get the included directories
|
|
||||||
get_directory_property(include_dirs INCLUDE_DIRECTORIES)
|
|
||||||
set(INCLUDES )
|
|
||||||
foreach(include_dir IN LISTS include_dirs)
|
|
||||||
list(APPEND INCLUDES "${CMAKE_INCLUDE_FLAG_D}${include_dir}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-D "CMAKE_D_COMPILER:STRING=${CMAKE_D_COMPILER}"
|
|
||||||
-D "CMAKE_D_FLAGS:STRING=${CMAKE_D_FLAGS}"
|
|
||||||
-D "include_directories:STRING=${INCLUDES}"
|
|
||||||
-D "source_file:STRING=${source_file}"
|
|
||||||
-D "dependency_file:STRING=${dependency_file}"
|
|
||||||
-P "${CMAKE_ROOT}/Modules/dependencies.cmake" # TODO hard coded path
|
|
||||||
)
|
|
||||||
|
|
||||||
# load dependencies from file
|
|
||||||
include(${dependency_file})
|
|
||||||
#message("DEPENDENCIES ${D_DMD_DEPEND}")
|
|
||||||
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${dependency_file}
|
|
||||||
DEPENDS ${D_DMD_DEPEND}
|
|
||||||
COMMAND ${CMAKE_COMMAND}
|
|
||||||
-D "CMAKE_D_COMPILER:STRING=${CMAKE_D_COMPILER}"
|
|
||||||
-D "CMAKE_D_FLAGS:STRING=${CMAKE_D_FLAGS}"
|
|
||||||
-D "include_directories:STRING=${INCLUDES}"
|
|
||||||
-D "source_file:STRING=${source_file}"
|
|
||||||
-D "dependency_file:STRING=${dependency_file}"
|
|
||||||
-P "${CMAKE_ROOT}/Modules/dependencies.cmake" # TODO hard coded path
|
|
||||||
COMMENT "Scanning for dependencies"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
add_executable(${ARGV} ${dependency_files})
|
|
||||||
endmacro(add_executable_with_dependencies)
|
|
|
@ -1,73 +0,0 @@
|
||||||
# check if the user wants to build ddocs
|
|
||||||
#
|
|
||||||
# Copyright (c) 2007 Tim Burrell <tim.burrell@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Do not build documentation by default
|
|
||||||
if (NOT CMAKE_D_BUILD_DOCS)
|
|
||||||
set(CMAKE_D_BUILD_DOCS False CACHE BOOLEAN TRUE FORCE)
|
|
||||||
else (NOT CMAKE_D_BUILD_DOCS)
|
|
||||||
# check for specified ddoc files
|
|
||||||
# default to the candydoc usual
|
|
||||||
set(CMAKE_D_BUILD_DOCS True CACHE BOOLEAN FALSE FORCE)
|
|
||||||
if (NOT CMAKE_D_DDOC_FILES)
|
|
||||||
set(CMAKE_D_DDOC_FILES "documentation/candydoc/candy.ddoc;documentation/candydoc/modules.ddoc" CACHE STRING FALSE FORCE)
|
|
||||||
else (NOT CMAKE_D_DDOC_FILES)
|
|
||||||
set(CMAKE_D_DDOC_FILES "${CMAKE_D_DDOC_FILES}" CACHE STRING FALSE FORCE)
|
|
||||||
endif (NOT CMAKE_D_DDOC_FILES)
|
|
||||||
|
|
||||||
# copy the candydoc files
|
|
||||||
file(GLOB_RECURSE CANDY_DOC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/candydoc/*")
|
|
||||||
foreach(item ${CANDY_DOC_FILES})
|
|
||||||
string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" item ${item})
|
|
||||||
configure_file(${item} ${CMAKE_CURRENT_BINARY_DIR}/documentation/${item} COPYONLY)
|
|
||||||
endforeach(item)
|
|
||||||
|
|
||||||
# create modules.ddoc
|
|
||||||
file(GLOB_RECURSE sources "${CMAKE_CURRENT_SOURCE_DIR}/*.d")
|
|
||||||
set(first True)
|
|
||||||
foreach(item ${sources})
|
|
||||||
# first make sure we're not config.d
|
|
||||||
string(REGEX MATCH "config\\.d" ignore ${item})
|
|
||||||
if (NOT ${ignore} MATCHES "")
|
|
||||||
# fix up the output
|
|
||||||
string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" item ${item})
|
|
||||||
string(REGEX REPLACE "\\.d" ".html" htmlFile ${item})
|
|
||||||
string(REGEX REPLACE "^.*/" "" htmlFile ${htmlFile})
|
|
||||||
string(REGEX REPLACE "\\.d" "" item ${item})
|
|
||||||
string(REGEX REPLACE "/" "." item ${item})
|
|
||||||
if (first)
|
|
||||||
set(modules "${item}")
|
|
||||||
set(first False)
|
|
||||||
set(CMAKE_D_DDOC_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/documentation/${htmlFile}" CACHE STRING FALSE FORCE)
|
|
||||||
else (first)
|
|
||||||
set(modules "${modules};${item}")
|
|
||||||
set(CMAKE_D_DDOC_CLEAN_FILES "${CMAKE_D_DDOC_CLEAN_FILES}" "${CMAKE_CURRENT_BINARY_DIR}/documentation/${htmlFile}" CACHE STRING FALSE FORCE)
|
|
||||||
endif (first)
|
|
||||||
endif (NOT ${ignore} MATCHES "")
|
|
||||||
endforeach(item)
|
|
||||||
|
|
||||||
# create formatted modules string
|
|
||||||
set(modString "MODULES = \n")
|
|
||||||
foreach(item ${modules})
|
|
||||||
set(modString "${modString}\t$(MODULE ${item})\n")
|
|
||||||
endforeach(item)
|
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/documentation/candydoc/modules.ddoc" ${modString})
|
|
||||||
|
|
||||||
# create index.html
|
|
||||||
set(modString "<html><head><title>${PROJECT_NAME} API Documentation</title></head><body>\n")
|
|
||||||
set(modString "<h>${PROJECT_NAME} API Documentation:<br /></h>\n")
|
|
||||||
set(modString "${modString}<ul>\n")
|
|
||||||
foreach(item ${modules})
|
|
||||||
string(REGEX REPLACE "[a-z0-9]*\\." "" filename ${item})
|
|
||||||
set(modString "${modString}\t<li> <a href=\"${filename}.html\">${item}</a> </li>\n")
|
|
||||||
endforeach(item)
|
|
||||||
set(modString "${modString}</ul>\n")
|
|
||||||
set(modString "${modString}</body></html>\n")
|
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/documentation/index.html" ${modString})
|
|
||||||
endif (NOT CMAKE_D_BUILD_DOCS)
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
# Adding D unittests
|
|
||||||
#
|
|
||||||
# Copyright (c) 2010 Jens Mueller <jens.k.mueller@gmx.de>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
|
|
||||||
macro(add_unittests _sourcefile)
|
|
||||||
|
|
||||||
set(_testname "${_sourcefile}")
|
|
||||||
set(main_unittest "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/unittest.d")
|
|
||||||
set(_source_file "${CMAKE_CURRENT_SOURCE_DIR}/${_sourcefile}")
|
|
||||||
|
|
||||||
#message("main_unittest ${main_unittest}")
|
|
||||||
#message("testname ${_testname}")
|
|
||||||
#message("_sourcefile ${_source_file}")
|
|
||||||
|
|
||||||
if(NOT EXISTS ${main_unittest})
|
|
||||||
file(WRITE ${main_unittest} "// Generated by UseDUnittest.cmake\nint main() { return 0; }")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
# better way to get the included directories
|
|
||||||
get_directory_property(include_dirs INCLUDE_DIRECTORIES)
|
|
||||||
set(INCLUDES )
|
|
||||||
foreach(include_dir IN LISTS include_dirs)
|
|
||||||
list(APPEND INCLUDES "${CMAKE_INCLUDE_FLAG_D}${include_dir}")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
separate_arguments(CMAKE_D_FLAGS)
|
|
||||||
|
|
||||||
add_test(NAME ${_testname}
|
|
||||||
COMMAND ${CMAKE_D_COMPILER} ${CMAKE_D_FLAGS} ${INCLUDES} ${main_unittest} -unittest -run ${_source_file})
|
|
||||||
|
|
||||||
endmacro(add_unittests)
|
|
|
@ -1,84 +0,0 @@
|
||||||
# This modules add functions for downloading and building dub dependencies.
|
|
||||||
# This code sets the following variables and functions:
|
|
||||||
#
|
|
||||||
# DUB_DIRECTORY = the full path to Dub pacakges
|
|
||||||
#
|
|
||||||
# DubProject_Add(<dub_package> [version])
|
|
||||||
#
|
|
||||||
#============================================================================
|
|
||||||
# Copyright (c) 2014 Dragos Carp <dragos.carp@gmail.com>
|
|
||||||
#
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# See LICENSE for details.
|
|
||||||
#
|
|
||||||
|
|
||||||
if(NOT DUB_DIRECTORY)
|
|
||||||
set(DUB_DIRECTORY ${CMAKE_BINARY_DIR}/UseDub CACHE PATH "Dub packages directory")
|
|
||||||
endif(NOT DUB_DIRECTORY)
|
|
||||||
|
|
||||||
set(DUB_REGISTRY "http://code.dlang.org/packages")
|
|
||||||
file(MAKE_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp)
|
|
||||||
|
|
||||||
if(NOT CMAKE_D_COMPILER)
|
|
||||||
message(FATAL_ERROR "UseDub needs a D compiler or use it in a D project.")
|
|
||||||
endif(NOT CMAKE_D_COMPILER)
|
|
||||||
|
|
||||||
#compile json parsers
|
|
||||||
if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl)
|
|
||||||
find_file(DUB_GET_PACKAGE_URL_D_SRC "DubUrl.d"
|
|
||||||
PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH
|
|
||||||
PATH_SUFFIXES "UseDub")
|
|
||||||
find_file(SEMVER_SRC "semver.d"
|
|
||||||
PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH
|
|
||||||
PATH_SUFFIXES "UseDub")
|
|
||||||
get_filename_component(SEMVER_PATH ${SEMVER_SRC} PATH)
|
|
||||||
execute_process(COMMAND ${CMAKE_D_COMPILER} -I${SEMVER_PATH} ${DUB_GET_PACKAGE_URL_D_SRC} ${SEMVER_SRC}
|
|
||||||
WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp)
|
|
||||||
unset(DUB_GET_PACKAGE_URL_D_SRC CACHE)
|
|
||||||
endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubUrl)
|
|
||||||
if(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake)
|
|
||||||
find_file(DUB_PACKAGE_TO_CMAKE_D_SRC "DubToCMake.d"
|
|
||||||
PATHS ${CMAKE_ROOT}/Modules ${CMAKE_MODULE_PATH} NO_DEFAULT_PATH
|
|
||||||
PATH_SUFFIXES "UseDub")
|
|
||||||
execute_process(COMMAND ${CMAKE_D_COMPILER} ${DUB_PACKAGE_TO_CMAKE_D_SRC}
|
|
||||||
WORKING_DIRECTORY ${DUB_DIRECTORY}/CMakeTmp)
|
|
||||||
unset(DUB_PACKAGE_TO_CMAKE_D_SRC CACHE)
|
|
||||||
endif(NOT EXISTS ${DUB_DIRECTORY}/CMakeTmp/DubToCMake)
|
|
||||||
|
|
||||||
include(ExternalProject)
|
|
||||||
|
|
||||||
function(DubProject_Add name)
|
|
||||||
if(NOT EXISTS ${DUB_DIRECTORY}/${name}.json)
|
|
||||||
file(DOWNLOAD ${DUB_REGISTRY}/${name}.json ${DUB_DIRECTORY}/${name}.json STATUS status)
|
|
||||||
list(GET status 0 statusCode)
|
|
||||||
|
|
||||||
if(NOT statusCode EQUAL 0)
|
|
||||||
file(REMOVE ${DUB_DIRECTORY}/${name}.json)
|
|
||||||
message(FATAL_ERROR "Failed to download ${DUB_REGISTRY}/${name}.json")
|
|
||||||
endif(NOT statusCode EQUAL 0)
|
|
||||||
endif(NOT EXISTS ${DUB_DIRECTORY}/${name}.json)
|
|
||||||
|
|
||||||
if(${ARGC} GREATER 1)
|
|
||||||
execute_process(COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubUrl -p ${name}.json -t ${ARGN}
|
|
||||||
WORKING_DIRECTORY ${DUB_DIRECTORY})
|
|
||||||
else(${ARGC} GREATER 1)
|
|
||||||
execute_process(COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubUrl -p ${name}.json
|
|
||||||
WORKING_DIRECTORY ${DUB_DIRECTORY})
|
|
||||||
endif(${ARGC} GREATER 1)
|
|
||||||
|
|
||||||
include(${DUB_DIRECTORY}/${name}.cmake)
|
|
||||||
|
|
||||||
ExternalProject_Add(${name}
|
|
||||||
DOWNLOAD_DIR ${DUB_DIRECTORY}/archive/${name}
|
|
||||||
SOURCE_DIR ${DUB_DIRECTORY}/source/${name}
|
|
||||||
URL ${DUB_PACKAGE_URL}
|
|
||||||
PATCH_COMMAND ${DUB_DIRECTORY}/CMakeTmp/DubToCMake -p package.json
|
|
||||||
INSTALL_DIR ${DUB_DIRECTORY}/export
|
|
||||||
CMAKE_CACHE_ARGS
|
|
||||||
-DCMAKE_MODULE_PATH:PATH=${CMAKE_MODULE_PATH}
|
|
||||||
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
|
||||||
-DDUB_DIRECTORY:PATH=${DUB_DIRECTORY})
|
|
||||||
|
|
||||||
include_directories(${DUB_DIRECTORY}/source/${name}/source ${DUB_DIRECTORY}/source/${name}/src)
|
|
||||||
endfunction()
|
|
|
@ -1,103 +0,0 @@
|
||||||
import std.file;
|
|
||||||
import std.getopt;
|
|
||||||
import std.json;
|
|
||||||
import std.stdio;
|
|
||||||
import std.string;
|
|
||||||
|
|
||||||
int main(string[] args)
|
|
||||||
{
|
|
||||||
string dubFile = "dub.json";
|
|
||||||
string cmakeFile = "CMakeLists.txt";
|
|
||||||
|
|
||||||
getopt(args,
|
|
||||||
"package|p", &dubFile,
|
|
||||||
"output|o", &cmakeFile);
|
|
||||||
|
|
||||||
if (!exists(dubFile))
|
|
||||||
{
|
|
||||||
stderr.writefln("Cannot find file: '%s'", dubFile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string json = readText(dubFile);
|
|
||||||
JSONValue root = parseJSON(json);
|
|
||||||
string target = root["targetName"].str;
|
|
||||||
|
|
||||||
string cmake = q"<
|
|
||||||
cmake_minimum_required(VERSION 2.8)
|
|
||||||
|
|
||||||
project(%1$s D)
|
|
||||||
|
|
||||||
find_file(APP_MAIN_FILE
|
|
||||||
NAMES app.d main.d %1$s/main.d %1$s/app.d
|
|
||||||
PATHS source src NO_DEFAULT_PATH)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE SRC_FILES source/*.d src/*.d)
|
|
||||||
if(APP_MAIN_FILE)
|
|
||||||
list(REMOVE_ITEM SRC_FILES ${APP_MAIN_FILE})
|
|
||||||
endif(APP_MAIN_FILE)
|
|
||||||
|
|
||||||
include_directories(source src)
|
|
||||||
>".format(root["name"].str);
|
|
||||||
|
|
||||||
switch ("targetType" in root.object ? root["targetType"].str : "autodetect")
|
|
||||||
{
|
|
||||||
case "autodetect":
|
|
||||||
cmake ~= q"<
|
|
||||||
if(APP_MAIN_FILE)
|
|
||||||
add_executable(%1$s ${SRC_FILES} ${APP_MAIN_FILE})
|
|
||||||
else(APP_MAIN_FILE)
|
|
||||||
add_library(%1$s ${SRC_FILES})
|
|
||||||
endif(APP_MAIN_FILE)
|
|
||||||
>".format(target);
|
|
||||||
break;
|
|
||||||
case "none":
|
|
||||||
break;
|
|
||||||
case "executable":
|
|
||||||
cmake ~= q"<
|
|
||||||
add_executable(%s ${SRC_FILES} ${APP_MAIN_FILE})
|
|
||||||
>".format(target);
|
|
||||||
break;
|
|
||||||
case "library":
|
|
||||||
cmake ~= q"<
|
|
||||||
add_library(%s ${SRC_FILES})
|
|
||||||
>".format(target);
|
|
||||||
break;
|
|
||||||
case "sourceLibrary":
|
|
||||||
break;
|
|
||||||
case "staticLibrary":
|
|
||||||
cmake ~= q"<
|
|
||||||
add_library(%s STATIC ${SRC_FILES})
|
|
||||||
>".format(target);
|
|
||||||
break;
|
|
||||||
case "dynamicLibrary":
|
|
||||||
cmake ~= q"<
|
|
||||||
add_library(%s SHARED ${SRC_FILES})
|
|
||||||
>".format(target);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false, "Unknown targetType");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmake ~= q"<
|
|
||||||
install(TARGETS %s
|
|
||||||
RUNTIME DESTINATION bin
|
|
||||||
LIBRARY DESTINATION lib
|
|
||||||
ARCHIVE DESTINATION lib)
|
|
||||||
>".format(target);
|
|
||||||
|
|
||||||
if ("dependencies" in root.object)
|
|
||||||
{
|
|
||||||
cmake ~= "\ninclude(UseDub)\n";
|
|
||||||
foreach (dependency, version_; root["dependencies"].object)
|
|
||||||
{
|
|
||||||
cmake ~= "DubProject_Add(%s %s)\n".format(dependency, version_.str);
|
|
||||||
}
|
|
||||||
cmake ~= "\nadd_dependencies(%s %-(%s %))\n".format(target, root["dependencies"].object.keys);
|
|
||||||
}
|
|
||||||
|
|
||||||
std.file.write(cmakeFile, cmake);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,158 +0,0 @@
|
||||||
import std.algorithm;
|
|
||||||
import std.array;
|
|
||||||
import std.file;
|
|
||||||
import std.getopt;
|
|
||||||
import std.json;
|
|
||||||
import std.stdio;
|
|
||||||
import std.string;
|
|
||||||
import semver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the best match of $(D range) in $(D choices) versions list.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* range = Match criteria.
|
|
||||||
* choices = Versions list it is matched against.
|
|
||||||
*
|
|
||||||
* Returns:
|
|
||||||
* Best match in $(D choices) or empty string if no match is found.
|
|
||||||
*
|
|
||||||
* See_Also:
|
|
||||||
* $(WEB https://github.com/npm/npm/blob/master/doc/misc/semver.md#ranges Ranges definition)
|
|
||||||
*/
|
|
||||||
string matchVersion(string range, string[] choices)
|
|
||||||
{
|
|
||||||
foreach (ref choice; choices)
|
|
||||||
{
|
|
||||||
choice.skipOver('~');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (range.skipOver('~'))
|
|
||||||
{
|
|
||||||
foreach (choice; choices)
|
|
||||||
{
|
|
||||||
if (choice.startsWith(range))
|
|
||||||
return choice;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(string[] args)
|
|
||||||
{
|
|
||||||
string registryFile = "";
|
|
||||||
string packageVersion = "";
|
|
||||||
bool listVersions;
|
|
||||||
string outputPath = ".";
|
|
||||||
|
|
||||||
getopt(args,
|
|
||||||
"package|p", ®istryFile,
|
|
||||||
"tag|t", &packageVersion,
|
|
||||||
"list|l", &listVersions,
|
|
||||||
"output|o", &outputPath);
|
|
||||||
|
|
||||||
if (registryFile.empty)
|
|
||||||
{
|
|
||||||
stderr.writeln("Package registry file (<package_name>.json) need to be specified.");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!exists(registryFile) && !registryFile.endsWith(".json"))
|
|
||||||
registryFile ~= ".json";
|
|
||||||
|
|
||||||
if (!exists(registryFile))
|
|
||||||
{
|
|
||||||
stderr.writefln("Package registry file '%s' not found.", registryFile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string json = readText(registryFile);
|
|
||||||
JSONValue node;
|
|
||||||
JSONValue root = parseJSON(json);
|
|
||||||
|
|
||||||
if (packageVersion.empty)
|
|
||||||
{
|
|
||||||
packageVersion = "*";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto versionRange = SemVerRange(packageVersion);
|
|
||||||
|
|
||||||
if (!versionRange.valid)
|
|
||||||
{
|
|
||||||
// try exact string match
|
|
||||||
auto range = root["versions"].array.find!`a["version"].str == b`(packageVersion);
|
|
||||||
if (!range.empty)
|
|
||||||
{
|
|
||||||
node = range[0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stderr.writefln("%s has no version tagged %s.", root["name"].str, packageVersion);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
string nodeVersionString(JSONValue node)
|
|
||||||
{
|
|
||||||
auto ver = node["version"].str;
|
|
||||||
ver.skipOver('~');
|
|
||||||
return ver;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto nodes = root["versions"].array.filter!(a => SemVer(nodeVersionString(a)).valid).array;
|
|
||||||
auto maxVersion = nodes.map!(a => SemVer(nodeVersionString(a))).array.maxSatisfying(versionRange);
|
|
||||||
|
|
||||||
if (maxVersion.valid)
|
|
||||||
{
|
|
||||||
auto range = nodes.find!((a, b) => SemVer(nodeVersionString(a)) == b)(maxVersion);
|
|
||||||
assert(!range.empty);
|
|
||||||
node = range[0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stderr.writefln("%s has no version %s.", root["name"].str, versionRange);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (registryFile.endsWith(".json"))
|
|
||||||
{
|
|
||||||
registryFile = registryFile[0..$-5];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listVersions)
|
|
||||||
{
|
|
||||||
writefln("Package '%s'", registryFile);
|
|
||||||
|
|
||||||
foreach(n; root["versions"].array)
|
|
||||||
{
|
|
||||||
writefln(" %s => %s", n["version"].str, n["downloadUrl"].str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
packageVersion = node["version"].str;
|
|
||||||
auto packageUrl = node["downloadUrl"].str;
|
|
||||||
auto packageName = root["name"].str;
|
|
||||||
|
|
||||||
if (!outputPath.isDir)
|
|
||||||
{
|
|
||||||
stderr.writefln("Output path '%s' need to be a directory.", outputPath);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
string output = "set(DUB_PACKAGE_NAME, \"%s\")\n".format(packageName) ~
|
|
||||||
"set(DUB_PACKAGE_VERSION \"%s\")\n".format(packageVersion) ~
|
|
||||||
"set(DUB_PACKAGE_URL \"%s\")\n".format(packageUrl);
|
|
||||||
|
|
||||||
std.file.write(outputPath ~ "/" ~ packageName ~ ".cmake", output);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,612 +0,0 @@
|
||||||
import std.algorithm;
|
|
||||||
import std.array;
|
|
||||||
import std.conv;
|
|
||||||
import std.range;
|
|
||||||
import std.regex;
|
|
||||||
import std.stdio;
|
|
||||||
import std.string;
|
|
||||||
|
|
||||||
enum ReleaseType
|
|
||||||
{
|
|
||||||
MAJOR,
|
|
||||||
MINOR,
|
|
||||||
PATCH,
|
|
||||||
PRERELEASE,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SemVer
|
|
||||||
{
|
|
||||||
uint[3] ids;
|
|
||||||
string[] prerelease;
|
|
||||||
string[] build;
|
|
||||||
|
|
||||||
bool isValid;
|
|
||||||
|
|
||||||
@disable this();
|
|
||||||
|
|
||||||
this(string semVer)
|
|
||||||
{
|
|
||||||
isValid = false;
|
|
||||||
if (semVer.empty)
|
|
||||||
return;
|
|
||||||
if (!semVer.skipOver('v'))
|
|
||||||
semVer.skipOver('=');
|
|
||||||
|
|
||||||
auto re = regex(`^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([a-zA-Z\d-.]+))?(?:\+([a-zA-Z\d-.]+))?$`);
|
|
||||||
auto m = semVer.matchAll(re);
|
|
||||||
if (m.empty)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (i, ref id; ids)
|
|
||||||
{
|
|
||||||
if (!m.captures[i+1].empty)
|
|
||||||
id = m.captures[i+1].to!uint;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m.captures[4].empty)
|
|
||||||
{
|
|
||||||
prerelease = m.captures[4].splitter('.').array;
|
|
||||||
if (prerelease.any!empty)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m.captures[5].empty)
|
|
||||||
{
|
|
||||||
build = m.captures[5].splitter('.').array;
|
|
||||||
if (build.any!empty)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isValid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
string toString() const
|
|
||||||
{
|
|
||||||
if (!isValid)
|
|
||||||
return "<invalid_semver>";
|
|
||||||
|
|
||||||
string semVer = "%(%s.%)".format(ids);
|
|
||||||
if (!prerelease.empty)
|
|
||||||
semVer ~= "-" ~ "%-(%s.%)".format(prerelease);
|
|
||||||
if (!build.empty)
|
|
||||||
semVer ~= "+" ~ "%-(%s.%)".format(build);
|
|
||||||
return semVer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@property bool valid() const
|
|
||||||
{
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
SemVer inc(ReleaseType releaseType) const
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(this.valid);
|
|
||||||
}
|
|
||||||
out(result)
|
|
||||||
{
|
|
||||||
assert(result.valid);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
|
||||||
SemVer result = "0";
|
|
||||||
foreach (i; 0..releaseType)
|
|
||||||
result.ids[i] = this.ids[i];
|
|
||||||
if (releaseType != ReleaseType.PRERELEASE)
|
|
||||||
result.ids[releaseType] = this.ids[releaseType]+1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
SemVer appendPrerelease0()
|
|
||||||
{
|
|
||||||
if (prerelease.empty)
|
|
||||||
prerelease ~= "0";
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
assert(SemVer("1.2.3").inc(ReleaseType.MAJOR) == SemVer("2.0.0"));
|
|
||||||
assert(SemVer("1.2.3").inc(ReleaseType.MINOR) == SemVer("1.3.0"));
|
|
||||||
assert(SemVer("1.2.3-alpha").inc(ReleaseType.MINOR) == SemVer("1.3.0"));
|
|
||||||
assert(SemVer("1.2.3").inc(ReleaseType.PATCH) == SemVer("1.2.4"));
|
|
||||||
assert(SemVer("1.2.3-alpha").inc(ReleaseType.PATCH) == SemVer("1.2.4"));
|
|
||||||
assert(SemVer("1.2.3").inc(ReleaseType.PRERELEASE) == SemVer("1.2.3"));
|
|
||||||
assert(SemVer("1.2.3-alpha").inc(ReleaseType.PRERELEASE) == SemVer("1.2.3"));
|
|
||||||
}
|
|
||||||
|
|
||||||
int opCmp(ref const SemVer v) const
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(this.valid);
|
|
||||||
assert(v.valid);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
|
||||||
foreach (i; 0..ids.length)
|
|
||||||
{
|
|
||||||
if (ids[i] != v.ids[i])
|
|
||||||
return ids[i] < v.ids[i] ? -1 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!prerelease.empty && v.prerelease.empty)
|
|
||||||
return -1;
|
|
||||||
if (prerelease.empty && !v.prerelease.empty)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
foreach (a, b; lockstep(prerelease, v.prerelease))
|
|
||||||
{
|
|
||||||
if (a.isNumeric && b.isNumeric)
|
|
||||||
{
|
|
||||||
if (a.to!uint != b.to!uint)
|
|
||||||
return a.to!uint < b.to!uint ? -1 : 1;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (a != b)
|
|
||||||
return a < b ? -1 : 1;
|
|
||||||
}
|
|
||||||
if (prerelease.length != v.prerelease.length)
|
|
||||||
return prerelease.length < v.prerelease.length ? -1 : 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int opCmp(const SemVer v) const
|
|
||||||
{
|
|
||||||
return this.opCmp(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool opEquals(ref const SemVer v) const
|
|
||||||
{
|
|
||||||
return this.opCmp(v) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool opEquals(const SemVer v) const
|
|
||||||
{
|
|
||||||
return this.opEquals(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
assert(!SemVer("1.2-.alpha.32").valid);
|
|
||||||
assert(!SemVer("1.2-alpha+").valid);
|
|
||||||
assert(!SemVer("1.2-alpha_").valid);
|
|
||||||
assert(!SemVer("1.2+32.").valid);
|
|
||||||
assert(!SemVer("1.2.5.6").valid);
|
|
||||||
assert(!SemVer("").valid);
|
|
||||||
assert(SemVer("1.0.0-alpha") < SemVer("1.0.0-alpha.1"));
|
|
||||||
assert(SemVer("1.0.0-alpha.1") < SemVer("1.0.0-alpha.beta"));
|
|
||||||
assert(SemVer("1.0.0-alpha.beta") < SemVer("1.0.0-beta"));
|
|
||||||
assert(SemVer("1.0.0-beta") < SemVer("1.0.0-beta.2"));
|
|
||||||
assert(SemVer("1.0.0-beta.2") < SemVer("1.0.0-beta.11"));
|
|
||||||
assert(SemVer("1.0.0-beta.11") < SemVer("1.0.0-rc.1"));
|
|
||||||
assert(SemVer("1.0.0-rc.1") < SemVer("1.0.0"));
|
|
||||||
assert(SemVer("1.0.0-rc.1") == SemVer("1.0.0-rc.1+build.5"));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SemVerRange
|
|
||||||
{
|
|
||||||
struct SimpleRange
|
|
||||||
{
|
|
||||||
string op;
|
|
||||||
SemVer semVer;
|
|
||||||
|
|
||||||
string toString() const
|
|
||||||
{
|
|
||||||
return op ~ semVer.toString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleRange[][] ranges;
|
|
||||||
|
|
||||||
invariant()
|
|
||||||
{
|
|
||||||
assert(ranges.all!(r => r.all!(r => ["<", "<=", "=", ">=", ">"].canFind(r.op))));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isValid;
|
|
||||||
|
|
||||||
@disable this();
|
|
||||||
|
|
||||||
this(string semVerRange)
|
|
||||||
{
|
|
||||||
isValid = false;
|
|
||||||
auto re = regex(`(~|~>|\^|<|<=|=|>=|>)?[v]?(\d+|\*|X|x)(?:\.(\d+|\*|X|x))?(?:\.(\d+|\*|X|x))?([\S]*)`);
|
|
||||||
|
|
||||||
ranges = [SimpleRange[].init];
|
|
||||||
|
|
||||||
while (!semVerRange.stripLeft.empty)
|
|
||||||
{
|
|
||||||
auto m = semVerRange.matchFirst(re);
|
|
||||||
if (m.empty)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto operator = m.captures[1];
|
|
||||||
auto wildcard = wildcardAt([m.captures[2], m.captures[3], m.captures[4]]);
|
|
||||||
auto expanded = expand([m.captures[2], m.captures[3], m.captures[4], m.captures[5]]);
|
|
||||||
if (expanded.empty)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto semVer = SemVer(expanded);
|
|
||||||
if (!semVer.valid)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (m.captures.pre.strip)
|
|
||||||
{
|
|
||||||
case "":
|
|
||||||
break;
|
|
||||||
case "-":
|
|
||||||
if (ranges[$-1].empty || ranges[$-1][$-1].op != "=" ||
|
|
||||||
operator != "" || wildcard != ReleaseType.PRERELEASE)
|
|
||||||
return;
|
|
||||||
ranges[$-1][$-1].op = ">=";
|
|
||||||
operator = "<=";
|
|
||||||
break;
|
|
||||||
case "||":
|
|
||||||
ranges ~= SimpleRange[].init;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (operator)
|
|
||||||
{
|
|
||||||
case "":
|
|
||||||
case "=":
|
|
||||||
final switch (wildcard)
|
|
||||||
{
|
|
||||||
case ReleaseType.MAJOR:
|
|
||||||
assert(semVer == SemVer("0.0.0"));
|
|
||||||
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
|
|
||||||
break;
|
|
||||||
case ReleaseType.MINOR:
|
|
||||||
case ReleaseType.PATCH:
|
|
||||||
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
|
|
||||||
ranges[$-1] ~= SimpleRange("<", semVer.inc(--wildcard).appendPrerelease0);
|
|
||||||
break;
|
|
||||||
case ReleaseType.PRERELEASE:
|
|
||||||
ranges[$-1] ~= SimpleRange("=", semVer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "<":
|
|
||||||
ranges[$-1] ~= SimpleRange(operator, semVer.appendPrerelease0);
|
|
||||||
break;
|
|
||||||
case "<=":
|
|
||||||
case ">=":
|
|
||||||
case ">":
|
|
||||||
if (wildcard < ReleaseType.PRERELEASE)
|
|
||||||
semVer.appendPrerelease0;
|
|
||||||
ranges[$-1] ~= SimpleRange(operator, semVer);
|
|
||||||
break;
|
|
||||||
case "~":
|
|
||||||
final switch (wildcard)
|
|
||||||
{
|
|
||||||
case ReleaseType.MAJOR:
|
|
||||||
return;
|
|
||||||
case ReleaseType.MINOR:
|
|
||||||
case ReleaseType.PATCH:
|
|
||||||
--wildcard;
|
|
||||||
break;
|
|
||||||
case ReleaseType.PRERELEASE:
|
|
||||||
--wildcard;
|
|
||||||
--wildcard;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
|
|
||||||
ranges[$-1] ~= SimpleRange("<", semVer.inc(wildcard).appendPrerelease0);
|
|
||||||
break;
|
|
||||||
case "~>":
|
|
||||||
final switch (wildcard)
|
|
||||||
{
|
|
||||||
case ReleaseType.MAJOR:
|
|
||||||
return;
|
|
||||||
case ReleaseType.MINOR:
|
|
||||||
--wildcard;
|
|
||||||
break;
|
|
||||||
case ReleaseType.PATCH:
|
|
||||||
case ReleaseType.PRERELEASE:
|
|
||||||
--wildcard;
|
|
||||||
--wildcard;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
|
|
||||||
ranges[$-1] ~= SimpleRange("<", semVer.inc(wildcard).appendPrerelease0);
|
|
||||||
break;
|
|
||||||
case "^":
|
|
||||||
if (wildcard == ReleaseType.MAJOR || !semVer.prerelease.empty)
|
|
||||||
return;
|
|
||||||
if (semVer.ids[ReleaseType.MAJOR] != 0)
|
|
||||||
{
|
|
||||||
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
|
|
||||||
ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.MAJOR).appendPrerelease0);
|
|
||||||
}
|
|
||||||
else if (semVer.ids[ReleaseType.MINOR] != 0)
|
|
||||||
{
|
|
||||||
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
|
|
||||||
ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.MINOR).appendPrerelease0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ranges[$-1] ~= SimpleRange(">=", semVer.appendPrerelease0);
|
|
||||||
ranges[$-1] ~= SimpleRange("<", semVer.inc(ReleaseType.PATCH).appendPrerelease0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
semVerRange = m.captures.post;
|
|
||||||
}
|
|
||||||
isValid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ReleaseType wildcardAt(string[3] semVer)
|
|
||||||
{
|
|
||||||
foreach (i; ReleaseType.MAJOR..ReleaseType.PRERELEASE)
|
|
||||||
{
|
|
||||||
if (["", "*", "X", "x"].canFind(semVer[i]))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return ReleaseType.PRERELEASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
assert(wildcardAt(["*", "", ""]) == ReleaseType.MAJOR);
|
|
||||||
assert(wildcardAt(["X", "", ""]) == ReleaseType.MAJOR);
|
|
||||||
assert(wildcardAt(["1", "", ""]) == ReleaseType.MINOR);
|
|
||||||
assert(wildcardAt(["1", "x", ""]) == ReleaseType.MINOR);
|
|
||||||
assert(wildcardAt(["1", "2", ""]) == ReleaseType.PATCH);
|
|
||||||
assert(wildcardAt(["1", "2", "x"]) == ReleaseType.PATCH);
|
|
||||||
assert(wildcardAt(["1", "2", "3"]) == ReleaseType.PRERELEASE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string expand(string[4] semVer)
|
|
||||||
{
|
|
||||||
ReleaseType wildcard = wildcardAt(semVer[0..3]);
|
|
||||||
if (wildcard != ReleaseType.PRERELEASE)
|
|
||||||
{
|
|
||||||
if (semVer[wildcard+1..$].any!`!["", "*", "X", "x"].canFind(a)`)
|
|
||||||
return "";
|
|
||||||
foreach (j; wildcard..ReleaseType.PRERELEASE)
|
|
||||||
semVer[j] = "0";
|
|
||||||
}
|
|
||||||
string result = "%-(%s.%)".format(semVer[0..3]);
|
|
||||||
if (!semVer[3].empty)
|
|
||||||
result ~= semVer[3];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
assert(expand(["*", "", "", ""]) == "0.0.0");
|
|
||||||
assert(expand(["X", "", "", ""]) == "0.0.0");
|
|
||||||
assert(expand(["1", "2", "3", ""]) == "1.2.3");
|
|
||||||
assert(expand(["1", "2", "3", "-abc"]) == "1.2.3-abc");
|
|
||||||
assert(expand(["1", "2", "", ""]) == "1.2.0");
|
|
||||||
assert(expand(["1", "2", "", "-abc"]) == "");
|
|
||||||
assert(expand(["1", "2", "x", ""]) == "1.2.0");
|
|
||||||
assert(expand(["1", "", "", ""]) == "1.0.0");
|
|
||||||
assert(expand(["1", "x", "", ""]) == "1.0.0");
|
|
||||||
}
|
|
||||||
|
|
||||||
string toString() const
|
|
||||||
{
|
|
||||||
if (!isValid)
|
|
||||||
return "<invalid_semver_range>";
|
|
||||||
|
|
||||||
return "%(%(%s %) || %)".format(ranges);
|
|
||||||
}
|
|
||||||
|
|
||||||
@property bool valid() const
|
|
||||||
{
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool simpleRangeSatisfiedBy(SimpleRange simpleRange, SemVer semVer)
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(semVer.valid);
|
|
||||||
assert(["<", "<=", "=", ">=", ">"].canFind(simpleRange.op));
|
|
||||||
assert(simpleRange.semVer.valid);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
|
||||||
switch (simpleRange.op)
|
|
||||||
{
|
|
||||||
case "<":
|
|
||||||
return semVer < simpleRange.semVer;
|
|
||||||
case "<=":
|
|
||||||
return semVer <= simpleRange.semVer;
|
|
||||||
case "=":
|
|
||||||
return semVer == simpleRange.semVer;
|
|
||||||
case ">=":
|
|
||||||
return semVer >= simpleRange.semVer;
|
|
||||||
case ">":
|
|
||||||
return semVer > simpleRange.semVer;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool satisfiedBy(SemVer semVer)
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(semVer.valid);
|
|
||||||
assert(valid);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
|
||||||
return ranges.any!(r => r.all!(s => simpleRangeSatisfiedBy(s, semVer)));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool satisfies(SemVer semVer, SemVerRange semVerRange)
|
|
||||||
{
|
|
||||||
return semVerRange.satisfiedBy(semVer);
|
|
||||||
}
|
|
||||||
|
|
||||||
SemVer maxSatisfying(SemVer[] semVers, SemVerRange semVerRange)
|
|
||||||
in
|
|
||||||
{
|
|
||||||
assert(semVers.all!"a.valid");
|
|
||||||
assert(semVerRange.valid);
|
|
||||||
}
|
|
||||||
body
|
|
||||||
{
|
|
||||||
auto found = semVers.sort!"a > b".find!(a => satisfies(a, semVerRange));
|
|
||||||
return found.empty ? SemVer("invalid") : found[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
assert(SemVerRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3").valid);
|
|
||||||
assert(!SemVerRange("blerg").valid);
|
|
||||||
assert(!SemVerRange("git+https://user:password0123@github.com/foo").valid);
|
|
||||||
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("1.x || >=2.5.0 || 5.0.0 - 7.2.3")));
|
|
||||||
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("1.0.0 - 2.0.0")));
|
|
||||||
assert(SemVer("1.0.0").satisfies(SemVerRange("1.0.0")));
|
|
||||||
assert(SemVer("0.2.4").satisfies(SemVerRange(">=*")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("*")));
|
|
||||||
assert(SemVer("v1.2.3-foo").satisfies(SemVerRange("*")));
|
|
||||||
assert(SemVer("1.0.0").satisfies(SemVerRange(">=1.0.0")));
|
|
||||||
assert(SemVer("1.0.1").satisfies(SemVerRange(">=1.0.0")));
|
|
||||||
assert(SemVer("1.1.0").satisfies(SemVerRange(">=1.0.0")));
|
|
||||||
assert(SemVer("1.0.1").satisfies(SemVerRange(">1.0.0")));
|
|
||||||
assert(SemVer("1.1.0").satisfies(SemVerRange(">1.0.0")));
|
|
||||||
assert(SemVer("2.0.0").satisfies(SemVerRange("<=2.0.0")));
|
|
||||||
assert(SemVer("1.9999.9999").satisfies(SemVerRange("<=2.0.0")));
|
|
||||||
assert(SemVer("0.2.9").satisfies(SemVerRange("<=2.0.0")));
|
|
||||||
assert(SemVer("1.9999.9999").satisfies(SemVerRange("<2.0.0")));
|
|
||||||
assert(SemVer("0.2.9").satisfies(SemVerRange("<2.0.0")));
|
|
||||||
assert(SemVer("1.0.0").satisfies(SemVerRange(">=1.0.0")));
|
|
||||||
assert(SemVer("1.0.1").satisfies(SemVerRange(">=1.0.0")));
|
|
||||||
assert(SemVer("1.1.0").satisfies(SemVerRange(">=1.0.0")));
|
|
||||||
assert(SemVer("1.0.1").satisfies(SemVerRange(">1.0.0")));
|
|
||||||
assert(SemVer("1.1.0").satisfies(SemVerRange(">1.0.0")));
|
|
||||||
assert(SemVer("2.0.0").satisfies(SemVerRange("<=2.0.0")));
|
|
||||||
assert(SemVer("1.9999.9999").satisfies(SemVerRange("<=2.0.0")));
|
|
||||||
assert(SemVer("0.2.9").satisfies(SemVerRange("<=2.0.0")));
|
|
||||||
assert(SemVer("1.9999.9999").satisfies(SemVerRange("<2.0.0")));
|
|
||||||
assert(SemVer("0.2.9").satisfies(SemVerRange("<2.0.0")));
|
|
||||||
assert(SemVer("v0.1.97").satisfies(SemVerRange(">=0.1.97")));
|
|
||||||
assert(SemVer("0.1.97").satisfies(SemVerRange(">=0.1.97")));
|
|
||||||
assert(SemVer("1.2.4").satisfies(SemVerRange("0.1.20 || 1.2.4")));
|
|
||||||
assert(SemVer("0.0.0").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
|
|
||||||
assert(SemVer("0.2.3").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
|
|
||||||
assert(SemVer("0.2.4").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
|
|
||||||
assert(SemVer("2.1.3").satisfies(SemVerRange("2.x.x")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.x")));
|
|
||||||
assert(SemVer("2.1.3").satisfies(SemVerRange("1.2.x || 2.x")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.x || 2.x")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("x")));
|
|
||||||
assert(SemVer("2.1.3").satisfies(SemVerRange("2.*.*")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.*")));
|
|
||||||
assert(SemVer("2.1.3").satisfies(SemVerRange("1.2.* || 2.*")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.* || 2.*")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("*")));
|
|
||||||
assert(SemVer("2.1.2").satisfies(SemVerRange("2")));
|
|
||||||
assert(SemVer("2.3.1").satisfies(SemVerRange("2.3")));
|
|
||||||
assert(SemVer("2.4.0").satisfies(SemVerRange("~2.4")));
|
|
||||||
assert(SemVer("2.4.5").satisfies(SemVerRange("~2.4")));
|
|
||||||
assert(SemVer("3.2.2").satisfies(SemVerRange("~>3.2.1")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("~1")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("~>1")));
|
|
||||||
assert(SemVer("1.0.2").satisfies(SemVerRange("~1.0")));
|
|
||||||
assert(SemVer("1.0.12").satisfies(SemVerRange("~1.0.3")));
|
|
||||||
assert(SemVer("1.0.0").satisfies(SemVerRange(">=1")));
|
|
||||||
assert(SemVer("1.1.1").satisfies(SemVerRange("<1.2")));
|
|
||||||
assert(SemVer("1.1.9").satisfies(SemVerRange("<=1.2")));
|
|
||||||
assert(SemVer("1.0.0-bet").satisfies(SemVerRange("1")));
|
|
||||||
assert(SemVer("0.5.5").satisfies(SemVerRange("~v0.5.4-pre")));
|
|
||||||
assert(SemVer("0.5.4").satisfies(SemVerRange("~v0.5.4-pre")));
|
|
||||||
assert(SemVer("0.7.2").satisfies(SemVerRange("=0.7.x")));
|
|
||||||
assert(SemVer("0.7.2").satisfies(SemVerRange(">=0.7.x")));
|
|
||||||
assert(SemVer("0.7.0-asdf").satisfies(SemVerRange("=0.7.x")));
|
|
||||||
assert(SemVer("0.7.0-asdf").satisfies(SemVerRange(">=0.7.x")));
|
|
||||||
assert(SemVer("0.6.2").satisfies(SemVerRange("<=0.7.x")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 >=1.2.3")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 =1.2.3")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 >=1.2.3 1.2.3")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3 >=1.2.3")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("~1.2.1 1.2.3")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.1 1.2.3")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange("1.2.3 >=1.2.1")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.3 >=1.2.1")));
|
|
||||||
assert(SemVer("1.2.3").satisfies(SemVerRange(">=1.2.1 >=1.2.3")));
|
|
||||||
assert(SemVer("1.2.3-beta").satisfies(SemVerRange("<=1.2.3")));
|
|
||||||
assert(SemVer("1.3.0-beta").satisfies(SemVerRange(">1.2")));
|
|
||||||
assert(SemVer("1.2.8").satisfies(SemVerRange(">=1.2")));
|
|
||||||
assert(SemVer("1.8.1").satisfies(SemVerRange("^1.2.3")));
|
|
||||||
assert(SemVer("1.2.3-beta").satisfies(SemVerRange("^1.2.3")));
|
|
||||||
assert(SemVer("0.1.2").satisfies(SemVerRange("^0.1.2")));
|
|
||||||
assert(SemVer("0.1.2").satisfies(SemVerRange("^0.1")));
|
|
||||||
assert(SemVer("1.4.2").satisfies(SemVerRange("^1.2")));
|
|
||||||
assert(SemVer("1.4.2").satisfies(SemVerRange("^1.2 ^1")));
|
|
||||||
assert(SemVer("1.2.0-pre").satisfies(SemVerRange("^1.2")));
|
|
||||||
assert(SemVer("1.2.3-pre").satisfies(SemVerRange("^1.2.3")));
|
|
||||||
|
|
||||||
assert(!SemVer("2.2.3").satisfies(SemVerRange("1.0.0 - 2.0.0")));
|
|
||||||
assert(!SemVer("1.0.1").satisfies(SemVerRange("1.0.0")));
|
|
||||||
assert(!SemVer("0.0.0").satisfies(SemVerRange(">=1.0.0")));
|
|
||||||
assert(!SemVer("0.0.1").satisfies(SemVerRange(">=1.0.0")));
|
|
||||||
assert(!SemVer("0.1.0").satisfies(SemVerRange(">=1.0.0")));
|
|
||||||
assert(!SemVer("0.0.1").satisfies(SemVerRange(">1.0.0")));
|
|
||||||
assert(!SemVer("0.1.0").satisfies(SemVerRange(">1.0.0")));
|
|
||||||
assert(!SemVer("3.0.0").satisfies(SemVerRange("<=2.0.0")));
|
|
||||||
assert(!SemVer("2.9999.9999").satisfies(SemVerRange("<=2.0.0")));
|
|
||||||
assert(!SemVer("2.2.9").satisfies(SemVerRange("<=2.0.0")));
|
|
||||||
assert(!SemVer("2.9999.9999").satisfies(SemVerRange("<2.0.0")));
|
|
||||||
assert(!SemVer("2.2.9").satisfies(SemVerRange("<2.0.0")));
|
|
||||||
assert(!SemVer("v0.1.93").satisfies(SemVerRange(">=0.1.97")));
|
|
||||||
assert(!SemVer("0.1.93").satisfies(SemVerRange(">=0.1.97")));
|
|
||||||
assert(!SemVer("1.2.3").satisfies(SemVerRange("0.1.20 || 1.2.4")));
|
|
||||||
assert(!SemVer("0.0.3").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
|
|
||||||
assert(!SemVer("0.2.2").satisfies(SemVerRange(">=0.2.3 || <0.0.1")));
|
|
||||||
assert(!SemVer("1.1.3").satisfies(SemVerRange("2.x.x")));
|
|
||||||
assert(!SemVer("3.1.3").satisfies(SemVerRange("2.x.x")));
|
|
||||||
assert(!SemVer("1.3.3").satisfies(SemVerRange("1.2.x")));
|
|
||||||
assert(!SemVer("3.1.3").satisfies(SemVerRange("1.2.x || 2.x")));
|
|
||||||
assert(!SemVer("1.1.3").satisfies(SemVerRange("1.2.x || 2.x")));
|
|
||||||
assert(!SemVer("1.1.3").satisfies(SemVerRange("2.*.*")));
|
|
||||||
assert(!SemVer("3.1.3").satisfies(SemVerRange("2.*.*")));
|
|
||||||
assert(!SemVer("1.3.3").satisfies(SemVerRange("1.2.*")));
|
|
||||||
assert(!SemVer("3.1.3").satisfies(SemVerRange("1.2.* || 2.*")));
|
|
||||||
assert(!SemVer("1.1.3").satisfies(SemVerRange("1.2.* || 2.*")));
|
|
||||||
assert(!SemVer("1.1.2").satisfies(SemVerRange("2")));
|
|
||||||
assert(!SemVer("2.4.1").satisfies(SemVerRange("2.3")));
|
|
||||||
assert(!SemVer("2.5.0").satisfies(SemVerRange("~2.4")));
|
|
||||||
assert(!SemVer("2.3.9").satisfies(SemVerRange("~2.4")));
|
|
||||||
assert(!SemVer("3.3.2").satisfies(SemVerRange("~>3.2.1")));
|
|
||||||
assert(!SemVer("3.2.0").satisfies(SemVerRange("~>3.2.1")));
|
|
||||||
assert(!SemVer("0.2.3").satisfies(SemVerRange("~1")));
|
|
||||||
assert(!SemVer("2.2.3").satisfies(SemVerRange("~>1")));
|
|
||||||
assert(!SemVer("1.1.0").satisfies(SemVerRange("~1.0")));
|
|
||||||
assert(!SemVer("1.0.0").satisfies(SemVerRange("<1")));
|
|
||||||
assert(!SemVer("1.1.1").satisfies(SemVerRange(">=1.2")));
|
|
||||||
assert(!SemVer("1.3.0").satisfies(SemVerRange("<=1.2")));
|
|
||||||
assert(!SemVer("2.0.0-beta").satisfies(SemVerRange("1")));
|
|
||||||
assert(!SemVer("0.5.4-alpha").satisfies(SemVerRange("~v0.5.4-beta")));
|
|
||||||
assert(!SemVer("1.0.0-beta").satisfies(SemVerRange("<1")));
|
|
||||||
assert(!SemVer("0.8.2").satisfies(SemVerRange("=0.7.x")));
|
|
||||||
assert(!SemVer("0.6.2").satisfies(SemVerRange(">=0.7.x")));
|
|
||||||
assert(!SemVer("0.7.2").satisfies(SemVerRange("<=0.7.x")));
|
|
||||||
assert(!SemVer("1.2.3-beta").satisfies(SemVerRange("<1.2.3")));
|
|
||||||
assert(!SemVer("1.2.3-beta").satisfies(SemVerRange("=1.2.3")));
|
|
||||||
assert(!SemVer("1.2.8").satisfies(SemVerRange(">1.3")));
|
|
||||||
assert(!SemVer("2.0.0-alpha").satisfies(SemVerRange("^1.2.3")));
|
|
||||||
assert(!SemVer("1.2.2").satisfies(SemVerRange("^1.2.3")));
|
|
||||||
assert(!SemVer("1.1.9").satisfies(SemVerRange("^1.2")));
|
|
||||||
assert(!SemVer("2.0.0-pre").satisfies(SemVerRange("^1.2.3")));
|
|
||||||
|
|
||||||
auto semVers = [SemVer("0.8.0"), SemVer("1.0.0"), SemVer("1.1.0")];
|
|
||||||
assert(semVers.maxSatisfying(SemVerRange("<=1.0.0")) == SemVer("1.0.0"));
|
|
||||||
assert(semVers.maxSatisfying(SemVerRange(">=1.0")) == SemVer("1.1.0"));
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
#message("Adding dependencies")
|
|
||||||
|
|
||||||
#message("CMAKE_D_FLAGS: ${CMAKE_D_FLAGS} ")
|
|
||||||
#message("CMAKE_D_COMPILER: ${CMAKE_D_COMPILER} ")
|
|
||||||
#message("include_directories: ${include_directories} ")
|
|
||||||
#message("source file ${source_file}")
|
|
||||||
#message("dependency file ${dependency_file}")
|
|
||||||
|
|
||||||
separate_arguments(CMAKE_D_FLAGS)
|
|
||||||
|
|
||||||
# TODO
|
|
||||||
# need to pass all arguments that are used for building
|
|
||||||
# can't I use the build rule somehow
|
|
||||||
execute_process(COMMAND ${CMAKE_D_COMPILER} ${CMAKE_D_FLAGS} ${include_directories} -deps=${dependency_file}.tmp -o- ${source_file})
|
|
||||||
#message("executing: ${CMAKE_D_COMPILER} ${CMAKE_D_FLAGS} ${include_directories} -deps=${dependency_file}.tmp -o- ${source_file}")
|
|
||||||
|
|
||||||
if(NOT EXISTS ${dependency_file})
|
|
||||||
file(WRITE ${dependency_file} "# Generated by: ${CMAKE_CURRENT_LIST_FILE}\nSET(D_DMD_DEPEND\n)\n\n")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
file(READ ${dependency_file}.tmp depend_text)
|
|
||||||
#message("DEPENDENCIES: ${depend_text}")
|
|
||||||
|
|
||||||
# extract dependencies
|
|
||||||
string(REGEX MATCHALL "\\([^)]*\\)" out ${depend_text})
|
|
||||||
string(REGEX MATCHALL "[^()]+" out ${out})
|
|
||||||
list(REMOVE_DUPLICATES out)
|
|
||||||
list(SORT out)
|
|
||||||
|
|
||||||
foreach(file ${out})
|
|
||||||
set(dependencies "${dependencies} \"${file}\"\n")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# write new dependencies to temporary file
|
|
||||||
file(WRITE ${dependency_file}.tmp "# Generated by: ${CMAKE_CURRENT_LIST_FILE}\nSET(D_DMD_DEPEND\n ${dependencies})\n\n")
|
|
||||||
|
|
||||||
# get old dependencies
|
|
||||||
include(${dependency_file})
|
|
||||||
set(old_dependencies ${D_DMD_DEPEND})
|
|
||||||
# and the new dependencies from temporary file
|
|
||||||
include(${dependency_file}.tmp)
|
|
||||||
|
|
||||||
# did the dependencies change?
|
|
||||||
if(NOT "${D_DMD_DEPEND}" STREQUAL "${old_dependencies}")
|
|
||||||
message("Dependencies changed. Need to build.")
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E touch ${source_file})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${dependency_file}.tmp ${dependency_file})
|
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${dependency_file}.tmp)
|
|
||||||
|
|
||||||
#message("Finished dependencies")
|
|
|
@ -1,5 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Nim)
|
|
||||||
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Nim/UseNim.cmake)
|
|
||||||
find_package(Nim)
|
|
||||||
add_subdirectory(Examples)
|
|
|
@ -1,304 +0,0 @@
|
||||||
:Authors:
|
|
||||||
Filippo Cucchetto <filippocucchetto@gmail.com>
|
|
||||||
|
|
||||||
Will Szumski <will@cowboycoders.org>
|
|
||||||
:Version: 0.3.0
|
|
||||||
:Date: 2015/02/15
|
|
||||||
|
|
||||||
Introduction
|
|
||||||
-----------
|
|
||||||
The NimQml module adds Qt Qml bindings to the Nim programming language
|
|
||||||
allowing you to create new modern UI by mixing the Qml declarative syntax
|
|
||||||
and the Nim imperative language.
|
|
||||||
|
|
||||||
The NimQml is made by two components:
|
|
||||||
* The DOtherSide C++ shared library
|
|
||||||
* The NimQml Nim module
|
|
||||||
|
|
||||||
This first component implements the glue code necessary for
|
|
||||||
communicating with the Qt C++ library, the latter module wraps
|
|
||||||
the libDOtherSide exported symbols in Nim
|
|
||||||
|
|
||||||
Building
|
|
||||||
--------
|
|
||||||
At the time of writing the DOtherSide C++ library must be compiled
|
|
||||||
and installed manually from source.
|
|
||||||
|
|
||||||
First clone the DOtherSide git repo
|
|
||||||
::
|
|
||||||
git clone https://github.com/filcuc/DOtherSide
|
|
||||||
|
|
||||||
than you can proceed with the common CMake build steps
|
|
||||||
|
|
||||||
::
|
|
||||||
mkdir build
|
|
||||||
cd build
|
|
||||||
cmake ..
|
|
||||||
make
|
|
||||||
|
|
||||||
If everything goes correctly, you'll have built both
|
|
||||||
the DOtherSide C++ library and the Nim examples
|
|
||||||
|
|
||||||
Installation
|
|
||||||
----------
|
|
||||||
The installation is not mandatory, in fact you could try
|
|
||||||
the built Nim example in the following way
|
|
||||||
::
|
|
||||||
cd path/to/build/dir
|
|
||||||
cd Nim/Examples/HelloWorld
|
|
||||||
export LD_LIBRARY_PATH=path/to/libDOtherSide.so
|
|
||||||
./HelloWorld
|
|
||||||
|
|
||||||
The DOtherSide project is made of two components
|
|
||||||
1. The DOtherSide C++ lib
|
|
||||||
2. The NimQml module
|
|
||||||
|
|
||||||
You can procede with the installation of the C++ library
|
|
||||||
in the following way
|
|
||||||
::
|
|
||||||
cd to/build/dir
|
|
||||||
make install
|
|
||||||
or by manually copying the library in your system lib directory
|
|
||||||
::
|
|
||||||
sudo cp build/dir/path/DOtherSide/libDOtherSide.so /usr/lib
|
|
||||||
|
|
||||||
For the NimQml module you can use the ``nimble`` package manager
|
|
||||||
::
|
|
||||||
nimble install NimQml
|
|
||||||
|
|
||||||
or
|
|
||||||
::
|
|
||||||
cd to/build/dir/Nim/NimQml
|
|
||||||
nimble install
|
|
||||||
|
|
||||||
|
|
||||||
Example 1: HelloWorld
|
|
||||||
----------
|
|
||||||
As usual lets start with an HelloWorld example.
|
|
||||||
Most of the NimQml projects are made by one or more nim and qml
|
|
||||||
files. Usually the .nim files contains your app logic and data
|
|
||||||
layer. The qml files contain the presentation layer and expose
|
|
||||||
the data in your nim files.
|
|
||||||
|
|
||||||
``Examples/HelloWorld/main.nim``
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
:file: ../Examples/HelloWorld/main.nim
|
|
||||||
|
|
||||||
``Examples/HelloWorld/main.qml``
|
|
||||||
|
|
||||||
.. code-block:: qml
|
|
||||||
:file: ../Examples/HelloWorld/main.qml
|
|
||||||
|
|
||||||
The following example shows the basic steps of each NimQml app
|
|
||||||
1. Create the QApplication for initializing the Qt runtime
|
|
||||||
2. Create the QQmlApplicationEngine and load your main .qml file
|
|
||||||
3. Call the ``exec`` proc of the QApplication instance for starting
|
|
||||||
the Qt event loop
|
|
||||||
|
|
||||||
Example 2: exposing data to Qml
|
|
||||||
------------------------------------
|
|
||||||
The previous example shown you how to create a simple application
|
|
||||||
window and how to startup the Qt event loop.
|
|
||||||
|
|
||||||
It's time to explore how to pass data to Qml, but lets see the
|
|
||||||
example code first:
|
|
||||||
|
|
||||||
``Examples/SimpleData/main.nim``
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
:file: ../Examples/SimpleData/main.nim
|
|
||||||
|
|
||||||
``Examples/SimpleData/main.qml``
|
|
||||||
|
|
||||||
.. code-block:: qml
|
|
||||||
:file: ../Examples/SimpleData/main.qml
|
|
||||||
|
|
||||||
The following example shows how to expose simple data types to Qml:
|
|
||||||
1. Create a QVariant and set its internal value.
|
|
||||||
2. Create a property in the Qml root context with a given name.
|
|
||||||
|
|
||||||
Once a property is set through the ``setContextProperty`` proc, it's available
|
|
||||||
globally in all the Qml script loaded by the current engine (see the official Qt
|
|
||||||
documentation for more details about the engine and context objects)
|
|
||||||
|
|
||||||
At the time of writing the QVariant class support the following types:
|
|
||||||
* int
|
|
||||||
* string
|
|
||||||
* bool
|
|
||||||
* float
|
|
||||||
* QObject derived classes
|
|
||||||
|
|
||||||
Example 3: exposing complex data and procedures to Qml
|
|
||||||
----------------------------------------------------------
|
|
||||||
As seen by the second example, simple data is fine. However most
|
|
||||||
applications need to expose complex data, functions and
|
|
||||||
update the view when something changes in the data layer.
|
|
||||||
This is achieved by creating an object that derives from QObject.
|
|
||||||
|
|
||||||
A QObject is made of :
|
|
||||||
1. ``Slots``: slots are functions that could be called from the qml engine and/or connected to Qt signals
|
|
||||||
2. ``Signals``: signals allow the sending of events and be connected to slots
|
|
||||||
3. ``Properties``: properties allow the passing of data to
|
|
||||||
the Qml view and make it aware of changes in the data layer
|
|
||||||
|
|
||||||
A QObject property is made of three things:
|
|
||||||
* a read slot: a method that returns the current value of the property
|
|
||||||
* a write slot: a method that sets the value of the property
|
|
||||||
* a notify signal: emitted when the current value of the property is changed
|
|
||||||
|
|
||||||
We'll start by looking at the main.nim file
|
|
||||||
|
|
||||||
``Examples/SlotsAndProperties/main.nim``
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
:file: ../Examples/SlotsAndProperties/main.nim
|
|
||||||
|
|
||||||
Here, nothing special happens except:
|
|
||||||
1. The creation of Contact object
|
|
||||||
2. The injection of the Contact object to the Qml root context
|
|
||||||
using the ``setContextProperty`` as seen in the previous
|
|
||||||
example
|
|
||||||
|
|
||||||
The Qml file is as follows:
|
|
||||||
|
|
||||||
``Examples/SlotsAndProperties/main.qml``
|
|
||||||
|
|
||||||
.. code-block:: qml
|
|
||||||
:file: ../Examples/SlotsAndProperties/main.qml
|
|
||||||
|
|
||||||
The qml is made up of: a Label, a TextInput widget, and a button.
|
|
||||||
The label displays the contact name - this automatically updates when
|
|
||||||
the contact name changes.
|
|
||||||
|
|
||||||
When clicked, the button updates the contact name with the text from
|
|
||||||
the TextInput widget.
|
|
||||||
|
|
||||||
So where's the magic?
|
|
||||||
|
|
||||||
The magic is in the Contact.nim file
|
|
||||||
|
|
||||||
``Examples/SlotsAndProperties/Contact.nim``
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
:file: ../Examples/SlotsAndProperties/Contact.nim
|
|
||||||
|
|
||||||
First we declare a QObject subclass and provide a simple
|
|
||||||
new method where we:
|
|
||||||
1. invoke the ``create()`` procedure. This invoke the C++ bridge and allocate
|
|
||||||
a QObject instance
|
|
||||||
2. register a slot ``getName`` for reading the Contact name field
|
|
||||||
3. register a slot ``setName`` for writing the Contact name
|
|
||||||
4. register a signal ``nameChanged`` for notify the contact name changes
|
|
||||||
5. register a property called ``name`` of type ``QString`` with the given
|
|
||||||
read, write slots and notify signal
|
|
||||||
|
|
||||||
Looking at the ``getName`` and ``setName`` methods, you can see that slots, as defined in Nim,
|
|
||||||
are nothing more than standard methods. The method corresponding to the ``setName`` slot
|
|
||||||
demonstrates how to use the ``emit`` method to emit a signal.
|
|
||||||
|
|
||||||
The last thing to consider is the override of the ``onSlotCalled`` method.
|
|
||||||
This method is called by the NimQml library when an invocation occurs from
|
|
||||||
the Qml side for one of the slots belonging to the QObject.
|
|
||||||
The usual implementation for the onSlotCalled method consists of a
|
|
||||||
switch statement that forwards the arguments to the correct slot.
|
|
||||||
If the invoked slot has a return value, this is always in the index position
|
|
||||||
0 of the args array.
|
|
||||||
|
|
||||||
|
|
||||||
Example 4: QtObject macro
|
|
||||||
-------------------------
|
|
||||||
The previous example shows how to create a simple QObject, however writing
|
|
||||||
all those ``register`` procs and writing the ``onSlotCalled`` method
|
|
||||||
becomes boring pretty soon.
|
|
||||||
|
|
||||||
Furthermore all this information can be automatically generated.
|
|
||||||
For this purpose you can import the NimQmlMacros module that provides
|
|
||||||
the QtObject macro.
|
|
||||||
|
|
||||||
Let's begin as usual with both the main.nim and main.qml files
|
|
||||||
|
|
||||||
``Examples/QtObjectMacro/main.nim``
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
:file: ../Examples/QtObjectMacro/main.nim
|
|
||||||
|
|
||||||
|
|
||||||
``Examples/QtObjectMacro/main.qml``
|
|
||||||
|
|
||||||
.. code-block:: qml
|
|
||||||
:file: ../Examples/QtObjectMacro/main.qml
|
|
||||||
|
|
||||||
Nothing is new in both the ``main.nim`` and ``main.qml`` with respect to
|
|
||||||
the previous example. What changed is the Contact object:
|
|
||||||
|
|
||||||
``Examples/QtObjectMacro/Contact.nim``
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
:file: ../Examples/QtObjectMacro/Contact.nim
|
|
||||||
|
|
||||||
In details:
|
|
||||||
1. Each QObject is defined inside the QtObject macro
|
|
||||||
2. Each slot is annotated with the ``{.slot.}`` pragma
|
|
||||||
3. Each signal is annotated with the ``{.signal.}`` pragma
|
|
||||||
4. Each property is created with the ``QtProperty`` macro
|
|
||||||
|
|
||||||
The ``QtProperty`` macro has the following syntax
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
QtProperty[typeOfProperty] nameOfProperty
|
|
||||||
|
|
||||||
Example 5: ContactApp
|
|
||||||
-------------------------
|
|
||||||
The last example tries to show you all the stuff presented
|
|
||||||
in the previous chapters and gives you an introduction to how
|
|
||||||
to expose lists to qml.
|
|
||||||
|
|
||||||
Qt models are a huge topic and explaining how they work is
|
|
||||||
out of scope. For further information please read the official
|
|
||||||
Qt documentation.
|
|
||||||
|
|
||||||
The main file follows the basic logic of creating a qml
|
|
||||||
engine and exposing a QObject derived object "ApplicationLogic"
|
|
||||||
through a global "logic" property
|
|
||||||
|
|
||||||
``Examples/ContactApp/main.nim``
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
:file: ../Examples/ContactApp/main.nim
|
|
||||||
|
|
||||||
The qml file shows a simple app with a central tableview
|
|
||||||
|
|
||||||
``Examples/ContactApp/main.qml``
|
|
||||||
|
|
||||||
.. code-block:: qml
|
|
||||||
:file: ../Examples/ContactApp/main.qml
|
|
||||||
|
|
||||||
The important things to notice are:
|
|
||||||
1. The menubar load, save and exit items handlers call the logic load, save and exit slots
|
|
||||||
2. The TableView model is retrieved by the logic.contactList property
|
|
||||||
3. The delete and add buttons call the del and add slots of the logic.contactList model
|
|
||||||
|
|
||||||
The ApplicationLogic object is as follows:
|
|
||||||
|
|
||||||
``Examples/ContactApp/ApplicationLogic.nim``
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
:file: ../Examples/ContactApp/ApplicationLogic.nim
|
|
||||||
|
|
||||||
The ApplicationLogic object,
|
|
||||||
1. expose some slots for handling the qml menubar triggered signals
|
|
||||||
2. expose a contactList property that return a QAbstractListModel derived object that manage the list of contacts
|
|
||||||
|
|
||||||
The ContactList object is as follows:
|
|
||||||
|
|
||||||
``Examples/ContactApp/ContactList.nim``
|
|
||||||
|
|
||||||
.. code-block:: nim
|
|
||||||
:file: ../Examples/ContactApp/ContactList.nim
|
|
||||||
|
|
||||||
The ContactList object:
|
|
||||||
1. overrides the ``rowCount`` method for returning the number of rows stored in the model
|
|
||||||
2. overrides the ``data`` method for returning the value for the exported roles
|
|
||||||
3. overrides the ``roleNames`` method for returning the names of the roles of the model. This name are then available in the qml item delegates
|
|
||||||
4. defines two slots ``add`` and ``del`` that add or delete a Contact. During this operations the model execute the ``beginInsertRows`` and ``beginRemoveRows`` for notifing the view of an upcoming change. Once the add or delete operations are done the model execute the ``endInsertRows`` and ``endRemoveRows``.
|
|
|
@ -1,2 +0,0 @@
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
add_nim_executable(TARGET NimQmlAbstractItemModel SOURCES main.nim PATHS ../../NimQml)
|
|
|
@ -1,37 +0,0 @@
|
||||||
import NimQml, NimQmlMacros, Tables
|
|
||||||
|
|
||||||
QtObject:
|
|
||||||
type
|
|
||||||
MyListModel* = ref object of QAbstractListModel
|
|
||||||
names*: seq[string]
|
|
||||||
RoleNames {.pure.} = enum
|
|
||||||
Name = 0,
|
|
||||||
|
|
||||||
converter toCInt(value: RoleNames): cint = return value.cint
|
|
||||||
converter toCInt(value: int): cint = return value.cint
|
|
||||||
converter toInt(value: RoleNames): int = return value.int
|
|
||||||
converter toInt(value: cint): int = return value.int
|
|
||||||
converter toQVariant(value: string): QVariant = return value.newQVariant
|
|
||||||
|
|
||||||
proc delete(self: MyListModel) =
|
|
||||||
let model = self.QAbstractListModel
|
|
||||||
model.delete
|
|
||||||
|
|
||||||
proc newMyListModel*(): MyListModel =
|
|
||||||
new(result, delete)
|
|
||||||
result.names = @["John", "Max", "Paul", "Anna"]
|
|
||||||
result.create
|
|
||||||
|
|
||||||
method rowCount(self: MyListModel, index: QModelIndex = nil): cint =
|
|
||||||
return self.names.len
|
|
||||||
|
|
||||||
method data(self: MyListModel, index: QModelIndex, role: cint): QVariant =
|
|
||||||
if not index.isValid:
|
|
||||||
return
|
|
||||||
if index.row < 0 or index.row >= self.names.len:
|
|
||||||
return
|
|
||||||
return self.names[index.row]
|
|
||||||
|
|
||||||
method roleNames(self: MyListModel): Table[cint, cstring] =
|
|
||||||
result = initTable[cint, cstring]()
|
|
||||||
result[RoleNames.Name] = "name"
|
|
|
@ -1,26 +0,0 @@
|
||||||
import NimQml
|
|
||||||
import MyListModel
|
|
||||||
|
|
||||||
proc mainProc() =
|
|
||||||
echo "Starting"
|
|
||||||
var app = newQApplication()
|
|
||||||
defer: app.delete
|
|
||||||
|
|
||||||
var myListModel = newMyListModel();
|
|
||||||
defer: myListModel.delete
|
|
||||||
|
|
||||||
var engine = newQQmlApplicationEngine()
|
|
||||||
defer: engine.delete
|
|
||||||
|
|
||||||
var variant = newQVariant(myListModel)
|
|
||||||
defer: variant.delete
|
|
||||||
|
|
||||||
engine.rootContext.setContextProperty("myListModel", variant)
|
|
||||||
engine.load("main.qml")
|
|
||||||
|
|
||||||
app.exec()
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
mainProc()
|
|
||||||
GC_fullcollect()
|
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow
|
|
||||||
{
|
|
||||||
width: 400
|
|
||||||
height: 300
|
|
||||||
title: "AbstractItemModel"
|
|
||||||
Component.onCompleted: visible = true
|
|
||||||
|
|
||||||
Component
|
|
||||||
{
|
|
||||||
id: myListModelDelegate
|
|
||||||
Label { text: "Name:" + name }
|
|
||||||
}
|
|
||||||
|
|
||||||
ListView
|
|
||||||
{
|
|
||||||
anchors.fill: parent
|
|
||||||
model: myListModel
|
|
||||||
delegate: myListModelDelegate
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
add_subdirectory(HelloWorld)
|
|
||||||
add_subdirectory(SimpleData)
|
|
||||||
add_subdirectory(SlotsAndProperties)
|
|
||||||
add_subdirectory(QtObjectMacro)
|
|
||||||
add_subdirectory(ContactApp)
|
|
||||||
add_subdirectory(AbstractItemModel)
|
|
|
@ -1,33 +0,0 @@
|
||||||
import NimQml, NimQmlMacros, ContactList
|
|
||||||
|
|
||||||
QtObject:
|
|
||||||
type ApplicationLogic* = ref object of QObject
|
|
||||||
contactList: ContactList
|
|
||||||
app: QApplication
|
|
||||||
|
|
||||||
proc delete*(self: ApplicationLogic) =
|
|
||||||
let qobject = self.QObject
|
|
||||||
qobject.delete
|
|
||||||
self.contactList.delete
|
|
||||||
|
|
||||||
proc newApplicationLogic*(app: QApplication): ApplicationLogic =
|
|
||||||
new(result)
|
|
||||||
result.contactList = newContactList()
|
|
||||||
result.app = app
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
method getContactList(self: ApplicationLogic): QVariant {.slot.} =
|
|
||||||
return newQVariant(self.contactList)
|
|
||||||
|
|
||||||
method onLoadTriggered(self: ApplicationLogic) {.slot.} =
|
|
||||||
echo "Load Triggered"
|
|
||||||
self.contactList.add("John", "Doo")
|
|
||||||
|
|
||||||
method onSaveTriggered(self: ApplicationLogic) {.slot.} =
|
|
||||||
echo "Save Triggered"
|
|
||||||
|
|
||||||
method onExitTriggered(self: ApplicationLogic) {.slot.} =
|
|
||||||
self.app.quit
|
|
||||||
|
|
||||||
QtProperty[QVariant] contactList:
|
|
||||||
read = getContactList
|
|
|
@ -1,2 +0,0 @@
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
add_nim_executable(TARGET NimQmlContactApp SOURCES main.nim PATHS ../../NimQml)
|
|
|
@ -1,51 +0,0 @@
|
||||||
## Please note we are using templates where ordinarily we would like to use procedures
|
|
||||||
## due to bug: https://github.com/Araq/Nim/issues/1821
|
|
||||||
import NimQml, NimQmlMacros
|
|
||||||
|
|
||||||
QtObject:
|
|
||||||
type Contact* = ref object of QObject
|
|
||||||
name: string
|
|
||||||
surname: string
|
|
||||||
|
|
||||||
proc delete*(self: Contact) =
|
|
||||||
let qobject = self.QObject
|
|
||||||
qobject.delete
|
|
||||||
|
|
||||||
proc newContact*(): Contact =
|
|
||||||
new(result)
|
|
||||||
result.name = ""
|
|
||||||
result.create
|
|
||||||
|
|
||||||
method firstName*(self: Contact): string {.slot.} =
|
|
||||||
result = self.name
|
|
||||||
|
|
||||||
method firstNameChanged*(self: Contact) {.signal.}
|
|
||||||
|
|
||||||
method setFirstName(self: Contact, name: string) {.slot.} =
|
|
||||||
if self.name != name:
|
|
||||||
self.name = name
|
|
||||||
self.firstNameChanged()
|
|
||||||
|
|
||||||
proc `firstName=`*(self: Contact, name: string) = self.setFirstName(name)
|
|
||||||
|
|
||||||
QtProperty[string] firstName:
|
|
||||||
read = firstName
|
|
||||||
write = setFirstName
|
|
||||||
notify = firstNameChanged
|
|
||||||
|
|
||||||
method surname*(self: Contact): string {.slot.} =
|
|
||||||
result = self.surname
|
|
||||||
|
|
||||||
method surnameChanged*(self: Contact) {.signal.}
|
|
||||||
|
|
||||||
method setSurname(self: Contact, surname: string) {.slot.} =
|
|
||||||
if self.surname != surname:
|
|
||||||
self.surname = surname
|
|
||||||
self.surnameChanged()
|
|
||||||
|
|
||||||
proc `surname=`*(self: Contact, surname: string) = self.setSurname(surname)
|
|
||||||
|
|
||||||
QtProperty[string] surname:
|
|
||||||
read = surname
|
|
||||||
write = setSurname
|
|
||||||
notify = surnameChanged
|
|
|
@ -1,62 +0,0 @@
|
||||||
import NimQml, NimQmlMacros, Contact, Tables
|
|
||||||
|
|
||||||
QtObject:
|
|
||||||
type
|
|
||||||
ContactList* = ref object of QAbstractListModel
|
|
||||||
contacts*: seq[Contact]
|
|
||||||
ContactRoles {.pure.} = enum
|
|
||||||
FirstName = 0
|
|
||||||
Surname = 1
|
|
||||||
|
|
||||||
converter toCInt(value: ContactRoles): cint = return value.cint
|
|
||||||
converter toCInt(value: int): cint = return value.cint
|
|
||||||
converter toInt(value: ContactRoles): int = return value.int
|
|
||||||
converter toInt(value: cint): int = return value.int
|
|
||||||
converter toQVariant(value: string): QVariant = return value.newQVariant
|
|
||||||
|
|
||||||
proc delete(self: ContactList) =
|
|
||||||
let model = self.QAbstractListModel
|
|
||||||
model.delete
|
|
||||||
for contact in self.contacts:
|
|
||||||
contact.delete
|
|
||||||
self.contacts = @[]
|
|
||||||
|
|
||||||
proc newContactList*(): ContactList =
|
|
||||||
new(result, delete)
|
|
||||||
result.contacts = @[]
|
|
||||||
result.create
|
|
||||||
|
|
||||||
method rowCount(self: ContactList, index: QModelIndex = nil): cint =
|
|
||||||
return self.contacts.len
|
|
||||||
|
|
||||||
method data(self: ContactList, index: QModelIndex, role: cint): QVariant =
|
|
||||||
if not index.isValid:
|
|
||||||
return
|
|
||||||
if index.row < 0 or index.row >= self.contacts.len:
|
|
||||||
return
|
|
||||||
let contact = self.contacts[index.row]
|
|
||||||
let contactRole = role.ContactRoles
|
|
||||||
case contactRole:
|
|
||||||
of ContactRoles.FirstName: return contact.firstName
|
|
||||||
of ContactRoles.Surname: return contact.surname
|
|
||||||
else: return
|
|
||||||
|
|
||||||
method roleNames(self: ContactList): Table[cint, cstring] =
|
|
||||||
result = initTable[cint, cstring]()
|
|
||||||
result[ContactRoles.FirstName] = "firstName"
|
|
||||||
result[ContactRoles.Surname] = "surname"
|
|
||||||
|
|
||||||
method add*(self: ContactList, name: string, surname: string) {.slot.} =
|
|
||||||
let contact = newContact()
|
|
||||||
contact.firstName = name
|
|
||||||
contact.surname = surname
|
|
||||||
self.beginInsertRows(newQModelIndex(), self.contacts.len, self.contacts.len)
|
|
||||||
self.contacts.add(contact)
|
|
||||||
self.endInsertRows()
|
|
||||||
|
|
||||||
method del*(self: ContactList, pos: int) {.slot.} =
|
|
||||||
if pos < 0 or pos >= self.contacts.len:
|
|
||||||
return
|
|
||||||
self.beginRemoveRows(newQModelIndex(), pos, pos)
|
|
||||||
self.contacts.del(pos)
|
|
||||||
self.endRemoveRows
|
|
|
@ -1,17 +0,0 @@
|
||||||
import NimQml, ApplicationLogic
|
|
||||||
|
|
||||||
proc mainProc() =
|
|
||||||
let app = newQApplication()
|
|
||||||
defer: app.delete
|
|
||||||
let logic = newApplicationLogic(app)
|
|
||||||
defer: logic.delete
|
|
||||||
let engine = newQQmlApplicationEngine()
|
|
||||||
defer: engine.delete
|
|
||||||
let logicVariant = newQVariant(logic)
|
|
||||||
defer: logicVariant.delete
|
|
||||||
engine.rootContext.setContextProperty("logic", logicVariant)
|
|
||||||
engine.load("main.qml")
|
|
||||||
app.exec()
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
mainProc()
|
|
|
@ -1,93 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow {
|
|
||||||
|
|
||||||
width: 500
|
|
||||||
height: 300
|
|
||||||
title: "ContactApp"
|
|
||||||
visible: true
|
|
||||||
|
|
||||||
menuBar: MenuBar {
|
|
||||||
Menu {
|
|
||||||
title: "&File"
|
|
||||||
MenuItem { text: "&Load"; onTriggered: logic.onLoadTriggered() }
|
|
||||||
MenuItem { text: "&Save"; onTriggered: logic.onSaveTriggered() }
|
|
||||||
MenuItem { text: "&Exit"; onTriggered: logic.onExitTriggered() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: tableTextDelegate
|
|
||||||
Label {
|
|
||||||
id: tableTextDelegateInstance
|
|
||||||
property var styleData: undefined
|
|
||||||
states: State {
|
|
||||||
when: styleData !== undefined
|
|
||||||
PropertyChanges {
|
|
||||||
target: tableTextDelegateInstance;
|
|
||||||
text: styleData.value;
|
|
||||||
color: styleData.textColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: tableButtonDelegate
|
|
||||||
Button {
|
|
||||||
id: tableButtonDelegateInstance
|
|
||||||
property var styleData: undefined
|
|
||||||
text: "Delete"
|
|
||||||
onClicked: logic.contactList.del(styleData.row)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
id: tableItemDelegate
|
|
||||||
Loader {
|
|
||||||
id: tableItemDelegateInstance
|
|
||||||
sourceComponent: {
|
|
||||||
if (styleData.column === 0 || styleData.column === 1)
|
|
||||||
return tableTextDelegate
|
|
||||||
else if (styleData.column === 2)
|
|
||||||
return tableButtonDelegate
|
|
||||||
else
|
|
||||||
return tableTextDelegate
|
|
||||||
}
|
|
||||||
Binding {
|
|
||||||
target: tableItemDelegateInstance.item
|
|
||||||
property: "styleData"
|
|
||||||
value: styleData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TableView {
|
|
||||||
model: logic.contactList
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
|
||||||
TableViewColumn { role: "firstName"; title: "FirstName"; width: 200 }
|
|
||||||
TableViewColumn { role: "surname"; title: "Surname"; width: 200}
|
|
||||||
TableViewColumn { width: 100; }
|
|
||||||
itemDelegate: tableItemDelegate
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Label { text: "Name" }
|
|
||||||
TextField { id: nameTextField; Layout.fillWidth: true; text: "" }
|
|
||||||
Label { text: "Surname" }
|
|
||||||
TextField { id: surnameTextField; Layout.fillWidth: true; text: "" }
|
|
||||||
Button {
|
|
||||||
text: "Add"
|
|
||||||
onClicked: logic.contactList.add(nameTextField.text, surnameTextField.text)
|
|
||||||
enabled: nameTextField.text !== "" && surnameTextField.text !== ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
add_nim_executable(TARGET NimQmlHelloWorld SOURCES main.nim PATHS ../../NimQml)
|
|
|
@ -1,18 +0,0 @@
|
||||||
import NimQml
|
|
||||||
import macros
|
|
||||||
import typeinfo
|
|
||||||
|
|
||||||
proc mainProc() =
|
|
||||||
var app = newQApplication()
|
|
||||||
defer: app.delete()
|
|
||||||
|
|
||||||
var engine = newQQmlApplicationEngine()
|
|
||||||
defer: engine.delete()
|
|
||||||
|
|
||||||
engine.load("main.qml")
|
|
||||||
app.exec()
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
mainProc()
|
|
||||||
GC_fullcollect()
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow
|
|
||||||
{
|
|
||||||
width: 400
|
|
||||||
height: 300
|
|
||||||
title: "Hello World"
|
|
||||||
Component.onCompleted: visible = true
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
add_nim_executable(TARGET NimQmlQtObjectMacro SOURCES main.nim PATHS ../../NimQml)
|
|
|
@ -1,31 +0,0 @@
|
||||||
## Please note we are using templates where ordinarily we would like to use procedures
|
|
||||||
## due to bug: https://github.com/Araq/Nim/issues/1821
|
|
||||||
import NimQml, NimQmlMacros
|
|
||||||
|
|
||||||
QtObject:
|
|
||||||
type Contact* = ref object of QObject
|
|
||||||
m_name: string
|
|
||||||
|
|
||||||
proc delete*(self: Contact) =
|
|
||||||
var qobject = self.QObject
|
|
||||||
qobject.delete()
|
|
||||||
|
|
||||||
proc newContact*(): Contact =
|
|
||||||
new(result, delete)
|
|
||||||
result.m_name = "InitialName"
|
|
||||||
result.create
|
|
||||||
|
|
||||||
method getName*(self: Contact): string {.slot.} =
|
|
||||||
result = self.m_name
|
|
||||||
|
|
||||||
method nameChanged*(self: Contact) {.signal.}
|
|
||||||
|
|
||||||
method setName*(self: Contact, name: string) {.slot.} =
|
|
||||||
if self.m_name != name:
|
|
||||||
self.m_name = name
|
|
||||||
self.nameChanged()
|
|
||||||
|
|
||||||
QtProperty[string] name:
|
|
||||||
read = getName
|
|
||||||
write = setName
|
|
||||||
notify = nameChanged
|
|
|
@ -1,23 +0,0 @@
|
||||||
import NimQml
|
|
||||||
import Contact
|
|
||||||
|
|
||||||
proc mainProc() =
|
|
||||||
var app = newQApplication()
|
|
||||||
defer: app.delete()
|
|
||||||
|
|
||||||
var contact = newContact()
|
|
||||||
defer: contact.delete()
|
|
||||||
|
|
||||||
var engine = newQQmlApplicationEngine()
|
|
||||||
defer: engine.delete()
|
|
||||||
|
|
||||||
var variant = newQVariant(contact)
|
|
||||||
defer: variant.delete()
|
|
||||||
|
|
||||||
engine.rootContext.setContextProperty("contact", variant)
|
|
||||||
engine.load("main.qml")
|
|
||||||
app.exec()
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
mainProc()
|
|
||||||
GC_fullcollect()
|
|
|
@ -1,33 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow
|
|
||||||
{
|
|
||||||
width: 400
|
|
||||||
height: 300
|
|
||||||
|
|
||||||
Component.onCompleted: visible = true
|
|
||||||
|
|
||||||
ColumnLayout
|
|
||||||
{
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: "Current name is:" + contact.name
|
|
||||||
}
|
|
||||||
|
|
||||||
TextField
|
|
||||||
{
|
|
||||||
id: textField
|
|
||||||
}
|
|
||||||
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
text: "Change Name"
|
|
||||||
onClicked: contact.name = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
add_nim_executable(TARGET NimQmlSimpleData SOURCES main.nim PATHS ../../NimQml)
|
|
|
@ -1,34 +0,0 @@
|
||||||
import NimQml
|
|
||||||
import macros
|
|
||||||
import typeinfo
|
|
||||||
|
|
||||||
proc mainProc() =
|
|
||||||
var app = newQApplication()
|
|
||||||
defer: app.delete()
|
|
||||||
|
|
||||||
var engine = newQQmlApplicationEngine()
|
|
||||||
defer: engine.delete()
|
|
||||||
|
|
||||||
var qVar1 = newQVariant(10)
|
|
||||||
defer: qVar1.delete()
|
|
||||||
|
|
||||||
var qVar2 = newQVariant("Hello World")
|
|
||||||
defer: qVar2.delete()
|
|
||||||
|
|
||||||
var qVar3 = newQVariant(false)
|
|
||||||
defer: qVar3.delete()
|
|
||||||
|
|
||||||
var qVar4 = newQVariant(3.5.float)
|
|
||||||
defer: qVar4.delete()
|
|
||||||
|
|
||||||
engine.rootContext.setContextProperty("qVar1", qVar1)
|
|
||||||
engine.rootContext.setContextProperty("qVar2", qVar2)
|
|
||||||
engine.rootContext.setContextProperty("qVar3", qVar3)
|
|
||||||
engine.rootContext.setContextProperty("qVar4", qVar4)
|
|
||||||
engine.load("main.qml")
|
|
||||||
app.exec()
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
mainProc()
|
|
||||||
GC_fullcollect()
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow
|
|
||||||
{
|
|
||||||
width: 400
|
|
||||||
height: 300
|
|
||||||
title: "SimpleData"
|
|
||||||
Component.onCompleted: visible = true
|
|
||||||
|
|
||||||
ColumnLayout
|
|
||||||
{
|
|
||||||
anchors.fill: parent
|
|
||||||
SpinBox { value: qVar1}
|
|
||||||
TextField { text: qVar2}
|
|
||||||
CheckBox { checked: qVar3}
|
|
||||||
SpinBox { value: qVar4; decimals: 1 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/main.qml DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
add_nim_executable(TARGET NimQmlSlotsAndProperties SOURCES main.nim PATHS ../../NimQml)
|
|
|
@ -1,40 +0,0 @@
|
||||||
## Please note we are using templates where ordinarily we would like to use procedures
|
|
||||||
## due to bug: https://github.com/Araq/Nim/issues/1821
|
|
||||||
import NimQml
|
|
||||||
|
|
||||||
type Contact = ref object of QObject
|
|
||||||
m_name: string
|
|
||||||
|
|
||||||
proc delete*(self: Contact) =
|
|
||||||
var qobject = self.QObject
|
|
||||||
qobject.delete()
|
|
||||||
|
|
||||||
proc create*(self: Contact) =
|
|
||||||
var qobject = self.QObject
|
|
||||||
qobject.create()
|
|
||||||
self.m_name = "InitialName"
|
|
||||||
self.registerSlot("getName", [QMetaType.QString])
|
|
||||||
self.registerSlot("setName", [QMetaType.Void, QMetaType.QString])
|
|
||||||
self.registerSignal("nameChanged", [QMetaType.Void])
|
|
||||||
self.registerProperty("name", QMetaType.QString, "getName", "setName", "nameChanged")
|
|
||||||
|
|
||||||
proc newContact*(): Contact =
|
|
||||||
new(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
method getName*(self: Contact): string =
|
|
||||||
result = self.m_name
|
|
||||||
|
|
||||||
method setName*(self: Contact, name: string) =
|
|
||||||
if self.m_name != name:
|
|
||||||
self.m_name = name
|
|
||||||
self.emit("nameChanged")
|
|
||||||
|
|
||||||
method onSlotCalled(self: Contact, slotName: string, args: openarray[QVariant]) =
|
|
||||||
case slotName:
|
|
||||||
of "getName":
|
|
||||||
args[0].stringVal = self.getName()
|
|
||||||
of "setName":
|
|
||||||
self.setName(args[1].stringVal)
|
|
||||||
else:
|
|
||||||
discard()
|
|
|
@ -1,24 +0,0 @@
|
||||||
import NimQml
|
|
||||||
import Contact
|
|
||||||
|
|
||||||
proc mainProc() =
|
|
||||||
var app = newQApplication()
|
|
||||||
defer: app.delete()
|
|
||||||
|
|
||||||
var contact = newContact()
|
|
||||||
defer: contact.delete()
|
|
||||||
|
|
||||||
var engine = newQQmlApplicationEngine()
|
|
||||||
defer: engine.delete()
|
|
||||||
|
|
||||||
var variant = newQVariant(contact)
|
|
||||||
defer: variant.delete()
|
|
||||||
|
|
||||||
engine.rootContext.setContextProperty("contact", variant)
|
|
||||||
engine.load("main.qml")
|
|
||||||
app.exec()
|
|
||||||
|
|
||||||
when isMainModule:
|
|
||||||
mainProc()
|
|
||||||
GC_fullcollect()
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
import QtQuick 2.2
|
|
||||||
import QtQuick.Controls 1.2
|
|
||||||
import QtQuick.Layouts 1.1
|
|
||||||
import QtQuick.Window 2.1
|
|
||||||
|
|
||||||
ApplicationWindow
|
|
||||||
{
|
|
||||||
width: 400
|
|
||||||
height: 300
|
|
||||||
|
|
||||||
Component.onCompleted: visible = true
|
|
||||||
|
|
||||||
ColumnLayout
|
|
||||||
{
|
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Label
|
|
||||||
{
|
|
||||||
text: "Current name is:" + contact.name
|
|
||||||
}
|
|
||||||
|
|
||||||
TextField
|
|
||||||
{
|
|
||||||
id: textField
|
|
||||||
}
|
|
||||||
|
|
||||||
Button
|
|
||||||
{
|
|
||||||
text: "Change Name"
|
|
||||||
onClicked: contact.name = textField.text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,795 +0,0 @@
|
||||||
include NimQmlTypes
|
|
||||||
|
|
||||||
when defined(windows):
|
|
||||||
const dOtherSideDll* = "libDOtherSide.dll"
|
|
||||||
elif defined(macosx):
|
|
||||||
const dOtherSideDll* = "libDOtherSide.dylib"
|
|
||||||
else:
|
|
||||||
const dOtherSideDll* = "libDOtherSide.so"
|
|
||||||
|
|
||||||
## NimQml aims to provide binding to the QML for the Nim programming language
|
|
||||||
##
|
|
||||||
## Optional finalizers
|
|
||||||
## -------------------
|
|
||||||
## To enable finalizers you must define ``nimqml_use_finalizers`` by passing
|
|
||||||
## the option, ``-d:nimqml_use_finalizers``, to the Nim compiler. The relevant
|
|
||||||
## delete method will then be called automatically by the garbage collector.
|
|
||||||
## Care should be taken when using this approach as there are no guarantees
|
|
||||||
## when a finalzier will be run, or if, indeed, it will run at all.
|
|
||||||
|
|
||||||
type QMetaType* {.pure.} = enum ## \
|
|
||||||
## Qt metatypes values used for specifing the
|
|
||||||
## signals and slots argument and return types.
|
|
||||||
##
|
|
||||||
## This enum mimic the QMetaType::Type C++ enum
|
|
||||||
UnknownType = cint(0),
|
|
||||||
Bool = cint(1),
|
|
||||||
Int = cint(2),
|
|
||||||
QString = cint(10),
|
|
||||||
VoidStar = cint(31),
|
|
||||||
QObjectStar = cint(39),
|
|
||||||
QVariant = cint(41),
|
|
||||||
Void = cint(43),
|
|
||||||
|
|
||||||
var qobjectRegistry = initTable[ptr QObjectObj, bool]()
|
|
||||||
|
|
||||||
template debugMsg(message: string) =
|
|
||||||
{.push warning[user]: off.} # workaround to remove warnings; this won't be needed soon
|
|
||||||
when defined(debug):
|
|
||||||
{.pop.}
|
|
||||||
echo "NimQml: ", message
|
|
||||||
else:
|
|
||||||
{.pop.}
|
|
||||||
|
|
||||||
template debugMsg(typeName: string, procName: string) =
|
|
||||||
{.push warning[user]: off.} # workaround to remove warnings; this won't be needed soon
|
|
||||||
when defined(debug):
|
|
||||||
{.pop.}
|
|
||||||
var message = typeName
|
|
||||||
message &= ": "
|
|
||||||
message &= procName
|
|
||||||
debugMsg(message)
|
|
||||||
else:
|
|
||||||
{.pop.}
|
|
||||||
|
|
||||||
template debugMsg(typeName: string, procName: string, userMessage: string) =
|
|
||||||
{.push warning[user]: off.} # workaround to remove warnings; this won't be needed soon
|
|
||||||
when defined(debug):
|
|
||||||
{.pop.}
|
|
||||||
var message = typeName
|
|
||||||
message &= ": "
|
|
||||||
message &= procName
|
|
||||||
message &= " "
|
|
||||||
message &= userMessage
|
|
||||||
debugMsg(message)
|
|
||||||
else:
|
|
||||||
{.pop.}
|
|
||||||
|
|
||||||
template newWithCondFinalizer(variable: expr, finalizer: expr) =
|
|
||||||
## calls ``new`` but only setting a finalizer when ``nimqml_use_finalizers``
|
|
||||||
## is defined
|
|
||||||
{.push warning[user]: off.} # workaround to remove warnings; this won't be needed soon
|
|
||||||
when defined(nimqml_use_finalizers):
|
|
||||||
{.pop.}
|
|
||||||
new(variable, finalizer)
|
|
||||||
else:
|
|
||||||
{.pop.}
|
|
||||||
new(variable)
|
|
||||||
|
|
||||||
# QVariant
|
|
||||||
proc dos_qvariant_create(variant: var RawQVariant) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_create_int(variant: var RawQVariant, value: cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_create_bool(variant: var RawQVariant, value: bool) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_create_string(variant: var RawQVariant, value: cstring) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_create_qobject(variant: var RawQVariant, value: RawQObject) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_create_qvariant(variant: var RawQVariant, value: RawQVariant) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_create_float(variant: var RawQVariant, value: cfloat) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_create_double(variant: var RawQVariant, value: cdouble) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_delete(variant: RawQVariant) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_isnull(variant: RawQVariant, isNull: var bool) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_toInt(variant: RawQVariant, value: var cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_toBool(variant: RawQVariant, value: var bool) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_toString(variant: RawQVariant, value: var cstring) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_setInt(variant: RawQVariant, value: cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_setBool(variant: RawQVariant, value: bool) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_setString(variant: RawQVariant, value: cstring) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_assign(leftValue: RawQVariant, rightValue: RawQVariant) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_toFloat(variant: RawQVariant, value: var cfloat) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_setFloat(variant: RawQVariant, value: float) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_toDouble(variant: RawQVariant, value: var cdouble) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_setDouble(variant: RawQVariant, value: cdouble) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qvariant_setQObject(variant: RawQVariant, value: RawQObject) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_chararray_delete(rawCString: cstring) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
proc create*(variant: QVariant) =
|
|
||||||
## Create a new QVariant
|
|
||||||
dos_qvariant_create(variant.data)
|
|
||||||
variant.deleted = false
|
|
||||||
|
|
||||||
proc create*(variant: QVariant, value: cint) =
|
|
||||||
## Create a new QVariant given a cint value
|
|
||||||
dos_qvariant_create_int(variant.data, value)
|
|
||||||
variant.deleted = false
|
|
||||||
|
|
||||||
proc create*(variant: QVariant, value: bool) =
|
|
||||||
## Create a new QVariant given a bool value
|
|
||||||
dos_qvariant_create_bool(variant.data, value)
|
|
||||||
variant.deleted = false
|
|
||||||
|
|
||||||
proc create*(variant: QVariant, value: string) =
|
|
||||||
## Create a new QVariant given a string value
|
|
||||||
dos_qvariant_create_string(variant.data, value)
|
|
||||||
variant.deleted = false
|
|
||||||
|
|
||||||
proc create*(variant: QVariant, value: QObject) =
|
|
||||||
## Create a new QVariant given a QObject
|
|
||||||
dos_qvariant_create_qobject(variant.data, value.data.RawQObject)
|
|
||||||
variant.deleted = false
|
|
||||||
|
|
||||||
proc create*(variant: QVariant, value: RawQVariant) =
|
|
||||||
## Create a new QVariant given another QVariant.
|
|
||||||
## The inner value of the QVariant is copied
|
|
||||||
dos_qvariant_create_qvariant(variant.data, value)
|
|
||||||
variant.deleted = false
|
|
||||||
|
|
||||||
proc create*(variant: QVariant, value: cfloat) =
|
|
||||||
## Create a new QVariant given a cfloat value
|
|
||||||
dos_qvariant_create_float(variant.data, value)
|
|
||||||
variant.deleted = false
|
|
||||||
|
|
||||||
proc create*(variant: QVariant, value: QVariant) =
|
|
||||||
## Create a new QVariant given another QVariant.
|
|
||||||
## The inner value of the QVariant is copied
|
|
||||||
create(variant, value.data)
|
|
||||||
|
|
||||||
proc delete*(variant: QVariant) =
|
|
||||||
## Delete a QVariant
|
|
||||||
if not variant.deleted:
|
|
||||||
debugMsg("QVariant", "delete")
|
|
||||||
dos_qvariant_delete(variant.data)
|
|
||||||
variant.data = nil.RawQVariant
|
|
||||||
variant.deleted = true
|
|
||||||
|
|
||||||
proc newQVariant*(): QVariant =
|
|
||||||
## Return a new QVariant
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
proc newQVariant*(value: cint): QVariant =
|
|
||||||
## Return a new QVariant given a cint
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create(value)
|
|
||||||
|
|
||||||
proc newQVariant*(value: bool): QVariant =
|
|
||||||
## Return a new QVariant given a bool
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create(value)
|
|
||||||
|
|
||||||
proc newQVariant*(value: string): QVariant =
|
|
||||||
## Return a new QVariant given a string
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create(value)
|
|
||||||
|
|
||||||
proc newQVariant*(value: QObject): QVariant =
|
|
||||||
## Return a new QVariant given a QObject
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create(value)
|
|
||||||
|
|
||||||
proc newQVariant*(value: RawQVariant): QVariant =
|
|
||||||
## Return a new QVariant given a raw QVariant pointer
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create(value)
|
|
||||||
|
|
||||||
proc newQVariant*(value: QVariant): QVariant =
|
|
||||||
## Return a new QVariant given another QVariant
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create(value)
|
|
||||||
|
|
||||||
proc newQVariant*(value: float): QVariant =
|
|
||||||
## Return a new QVariant given a float
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create(value)
|
|
||||||
|
|
||||||
proc isNull*(variant: QVariant): bool =
|
|
||||||
## Return true if the QVariant value is null, false otherwise
|
|
||||||
dos_qvariant_isnull(variant.data, result)
|
|
||||||
|
|
||||||
proc intVal*(variant: QVariant): int =
|
|
||||||
## Return the QVariant value as int
|
|
||||||
var rawValue: cint
|
|
||||||
dos_qvariant_toInt(variant.data, rawValue)
|
|
||||||
result = rawValue.cint
|
|
||||||
|
|
||||||
proc `intVal=`*(variant: QVariant, value: int) =
|
|
||||||
## Sets the QVariant value int value
|
|
||||||
var rawValue = value.cint
|
|
||||||
dos_qvariant_setInt(variant.data, rawValue)
|
|
||||||
|
|
||||||
proc boolVal*(variant: QVariant): bool =
|
|
||||||
## Return the QVariant value as bool
|
|
||||||
dos_qvariant_toBool(variant.data, result)
|
|
||||||
|
|
||||||
proc `boolVal=`*(variant: QVariant, value: bool) =
|
|
||||||
## Sets the QVariant bool value
|
|
||||||
dos_qvariant_setBool(variant.data, value)
|
|
||||||
|
|
||||||
proc floatVal*(variant: QVariant): float =
|
|
||||||
## Return the QVariant value as float
|
|
||||||
var rawValue: cfloat
|
|
||||||
dos_qvariant_toFloat(variant.data, rawValue)
|
|
||||||
result = rawValue.cfloat
|
|
||||||
|
|
||||||
proc `floatVal=`*(variant: QVariant, value: float) =
|
|
||||||
## Sets the QVariant float value
|
|
||||||
dos_qvariant_setFloat(variant.data, value.cfloat)
|
|
||||||
|
|
||||||
proc doubleVal*(variant: QVariant): cdouble =
|
|
||||||
## Return the QVariant value as double
|
|
||||||
var rawValue: cdouble
|
|
||||||
dos_qvariant_toDouble(variant.data, rawValue)
|
|
||||||
result = rawValue
|
|
||||||
|
|
||||||
proc `doubleVal=`*(variant: QVariant, value: cdouble) =
|
|
||||||
## Sets the QVariant double value
|
|
||||||
dos_qvariant_setDouble(variant.data, value)
|
|
||||||
|
|
||||||
proc stringVal*(variant: QVariant): string =
|
|
||||||
## Return the QVariant value as string
|
|
||||||
var rawCString: cstring
|
|
||||||
dos_qvariant_toString(variant.data, rawCString)
|
|
||||||
result = $rawCString
|
|
||||||
dos_chararray_delete(rawCString)
|
|
||||||
|
|
||||||
proc `stringVal=`*(variant: QVariant, value: string) =
|
|
||||||
## Sets the QVariant string value
|
|
||||||
dos_qvariant_setString(variant.data, value)
|
|
||||||
|
|
||||||
proc `qobjectVal=`*(variant: QVariant, value: QObject) =
|
|
||||||
## Sets the QVariant qobject value
|
|
||||||
dos_qvariant_setQObject(variant.data, value.data.RawQObject)
|
|
||||||
|
|
||||||
proc assign*(leftValue: QVariant, rightValue: QVariant) =
|
|
||||||
## Assign a QVariant with another. The inner value of the QVariant is copied
|
|
||||||
dos_qvariant_assign(leftValue.data, rightValue.data)
|
|
||||||
|
|
||||||
# QQmlApplicationEngine
|
|
||||||
proc dos_qqmlapplicationengine_create(engine: var RawQQmlApplicationEngine) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qqmlapplicationengine_load(engine: RawQQmlApplicationEngine, filename: cstring) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qqmlapplicationengine_context(engine: RawQQmlApplicationEngine, context: var QQmlContext) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qqmlapplicationengine_delete(engine: RawQQmlApplicationEngine) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
proc create*(engine: QQmlApplicationEngine) =
|
|
||||||
## Create an new QQmlApplicationEngine
|
|
||||||
dos_qqmlapplicationengine_create(engine.data)
|
|
||||||
engine.deleted = false
|
|
||||||
|
|
||||||
proc load*(engine: QQmlApplicationEngine, filename: cstring) =
|
|
||||||
## Load the given Qml file
|
|
||||||
dos_qqmlapplicationengine_load(engine.data, filename)
|
|
||||||
|
|
||||||
proc rootContext*(engine: QQmlApplicationEngine): QQmlContext =
|
|
||||||
## Return the engine root context
|
|
||||||
dos_qqmlapplicationengine_context(engine.data, result)
|
|
||||||
|
|
||||||
proc delete*(engine: QQmlApplicationEngine) =
|
|
||||||
## Delete the given QQmlApplicationEngine
|
|
||||||
if not engine.deleted:
|
|
||||||
debugMsg("QQmlApplicationEngine", "delete")
|
|
||||||
dos_qqmlapplicationengine_delete(engine.data)
|
|
||||||
engine.data = nil.RawQQmlApplicationEngine
|
|
||||||
engine.deleted = true
|
|
||||||
|
|
||||||
proc newQQmlApplicationEngine*(): QQmlApplicationEngine =
|
|
||||||
## Return a new QQmlApplicationEngine
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
# QQmlContext
|
|
||||||
proc dos_qqmlcontext_setcontextproperty(context: QQmlContext, propertyName: cstring, propertyValue: RawQVariant) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
proc setContextProperty*(context: QQmlContext, propertyName: string, propertyValue: QVariant) =
|
|
||||||
## Sets a new property with the given value
|
|
||||||
dos_qqmlcontext_setcontextproperty(context, propertyName, propertyValue.data)
|
|
||||||
|
|
||||||
# QApplication
|
|
||||||
proc dos_qapplication_create() {.cdecl, dynlib: dOtherSideDll, importc.}
|
|
||||||
proc dos_qapplication_exec() {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qapplication_quit() {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qapplication_delete() {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
proc create*(application: QApplication) =
|
|
||||||
## Create a new QApplication
|
|
||||||
dos_qapplication_create()
|
|
||||||
application.deleted = false
|
|
||||||
|
|
||||||
proc exec*(application: QApplication) =
|
|
||||||
## Start the Qt event loop
|
|
||||||
dos_qapplication_exec()
|
|
||||||
|
|
||||||
proc quit*(application: QApplication) =
|
|
||||||
## Quit the Qt event loop
|
|
||||||
dos_qapplication_quit()
|
|
||||||
|
|
||||||
proc delete*(application: QApplication) =
|
|
||||||
## Delete the given QApplication
|
|
||||||
if not application.deleted:
|
|
||||||
debugMsg("QApplication", "delete")
|
|
||||||
dos_qapplication_delete()
|
|
||||||
application.deleted = true
|
|
||||||
|
|
||||||
proc newQApplication*(): QApplication =
|
|
||||||
## Return a new QApplication
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
# QGuiApplication
|
|
||||||
proc dos_qguiapplication_create() {.cdecl, dynlib: dOtherSideDll, importc.}
|
|
||||||
proc dos_qguiapplication_exec() {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qguiapplication_quit() {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qguiapplication_delete() {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
proc create*(application: QGuiApplication) =
|
|
||||||
## Create a new QApplication
|
|
||||||
dos_qguiapplication_create()
|
|
||||||
application.deleted = false
|
|
||||||
|
|
||||||
proc exec*(application: QGuiApplication) =
|
|
||||||
## Start the Qt event loop
|
|
||||||
dos_qguiapplication_exec()
|
|
||||||
|
|
||||||
proc quit*(application: QGuiApplication) =
|
|
||||||
## Quit the Qt event loop
|
|
||||||
dos_qguiapplication_quit()
|
|
||||||
|
|
||||||
proc delete*(application: QGuiApplication) =
|
|
||||||
## Delete the given QApplication
|
|
||||||
if not application.deleted:
|
|
||||||
debugMsg("QApplication", "delete")
|
|
||||||
dos_qguiapplication_delete()
|
|
||||||
application.deleted = true
|
|
||||||
|
|
||||||
proc newQGuiApplication*(): QGuiApplication =
|
|
||||||
## Return a new QApplication
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
# QObject
|
|
||||||
type RawQVariantArray {.unchecked.} = array[0..0, RawQVariant]
|
|
||||||
type RawQVariantArrayPtr = ptr RawQVariantArray
|
|
||||||
type RawQVariantSeq = seq[RawQVariant]
|
|
||||||
|
|
||||||
proc toVariantSeq(args: RawQVariantArrayPtr, numArgs: cint): seq[QVariant] =
|
|
||||||
result = @[]
|
|
||||||
for i in 0..numArgs-1:
|
|
||||||
result.add(newQVariant(args[i]))
|
|
||||||
|
|
||||||
proc toRawVariantSeq(args: openarray[QVariant]): RawQVariantSeq =
|
|
||||||
result = @[]
|
|
||||||
for variant in args:
|
|
||||||
result.add(variant.data)
|
|
||||||
|
|
||||||
proc delete(sequence: seq[QVariant]) =
|
|
||||||
for variant in sequence:
|
|
||||||
variant.delete
|
|
||||||
|
|
||||||
proc toCIntSeq(metaTypes: openarray[QMetaType]): seq[cint] =
|
|
||||||
result = @[]
|
|
||||||
for metaType in metaTypes:
|
|
||||||
result.add(cint(metaType))
|
|
||||||
|
|
||||||
type QObjectCallBack = proc(nimobject: ptr QObjectObj, slotName: RawQVariant, numArguments: cint, arguments: RawQVariantArrayPtr) {.cdecl.}
|
|
||||||
|
|
||||||
proc dos_qobject_create(qobject: var RawQObject, nimobject: ptr QObjectObj, qobjectCallback: QObjectCallBack) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qobject_delete(qobject: RawQObject) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qobject_slot_create(qobject: RawQObject, slotName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, slotIndex: var cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qobject_signal_create(qobject: RawQObject, signalName: cstring, argumentsCount: cint, argumentsMetaTypes: ptr cint, signalIndex: var cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qobject_signal_emit(qobject: RawQObject, signalName: cstring, argumentsCount: cint, arguments: ptr RawQVariant) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qobject_property_create(qobject: RawQObject, propertyName: cstring, propertyType: cint, readSlot: cstring, writeSlot: cstring, notifySignal: cstring) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
method onSlotCalled*(nimobject: QObject, slotName: string, args: openarray[QVariant]) =
|
|
||||||
## Called from the NimQml bridge when a slot is called from Qml.
|
|
||||||
## Subclasses can override the given method for handling the slot call
|
|
||||||
discard()
|
|
||||||
|
|
||||||
proc qobjectCallback(nimObject: ptr QObjectObj, slotName: RawQVariant, numArguments: cint, arguments: RawQVariantArrayPtr) {.cdecl, exportc.} =
|
|
||||||
if qobjectRegistry[nimObject]:
|
|
||||||
let qobject = cast[QObject](nimObject)
|
|
||||||
GC_ref(qobject)
|
|
||||||
let slotNameAsQVariant = newQVariant(slotName)
|
|
||||||
defer: slotNameAsQVariant.delete
|
|
||||||
let argumentsAsQVariant = arguments.toVariantSeq(numArguments)
|
|
||||||
defer: argumentsAsQVariant.delete
|
|
||||||
# Forward to args to the slot
|
|
||||||
qobject.onSlotCalled(slotNameAsQVariant.stringVal, argumentsAsQVariant)
|
|
||||||
# Update the slot return value
|
|
||||||
dos_qvariant_assign(arguments[0], argumentsAsQVariant[0].data)
|
|
||||||
GC_unref(qobject)
|
|
||||||
|
|
||||||
proc create*(qobject: QObject) =
|
|
||||||
## Create a new QObject
|
|
||||||
debugMsg("QObject", "create")
|
|
||||||
qobject.deleted = false
|
|
||||||
qobject.slots = initTable[string,cint]()
|
|
||||||
qobject.signals = initTable[string, cint]()
|
|
||||||
qobject.properties = initTable[string, cint]()
|
|
||||||
let qobjectPtr = addr(qobject[])
|
|
||||||
dos_qobject_create(qobject.data, qobjectPtr, qobjectCallback)
|
|
||||||
qobjectRegistry[qobjectPtr] = true
|
|
||||||
|
|
||||||
proc delete*(qobject: QObject) =
|
|
||||||
## Delete the given QObject
|
|
||||||
if not qobject.deleted:
|
|
||||||
debugMsg("QObject", "delete")
|
|
||||||
let qobjectPtr = addr(qobject[])
|
|
||||||
qobjectRegistry.del qobjectPtr
|
|
||||||
dos_qobject_delete(qobject.data)
|
|
||||||
qobject.data = nil.RawQObject
|
|
||||||
qobject.deleted = true
|
|
||||||
|
|
||||||
proc newQObject*(): QObject =
|
|
||||||
## Return a new QObject
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
proc registerSlot*(qobject: QObject,
|
|
||||||
slotName: string,
|
|
||||||
metaTypes: openarray[QMetaType]) =
|
|
||||||
## Register a slot in the QObject with the given name and signature
|
|
||||||
# Copy the metatypes array
|
|
||||||
var copy = toCIntSeq(metatypes)
|
|
||||||
var index: cint
|
|
||||||
dos_qobject_slot_create(qobject.data, slotName, cint(copy.len), addr(copy[0].cint), index)
|
|
||||||
qobject.slots[slotName] = index
|
|
||||||
|
|
||||||
proc registerSignal*(qobject: QObject,
|
|
||||||
signalName: string,
|
|
||||||
metatypes: openarray[QMetaType]) =
|
|
||||||
## Register a signal in the QObject with the given name and signature
|
|
||||||
var index: cint
|
|
||||||
if metatypes.len > 0:
|
|
||||||
var copy = toCIntSeq(metatypes)
|
|
||||||
dos_qobject_signal_create(qobject.data, signalName, copy.len.cint, addr(copy[0].cint), index)
|
|
||||||
else:
|
|
||||||
dos_qobject_signal_create(qobject.data, signalName, 0, nil, index)
|
|
||||||
qobject.signals[signalName] = index
|
|
||||||
|
|
||||||
proc registerProperty*(qobject: QObject,
|
|
||||||
propertyName: string,
|
|
||||||
propertyType: QMetaType,
|
|
||||||
readSlot: string,
|
|
||||||
writeSlot: string,
|
|
||||||
notifySignal: string) =
|
|
||||||
## Register a property in the QObject with the given name and type.
|
|
||||||
assert propertyName != nil, "property name cannot be nil"
|
|
||||||
# don't convert a nil string, else we get a strange memory address
|
|
||||||
let cReadSlot: cstring = if readSlot == nil: cast[cstring](nil) else: readSlot
|
|
||||||
let cWriteSlot: cstring = if writeSlot == nil: cast[cstring](nil) else: writeSlot
|
|
||||||
let cNotifySignal: cstring = if notifySignal == nil: cast[cstring](nil) else: notifySignal
|
|
||||||
dos_qobject_property_create(qobject.data, propertyName, propertyType.cint, cReadSlot, cWriteSlot, cNotifySignal)
|
|
||||||
|
|
||||||
proc emit*(qobject: QObject, signalName: string, args: openarray[QVariant] = []) =
|
|
||||||
## Emit the signal with the given name and values
|
|
||||||
if args.len > 0:
|
|
||||||
var copy = args.toRawVariantSeq
|
|
||||||
dos_qobject_signal_emit(qobject.data, signalName, copy.len.cint, addr(copy[0]))
|
|
||||||
else:
|
|
||||||
dos_qobject_signal_emit(qobject.data, signalName, 0, nil)
|
|
||||||
|
|
||||||
# QQuickView
|
|
||||||
proc dos_qquickview_create(view: var RawQQuickView) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qquickview_delete(view: RawQQuickView) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qquickview_show(view: RawQQuickView) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qquickview_source(view: RawQQuickView, filename: var cstring, length: var int) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qquickview_set_source(view: RawQQuickView, filename: cstring) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
proc create(view: var QQuickView) =
|
|
||||||
## Create a new QQuickView
|
|
||||||
dos_qquickview_create(view.data)
|
|
||||||
view.deleted = false
|
|
||||||
|
|
||||||
proc source(view: QQuickView): cstring =
|
|
||||||
## Return the source Qml file loaded by the view
|
|
||||||
var length: int
|
|
||||||
dos_qquickview_source(view.data, result, length)
|
|
||||||
|
|
||||||
proc `source=`(view: QQuickView, filename: cstring) =
|
|
||||||
## Sets the source Qml file laoded by the view
|
|
||||||
dos_qquickview_set_source(view.data, filename)
|
|
||||||
|
|
||||||
proc show(view: QQuickView) =
|
|
||||||
## Sets the view visible
|
|
||||||
dos_qquickview_show(view.data)
|
|
||||||
|
|
||||||
proc delete(view: QQuickView) =
|
|
||||||
## Delete the given QQuickView
|
|
||||||
if not view.deleted:
|
|
||||||
debugMsg("QQuickView", "delete")
|
|
||||||
dos_qquickview_delete(view.data)
|
|
||||||
view.data = nil.RawQQuickView
|
|
||||||
view.deleted = true
|
|
||||||
|
|
||||||
proc newQQuickView*(): QQuickView =
|
|
||||||
## Return a new QQuickView
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
# QModelIndex
|
|
||||||
proc dos_qmodelindex_create(modelIndex: var RawQModelIndex) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qmodelindex_delete(modelIndex: RawQModelIndex) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qmodelindex_row(modelIndex: RawQModelIndex, row: var cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qmodelindex_column(modelIndex: RawQModelIndex, column: var cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qmodelindex_isValid(modelIndex: RawQModelIndex, column: var bool) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qmodelindex_data(modelIndex: RawQModelIndex, role: cint, data: RawQVariant) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qmodelindex_parent(modelIndex: RawQModelIndex, parent: RawQModelIndex) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qmodelindex_child(modelIndex: RawQModelIndex, row: cint, column: cint, parent: RawQModelIndex) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qmodelindex_sibling(modelIndex: RawQModelIndex, row: cint, column: cint, sibling: RawQModelIndex) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
proc create*(modelIndex: var QModelIndex) =
|
|
||||||
## Create a new QModelIndex
|
|
||||||
dos_qmodelindex_create(modelIndex.data)
|
|
||||||
modelIndex.deleted = false
|
|
||||||
|
|
||||||
proc create*(modelIndex: var QModelIndex, rawQModelIndex: RawQModelIndex) =
|
|
||||||
## Create a new QModelIndex
|
|
||||||
modelIndex.data = rawQModelIndex
|
|
||||||
modelIndex.deleted = false
|
|
||||||
|
|
||||||
proc delete*(modelIndex: QModelIndex) =
|
|
||||||
## Delete the given QModelIndex
|
|
||||||
if not modelIndex.deleted:
|
|
||||||
debugMsg("QModelIndex", "delete")
|
|
||||||
dos_qmodelindex_delete(modelIndex.data)
|
|
||||||
modelIndex.data = nil.RawQModelIndex
|
|
||||||
modelIndex.deleted = true
|
|
||||||
|
|
||||||
proc newQModelIndex*(): QModelIndex =
|
|
||||||
## Return a new QModelIndex
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
proc newQModelIndex*(rawQModelIndex: RawQModelIndex): QModelIndex =
|
|
||||||
## Return a new QModelIndex given a raw index
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create(rawQModelIndex)
|
|
||||||
|
|
||||||
proc row*(modelIndex: QModelIndex): cint =
|
|
||||||
## Return the index row
|
|
||||||
dos_qmodelindex_row(modelIndex.data, result)
|
|
||||||
|
|
||||||
proc column*(modelIndex: QModelIndex): cint =
|
|
||||||
## Return the index column
|
|
||||||
dos_qmodelindex_column(modelIndex.data, result)
|
|
||||||
|
|
||||||
proc isValid*(modelIndex: QModelIndex): bool =
|
|
||||||
## Return true if the index is valid, false otherwise
|
|
||||||
dos_qmodelindex_isValid(modelIndex.data, result)
|
|
||||||
|
|
||||||
proc data*(modelIndex: QModelIndex, role: cint): QVariant =
|
|
||||||
## Return the model data associated to the given role
|
|
||||||
result = newQVariant()
|
|
||||||
dos_qmodelindex_data(modelIndex.data, role, result.data)
|
|
||||||
|
|
||||||
proc parent*(modelIndex: QModelIndex): QModelIndex =
|
|
||||||
## Return the parent index
|
|
||||||
result = newQModelIndex()
|
|
||||||
dos_qmodelindex_parent(modelIndex.data, result.data)
|
|
||||||
|
|
||||||
proc child*(modelIndex: QModelIndex, row: cint, column: cint): QModelIndex =
|
|
||||||
## Return the child index associated to the given row and column
|
|
||||||
result = newQModelIndex()
|
|
||||||
dos_qmodelindex_child(modelIndex.data, row, column, result.data)
|
|
||||||
|
|
||||||
proc sibling*(modelIndex: QModelIndex, row: cint, column: cint): QModelIndex =
|
|
||||||
## Return the sibling index associated to the given row and column
|
|
||||||
result = newQModelIndex()
|
|
||||||
dos_qmodelindex_sibling(modelIndex.data, row, column, result.data)
|
|
||||||
|
|
||||||
# QHashIntByteArray
|
|
||||||
proc dos_qhash_int_qbytearray_create(qHash: var RawQHashIntByteArray) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qhash_int_qbytearray_delete(qHash: RawQHashIntByteArray) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qhash_int_qbytearray_insert(qHash: RawQHashIntByteArray, key: int, value: cstring) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qhash_int_qbytearray_value(qHash: RawQHashIntByteArray, key: int, value: var cstring) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
proc create*(qHash: var QHashIntByteArray) =
|
|
||||||
## Create the QHash
|
|
||||||
debugMsg("QHashIntByteArray", "create")
|
|
||||||
dos_qhash_int_qbytearray_create(qHash.data)
|
|
||||||
qHash.deleted = false
|
|
||||||
|
|
||||||
proc delete*(qHash: QHashIntByteArray) =
|
|
||||||
## Delete the QHash
|
|
||||||
if not qHash.deleted:
|
|
||||||
debugMsg("QHashIntByteArray", "delete")
|
|
||||||
dos_qhash_int_qbytearray_delete(qHash.data)
|
|
||||||
qHash.deleted = true
|
|
||||||
|
|
||||||
proc insert*(qHash: QHashIntByteArray, key: int, value: cstring) =
|
|
||||||
## Insert the value at the given key
|
|
||||||
dos_qhash_int_qbytearray_insert(qHash.data, key, value)
|
|
||||||
|
|
||||||
proc value*(qHash: QHashIntByteArray, key: int): string =
|
|
||||||
## Return the value associated at the given key
|
|
||||||
var rawString: cstring
|
|
||||||
dos_qhash_int_qbytearray_value(qHash.data, key, rawString)
|
|
||||||
result = $rawString
|
|
||||||
dos_chararray_delete(rawString)
|
|
||||||
|
|
||||||
proc newQHashIntQByteArray*(): QHashIntByteArray =
|
|
||||||
## Create a new QHashIntQByteArray
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
# QAbstractListModel
|
|
||||||
type
|
|
||||||
RowCountCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl.}
|
|
||||||
ColumnCountCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl.}
|
|
||||||
DataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, role: cint, result: RawQVariant) {.cdecl.}
|
|
||||||
SetDataCallback = proc(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, value: RawQVariant, role: cint, result: var bool) {.cdecl.}
|
|
||||||
RoleNamesCallback = proc(modelObject: ptr QAbstractListModelObj, result: RawQHashIntByteArray) {.cdecl.}
|
|
||||||
FlagsCallback = proc(modelObject: ptr QAbstractListModelObj, index: RawQModelIndex, result: var cint) {.cdecl.}
|
|
||||||
HeaderDataCallback = proc(modelObject: ptr QAbstractListModelObj, section: cint, orientation: cint, role: cint, result: RawQVariant) {.cdecl.}
|
|
||||||
|
|
||||||
proc dos_qabstractlistmodel_create(model: var RawQAbstractListModel,
|
|
||||||
modelPtr: ptr QAbstractListModelObj,
|
|
||||||
qobjectCallback: QObjectCallBack,
|
|
||||||
rowCountCallback: RowCountCallback,
|
|
||||||
columnCountCallback: ColumnCountCallback,
|
|
||||||
dataCallback: DataCallback,
|
|
||||||
setDataCallback: SetDataCallBack,
|
|
||||||
roleNamesCallback: RoleNamesCallback,
|
|
||||||
flagsCallback: FlagsCallback,
|
|
||||||
headerDataCallback: HeaderDataCallback) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qabstractlistmodel_delete(model: RawQAbstractListModel) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qabstractlistmodel_beginInsertRows(model: RawQAbstractListModel,
|
|
||||||
parentIndex: RawQModelIndex,
|
|
||||||
first: cint,
|
|
||||||
last: cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qabstractlistmodel_endInsertRows(model: RawQAbstractListModel) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qabstractlistmodel_beginRemoveRows(model: RawQAbstractListModel,
|
|
||||||
parentIndex: RawQModelIndex,
|
|
||||||
first: cint,
|
|
||||||
last: cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qabstractlistmodel_endRemoveRows(model: RawQAbstractListModel) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qabstractlistmodel_beginResetModel(model: RawQAbstractListModel) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qabstractlistmodel_endResetModel(model: RawQAbstractListModel) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
proc dos_qabstractlistmodel_dataChanged(model: RawQAbstractListModel,
|
|
||||||
parentLeft: RawQModelIndex,
|
|
||||||
bottomRight: RawQModelIndex,
|
|
||||||
rolesArrayPtr: ptr cint,
|
|
||||||
rolesArrayLength: cint) {.cdecl, dynlib:dOtherSideDll, importc.}
|
|
||||||
|
|
||||||
method rowCount*(model: QAbstractListModel, index: QModelIndex): cint =
|
|
||||||
## Return the model's row count
|
|
||||||
return 0
|
|
||||||
|
|
||||||
proc rowCountCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl, exportc.} =
|
|
||||||
debugMsg("QAbstractListModel", "rowCountCallback")
|
|
||||||
let model = cast[QAbstractListModel](modelObject)
|
|
||||||
let index = newQModelIndex(rawIndex)
|
|
||||||
result = model.rowCount(index)
|
|
||||||
|
|
||||||
method columnCount*(model: QAbstractListModel, index: QModelIndex): cint =
|
|
||||||
## Return the model's column count
|
|
||||||
return 1
|
|
||||||
|
|
||||||
proc columnCountCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl, exportc.} =
|
|
||||||
debugMsg("QAbstractListModel", "columnCountCallback")
|
|
||||||
let model = cast[QAbstractListModel](modelObject)
|
|
||||||
let index = newQModelIndex(rawIndex)
|
|
||||||
result = model.columnCount(index)
|
|
||||||
|
|
||||||
method data*(model: QAbstractListModel, index: QModelIndex, role: cint): QVariant =
|
|
||||||
## Return the data at the given model index and role
|
|
||||||
return nil
|
|
||||||
|
|
||||||
proc dataCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, role: cint, result: RawQVariant) {.cdecl, exportc.} =
|
|
||||||
debugMsg("QAbstractListModel", "dataCallback")
|
|
||||||
let model = cast[QAbstractListModel](modelObject)
|
|
||||||
let index = newQModelIndex(rawIndex)
|
|
||||||
let variant = data(model, index, role)
|
|
||||||
if variant != nil:
|
|
||||||
dos_qvariant_assign(result, variant.data)
|
|
||||||
variant.delete
|
|
||||||
|
|
||||||
method setData*(model: QAbstractListModel, index: QModelIndex, value: QVariant, role: cint): bool =
|
|
||||||
## Sets the data at the given index and role. Return true on success, false otherwise
|
|
||||||
return false
|
|
||||||
|
|
||||||
proc setDataCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, rawQVariant: RawQVariant, role: cint, result: var bool) {.cdecl, exportc.} =
|
|
||||||
debugMsg("QAbstractListModel", "setDataCallback")
|
|
||||||
let model = cast[QAbstractListModel](modelObject)
|
|
||||||
let index = newQModelIndex(rawIndex)
|
|
||||||
let variant = newQVariant(rawQVariant)
|
|
||||||
result = model.setData(index, variant, role)
|
|
||||||
|
|
||||||
method roleNames*(model: QAbstractListModel): Table[cint, cstring] =
|
|
||||||
## Return the model role names
|
|
||||||
result = initTable[cint, cstring]()
|
|
||||||
|
|
||||||
proc roleNamesCallback(modelObject: ptr QAbstractListModelObj, hash: RawQHashIntByteArray) {.cdecl, exportc.} =
|
|
||||||
debugMsg("QAbstractListModel", "roleNamesCallback")
|
|
||||||
let model = cast[QAbstractListModel](modelObject)
|
|
||||||
let table = model.roleNames()
|
|
||||||
for key, val in table.pairs:
|
|
||||||
dos_qhash_int_qbytearray_insert(hash, key, val)
|
|
||||||
|
|
||||||
method flags*(model: QAbstractListModel, index: QModelIndex): QtItemFlag =
|
|
||||||
## Return the item flags and the given index
|
|
||||||
return QtItemFlag.None
|
|
||||||
|
|
||||||
proc flagsCallback(modelObject: ptr QAbstractListModelObj, rawIndex: RawQModelIndex, result: var cint) {.cdecl, exportc.} =
|
|
||||||
debugMsg("QAbstractListModel", "flagsCallback")
|
|
||||||
let model = cast[QAbstractListModel](modelObject)
|
|
||||||
let index = newQModelIndex(rawIndex)
|
|
||||||
result = model.flags(index).cint
|
|
||||||
|
|
||||||
method headerData*(model: QAbstractListModel, section: cint, orientation: QtOrientation, role: cint): QVariant =
|
|
||||||
## Returns the data for the given role and section in the header with the specified orientation
|
|
||||||
return nil
|
|
||||||
|
|
||||||
proc headerDataCallback(modelObject: ptr QAbstractListModelObj, section: cint, orientation: cint, role: cint, result: RawQVariant) {.cdecl, exportc.} =
|
|
||||||
debugMsg("QAbstractListModel", "headerDataCallback")
|
|
||||||
let model = cast[QAbstractListModel](modelObject)
|
|
||||||
let variant = model.headerData(section, orientation.QtOrientation, role)
|
|
||||||
if variant != nil:
|
|
||||||
dos_qvariant_assign(result, variant.data)
|
|
||||||
variant.delete
|
|
||||||
|
|
||||||
proc create*(model: var QAbstractListModel) =
|
|
||||||
## Create a new QAbstractListModel
|
|
||||||
debugMsg("QAbstractListModel", "create")
|
|
||||||
model.slots = initTable[string,cint]()
|
|
||||||
model.signals = initTable[string, cint]()
|
|
||||||
model.properties = initTable[string, cint]()
|
|
||||||
model.deleted = false
|
|
||||||
let modelPtr = addr(model[])
|
|
||||||
dos_qabstractlistmodel_create(model.data.RawQAbstractListModel, modelPtr, qobjectCallback, rowCountCallback, columnCountCallback, dataCallback, setDataCallback, roleNamesCallback, flagsCallback, headerDataCallback)
|
|
||||||
qobjectRegistry[modelPtr] = true
|
|
||||||
|
|
||||||
proc delete*(model: QAbstractListModel) =
|
|
||||||
## Delete the given QAbstractListModel
|
|
||||||
if not model.deleted:
|
|
||||||
debugMsg("QAbstractListModel", "delete")
|
|
||||||
let modelPtr = addr(model[])
|
|
||||||
qobjectRegistry.del modelPtr
|
|
||||||
dos_qabstractlistmodel_delete(model.data.RawQAbstractListModel)
|
|
||||||
model.data = nil.RawQObject
|
|
||||||
model.deleted = true
|
|
||||||
|
|
||||||
proc newQAbstractListModel*(): QAbstractListModel =
|
|
||||||
## Return a new QAbstractListModel
|
|
||||||
newWithCondFinalizer(result, delete)
|
|
||||||
result.create()
|
|
||||||
|
|
||||||
proc beginInsertRows*(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) =
|
|
||||||
## Notify the view that the model is about to inserting the given number of rows
|
|
||||||
dos_qabstractlistmodel_beginInsertRows(model.data.RawQAbstractListModel, parentIndex.data, first.cint, last.cint)
|
|
||||||
|
|
||||||
proc endInsertRows*(model: QAbstractListModel) =
|
|
||||||
## Notify the view that the rows have been inserted
|
|
||||||
dos_qabstractlistmodel_endInsertRows(model.data.RawQAbstractListModel)
|
|
||||||
|
|
||||||
proc beginRemoveRows*(model: QAbstractListModel, parentIndex: QModelIndex, first: int, last: int) =
|
|
||||||
## Notify the view that the model is about to remove the given number of rows
|
|
||||||
dos_qabstractlistmodel_beginRemoveRows(model.data.RawQAbstractListModel, parentIndex.data, first.cint, last.cint)
|
|
||||||
|
|
||||||
proc endRemoveRows*(model: QAbstractListModel) =
|
|
||||||
## Notify the view that the rows have been removed
|
|
||||||
dos_qabstractlistmodel_endRemoveRows(model.data.RawQAbstractListModel)
|
|
||||||
|
|
||||||
proc beginResetModel*(model: QAbstractListModel) =
|
|
||||||
## Notify the view that the model is about to resetting
|
|
||||||
dos_qabstractlistmodel_beginResetModel(model.data.RawQAbstractListModel)
|
|
||||||
|
|
||||||
proc endResetModel*(model: QAbstractListModel) =
|
|
||||||
## Notify the view that model has finished resetting
|
|
||||||
dos_qabstractlistmodel_endResetModel(model.data.RawQAbstractListModel)
|
|
||||||
|
|
||||||
proc dataChanged*(model: QAbstractListModel,
|
|
||||||
topLeft: QModelIndex,
|
|
||||||
bottomRight: QModelIndex,
|
|
||||||
roles: seq[cint]) =
|
|
||||||
## Notify the view that the model data changed
|
|
||||||
var copy = roles
|
|
||||||
dos_qabstractlistmodel_dataChanged(model.data.RawQAbstractListModel, topLeft.data, bottomRight.data, copy[0].addr, copy.len.cint)
|
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
[Package]
|
|
||||||
name = "NimQml"
|
|
||||||
version = "0.3.0"
|
|
||||||
author = "Filippo Cucchetto, Will Szumski"
|
|
||||||
description = "QML bindings for Nimrod"
|
|
||||||
license = "GPLv3"
|
|
||||||
|
|
||||||
[Deps]
|
|
||||||
Requires: "nimrod >= 0.10.2"
|
|
|
@ -1,502 +0,0 @@
|
||||||
## Contains helper macros for NimQml
|
|
||||||
|
|
||||||
import macros
|
|
||||||
import strutils
|
|
||||||
import typetraits
|
|
||||||
import tables
|
|
||||||
|
|
||||||
template debug(body: stmt): stmt =
|
|
||||||
{.push warning[user]: off.}
|
|
||||||
when defined(debug):
|
|
||||||
{.pop.}
|
|
||||||
body
|
|
||||||
else:
|
|
||||||
{.pop.}
|
|
||||||
|
|
||||||
let nimFromQtVariant {.compileTime.} = {
|
|
||||||
"int" : "intVal",
|
|
||||||
"string" : "stringVal",
|
|
||||||
"bool" : "boolVal",
|
|
||||||
"float" : "floatVal",
|
|
||||||
"QObject" : "qobjectVal",
|
|
||||||
}.toTable
|
|
||||||
|
|
||||||
let nim2QtMeta {.compileTime.} = {
|
|
||||||
"bool": "Bool",
|
|
||||||
"int" : "Int",
|
|
||||||
"string" : "QString",
|
|
||||||
"pointer" : "VoidStar",
|
|
||||||
"QObject" : "QObjectStar",
|
|
||||||
"QVariant": "QVariant",
|
|
||||||
"" : "Void", # no return, which is represented by an nnkEmpty node
|
|
||||||
}.toTable
|
|
||||||
|
|
||||||
proc getNodeOf*(tree: NimNode, kind: NimNodeKind): NimNode {.compileTime.} =
|
|
||||||
## recursively looks for a node of kind, ``kind``, in the tree provided as ``tree``
|
|
||||||
## Returns the first node that satisfies this condition
|
|
||||||
for i in 0.. <tree.len:
|
|
||||||
var child = tree[i]
|
|
||||||
if child.kind == kind:
|
|
||||||
return child
|
|
||||||
var candidate = getNodeOf(child, kind)
|
|
||||||
if not candidate.isNil:
|
|
||||||
return candidate
|
|
||||||
|
|
||||||
static:
|
|
||||||
type Context* = ref object of RootObj
|
|
||||||
type NullContext* = ref object of Context
|
|
||||||
|
|
||||||
type NodeModifier*[T] = proc(context: T, a: var NimNode): NimNode
|
|
||||||
|
|
||||||
# had to remove type bound on hook due to recent regression with generics
|
|
||||||
proc hookOnNode*[T](context: T, code: NimNode, hook: NodeModifier,
|
|
||||||
recursive: bool = false): NimNode {.compileTime.} =
|
|
||||||
## Iterates over the tree, ``code``, calling ``hook`` on each ``NimNode``
|
|
||||||
## encountered. If ``recursive`` is true, it will recurse over the tree, otherwise
|
|
||||||
## it will only visit ``code``'s children. ``hook`` should return a replacement for
|
|
||||||
## the node that was passed in via it's return value. `hook` may return nil to remove
|
|
||||||
## the node from the tree.
|
|
||||||
if code.len == 0:
|
|
||||||
return code
|
|
||||||
var newCode = newNimNode(code.kind)
|
|
||||||
for i in 0.. <code.len:
|
|
||||||
var child = code[i].copy()
|
|
||||||
child = hook(context, child)
|
|
||||||
if recursive:
|
|
||||||
child = hookOnNode(context,child,hook,true)
|
|
||||||
if child != nil:
|
|
||||||
newCode.add child
|
|
||||||
return newCode
|
|
||||||
|
|
||||||
proc removeOpenSym*(context: NullContext,
|
|
||||||
a: var NimNode): NimNode {.compileTime.} =
|
|
||||||
## replaces: ``nnkOpenSymChoice`` and ``nnkSym`` nodes with idents
|
|
||||||
## corresponding to the symbols string representation.
|
|
||||||
if a.kind == nnkOpenSymChoice:
|
|
||||||
return ident($a[0].symbol)
|
|
||||||
elif a.kind == nnkSym:
|
|
||||||
return ident($a.symbol)
|
|
||||||
return a
|
|
||||||
|
|
||||||
proc newTemplate*(name = newEmptyNode();
|
|
||||||
params: openArray[NimNode] = [newEmptyNode()];
|
|
||||||
body: NimNode = newStmtList()): NimNode {.compileTime.} =
|
|
||||||
## shortcut for creating a new template
|
|
||||||
##
|
|
||||||
## The ``params`` array must start with the return type of the template,
|
|
||||||
## followed by a list of IdentDefs which specify the params.
|
|
||||||
result = newNimNode(nnkTemplateDef).add(
|
|
||||||
name,
|
|
||||||
newEmptyNode(),
|
|
||||||
newEmptyNode(),
|
|
||||||
newNimNode(nnkFormalParams).add(params), ##params
|
|
||||||
newEmptyNode(), ## pragmas
|
|
||||||
newEmptyNode(),
|
|
||||||
body)
|
|
||||||
|
|
||||||
#FIXME: changed parent, typ from typedesc to expr to workaround Nim issue #1874
|
|
||||||
template declareSuperTemplate*(parent: expr, typ: expr): stmt =
|
|
||||||
template superType*(ofType: typedesc[typ]): typedesc[parent] =
|
|
||||||
parent
|
|
||||||
|
|
||||||
proc getTypeName*(a: NimNode): NimNode {.compileTime.} =
|
|
||||||
## returns the node containing the name of an object in a
|
|
||||||
## given type definition block
|
|
||||||
expectMinLen a, 1
|
|
||||||
expectKind a, nnkTypeDef
|
|
||||||
var testee = a
|
|
||||||
if testee[0].kind == nnkPragmaExpr:
|
|
||||||
testee = testee[0]
|
|
||||||
if testee[0].kind in {nnkIdent}:
|
|
||||||
return testee[0]
|
|
||||||
elif testee[0].kind in {nnkPostfix}:
|
|
||||||
return testee[0][1]
|
|
||||||
|
|
||||||
proc isExported(def: NimNode): bool {.compileTime.} =
|
|
||||||
## given a type definition, ``typedef``, determines whether or
|
|
||||||
## not the type is exported with a '*'
|
|
||||||
assert def.kind in {nnkTypeDef, nnkProcDef, nnkMethodDef, nnkTemplateDef},
|
|
||||||
"unsupported type: " & $def.kind
|
|
||||||
if def[0].kind == nnkPostfix:
|
|
||||||
return true
|
|
||||||
|
|
||||||
proc exportDef(def: NimNode) {.compileTime.} =
|
|
||||||
## Exports exportable definitions. Currently only supports
|
|
||||||
## templates, methods and procedures and types.
|
|
||||||
if def.kind in {nnkProcDef, nnkMethodDef, nnkTemplateDef, nnkTypeDef}:
|
|
||||||
if def.isExported:
|
|
||||||
return
|
|
||||||
def[0] = postfix(def[0], "*")
|
|
||||||
else:
|
|
||||||
error("node: " & $def.kind & " not supported")
|
|
||||||
|
|
||||||
proc unexportDef(def: NimNode) {.compileTime.} =
|
|
||||||
## unexports exportable definitions. Currently only supports
|
|
||||||
## templates, methods and procedures and types.
|
|
||||||
if def.kind in {nnkProcDef, nnkMethodDef, nnkTemplateDef, nnkTypeDef}:
|
|
||||||
if not def.isExported:
|
|
||||||
return
|
|
||||||
def[0] = ident unpackPostfix(def[0])[1]
|
|
||||||
else:
|
|
||||||
error("node: " & $def.kind & " not supported")
|
|
||||||
|
|
||||||
proc genSuperTemplate*(typeDecl: NimNode): NimNode {.compileTime.} =
|
|
||||||
## generates a template, with name: superType, that returns the super type
|
|
||||||
## of the object defined in the type defintion, ``typeDecl``. ``typeDecl``
|
|
||||||
## must contain an object inheriting from a base type.
|
|
||||||
expectKind typeDecl, nnkTypeDef
|
|
||||||
let inheritStmt = typeDecl.getNodeOf(nnkOfInherit)
|
|
||||||
let typeName = getTypeName(typeDecl)
|
|
||||||
if inheritStmt == nil: error("you must declare a super type for " & $typeName)
|
|
||||||
# ident of superType (have to deal with generics)
|
|
||||||
let superType = if inheritStmt[0].kind == nnkIdent: inheritStmt[0]
|
|
||||||
else: inheritStmt[0].getNodeOf(nnkIdent)
|
|
||||||
let superTemplate = getAst declareSuperTemplate(superType, typeName)
|
|
||||||
result = superTemplate[0]
|
|
||||||
if typeDecl.isExported():
|
|
||||||
result.exportDef()
|
|
||||||
else:
|
|
||||||
result.unexportDef()
|
|
||||||
|
|
||||||
proc getSuperType*(typeDecl: NimNode): NimNode {.compileTime.} =
|
|
||||||
## returns ast containing superType info, may not be an ident if generic
|
|
||||||
let inheritStmt = typeDecl.getNodeOf(nnkOfInherit)
|
|
||||||
if inheritStmt.isNil: return newEmptyNode()
|
|
||||||
return inheritStmt[0]
|
|
||||||
|
|
||||||
proc getPragmaName*(child: NimNode): NimNode {.compileTime.} =
|
|
||||||
## name of child in a nnkPragma section
|
|
||||||
if child.kind == nnkIdent:
|
|
||||||
return child
|
|
||||||
# assumes first ident is name of pragma
|
|
||||||
let ident = child.getNodeOf(nnkIdent)
|
|
||||||
result = ident
|
|
||||||
|
|
||||||
proc removePragma*(pragma: NimNode, toRemove: string): NimNode {.compileTime.} =
|
|
||||||
## removes a pragma from pragma definition, `pragma`, with name `toRemove`
|
|
||||||
expectKind pragma, nnkPragma
|
|
||||||
result = newNimNode(nnkPragma)
|
|
||||||
for i in 0.. <pragma.len:
|
|
||||||
let child = pragma[i]
|
|
||||||
if $child.getPragmaName == toRemove:
|
|
||||||
continue
|
|
||||||
result.add child
|
|
||||||
if result.len == 0:
|
|
||||||
return newEmptyNode()
|
|
||||||
|
|
||||||
proc hasPragma*(node: NimNode, pragmaName: string): bool {.compileTime.} =
|
|
||||||
## Returns ``true`` iff the method, or proc definition: ``node``, has a pragma
|
|
||||||
## ``pragmaName``
|
|
||||||
doAssert node.kind in {nnkMethodDef, nnkProcDef}
|
|
||||||
result = false
|
|
||||||
let pragma = node.pragma
|
|
||||||
if pragma.kind == nnkEmpty:
|
|
||||||
# denotes no pragma set
|
|
||||||
return false
|
|
||||||
for child in pragma.children():
|
|
||||||
if $child.getPragmaName() == pragmaName:
|
|
||||||
return true
|
|
||||||
|
|
||||||
proc getArgType*(arg: NimNode): NimNode {.compileTime.} =
|
|
||||||
## returns the ``NimNode`` representing a parameters type
|
|
||||||
if arg[1].kind == nnkIdent:
|
|
||||||
arg[1]
|
|
||||||
else:
|
|
||||||
arg[1].getNodeOf(nnkIdent)
|
|
||||||
|
|
||||||
proc getArgName*(arg: NimNode): NimNode {.compileTime.} =
|
|
||||||
## returns the ``NimNode`` representing a parameters name
|
|
||||||
if arg[0].kind == nnkIdent:
|
|
||||||
arg[0]
|
|
||||||
else:
|
|
||||||
arg[0].getNodeOf(nnkIdent)
|
|
||||||
|
|
||||||
proc addSignalBody(signal: NimNode): NimNode {.compileTime.} =
|
|
||||||
# e.g: produces: emit(MyQObject, "nameChanged")
|
|
||||||
assert signal.kind in {nnkMethodDef, nnkProcDef}
|
|
||||||
result = newStmtList()
|
|
||||||
# if exported, will use postfix
|
|
||||||
let name = if signal.name.kind == nnkIdent: signal.name else: signal.name[1]
|
|
||||||
let params = signal.params
|
|
||||||
# type signal defined on is the 1st arg
|
|
||||||
let self = getArgName(params[1])
|
|
||||||
var args = newSeq[NimNode]()
|
|
||||||
args.add(self)
|
|
||||||
args.add newLit($name)
|
|
||||||
if params.len > 2: # more args than just type
|
|
||||||
for i in 2.. <params.len:
|
|
||||||
args.add getArgName params[i]
|
|
||||||
result.add newCall("emit", args)
|
|
||||||
|
|
||||||
#FIXME: changed typ from typedesc to expr to workaround Nim issue #1874
|
|
||||||
# This is declared dirty so that identifers are not bound to symbols.
|
|
||||||
# The alternative is to use `removeOpenSym` as we did for `prototypeCreate`.
|
|
||||||
# We should decide which method is preferable.
|
|
||||||
template prototypeOnSlotCalled(typ: expr): stmt {.dirty.} =
|
|
||||||
method onSlotCalled(myQObject: typ, slotName: string, args: openarray[QVariant]) =
|
|
||||||
var super = (typ.superType())(myQObject)
|
|
||||||
procCall onSlotCalled(super, slotName, args)
|
|
||||||
|
|
||||||
#FIXME: changed parent, typ from typedesc to expr to workaround Nim issue #1874
|
|
||||||
template prototypeCreate(typ: expr): stmt {.dirty.}=
|
|
||||||
proc create*(myQObject: var typ) =
|
|
||||||
var super = (typ.superType())(myQObject)
|
|
||||||
procCall create(super)
|
|
||||||
|
|
||||||
proc doRemoveOpenSym(a: var NimNode): NimNode {.compileTime.} =
|
|
||||||
hookOnNode(NullContext(),a, removeOpenSym, true)
|
|
||||||
|
|
||||||
proc templateBody*(a: NimNode): NimNode {.compileTime.} =
|
|
||||||
expectKind a, nnkTemplateDef
|
|
||||||
result = a[6]
|
|
||||||
|
|
||||||
proc genArgTypeArray(params: NimNode): NimNode {.compileTime.} =
|
|
||||||
expectKind params, nnkFormalParams
|
|
||||||
result = newNimNode(nnkBracket)
|
|
||||||
for i in 0 .. <params.len:
|
|
||||||
if i == 1:
|
|
||||||
# skip "self" param eg: myQObject: MyQObject
|
|
||||||
continue
|
|
||||||
let pType = if i != 0: getArgType params[i] else: params[i]
|
|
||||||
let pTypeString = if pType.kind == nnkEmpty: "" else: $pType
|
|
||||||
# function that maps Qvariant type to nim type
|
|
||||||
let qtMeta = nim2QtMeta[pTypeString]
|
|
||||||
if qtMeta == nil: error(pTypeString & " not supported yet")
|
|
||||||
let metaDot = newDotExpr(ident "QMetaType", ident qtMeta)
|
|
||||||
result.add metaDot
|
|
||||||
|
|
||||||
proc getIdentDefName*(a: NimNode): NimNode {.compileTime.} =
|
|
||||||
## returns object field name from ident def
|
|
||||||
expectKind a, nnkIdentDefs
|
|
||||||
if a[0].kind == nnkIdent:
|
|
||||||
return a[0]
|
|
||||||
elif a[0].kind == nnkPostFix:
|
|
||||||
return a[0][1]
|
|
||||||
|
|
||||||
proc tryHandleSigSlot(def: NimNode, signals: var seq[NimNode], slots: var seq[NimNode],
|
|
||||||
generatedCode: var NimNode): bool {.compileTime.} =
|
|
||||||
## Checks a method/proc definition for signals and slots. On finding a method/proc with
|
|
||||||
## a {.signal.} or {.slot.} pragma, it will strip the pragma, add the definition to the
|
|
||||||
## appropriate seq, append the stripped version to the generated code block and return true
|
|
||||||
## indicating the definition was a signal or a slot. If the method/proc is not a slot
|
|
||||||
## or a slot it will return false.
|
|
||||||
expectKind generatedCode, nnkStmtList
|
|
||||||
assert (not signals.isNil)
|
|
||||||
assert (not slots.isNil)
|
|
||||||
assert def.kind in {nnkMethodDef, nnkProcDef}
|
|
||||||
result = false
|
|
||||||
if def.hasPragma("slot"):
|
|
||||||
let pragma = def.pragma()
|
|
||||||
def.pragma = pragma.removePragma("slot")
|
|
||||||
slots.add def # we need to gensome code later
|
|
||||||
generatedCode.add def
|
|
||||||
result = true
|
|
||||||
elif def.hasPragma("signal"):
|
|
||||||
let pragma = def.pragma()
|
|
||||||
def.pragma = pragma.removePragma("signal")
|
|
||||||
def.body = addSignalBody(def)
|
|
||||||
generatedCode.add def
|
|
||||||
signals.add def
|
|
||||||
result = true
|
|
||||||
|
|
||||||
proc genCreateDecl(typ: NimNode): NimNode {.compileTime.} =
|
|
||||||
## generates forward declaration for ``create`` procedure
|
|
||||||
expectKind typ, nnkTypeDef
|
|
||||||
let typeName = typ.getTypeName()
|
|
||||||
result = (getAst prototypeCreate(typeName))[0]
|
|
||||||
result.body = newEmptyNode()
|
|
||||||
if typ.isExported:
|
|
||||||
result.exportDef()
|
|
||||||
else:
|
|
||||||
result.unexportDef()
|
|
||||||
|
|
||||||
proc genCreate(typ: NimNode, signals: seq[NimNode], slots: seq[NimNode],
|
|
||||||
properties: seq[NimNode]): NimNode {.compileTime.} =
|
|
||||||
expectKind typ, nnkTypeDef
|
|
||||||
let typeName = typ.getTypeName()
|
|
||||||
result = (getAst prototypeCreate(typeName))[0]
|
|
||||||
# the template creates loads of openSyms - replace these with idents
|
|
||||||
result = doRemoveOpenSym(result)
|
|
||||||
if typ.isExported:
|
|
||||||
result.exportDef()
|
|
||||||
else:
|
|
||||||
result.unexportDef()
|
|
||||||
var createBody = result.body
|
|
||||||
for slot in slots:
|
|
||||||
let params = slot.params
|
|
||||||
let regSlotDot = newDotExpr(ident "myQObject", ident "registerSlot")
|
|
||||||
let name = ($slot.name).replace("*","")
|
|
||||||
let argTypesArray = genArgTypeArray(params)
|
|
||||||
let call = newCall(regSlotDot, newLit name, argTypesArray)
|
|
||||||
createBody.add call
|
|
||||||
for signal in signals:
|
|
||||||
let params = signal.params
|
|
||||||
let regSigDot = newDotExpr(ident "myQObject", ident "registerSignal")
|
|
||||||
let name = ($signal.name).replace("*","")
|
|
||||||
let argTypesArray = genArgTypeArray(params)
|
|
||||||
let call = newCall(regSigDot, newLit name, argTypesArray)
|
|
||||||
createBody.add call
|
|
||||||
for property in properties:
|
|
||||||
let bracket = property[0]
|
|
||||||
expectKind bracket, nnkBracketExpr
|
|
||||||
#Command
|
|
||||||
# BracketExpr
|
|
||||||
# Ident !"QtProperty"
|
|
||||||
# Ident !"string"
|
|
||||||
# Ident !"name"
|
|
||||||
# StmtList
|
|
||||||
let nimPropType = bracket[1]
|
|
||||||
let qtPropMeta = nim2QtMeta[$nimPropType]
|
|
||||||
if qtPropMeta == nil: error($nimPropType & " not supported")
|
|
||||||
let metaDot = newDotExpr(ident "QMetaType", ident qtPropMeta)
|
|
||||||
let propertyName = property[1]
|
|
||||||
var read, write, notify: NimNode
|
|
||||||
let stmtList = property[2]
|
|
||||||
# fields
|
|
||||||
# StmtList
|
|
||||||
# Asgn
|
|
||||||
# Ident !"read"
|
|
||||||
# Ident !"getName
|
|
||||||
for asgn in stmtList.children:
|
|
||||||
let name = asgn[0]
|
|
||||||
case $name
|
|
||||||
of "read":
|
|
||||||
read = asgn[1]
|
|
||||||
of "write":
|
|
||||||
write = asgn[1]
|
|
||||||
of "notify":
|
|
||||||
notify = asgn[1]
|
|
||||||
else:
|
|
||||||
error("unknown property field: " & $name)
|
|
||||||
let regPropDot = newDotExpr(ident "myQObject", ident "registerProperty")
|
|
||||||
let readArg = if read == nil: newNilLit() else: newLit($read)
|
|
||||||
let writeArg = if write == nil: newNilLit() else: newLit($write)
|
|
||||||
let notifyArg = if notify == nil: newNilLit() else: newLit($notify)
|
|
||||||
let call = newCall(regPropDot, newLit($propertyName), metaDot, readArg, writeArg, notifyArg)
|
|
||||||
createBody.add call
|
|
||||||
|
|
||||||
proc genOnSlotCalled(typ: NimNode, slots: seq[NimNode]): NimNode {.compileTime.} =
|
|
||||||
expectKind typ, nnkTypeDef
|
|
||||||
let typeName = typ.getTypeName()
|
|
||||||
result = (getAst prototypeOnSlotCalled(typeName))[0]
|
|
||||||
var caseStmt = newNimNode(nnkCaseStmt)
|
|
||||||
caseStmt.add ident("slotName")
|
|
||||||
for slot in slots:
|
|
||||||
var ofBranch = newNimNode(nnkOfBranch)
|
|
||||||
# for exported procedures - strip * marker
|
|
||||||
let slotName = ($slot.name).replace("*","")
|
|
||||||
ofBranch.add newLit slotName
|
|
||||||
let params = slot.params
|
|
||||||
let hasReturn = not (params[0].kind == nnkEmpty)
|
|
||||||
var branchStmts = newStmtList()
|
|
||||||
var args = newSeq[NimNode]()
|
|
||||||
# first params always the object
|
|
||||||
args.add ident "myQObject"
|
|
||||||
for i in 2.. <params.len:
|
|
||||||
let pType = getArgType params[i]
|
|
||||||
let argAccess = newNimNode(nnkBracketExpr)
|
|
||||||
.add (ident "args")
|
|
||||||
.add newIntLitNode(i-1)
|
|
||||||
if $pType == "QVariant":
|
|
||||||
args.add argAccess
|
|
||||||
else:
|
|
||||||
# function that maps QVariant type to nim type
|
|
||||||
let mapper = nimFromQtVariant[$pType]
|
|
||||||
let dot = newDotExpr(argAccess, ident mapper)
|
|
||||||
args.add dot
|
|
||||||
var call = newCall(ident slotName, args)
|
|
||||||
if hasReturn:
|
|
||||||
let retType = params[0]
|
|
||||||
let argAccess = newNimNode(nnkBracketExpr)
|
|
||||||
.add (ident "args")
|
|
||||||
.add newIntLitNode(0)
|
|
||||||
if $retType == "QVariant":
|
|
||||||
# eg: args[0].assign(getName(myQObject))
|
|
||||||
let dot = newDotExpr(argAccess, ident "assign")
|
|
||||||
call = newCall(dot, call)
|
|
||||||
else:
|
|
||||||
# eg: args[0].strVal = getName(myQObject)
|
|
||||||
let mapper = nimFromQtVariant[$retType]
|
|
||||||
let dot = newDotExpr(argAccess, ident mapper)
|
|
||||||
call = newAssignment(dot, call)
|
|
||||||
branchStmts.add call
|
|
||||||
ofBranch.add branchStmts
|
|
||||||
caseStmt.add ofBranch
|
|
||||||
# add else: discard
|
|
||||||
caseStmt.add newNimNode(nnkElse)
|
|
||||||
.add newStmtList().add newNimNode(nnkDiscardStmt).add newNimNode(nnkEmpty)
|
|
||||||
result.body.add caseStmt
|
|
||||||
|
|
||||||
macro QtObject*(qtDecl: stmt): stmt {.immediate.} =
|
|
||||||
## Generates boiler plate code for registering signals, slots
|
|
||||||
## and properties.
|
|
||||||
##
|
|
||||||
## Currently generates:
|
|
||||||
## - create: a method to register signal, slots and properties
|
|
||||||
## - superType: a template that returns the super type of the
|
|
||||||
## object defined within the macro body
|
|
||||||
## - onSlotCalled: a method to dispatch an on slot call to the
|
|
||||||
## appropiate method.
|
|
||||||
##
|
|
||||||
## Current limitations:
|
|
||||||
## - only one type can be defined within the body of code sent to the
|
|
||||||
## the macro. It is assumed, but not checked, that somewhere in the
|
|
||||||
## inheritance hierarchy this object derives from ``QObject``.
|
|
||||||
## - generics are not currently supported
|
|
||||||
expectKind(qtDecl, nnkStmtList)
|
|
||||||
#echo treeRepr qtDecl
|
|
||||||
result = newStmtList()
|
|
||||||
var slots = newSeq[NimNode]()
|
|
||||||
var properties = newSeq[NimNode]()
|
|
||||||
var signals = newSeq[NimNode]()
|
|
||||||
# assume only one type per section for now
|
|
||||||
var typ: NimNode
|
|
||||||
for it in qtDecl.children():
|
|
||||||
if it.kind == nnkTypeSection:
|
|
||||||
let typeDecl = it.findChild(it.kind == nnkTypeDef)
|
|
||||||
let superType = typeDecl.getSuperType()
|
|
||||||
if superType.kind == nnkEmpty:
|
|
||||||
# allow simple types and type aliases
|
|
||||||
result.add it
|
|
||||||
else:
|
|
||||||
# may come in useful if we want to check objects inherit from QObject
|
|
||||||
#let superName = if superType.kind == nnkIdent: superType
|
|
||||||
# else: superType.getNodeOf(nnkIdent)
|
|
||||||
if typ != nil:
|
|
||||||
error("you may not define more than one type " &
|
|
||||||
"within the code block passed to this macro")
|
|
||||||
else: # without this else, it fails to compile
|
|
||||||
typ = typeDecl
|
|
||||||
result.add it
|
|
||||||
result.add genSuperTemplate(typeDecl)
|
|
||||||
result.add genCreateDecl(typeDecl)
|
|
||||||
elif it.kind == nnkMethodDef:
|
|
||||||
if tryHandleSigSlot(it, signals, slots, result): continue
|
|
||||||
result.add it
|
|
||||||
elif it.kind == nnkProcDef:
|
|
||||||
if tryHandleSigSlot(it, signals, slots, result): continue
|
|
||||||
result.add it
|
|
||||||
elif it.kind == nnkCommand:
|
|
||||||
let bracket = it[0]
|
|
||||||
if bracket.kind != nnkBracketExpr:
|
|
||||||
error("do not know how to handle: \n" & repr(it))
|
|
||||||
# BracketExpr
|
|
||||||
# Ident !"QtProperty"
|
|
||||||
# Ident !"string"
|
|
||||||
let cmdIdent = bracket[0]
|
|
||||||
if cmdIdent == nil or cmdIdent.kind != nnkIdent or
|
|
||||||
($cmdIdent).toLower() != "qtproperty":
|
|
||||||
error("do not know how to handle: \n" & repr(it))
|
|
||||||
properties.add it
|
|
||||||
else:
|
|
||||||
# everything else should pass through unchanged
|
|
||||||
result.add it
|
|
||||||
if typ == nil:
|
|
||||||
error("you must declare an object that inherits from QObject")
|
|
||||||
|
|
||||||
result.add genOnSlotCalled(typ, slots)
|
|
||||||
|
|
||||||
result.add genCreate(typ, signals, slots, properties)
|
|
||||||
|
|
||||||
debug:
|
|
||||||
echo repr result
|
|
|
@ -1,68 +0,0 @@
|
||||||
import tables
|
|
||||||
|
|
||||||
type
|
|
||||||
RawQVariant = distinct pointer
|
|
||||||
QVariant* = ref object of RootObj ## A QVariant
|
|
||||||
data: RawQVariant
|
|
||||||
deleted: bool
|
|
||||||
|
|
||||||
RawQQmlApplicationEngine = distinct pointer
|
|
||||||
QQmlApplicationEngine* = ref object of RootObj ## A QQmlApplicationEngine
|
|
||||||
data: RawQQmlApplicationEngine
|
|
||||||
deleted: bool
|
|
||||||
|
|
||||||
QApplication* = ref object of RootObj ## A QApplication
|
|
||||||
deleted: bool
|
|
||||||
|
|
||||||
QGuiApplication* = ref object of RootObj ## A QGuiApplication
|
|
||||||
deleted: bool
|
|
||||||
|
|
||||||
RawQObject = distinct pointer
|
|
||||||
QObjectObj = object of RootObj
|
|
||||||
data: RawQObject
|
|
||||||
slots: Table[string, cint]
|
|
||||||
signals: Table[string, cint]
|
|
||||||
properties: Table[string, cint]
|
|
||||||
deleted: bool
|
|
||||||
QObject* = ref QObjectObj
|
|
||||||
|
|
||||||
RawBaseQObjectObj = distinct pointer
|
|
||||||
BaseQObjectObj = object of QObjectObj
|
|
||||||
BaseQObject* = ref BaseQObjectObj ## A QObject
|
|
||||||
|
|
||||||
RawQAbstractListModel = distinct pointer
|
|
||||||
QAbstractListModelObj = object of QObjectObj
|
|
||||||
QAbstractListModel* = ref QAbstractListModelObj ## A QAbstractListModel
|
|
||||||
|
|
||||||
RawQQuickView = distinct pointer
|
|
||||||
QQuickView = ref object of RootObj ## A QQuickView
|
|
||||||
data: RawQQuickView
|
|
||||||
deleted: bool
|
|
||||||
|
|
||||||
QQmlContext* = distinct pointer ## A QQmlContext
|
|
||||||
|
|
||||||
RawQModelIndex = distinct pointer
|
|
||||||
QModelIndex* = ref object of RootObj ## A QModelIndex
|
|
||||||
data: RawQModelIndex
|
|
||||||
deleted: bool
|
|
||||||
|
|
||||||
RawQHashIntByteArray = distinct pointer
|
|
||||||
QHashIntByteArrayObj = object of RootObj
|
|
||||||
data: RawQHashIntByteArray
|
|
||||||
deleted: bool
|
|
||||||
QHashIntByteArray* = ref QHashIntByteArrayObj ## A QHash<int,QByteArray>
|
|
||||||
|
|
||||||
QtItemFlag* {.pure.} = enum
|
|
||||||
None = 0.cint,
|
|
||||||
IsSelectable = 1.cint,
|
|
||||||
IsEditable = 2.cint,
|
|
||||||
IsDragEnabled = 4.cint,
|
|
||||||
IsDropEnabled = 8.cint,
|
|
||||||
IsUserCheckable = 16.cint,
|
|
||||||
IsEnabled = 32.cint,
|
|
||||||
IsTristate = 64.cint,
|
|
||||||
NeverHasChildren = 128.cint
|
|
||||||
|
|
||||||
QtOrientation {.pure.} = enum
|
|
||||||
Horizontal = 1.cint,
|
|
||||||
Vertical = 2.cint
|
|
|
@ -1,22 +0,0 @@
|
||||||
include(CMakeParseArguments)
|
|
||||||
|
|
||||||
find_program(NIM_EXECUTABLE nim PATHS ENV PATH)
|
|
||||||
mark_as_advanced(NIM_EXECUTABLE)
|
|
||||||
|
|
||||||
# Determine the nimrod version
|
|
||||||
if(NIM_EXECUTABLE)
|
|
||||||
execute_process(COMMAND ${NIM_EXECUTABLE} "--version"
|
|
||||||
OUTPUT_VARIABLE NIM_VERSION
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
STRING(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" NIM_VERSION ${NIM_VERSION})
|
|
||||||
endif(NIM_EXECUTABLE)
|
|
||||||
|
|
||||||
# Handle the QUIETLY and REQUIRED arguments, which may be given to the find call.
|
|
||||||
# set NIM_FOUND to TRUE if Nimrod has been found
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(Nim
|
|
||||||
REQUIRED_VARS NIM_EXECUTABLE
|
|
||||||
VERSION_VAR NIM_VERSION)
|
|
||||||
|
|
||||||
set(NIM_USE_FILE "${CMAKE_CURRENT_LIST_DIR}/UseNim.cmake")
|
|
|
@ -1,49 +0,0 @@
|
||||||
include(CMakeParseArguments)
|
|
||||||
|
|
||||||
function(add_nim_executable )
|
|
||||||
set(options )
|
|
||||||
set(oneValueArgs TARGET)
|
|
||||||
set(multiValueArgs SOURCES PATHS)
|
|
||||||
cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
||||||
|
|
||||||
# collect set of input source files
|
|
||||||
set(in_files "")
|
|
||||||
foreach(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS})
|
|
||||||
list(APPEND in_files "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
|
|
||||||
endforeach(src ${ARGS_SOURCES} ${ARGS_UNPARSED_ARGUMENTS})
|
|
||||||
|
|
||||||
set(in_paths "")
|
|
||||||
foreach(path ${ARGS_PATHS} ${ARGS_UNPARSED_ARGUMENTS})
|
|
||||||
list(APPEND in_paths "--path:${CMAKE_CURRENT_SOURCE_DIR}/${path}")
|
|
||||||
endforeach(path ${ARGS_PATHS} ${ARGS_UNPARSED_ARGUMENTS})
|
|
||||||
|
|
||||||
# set the target binary and nim cache directory
|
|
||||||
set(nim_target "${CMAKE_CURRENT_BINARY_DIR}/${ARGS_TARGET}")
|
|
||||||
set(nim_cache_dir "${CMAKE_CURRENT_BINARY_DIR}/nimcache")
|
|
||||||
|
|
||||||
# compiler
|
|
||||||
set(nim_compiler "c")
|
|
||||||
|
|
||||||
# compiler options
|
|
||||||
set(nim_compiler_options "")
|
|
||||||
if (WIN32)
|
|
||||||
if (MSVC OR MSVC_IDE)
|
|
||||||
set(nim_compiler_options "--cc:vcc")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# thread options
|
|
||||||
set(nim_thread_options "")
|
|
||||||
if(UNIX)
|
|
||||||
set(nim_thread_options "--passL:-lpthread")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# add target to trigger the nimrod compiler
|
|
||||||
add_custom_target(
|
|
||||||
${ARGS_TARGET} ALL
|
|
||||||
COMMAND
|
|
||||||
${NIM_EXECUTABLE} ${nim_compiler} ${nim_compiler_options} ${nim_thread_options} ${in_paths} "--nimcache:" ${nim_cache_dir} "--out:" ${nim_target} ${in_files}
|
|
||||||
DEPENDS
|
|
||||||
${in_files}
|
|
||||||
)
|
|
||||||
endfunction(add_nim_executable)
|
|
52
README.md
52
README.md
|
@ -1,57 +1,33 @@
|
||||||
# DOtherSide
|
# DOtherSide
|
||||||
|
[![License](https://img.shields.io/badge/license-LGPL-green.svg)](https://github.com/filcuc/DOtherSide/blob/master/LICENSE)
|
||||||
[![Build Status](https://travis-ci.org/filcuc/DOtherSide.svg?branch=master)](https://travis-ci.org/filcuc/DOtherSide)
|
[![Build Status](https://travis-ci.org/filcuc/DOtherSide.svg?branch=master)](https://travis-ci.org/filcuc/DOtherSide)
|
||||||
|
|
||||||
## Description
|
C language library for creating bindings for the Qt QML language.
|
||||||
|
|
||||||
Qml bindings for both D and Nim programming languages
|
Currently the DOtherSide library is used by the following bindings:
|
||||||
|
* [nimqml](https://github.com/filcuc/nimqml), QML bindings for the Nim programming language
|
||||||
|
* [dqml](https://github.com/filcuc/dqml), QML bindings for the D programming language
|
||||||
|
|
||||||
|
## Supported platforms
|
||||||
|
Currently we support the following platforms/compilers:
|
||||||
|
- Linux both 32/64bit with gcc
|
||||||
|
- Windows 32/64bit with Visual Studio 2013 Community Edition
|
||||||
|
|
||||||
## Change log
|
## Change log
|
||||||
The project change log can be read [here](./CHANGELOG.md).
|
The project change log can be read [here](./CHANGELOG.md).
|
||||||
|
|
||||||
## Documentation
|
## Build requirements
|
||||||
The documentation for the Nim programming language can be
|
|
||||||
read [here](http://filcuc.github.io/DOtherSide/ "").
|
|
||||||
|
|
||||||
For the D programming language is an on going project
|
|
||||||
and pull request are accepted.
|
|
||||||
|
|
||||||
## Supported Platforms and Requirements
|
|
||||||
Currently we support the following platforms/compilers:
|
|
||||||
- Linux both 32/64bit with gcc
|
|
||||||
- Windows 32/64bit with Visual Studio 2013 Community Edition
|
|
||||||
|
|
||||||
You need the following software:
|
You need the following software:
|
||||||
* Qt 5.3 or higher
|
* Qt 5.3 or higher
|
||||||
* dmd 2.065 or higher
|
|
||||||
* Linux: gcc 4.8 or later with c++11 support or higher
|
* Linux: gcc 4.8 or later with c++11 support or higher
|
||||||
* Windows: Visual Studio 2013 Community Edition (Windows) or higher
|
* Windows: Visual Studio 2013 Community Edition (Windows) or higher
|
||||||
* Windows: MingGW 4.9.2 or higher
|
* Windows: MingGW 4.9.2 or higher
|
||||||
* nim 0.10.3 or higher
|
|
||||||
|
|
||||||
## Build Instructions
|
## Build instructions:
|
||||||
1. Open a shell terminal inside the cloned repo
|
1. Open a shell terminal inside the cloned repo
|
||||||
2. mkdir build && cd build
|
2. mkdir build && cd build
|
||||||
3. cmake ..
|
3. cmake ..
|
||||||
4. make
|
4. make
|
||||||
|
|
||||||
## Install Instructions
|
## Install Instructions
|
||||||
For the DOtherSide C++ bridge:
|
Copy the libDOtherSide.so from the build dir to your system lib i.e /usr/lib
|
||||||
|
|
||||||
1. Copy the libDOtherSide.so from the build dir to your system lib i.e /usr/lib
|
|
||||||
|
|
||||||
For NimQml use the Nimble package manager:
|
|
||||||
|
|
||||||
1. Open a shell and navigate to the NimQml subdirectory
|
|
||||||
2. Type: nimble install
|
|
||||||
3. Now you can use it in your .nim files
|
|
||||||
|
|
||||||
## Supported features:
|
|
||||||
* Creation of custom QObject and inject in a qml QtQuick view (both Nim and D)
|
|
||||||
* Slot and Signal creation for the following types int, bool, string (both Nim and D)
|
|
||||||
* Creation of properties for databinding (both Nim and D)
|
|
||||||
* Subclassing of QAbstractListModels
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue