Mercurial > projects > qtd
changeset 335:1e9092e20a67
merge signals branch into default
author | eldar1@eldar1-laptop |
---|---|
date | Sun, 07 Feb 2010 16:04:36 +0000 |
parents | 70f64e5b5942 (current diff) ed7018b63aa7 (diff) |
children | b0a7819153bb |
files | cpp/qt_gui/UrlHandler_shell.cpp cpp/qt_gui/UrlHandler_shell.h qt/gui/UrlHandler.d |
diffstat | 77 files changed, 6401 insertions(+), 2000 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Sat Dec 19 18:43:32 2009 +0300 +++ b/CMakeLists.txt Sun Feb 07 16:04:36 2010 +0000 @@ -123,14 +123,14 @@ make_native_path(cd_path) add_custom_command(TARGET main POST_BUILD COMMAND ${CMAKE_COMMAND} ARGS -E make_directory ${CMAKE_BINARY_DIR}/build - COMMAND cd ARGS ${cd_path} && ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} -DSECOND_RUN=1 ${CMAKE_SOURCE_DIR} && ${make_util} + COMMAND cd ARGS ${cd_path} && ${CMAKE_COMMAND} -G${CMAKE_GENERATOR} -DSECOND_RUN=1 ${CMAKE_SOURCE_DIR} && ${make_util} COMMENT "" ) ## "Make install" command. set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CMAKE_BINARY_DIR}/build) add_custom_target(install - COMMAND cd ARGS ${cd_path} && ${make_util} install + COMMAND cd ${CMAKE_BINARY_DIR}/build && ${make_util} install COMMENT "" ) add_dependencies(install preinstall) @@ -319,10 +319,10 @@ else(NOT is_founded) set(qtd_libs ${${package}_lib_param} ${qtd_libs}) endif(NOT is_founded) - endforeach(package ${PACKAGES_tmp}) + endforeach(package ${PACKAGES_tmp}) add_d_program(${name} ${SOURCES_tmp} NO_DEPS_SOURCES ${res_sources} ${uic_sources} DEPENDS ${res_sources} INCLUDES ${QTD_IMPORT_PATH} ${CMAKE_CURRENT_BINARY_DIR} - LIB_PATHS ${QTD_LIBRARIES_PATH} ${CMAKE_SOURCE_DIR}/lib LIBS ${qtd_libs}) + LIB_PATHS ${QTD_LIBRARIES_PATH} ${CMAKE_SOURCE_DIR}/lib ${QT_LIBRARY_DIR} LIBS ${qtd_libs}) ## TODO: Uncomment. #if(STRIP AND ${CMAKE_BUILD_TYPE} EQUAL "Release" AND CMAKE_HOST_UNIX) ## # add_custom_command(TARGET example_${name} POST_BUILD COMMAND "${STRIP}" ARGS "${output}") @@ -581,4 +581,4 @@ set(SECOND_RUN 0 CACHE INTERNAL "") -endif(NOT SECOND_RUN) \ No newline at end of file +endif(NOT SECOND_RUN)
--- a/build/core.makefile Sat Dec 19 18:43:32 2009 +0300 +++ b/build/core.makefile Sun Feb 07 16:04:36 2010 +0000 @@ -79,4 +79,5 @@ QBuffer \ QMetaType \ QLibraryInfo \ + QFileSystemWatcher \ QXmlStreamEntityResolver \ No newline at end of file
--- a/build/core.txt Sat Dec 19 18:43:32 2009 +0300 +++ b/build/core.txt Sun Feb 07 16:04:36 2010 +0000 @@ -17,7 +17,19 @@ qtd/Traits core/QString core/QMetaType - core/QMetaObject) + core/QMetaObject + + core/QTypeInfo + core/QList + qtd/Atomic + qtd/MetaMarshall + qtd/MOC + qtd/Meta + qtd/util/Tuple + qtd/ctfe/Integer + qtd/ctfe/String + qtd/ctfe/Format + ) set (d_version_files QtdObject Signal qtd/Str @@ -68,5 +80,6 @@ QBuffer QLibraryInfo QXmlStreamEntityResolver + QFileSystemWatcher )
--- a/build/gui.txt Sat Dec 19 18:43:32 2009 +0300 +++ b/build/gui.txt Sun Feb 07 16:04:36 2010 +0000 @@ -1,10 +1,4 @@ set(required Core) -qt4_generate_moc(cpp/qt_gui/UrlHandler_shell.h - ${CMAKE_BINARY_DIR}/cpp/qt_gui/UrlHandler_shell_moc.cpp - ) -set (cpp_files qt_gui/UrlHandler_shell ) -set (cpp_generated_files qt_gui/UrlHandler_shell_moc) -#set (d_files gui/UrlHandler) set(classes QPushButton QFileIconProvider @@ -352,4 +346,6 @@ QSizeGrip QSortFilterProxyModel QSound + + QGraphicsObject )
--- a/changelog.txt Sat Dec 19 18:43:32 2009 +0300 +++ b/changelog.txt Sun Feb 07 16:04:36 2010 +0000 @@ -15,4 +15,5 @@ * D2 port * new CMake module for D - * support for MSVC \ No newline at end of file + * support for MSVC + * Rewritten signals and slots implementation. Now integrates nicely into Qt metasystem
--- a/cpp/qt_core/QMetaObject_shell.cpp Sat Dec 19 18:43:32 2009 +0300 +++ b/cpp/qt_core/QMetaObject_shell.cpp Sun Feb 07 16:04:36 2010 +0000 @@ -1,6 +1,9 @@ #include "qtd_core.h" #include <qobjectdefs.h> + +#include <QList> + extern "C" DLL_PUBLIC void* qtd_QMetaObject_superClass(void *nativeId) { return (void*)((QMetaObject*)nativeId)->superClass(); @@ -10,3 +13,58 @@ { QMetaObject::activate(sender, signal_index, argv); } + +extern "C" DLL_PUBLIC void qtd_QMetaObject_activate_3(QObject *sender, const QMetaObject *m, int local_signal_index, void **argv) +{ + QMetaObject::activate(sender, m, local_signal_index, argv); +} + +extern "C" DLL_PUBLIC void qtd_QMetaObject_activate_4(QObject *sender, const QMetaObject *m, int from_local_signal_index, int to_local_signal_index, void **argv) +{ + QMetaObject::activate(sender, m, from_local_signal_index, to_local_signal_index, argv); +} + +extern "C" DLL_PUBLIC bool qtd_QMetaObject_connect(const QObject *sender, int signal_index, + const QObject *receiver, int method_index, + int type, int *types) +{ + return QMetaObject::connect(sender, signal_index, receiver, method_index, type, types); +} + +extern "C" DLL_PUBLIC int qtd_QMetaObject_indexOfMethod(void *nativeId, const char *method) +{ + return ((QMetaObject*)nativeId)->indexOfMethod(method); +} + +extern "C" DLL_PUBLIC int qtd_QMetaObject_methodCount(void *nativeId) +{ + return ((QMetaObject*)nativeId)->methodCount(); +} + +extern "C" DLL_PUBLIC void qtd_create_QList(void *nativeId) +{ + QList<int> & list = (*(QList<int> *)nativeId); + list.append(54); + list.append(45); +} + +extern "C" DLL_PUBLIC void qtd_create_QList_double(void *nativeId) +{ + QList<double> & list = (*(QList<double> *)nativeId); + list.append(54.44); + list.append(45.55); +} + +extern "C" DLL_PUBLIC void qtd_create_QList_QObject(void *nativeId) +{ + QList<QObject*> & list2 = (*(QList<QObject*> *)nativeId); + + QList<QObject*> list; + QObject* a1 = new QObject(); + a1->setObjectName("a1"); + list.append(a1); + QObject* a2 = new QObject(); + a2->setObjectName("a2"); + list.append(a2); + list2 = list; +}
--- a/cpp/qt_core/QString_shell.cpp Sat Dec 19 18:43:32 2009 +0300 +++ b/cpp/qt_core/QString_shell.cpp Sun Feb 07 16:04:36 2010 +0000 @@ -1,24 +1,67 @@ #include <QString> #include "qtd_core.h" -extern "C" DLL_PUBLIC const ushort* __qtd_QString_utf16 +extern "C" DLL_PUBLIC const ushort* qtd_QString_utf16 (void* __this_nativeId) { QString *__qt_this = (QString *) __this_nativeId; return __qt_this->utf16(); } -extern "C" DLL_PUBLIC int __qtd_QString_size +extern "C" DLL_PUBLIC int qtd_QString_size (void* __this_nativeId) { QString *__qt_this = (QString *) __this_nativeId; return __qt_this->size(); } -extern "C" DLL_PUBLIC void __qtd_QString_operatorAssign +extern "C" DLL_PUBLIC void qtd_QString_operatorAssign (void* __this_nativeId, DArray text) { QString *__qt_this = (QString *) __this_nativeId; *__qt_this = QString::fromUtf8((const char *)text.ptr, text.length); } + +extern "C" DLL_PUBLIC void qtd_QString_destructor(void *ptr) +{ + delete (QString *)ptr; +} + +extern "C" DLL_PUBLIC void qtd_QString_call_destructor(QString *ptr) +{ + ptr->~QString(); +} + + +extern "C" DLL_PUBLIC void* qtd_QString_QString_QString +(void* string0) +{ + const QString& __qt_string0 = (const QString& ) *(QString *)string0; + QString *__qt_this = new QString((const QString& )__qt_string0); + return (void *) __qt_this; +} + +extern "C" DLL_PUBLIC void* qtd_QString_new_fromUtf8_at +(void* place, DArray text) +{ + QString *__qt_this = new(place) QString; + *__qt_this = QString::fromUtf8((const char *)text.ptr, text.length); + return __qt_this; +} + +extern "C" DLL_PUBLIC void* qtd_QString_placed_copy(void* string0, void* place) { + const QString& __qt_string0 = (const QString& ) *(QString *)string0; + QString *result = new (place)QString((const QString& )__qt_string0); + return (void *) result; +} + +extern "C" DLL_PUBLIC void qtd_QString_placed_ctor(void* place) { + new (place) QString(); +} + +extern "C" DLL_PUBLIC void qtd_QString_assign_fromUtf8 +(QString *__qt_this, DArray text) +{ + *__qt_this = QString::fromUtf8((const char *)text.ptr, text.length); +} \ No newline at end of file
--- a/cpp/qt_core/QVariant_shell.cpp Sat Dec 19 18:43:32 2009 +0300 +++ b/cpp/qt_core/QVariant_shell.cpp Sun Feb 07 16:04:36 2010 +0000 @@ -22,6 +22,11 @@ delete (QVariant *)ptr; } +extern "C" DLL_PUBLIC void qtd_QVariant_call_destructor(QVariant *ptr) +{ + ptr->~QVariant(); +} + QVariant_QtDShell::QVariant_QtDShell() : QVariant() { @@ -961,3 +966,8 @@ +extern "C" DLL_PUBLIC void* qtd_QVariant_placed_copy(void* variant0, void* place) { + const QVariant& __qt_variant0 = (const QVariant& ) *(QVariant *)variant0; + QVariant *result = new (place)QVariant((const QVariant& )__qt_variant0); + return (void *) result; +} \ No newline at end of file
--- a/cpp/qt_gui/UrlHandler_shell.cpp Sat Dec 19 18:43:32 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -#include "UrlHandler_shell.h" - -#include "qtd_core.h" - -UrlHandler::UrlHandler(void *d_ptr, QObject* parent0) - : QObject(parent0), - QtD_QObjectEntity(this, d_ptr) -{ -} - -#ifdef CPP_SHARED -extern "C" typedef void (*pfqtd_UrlHandler_handleUrl_QUrl_dispatch)(void *dId, void* arg__1); -pfqtd_UrlHandler_handleUrl_QUrl_dispatch qtd_UrlHandler_handleUrl_QUrl_dispatch; -#else -extern "C" void qtd_UrlHandler_handleUrl_QUrl_dispatch(void *dId, void* name1); -#endif -void UrlHandler::handleUrl(const QUrl &url) -{ - qtd_UrlHandler_handleUrl_QUrl_dispatch(this->dId, &(QUrl& )url); -} - -extern "C" DLL_PUBLIC void qtd_UrlHandler_destructor(void *ptr) -{ - delete (UrlHandler *)ptr; -} - -extern "C" DLL_PUBLIC void* qtd_UrlHandler_UrlHandler_QObject -(void *d_ptr, - void* parent0) -{ - QObject* __qt_parent0 = (QObject* ) parent0; - UrlHandler *__qt_this = new UrlHandler(d_ptr, (QObject* )__qt_parent0); - return (void *) __qt_this; -} - -#ifdef CPP_SHARED -extern "C" DLL_PUBLIC void qtd_UrlHandler_initCallBacks(pfunc_abstr *virts, pfunc_abstr qobj_del) { - qtd_UrlHandler_handleUrl_QUrl_dispatch = (pfqtd_UrlHandler_handleUrl_QUrl_dispatch) virts[0]; -// qtd_D_QWidget_delete = (qtd_pf_D_QWidget_delete)qobj_del; -} -#endif
--- a/cpp/qt_gui/UrlHandler_shell.h Sat Dec 19 18:43:32 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -#include <QUrl> -#include <QObjectEntity.h> - -class UrlHandler : public QObject, public QtD_QObjectEntity -{ - Q_OBJECT - -public: - UrlHandler(void *d_ptr, QObject *parent = 0); - -public slots: - void handleUrl(const QUrl &url); -};
--- a/demos/interview/model.d Sat Dec 19 18:43:32 2009 +0300 +++ b/demos/interview/model.d Sun Feb 07 16:04:36 2010 +0000 @@ -59,7 +59,7 @@ Node[] children; } -size_t find(Node[] arr, Node elem) +size_t find(const Node[] arr, const Node elem) { size_t res = arr.length; for(size_t i = 0; i < arr.length; i++) @@ -89,18 +89,18 @@ } - override QModelIndex index(int row, int column, const QModelIndex parent) + override QModelIndex index(int row, int column, const QModelIndex parent) const { if (row < rc && row >= 0 && column < cc && column >= 0) { - Node p = cast(Node) parent.internalPointer(); - Node n = getNode(row, p); + auto p = cast(Node) parent.internalPointer(); + auto n = getNode(row, p); if (n !is null) return createIndex(row, column, cast(void*)n); } return QModelIndex(); } - override QModelIndex parent(const QModelIndex child) + override QModelIndex parent(const QModelIndex child) const { if (child.isValid()) { Node n = cast(Node) child.internalPointer(); @@ -111,17 +111,17 @@ return QModelIndex(); } - override int rowCount(const QModelIndex parent) + override int rowCount(const QModelIndex parent) const { return (parent.isValid() && parent.column() != 0) ? 0 : rc; } - override int columnCount(const QModelIndex parent) + override int columnCount(const QModelIndex parent) const { return cc; } - override QVariant data(const QModelIndex index, int role) + override QVariant data(const QModelIndex index, int role) const { if (!index.isValid) return new QVariant; @@ -136,7 +136,7 @@ return new QVariant; } - override QVariant headerData(int section, Qt.Orientation orientation, int role) + override QVariant headerData(int section, Qt.Orientation orientation, int role) const { if (role == Qt.DisplayRole) return new QVariant(to!string(section)); @@ -145,39 +145,39 @@ return QAbstractItemModel.headerData(section, orientation, role); } - override bool hasChildren(const QModelIndex parent) + override bool hasChildren(const QModelIndex parent) const { if (parent.isValid && parent.column != 0) return false; return rc > 0 && cc > 0; } - override int flags(const QModelIndex index) + override int flags(const QModelIndex index) const { if (!index.isValid) return 0; return (Qt.ItemIsDragEnabled | Qt.ItemIsSelectable | Qt.ItemIsEnabled); } - Node getNode(int row, Node parent) + const (Node) getNode(int row, Node parent) const { if(parent !is null && parent.children.length == 0) { for(int i = 0; i < rc; i++) parent.children ~= new Node(parent); } - Node[] v = parent !is null ? parent.children : tree; + auto v = parent !is null ? parent.children : tree; return v[row]; } - Node parent(Node child) + Node parent(Node child) const { return child !is null ? child.parent : null; } - int row(Node node) + int row(Node node) const { - Node[] v = node.parent !is null ? node.parent.children : tree; + auto v = node.parent !is null ? node.parent.children : tree; return find(v, node); }
--- a/examples/desktop/systray/window.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/desktop/systray/window.d Sun Feb 07 16:04:36 2010 +0000 @@ -72,11 +72,11 @@ createActions(); createTrayIcon(); - connect!("clicked")(showMessageButton, &this.showMessage); - connect!("toggled")(showIconCheckBox, &trayIcon.setVisible); - connect!("currentIndexChanged")(iconComboBox, &this.setIcon); - connect!("messageClicked")(trayIcon, &this.messageClicked); - connect!("activated")(trayIcon, &this.iconActivated); + connect(showMessageButton, "clicked", this, "showMessage"); + connect(showIconCheckBox, "toggled", trayIcon, "setVisible"); + connect(iconComboBox, "currentIndexChanged", this, "setIcon"); + connect(trayIcon, "messageClicked", this, "messageClicked"); + connect(trayIcon, "activated", this, "iconActivated"); QVBoxLayout mainLayout = new QVBoxLayout; mainLayout.addWidget(iconGroupBox); @@ -111,9 +111,9 @@ } } -private: +private: // slots - void setIcon(int index) + void slot_setIcon(int index) { QIcon icon = iconComboBox.itemIcon(index); trayIcon.setIcon(icon); @@ -122,7 +122,7 @@ trayIcon.setToolTip(iconComboBox.itemText(index)); } - void iconActivated(QSystemTrayIcon.ActivationReason reason) + void slot_iconActivated(QSystemTrayIcon.ActivationReason reason) { switch (reason) { case QSystemTrayIcon.Trigger: @@ -136,14 +136,14 @@ } } - void showMessage() + void slot_showMessage() { QSystemTrayIcon.MessageIcon icon = cast(QSystemTrayIcon.MessageIcon) typeComboBox.itemData(typeComboBox.currentIndex()).toInt(); trayIcon.showMessage(titleEdit.text(), bodyEdit.toPlainText(), icon, durationSpinBox.value() * 1000); } - void messageClicked() + void slot_messageClicked() { QMessageBox.information(null, tr("Systray"), tr("Sorry, I already gave what help I could.\nMaybe you should try asking a human?")); @@ -233,16 +233,16 @@ void createActions() { minimizeAction = new QAction(tr("Mi&nimize"), this); - connect!("triggered")(minimizeAction, &this.hide); + connect(minimizeAction, "activated", this, "hide"); maximizeAction = new QAction(tr("Ma&ximize"), this); - connect!("triggered")(maximizeAction, &this.showMaximized); + connect(maximizeAction, "activated", this, "showMaximized"); restoreAction = new QAction(tr("&Restore"), this); - connect!("triggered")(restoreAction, &this.showNormal); + connect(restoreAction, "activated", this, "showNormal"); quitAction = new QAction(tr("&Quit"), this); - connect!("triggered")(quitAction, &QApplication.quit); + connect(quitAction, "triggered", qApp(), "quit"); } void createTrayIcon() @@ -282,4 +282,6 @@ QSystemTrayIcon trayIcon; QMenu trayIconMenu; + + mixin Q_OBJECT; }
--- a/examples/dialogs/classwizard/classwizard.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/dialogs/classwizard/classwizard.d Sun Feb 07 16:04:36 2010 +0000 @@ -54,7 +54,7 @@ import qt.core.QDir; import qt.core.QRegExp; -import std.string; +import std.string : format, tolower, toupper; class ClassWizard : public QWizard @@ -263,7 +263,7 @@ copyCtorCheckBox = new QCheckBox(tr("&Generate copy constructor and operator=")); defaultCtorRadioButton.setChecked(true); - connect!("toggled")(defaultCtorRadioButton, ©CtorCheckBox.setEnabled); + connect(defaultCtorRadioButton, "toggled", copyCtorCheckBox, "setEnabled"); registerField("className*", classNameLineEdit); registerField("baseClass", baseClassLineEdit); @@ -331,10 +331,8 @@ baseIncludeLineEdit = new QLineEdit; baseIncludeLabel.setBuddy(baseIncludeLineEdit); - connect!("toggled")(protectCheckBox, ¯oNameLabel.setEnabled); -// ? connect!("toggled")(protectCheckBox, ¯oNameLabel.setEnabled); - connect!("toggled")(includeBaseCheckBox, ¯oNameLabel.setEnabled); -// ? connect!("toggled")(includeBaseCheckBox, ¯oNameLabel.setEnabled); + connect(protectCheckBox, "toggled", macroNameLabel, "setEnabled"); + connect(includeBaseCheckBox, "toggled", macroNameLabel, "setEnabled"); registerField("comment", commentCheckBox); registerField("protect", protectCheckBox);
--- a/examples/dialogs/standarddialogs/dialog.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/dialogs/standarddialogs/dialog.d Sun Feb 07 16:04:36 2010 +0000 @@ -135,21 +135,21 @@ errorLabel.setFrameStyle(frameStyle); QPushButton errorButton = new QPushButton(tr("QErrorMessage.show&M&essage()")); - connect!("clicked")(integerButton, &this.setInteger); - connect!("clicked")(doubleButton, &this.setDouble); - connect!("clicked")(itemButton, &this.setItem); - connect!("clicked")(textButton, &this.setText); - connect!("clicked")(colorButton, &this.setColor); - connect!("clicked")(fontButton, &this.setFont); - connect!("clicked")(directoryButton, &this.setExistingDirectory); - connect!("clicked")(openFileNameButton, &this.setOpenFileName); - connect!("clicked")(openFileNamesButton, &this.setOpenFileNames); - connect!("clicked")(saveFileNameButton, &this.setSaveFileName); - connect!("clicked")(criticalButton, &this.criticalMessage); - connect!("clicked")(informationButton, &this.informationMessage); - connect!("clicked")(questionButton, &this.questionMessage); - connect!("clicked")(warningButton, &this.warningMessage); - connect!("clicked")(errorButton, &this.errorMessage); + connect(integerButton, "clicked", this, "setInteger"); + connect(doubleButton, "clicked", this, "setDouble"); + connect(itemButton, "clicked", this, "setItem"); + connect(textButton, "clicked", this, "setText"); + connect(colorButton, "clicked", this, "setColor"); + connect(fontButton, "clicked", this, "setFont"); + connect(directoryButton, "clicked", this, "setExistingDirectory"); + connect(openFileNameButton, "clicked", this, "setOpenFileName"); + connect(openFileNamesButton, "clicked", this, "setOpenFileNames"); + connect(saveFileNameButton, "clicked", this, "setSaveFileName"); + connect(criticalButton, "clicked", this, "criticalMessage"); + connect(informationButton, "clicked", this, "informationMessage"); + connect(questionButton, "clicked", this, "questionMessage"); + connect(warningButton, "clicked", this, "warningMessage"); + connect(errorButton, "clicked", this, "errorMessage"); native = new QCheckBox(this); native.setText("Use native file dialog."); @@ -202,9 +202,9 @@ setWindowTitle(tr("Standard Dialogs")); } -private: +private: // slots - void setInteger() + void slot_setInteger() { bool ok; int i = QInputDialog.getInt(this, tr("QInputgetInteger()"), tr("Percentage:"), 25, 0, 100, 1, ok); @@ -212,27 +212,27 @@ integerLabel.setText(format("%d", i)); } - void setDouble() + void slot_setDouble() { bool ok; double d = QInputDialog.getDouble(this, tr("QInputgetDouble()"), tr("Amount:"), 37.56, -10000, 10000, 2, ok); if (ok) - integerLabel.setText(format("%g", d)); + doubleLabel.setText(format("%g", d)); } - void setItem() + void slot_setItem() { string[] items = [tr("Spring"), tr("Summer"), tr("Fall"), tr("Winter")]; bool ok; string item = QInputDialog.getItem(this, tr("QInputgetItem()"), - tr("Season:"), items, 0, false, ok); + tr("Season:"), items.toQList, 0, false, ok); if (ok && item.length) itemLabel.setText(item); } - void setText() + void slot_setText() { bool ok; string text = QInputDialog.getText(this, tr("QInputgetText()"), @@ -242,7 +242,7 @@ textLabel.setText(text); } - void setColor() + void slot_setColor() { QColor color = QColorDialog.getColor(QColor.Green, this); if (color.isValid()) { @@ -252,7 +252,7 @@ } } - void setFont() + void slot_setFont() { bool ok; QFont font = QFontDialog.getFont(&ok, new QFont(fontLabel.text()), this); @@ -262,7 +262,7 @@ } } - void setExistingDirectory() + void slot_setExistingDirectory() { int options = QFileDialog_Option.DontResolveSymlinks | QFileDialog_Option.ShowDirsOnly; if (!native.isChecked()) @@ -275,7 +275,7 @@ directoryLabel.setText(directory); } - void setOpenFileName() + void slot_setOpenFileName() { int options; if (!native.isChecked()) @@ -291,13 +291,13 @@ openFileNameLabel.setText(fileName); } - void setOpenFileNames() + void slot_setOpenFileNames() { int options; if (!native.isChecked()) options |= QFileDialog_Option.DontUseNativeDialog; string selectedFilter; - string[] files = QFileDialog.getOpenFileNames( + auto files = QFileDialog.getOpenFileNames( this, tr("QFilegetOpenFileNames()"), openFilesPath, tr("All Files (*);;Text Files (*.txt)"), @@ -305,11 +305,11 @@ options); if (files.length) { openFilesPath = files[0]; - openFileNamesLabel.setText(join(files, "; ")); + openFileNamesLabel.setText(join(files.toArray, "; ")); } } - void setSaveFileName() + void slot_setSaveFileName() { int options; if (!native.isChecked()) @@ -325,7 +325,7 @@ saveFileNameLabel.setText(fileName); } - void criticalMessage() + void slot_criticalMessage() { QMessageBox.StandardButton reply; reply = QMessageBox.critical(this, tr("QMessageBox.critical()"), @@ -339,7 +339,7 @@ criticalLabel.setText(tr("Ignore")); } - void informationMessage() + void slot_informationMessage() { QMessageBox.StandardButton reply; reply = QMessageBox.information(this, tr("QMessageBox.information()"), MESSAGE); @@ -349,7 +349,7 @@ informationLabel.setText(tr("Escape")); } - void questionMessage() + void slot_questionMessage() { QMessageBox.StandardButton reply; reply = QMessageBox.question(this, tr("QMessageBox.question()"), @@ -363,7 +363,7 @@ questionLabel.setText(tr("Cancel")); } - void warningMessage() + void slot_warningMessage() { auto msgBox = new QMessageBox(QMessageBox.Warning, tr("QMessageBox.warning()"), MESSAGE, 0, this); msgBox.addButton(tr("Save &Again"), QMessageBox.AcceptRole); @@ -374,7 +374,7 @@ warningLabel.setText(tr("Continue")); } - void errorMessage() + void slot_errorMessage() { errorMessageDialog.showMessage( tr("This dialog shows and remembers error messages. " @@ -407,4 +407,6 @@ QErrorMessage errorMessageDialog; string openFilesPath; + + mixin Q_OBJECT; }
--- a/examples/draganddrop/dropsite/droparea.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/draganddrop/dropsite/droparea.d Sun Feb 07 16:04:36 2010 +0000 @@ -58,7 +58,7 @@ clearArea(); } - void clearArea() + void slot_clearArea() { setText(tr("<drop content>")); setBackgroundRole(QPalette.Dark); @@ -66,10 +66,9 @@ changed(null); } - mixin Signal!("changed", QMimeData); + final void signal_changed(QMimeData); protected: - void dragEnterEvent(QDragEnterEvent event) { setText(tr("<drop content>")); @@ -103,7 +102,7 @@ setText(mimeData.text()); setTextFormat(Qt.PlainText); } else if (mimeData.hasUrls()) { - QUrl[] urlList = mimeData.urls(); + auto urlList = mimeData.urls(); string text; for (int i = 0; i < urlList.length && i < 32; ++i) { text ~= urlList[i].path() ~ "\n"; @@ -119,5 +118,7 @@ private: QLabel label; + + mixin Q_OBJECT; }
--- a/examples/draganddrop/dropsite/dropsitewindow.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/draganddrop/dropsite/dropsitewindow.d Sun Feb 07 16:04:36 2010 +0000 @@ -67,7 +67,7 @@ abstractLabel.adjustSize(); dropArea = new DropArea; - connect!("changed")(dropArea, &updateFormatsTable); + connect(dropArea, "changed", this, "updateFormatsTable"); string[] labels; labels ~= tr("Format"); @@ -76,7 +76,7 @@ formatsTable = new QTableWidget; formatsTable.setColumnCount(2); formatsTable.setEditTriggers(QAbstractItemView.NoEditTriggers); - formatsTable.setHorizontalHeaderLabels(labels); + formatsTable.setHorizontalHeaderLabels(labels.toQList()); formatsTable.horizontalHeader().setStretchLastSection(true); clearButton = new QPushButton(tr("Clear")); @@ -86,8 +86,8 @@ buttonBox.addButton(clearButton, QDialogButtonBox.ActionRole); buttonBox.addButton(quitButton, QDialogButtonBox.RejectRole); - connect!("pressed")(quitButton, &close); - connect!("pressed")(clearButton, &dropArea.clearArea); + connect(quitButton, "pressed", this, "close"); + connect(clearButton, "pressed", dropArea, "clearArea"); QVBoxLayout mainLayout = new QVBoxLayout; mainLayout.addWidget(abstractLabel); @@ -100,7 +100,7 @@ setMinimumSize(350, 500); } - void updateFormatsTable(QMimeData mimeData) + void slot_updateFormatsTable(QMimeData mimeData) { formatsTable.setRowCount(0); if (!mimeData) @@ -117,7 +117,7 @@ } else if (format == "text/html") { text = strip(mimeData.html()); } else if (format == "text/uri-list") { - QUrl[] urlList = mimeData.urls(); + auto urlList = mimeData.urls(); for (int i = 0; i < urlList.length && i < 32; ++i) { string url = urlList[i].path(); text ~= url ~ " "; @@ -148,4 +148,6 @@ QPushButton clearButton; QPushButton quitButton; QDialogButtonBox buttonBox; + + mixin Q_OBJECT; }
--- a/examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.d Sun Feb 07 16:04:36 2010 +0000 @@ -82,7 +82,7 @@ protected: - override bool filterAcceptsRow(int sourceRow, const QModelIndex sourceParent) + override bool filterAcceptsRow(int sourceRow, const QModelIndex sourceParent) const { QModelIndex index0 = sourceModel().index(sourceRow, 0, sourceParent); QModelIndex index1 = sourceModel().index(sourceRow, 1, sourceParent); @@ -96,10 +96,10 @@ return (contains(sourceModel().data(index0).toString(), filterRegExp()) || contains(sourceModel().data(index1).toString(), filterRegExp())) - && dateInRange(sourceModel().data(index2).toDate()); + /* && dateInRange(sourceModel().data(index2).toDate())*/; } - override bool lessThan(const QModelIndex left, const QModelIndex right) + override bool lessThan(const QModelIndex left, const QModelIndex right) const { QVariant leftData = sourceModel().data(left); QVariant rightData = sourceModel().data(right); @@ -122,12 +122,12 @@ } private: - - bool dateInRange(QDate date) +/* + bool dateInRange(const QDate date) const { return (!minDate.isValid() || date > minDate) && (!maxDate.isValid() || date < maxDate); } - +*/ QDate minDate; QDate maxDate; }
--- a/examples/itemviews/customsortfiltermodel/window.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/itemviews/customsortfiltermodel/window.d Sun Feb 07 16:04:36 2010 +0000 @@ -102,11 +102,11 @@ toLabel = new QLabel(tr("&To:")); toLabel.setBuddy(toDateEdit); - connect!("textChanged")(filterPatternLineEdit, &this.textFilterChanged); - connect!("currentIndexChanged")(filterSyntaxComboBox, &this.textFilterChanged); - connect!("toggled")(filterCaseSensitivityCheckBox, &this.textFilterChanged); - connect!("dateChanged")(fromDateEdit, &this.dateFilterChanged); - connect!("dateChanged")(toDateEdit, &this.dateFilterChanged); + connect(filterPatternLineEdit, "textChanged", this, "textFilterChanged"); + connect(filterSyntaxComboBox, "currentIndexChanged", this, "textFilterChanged"); + connect(filterCaseSensitivityCheckBox, "toggled", this, "textFilterChanged"); + connect(fromDateEdit, "dateChanged", this, "dateFilterChanged"); + connect(toDateEdit, "dateChanged", this, "dateFilterChanged"); proxyView = new QTreeView; proxyView.setRootIsDecorated(false); @@ -144,9 +144,9 @@ sourceView.setModel(model); } -private: +private: // slots - void textFilterChanged() + void slot_textFilterChanged() { QRegExp.PatternSyntax syntax = cast(QRegExp.PatternSyntax) filterSyntaxComboBox.itemData( filterSyntaxComboBox.currentIndex()).toInt(); @@ -158,11 +158,13 @@ proxyModel.setFilterRegExp(regExp); } - void dateFilterChanged() + void slot_dateFilterChanged() { proxyModel.setFilterMinimumDate(fromDateEdit.date()); proxyModel.setFilterMaximumDate(toDateEdit.date()); } + + mixin Q_OBJECT; private:
--- a/examples/layouts/basiclayouts/dialog.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/layouts/basiclayouts/dialog.d Sun Feb 07 16:04:36 2010 +0000 @@ -61,6 +61,8 @@ else import std.string; +import std.stdio; + class Dialog : public QDialog { this() @@ -75,8 +77,8 @@ buttonBox = new QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel); - connect!("accepted")(buttonBox, &this.accept); - connect!("rejected")(buttonBox, &this.reject); + connect(buttonBox, "accepted", this, "accept"); + connect(buttonBox, "rejected", this, "reject"); QVBoxLayout mainLayout = new QVBoxLayout; @@ -101,7 +103,7 @@ exitAction = fileMenu.addAction(tr("E&xit")); menuBar.addMenu(fileMenu); - connect!("triggered")(exitAction, &this.accept); + connect(exitAction, "triggered", this, "accept"); } void createHorizontalGroupBox() @@ -155,6 +157,8 @@ formGroupBox.setLayout(layout); } + mixin Q_OBJECT; + enum { NumGridRows = 3, NumButtons = 4 }; QMenuBar menuBar;
--- a/examples/layouts/borderlayout/borderlayout.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/layouts/borderlayout/borderlayout.d Sun Feb 07 16:04:36 2010 +0000 @@ -75,40 +75,47 @@ } } - void addItem(IQLayoutItem item) - { - add(item, Position.West); - } - void addWidget(QWidget widget, Position position) { add(cast(IQLayoutItem) new QWidgetItem(widget), position); } - int expandingDirections() + void add(IQLayoutItem item, Position position) + { + list ~= new ItemWrapper(item, position); + } + +override +{ + void addItem(IQLayoutItem item) + { + add(item, Position.West); + } + + int expandingDirections() const { return Qt.Horizontal | Qt.Vertical; } - bool hasHeightForWidth() + bool hasHeightForWidth() const { return false; } - int count() + int count() const { return list.length; } - QLayoutItem itemAt(int index) + IQLayoutItem itemAt(int index) const { if(index >= 0 && index < list.length) - return list[index].item; + return cast(IQLayoutItem) list[index].item; else return null; } - QSize minimumSize() + QSize minimumSize() const { return calculateSize(SizeType.MinimumSize); } @@ -182,7 +189,7 @@ centerHeight)); } - QSize sizeHint() + QSize sizeHint() const { return calculateSize(SizeType.SizeHint); } @@ -195,11 +202,7 @@ } return null; } - - void add(IQLayoutItem item, Position position) - { - list ~= new ItemWrapper(item, position); - } +} private: @@ -217,12 +220,12 @@ enum SizeType { MinimumSize, SizeHint }; - QSize calculateSize(SizeType sizeType) + QSize calculateSize(SizeType sizeType) const { QSize totalSize; for (int i = 0; i < list.length; ++i) { - ItemWrapper wrapper = list[i]; + const ItemWrapper wrapper = list[i]; Position position = wrapper.position; QSize itemSize;
--- a/examples/layouts/dynamiclayouts/dialog.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/layouts/dynamiclayouts/dialog.d Sun Feb 07 16:04:36 2010 +0000 @@ -76,9 +76,9 @@ setWindowTitle(tr("Dynamic Layouts")); } -private: +private: // slots - void buttonsOrientationChanged(int index) + void slot_buttonsOrientationChanged(int index) { mainLayout.setSizeConstraint(QLayout.SetNoConstraint); setMinimumSize(0, 0); @@ -107,7 +107,7 @@ mainLayout.setSizeConstraint(QLayout.SetDefaultConstraint); } - void rotateWidgets() + void slot_rotateWidgets() { assert(rotableWidgets.length % 2 == 0); @@ -123,7 +123,7 @@ } } - void help() + void slot_help() { QMessageBox.information(this, tr("Dynamic Layouts Help"), tr("This example shows how to change layouts dynamically.")); @@ -145,17 +145,11 @@ rotableWidgets ~= a2; rotableWidgets ~= a3; - connect!("valueChanged")(a0, &a1.setValue); - connect!("valueChanged")(a1, &a2.setValue); - connect!("valueChanged")(a2, &a3.setValue); - connect!("valueChanged")(a3, &a0.setValue); + int n = rotableWidgets.length; + for (int i = 0; i < n; ++i) + connect(rotableWidgets[i], "valueChanged", rotableWidgets[(i + 1) % n], "setValue"); - /* - int n = rotableWidgets.length; - for (int i = 0; i < n; ++i) { - rotableWidgets[i].valueChanged.connect(&rotableWidgets[(i + 1) % n].setValue); - }*/ - + rotableLayout = new QGridLayout; rotableGroupBox.setLayout(rotableLayout); @@ -172,8 +166,8 @@ buttonsOrientationComboBox.addItem(tr("Horizontal"), new QVariant(cast(ulong) Qt.Horizontal)); buttonsOrientationComboBox.addItem(tr("Vertical"), new QVariant(cast(ulong) Qt.Vertical)); - connect!("currentIndexChanged")(buttonsOrientationComboBox, &this.buttonsOrientationChanged); - + connect(buttonsOrientationComboBox, "currentIndexChanged", this, "buttonsOrientationChanged"); + optionsLayout = new QGridLayout; optionsLayout.addWidget(buttonsOrientationLabel, 0, 0); optionsLayout.addWidget(buttonsOrientationComboBox, 0, 1); @@ -189,9 +183,9 @@ helpButton = buttonBox.addButton(QDialogButtonBox.Help); rotateWidgetsButton = buttonBox.addButton(tr("Rotate &Widgets"), QDialogButtonBox.ActionRole); - connect!("clicked")(rotateWidgetsButton, &this.rotateWidgets); - connect!("clicked")(closeButton, &this.close); - connect!("clicked")(helpButton, &this.help); + connect(rotateWidgetsButton, "clicked", this, "rotateWidgets"); + connect(closeButton, "clicked", this, "close"); + connect(helpButton, "clicked", this, "help"); } QGroupBox rotableGroupBox; @@ -209,4 +203,6 @@ QGridLayout mainLayout; QGridLayout rotableLayout; QGridLayout optionsLayout; + + mixin Q_OBJECT; }
--- a/examples/mainwindows/dockwidgets/mainwindow.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/mainwindows/dockwidgets/mainwindow.d Sun Feb 07 16:04:36 2010 +0000 @@ -82,7 +82,7 @@ } private : //slots: - void newLetter() + void slot_newLetter() { textEdit.clear(); @@ -128,7 +128,7 @@ cursor.insertText("ADDRESS", italicFormat); } /* - void save() + void slot_save() { char[] fileName = QFileDialog.getSaveFileName(this, tr("Choose a file name"), ".", @@ -150,14 +150,14 @@ statusBar.showMessage(layout("Saved '%1'", fileName), 2000); }*/ - void print() { } + void slot_print() { } - void undo() { + void slot_undo() { auto document = textEdit.document(); document.undo(); } - void insertCustomer(string customer) + void slot_insertCustomer(string customer) { if (customer == "") return; @@ -182,7 +182,7 @@ } } - void addParagraph(string paragraph) + void slot_addParagraph(string paragraph) { if (paragraph == "") return; @@ -199,7 +199,7 @@ } - void about() + void slot_about() { QMessageBox.about(this, "About Dock Widgets", "The <b>Dock Widgets</b> example demonstrates how to " @@ -214,7 +214,7 @@ newLetterAct = new QAction(new QIcon(":images/new.png"), tr("&New Letter"), this); newLetterAct.setShortcut(tr("Ctrl+N")); newLetterAct.setStatusTip(tr("Create a new form letter")); - connect!("triggered")(newLetterAct, &this.newLetter); + connect(newLetterAct, "triggered", this, "newLetter"); saveAct = new QAction(new QIcon(":images/save.png"), tr("&Save..."), this); saveAct.setShortcut(tr("Ctrl+S")); @@ -229,20 +229,20 @@ undoAct = new QAction(new QIcon(":images/undo.png"), tr("&Undo"), this); undoAct.setShortcut(tr("Ctrl+Z")); undoAct.setStatusTip(tr("Undo the last editing action")); - connect!("triggered")(undoAct, &undo); + connect(undoAct, "triggered", this, "undo"); quitAct = new QAction(tr("&Quit"), this); quitAct.setShortcut(tr("Ctrl+Q")); quitAct.setStatusTip(tr("Quit the application")); - connect!("triggered")(quitAct, &this.close); + connect(quitAct, "triggered", this, "close"); aboutAct = new QAction(tr("&About"), this); aboutAct.setStatusTip(tr("Show the application's About box")); - connect!("triggered")(aboutAct, &about); + connect(aboutAct, "triggered", this, "about"); aboutQtAct = new QAction(tr("About &Qt"), this); aboutQtAct.setStatusTip(tr("Show the Qt library's About box")); - // aboutQtAct.triggered(&aboutQt); + connect(aboutQtAct, "triggered", qApp, "aboutQt"); } void createMenus() @@ -327,8 +327,8 @@ addDockWidget(Qt.RightDockWidgetArea, dock); viewMenu.addAction(dock.toggleViewAction()); - connect!("currentTextChanged")(customerList, &this.insertCustomer); - connect!("currentTextChanged")(paragraphsList, &this.addParagraph); + connect(customerList, "currentTextChanged", this, "insertCustomer"); + connect(paragraphsList, "currentTextChanged", this, "addParagraph"); } QTextEdit textEdit; @@ -348,7 +348,6 @@ QAction aboutAct; QAction aboutQtAct; QAction quitAct; + + mixin Q_OBJECT; } - - -//! [9]
--- a/examples/mainwindows/sdi/mainwindow.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/mainwindows/sdi/mainwindow.d Sun Feb 07 16:04:36 2010 +0000 @@ -98,14 +98,14 @@ private: // slots - void newFile() + void slot_newFile() { MainWindow other = new MainWindow; other.move(x() + 40, y() + 40); other.show(); } - void open() + void slot_open() { scope fileName = QFileDialog.getOpenFileName(this); if (fileName) { @@ -131,7 +131,7 @@ } } - bool save() + bool slot_save() { if (isUntitled) { return saveAs(); @@ -140,7 +140,7 @@ } } - bool saveAs() + bool slot_saveAs() { string fileName = QFileDialog.getSaveFileName(this, tr("Save As"), curFile); @@ -150,14 +150,14 @@ return saveFile(fileName); } - void about() + void slot_about() { QMessageBox.about(this, tr("About SDI"), tr("The <b>SDI</b> example demonstrates how to write single " ~ "document interface applications using Qt.")); } - void documentWasModified() + void slot_documentWasModified() { setWindowModified(true); } @@ -180,7 +180,7 @@ readSettings(); - connect!("contentsChanged")(textEdit.document(), &this.documentWasModified); + connect(textEdit.document(), "contentsChanged", this, "documentWasModified"); setUnifiedTitleAndToolBarOnMac(true); } @@ -190,64 +190,64 @@ newAct = new QAction(new QIcon(":/images/new.png"), tr("&New"), this); newAct.setShortcuts(QKeySequence.New); newAct.setStatusTip(tr("Create a new file")); - connect!("triggered")(newAct, &this.newFile); + connect(newAct, "triggered", this, "newFile"); openAct = new QAction(new QIcon(":/images/open.png"), tr("&Open..."), this); openAct.setShortcuts(QKeySequence.Open); openAct.setStatusTip(tr("Open an existing file")); - connect!("triggered")(openAct, &this.open); + connect(openAct, "triggered", this, "open"); saveAct = new QAction(new QIcon(":/images/save.png"), tr("&Save"), this); saveAct.setShortcuts(QKeySequence.Save); saveAct.setStatusTip(tr("Save the document to disk")); - connect!("triggered")(saveAct, &this.save); + connect(saveAct, "triggered", this, "save"); saveAsAct = new QAction(tr("Save &As..."), this); saveAsAct.setShortcuts(QKeySequence.SaveAs); saveAsAct.setStatusTip(tr("Save the document under a new name")); - connect!("triggered")(saveAsAct, &this.saveAs); + connect(saveAsAct, "triggered", this, "saveAs"); closeAct = new QAction(tr("&Close"), this); closeAct.setShortcut(tr("Ctrl+W")); closeAct.setStatusTip(tr("Close this window")); - connect!("triggered")(closeAct, &this.close); + connect(closeAct, "triggered", this, "close"); exitAct = new QAction(tr("E&xit"), this); exitAct.setShortcut(tr("Ctrl+Q")); exitAct.setStatusTip(tr("Exit the application")); - connect!("triggered")(exitAct, &QApplication.closeAllWindows); + connect(exitAct, "triggered", qApp(), "closeAllWindows"); cutAct = new QAction(new QIcon(":/images/cut.png"), tr("Cu&t"), this); cutAct.setShortcuts(QKeySequence.Cut); cutAct.setStatusTip(tr("Cut the current selection's contents to the " ~ "clipboard")); - connect!("triggered")(cutAct, &textEdit.cut); + connect(cutAct, "triggered", textEdit, "cut"); copyAct = new QAction(new QIcon(":/images/copy.png"), tr("&Copy"), this); copyAct.setShortcuts(QKeySequence.Copy); copyAct.setStatusTip(tr("Copy the current selection's contents to the " ~ "clipboard")); - connect!("triggered")(copyAct, &textEdit.copy); + connect(copyAct, "triggered", textEdit, "copy"); pasteAct = new QAction(new QIcon(":/images/paste.png"), tr("&Paste"), this); pasteAct.setShortcuts(QKeySequence.Paste); pasteAct.setStatusTip(tr("Paste the clipboard's contents into the current " ~ "selection")); - connect!("triggered")(pasteAct, &textEdit.paste); + connect(pasteAct, "triggered", textEdit, "paste"); aboutAct = new QAction(tr("&About"), this); aboutAct.setStatusTip(tr("Show the application's About box")); - connect!("triggered")(aboutAct, &this.about); + connect(aboutAct, "triggered", this, "about"); aboutQtAct = new QAction(tr("About &Qt"), this); aboutQtAct.setStatusTip(tr("Show the Qt library's About box")); - connect!("triggered")(aboutQtAct, &QApplication.aboutQt); + connect(aboutQtAct, "triggered", qApp, "aboutQt"); cutAct.setEnabled(false); copyAct.setEnabled(false); - connect!("copyAvailable")(textEdit, &cutAct.setEnabled); - connect!("copyAvailable")(textEdit, ©Act.setEnabled); + connect(textEdit, "copyAvailable", cutAct, "setEnabled"); + connect(textEdit, "copyAvailable", copyAct, "setEnabled"); } void createMenus() @@ -426,4 +426,6 @@ QAction pasteAct; QAction aboutAct; QAction aboutQtAct; + + mixin Q_OBJECT; };
--- a/examples/opengl/hellogl/CMakeLists.txt Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/opengl/hellogl/CMakeLists.txt Sun Feb 07 16:04:36 2010 +0000 @@ -1,2 +1,1 @@ -build_example(hellogl PACKAGES QtCore QtGui QtOpenGL - SOURCES main.d) \ No newline at end of file +build_example(hellogl main.d PACKAGES QtCore QtGui QtOpenGL) \ No newline at end of file
--- a/examples/opengl/hellogl/glwidget.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/opengl/hellogl/glwidget.d Sun Feb 07 16:04:36 2010 +0000 @@ -69,19 +69,19 @@ glDeleteLists(object, 1); } - QSize minimumSizeHint() + QSize minimumSizeHint() const { return QSize(50, 50); } - QSize sizeHint() + QSize sizeHint() const { return QSize(400, 400); } public: // slots: - void setXRotation(int angle) + void slot_setXRotation(int angle) { normalizeAngle(&angle); if (angle != xRot) { @@ -91,7 +91,7 @@ } } - void setYRotation(int angle) + void slot_setYRotation(int angle) { normalizeAngle(&angle); if (angle != yRot) { @@ -101,7 +101,7 @@ } } - void setZRotation(int angle) + void slot_setZRotation(int angle) { normalizeAngle(&angle); if (angle != zRot) { @@ -110,11 +110,13 @@ updateGL(); } } - - mixin Signal!("xRotationChanged", int); - mixin Signal!("yRotationChanged", int); - mixin Signal!("zRotationChanged", int); - + + final // signals + { + void signal_xRotationChanged(int); + void signal_yRotationChanged(int); + void signal_zRotationChanged(int); + } protected: void initializeGL() @@ -264,4 +266,6 @@ QPoint lastPos; QColor trolltechGreen; QColor trolltechPurple; + + mixin Q_OBJECT; } \ No newline at end of file
--- a/examples/opengl/hellogl/window.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/opengl/hellogl/window.d Sun Feb 07 16:04:36 2010 +0000 @@ -39,58 +39,55 @@ import qt.gui.QSlider; import qt.gui.QHBoxLayout; -version(D_Version2) - import glwidget; -else - import glwidget_d1; +import glwidget; class Window : public QWidget { -// Q_OBJECT - - public: - this() - { - glWidget = new GLWidget; - - xSlider = createSlider(); - ySlider = createSlider(); - zSlider = createSlider(); - - connect!("valueChanged")(xSlider, &glWidget.setXRotation); - connect!("xRotationChanged")(glWidget, &xSlider.setValue); - connect!("valueChanged")(ySlider, &glWidget.setYRotation); - connect!("yRotationChanged")(glWidget, &ySlider.setValue); - connect!("valueChanged")(zSlider,&glWidget.setZRotation); - connect!("zRotationChanged")(glWidget, &zSlider.setValue); - - QHBoxLayout mainLayout = new QHBoxLayout; - mainLayout.addWidget(glWidget); - mainLayout.addWidget(xSlider); - mainLayout.addWidget(ySlider); - mainLayout.addWidget(zSlider); - setLayout(mainLayout); - - xSlider.setValue(15 * 16); - ySlider.setValue(345 * 16); - zSlider.setValue(0 * 16); - setWindowTitle(tr("Hello GL")); - } - - private: - QSlider createSlider() - { - auto slider = new QSlider(Qt.Vertical); - slider.setRange(0, 360 * 16); - slider.setSingleStep(16); - slider.setPageStep(15 * 16); - slider.setTickInterval(15 * 16); - slider.setTickPosition(QSlider.TicksRight); - return slider; - } - - GLWidget glWidget; - QSlider xSlider; - QSlider ySlider; - QSlider zSlider; + public: + this() + { + glWidget = new GLWidget; + + xSlider = createSlider(); + ySlider = createSlider(); + zSlider = createSlider(); + + connect(xSlider, "valueChanged", glWidget, "setXRotation"); + connect(glWidget, "xRotationChanged", xSlider, "setValue"); + connect(ySlider, "valueChanged", glWidget, "setYRotation"); + connect(glWidget, "yRotationChanged", ySlider, "setValue"); + connect(zSlider, "valueChanged", glWidget, "setZRotation"); + connect(glWidget, "zRotationChanged", zSlider, "setValue"); + + QHBoxLayout mainLayout = new QHBoxLayout; + mainLayout.addWidget(glWidget); + mainLayout.addWidget(xSlider); + mainLayout.addWidget(ySlider); + mainLayout.addWidget(zSlider); + setLayout(mainLayout); + + xSlider.setValue(15 * 16); + ySlider.setValue(345 * 16); + zSlider.setValue(0 * 16); + setWindowTitle(tr("Hello GL")); + } + + private: + QSlider createSlider() + { + auto slider = new QSlider(Qt.Vertical); + slider.setRange(0, 360 * 16); + slider.setSingleStep(16); + slider.setPageStep(15 * 16); + slider.setTickInterval(15 * 16); + slider.setTickPosition(QSlider.TicksRight); + return slider; + } + + GLWidget glWidget; + QSlider xSlider; + QSlider ySlider; + QSlider zSlider; + + mixin Q_OBJECT; } \ No newline at end of file
--- a/examples/tutorials/tutorial/t2/main.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/tutorials/tutorial/t2/main.d Sun Feb 07 16:04:36 2010 +0000 @@ -47,7 +47,7 @@ quit.resize(75, 30); quit.setFont(new QFont("Times", 18, QFont.Bold)); - QObject.connect!("clicked")(quit, &QApplication.quit); + QObject.connect(quit, "clicked", app, "quit"); quit.show(); return app.exec();
--- a/examples/tutorials/tutorial/t3/main.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/tutorials/tutorial/t3/main.d Sun Feb 07 16:04:36 2010 +0000 @@ -51,7 +51,7 @@ quit.setFont(new QFont("Times", 18, QFont.Light)); quit.setGeometry(10, 40, 180, 40); - QObject.connect!("clicked")(quit, &QApplication.quit); + QObject.connect(quit, "clicked", app, "quit"); window.show(); return app.exec();
--- a/examples/tutorials/tutorial/t4/main.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/tutorials/tutorial/t4/main.d Sun Feb 07 16:04:36 2010 +0000 @@ -51,7 +51,7 @@ auto quit = new QPushButton("Quit", this); quit.setGeometry(62, 40, 75, 30); quit.setFont(new QFont("Times", 18, QFont.Bold)); - connect!("clicked")(quit, &QApplication.quit); + connect(quit, "clicked", qApp(), "quit"); } }
--- a/examples/tutorials/tutorial/t5/main.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/tutorials/tutorial/t5/main.d Sun Feb 07 16:04:36 2010 +0000 @@ -60,8 +60,8 @@ slider.setRange(0, 99); slider.setValue(0); - connect!("clicked")(quit, &QApplication.quit); - connect!("valueChanged")(slider, cast(void delegate(int)) &lcd.display); + connect(quit, "clicked", qApp(), "quit"); + connect(slider, "valueChanged", lcd, "display"); auto layout = new QVBoxLayout; layout.addWidget(quit);
--- a/examples/tutorials/tutorial/t6/main.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/tutorials/tutorial/t6/main.d Sun Feb 07 16:04:36 2010 +0000 @@ -58,7 +58,7 @@ auto slider = new QSlider(Qt.Horizontal); slider.setRange(0, 99); slider.setValue(0); - connect!("valueChanged")(slider, cast(void delegate(int)) &lcd.display); + connect(slider, "valueChanged", lcd, "display"); auto layout = new QVBoxLayout; layout.addWidget(lcd); @@ -76,7 +76,7 @@ auto quit = new QPushButton("Quit"); quit.setFont(new QFont("Times", 18, QFont.Bold)); - connect!("clicked")(quit, &QApplication.quit); + connect(quit, "clicked", qApp(), "quit"); auto grid = new QGridLayout; for (int row = 0; row < 3; ++row) {
--- a/examples/widgets/analogclock/AnalogClock.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/widgets/analogclock/AnalogClock.d Sun Feb 07 16:04:36 2010 +0000 @@ -55,7 +55,7 @@ { super(parent); auto timer = new QTimer(this); - connect!("timeout")(timer, &this.update); + connect(timer, "timeout", this, "update"); timer.start(1000); setWindowTitle("Analog Clock"); resize(200, 200); @@ -119,4 +119,6 @@ painter.rotate(6.0); } } + + mixin Q_OBJECT; } \ No newline at end of file
--- a/examples/widgets/calculator/button.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/widgets/calculator/button.d Sun Feb 07 16:04:36 2010 +0000 @@ -57,11 +57,13 @@ setText(text); } - QSize sizeHint() + QSize sizeHint() const { QSize size = super.sizeHint(); size.height = size.height + 20; size.width= qMax(size.width(), size.height()); return size; } + + mixin Q_OBJECT; }
--- a/examples/widgets/calculator/calculator.d Sat Dec 19 18:43:32 2009 +0300 +++ b/examples/widgets/calculator/calculator.d Sun Feb 07 16:04:36 2010 +0000 @@ -75,30 +75,30 @@ display.setFont(font); for (int i = 0; i < NumDigitButtons; ++i) { - digitButtons[i] = createButton(format("%d", i), &digitClicked); + digitButtons[i] = createButton(format("%d", i), "digitClicked"); } - Button pointButton = createButton(tr("."), &pointClicked); - Button changeSignButton = createButton(tr("+/-"), &changeSignClicked); + Button pointButton = createButton(tr("."), "pointClicked"); + Button changeSignButton = createButton(tr("+/-"), "changeSignClicked"); - Button backspaceButton = createButton(tr("Backspace"), &backspaceClicked); - Button clearButton = createButton(tr("Clear"), &clear); - Button clearAllButton = createButton(tr("Clear All"), &clearAll); + Button backspaceButton = createButton(tr("Backspace"), "backspaceClicked"); + Button clearButton = createButton(tr("Clear"), "clear"); + Button clearAllButton = createButton(tr("Clear All"), "clearAll"); - Button clearMemoryButton = createButton(tr("MC"), &clearMemory); - Button readMemoryButton = createButton(tr("MR"), &readMemory); - Button setMemoryButton = createButton(tr("MS"), &setMemory); - Button addToMemoryButton = createButton(tr("M+"), &addToMemory); + Button clearMemoryButton = createButton(tr("MC"), "clearMemory"); + Button readMemoryButton = createButton(tr("MR"), "readMemory"); + Button setMemoryButton = createButton(tr("MS"), "setMemory"); + Button addToMemoryButton = createButton(tr("M+"), "addToMemory"); - Button divisionButton = createButton(tr("/"), &multiplicativeOperatorClicked); - Button timesButton = createButton(tr("*"), &multiplicativeOperatorClicked); - Button minusButton = createButton(tr("-"), &additiveOperatorClicked); - Button plusButton = createButton(tr("+"), &additiveOperatorClicked); + Button divisionButton = createButton(tr("/"), "multiplicativeOperatorClicked"); + Button timesButton = createButton(tr("*"), "multiplicativeOperatorClicked"); + Button minusButton = createButton(tr("-"), "additiveOperatorClicked"); + Button plusButton = createButton(tr("+"), "additiveOperatorClicked"); - Button squareRootButton = createButton(tr("Sqrt"), &unaryOperatorClicked); - Button powerButton = createButton(tr("x^2"), &unaryOperatorClicked); - Button reciprocalButton = createButton(tr("1/x"), &unaryOperatorClicked); - Button equalButton = createButton(tr("="), &equalClicked); + Button squareRootButton = createButton(tr("Sqrt"), "unaryOperatorClicked"); + Button powerButton = createButton(tr("x^2"), "unaryOperatorClicked"); + Button reciprocalButton = createButton(tr("1/x"), "unaryOperatorClicked"); + Button equalButton = createButton(tr("="), "equalClicked"); QGridLayout mainLayout = new QGridLayout(); @@ -139,9 +139,9 @@ } //private slots: - void digitClicked() + void slot_digitClicked() { - Button clickedButton = cast(Button) signalSender(); + Button clickedButton = cast(Button) sender(); int digitValue = to!int(clickedButton.text); if (display.text() == "0" && digitValue == 0.0) return; @@ -153,9 +153,9 @@ display.setText(display.text() ~ format("%g", digitValue)); } - void unaryOperatorClicked() + void slot_unaryOperatorClicked() { - Button clickedButton = cast(Button) signalSender(); + Button clickedButton = cast(Button) sender(); string clickedOperator = clickedButton.text(); double operand = to!float(display.text); double result = 0.0; @@ -179,9 +179,9 @@ waitingForOperand = true; } - void additiveOperatorClicked() + void slot_additiveOperatorClicked() { - Button clickedButton = cast(Button) signalSender(); + Button clickedButton = cast(Button) sender(); string clickedOperator = clickedButton.text(); double operand = to!float(display.text); @@ -210,9 +210,9 @@ waitingForOperand = true; } - void multiplicativeOperatorClicked() + void slot_multiplicativeOperatorClicked() { - Button clickedButton = cast(Button) signalSender(); + Button clickedButton = cast(Button) sender(); string clickedOperator = clickedButton.text(); double operand = to!float(display.text); @@ -230,7 +230,7 @@ waitingForOperand = true; } - void equalClicked() + void slot_equalClicked() { double operand = to!float(display.text); @@ -258,7 +258,7 @@ waitingForOperand = true; } - void pointClicked() + void slot_pointClicked() { string text = display.text; @@ -271,7 +271,7 @@ waitingForOperand = false; } - void changeSignClicked() + void slot_changeSignClicked() { string text = display.text(); double value = to!float(text); @@ -284,7 +284,7 @@ display.setText(text); } - void backspaceClicked() + void slot_backspaceClicked() { if (waitingForOperand) return; @@ -299,7 +299,7 @@ } - void clear() + void slot_clear() { if (waitingForOperand) return; @@ -308,7 +308,7 @@ waitingForOperand = true; } - void clearAll() + void slot_clearAll() { sumSoFar = 0.0; factorSoFar = 0.0; @@ -318,24 +318,24 @@ waitingForOperand = true; } - void clearMemory() + void slot_clearMemory() { sumInMemory = 0.0; } - void readMemory() + void slot_readMemory() { display.setText(format("%g", sumInMemory)); waitingForOperand = true; } - void setMemory() + void slot_setMemory() { equalClicked(); sumInMemory = to!float(display.text); } - void addToMemory() + void slot_addToMemory() { equalClicked(); sumInMemory += to!float(display.text); @@ -343,10 +343,10 @@ private: - Button createButton(string text, void delegate() member) + Button createButton(string text, string member) { Button button = new Button(text); - connect!("clicked")(button, member); + connect(button, "clicked", this, member); return button; } @@ -383,4 +383,6 @@ enum { NumDigitButtons = 10 }; Button[NumDigitButtons] digitButtons; + + mixin Q_OBJECT; }
--- a/generator/CMakeLists.txt Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/CMakeLists.txt Sun Feb 07 16:04:36 2010 +0000 @@ -139,21 +139,6 @@ generator.qrc ) -#win32-msvc2005:{ -# QMAKE_CXXFLAGS += -wd4996 -# QMAKE_CFLAGS += -wd4996 -#} - -#if(MSVC) -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm500 /Zc:wchar_t-") -#endif(MSVC) - -#win32-msvc.net { -# QMAKE_CXXFLAGS += /Zm500 -# QMAKE_CXXFLAGS -= -Zm200 -# QMAKE_CFLAGS -= -Zm200 -#} - ## Includes path. set(inc_paths ${CMAKE_CURRENT_SOURCE_DIR}/../common
--- a/generator/abstractmetalang.cpp Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/abstractmetalang.cpp Sun Feb 07 16:04:36 2010 +0000 @@ -42,6 +42,7 @@ #include "abstractmetalang.h" #include "reporthandler.h" #include "jumptable.h" +#include <iostream> /******************************************************************************* * AbstractMetaType @@ -225,6 +226,10 @@ returned += arg->type()->name().replace("[]", "_3").replace(".", "_"); } } + + if(this->isConstant()) + returned += "_const"; + return returned; } @@ -253,6 +258,11 @@ result |= EqualAttributes; } + // Constness + if (isConstant() == other->isConstant()) { + result |= EqualConstness; + } + // Compare types AbstractMetaType *t = type(); AbstractMetaType *ot = other->type(); @@ -668,15 +678,15 @@ return QString(); } -QString AbstractMetaFunction::minimalSignature() const +QString AbstractMetaFunction::minimalSignature(int reduce) const { - if (!m_cached_minimal_signature.isEmpty()) + if (!m_cached_minimal_signature.isEmpty() && !reduce) return m_cached_minimal_signature; QString minimalSignature = originalName() + "("; AbstractMetaArgumentList arguments = this->arguments(); - - for (int i=0; i<arguments.count(); ++i) { + int argsCount = arguments.count() - reduce; + for (int i=0; i<argsCount; ++i) { AbstractMetaType *t = arguments.at(i)->type(); if (i > 0) @@ -689,7 +699,8 @@ minimalSignature += "const"; minimalSignature = QMetaObject::normalizedSignature(minimalSignature.toLocal8Bit().constData()); - m_cached_minimal_signature = minimalSignature; + if(!reduce) + m_cached_minimal_signature = minimalSignature; return minimalSignature; } @@ -1192,7 +1203,19 @@ return 0; } +AbstractMetaFunction* AbstractMetaClass::copyConstructor() const +{ + AbstractMetaFunctionList ctors = queryFunctions(Constructors); + for(int i = 0; i < ctors.size(); i++) + { + AbstractMetaFunction *ctor = ctors.at(i); + if (ctor->arguments().size() > 0) + if(ctor->arguments().at(0)->type()->typeEntry() == typeEntry()) + return ctor; + } + return NULL; +} static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) { @@ -1891,10 +1914,13 @@ if (isConstant()) minimalSignature += "const "; minimalSignature += typeEntry()->qualifiedCppName(); - if (hasInstantiations()) { + if (hasInstantiations() && + (static_cast<const ContainerTypeEntry *>(typeEntry()))->type() != ContainerTypeEntry::StringListContainer) + { QList<AbstractMetaType *> instantiations = this->instantiations(); minimalSignature += "<"; - for (int i=0;i<instantiations.size();++i) { + for (int i=0;i<instantiations.size();++i) + { if (i > 0) minimalSignature += ","; minimalSignature += instantiations.at(i)->minimalSignature();
--- a/generator/abstractmetalang.h Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/abstractmetalang.h Sun Feb 07 16:04:36 2010 +0000 @@ -406,10 +406,11 @@ EqualReturnType = 0x00000010, EqualDefaultValueOverload = 0x00000020, EqualModifiedName = 0x00000040, + EqualConstness = 0x00000080, NameLessThan = 0x00001000, - PrettySimilar = EqualName | EqualArguments, + PrettySimilar = EqualName | EqualArguments | EqualConstness, Equal = 0x0000001f, NotEqual = 0x00001000 }; @@ -440,7 +441,7 @@ QString modifiedName() const; - QString minimalSignature() const; + QString minimalSignature(int reduce = 0) const; QStringList possibleIntrospectionCompatibleSignatures() const; QString marshalledName(bool classIsOwner = true) const; @@ -713,6 +714,7 @@ bool hasSignal(const AbstractMetaFunction *f) const; bool hasConstructors() const; + AbstractMetaFunction *copyConstructor() const; void addDefaultConstructor(); @@ -845,6 +847,7 @@ bool isTypeAlias() const { return m_is_type_alias; } const QStringList &depends() { return m_type_entry->depends(); } + AbstractMetaFunctionList allFunctions() const { return m_functions; } bool needsConversionFunc; private: @@ -969,4 +972,12 @@ | NotRemovedFromTargetLang); } +inline bool isNativeContainer(AbstractMetaType *argumentType) +{ + if (argumentType && argumentType->isContainer()) + if (((const ContainerTypeEntry *)argumentType->typeEntry())->isQList()) + return true; + return false; +} + #endif // ABSTRACTMETALANG_H
--- a/generator/cppheadergenerator.cpp Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/cppheadergenerator.cpp Sun Feb 07 16:04:36 2010 +0000 @@ -197,6 +197,9 @@ // << " void *qt_metacast(const char *);" << endl // << " QT_TR_FUNCTIONS" << end << " virtual int qt_metacall(QMetaObject::Call, int, void **);" << endl + << " int __override_qt_metacall(QMetaObject::Call _c, int _id, void **_a);" << endl + << " virtual const QMetaObject *metaObject() const;" << endl + << "private:" << endl; }
--- a/generator/cppimplgenerator.cpp Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/cppimplgenerator.cpp Sun Feb 07 16:04:36 2010 +0000 @@ -505,13 +505,11 @@ "(pf" << function->marshalledName() << "_dispatch) virts[" << pos << "];" << endl; } } - // D-side signal callbacks - AbstractMetaFunctionList signal_funcs = signalFunctions(java_class); - for(int i = 0; i < signal_funcs.size(); i++) - s << " emit_callbacks_" << java_class->name() << "[" << i << "] = (EmitCallback)" - "sigs[" << i << "];" << endl; - + if (java_class->isQObject()) { + s << " qtd_" << java_class->name() << "_qt_metacall_dispatch = (QtMetacallCallback)sigs[0];" << endl + << " qtd_" << java_class->name() << "_metaObject_dispatch = (MetaObjectCallback)sigs[1];" << endl; + } s << "}" << endl; } @@ -592,9 +590,10 @@ if (!java_class->isQObject()) writeFinalDestructor(s, java_class); - if (java_class->isQObject()) + if (java_class->isQObject()) { + writeQObjectEntity(s, java_class); writeSignalsHandling(s, java_class); - + } if (shellClass) { foreach (AbstractMetaFunction *function, java_class->functions()) { if (function->isConstructor() && !function->isPrivate()) @@ -709,6 +708,9 @@ */ // qtd writeJavaLangObjectOverrideFunctions(s, java_class); + if (java_class->typeEntry()->isValue()) + writeValueFunctions(s, java_class); + if (java_class->isQObject()) { s << endl << endl @@ -717,11 +719,42 @@ << "}" << endl; } + if (java_class->typeEntry()->isValue()) + { + if (!java_class->typeEntry()->hasPrivateCopyConstructor()) // can do a copy if we have a public ctor or don't have any + { + QString argName = "orig"; + s << endl << endl + << "extern \"C\" DLL_PUBLIC void qtd_" << java_class->name() << "_placed_copy(void* " + << argName << ", void* place) {" << endl + << QString(" const %1& __qt_%2 = (const %1& ) *(%1 *)%2;").arg(shellClassName(java_class)).arg(argName) << endl + << QString(" %1 *result = new (place) %1 (__qt_%2);").arg(java_class->qualifiedCppName()).arg(argName) << endl; +// writeFinalConstructor(s, ctor, "result", "original", "(place)"); + s << "}"; + + s << endl << endl + << "extern \"C\" DLL_PUBLIC void* qtd_" << java_class->name() << "_native_copy(void* " << argName << ") {" << endl + << QString(" const %1& __qt_%2 = (const %1& ) *(%1 *)%2;").arg(shellClassName(java_class)).arg(argName) << endl + << QString(" %1 *result = new %1 (__qt_%2);").arg(java_class->qualifiedCppName()).arg(argName) << endl + << " return result;" << endl; + s << "}"; + } + } + s << endl << endl; priGenerator->addSource(java_class->package(), fileNameForClass(java_class)); } +void CppImplGenerator::writeValueFunctions(QTextStream &s, const AbstractMetaClass *java_class) +{ + s << QString("extern \"C\" DLL_PUBLIC bool qtd_%1_QTypeInfo_isComplex() { return (bool) QTypeInfo<%2>::isComplex; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); + s << QString("extern \"C\" DLL_PUBLIC bool qtd_%1_QTypeInfo_isStatic() { return (bool) QTypeInfo<%2>::isStatic; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); + s << QString("extern \"C\" DLL_PUBLIC bool qtd_%1_QTypeInfo_isLarge() { return (bool) QTypeInfo<%2>::isLarge; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); + s << QString("extern \"C\" DLL_PUBLIC bool qtd_%1_QTypeInfo_isPointer() { return (bool) QTypeInfo<%2>::isPointer; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); + s << QString("extern \"C\" DLL_PUBLIC bool qtd_%1_QTypeInfo_isDummy() { return (bool) QTypeInfo<%2>::isDummy; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); +} + void CppImplGenerator::writeVirtualDispatchFunction(QTextStream &s, const AbstractMetaFunction *function, bool d_export) { uint options2 = ReturnType | ExternC; @@ -782,27 +815,35 @@ s << INDENT << f_type->typeEntry()->qualifiedCppName() << " __d_return_value;" << endl; if (f_type->isContainer()) - s << INDENT << "void* __d_return_value;" << endl - << INDENT << "size_t __d_return_value_size;" << endl; + { + if (isNativeContainer(f_type)) + { + s << INDENT; + writeTypeInfo(s, f_type, ForceValueType); + s << "__d_return_value;" << endl; + } + else + s << INDENT << "void* __d_return_value;" << endl + << INDENT << "size_t __d_return_value_size;" << endl; + } } AbstractMetaArgumentList arguments = function->arguments(); foreach (AbstractMetaArgument *argument, arguments) { if (!function->argumentRemoved(argument->argumentIndex()+1)) { - if (!argument->type()->isPrimitive() + AbstractMetaType *atype = argument->type(); + if (!atype->isPrimitive() || !function->conversionRule(TypeSystem::NativeCode, argument->argumentIndex()+1).isEmpty()) { - if(argument->type()->isContainer()) { + if(atype->isContainer()) { QString arg_name = argument->indexedName(); - s << INDENT << QString("DArray %1_arr;").arg(arg_name) << endl - << INDENT << QString("DArray *__d_%1 = &%1_arr;").arg(arg_name); - - writeQtToJava(s, - argument->type(), - arg_name, - "__d_" + arg_name, - function, - argument->argumentIndex() + 1, - Option(VirtualDispatch)); + if(!isNativeContainer(atype)) + writeQtToJava(s, + argument->type(), + arg_name, + "__d_" + arg_name, + function, + argument->argumentIndex() + 1, + Option(VirtualDispatch)); } } } @@ -838,9 +879,13 @@ if (f_type->isTargetLangString()) s << ", &ret_str"; if (f_type->name() == "QModelIndex" || f_type->typeEntry()->isStructInD()) - s << ", &__d_return_value"; - if (f_type->isContainer()) - s << ", &__d_return_value, &__d_return_value_size"; + s << ", &__d_return_value"; // TODO should both be refactored into isNativeType function + if (f_type->isContainer()) { + if ( ((const ContainerTypeEntry *)f_type->typeEntry())->isQList() ) + s << ", &__d_return_value"; + else + s << ", &__d_return_value, &__d_return_value_size"; + } } if (function->arguments().size() > 0) @@ -862,9 +907,14 @@ s << INDENT << "return __d_return_value;" << endl; if (f_type->isContainer()) { - writeJavaToQt(s, f_type, "__qt_return_value", "__d_return_value", - function, 0, GlobalRefJObject); - s << INDENT << "return __qt_return_value;" << endl; + if (isNativeContainer(f_type)) + s << INDENT << "return __d_return_value;" << endl; + else + { + writeJavaToQt(s, f_type, "__qt_return_value", "__d_return_value", + function, 0, GlobalRefJObject); + s << INDENT << "return __qt_return_value;" << endl; + } } if (f_type->isTargetLangString()) @@ -898,8 +948,16 @@ else if(ret_type->typeEntry()->isStructInD()) s << ", " << ret_type->typeEntry()->qualifiedCppName() << " *__d_return_value"; - if (ret_type->isContainer()) - s << ", void** __d_arr_ptr, size_t* __d_arr_size"; + if (ret_type->isContainer()) { + if(isNativeContainer(ret_type)) { + if(d_export) + s << ", " << DGenerator::translateType(ret_type, d_function->ownerClass(), NoOption) << "* __d_arr"; + else + s << ", void * __d_arr"; + } + else + s << ", void** __d_arr_ptr, size_t* __d_arr_size"; + } } if (d_function->arguments().size() > 0) @@ -919,9 +977,11 @@ if (d_type->name() == "QModelIndex") s << "QModelIndexAccessor" << QString(d_type->actualIndirections(), '*') << " " << arg_name; else if (d_type->isContainer()) { - if (d_export) { + if ( isNativeContainer(d_type) ) + s << "void* "; + else if (d_export) s << DGenerator::translateType(d_type, d_function->ownerClass(), NoOption) << "* "; - } else + else s << "DArray* "; s << arg_name; } else if (d_type->typeEntry()->isStructInD()) @@ -1217,22 +1277,21 @@ << "{" << endl << "public:" << endl << " Q_OBJECT_CHECK" << endl - << " virtual int qt_metacall(QMetaObject::Call, int, void **);" << endl << endl + << "// virtual int qt_metacall(QMetaObject::Call, int, void **);" << endl << endl << " " << entityName << "(QObject *qObject, void *dId) : QObject(), QtD_QObjectEntity(qObject, dId) {}" << endl << "};" << endl << endl; - // QObject_Link::qt_metacall() +/* // QObject_Link::qt_metacall() s << "int " << entityName << "::qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl << "{" << endl << " _id = QObject::qt_metacall(_c, _id, _a);" << endl << " if (_id < 0 || _c != QMetaObject::InvokeMetaMethod)" << endl << " return _id;" << endl -// << " Q_ASSERT(_id < 2);" << endl << " emit_callbacks_" << java_class->name() << "[_id](dId, _a);" << endl << " return -1;" << endl << "}" << endl << endl; - +*/ s << "extern \"C\" DLL_PUBLIC void qtd_" << className << "_createEntity(void *nativeId, void* dId)" << endl << "{" << endl << " new " << entityName << "((QObject*)nativeId, dId);" << endl @@ -1282,16 +1341,44 @@ << " return " << java_class->qualifiedCppName() << "::qt_metacast(_clname);" << endl << "}" << endl << endl; */ - +/* s << "int " << shellClassName(java_class) << "::qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl - << "{" << endl; - - s << " _id = " << java_class->qualifiedCppName() << "::qt_metacall(_c, _id, _a);" << endl + << "{" << endl + << " _id = " << java_class->qualifiedCppName() << "::qt_metacall(_c, _id, _a);" << endl << " if (_id < 0 || _c != QMetaObject::InvokeMetaMethod)" << endl << " return _id;" << endl << " emit_callbacks_" << java_class->name() << "[_id](this->dId, _a);" << endl << " return -1;" << endl << "}" << endl << endl; + */ + + if(cpp_shared) + s << "MetaObjectCallback qtd_" << java_class->name() << "_metaObject_dispatch;" << endl + << "QtMetacallCallback qtd_" << java_class->name() << "_qt_metacall_dispatch;" << endl; + else + s << "extern \"C\" const QMetaObject* qtd_" << java_class->name() << "_metaObject_dispatch(void *d_entity);" << endl + << "extern \"C\" int qtd_" << java_class->name() << "_qt_metacall_dispatch(void *d_entity, QMetaObject::Call _c, int _id, void **_a);" << endl; + + s << endl + << "const QMetaObject * " << shellClassName(java_class) << "::metaObject() const" << endl + << "{" << endl + << " return qtd_" << java_class->name() << "_metaObject_dispatch(this->dId);" << endl + << "}" << endl << endl + << "int " << shellClassName(java_class) << "::qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl + << "{" << endl + << " return qtd_" << java_class->name() << "_qt_metacall_dispatch(this->dId, _c, _id, _a);" << endl + << "}" << endl << endl + + << "int " << shellClassName(java_class) << "::__override_qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl + << "{" << endl + << " return " << java_class->qualifiedCppName() << "::qt_metacall(_c, _id, _a);" + << "}" << endl << endl + + << "extern \"C\" DLL_PUBLIC int qtd_" << java_class->name() << "_qt_metacall(void* __this_nativeId, QMetaObject::Call _c, int _id, void **_a)" + << "{" << endl + << " " << shellClassName(java_class) << " *__qt_this = (" << shellClassName(java_class) << " *) __this_nativeId;" << endl + << " return __qt_this->__override_qt_metacall(_c, _id, _a);" << endl + << "}" << endl << endl; } void CppImplGenerator::writeSignalEmitter(QTextStream &s, const AbstractMetaClass *d_class, AbstractMetaFunction *function) @@ -1341,6 +1428,8 @@ void CppImplGenerator::writeSignalsHandling(QTextStream &s, const AbstractMetaClass *java_class) { + return; // #TODO probably don't need this function at all + s << "extern \"C\" typedef void (*EmitCallback)(void*, void**);" << endl; AbstractMetaFunctionList signal_funcs = signalFunctions(java_class); @@ -1369,8 +1458,6 @@ } s << endl << "};" << endl << endl; } - - writeQObjectEntity(s, java_class); } @@ -1934,8 +2021,10 @@ } else if (d_type->isContainer()) { const ContainerTypeEntry *cte = static_cast<const ContainerTypeEntry *>(te); - if(isLinearContainer(cte)) - s << QString("void *%1, size_t %1_size").arg(arg_name); + if(cte->isQList()) + s << "void* " << arg_name; + else if(isLinearContainer(cte)) + s << "DArray* " << arg_name; } else { if (!d_type->hasNativeId()) { if(d_type->isVariant()) { @@ -2298,19 +2387,22 @@ { if (cls->hasConstructors()) { s << INDENT << "extern \"C\" DLL_PUBLIC void qtd_" << cls->name() << "_destructor(void *ptr)" << endl - << INDENT << "{" << endl; - { - s << INDENT << "delete (" << shellClassName(cls) << " *)ptr;" << endl; - } - - s << INDENT << "}" << endl << endl; + << INDENT << "{" << endl + << INDENT << " delete (" << shellClassName(cls) << " *)ptr;" << endl + << INDENT << "}" << endl << endl; + + s << INDENT << "extern \"C\" DLL_PUBLIC void qtd_" << cls->name() << "_call_destructor(" << shellClassName(cls) << " *ptr)" << endl + << INDENT << "{" << endl + << INDENT << " call_destructor(ptr);" << endl + << INDENT << "}" << endl << endl; } } void CppImplGenerator::writeFinalConstructor(QTextStream &s, const AbstractMetaFunction *java_function, const QString &qt_object_name, - const QString &java_object_name) + const QString &java_object_name, + const QString &place) { const AbstractMetaClass *cls = java_function->ownerClass(); AbstractMetaArgumentList arguments = java_function->arguments(); @@ -2319,7 +2411,7 @@ bool hasShellClass = cls->generateShellClass(); s << INDENT << shellClassName(cls) << " *" << qt_object_name - << " = new " << shellClassName(cls) + << " = new " << place << shellClassName(cls) << "("; writeFunctionCallArguments(s, java_function, "__qt_"); s << ");" << endl; @@ -3139,9 +3231,7 @@ const ContainerTypeEntry *type = static_cast<const ContainerTypeEntry *>(java_type->typeEntry()); - if (type->type() == ContainerTypeEntry::ListContainer - || type->type() == ContainerTypeEntry::VectorContainer - || type->type() == ContainerTypeEntry::StringListContainer + if (type->type() == ContainerTypeEntry::VectorContainer || type->type() == ContainerTypeEntry::LinkedListContainer || type->type() == ContainerTypeEntry::StackContainer || type->type() == ContainerTypeEntry::SetContainer @@ -3154,7 +3244,6 @@ cls_name.remove("_ConcreteWrapper"); s << endl -// << INDENT << "{" << endl // qtd2 hack, additional scope for avoiding duplicating of "i" << INDENT; switch (type->type()) { @@ -3202,7 +3291,14 @@ s << INDENT << "++" << index << ";" << endl; } s << INDENT << "}" << endl; -// << INDENT << "}" << endl; + + } else if (type->isQList()) { +// QList<QObject*> & list2 = (*(QList<QObject*> *)nativeId); + writeTypeInfo(s, java_type, ForceValueType); + s << "&" << java_name << "_tmp = (*("; + writeTypeInfo(s, java_type, ForceValueType); + s << "*)" << java_name << ");" << endl + << INDENT << java_name << "_tmp = " << qt_name << ";" << endl; } else if (type->type() == ContainerTypeEntry::PairContainer) { QList<AbstractMetaType *> args = java_type->instantiations(); @@ -3329,9 +3425,7 @@ const ContainerTypeEntry *type = static_cast<const ContainerTypeEntry *>(java_type->typeEntry()); - if (type->type() == ContainerTypeEntry::ListContainer - || type->type() == ContainerTypeEntry::VectorContainer - || type->type() == ContainerTypeEntry::StringListContainer + if (type->type() == ContainerTypeEntry::VectorContainer || type->type() == ContainerTypeEntry::LinkedListContainer || type->type() == ContainerTypeEntry::StackContainer || type->type() == ContainerTypeEntry::SetContainer @@ -3345,23 +3439,17 @@ writeTypeInfo(s, java_type, ForceValueType); s << qt_name << ";" << endl; -// qtd s << INDENT << "if (" << java_name << " != 0) {" << endl; { -/* qtd Indentation indent(INDENT); - s << INDENT << "jobjectArray __qt__array = qtjambi_collection_toArray(__jni_env, " - << java_name << ");" << endl - << INDENT << "jsize __qt__size = __jni_env->GetArrayLength(__qt__array);" << endl; -*/ if (type->type() == ContainerTypeEntry::VectorContainer || type->type() == ContainerTypeEntry::StackContainer) - s << INDENT << qt_name << ".reserve(" << java_name << "_size);" << endl; - - s << INDENT << "for (int i=0; i<" << java_name << "_size; ++i) {" << endl; + s << INDENT << qt_name << ".reserve(" << java_name << "->length);" << endl; + + s << INDENT << "for (int i=0; i<" << java_name << "->length; ++i) {" << endl; { Indentation indent(INDENT); if(targ->isTargetLangString()) s << INDENT << "DArray __d_element;" << endl - << INDENT << "qtd_get_string_from_array(" << java_name << ", i, &__d_element);" << endl; + << INDENT << "qtd_get_string_from_array(" << java_name << "->ptr, i, &__d_element);" << endl; else { s << INDENT; writeTypeInfo(s, targ, Option(VirtualDispatch | ForcePointer | EnumAsInts)); @@ -3372,8 +3460,6 @@ s << "__d_element;" << endl << INDENT << "qtd_get_" << elem_type << "_from_array(" << java_name << ", i, &__d_element);" << endl; } -/* qtd s << INDENT << "jobject __d_element = " - << "__jni_env->GetObjectArrayElement(__qt__array, i);" << endl;*/ writeJavaToQt(s, targ, "__qt_element", "__d_element", 0, -1, BoxedPrimitive); QString cont_element = "__qt_element"; if(targ->typeEntry()->isStructInD() && targ->name() != "QModelIndex") @@ -3383,6 +3469,11 @@ // qtd s << INDENT << "}" << endl; } s << INDENT << "}" << endl; + } else if (type->isQList()) { + writeTypeInfo(s, java_type, ForceValueType); + s << qt_name << " = (*("; + writeTypeInfo(s, java_type, ForceValueType); + s << "*)" << java_name << ");" << endl; } else if (type->type() == ContainerTypeEntry::PairContainer) { QList<AbstractMetaType *> targs = java_type->instantiations(); Q_ASSERT(targs.size() == 2); @@ -3548,7 +3639,10 @@ if ( (options & VirtualDispatch) && a_type->isContainer()) { - s << "__d_" << argument->indexedName(); + if ( ((const ContainerTypeEntry *)a_type->typeEntry())->isQList() ) + s << "(void*)&" << argument->indexedName(); + else + s << "__d_" << argument->indexedName(); continue; } @@ -3722,3 +3816,4 @@ s << endl << endl; } } +
--- a/generator/cppimplgenerator.h Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/cppimplgenerator.h Sun Feb 07 16:04:36 2010 +0000 @@ -109,7 +109,8 @@ void writeFinalConstructor(QTextStream &s, const AbstractMetaFunction *java_function, const QString &qt_object_name, - const QString &java_object_name); + const QString &java_object_name, + const QString &place = ""); void writeQObjectFunctions(QTextStream &s, const AbstractMetaClass *java_class); void writeFunctionCall(QTextStream &s, const QString &variable_name, @@ -215,6 +216,7 @@ static void writeInitCallbacks(QTextStream &s, const AbstractMetaClass *java_class); static void writeQtdEntityFunction(QTextStream &s, const AbstractMetaClass *java_class); void writeRefArguments(QTextStream &s, const AbstractMetaFunction *java_function); + void writeValueFunctions(QTextStream &s, const AbstractMetaClass *java_class); private: void writeDefaultConstructedValues_helper(QSet<QString> &values,
--- a/generator/dgenerator.cpp Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/dgenerator.cpp Sun Feb 07 16:04:36 2010 +0000 @@ -63,14 +63,14 @@ m_recursive(0), m_isRecursive(false) { - excludedTypes << "long long" << "bool" << "int" << "QString" << "char" << "WId" + excludedTypes << "qint64" << "bool" << "int" << "QString" << "char" << "WId" << "unsigned char" << "uint" << "double" << "short" << "float" << "signed char" << "unsigned short" << "QBool" << "unsigned int" << "Qt::HANDLE" << "QChar" << "java.lang.JObjectWrapper" << "void" << "QLatin1String" << "unsigned long long" << "signed int" << "signed short" << "Array" << "GLuint" << "GLenum" << "GLint" << "unsigned long" << "ulong" << "long" << "QByteRef" - << "QStringList" << "QList" << "QVector" << "QPair" + << "QStringList" << "QVector" << "QPair" << "QSet" << "QStringRef" << "quintptr"; } @@ -126,7 +126,7 @@ QString constPrefix, constPostfix; if (d_type && d_type->isConstant() && dVersion == 2) { constPrefix = "const("; - constPostfix = ") "; + constPostfix = ")"; } if (!d_type) { @@ -176,9 +176,14 @@ if ((option & SkipTemplateParameters) == 0) { QList<AbstractMetaType *> args = d_type->instantiations(); - - if (args.size() == 1) // QVector or QList - s = translateType(args.at(0), context, BoxedPrimitive) + "[]"; + const ContainerTypeEntry *cte = + static_cast<const ContainerTypeEntry *>(d_type->typeEntry()); + if (args.size() == 1) { // QVector or QList + if(cte->isQList()) + s = "QList!(" + translateType(args.at(0), context, BoxedPrimitive) + ")"; + else + s = translateType(args.at(0), context, BoxedPrimitive) + "[]"; + } else if(args.size() == 2) { // all sorts of maps s = translateType(args.at(1), context, BoxedPrimitive); // value bool isMultiMap = static_cast<const ContainerTypeEntry *>(d_type->typeEntry())->type() == ContainerTypeEntry::MultiMapContainer; @@ -230,7 +235,7 @@ QString arg; AbstractMetaType *type = d_argument->type(); - // if argument is "QString &" ref attribute needed + // qtd2 if argument is "QString &" ref attribute needed FIXME maybe we need this not only for QString, but for other Value types?? if (type->typeEntry()->isValue() && type->isNativePointer() && type->typeEntry()->name() == "QString") arg = "ref "; @@ -589,7 +594,10 @@ if (!d_function->argumentRemoved(i+1)) { TypeSystem::Ownership owner = d_function->ownership(d_function->implementingClass(), TypeSystem::TargetLangCode, i+1); if (owner != TypeSystem::InvalidOwnership) { - s << INDENT << "if (" << arg->argumentName() << " !is null) {" << endl; + QString empty_condition = " !is null"; + if (arg->type()->isContainer()) + empty_condition = ".length != 0"; + s << INDENT << "if (" << arg->argumentName() << empty_condition << ") {" << endl; { Indentation indent(INDENT); if (arg->type()->isContainer()) @@ -645,7 +653,7 @@ i == 0 ? -1 : i); foreach (ReferenceCount refCount, referenceCounts) - writeReferenceCount(s, refCount, i == 0 ? "this" : arguments.at(i-1)->argumentName()); + writeReferenceCount(s, refCount, i == 0 ? "this" : arguments.at(i-1)->argumentName(), arguments.at(i-1)->type()); } referenceCounts = d_function->referenceCounts(d_function->implementingClass(), 0); @@ -679,7 +687,14 @@ s << INDENT << return_type->name() << " res;" << endl; if(return_type->isContainer()) - s << INDENT << this->translateType(d_function->type(), d_function->ownerClass(), NoOption) << " res;" << endl; + { + const ContainerTypeEntry *type = + static_cast<const ContainerTypeEntry *>(return_type->typeEntry()); + if(type->isQList()) // QList is a native type now + s << INDENT << "auto res = " << this->translateType(d_function->type(), d_function->ownerClass(), NoOption) << ".opCall();" << endl; + else + s << INDENT << this->translateType(d_function->type(), d_function->ownerClass(), NoOption) << " res;" << endl; + } } // returning string or a struct @@ -812,7 +827,7 @@ const ContainerTypeEntry *cte = static_cast<const ContainerTypeEntry *>(te); if(isLinearContainer(cte)) - s << QString("%1.ptr, %1.length").arg(arg_name); + s << QString("&%1").arg(arg_name); } else if (type->typeEntry()->qualifiedCppName() == "QChar") { s << arg_name; } else if (type->isTargetLangString() || (te && te->qualifiedCppName() == "QString")) { @@ -882,7 +897,7 @@ // return value marschalling if(return_type) { - if (!returnImmediately && !d_function->storeResult()) { + if (!returnImmediately) { s << INDENT; QString modified_type = d_function->typeReplaced(0); if (modified_type.isEmpty()) @@ -908,12 +923,7 @@ s << "new " << return_type->name() << "(ret, QtdObjectFlags.nativeOwnership);" << endl; if (return_type->isObject()) { - if(d_function->storeResult()) - s << INDENT << QString("__m_%1.__nativeId = ret;").arg(d_function->name()) << endl - << INDENT << QString("return __m_%1;").arg(d_function->name()) << endl; - else - s << "qtd_" << return_type->name() << "_from_ptr(ret);" << endl; - s << endl; + s << "qtd_" << return_type->name() << "_from_ptr(ret);" << endl << endl; } if (return_type->isArray()) { @@ -921,10 +931,10 @@ } foreach (ReferenceCount referenceCount, referenceCounts) { - writeReferenceCount(s, referenceCount, "__d_return_value"); + writeReferenceCount(s, referenceCount, "__d_return_value", return_type); } - if (!returnImmediately && !d_function->storeResult()) + if (!returnImmediately) s << INDENT << "return __d_return_value;" << endl; } writeInjectedCode(s, d_function, CodeSnip::End); @@ -983,14 +993,14 @@ if (!(d_function->isEmptyFunction() || d_function->isNormal() || d_function->isSignal())) option = Option(option | SkipReturnType); writeFunctionAttributes(s, d_function, included_attributes, excluded_attributes, option); -/* - if(d_function->isSignal()) - functionName += "_emit"; -*/ + s << functionName << "("; writeFunctionArguments(s, d_function, argument_count, option); s << ")"; + if(d_function->isConstant()) + s << " const"; + return result; } @@ -1011,7 +1021,7 @@ } void DGenerator::writeReferenceCount(QTextStream &s, const ReferenceCount &refCount, - const QString &argumentName) + const QString &argumentName, AbstractMetaType *argumentType) { if (refCount.action == ReferenceCount::Ignore) return; @@ -1021,9 +1031,13 @@ s << INDENT << "auto __rcTmp = " << refCountVariableName << ";" << endl; refCountVariableName = "__rcTmp"; } + QString empty_condition = " !is null"; + if (argumentType && argumentType->isContainer()) +// if (((const ContainerTypeEntry *)argumentType->typeEntry())->isQList()) + empty_condition = ".length != 0"; if (refCount.action != ReferenceCount::Set) { - s << INDENT << "if (" << argumentName << " !is null"; + s << INDENT << "if (" << argumentName << empty_condition; if (!refCount.conditional.isEmpty()) s << " && " << refCount.conditional; @@ -1037,12 +1051,15 @@ { Indentation indent(INDENT); + QString summand = argumentName; switch (refCount.action) { case ReferenceCount::Add: s << INDENT << refCountVariableName << " ~= cast(Object) " << argumentName << ";" << endl; break; case ReferenceCount::AddAll: - s << INDENT << refCountVariableName << " ~= " << argumentName << ";" << endl; + if(isNativeContainer(argumentType)) + summand = argumentName + ".toArray()"; + s << INDENT << refCountVariableName << " ~= " << summand << ";" << endl; break; case ReferenceCount::Remove: s << INDENT << "remove(" << refCountVariableName @@ -1697,6 +1714,20 @@ } s << INDENT << "}" << endl << endl; } + + if (d_class->typeEntry()->isValue()) + { + s << INDENT << "public static void __deleteNativeObject(void* ptr) {" << endl + << INDENT << " qtd_" << d_class->name() << "_destructor(ptr);" << endl + << INDENT << "}" << endl << endl; + } + + if (d_class->typeEntry()->isValue()) + { + s << INDENT << "public static void __callNativeDestructor(void* ptr) {" << endl + << INDENT << " qtd_" << d_class->name() << "_call_destructor(ptr);" << endl + << INDENT << "}" << endl << endl; + } } void DGenerator::writeFlagsSetter(QTextStream &s, const AbstractMetaClass *d_class) @@ -1713,12 +1744,12 @@ QString attr; +// return; // #TODO Don't need handlers for now. Restore in conversion functions later + s << "// signal handlers" << endl; foreach(AbstractMetaFunction *signal, signal_funcs) { QString sigExternName = signalExternName(d_class, signal); - s << "private " << attr << "extern(C) void " << sigExternName << "_connect(void* native_id);" << endl; - s << "private " << attr << "extern(C) void " << sigExternName << "_disconnect(void* native_id);" << endl; /* QString extra_args; @@ -1733,7 +1764,7 @@ */ AbstractMetaArgumentList arguments = signal->arguments(); - s << "private extern(C) void " << sigExternName << "_handle(void* d_entity, void** args) {" << endl; + s << "/*private extern(C) void " << sigExternName << "_handle(void* d_entity, void** args) {" << endl; { Indentation indent(INDENT); s << INDENT << "auto d_object = cast(" << d_class->name() << ") d_entity;" << endl; @@ -1752,7 +1783,7 @@ << INDENT << cppContainerConversionName(d_class, type, FromCpp) << "(" << arg_ptr << ", &" << arg_name << ");" << endl; } else if (type->isTargetLangString()) { s << INDENT << "auto " << arg_name << "_ptr = " << arg_ptr << ";" << endl - << INDENT << "string " << arg_name << " = QString.toNativeString(" << arg_name << "_ptr);"; + << INDENT << "string " << arg_name << " = QStringUtil.toNativeString(" << arg_name << "_ptr);"; } else if(type->isPrimitive() || type->isEnum() || type->isFlags() || type->typeEntry()->isStructInD()) { QString type_name = argument->type()->typeEntry()->qualifiedTargetLangName(); if (type->isFlags()) @@ -1771,7 +1802,7 @@ s << endl; } // s << INDENT << "Stdout(\"" << d_class->name() << "\", \"" << signal->name() << "\").newline;" << endl; - s << INDENT << "d_object." << signal->name() << "_emit("; + s << INDENT << "//d_object." << signal->name() << "_emit("; for (int j = 0; j<sz; ++j) { AbstractMetaArgument *argument = arguments.at(j); QString arg_name = argument->indexedName(); @@ -1782,10 +1813,33 @@ s << ");" << endl; } - s << "}" << endl; + s << "}*/" << endl; } } +AbstractMetaFunctionList DGenerator::generatedClassFunctions(const AbstractMetaClass *d_class) +{ + AbstractMetaFunctionList r; + AbstractMetaFunctionList d_funcs = d_class->functionsInTargetLang(); + for (int i=0; i<d_funcs.size(); ++i) { + AbstractMetaFunction *function = d_funcs.at(i); + + // If a method in an interface class is modified to be private, this should + // not be present in the interface at all, only in the implementation. + if (d_class->isInterface()) { + uint includedAttributes = 0; + uint excludedAttributes = 0; + retrieveModifications(function, d_class, &excludedAttributes, &includedAttributes); + if (includedAttributes & AbstractMetaAttributes::Private) + continue; + } + + if (!notWrappedYet(function)) // qtd2 + r += function; + } + return r; +} + void DGenerator::write(QTextStream &s, const AbstractMetaClass *d_class) { ReportHandler::debugSparse("Generating class: " + d_class->fullName()); @@ -1798,12 +1852,12 @@ auxFile.isDone = true; auxFile.stream << "module " << auxModName << ";" << endl << endl; - bool staticInit = d_class->isQObject() || (cpp_shared && d_class->generateShellClass() && !d_class->isInterface()); + bool staticInit = d_class->isQObject() || d_class->typeEntry()->isValue() || (cpp_shared && d_class->generateShellClass() && !d_class->isInterface()); if (staticInit) { auxFile.isDone = false; auxFile.stream << "extern(C) void static_init_" << d_class->name() << "();" << endl; - auxFile.stream << "static this() { static_init_" << d_class->name() << "; }" << endl << endl; + auxFile.stream << "shared static this() { static_init_" << d_class->name() << "; }" << endl << endl; } if (m_docs_enabled) { @@ -1906,9 +1960,11 @@ << "public import qt.core.Qt;" << endl << "private import qt.QtdObject;" << endl << "private import qt.core.QString;" << endl - << "private import qt.qtd.Array;" << endl; + << "private import qt.qtd.Array;" << endl + << "private import qt.core.QList;" << endl; if (d_class->isQObject()) { s << "public import qt.Signal;" << endl + << "public import qt.qtd.MOC;" << endl << "public import qt.core.QMetaObject;" << endl << "public import qt.qtd.Traits;" << endl; @@ -1937,7 +1993,7 @@ if (dPhobos) { s << "import std.stdio;" << endl - << "import std.string;" << endl + << "import std.string : toStringz;" << endl << "import std.utf;" << endl << "import core.memory;" << endl; } @@ -2144,11 +2200,11 @@ } */ - // Enums aliaases + // Enums aliases foreach (AbstractMetaEnum *d_enum, d_class->enums()) writeEnumAlias(s, d_enum); - // Signals + // Signals if (d_class->isQObject()) { AbstractMetaFunctionList signal_funcs = signalFunctions(d_class, false); @@ -2181,22 +2237,13 @@ // Functions AbstractMetaFunctionList d_funcs = d_class->functionsInTargetLang(); - for (int i=0; i<d_funcs.size(); ++i) { - AbstractMetaFunction *function = d_funcs.at(i); - - // If a method in an interface class is modified to be private, this should - // not be present in the interface at all, only in the implementation. - if (d_class->isInterface()) { - uint includedAttributes = 0; - uint excludedAttributes = 0; - retrieveModifications(function, d_class, &excludedAttributes, &includedAttributes); - if (includedAttributes & AbstractMetaAttributes::Private) - continue; - } - - if (!notWrappedYet(function)) // qtd2 - writeFunction(s, function); -// s << function->minimalSignature() << endl; + AbstractMetaFunctionList d_funcs_gen = generatedClassFunctions(d_class); + for (int i=0; i<d_funcs_gen.size(); ++i) { + AbstractMetaFunction *function = d_funcs_gen.at(i); +// if(function->isSlot()) +// writeSlot(s, function); + writeFunction(s, function); +// qtd s << function->minimalSignature() << endl; } if(d_class->isInterface()) s << endl << INDENT << "public void* __ptr_" << d_class->name() << "();" << endl << endl; @@ -2210,39 +2257,47 @@ writeFieldAccessors(s, field); } -/* qtd - - // the static fromNativePointer function... - if (!d_class->isNamespace() && !d_class->isInterface() && !fakeClass) { - s << endl - << INDENT << "public static native " << d_class->name() << " fromNativePointer(" - << "QNativePointer nativePointer);" << endl; - } - - if (d_class->isQObject()) { - s << endl; - if (TypeDatabase::instance()->includeEclipseWarnings()) - s << INDENT << "@SuppressWarnings(\"unused\")" << endl; - - s << INDENT << "private static native long originalMetaObject();" << endl; - } - - // The __qt_signalInitialization() function - if (signal_funcs.size() > 0) { - s << endl - << INDENT << "@Override" << endl - << INDENT << "@QtBlockedSlot protected boolean __qt_signalInitialization(String name) {" << endl - << INDENT << " return (__qt_signalInitialization(nativeId(), name)" << endl - << INDENT << " || super.__qt_signalInitialization(name));" << endl - << INDENT << "}" << endl - << endl - << INDENT << "@QtBlockedSlot" << endl - << INDENT << "private native boolean __qt_signalInitialization(long ptr, String name);" << endl; - } -*/ if (d_class->isQObject()) writeQObjectFunctions(s, d_class); + if (ctype->isObject() && !ctype->isQObject()) // conversion function wrapper to be consistent with QObject + { // some code duplication, remove when there is a better mechanism for Object type conversions + QString class_name = ctype->name(); + QString return_type_name = class_name; + if(ctype->designatedInterface()) + return_type_name = ctype->designatedInterface()->name(); + s << " static " << return_type_name << " __getObject(void* nativeId) {" << endl + << " return qtd_" << class_name << "_from_ptr(nativeId);" << endl + << " }" << endl << endl; + } + + // flag to mark the type of class (to use in templates to convert arguments) + if (d_class->baseClassName().isEmpty()) + { + if (d_class->typeEntry()->isQObject()) + s << INDENT << "public alias void __isQObjectType;" << endl << endl; + else if (d_class->typeEntry()->isObject()) + s << INDENT << "public alias void __isObjectType;" << endl << endl; + else if (d_class->typeEntry()->isValue()) + s << INDENT << "public alias void __isValueType;" << endl << endl; + } + + s << INDENT << "public alias void __isQtType_" << d_class->name() << ";" << endl << endl; + + // construction of a native copy of a Value + if (d_class->typeEntry()->isValue()) + { + AbstractMetaFunction *copy_ctor = d_class->copyConstructor(); + if (!d_class->typeEntry()->hasPrivateCopyConstructor()) // can do a copy if we have a public ctor or don't have any + s << INDENT << "static void* __constructNativeCopy(const void* orig) {" << endl + << INDENT << " return qtd_" << d_class->name() << "_native_copy(orig);" << endl + << INDENT << "}" << endl << endl + + << INDENT << "static void __constructPlacedNativeCopy(const void* orig, void* place) {" << endl + << INDENT << " qtd_" << d_class->name() << "_placed_copy(orig, place);" << endl + << INDENT << "}" << endl << endl; + } + // Add dummy constructor for use when constructing subclasses if (!d_class->isNamespace() && !d_class->isInterface() && !fakeClass) { s << endl @@ -2273,31 +2328,6 @@ } */ - // customized store-result instances - d_funcs = d_class->functionsInTargetLang(); - for (int i=0; i<d_funcs.size(); ++i) { - AbstractMetaFunction *d_function = d_funcs.at(i); - uint included_attributes = 0; - uint excluded_attributes = 0; - setupForFunction(d_function, &included_attributes, &excluded_attributes); - uint attr = d_function->attributes() & (~excluded_attributes) | included_attributes; - bool isStatic = (attr & AbstractMetaAttributes::Static); - - if (!isStatic && (attr & AbstractMetaAttributes::Abstract)) - continue; - - if(d_function->storeResult()) { - QString type_name = d_function->type()->name(); - const ComplexTypeEntry *ctype = static_cast<const ComplexTypeEntry *>(d_function->type()->typeEntry()); - if(ctype->isAbstract()) - type_name = type_name + "_ConcreteWrapper"; - - s << INDENT << " __m_" << d_function->name() << " = new " - << type_name << "(cast(void*)null);" << endl; - if (d_function->type()->isQObject()) - s << INDENT << " __m_" << d_function->name() << ".__setFlags(QtdObjectFlags.nativeOwnership, true);" << endl; - } - } // pointers to native interface objects for classes that implement interfaces // initializing @@ -2314,29 +2344,6 @@ s << INDENT << "}" << endl << endl; -/******************!!!DUPLICATE OF ABOVE!!!*********************/ - for (int i=0; i<d_funcs.size(); ++i) { - AbstractMetaFunction *d_function = d_funcs.at(i); - uint included_attributes = 0; - uint excluded_attributes = 0; - setupForFunction(d_function, &included_attributes, &excluded_attributes); - uint attr = d_function->attributes() & (~excluded_attributes) | included_attributes; - bool isStatic = (attr & AbstractMetaAttributes::Static); - - if (!isStatic && (attr & AbstractMetaAttributes::Abstract)) - continue; - - if(d_function->storeResult()) { - QString type_name = d_function->type()->name(); - const ComplexTypeEntry *ctype = static_cast<const ComplexTypeEntry *>(d_function->type()->typeEntry()); - if(ctype->isAbstract()) - type_name = type_name + "_ConcreteWrapper"; - - s << INDENT << type_name << " __m_" << d_function->name() << ";" << endl; - } - } -/***************************************************************/ - // pointers to native interface objects for classes that implement interfaces // initializing interfaces = d_class->interfaces(); @@ -2352,6 +2359,8 @@ writeDestructor(s, d_class); } + if (d_class->typeEntry()->isValue()) + writeValueFunctions(s, d_class); /* qtd // Add a function that converts an array of the value type to a QNativePointer if (d_class->typeEntry()->isValue() && !fakeClass) { @@ -2387,7 +2396,7 @@ writeCloneFunction(s, d_class); } */ - s << "}" << endl; + s << "}" << endl; // end of class scope /* ---------------- injected free code ----------------*/ const ComplexTypeEntry *class_type = d_class->typeEntry(); @@ -2423,54 +2432,8 @@ s << INDENT << "public this(void* native_id, QtdObjectFlags flags = QtdObjectFlags.nativeOwnership) {" << endl << INDENT << " super(native_id, flags);" << endl << endl; - /******************!!!DUPLICATE!!!*********************/ - d_funcs = d_class->functionsInTargetLang(); - for (int i=0; i<d_funcs.size(); ++i) { - AbstractMetaFunction *d_function = d_funcs.at(i); - uint included_attributes = 0; - uint excluded_attributes = 0; - setupForFunction(d_function, &included_attributes, &excluded_attributes); - uint attr = d_function->attributes() & (~excluded_attributes) | included_attributes; -// qtd bool isStatic = (attr & AbstractMetaAttributes::Static); - - if(d_function->storeResult()) { - QString type_name = d_function->type()->name(); - const ComplexTypeEntry *ctype = static_cast<const ComplexTypeEntry *>(d_function->type()->typeEntry()); - if(ctype->isAbstract()) - type_name = type_name + "_ConcreteWrapper"; - s << INDENT << " __m_" << d_function->name() << " = new " - << type_name << "(cast(void*)null);" << endl; - if (d_function->type()->isQObject()) - s << INDENT << " __m_" << d_function->name() << ".__setFlags(QtdObjectFlags.nativeOwnership, true);" << endl; - } - } - s << INDENT << "}" << endl << endl; - for (int i=0; i<d_funcs.size(); ++i) { - AbstractMetaFunction *d_function = d_funcs.at(i); - uint included_attributes = 0; - uint excluded_attributes = 0; - setupForFunction(d_function, &included_attributes, &excluded_attributes); - uint attr = d_function->attributes() & (~excluded_attributes) | included_attributes; -// qtd bool isStatic = (attr & AbstractMetaAttributes::Static); - - if(d_function->storeResult()) { - QString type_name = d_function->type()->name(); - const ComplexTypeEntry *ctype = static_cast<const ComplexTypeEntry *>(d_function->type()->typeEntry()); - if(ctype->isAbstract()) - type_name = type_name + "_ConcreteWrapper"; - - s << INDENT << d_function->type()->name() << " __m_" << d_function->name() << ";" << endl; - } - } - /***************************************************************/ - - - - - - uint exclude_attributes = AbstractMetaAttributes::Native | AbstractMetaAttributes::Abstract; uint include_attributes = 0; AbstractMetaFunctionList functions = d_class->queryFunctions(AbstractMetaClass::NormalFunctions | AbstractMetaClass::AbstractFunctions | AbstractMetaClass::NonEmptyFunctions | AbstractMetaClass::NotRemovedFromTargetLang); @@ -2478,14 +2441,19 @@ retrieveModifications(d_function, d_class, &exclude_attributes, &include_attributes); if (notWrappedYet(d_function)) continue; - /* qtd s << endl - << INDENT << "@Override" << endl; */ + s << endl + << INDENT << "override "; writeFunctionAttributes(s, d_function, include_attributes, exclude_attributes, d_function->isNormal() || d_function->isSignal() ? 0 : SkipReturnType); s << d_function->name() << "("; writeFunctionArguments(s, d_function, d_function->arguments().count()); - s << ") {" << endl; + s << ")"; + + if(d_function->isConstant()) + s << " const"; + + s << " {" << endl; { Indentation indent(INDENT); writeJavaCallThroughContents(s, d_function, SuperCall); @@ -2502,12 +2470,22 @@ s << endl << "extern (C) void *__" << d_class->name() << "_entity(void *q_ptr);" << endl << endl; } + if (d_class->typeEntry()->isValue()) + { + AbstractMetaFunction *copy_ctor = d_class->copyConstructor(); + if (!d_class->typeEntry()->hasPrivateCopyConstructor()) // can do a copy if we have a public ctor or don't have any + { + s << "private extern(C) void qtd_" << d_class->name() << "_placed_copy(const void* orig, void* place);" << endl + << "private extern(C) void* qtd_" << d_class->name() << "_native_copy(const void* orig);" << endl; + } + } // if (d_class->needsConversionFunc) writeConversionFunction(s, d_class); if (d_class->hasConstructors() && !d_class->isQObject()) - s << "extern (C) void qtd_" << d_class->name() << "_destructor(void *ptr);" << endl << endl; + s << "extern (C) void qtd_" << d_class->name() << "_destructor(void *ptr);" << endl + << "extern (C) void qtd_" << d_class->name() << "_call_destructor(void *ptr);" << endl << endl; // qtd @@ -2577,6 +2555,9 @@ s << "extern(C) void static_init_" << d_class->name() << "() {" << endl; + if (d_class->typeEntry()->isValue()) + s << INDENT << d_class->name() << ".QTypeInfo.init();" << endl; + if (d_class->isQObject()) { s << INDENT << "if (!" << d_class->name() << "._staticMetaObject) " << endl << INDENT << " " << d_class->name() << ".createStaticMetaObject;" << endl << endl; @@ -2596,18 +2577,11 @@ initArgs = "virt_arr.ptr"; if (d_class->isQObject()) { - - // signals - AbstractMetaFunctionList signal_funcs = signalFunctions(d_class); - s << endl << INDENT << "void*[" << signal_funcs.size() << "] sign_arr;" << endl; - for(int i = 0; i < signal_funcs.size(); i++) { - AbstractMetaFunction *signal = signal_funcs.at(i); - s << INDENT << "sign_arr[" << i << "] = &" << signalExternName(d_class, signal) << "_handle;" << endl; - } - if(signal_funcs.size() == 0) - initArgs += ", null"; - else - initArgs += ", sign_arr.ptr"; + // qt_metacall, metaObject + s << endl << INDENT << "void*[2] sign_arr;" << endl; + s << INDENT << "sign_arr[0] = &qtd_" << d_class->name() << "_qt_metacall_dispatch;" << endl; + s << INDENT << "sign_arr[1] = &qtd_" << d_class->name() << "_metaObject_dispatch;" << endl; + initArgs += ", sign_arr.ptr"; } s << INDENT << "qtd_" << d_class->name() << QString("_initCallBacks(%1);").arg(initArgs) << endl; @@ -2633,10 +2607,39 @@ if (d_class->isQObject()) - { - s << "private extern(C) void* qtd_" << d_class->name() << "_staticMetaObject();" << endl << endl - << "private extern(C) void qtd_" << d_class->name() << "_createEntity(void* nativeId, void* dId);" << endl << endl; - } + writeQObjectFreeFunctions(s, d_class); + + if (d_class->typeEntry()->isValue()) + writeValueFreeFunctions(s, d_class); +} + +void DGenerator::writeValueFunctions(QTextStream &s, const AbstractMetaClass *d_class) +{ + s << INDENT << "struct QTypeInfo {" << endl; + s << INDENT << " static __gshared bool isComplex;" << endl; + s << INDENT << " static __gshared bool isStatic;" << endl; + s << INDENT << " static __gshared bool isLarge;" << endl; + s << INDENT << " static __gshared bool isPointer;" << endl; + s << INDENT << " static __gshared bool isDummy;" << endl << endl; + + s << INDENT << " static init() {" << endl; + + s << QString(" isComplex = qtd_%1_QTypeInfo_isComplex();\n" + " isStatic = qtd_%1_QTypeInfo_isStatic();\n" + " isLarge = qtd_%1_QTypeInfo_isLarge();\n" + " isPointer = qtd_%1_QTypeInfo_isPointer();\n" + " isDummy = qtd_%1_QTypeInfo_isDummy();\n").arg(d_class->name()) + << " }" << endl + << " }" << endl << endl; +} + +void DGenerator::writeValueFreeFunctions(QTextStream &s, const AbstractMetaClass *d_class) +{ + s << QString("private extern (C) bool qtd_%1_QTypeInfo_isComplex();\n").arg(d_class->name()); + s << QString("private extern (C) bool qtd_%1_QTypeInfo_isStatic();\n").arg(d_class->name()); + s << QString("private extern (C) bool qtd_%1_QTypeInfo_isLarge();\n").arg(d_class->name()); + s << QString("private extern (C) bool qtd_%1_QTypeInfo_isPointer();\n").arg(d_class->name()); + s << QString("private extern (C) bool qtd_%1_QTypeInfo_isDummy();\n").arg(d_class->name()); } void DGenerator::writeConversionFunction(QTextStream &s, const AbstractMetaClass *d_class) @@ -2674,13 +2677,73 @@ s << "}" << endl << endl; } +void DGenerator::writeQObjectFreeFunctions(QTextStream &s, const AbstractMetaClass *d_class) +{ + s << "private extern(C) QMetaObjectNative* qtd_" << d_class->name() << "_staticMetaObject();" << endl << endl + << "private extern(C) void qtd_" << d_class->name() << "_createEntity(void* nativeId, void* dId);" << endl << endl; + + if (!d_class->isFinal()) + s << "private extern(C) int qtd_" << d_class->name() << "_qt_metacall(void* __this_nativeId, QMetaObject.Call _c, int _id, void **_a);" + << "private extern(C) int qtd_" << d_class->name() << "_qt_metacall_dispatch(void *d_entity, QMetaObject.Call _c, int _id, void **_a) {" + << " auto d_object = cast(" << d_class->name() << ") d_entity;" + << " return d_object.qt_metacall(_c, _id, _a);" + << "}" << endl << endl + + << "private extern(C) void* qtd_" << d_class->name() << "_metaObject_dispatch(void *d_entity) {" + << " auto d_object = cast(" << d_class->name() << ") d_entity;" + << " return d_object.metaObject().nativeId();" + << "}" << endl << endl; + } + +void writeMetaMethodSignatures(QTextStream &s, const QString &var_name, AbstractMetaFunctionList meta_funcs) +{ + s << INDENT << "private static const string[] " << var_name << " = ["; + { + Indentation indent(INDENT); + for (int i = 0; i < meta_funcs.size(); ++i) + { + if (i) + s << ", "; + int j = 0; + bool hasDefault = false; + do // need this to look for default arguments and generate extra signatures + { + if (j) + s << ", "; + s << endl << INDENT << " \"" << meta_funcs.at(i)->minimalSignature(j) << "\""; + AbstractMetaArgumentList args = meta_funcs.at(i)->arguments(); + if(args.size() && j<args.size()) + hasDefault = !args.at(args.size() - 1 - j)->defaultValueExpression().isEmpty(); + else + hasDefault = false; + j++; + } while (hasDefault); + } + } + s << INDENT << "];" << endl << endl; +} + void DGenerator::writeQObjectFunctions(QTextStream &s, const AbstractMetaClass *d_class) { - QString concreteArg; + AbstractMetaFunctionList d_funcs_gen = generatedClassFunctions(d_class); + AbstractMetaFunctionList slot_funcs; + for (int i=0; i<d_funcs_gen.size(); ++i) { + AbstractMetaFunction *function = d_funcs_gen.at(i); + if(function->isSlot()) + slot_funcs += function; + } + writeMetaMethodSignatures(s, "__slotSignatures", slot_funcs); + + QString concreteArg; if (d_class->isAbstract()) concreteArg += ", " + d_class->name() + "_ConcreteWrapper"; - s << " private static QMetaObject _staticMetaObject;" << endl + if (!d_class->isFinal()) + s << " int qt_metacall(QMetaObject.Call _c, int _id, void **_a) {" << endl + << " return qtd_" << d_class->name() << "_qt_metacall(__nativeId, _c, _id, _a);" << endl + << " }" << endl << endl; + + s << " private static __gshared QMetaObject _staticMetaObject;" << endl << " protected static void createStaticMetaObject() {" << endl << " assert(!_staticMetaObject);" << endl << " QMetaObject base;" << endl; @@ -2695,6 +2758,7 @@ s << " _staticMetaObject = new QMetaObject(qtd_" << d_class->name() << "_staticMetaObject, base);" << endl << " _staticMetaObject.construct!(" << d_class->name() << concreteArg << ");" << endl + << " _populateMetaInfo();" << endl << " }" << endl << endl << " QMetaObject metaObject() {" << endl @@ -2711,7 +2775,60 @@ << " static void __createEntity(void* nativeId, void* dId) {" << endl << " return qtd_" << d_class->name() << "_createEntity(nativeId, dId);" << endl - << " }" << endl << endl; + << " }" << endl << endl + + << " private static void _populateMetaInfo() {" << endl + << " int index;" << endl << endl; + + AbstractMetaFunctionList signal_funcs = signalFunctions(d_class, false); + + int staticId = 0; + for (int i = 0; i < signal_funcs.size(); ++i) + { + int j = 0; + bool hasDefault = false; + do // need this to look for default arguments and generate extra signatures + { + AbstractMetaFunction *fn = signal_funcs.at(i); + s << " index = _staticMetaObject.indexOfMethod_Cpp(__signalSignatures[" << staticId << "]);" << endl + << " _staticMetaObject.addMethod(new QMetaSignal(signature!("; + writeMetaMethodArguments(s, fn, j); + s << ")(\"" << fn->name() << "\"), index));" << endl << endl; + AbstractMetaArgumentList args = fn->arguments(); + if(args.size() && j<args.size()) + hasDefault = !args.at(args.size() - 1 - j)->defaultValueExpression().isEmpty(); + else + hasDefault = false; + j++; + staticId++; + } while (hasDefault); + } + + staticId = 0; + for (int i = 0; i < slot_funcs.size(); ++i) + { + int j = 0; + bool hasDefault = false; + do // need this to look for default arguments and generate extra signatures + { + AbstractMetaFunction *fn = slot_funcs.at(i); + s << " index = _staticMetaObject.indexOfMethod_Cpp(__slotSignatures[" << staticId << "]);" << endl + << " _staticMetaObject.addMethod(new QMetaSlot(signature!("; + writeMetaMethodArguments(s, fn, j); + s << ")(\"" << fn->name() << "\"), index));" << endl << endl; + AbstractMetaArgumentList args = fn->arguments(); + if(args.size() && j<args.size()) + hasDefault = !args.at(args.size() - 1 - j)->defaultValueExpression().isEmpty(); + else + hasDefault = false; + j++; + staticId++; + } while (hasDefault); + } + + s << " }" << endl << endl; + + s << INDENT << "mixin Q_OBJECT_BIND;" << endl << endl; } /* @@ -2778,17 +2895,7 @@ void DGenerator::writeSignalSignatures(QTextStream &s, const AbstractMetaClass *d_class, AbstractMetaFunctionList signal_funcs) { - s << INDENT << "private const string[" << signal_funcs.size() << "] __signalSignatures = ["; - { - Indentation indent(INDENT); - for (int i = 0; i < signal_funcs.size(); ++i) - { - if (i) - s << ", "; - s << endl << INDENT << " \"" << signal_funcs.at(i)->minimalSignature() << "\""; - } - } - s << INDENT << "];" << endl << endl; + writeMetaMethodSignatures(s, "__signalSignatures", signal_funcs); s << INDENT << "int signalSignature(int signalId, ref stringz signature) {" << endl; { @@ -2810,29 +2917,43 @@ s << INDENT << "}" << endl; } +void DGenerator::writeMetaMethodArguments(QTextStream &s, const AbstractMetaFunction *d_function, int reduce) +{ + bool withDefArgs = false; + if(reduce == -1) { + reduce = 0; + withDefArgs = true; + } + + AbstractMetaArgumentList arguments = d_function->arguments(); + int sz = arguments.count() - reduce; + + for (int i=0; i<sz; ++i) { + if(i != 0) + s << ","; + + QString modifiedType = d_function->typeReplaced(i+1); + + if (modifiedType.isEmpty()) + s << translateType(arguments.at(i)->type(), d_function->implementingClass(), BoxedPrimitive); + else + s << modifiedType; + + if (!arguments.at(i)->defaultValueExpression().isEmpty() && withDefArgs) // qtd + s << " = " + arguments.at(i)->defaultValueExpression(); + } +} + void DGenerator::writeSignal(QTextStream &s, const AbstractMetaFunction *d_function) { Q_ASSERT(d_function->isSignal()); - - AbstractMetaArgumentList arguments = d_function->arguments(); - int sz = arguments.count(); - - s << INDENT << "mixin BindQtSignal!(\"" << d_function->name() << "\""; - - if (sz > 0) { - for (int i=0; i<sz; ++i) { - s << ", "; - - QString modifiedType = d_function->typeReplaced(i+1); - - if (modifiedType.isEmpty()) - s << translateType(arguments.at(i)->type(), d_function->implementingClass(), BoxedPrimitive); - else - s << modifiedType; - } - } - - s << ");" << endl; +/* + s << INDENT << "mixin BindQtSignal!(\"" << d_function->name() << "("; + + writeMetaMethodArguments(s, d_function); + + s << ")\");" << endl; + */ } void DGenerator::writeShellVirtualFunction(QTextStream &s, const AbstractMetaFunction *d_function, @@ -2857,7 +2978,13 @@ AbstractMetaType *type = argument->type(); // if has QString argument we have to pass char* and str.length to QString constructor { - if(type->isEnum()) + if (type->isContainer()) + { + if ( ((const ContainerTypeEntry *)type->typeEntry())->isQList() ) { + s << INDENT; + s << "auto " << arg_name << "_d_ref = cast(" << translateType(type, implementor) << "*)" << arg_name << ";" << endl; + } + } else if(type->isEnum()) s << INDENT << "auto " << arg_name << "_enum = cast(" << type->typeEntry()->qualifiedTargetLangName() << ") " << arg_name << ";"; else if (type->typeEntry()->qualifiedCppName() == "QChar") @@ -2867,7 +2994,7 @@ s << INDENT << "string " << arg_name << "_d_ref = toUTF8(" << arg_name << "[0.." << arg_name << "_size]);"; else if (type->typeEntry()->isValue() && type->isNativePointer() && type->typeEntry()->name() == "QString") { - s << INDENT << "auto " << arg_name << "_d_qstr = QString(" << arg_name << ", true);" << endl + s << INDENT << "auto " << arg_name << "_d_qstr = QStringUtil(" << arg_name << ", true);" << endl << INDENT << "string " << arg_name << "_d_ref = " << arg_name << "_d_qstr.toNativeString();"; } else if(type->isVariant()) s << INDENT << "scope " << arg_name << "_d_ref = new QVariant(" << arg_name << ", QtdObjectFlags.nativeOwnership);"; @@ -2935,11 +3062,14 @@ if (modified_type == "string" /* && type->fullName() == "char" */) s << "fromStringz(" << arg_name << ")"; - else { + else + { if(type->isContainer() || (type->isReference() && type->typeEntry()->isStructInD())) s << "*"; s << arg_name; + if (type->isContainer() && ((const ContainerTypeEntry *)type->typeEntry())->isQList() ) + s << "_d_ref"; } if (type->typeEntry()->isStructInD()) ; else if (type->isQObject() || type->isObject() @@ -2975,10 +3105,13 @@ s << INDENT << "return ret_value is null? null : ret_value." << native_id << ";" << endl; } else if (f_type->isTargetLangString()) s << INDENT << "*ret_str = _d_str;" << endl; - else if (f_type->isContainer()) - s << INDENT << "*__d_arr_ptr = return_value.ptr;" << endl - << INDENT << "*__d_arr_size = return_value.length;" << endl; - else if (f_type->name() == "QModelIndex" || f_type->typeEntry()->isStructInD()) + else if (f_type->isContainer()) { + if (isNativeContainer(f_type)) + s << INDENT << "*__d_arr = return_value;" << endl; + else + s << INDENT << "*__d_arr_ptr = return_value.ptr;" << endl + << INDENT << "*__d_arr_size = return_value.length;" << endl; + } else if (f_type->name() == "QModelIndex" || f_type->typeEntry()->isStructInD()) ; else s << INDENT << "return return_value;" << endl; @@ -3007,8 +3140,6 @@ ctype_child->addedTo = cls->name(); } - foreach (AbstractMetaFunction *function, cls->functions()) - function->checkStoreResult(); /* we don't need this anymore // generate QObject conversion functions only those that are required AbstractMetaFunctionList d_funcs = cls->functionsInTargetLang();
--- a/generator/dgenerator.h Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/dgenerator.h Sun Feb 07 16:04:36 2010 +0000 @@ -98,7 +98,7 @@ const QString &arg_name); void writePrivateNativeFunction(QTextStream &s, const AbstractMetaFunction *d_function); void writeJavaLangObjectOverrideFunctions(QTextStream &s, const AbstractMetaClass *cls); - void writeReferenceCount(QTextStream &s, const ReferenceCount &refCount, const QString &argumentName); + void writeReferenceCount(QTextStream &s, const ReferenceCount &refCount, const QString &argumentName, AbstractMetaType *argumentType = 0); void retrieveModifications(const AbstractMetaFunction *f, const AbstractMetaClass *d_class, uint *exclude_attributes, uint *include_attributes) const; QString functionSignature(const AbstractMetaFunction *d_function, @@ -149,14 +149,19 @@ void addInstantiations(const AbstractMetaType* d_type); void writeRequiredImports(QTextStream &s, const AbstractMetaClass *d_class); const TypeEntry* fixedTypeEntry(const TypeEntry *type); + AbstractMetaFunctionList generatedClassFunctions(const AbstractMetaClass *d_class); void writeDestructor(QTextStream &s, const AbstractMetaClass *d_class); void writeFlagsSetter(QTextStream &s, const AbstractMetaClass *d_class); void writeSignalHandlers(QTextStream &s, const AbstractMetaClass *d_class); void writeEnumAlias(QTextStream &s, const AbstractMetaEnum *d_enum); void writeSignalSignatures(QTextStream &s, const AbstractMetaClass *d_class, AbstractMetaFunctionList signal_funcs); + void writeMetaMethodArguments(QTextStream &s, const AbstractMetaFunction *d_function, int reduce = -1); void writeQObjectFunctions(QTextStream &s, const AbstractMetaClass *d_class); + void writeQObjectFreeFunctions(QTextStream &s, const AbstractMetaClass *d_class); void writeConversionFunction(QTextStream &s, const AbstractMetaClass *d_class); + void writeValueFreeFunctions(QTextStream &s, const AbstractMetaClass *d_class); + void writeValueFunctions(QTextStream &s, const AbstractMetaClass *d_class); // void writeMarshallFunction(QTextStream &s, const AbstractMetaClass *d_class);
--- a/generator/typesystem.cpp Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem.cpp Sun Feb 07 16:04:36 2010 +0000 @@ -96,6 +96,7 @@ // qtd stuff AddClass = 0x1100, PackageDepend = 0x1200, + PrivateCopyConstructor = 0x1300, // Code snip tags (0x1000, 0x2000, ... , 0xf000) InjectCode = 0x1000, @@ -163,6 +164,7 @@ tagNames["rename"] = StackElement::Rename; tagNames["typesystem"] = StackElement::Root; tagNames["custom-constructor"] = StackElement::CustomMetaConstructor; + tagNames["private-copy-constructor"] = StackElement::PrivateCopyConstructor; tagNames["custom-destructor"] = StackElement::CustomMetaDestructor; tagNames["argument-map"] = StackElement::ArgumentMap; tagNames["suppress-warning"] = StackElement::SuppressedWarning; @@ -299,6 +301,11 @@ delete current->value.customFunction; } break; + case StackElement::PrivateCopyConstructor: + { + current->entry->setHasPrivateCopyConstructor(true); + } + break; case StackElement::CustomMetaDestructor: { current->entry->setCustomDestructor(*current->value.customFunction); @@ -1677,19 +1684,17 @@ QString ContainerTypeEntry::javaPackage() const { - if (m_type == PairContainer) - return "qt"; - return "java.util"; + return "qt.core"; } QString ContainerTypeEntry::targetLangName() const { switch (m_type) { - case StringListContainer: return "List"; - case ListContainer: return "List"; - case LinkedListContainer: return "LinkedList"; - case VectorContainer: return "List"; + case StringListContainer: return "QList"; + case ListContainer: return "QList"; + case LinkedListContainer: return "QLinkedList"; + case VectorContainer: return "QVector"; case StackContainer: return "Stack"; case QueueContainer: return "Queue"; case SetContainer: return "Set";
--- a/generator/typesystem.h Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem.h Sun Feb 07 16:04:36 2010 +0000 @@ -436,9 +436,10 @@ : m_name(name), m_type(t), m_code_generation(GenerateAll), - m_preferred_conversion(true) + m_preferred_conversion(true), + m_has_copy_constructor(false) { - }; + } virtual ~TypeEntry() { } @@ -508,6 +509,8 @@ // qtd virtual bool isStructInD() const { return false; } + bool hasPrivateCopyConstructor() const { return m_has_copy_constructor; } + void setHasPrivateCopyConstructor(bool has_copy_constructor) { m_has_copy_constructor = has_copy_constructor; } private: QString m_name; @@ -516,6 +519,7 @@ CustomFunction m_customConstructor; CustomFunction m_customDestructor; bool m_preferred_conversion; + bool m_has_copy_constructor; }; typedef QHash<QString, QList<TypeEntry *> > TypeEntryHash; typedef QHash<QString, TypeEntry *> SingleTypeEntryHash; @@ -950,6 +954,8 @@ QString javaPackage() const; QString qualifiedCppName() const; + bool isQList() const { return type() == ListContainer || type() == StringListContainer; } + private: Type m_type; };
--- a/generator/typesystem_core-java.java Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem_core-java.java Sun Feb 07 16:04:36 2010 +0000 @@ -79,7 +79,7 @@ QObject __next; QObject __prev; } - +/* override void onSignalHandlerCreated(ref SignalHandler sh) { sh.signalEvent = &onSignalEvent; @@ -104,7 +104,7 @@ } } } - +*/ ~this() { if (__prev) @@ -154,6 +154,11 @@ find(children); return result; } + + static void connect(QObject sender, string signal, QObject receiver, string method, int type = 0) + { + QMetaObject.connectImpl(sender, signal, receiver, method, type); + } }// class abstract class QAbstractItemModel___ extends QAbstractItemModel {
--- a/generator/typesystem_core.xml Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem_core.xml Sun Feb 07 16:04:36 2010 +0000 @@ -103,7 +103,7 @@ <primitive-type name="__int64" java-name="long" preferred-conversion="no" jni-name="jlong"/> <primitive-type name="unsigned __int64" java-name="long" preferred-conversion="no" jni-name="jlong"/> <primitive-type name="unsigned long long" java-name="ulong" preferred-conversion="no" jni-name="jlong"/> - <primitive-type name="long long" java-name="long" preferred-conversion="no" jni-name="jlong"/> + <primitive-type name="qint64" java-name="long" preferred-conversion="no" jni-name="jlong"/> <primitive-type name="quintptr" preferred-conversion="no" java-name="quintptr" jni-name="quintptr" /> <primitive-type name="short" preferred-conversion="no" java-name="short" jni-name="jchar"/> @@ -558,8 +558,7 @@ <rejection class="QObject" function-name="disconnect"/> <rejection class="QObject" function-name="disconnectNotify"/> <rejection class="QObject" function-name="registerUserData"/> - <rejection class="QObject" function-name="sender"/> - <rejection class="QTimer" function-name="singleShot"/> +<!-- <rejection class="QObject" function-name="sender"/> --> <rejection class="QProcess" function-name="pid"/> <rejection class="QRegion" function-name="cleanUp"/> <rejection class="QSettings" function-name="registerFormat"/> @@ -2282,15 +2281,16 @@ <modify-function signature="error()const"> <rename to="lastError"/> </modify-function> - <modify-function signature="finished(int, QProcess::ExitStatus)"> +<!-- <modify-function signature="finished(int, QProcess::ExitStatus)"> <rename to="finishedWithStatusCode"/> </modify-function> + --> <modify-function signature="setStandardOutputProcess(QProcess*)"> <modify-argument index="1"> <reference-count action="set" variable-name="__rcStandardOutputProcess"/> </modify-argument> </modify-function> -<!-- <modify-function signature="startDetached(QString,QStringList<QString>,QString,long long*)"> +<!-- <modify-function signature="startDetached(QString,QStringList,QString,long long*)"> <access modifier="private"/> <modify-argument index="4"> <remove-default-expression/> @@ -2302,7 +2302,7 @@ </object-type> <object-type name="QSignalMapper"> - <modify-function signature="mapped(const QString &)"> +<!-- <modify-function signature="mapped(const QString &)"> <rename to="mappedString"/> </modify-function> <modify-function signature="mapped(int)"> @@ -2310,7 +2310,7 @@ </modify-function> <modify-function signature="mapped(QObject *)"> <rename to="mappedQObject"/> - </modify-function> + </modify-function> --> <modify-function signature="mapped(QWidget *)" remove="all"/> <modify-function signature="mapping(QWidget*)const" remove="all"/> @@ -2477,11 +2477,11 @@ </inject-code> --> </modify-function> - +<!-- <modify-function signature="deleteLater()"> <rename to="disposeLater"/> </modify-function> - +--> <modify-function signature="inherits(const char*)const"> <remove/> </modify-function> @@ -2655,7 +2655,7 @@ <rename to="writeInt"/> <modify-argument index="0" replace-value="this"/> </modify-function> - <modify-function signature="operator<<(long long)"> + <modify-function signature="operator<<(qint64)"> <rename to="writeLong"/> <modify-argument index="0" replace-value="this"/> </modify-function> @@ -2691,7 +2691,7 @@ <access modifier="private"/> </modify-function> - <modify-function signature="operator>>(long long&)"> + <modify-function signature="operator>>(qint64&)"> <rename to="operator_shift_right_long"/> <modify-argument index="0" replace-value="this"/> <access modifier="private"/>
--- a/generator/typesystem_gui-java.java Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem_gui-java.java Sun Feb 07 16:04:36 2010 +0000 @@ -1694,15 +1694,13 @@ static if (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0)) { - public static int getInt(QWidget _parent, string title, string label, int value = 0, int minValue = -2147483647, int maxValue = 2147483647, int step = 1, ref bool ok = false, int flags = 0) { + public static int getInt(QWidget _parent, string title, string label, int value = 0, int minValue = -2147483647, int maxValue = 2147483647, int step = 1, ref bool ok = false, int flags = 0) { return qtd_QInputDialog_getInt_private_QWidget_string_string_int_int_int_int_nativepointerbool_WindowFlags(_parent is null ? null : _parent.__nativeId, title, label, value, minValue, maxValue, step, &ok, flags); - } + } } - public static string getItem(QWidget _parent, string title, string label, string[] items, int current = 0, bool editable = true, ref bool ok = false, int flags = 0) { - string res; - qtd_QInputDialog_getItem_private_QWidget_string_string_List_int_bool_nativepointerbool_WindowFlags(&res, _parent is null ? null : _parent.__nativeId, title, label, items.ptr, items.length, current, editable, &ok, flags); - return res; + public static string getItem(QWidget _parent, string title, string label, QList!(string) items, int current = 0, bool editable = true, ref bool ok = false, int flags = 0) { + return getItem_private(_parent, title, label, items, current, editable, &ok, flags); } public static string getText(QWidget _parent, string title, string label, QLineEdit_EchoMode echo = QLineEdit_EchoMode.Normal, string text = null, ref bool ok = false, int flags = 0) {
--- a/generator/typesystem_gui.xml Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem_gui.xml Sun Feb 07 16:04:36 2010 +0000 @@ -1298,7 +1298,7 @@ </modify-function> <modify-function signature="operator QVariant()const" access="private"/> <inject-code class="java"> - public final QVariant toVariant() { + public final QVariant toVariant() const { return operator_cast_QVariant(); } </inject-code> @@ -2202,7 +2202,9 @@ <modify-function signature="setMatrix(QMatrix, bool)" remove="all"/> <modify-function signature="children()const" remove="all"/> - <!-- + <modify-function signature="isBlockedByModalPanel(QGraphicsItem**)const" remove="all"/> +<!-- <modify-function signature="toGraphicsObject()const" remove="all"/> --> + <!-- <modify-function signature="setMatrix(QMatrix, bool)" remove="all"/> <modify-function signature="paint(QPainter*,const QStyleOptionGraphicsItem*,QWidget*)"> @@ -3687,11 +3689,11 @@ <modify-function signature="find(QString)"> <remove/> </modify-function> + <modify-function signature="find(QString,QPixmap&)"> + <remove/> + </modify-function> + <!-- - <modify-function signature="find(QString,QPixmap&)"> - <access modifier="private"/> - </modify-function> - <inject-code> <import-file name="typesystem_gui-java.java" quote-after-line="class QPixmapCache___" quote-before-line="}// class"/> </inject-code> @@ -3703,13 +3705,13 @@ <modify-function signature="layoutSpacingImplementation(QSizePolicy::ControlType, QSizePolicy::ControlType, Qt::Orientation, const QStyleOption *, const QWidget *) const" virtual-slot="yes"/> </object-type> <object-type name="QPrintDialog"> - <modify-function signature="accepted(QPrinter *)"> +<!-- <modify-function signature="accepted(QPrinter *)"> <rename to="accepted_printer"/> - </modify-function> + </modify-function> --> <modify-function signature="accepted()" remove="all"/> <modify-function signature="open(QObject *, const char *)" remove="all"/> <!-- # TODO --> - </object-type> + </object-type> <object-type name="QPrintEngine"/> <object-type name="QProgressBar"> <!-- <modify-function signature="initStyleOption(QStyleOptionProgressBar*)const"> @@ -4868,7 +4870,7 @@ <access modifier="private" /> </modify-function> - <modify-function signature="getItem(QWidget *, const QString &, const QString &, const QStringList<QString> &, int, bool, bool *, QFlags<Qt::WindowType>)"> + <modify-function signature="getItem(QWidget *, const QString &, const QString &, const QStringList &, int, bool, bool *, QFlags<Qt::WindowType>)"> <rename to="getItem_private"/> <access modifier="private"/> </modify-function> @@ -5297,7 +5299,11 @@ <modify-function signature="setTextColor(QColor)" remove="all"/> <!--### Obsolete in 4.3--> <modify-function signature="textColor()const" remove="all"/> <!--### Obsolete in 4.3--> </object-type> - + + <object-type name="QGraphicsObject"> + <modify-function signature="children()const" remove="all"/> + </object-type> + <object-type name="QGraphicsTextItem"> <!-- a QObject so main-thread delete redundant --> <extra-includes> <include file-name="QTextCursor" location="global"/> @@ -5330,12 +5336,12 @@ </object-type> <object-type name="QCompleter"> - <modify-function signature="activated(const QModelIndex &)"> +<!-- <modify-function signature="activated(const QModelIndex &)"> <rename to="activatedIndex"/> </modify-function> <modify-function signature="highlighted(const QModelIndex &)"> <rename to="highlightedIndex"/> - </modify-function> + </modify-function> --> <modify-function signature="setModel(QAbstractItemModel *)"> <modify-argument index="1"> <reference-count action="set" variable-name="__rcModel"/> @@ -5375,7 +5381,7 @@ <define-ownership class="java" owner="c++"/> </modify-argument> </modify-function> - <modify-function signature="QTreeWidgetItem(QTreeWidget *,const QStringList<QString> &,int)"> + <modify-function signature="QTreeWidgetItem(QTreeWidget *,const QStringList &,int)"> <modify-argument index="this"> <define-ownership class="java" owner="c++"/> </modify-argument> @@ -5390,7 +5396,7 @@ <define-ownership class="java" owner="c++"/> </modify-argument> </modify-function> - <modify-function signature="QTreeWidgetItem(QTreeWidgetItem *,const QStringList<QString> &,int)"> + <modify-function signature="QTreeWidgetItem(QTreeWidgetItem *,const QStringList &,int)"> <modify-argument index="this"> <define-ownership class="java" owner="c++"/> </modify-argument> @@ -5509,9 +5515,9 @@ <!-- <modify-function signature="addItem(const QString &)" remove="all"/>--> - <modify-function signature="addItems(const QStringList<QString> &)" remove="all"/> + <modify-function signature="addItems(const QStringList &)" remove="all"/> <modify-function signature="insertItem(int, const QString &)" remove="all"/> - <modify-function signature="insertItems(int, const QStringList<QString> &)" remove="all"/> + <modify-function signature="insertItems(int, const QStringList &)" remove="all"/> <inject-code> <import-file name="typesystem_gui-java.java" quote-after-line="class QListWidget___" quote-before-line="}// class"/> </inject-code> @@ -6815,25 +6821,25 @@ </object-type> <object-type name="QSpinBox"> - <modify-function signature="valueChanged(const QString &)"> +<!-- <modify-function signature="valueChanged(const QString &)"> <rename to="valueStringChanged"/> - </modify-function> + </modify-function> --> </object-type> <object-type name="QTextBrowser"> - <modify-function signature="highlighted(const QString &)"> +<!-- <modify-function signature="highlighted(const QString &)"> <rename to="highlightedString"/> - </modify-function> + </modify-function> --> </object-type> <object-type name="QDoubleSpinBox"> - <modify-function signature="valueChanged(const QString &)"> +<!-- <modify-function signature="valueChanged(const QString &)"> <rename to="valueStringChanged"/> - </modify-function> + </modify-function> --> </object-type> <object-type name="QButtonGroup"> - <modify-function signature="buttonClicked(int)"> +<!-- <modify-function signature="buttonClicked(int)"> <rename to="buttonIdClicked"/> </modify-function> <modify-function signature="buttonPressed(int)"> @@ -6841,7 +6847,7 @@ </modify-function> <modify-function signature="buttonReleased(int)"> <rename to="buttonIdReleased"/> - </modify-function> + </modify-function> --> <modify-function signature="addButton(QAbstractButton *)"> <modify-argument index="1"> <reference-count action="add" variable-name="__rcButtons"/> @@ -7235,7 +7241,7 @@ <inject-code> <import-file name="typesystem_gui-java.java" quote-after-line="class QComboBox___" quote-before-line="}// class"/> </inject-code> - <modify-function signature="activated(int)">> +<!-- <modify-function signature="activated(int)">> <rename to="activatedIndex"/> </modify-function> <modify-function signature="currentIndexChanged(const QString &)"> @@ -7244,7 +7250,7 @@ <modify-function signature="highlighted(int)"> <rename to="highlightedIndex"/> </modify-function> - +--> <modify-function signature="autoCompletion()const" remove="all"/> <!--### Obsolete in 4.3--> <modify-function signature="autoCompletionCaseSensitivity()const" remove="all"/> <!--### Obsolete in 4.3--> <modify-function signature="setAutoCompletion(bool)" remove="all"/> <!--### Obsolete in 4.3--> @@ -7586,6 +7592,13 @@ return %FUNCTION_NAME(%PRE_CALL_ARGUMENTS %COMMA className == null ? null : className.data()); } </template> + + <inject-code class="java-free"> + QApplication qApp() + { + return cast(QApplication) QCoreApplication.instance(); + } + </inject-code> </object-type> <object-type name="QCommandLinkButton"/>
--- a/generator/typesystem_network.xml Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem_network.xml Sun Feb 07 16:04:36 2010 +0000 @@ -102,7 +102,7 @@ <modify-function signature="abort()" access="non-final"/> <modify-function signature="disconnectFromHostImplementation()" access="non-final"/> <modify-function signature="flush()" access="non-final"/> - <modify-function signature="setReadBufferSize(long long)" access="non-final"/> + <modify-function signature="setReadBufferSize(qint64)" access="non-final"/> <modify-function signature="setSocketDescriptor(int,QAbstractSocket::SocketState,QFlags<QIODevice::OpenModeFlag>)" access="non-final"/> <modify-function signature="waitForConnected(int)" access="non-final"/> <modify-function signature="waitForDisconnected(int)" access="non-final"/>
--- a/generator/typesystem_phonon.xml Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem_phonon.xml Sun Feb 07 16:04:36 2010 +0000 @@ -75,7 +75,7 @@ <interface-type name="Phonon::MediaObjectInterface" java-name="AbstractMediaObject"/> <interface-type name="Phonon::PlatformPlugin" java-name="PlatformPlugin"> - <modify-function signature="notification(const char *, const QString &, const QStringList<QString> &, QObject *, const char *)const"> + <modify-function signature="notification(const char *, const QString &, const QStringList &, QObject *, const char *)const"> <modify-argument index="3"> <replace-default-expression with="null"/> </modify-argument>
--- a/generator/typesystem_xml.xml Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem_xml.xml Sun Feb 07 16:04:36 2010 +0000 @@ -346,6 +346,7 @@ </value-type> <value-type name="QXmlNamespaceSupport"> + <private-copy-constructor/> <!-- <custom-constructor> QXmlNamespaceSupport *clone = new QXmlNamespaceSupport; clone->setPrefix("", copy->uri("")); @@ -360,7 +361,6 @@ delete (QXmlNamespaceSupport *)copy; </custom-destructor> - <inject-code> <import-file name="typesystem_xml-java.java" quote-after-line="class QXmlNamespaceSupport___" quote-before-line="}// class"/>
--- a/generator/typesystem_xmlpatterns.xml Sat Dec 19 18:43:32 2009 +0300 +++ b/generator/typesystem_xmlpatterns.xml Sun Feb 07 16:04:36 2010 +0000 @@ -125,7 +125,7 @@ <object-type name="QXmlQuery"> <modify-function signature="evaluateTo(QAbstractXmlReceiver *)const" remove="all"/> - <modify-function signature="evaluateTo(QStringList<QString>*)const" remove="all"/> + <modify-function signature="evaluateTo(QStringList*)const" remove="all"/> <modify-function signature="setMessageHandler(QAbstractMessageHandler*)"> <modify-argument index="1"> <reference-count action="set" variable-name="__rcMessageHandler"/>
--- a/include/qtd_core.h Sat Dec 19 18:43:32 2009 +0300 +++ b/include/qtd_core.h Sun Feb 07 16:04:36 2010 +0000 @@ -81,6 +81,13 @@ extern "C" QModelIndex qtd_to_QModelIndex(QModelIndexAccessor mia); extern "C" QModelIndexAccessor qtd_from_QModelIndex(const QModelIndex &index); - +extern "C" typedef void (*EmitCallback)(void*, void**); +extern "C" typedef int (*QtMetacallCallback)(void *d_entity, QMetaObject::Call _c, int _id, void **_a); +extern "C" typedef const QMetaObject* (*MetaObjectCallback)(void *d_entity); +template <class T> +void call_destructor(T *a) +{ + a->~T(); +} #endif // QTD_CORE_H
--- a/qt/QGlobal.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/QGlobal.d Sun Feb 07 16:04:36 2010 +0000 @@ -225,6 +225,11 @@ //class QString; //char[] qPrintable(QString string) { string.toLocal8Bit().constData(); } //TODO(katrina) These should probably actually call into the c++ functions +void qFatal(string str) +{ + throw new Exception(str); +} + void qDebug( char[] str ) /* print debug message */ { writeln(str); } @@ -360,7 +365,7 @@ /* The catch-all template. */ - +/* bool qIsDetached(T)(T) { return true; } class QTypeInfossss(T) @@ -386,7 +391,7 @@ isDummy = false }; }; - +*/ /* Specialize a specific type with: @@ -735,5 +740,7 @@ } +/ +alias void DArray; + mixin QT_END_HEADER;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/core/QList.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,626 @@ +module qt.core.QList; + +import qt.QGlobal; +import qt.QtdObject; +import qt.qtd.Atomic; +import qt.qtd.MetaMarshall; +import qt.core.QTypeInfo; +import qt.core.QString; + +import core.stdc.stdlib : qRealloc = realloc, qFree = free, qMalloc = malloc; +import core.stdc.string : memcpy, memmove; + +import std.traits; + +enum INT_MAX = int.max; + +bool isComplex(T)() + if (is(T.QTypeInfo)) +{ + return T.QTypeInfo.isComplex; +} + +bool isStatic(T)() + if (is(T.QTypeInfo)) +{ + return T.QTypeInfo.isStatic; +} + +bool isLarge(T)() + if (is(T.QTypeInfo)) +{ + return T.QTypeInfo.isLarge; +} + +template isQtReference(T) +{ + enum isQtReference = isQObjectType!T || isObjectType!T || isValueType!T || is(T == string); +} + +int qAllocMore(int alloc, int extra) +{ + if (alloc == 0 && extra == 0) + return 0; + const int page = 1 << 12; + int nalloc; + alloc += extra; + if (alloc < 1<<6) { + nalloc = (1<<3) + ((alloc >>3) << 3); + } else { + // don't do anything if the loop will overflow signed int. + if (alloc >= INT_MAX/2) + return INT_MAX; + nalloc = (alloc < page) ? 1 << 3 : page; + while (nalloc < alloc) { + if (nalloc <= 0) + return INT_MAX; + nalloc *= 2; + } + } + return nalloc - extra; +} + +void q_new_at(T)(T* ptr, const ref T t) +{ + memcpy(ptr, &t, T.sizeof); +/* static if (__traits(compiles, ptr.__postblit())) DMD bug #3539 + ptr.__postblit();*/ +} + +T* q_new(T)(const ref T t) +{ + T* ptr = cast(T*) qMalloc(T.sizeof); + q_new_at!T(ptr, t); + return ptr; +} + +void q_delete(T)(T* t) +{ + static if (__traits(compiles, t.__dtor())) + t.__dtor(); + qFree(t); +} + +private int grow(int size) +{ + // dear compiler: don't optimize me out. +// synchronized { + int x = qAllocMore(size * (void*).sizeof, QListData.DataHeaderSize) / (void*).sizeof; + return x; +// } +} + +struct QListData { + struct Data { + Atomic!int ref_; + int alloc, begin, end; + uint sharable; + void*[1] array; + } + + enum { DataHeaderSize = Data.sizeof - (void*).sizeof } + + static Data shared_null; + Data *d; + + static this() + { + shared_null = Data(Atomic!int(1), 0, 0, 0, true, [null]); + } + + +// Data *detach(); // remove in 5.0 + + Data* detach2() + { + Data* x = d; + d = cast(Data*)(qMalloc(DataHeaderSize + x.alloc * (void*).sizeof)); + if (!d) + qFatal("QList: Out of memory"); + + memcpy(d, x, DataHeaderSize + x.alloc * (void*).sizeof); + d.alloc = x.alloc; + d.ref_.store(1); + d.sharable = true; + if (!d.alloc) + d.begin = d.end = 0; + + return x; + } + + void realloc(int alloc) + { +// assert(d.ref_ == 1); + Data* x = cast(Data*)(qRealloc(d, DataHeaderSize + alloc * (void*).sizeof)); + if (!x) + qFatal("QList: Out of memory"); + + d = x; + d.alloc = alloc; + if (!alloc) + d.begin = d.end = 0; + } + + void** append() + { +// #TODO Q_ASSERT(d.ref_ == 1); + if (d.end == d.alloc) { + int n = d.end - d.begin; + if (d.begin > 2 * d.alloc / 3) { + memcpy(d.array.ptr + n, d.array.ptr + d.begin, n * (void*).sizeof); + d.begin = n; + d.end = n * 2; + } else { + realloc(grow(d.alloc + 1)); + } + } + return d.array.ptr + d.end++; + } + + void **append(const ref QListData l) + { +// Q_ASSERT(d.ref_ == 1); + int e = d.end; + int n = l.d.end - l.d.begin; + if (n) { + if (e + n > d.alloc) + realloc(grow(e + l.d.end - l.d.begin)); + memcpy(d.array.ptr + d.end, l.d.array.ptr + l.d.begin, n * (void*).sizeof); + d.end += n; + } + return d.array.ptr + e; + } + + void **prepend() + { +// Q_ASSERT(d.ref_ == 1); + if (d.begin == 0) { + if (d.end >= d.alloc / 3) + realloc(grow(d.alloc + 1)); + + if (d.end < d.alloc / 3) + d.begin = d.alloc - 2 * d.end; + else + d.begin = d.alloc - d.end; + + memmove(d.array.ptr + d.begin, d.array.ptr, d.end * (void*).sizeof); + d.end += d.begin; + } + return d.array.ptr + --d.begin; + } + + void **insert(int i) + { +// Q_ASSERT(d.ref_ == 1); + if (i <= 0) + return prepend(); + if (i >= d.end - d.begin) + return append(); + + bool leftward = false; + int size = d.end - d.begin; + + if (d.begin == 0) { + if (d.end == d.alloc) { + // If the array is full, we expand it and move some items rightward + realloc(grow(d.alloc + 1)); + } else { + // If there is free space at the end of the array, we move some items rightward + } + } else { + if (d.end == d.alloc) { + // If there is free space at the beginning of the array, we move some items leftward + leftward = true; + } else { + // If there is free space at both ends, we move as few items as possible + leftward = (i < size - i); + } + } + + if (leftward) { + --d.begin; + memmove(d.array.ptr + d.begin, d.array.ptr + d.begin + 1, i * (void*).sizeof); + } else { + memmove(d.array.ptr + d.begin + i + 1, d.array.ptr + d.begin + i, + (size - i) * (void*).sizeof); + ++d.end; + } + return d.array.ptr + d.begin + i; + } + + void remove(int i) + { +// Q_ASSERT(d.ref_ == 1); + i += d.begin; + if (i - d.begin < d.end - i) { + if (int offset = i - d.begin) + memmove(d.array.ptr + d.begin + 1, d.array.ptr + d.begin, offset * (void*).sizeof); + d.begin++; + } else { + if (int offset = d.end - i - 1) + memmove(d.array.ptr + i, d.array.ptr + i + 1, offset * (void*).sizeof); + d.end--; + } + } + + void remove(int i, int n) + { +// Q_ASSERT(d.ref_ == 1); + i += d.begin; + int middle = i + n/2; + if (middle - d.begin < d.end - middle) { + memmove(d.array.ptr + d.begin + n, d.array.ptr + d.begin, + (i - d.begin) * (void*).sizeof); + d.begin += n; + } else { + memmove(d.array.ptr + i, d.array.ptr + i + n, + (d.end - i - n) * (void*).sizeof); + d.end -= n; + } + } + + void move(int from, int to) + { +// Q_ASSERT(d.ref_ == 1); + if (from == to) + return; + + from += d.begin; + to += d.begin; + void *t = d.array.ptr[from]; + + if (from < to) { + if (d.end == d.alloc || 3 * (to - from) < 2 * (d.end - d.begin)) { + memmove(d.array.ptr + from, d.array.ptr + from + 1, (to - from) * (void*).sizeof); + } else { + // optimization + if (int offset = from - d.begin) + memmove(d.array.ptr + d.begin + 1, d.array.ptr + d.begin, offset * (void*).sizeof); + if (int offset = d.end - (to + 1)) + memmove(d.array.ptr + to + 2, d.array.ptr + to + 1, offset * (void*).sizeof); + ++d.begin; + ++d.end; + ++to; + } + } else { + if (d.begin == 0 || 3 * (from - to) < 2 * (d.end - d.begin)) { + memmove(d.array.ptr + to + 1, d.array.ptr + to, (from - to) * (void*).sizeof); + } else { + // optimization + if (int offset = to - d.begin) + memmove(d.array.ptr + d.begin - 1, d.array.ptr + d.begin, offset * (void*).sizeof); + if (int offset = d.end - (from + 1)) + memmove(d.array.ptr + from, d.array.ptr + from + 1, offset * (void*).sizeof); + --d.begin; + --d.end; + --to; + } + } + d.array.ptr[to] = t; + } + + void **erase(void **xi) + { +// Q_ASSERT(d.ref_ == 1); + int i = xi - (d.array.ptr + d.begin); + remove(i); + return d.array.ptr + d.begin + i; + } + + int size() const { return d.end - d.begin; } + bool isEmpty() const { return d.end == d.begin; } + const (void*)* at(int i) const { return d.array.ptr + d.begin + i; } + const (void*)* begin() const { return d.array.ptr + d.begin; } + const (void*)* end() const { return d.array.ptr + d.end; } +} + +import std.stdio; +import std.conv; + +alias void Dummy; // DMD bug #3538 + +struct QList(T, alias Default = Dummy) +{ + static if (is(Default == Dummy)) + alias QTypeInfo!T TI; + else + alias Default TI; + + struct Node + { + void *v; + + static if (isQObjectType!T || isObjectType!T || isValueType!T || is(T == string)) // binded Qt types + { + T t() + { + static if(is(T == string)) + { + void* ptr = cast(void*)(TI.isLarge || TI.isStatic ? v : &this); + return QStringUtil.toNativeString(ptr); + } + else static if (isValueType!T) + { + void* ptr = cast(void*)(isLarge!T() || isStatic!T() ? v : &this); + return new T(ptr, QtdObjectFlags.nativeOwnership); + } + else + { + return T.__getObject( *cast(void**)(&this) ); + } + } + } + else // native types + { + ref T t() + { + static if(TI.isLarge || TI.isStatic) + return *cast(T*)(v); + else + return *cast(T*)(&this); + } + } + } + + union { + QListData p; + QListData.Data* d; + } + +public: + /* + void output() + { + writeln("QList atomic ", d.ref_.load()); + } + */ + + static QList!T opCall() + { + QList!T res; +// writeln("QList opCall"); + + res.d = &QListData.shared_null; + res.d.ref_.increment(); + + return res; + } + + this(this) + { +// writeln("QList postblit"); + d.ref_.increment(); + if (!d.sharable) + detach_helper(); + } + + ~this() + { +// writeln("QList ~this"); + if (d && !d.ref_.decrement()) + free(d); + } + + ref QList!T opAssign(const ref QList!T l) + { +// writeln("QList opAssign"); + if (d != l.d) { + QListData.Data* nd = cast(QListData.Data*)l.d; + nd.ref_.increment(); + if (!d.ref_.decrement()) + free(d); + d = nd; + if (!d.sharable) + detach_helper(); + } + return this; + } + + int length() const { return p.size(); } + int size() const { return length; } + + void detach() { if (d.ref_.load() != 1) detach_helper(); } + + private void detach_helper() + { + Node *n = cast(Node*)(p.begin()); + QListData.Data* x = p.detach2(); + node_copy(cast(Node*)(p.begin()), cast(Node*)(p.end()), n); + if (!x.ref_.decrement()) + free(x); + } + + void append(const T t) // fix to const ref for complex types TODO + { + detach(); + static if (isQObjectType!T || isObjectType!T || isValueType!T) + { + node_construct(cast(Node*)(p.append()), t); + } + else + { + const T cpy = t; + node_construct(cast(Node*)(p.append()), cpy); + } + } + + alias append opCatAssign; + + static if (isQObjectType!T || isObjectType!T || isValueType!T || is(T == string)) + { + T at(int i) const + { + assert(i >= 0 && i < p.size(), "QList!T.at(): index out of range"); + return (cast(Node*)(p.at(i))).t(); + } + T opIndex(int i) + { + assert(i >= 0 && i < p.size(), "QList!T.at(): index out of range"); + return (cast(Node*)(p.at(i))).t(); + } + } + else + { + const (T) at(int i) const // DMD BUG + { + assert(i >= 0 && i < p.size(), "QList!T.at(): index out of range"); + return (cast(Node*)(p.at(i))).t(); + } + ref T opIndex(int i) + { + assert(i >= 0 && i < p.size(), "QList!T.at(): index out of range"); + return (cast(Node*)(p.at(i))).t(); + } + } + + static if (isQObjectType!T || isObjectType!T || isValueType!T) //binded types + void node_construct(Node *n, const T t) + { + static if (isValueType!T) + { + if (isLarge!T() || isStatic!T()) // TODO should be static if + n.v = T.__constructNativeCopy(t.__nativeId); // n.v = new T(t); + else if (isComplex!T()) + T.__constructPlacedNativeCopy(t.__nativeId, n); // new (n) T(t); + else + T.__constructPlacedNativeCopy(t.__nativeId, n); // TODO should be *cast(T*)(n) = cast(T)(t); as it is a primitive type. fix when they are implemented with structs + } + else // in case of QObject or Object Qt types we place a pointer to a native object in the node + n = cast(Node*) t.__nativeId; + } + else static if (is(T == string)) + { + void node_construct(Node *n, T t) + { + QString.__constructPlacedQString(n, t); + } + } + else // native types + void node_construct(Node *n, const ref T t) + { + static if (TI.isLarge || TI.isStatic) + n.v = q_new!T(t); // n.v = new T(t); + else static if (TI.isComplex) + q_new_at(n, t); // new (n) T(t); + else + *cast(T*)(n) = cast(T)(t); + } + + void node_copy(Node *from, Node *to, Node *src) + { +// writeln("QList node_copy"); + static if (isQObjectType!T || isObjectType!T) + {} // ensure to do nothing. copying only a pointer + else static if(is(T == string)) + { + while(from != to) // TODO when porting to Qt 5 ensure that QTypeInfo<QString>.isLarge and .isStatic == false + QString.__constructPlacedNativeCopy(src++, from++); // new (from++) T(*reinterpret_cast<T*>(src++)); + } + else static if (isValueType!T) + { + if (TI.isLarge || TI.isStatic) // TODO should be static if + while(from != to) + (from++).v = T.__constructNativeCopy((src++).v); // (from++)->v = new T(*reinterpret_cast<T*>((src++)->v)); + else if (TI.isComplex) + while(from != to) + T.__constructPlacedNativeCopy(src++, from++); // new (from++) T(*reinterpret_cast<T*>(src++)); + } + else static if (TI.isLarge || TI.isStatic) + while(from != to) + (from++).v = q_new!T(*cast(T*)((src++).v)); + else static if (TI.isComplex) + while(from != to) + q_new_at(from++, *cast(T*)(src++)); + } + + T[] toArray() + { + T[] res; + res.length = this.length; + for(int i = 0; i < res.length; ++i) + { + static if (isValueType!T) + res[i] = new T(T.__constructNativeCopy(this.at(i).__nativeId)); // Node should probably provide a ptr method to directly extract pointer to the native value stored in the list to avoid creating a dummy D object in t() + else + res[i] = this.opIndex(i); + } + return res; + } + + void free(QListData.Data* data) + { +// writeln("QList data destroyed"); + node_destruct(cast(Node*)(data.array.ptr + data.begin), + cast(Node*)(data.array.ptr + data.end)); + if (data.ref_.load() == 0) + qFree(data); + } + + void node_destruct(Node *from, Node *to) + { + static if (isQObjectType!T || isObjectType!T) //binded types + {} // removing just pointers, do nothing + else static if (is(T == string)) + { + while (from != to) + --to, QString.__callNativeDestructor(to); + } + else static if (isValueType!T) //binded value types + { + if (isLarge!T() || isStatic!T()) // TODO should be static if + while (from != to) + --to, T.__deleteNativeObject(to.v); + else if (isComplex!T()) + while (from != to) + --to, T.__callNativeDestructor(to); + } + else + { + static if (TI.isLarge || TI.isStatic) + while (from != to) --to, q_delete(cast(T*)(to.v)); + else static if (TI.isComplex) + while (from != to) --to, cast(T*)(to).__dtor(); + } + } + + //iteration support + int opApply(int delegate(ref T) dg) + { + int result = 0; + int sz = this.length; + for (int i = 0; i < sz; i++) + { + static if (isQtReference!T) + { + T t = this[i]; // hack to avoid "is not an lvalue" error, since dg accepts ref T + result = dg(t); + } + else + result = dg(this[i]); + + if (result) + break; + } + return result; + } +} + +alias QList!string QStringList; + +QList!T toQList(T)(T[] src) +{ + auto res = QList!T.opCall(); + foreach(elem; src) + res.append(elem); + return res; +} + +QList!T qList(T)() +{ + return QList!T.opCall(); +} + +extern(C) void qtd_create_QList(void *nativeId); +extern(C) void qtd_create_QList_double(void *nativeId); + +extern(C) void qtd_create_QList_QObject(void *nativeId);
--- a/qt/core/QMetaObject.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/core/QMetaObject.d Sun Feb 07 16:04:36 2010 +0000 @@ -4,14 +4,115 @@ import qt.core.QObject; import qt.QtdObject; +import std.algorithm; +import std.string; +import std.stdio; + +class Meta +{ + string name; +} + +class MetaType : Meta +{ + this() + { + } +} + +class MetaVariable : Meta +{ + MetaType type; +} + +class MetaCallable : Meta { } + +class MetaMethod : Meta { } + +class QMetaArgument : MetaVariable { } + +class QMetaMethod : MetaMethod +{ +// QMetaArgument[] arguments; + string signature; + int indexOfMethod; + + this(string signature_, int indexOfMethod_) + { + signature = signature_; + indexOfMethod = indexOfMethod_; + } + + string args() const + { + int openBracket = indexOf(signature, '('); + if(signature.length - openBracket - 2 > 0) + return signature[openBracket + 1 .. $-1]; + else + return ""; + } + + string name() const + { + int openBracket = indexOf(signature, '('); + return signature[0..openBracket]; + } +} + +class QMetaSignal : QMetaMethod +{ + this(string signature_, int indexOfMethod_) + { + super(signature_, indexOfMethod_); + } +} + +class QMetaSlot : QMetaMethod +{ + this(string signature_, int indexOfMethod_) + { + super(signature_, indexOfMethod_); + } +} + +class MetaObject : MetaType +{ + MetaObject _base; +} + +struct QMetaObjectNative +{ + QMetaObjectNative *superdata; + immutable(char) *stringdata; + const(uint) *data; + void *extradata; +} + +class QMetaException : Exception { this(string msg) { super(msg); } } + final class QMetaObject { + enum Call + { + InvokeMetaMethod, + ReadProperty, + WriteProperty, + ResetProperty, + QueryPropertyDesignable, + QueryPropertyScriptable, + QueryPropertyStored, + QueryPropertyEditable, + QueryPropertyUser, + CreateInstance + } + private { - void* _nativeId; + QMetaObjectNative* _nativeId; QMetaObject _base; // super class QMetaObject _firstDerived; // head of the linked list of derived classes QMetaObject _next; // next sibling on this derivation level + QMetaMethod[] _methods; ClassInfo _classInfo; QObject function(void* nativeId) _createWrapper; @@ -24,7 +125,7 @@ } // NOTE: construction is split between this non-templated constructor and 'construct' function below. - this(void* nativeId, QMetaObject base) + this(QMetaObjectNative* nativeId, QMetaObject base) { _nativeId = nativeId; if (base) @@ -57,7 +158,7 @@ /++ +/ - void* nativeId() + QMetaObjectNative* nativeId() { return _nativeId; } @@ -69,6 +170,60 @@ return _classInfo; } + const (QMetaMethod[]) methods() + { + return _methods; + } + + void addMethod(QMetaMethod method_) + { + _methods ~= method_; + } + + QMetaMethod lookUpMethod(string slot) + { + foreach (method; _methods) + if (method.signature == slot) + return method; + if (_base) + return _base.lookUpMethod(slot); + else + return null; + } + + QMetaSignal lookUpSignal(string signal) + { + foreach (method; _methods) + if (method.signature == signal && cast(QMetaSignal)method) + return cast(QMetaSignal)method; + if (_base) + return _base.lookUpSignal(signal); + else + return null; + } + + QMetaMethod[] lookUpMethodOverloads(string methodName) + { + typeof(return) result; + foreach (method; _methods) + if (method.name == methodName) + result ~= method; + if (_base) + result ~= _base.lookUpMethodOverloads(methodName); + return result; + } + + QMetaSignal[] lookUpSignalOverloads(string signalName) + { + typeof(return) result; + foreach (method; _methods) + if (method.name == signalName && cast(QMetaSignal)method) + result ~= cast(QMetaSignal)method; + if (_base) + result ~= _base.lookUpSignalOverloads(signalName); + return result; + } + private QMetaObject lookupDerived(void*[] moIds) { assert (moIds.length >= 1); @@ -123,12 +278,113 @@ moIds[--moCount] = moId = qtd_QMetaObject_superClass(moId); result = lookupDerived(moIds)._createWrapper(nativeObjId); - } + } } } return result; } + + static void activate(QObject sender, QMetaObject m, int local_signal_index, void **argv) + { + qtd_QMetaObject_activate_3(sender.__nativeId, m.nativeId, local_signal_index, argv); + } + + static void activate(QObject sender, QMetaObject m, int from_local_signal_index, int to_local_signal_index, void **argv) + { + qtd_QMetaObject_activate_4(sender.__nativeId, m.nativeId, from_local_signal_index, to_local_signal_index, argv); + } + + static bool connect(const QObject sender, int signal_index, + const QObject receiver, int method_index, + int type = 0, int *types = null) + { + return qtd_QMetaObject_connect(sender.__nativeId, signal_index, receiver.__nativeId, method_index, type, types); + } + + int indexOfMethod_Cpp(string method) + { + return qtd_QMetaObject_indexOfMethod(_nativeId, toStringz(method)); + } + + int methodCount() + { + return qtd_QMetaObject_methodCount(_nativeId); + } + + static void connectImpl(QObject sender, string signalString, QObject receiver, string methodString, int type) + { + QMetaSignal[] signals; + QMetaMethod[] methods; + QMetaSignal signal; + QMetaMethod method; + + if(indexOf(signalString, '(') > 0) + signal = sender.metaObject.lookUpSignal(signalString); + else + signals = sender.metaObject.lookUpSignalOverloads(signalString); // parameters not specified. Looking for a match + + if(indexOf(methodString, '(') > 0) + method = receiver.metaObject.lookUpMethod(methodString); + else + methods = receiver.metaObject.lookUpMethodOverloads(methodString); // parameters not specified. Looking for a match + + if(!signal && !method) + { + Top: + foreach(sig; signals) + foreach(meth; methods) + if(startsWith(sig.args, meth.args)) + { + signal = sig; + method = meth; + break Top; + } + } + else if (!signal) + { + foreach(sig; signals) + if(startsWith(sig.args, method.args)) + { + signal = sig; + break; + } + } + else if (!method) + { + foreach(meth; methods) + if(startsWith(signal.args, meth.args)) + { + method = meth; + break; + } + } + + bool success = false; + + if(!signal && !method) + { + success = false; + } + else + { + int signalIndex = signal.indexOfMethod; + int methodIndex = method.indexOfMethod; + success = QMetaObject.connect(sender, signalIndex, receiver, methodIndex, type); + } + + if(!success) + throw new QMetaException("QMetaObject: Signal " ~ signalString ~ " and slot " ~ methodString ~ " cannot be found"); + } } -extern(C) void* qtd_QMetaObject_superClass(void* nativeId); \ No newline at end of file +extern(C) void qtd_QMetaObject_activate_3(void* sender, void* m, int local_signal_index, void **argv); +extern(C) void qtd_QMetaObject_activate_4(void *sender, void* m, int from_local_signal_index, int to_local_signal_index, void **argv); +extern(C) bool qtd_QMetaObject_connect(const void* sender, int signal_index, + const void* receiver, int method_index, + int type, int *types); + +extern(C) int qtd_QMetaObject_indexOfMethod(void *nativeId, const(char) *method); +extern(C) int qtd_QMetaObject_methodCount(void *nativeId); + +extern(C) void* qtd_QMetaObject_superClass(void* nativeId);
--- a/qt/core/QString.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/core/QString.d Sun Feb 07 16:04:36 2010 +0000 @@ -13,37 +13,100 @@ struct QString { - public static QString opCall(void* ptr, bool proxy) { + public static QString opCall() + { QString str; - str.native_id = ptr; + qtd_QString_placed_ctor(&str); return str; } - private void* native_id; + ~this() + { + qtd_QString_call_destructor(&this); + } + + void opAssign(string str) + { + qtd_QString_assign_fromUtf8(&this, str); + } + + this(string str) + { + qtd_QString_new_fromUtf8_at(&this, str); + } + + public static void __constructPlacedQString(void* place, string source) { + qtd_QString_new_fromUtf8_at(place, source); + } + // service stuff + static void* __constructNativeCopy(const void* orig) { + return qtd_QString_QString_QString(cast(void*)orig); + } + + static void* __constructPlacedNativeCopy(const void* orig, void* place) { + return qtd_QString_placed_copy(orig, place); + } + + public static void __deleteNativeObject(void* ptr) { + qtd_QString_destructor(ptr); + } + + public static void __callNativeDestructor(void* ptr) { + qtd_QString_call_destructor(ptr); + } + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = false; + enum bool isPointer = false; + enum bool isDummy = false; + } + +private: + void *dummy; // sizeof(QString) == sizeof(void*) +} + +struct QStringUtil +{ public static final string toNativeString(void* qstring) { - wchar* arr = __qtd_QString_utf16(qstring); - int size = __qtd_QString_size(qstring); + wchar* arr = qtd_QString_utf16(qstring); + int size = qtd_QString_size(qstring); return .toUTF8(arr[0..size]); } + + public static string fromUtf8(string source) { + return source; + } + + public static QStringUtil opCall(void* ptr, bool proxy) { + QStringUtil str; + str.__nativeId = ptr; + return str; + } + public void* __nativeId; + public final string toNativeString() { - return toNativeString(native_id); + return QStringUtil.toNativeString(__nativeId); } public void assign(string text) { - __qtd_QString_operatorAssign(native_id, text); - } - - public static string fromUtf8(string source) { - return source; + qtd_QString_operatorAssign(__nativeId, text); } -/* - public static string fromUtf16(wstring src) { - version(Tango) - }*/ } +private extern(C) void* qtd_QString_placed_copy(const void* orig, void* place); -private extern (C) wchar* __qtd_QString_utf16(void* __this_nativeId); -private extern (C) int __qtd_QString_size(void* __this_nativeId); -private extern (C) void __qtd_QString_operatorAssign(void* __this_nativeId, string text); \ No newline at end of file +private extern (C) void qtd_QString_destructor(void* __this_nativeId); +private extern (C) void qtd_QString_call_destructor(void *ptr); + +private extern (C) void* qtd_QString_QString_QString(void* orig); + +private extern (C) wchar* qtd_QString_utf16(void* __this_nativeId); +private extern (C) int qtd_QString_size(void* __this_nativeId); +private extern (C) void qtd_QString_operatorAssign(void* __this_nativeId, string text); +private extern (C) void* qtd_QString_new_fromUtf8_at(void* place, string text); + +private extern (C) void qtd_QString_placed_ctor(void* place); +private extern (C) void qtd_QString_assign_fromUtf8(QString *__qt_this, string text); \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/core/QTypeInfo.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,139 @@ +module qt.core.QTypeInfo; + +//import qt.QGlobal; +//import qt.qtd.Atomic; + +/* + The catch-all template. +*/ +import std.traits; + +import qt.qtd.MetaMarshall; +import qt.core.QString; + +bool qIsDetached(T)(ref T) { return true; } + +template isBasicType(T) +{ + enum isBasicType = isNumeric!T || is(T == bool) || is(T == enum); +} + +template QTypeInfo(T) +{ + static if(is(T == string)) + { + alias QString.QTypeInfo QTypeInfo; + } + else static if(isBasicType!T) + { + public enum + { + isPointer = false, + isComplex = false, + isStatic = false, + isLarge = (T.sizeof > (void*).sizeof), + isDummy = false + } + } + else static if(is(T.QTypeInfo)) + { + alias T.QTypeInfo QTypeInfo; // alias member QTypeInfo + } + else static if ( isQObjectType!T || isObjectType!T ) + { + public enum // are pointers + { + isPointer = true, + isComplex = false, + isStatic = false, + isLarge = false, + isDummy = false + } + } + else // default parameters + { + public enum + { + isPointer = isPointer!T, + isComplex = !isPointer, + isStatic = !isPointer, + isLarge = (T.sizeof > (void*).sizeof), + isDummy = false + } + } +} + + +/* + Specialize a specific type with: + + Q_DECLARE_TYPEINFO(type, flags); + + where 'type' is the name of the type to specialize and 'flags' is + logically-OR'ed combination of the flags below. +*/ + +/* presents in QGlobal +enum { /* TYPEINFO flags + Q_COMPLEX_TYPE = 0, + Q_PRIMITIVE_TYPE = 0x1, + Q_STATIC_TYPE = 0, + Q_MOVABLE_TYPE = 0x2, + Q_DUMMY_TYPE = 0x4 +} +*/ + +/* +template QTypeInfo(alias FLAGS) +{ + template QTypeInfo(TYPE) + { + public: + enum { + isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0), + isStatic = (((FLAGS) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), + isLarge = (TYPE.sizeof > (void*).sizeof), + isPointer = false, + isDummy = (((FLAGS) & Q_DUMMY_TYPE) != 0) + } + } +} +*/ +/* + Specialize a shared type with: + + Q_DECLARE_SHARED(type); + + where 'type' is the name of the type to specialize. NOTE: shared + types must declare a 'bool isDetached(void) const;' member for this + to work. +*/ +/* +#if defined Q_CC_MSVC && _MSC_VER < 1300 +template <typename T> +inline void qSwap_helper(T &value1, T &value2, T*) +{ + T t = value1; + value1 = value2; + value2 = t; +} +#define Q_DECLARE_SHARED(TYPE) \ +template <> inline bool qIsDetached<TYPE>(TYPE &t) { return t.isDetached(); } \ +template <> inline void qSwap_helper<TYPE>(TYPE &value1, TYPE &value2, TYPE*) \ +{ \ + const TYPE::DataPtr t = value1.data_ptr(); \ + value1.data_ptr() = value2.data_ptr(); \ + value2.data_ptr() = t; \ +} +#else +#define Q_DECLARE_SHARED(TYPE) \ +template <> inline bool qIsDetached<TYPE>(TYPE &t) { return t.isDetached(); } \ +template <typename T> inline void qSwap(T &, T &); \ +template <> inline void qSwap<TYPE>(TYPE &value1, TYPE &value2) \ +{ \ + const TYPE::DataPtr t = value1.data_ptr(); \ + value1.data_ptr() = value2.data_ptr(); \ + value2.data_ptr() = t; \ +} +#endif +*/ \ No newline at end of file
--- a/qt/d2/qt/QtdObject.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/d2/qt/QtdObject.d Sun Feb 07 16:04:36 2010 +0000 @@ -27,8 +27,6 @@ protected QtdObjectFlags __flags_; void* __nativeId; - mixin SignalHandlerOps; - this(void* nativeId, QtdObjectFlags flags = QtdObjectFlags.none) { __nativeId = nativeId;
--- a/qt/d2/qt/Signal.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/d2/qt/Signal.d Sun Feb 07 16:04:36 2010 +0000 @@ -12,1038 +12,151 @@ module qt.Signal; public import qt.QGlobal; -public import - std.metastrings, - std.typetuple; +import qt.qtd.MetaMarshall; +import qt.qtd.Meta; + import core.stdc.stdlib : crealloc = realloc, cfree = free; import core.stdc.string : memmove; import - std.traits, core.thread, - core.exception; - -private: // private by default - -alias void delegate(Object) DEvent; - -extern(C) void rt_attachDisposeEvent(Object o, DEvent e); -extern(C) void rt_detachDisposeEvent(Object o, DEvent e); -extern(C) Object _d_toObject(void* p); - -void realloc(T)(ref T[] a, size_t length) -{ - a = (cast(T*)crealloc(a.ptr, length * T.sizeof))[0..length]; - if (!a.ptr) - new OutOfMemoryError(__FILE__, __LINE__); -} + core.exception, + std.algorithm; - -void append(T)(ref T[] a, T element) -{ - auto newLen = a.length + 1; - a = (cast(T*)crealloc(a.ptr, newLen * T.sizeof))[0..newLen]; - if (!a.ptr) - new OutOfMemoryError(__FILE__, __LINE__); - a[newLen - 1] = element; -} +public import + std.typetuple, + std.traits, + std.conv, + std.metastrings; -void move(T)(ref T[] a, size_t src, size_t dest, size_t length) -{ - if (a.length > 1) - memmove(a.ptr + dest, a.ptr + src, length * T.sizeof); -} - -// COMPILER BUG: Though this is private cannot name it 'remove' because of conflicts -// with Array.remove -void erase(T)(ref T[] a, size_t i) +public import std.string : strip, toStringz; + +/** The beast that takes string representation of function arguments + * and returns an array of default values it doesn't check if arguments + * without default values follow the arguments with default values for + * simplicity. It is done by mixing in an delegate alias. + */ +string[] defaultValues(string signature) { - auto newLen = a.length - 1; - move(a, i + 1, i, newLen); - realloc(a, newLen); -} - -version (QtdUnittest) -{ - unittest - { - int[] a; - realloc(a, 16); - assert(a.length == 16); - foreach (i, ref e; a) - e = i; - realloc(a, 4096); - assert(a.length == 4096); - foreach (i, e; a[0..16]) - assert(e == i); - cfree(a.ptr); - } -} + int braces = 0; + bool inDefaultValue = false; + bool inStringLiteral = false; + string[] res; + int startValue = 0; + + if(strip(signature).length == 0) + return res; -//TODO: should be in the standard library -struct STuple(A...) -{ - static string genSTuple() - { - string r = ""; - foreach (i, e; A) - r ~= A[i].stringof ~ " _" ~ ToString!(i) ~ ";"; - return r; - } - - mixin (genSTuple); - template at(size_t i) { mixin("alias _" ~ ToString!(i) ~ " at;"); }; -} - -enum SignalEventId -{ - firstSlotConnected, - lastSlotDisconnected -} - -public class SignalException : Exception -{ - this(string msg) + foreach (i,c; signature) { - super(msg); - } -} - -struct Fn -{ - void* funcptr; - - static typeof(this) opCall(R, A...)(R function(A) fn) - { - typeof(this) r; - r.funcptr = fn; - return r; - } - - template call(R) - { - R call(A...)(A args) + if(!inStringLiteral) { - alias R function(A) Fn; - return (cast(Fn)funcptr)(args); - } - } - - S get(S)() - { - static assert (is(typeof(*S.init) == function)); - return cast(S)funcptr; - } -} - -struct Dg -{ - void* context; - void* funcptr; - - static typeof(this) opCall(R, A...)(R delegate(A) dg) - { - typeof(this) r; - r.context = dg.ptr; - r.funcptr = dg.funcptr; - return r; - } - - template call(R) - { - R call(A...)(A args) - { - R delegate(A) dg; // BUG: parameter storage classes are ignored - dg.ptr = context; - dg.funcptr = cast(typeof(dg.funcptr))funcptr; - return dg(args); - } - } - - S get(S)() - { - static assert (is(S == delegate)); - S r; - r.ptr = context; - r.funcptr = cast(typeof(r.funcptr))funcptr; - return r; - } -} - -struct Slot(R) -{ - alias R Receiver; - - Receiver receiver; - Dg invoker; - ConnectionFlags flags; - - static if (is(Receiver == Dg)) - { - static const isDelegate = true; - - bool isDisposed() - { - return !receiver.funcptr; - } - - void dispose() - { - receiver.funcptr = null; - receiver.context = null; + if(c == '{' || c =='(') + braces++; + else if(c == '}' || c ==')') + braces--; } - Object getObject() - { - return flags & ConnectionFlags.NoObject || !receiver.context - ? null : _d_toObject(receiver.context); - } - } - else - static const isDelegate = false; -} - -enum SlotListId -{ - Func, // function pointers - Weak, // object delegates stored in C heap - Strong // delegates stored in GC heap -} - -/** - Used to specify the type of a signal-to-slot connection. - - Examples: ----- -class Sender -{ - mixin Signal!("changed"); - void change() - { - changed.emit; - } -} - - -class Receiver -{ - void alarm() {} -} - -void main() -{ - auto s = new Sender; - auto r = new Receiver; - s.changed.connect(&r.alarm); // now s weakly references r - - r = null; - // collect garbage (assume there is no more reachable pointers - // to the receiver and it gets finalized) - ... - - s.change; - // weak reference to the receiving object - // has been removed from the sender's connection lists. - - r = new Receiver; - s.changed.connect(&r.alarm, ConnectionFlags.Strong); - - r = null; - // collect garbage - ... - // the receiving object has not been finalized because s strongly references it. - - s.change; // the receiver is called. - delete r; - s.change; // the receiver is disconnected from the sender. - - static void foo() - { - } - - s.changed.connect(&foo); - s.changed.emit; // foo is called. - s.changed.disconnect(&foo); // must be explicitly disconnected. - - void bar() - { - } - - // ConnectionFlags.NoObject must be specified for delegates - // to non-static local functions or struct member functions. - s.changed.connect(&bar, ConnectionFlags.NoObject); - s.changed.emit; // bar is called. - s.changed.disconnect(&bar); // must be explicitly disconnected. -} ----- -*/ -public enum ConnectionFlags : ubyte -{ - /// - None, - /** - The receiver will be stored as weak reference (implied if ConnectionFlags.NoObject is not specified). - If the signal receiver is not a function pointer or a delegate referencing a D class instance. - the sender will not be notified when the receiving object is deleted and emitting the signal - connected to that receiving object will result in undefined behavior. - */ - Weak = 0x0001, - /** - The receiver is stored as strong reference (implied if ConnectionFlags.NoObject is specified). - */ - Strong = 0x0002, - /** - Must be specified if the receiver is not a function pointer or a delegate referencing a D class instance. - */ - NoObject = 0x0004 - - // Queued = 0x0004, - // BlockingQueued = 0x0008 -} - - -struct SlotList(SlotT, bool strong = false) -{ - alias SlotT SlotType; - SlotType[] data; - - void length(size_t length) - { - static if (strong) - data.length = length; - else - realloc(data, length); - } - - SlotType* add(SlotType slot) - { - auto oldLen = data.length; - length = oldLen + 1; - auto p = &data[oldLen]; - *p = slot; - return p; - } - - SlotType* get(int slotId) - { - return &data[slotId]; - } - - void remove(int slotId) - { - move(data, slotId, slotId + 1, data.length - slotId - 1); - data = data[0..$ - 1]; - } - - size_t length() - { - return data.length; - } - - void free() - { - static if (!strong) - cfree(data.ptr); - } -} - -public alias void delegate(int signalId, SignalEventId event) SignalEvent; - -struct Receivers -{ - struct Data - { - Object object; - int refs; - } - - Data[] data; - void add(Object receiver, DEvent disposeEvent) - { - foreach (ref d; data) + if(c == '\"' || c == '\'') { - if (d.object is receiver) - { - d.refs++; - return; + if (inStringLiteral) + { + if(signature[i-1] != '\\') + inStringLiteral = false; + } + else + { + inStringLiteral = true; } } - append(data, Data(receiver, 1)); - rt_attachDisposeEvent(receiver, disposeEvent); - } - - void remove(Object receiver, DEvent disposeEvent) - { - foreach (i, ref d; data) + if (!inStringLiteral && braces == 0) { - if (d.object is receiver) + if(c == '=') // found default value { - assert (d.refs); - d.refs--; - if (!d.refs) - { - .erase(data, i); - rt_detachDisposeEvent(receiver, disposeEvent); - } - return; - } - } - - assert (false); - } - - // remove all refarences for receiver, receiver has been disposed - void removeAll(Object receiver) - { - foreach (i, ref d; data) - { - if (d.object is receiver) - { - .erase(data, i); - return; + inDefaultValue = true; + startValue = i+1; } - } - } - - // remove all references for all receivers, detaching dispose events - void free(DEvent disposeEvent) - { - foreach (i, ref d; data) - rt_detachDisposeEvent(d.object, disposeEvent); - cfree(data.ptr); - data = null; - } -} - -struct SignalConnections -{ - bool isInUse; - - STuple!( - SlotList!(Slot!(Fn)), - SlotList!(Slot!(Dg)), - SlotList!(Slot!(Dg), true) - ) slotLists; - - STuple!( - Fn[], - Dg[] - ) delayedDisconnects; - - void addDelayedDisconnect(Fn r) - { - delayedDisconnects.at!(0) ~= r; - } - - void addDelayedDisconnect(Dg r) - { - delayedDisconnects.at!(1) ~= r; - } - - SlotListType!(slotListId)* getSlotList(int slotListId)() - { - return &slotLists.tupleof[slotListId]; - } - - bool hasSlots() - { - foreach(i, e; slotLists.tupleof) - { - if (slotLists.tupleof[i].length) - return true; - } - return false; - } - - int slotCount() - { - int count; - foreach(i, e; slotLists.tupleof) - count += slotLists.at!(i).length; - return count; - } - - void slotListLengths(int[] lengths) - { - foreach(i, e; slotLists.tupleof) - lengths[i] = slotLists.at!(i).length; - } - - SlotType!(slotListId)* addSlot(int slotListId)(SlotType!(slotListId) slot) - { - return getSlotList!(slotListId).add(slot); - } - - void removeSlot(int slotListId)(int slotId) - { - slotLists.at!(slotListId).remove(slotId); - } - - void free() - { - foreach(i, e; slotLists.tupleof) - { - static if (is(typeof(slotLists.at!(i).free))) - slotLists.at!(i).free; - } - } - - void onReceiverDisposed(Object receiver) - { - foreach (i, e; slotLists.tupleof) - { - static if (slotLists.at!(i).SlotType.isDelegate) + else if(c == ',') // next function argument { - foreach (ref slot; slotLists.at!(i).data) + if (inDefaultValue) { - if (slot.getObject is receiver) - slot.dispose; + res ~= signature[startValue..i]; + inDefaultValue = false; } } } } - - template SlotListType(int slotListId) - { - alias typeof(slotLists.tupleof)[slotListId] SlotListType; - } + + if (inDefaultValue) + res ~= signature[startValue..$]; - template SlotType(int slotListId) - { - alias SlotListType!(slotListId).SlotType SlotType; - } + return res; +} - template ReceiverType(int slotListId) - { - alias SlotType!(slotListId).Receiver ReceiverType; - } - - static const slotListCount = slotLists.tupleof.length; +int defaultValuesLength(string[] defVals) +{ + return defVals.length; } -private Object signalSender_; - -/** - If called from a slot, returns the object - that is emitting the signal. Otherwise, returns null. -*/ -public Object signalSender() { - return signalSender_; +// templates for extracting data from static meta-information of signals, slots or properties +// public alias TypeTuple!("name", index, OwnerClass, ArgTypes) __signal +template MetaEntryName(source...) +{ + enum MetaEntryName = source[0]; // name of the metaentry is the first element } -public final class SignalHandler +template MetaEntryOwner(source...) { - SignalConnections[] connections; - Receivers receivers; - Object owner; - int blocked; - - SignalEvent signalEvent; - - alias SignalConnections.SlotType SlotType; - alias SignalConnections.ReceiverType ReceiverType; - - public this(Object owner_) { - owner = owner_; - } - - private SignalConnections* getConnections(int signalId) - { - if (signalId < connections.length) - return &connections[signalId]; - return null; - } - - private SlotType!(slotListId)* addSlot(int slotListId)(int signalId, ReceiverType!(slotListId) receiver, - Dg invoker, ConnectionFlags flags) - { - if (signalId >= connections.length) - connections.length = signalId + 1; - auto slot = connections[signalId].addSlot!(slotListId)(SlotType!(slotListId)(receiver, invoker)); - - static if (slot.isDelegate) - { - if (!(flags & ConnectionFlags.NoObject)) - receivers.add(_d_toObject(receiver.context), &onReceiverDisposed); - } - - if (signalEvent && connections[signalId].slotCount == 1) - signalEvent(signalId, SignalEventId.firstSlotConnected); - - return slot; - } - - void onReceiverDisposed(Object receiver) - { - synchronized(this) - { - foreach(ref c; connections) - c.onReceiverDisposed(receiver); - receivers.removeAll(receiver); - } - } - - private void removeSlot(int slotListId)(int signalId, int slotId) - { - auto slot = connections[signalId].getSlotList!(slotListId).get(slotId); - static if (slot.isDelegate) - { - if (auto obj = slot.getObject) - receivers.remove(obj, &onReceiverDisposed); - } - - connections[signalId].removeSlot!(slotListId)(slotId); - - if (signalEvent && !connections[signalId].slotCount) - signalEvent(signalId, SignalEventId.lastSlotDisconnected); - } - - size_t slotCount(int signalId) - { - synchronized(this) - { - auto con = getConnections(signalId); - if (con) - return con.slotCount; - return 0; - } - } - - void connect(Receiver)(int signalId, Receiver receiver, - Dg invoker, ConnectionFlags flags) - { - synchronized(this) - { - static if (is(typeof(receiver.context))) - { - Object obj; - if ((flags & ConnectionFlags.NoObject)) - { - // strong by default - if (flags & ConnectionFlags.Weak) - addSlot!(SlotListId.Weak)(signalId, receiver, invoker, flags); - else - addSlot!(SlotListId.Strong)(signalId, receiver, invoker, flags); - } - else - { - // weak by default - if (flags & ConnectionFlags.Strong) - addSlot!(SlotListId.Strong)(signalId, receiver, invoker, flags); - else - addSlot!(SlotListId.Weak)(signalId, receiver, invoker, flags); - } - } - else - addSlot!(SlotListId.Func)(signalId, receiver, invoker, flags); - } - } - - void disconnect(Receiver)(int signalId, Receiver receiver) - { - synchronized(this) - { - auto cons = getConnections(signalId); - if (!cons) - return; - - // if called from a slot being executed by this signal, delay disconnection - // until all slots has been called. - if (cons.isInUse) - { - cons.addDelayedDisconnect(receiver); - return; - } - - TOP: - foreach (slotListId, e; cons.slotLists.tupleof) - { - /// COMPILER BUG: ReceiverType is evaluated to expression instead of type. - static if (is(typeof(cons.ReceiverType!(slotListId)) == Receiver)) - { - auto slotList = cons.getSlotList!(slotListId); - for (int slotId; slotId < slotList.length;) - { - auto slot = slotList.get(slotId); - static if (slot.isDelegate) - { - if (slot.isDisposed) - { - removeSlot!(slotListId)(signalId, slotId); - continue; - } - } - - if (slot.receiver == receiver) - { - removeSlot!(slotListId)(signalId, slotId); - break TOP; - } - - slotId++; - } - } - } - } - } - - void emit(A...)(size_t signalId, A args) - { - synchronized(this) - { - if (signalId >= connections.length || blocked) - return; - auto cons = &connections[signalId]; - - if (cons.hasSlots) - { - { - cons.isInUse = true; - signalSender_ = owner; - scope(exit) - { - cons.isInUse = false; - signalSender_ = null; - } - - // Store the lengths to avoid calling new slots - // connected in the slots being called. - // dmd bug: int[cons.slotListCount] fails - static const c = cons.slotListCount; - int[c] lengths = void; - cons.slotListLengths(lengths); - - foreach (slotListId, e; cons.slotLists.tupleof) - { - auto slotList = cons.getSlotList!(slotListId); - for (size_t slotId; slotId < lengths[slotListId];) - { - auto slot = slotList.get(slotId); - static if (slot.isDelegate) - { - if (slot.isDisposed) - { - removeSlot!(slotListId)(signalId, slotId); - lengths[slotListId]--; - continue; - } - } - - slot.invoker.call!(void)(slot.receiver, args); - ++slotId; - } - } - } - - - // process delayed disconnects if any - foreach(i, e; cons.delayedDisconnects.tupleof) - { - if (cons.delayedDisconnects.at!(i).length) - { - foreach (d; cons.delayedDisconnects.at!(i)) - disconnect(signalId, d); - cons.delayedDisconnects.at!(i).length = 0; - } - } - } - } - } - - // Adjusts signal arguments and calls the slot. S - slot signature, A - signal arguments - private void invokeSlot(S, Receiver, A...)(Receiver r, A args) - { - r.get!(S)()(args[0..ParameterTypeTuple!(S).length]); - } - - void blockSignals() - { - synchronized(this) - blocked++; - } - - void unblockSignals() - { - synchronized(this) - { - if(!blocked) - throw new SignalException("Signals are not blocked"); - blocked--; - } - } - - ~this() - { - receivers.free(&onReceiverDisposed); - foreach(ref c; connections) - c.free; - } + alias TupleWrapper!(source[2]).at[0] MetaEntryOwner; // class that owns the property is the third + // Compiler #BUG 3092 - evaluates MetaEntryOwner as a Tuple with one element } -public template SignalHandlerOps() +template MetaEntryArgs(source...) { - static assert (is(typeof(this.signalHandler)), - "SignalHandlerOps is already instantiated in " ~ typeof(this).stringof ~ " or one of its base classes"); - -protected: - SignalHandler signalHandler_; // manages signal-to-slot connections - - final SignalHandler signalHandler() - { - if (!signalHandler_) - { - signalHandler_ = new SignalHandler(this); - onSignalHandlerCreated(signalHandler_); - } - return signalHandler_; - } - - void onSignalHandlerCreated(ref SignalHandler sh) - { - } - -public: - final void blockSignals() - { - signalHandler.blockSignals(); - } - - final void unblockSignals() - { - signalHandler.unblockSignals(); - } - - template connect(string signalName, A...) - { - static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None) - if (isFnOrDg!(Func)) - { - alias findSignal!(T, signalName, Func, A).result sig; - auto sh = sender.signalHandler(); - static if (isFn!(Func)) - alias Fn Callable; - else - alias Dg Callable; - auto invoker = Dg(&sh.invokeSlot!(typeof(func), Callable, sig[2..$])); - sh.connect(sig[1], Callable(func), invoker, flags); - } - } - - template disconnect(string signalName, A...) - { - static void connect(T, Func)(T sender, Func func, ConnectionFlags flags = ConnectionFlags.None) - if (isFnOrDg!(Func)) - { - alias findSignal!(T, signalName, Func, A).result sig; - auto sh = sender.signalHandler(); - static if (isFn!(Func)) - alias Fn Callable; - else - alias Dg Callable; - sh.disconnect(sig[1], Callable(func)); - } - } -/* - template slotCount(string signalName, A...) - { - debug static void slotCount(T)(T sender) - { - alias findSignal!(T, signalName, Func, A).result sig; - auto sh = sender.signalHandler(); - return sh.slotCount(sig[1]); - } - } - */ + alias ParameterTypeTuple!(source[1]) MetaEntryArgs; // arguments-tuple starts from the fourth position } -/** - New implementation. -*/ - -const string signalPrefix = "__signal"; - template TupleWrapper(A...) { alias A at; } -template isDg(Dg) -{ - enum isDg = is(Dg == delegate); -} - -template isFn(Fn) -{ - enum isFn = is(typeof(*Fn.init) == function); -} - -template isFnOrDg(Dg) +string convertSignalArguments(Args...)() { - enum isFnOrDg = isFn!(Dg) || isDg!(Dg); -} - -string joinArgs(A...)() -{ - string res = ""; - static if(A.length) - { - res = A[0].stringof; - foreach(k; A[1..$]) - res ~= "," ~ k.stringof; - } +// void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) }; + // at least for string argument need to construct a QString value + string res = prepareSignalArguments!(Args); + + res ~= "void*[" ~ __toString(Args.length+1) ~ "] _a = [null"; + foreach(i, _; Args) + res ~= ", " ~ "cast(void*) (" ~ convertSignalArgument!(Args[i])("_t" ~ __toString(i)) ~ ")"; + res ~= "];\n"; return res; } -template SlotPred(T1, T2) -{ - enum SlotPred = is(T1 : T2); -} - -template CheckSlot(alias Needle, alias Source) -{ - static if(Needle.at.length <= Source.at.length) - enum CheckSlot = CheckArgs!(Needle, Source, SlotPred, 0).value; - else - enum CheckSlot = false; -} - -template SignalPred(T1, T2) -{ - enum SignalPred = is(T1 == T2); -} - -template CheckSignal(alias Needle, alias Source) -{ - static if(Needle.at.length == Source.at.length) - enum CheckSignal = CheckArgs!(Needle, Source, SignalPred, 0).value; - else - enum CheckSignal = false; -} - -template CheckArgs(alias Needle, alias Source, alias pred, int i) -{ - static if (i < Needle.at.length) - { - static if (pred!(Needle.at[i], Source.at[i])) - enum value = CheckArgs!(Needle, Source, pred, i + 1).value; - else - enum value = false; - } - else - { - enum value = true; - } -} - -template SigByNamePred(string name, SlotArgs...) -{ - template SigByNamePred(source...) - { - static if (source[0] == name) // only instantiate CheckSlot if names match - enum SigByNamePred = CheckSlot!(TupleWrapper!(SlotArgs), TupleWrapper!(source[2 .. $])); - else - enum SigByNamePred = false; - } -} - -template SigBySignPred(string name, SigArgs...) -{ - template SigBySignPred(source...) - { - static if (source[0] == name) // only instantiate CheckSignal if names match - enum SigBySignPred = CheckSignal!(TupleWrapper!(SigArgs), TupleWrapper!(source[2 .. $])); - else - enum SigBySignPred = false; - } -} - -template staticSymbolName(string prefix, int id) -{ - const string staticSymbolName = prefix ~ ToString!(id); -} - -template signatureString(string name, A...) -{ - const string signatureString = name ~ "(" ~ joinArgs!(A) ~ ")"; -} - -template findSymbolImpl(string prefix, C, int id, alias pred) -{ - static if ( is(typeof(mixin("C." ~ staticSymbolName!(prefix, id)))) ) - { - mixin ("alias C." ~ staticSymbolName!(prefix, id) ~ " current;"); - static if (pred!current) - alias current result; - else - alias findSymbolImpl!(prefix, C, id + 1, pred).result result; - } - else - { - alias void result; - } -} - -template findSymbol(string prefix, C, alias pred) -{ - alias findSymbolImpl!(prefix, C, 0, pred).result findSymbol; -} - -template findSignal(C, string name, Receiver, SigArgs...) -{ - alias TupleWrapper!(ParameterTypeTuple!Receiver) SlotArgsWr; - static if (SigArgs.length > 0) - { - alias findSymbol!(signalPrefix, C, SigBySignPred!(name, SigArgs)) result; - static if (is(result == void)) - static assert(0, "Signal " ~ name ~ "(" ~ joinArgs!SigArgs() ~ ") was not found."); - else - static if (!CheckSlot!(SlotArgsWr, TupleWrapper!(result[2 .. $]))) - static assert(0, "Signature of slot is incompatible with signal " ~ name ~ "."); - } - else - { - alias findSymbol!(signalPrefix, C, SigByNamePred!(name, SlotArgsWr.at)) result; - static if (is(result == void)) - static assert(0, "Signal " ~ name ~ " was not found."); - } -} - -string __toString(long v) -{ - if (v == 0) - return "0"; - - string ret; - - bool neg; - if (v < 0) - { - neg = true; - v = -v; - } - - while (v != 0) - { - ret = cast(char)(v % 10 + '0') ~ ret; - v = cast(long)(v / 10); - } - - if (neg) - ret = "-" ~ ret; - - return ret; -} - -public string SignalEmitter(A...)(SignalType signalType, string name, int index) +public string SignalEmitter(A...)(SignalType signalType, string name, string[] defVals, int localIndex) { string fullArgs, args; + int defValsLength = defVals.length; + string argsConversion = ""; + string argsPtr = "null"; static if (A.length) { - fullArgs = A[0].stringof ~ " a0"; - args = ", a0"; + while(A.length != defVals.length) + defVals = "" ~ defVals; + + fullArgs = A[0].stringof ~ " _t0"; + if (defVals[0].length) + fullArgs ~= " = " ~ defVals[0]; + args = "_t0"; foreach(i, _; A[1..$]) { - fullArgs ~= ", " ~ A[i+1].stringof ~ " a" ~ __toString(i+1); - args ~= ", a" ~ __toString(i+1); + fullArgs ~= ", " ~ A[i+1].stringof ~ " _t" ~ __toString(i+1); + if (defVals[i+1].length) + fullArgs ~= " = " ~ defVals[i+1]; + args ~= ", _t" ~ __toString(i+1); } + // build up conversion of signal args from D to C++ + argsPtr = "_a.ptr"; + argsConversion = convertSignalArguments!(A)(); } string attribute; string sigName = name; @@ -1051,197 +164,133 @@ name ~= "_emit"; else attribute = "protected "; - string str = attribute ~ "void " ~ name ~ "(" ~ fullArgs ~ ")" ~ - "{ this.signalHandler.emit(" ~ __toString(index) ~ args ~ "); }"; + + string indexArgs = __toString(localIndex); + if(defValsLength > 0) + indexArgs ~= ", " ~ __toString(localIndex+defValsLength); + string str = attribute ~ "final void " ~ name ~ "(" ~ fullArgs ~ ") {\n" ~ argsConversion ~ "\n" + ~ " QMetaObject.activate(this, typeof(this).staticMetaObject, " ~ indexArgs ~ ", " ~ argsPtr ~ ");\n" + ~ "}\n"; // ~ return str; } - /** ---------------- */ -/** - Examples: ----- -struct Args -{ - bool cancel; -} - -class C -{ - private int _x; - // reference parameters are not supported yet, - // so we pass arguments by pointer. - mixin Signal!("xChanging", int, Args*); - mixin Signal!("xChanged"); - - void x(int v) - { - if (v != _x) - { - Args args; - xChanging.emit(v, &args); - if (!args.cancel) - { - _x = v; - xChanged.emit; - } - } - } -} ----- -*/ +const string signalPrefix = "__signal"; +const string slotPrefix = "__slot"; enum SignalType { BindQtSignal, - NewSignal + NewSignal, + NewSlot } -template BindQtSignal(string name, A...) +string signature(T...)(string name) { - mixin SignalImpl!(0, name, SignalType.BindQtSignal, A); -} - -template Signal(string name, A...) -{ - mixin SignalImpl!(0, name, SignalType.NewSignal, A); + string res = name ~ "("; + foreach(i, _; T) + { + if(i > 0) + res ~= ","; + static if (isNativeType!(T[i])) + res ~= Unqual!(T[i]).stringof; + else + res ~= T[i].stringof; + } + res ~= ")"; + return res; } -template SignalImpl(int index, string name, SignalType signalType, A...) +// ------------------------------------------------------------------ + +string[] getSymbols(C)(string prefix) { - static if (is(typeof(mixin(typeof(this).stringof ~ ".__signal" ~ ToString!(index))))) - mixin SignalImpl!(index + 1, name, signalType, A); - else - { - // mixed-in once - static if (!is(typeof(this.signalHandler))) - mixin SignalHandlerOps; + string[] result; + auto allSymbols = __traits(derivedMembers, C); + foreach(s; allSymbols) + if(ctfeStartsWith(s, prefix)) + result ~= s; + return result; +} - mixin (SignalEmitter!(A)(signalType, name, index)); - mixin("public alias TypeTuple!(\"" ~ name ~ "\", index, A) __signal" ~ ToString!(index) ~ ";"); - } +string removePrefix(string source) +{ + foreach (i, c; source) + if (c == '_') + return source[i+1..$]; + return source; +} + +template Alias(T...) +{ + alias T Alias; } -extern(C) alias void function(void*) SlotConnector; - -debug (UnitTest) +// recursive search in the static meta-information +template findSymbolsImpl2(C, alias signals, int id) { - class A - { - mixin Signal!("scorched", int); + alias Alias!(__traits(getOverloads, C, signals[id])) current; + static if (signals.length - id - 1 > 0) + alias TypeTuple!(current, findSymbolsImpl2!(C, signals, id + 1).result) result; + else + alias current result; +} - int signalId1 = -1; - int signalId2 = -1; +template findSymbols2(C, string prefix) +{ + enum signals = getSymbols!(C)(prefix); + static if (signals) + alias findSymbolsImpl2!(C, signals, 0).result result; + else + alias TypeTuple!() result; +} - void onFirstConnect(int sId) - { - signalId1 = sId; - } +template findSignals(C) +{ + alias findSymbols2!(C, "signal_").result findSignals; +} - void onLastDisconnect(int sId) - { - signalId2 = sId; - } +template findSlots(C) +{ + alias findSymbols2!(C, "slot_").result findSlots; +} - this() - { - signalHandler.firstSlotConnected = &onFirstConnect; - signalHandler.lastSlotDisconnected = &onLastDisconnect; - } +/* commented out for future when we will implement default arguments +template metaMethods(alias func, int index, int defValsCount) +{ + static if(defValsCount >= 0) { + alias TupleWrapper!(func, index) current; +// pragma(msg, __traits(identifier, (current.at)[0]) ~ " " ~ typeof(&(current.at)[0]).stringof); + alias metaMethods!(func, index+1, defValsCount-1).result next; + alias TypeTuple!(current, next) result; } - - class B : A + else { - mixin Signal!("booed", int); + alias TypeTuple!() result; + } +} +*/ - int bazSum; - void baz(int i) - { - bazSum += i; - } +template toMetaEntriesImpl(int id, Methods...) +{ + static if (Methods.length > id) + { + alias typeof(&Methods[id]) Fn; +// commented out for future when we will implement default arguments +// enum defValsLength = 0; //ParameterTypeTuple!(Fn).length - requiredArgCount!(Methods[id])(); +// pragma(msg, __traits(identifier, Methods[id]) ~ " " ~ typeof(&Methods[id]).stringof); +// alias metaMethods!(Methods[id], 0, defValsLength).result subres; + alias TupleWrapper!(removePrefix(__traits(identifier, Methods[id])), typeof(&Methods[id])) subres; + alias TypeTuple!(subres, toMetaEntriesImpl!(id+1, Methods).result) result; } - - class C : A + else { - mixin Signal!("cooked"); + alias TypeTuple!() result; } } -unittest +template toMetaEntries(Methods...) { - static int fooSum; - static int barSum; - - static void foo(int i) - { - fooSum += i; - } - - void bar(long i) - { - barSum += i; - } - - auto a = new A; - auto b = new B; - auto c = new C; - assert(b.scorched.signalId == 0); - assert(b.booed.signalId == 1); - assert(c.cooked.signalId == 1); - - auto sh = b.signalHandler; - - b.scorched.connect(&foo); - assert(sh.connections.length == 1); - assert(b.signalId1 == 0); - auto scCons = &sh.connections[0]; - - assert(scCons.getSlotList!(SlotListId.Func).length == 1); - b.scorched.emit(1); - assert(fooSum == 1); - - b.scorched.connect(&bar, ConnectionFlags.NoObject); - assert(sh.connections.length == 1); - assert(scCons.getSlotList!(SlotListId.Strong).length == 1); - b.scorched.emit(1); - assert (fooSum == 2 && barSum == 1); - - b.scorched.connect(&b.baz); - assert(scCons.getSlotList!(SlotListId.Weak).length == 1); - b.scorched.emit(1); - assert (fooSum == 3 && barSum == 2 && b.bazSum == 1); - - b.scorched.disconnect(&bar); - assert(scCons.slotCount == 2); - b.scorched.disconnect(&b.baz); - assert(scCons.slotCount == 1); - b.scorched.disconnect(&foo); - assert(scCons.slotCount == 0); - assert(b.signalId2 == 0); - - fooSum = 0; - void connectFoo() - { - b.scorched.connect(&foo); - b.scorched.disconnect(&connectFoo); - } - - b.scorched.connect(&connectFoo, ConnectionFlags.NoObject); - b.scorched.emit(1); - assert(scCons.getSlotList!(SlotListId.Func).length == 1); - assert(scCons.getSlotList!(SlotListId.Strong).length == 0); - assert(!fooSum); - - auto r = new B(); - b.scorched.connect(&r.baz); - assert(scCons.getSlotList!(SlotListId.Weak).length == 1); - b.scorched.emit(1); - assert(r.bazSum == 1); - assert(fooSum == 1); - - delete(r); - assert(scCons.getSlotList!(SlotListId.Weak).length == 1); - b.scorched.emit(1); - assert(scCons.getSlotList!(SlotListId.Weak).length == 0); -} + alias TupleWrapper!(toMetaEntriesImpl!(0, Methods).result) toMetaEntries; +} \ No newline at end of file
--- a/qt/d2/qt/core/QLine.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/d2/qt/core/QLine.d Sun Feb 07 16:04:36 2010 +0000 @@ -123,7 +123,7 @@ pt2 = QPoint(aX2, aY2); } - bool opEquals(ref QLine d) // const + bool opEquals(ref const QLine d) const { return pt1 == d.pt1 && pt2 == d.pt2; } @@ -135,7 +135,18 @@ public final void readFrom(QDataStream arg__1) { qtd_QLine_readFrom_QDataStream(&this, arg__1 is null ? null : arg__1.__nativeId); } + + // service stuff + public alias void __isNativeValueType; + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } private: QPoint pt1, pt2; } @@ -309,7 +320,7 @@ pt2 = QPointF(aX2, aY2); } - bool opEquals(ref QLineF d) // const + bool opEquals(ref const QLineF d) const { return pt1 == d.pt1 && pt2 == d.pt2; } @@ -355,6 +366,18 @@ return qtd_QLineF_fromPolar_double_double(length, angle); } + // service stuff + public alias void __isNativeValueType; + + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } + private: QPointF pt1, pt2; }
--- a/qt/d2/qt/core/QModelIndex.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/d2/qt/core/QModelIndex.d Sun Feb 07 16:04:36 2010 +0000 @@ -4,7 +4,7 @@ private import qt.core.QObject; // automatic imports------------- -private import qt.core.QVariant; +//private import qt.core.QVariant; private import qt.core.QAbstractItemModel; public import qt.core.Qt; @@ -51,7 +51,7 @@ public final bool isValid() const { return __qtd_QModelIndex_isValid(cast(void*)&this); } - + public final QAbstractItemModel model() { // void* __qt_return_value = __qtd_QModelIndex_model(&this); void* __qt_return_value = m; @@ -80,6 +80,17 @@ public final QModelIndex sibling(int row, int column) { return __qtd_QModelIndex_sibling_int_int(&this, row, column); } + + public alias void __isNativeValueType; + + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } private: int r; @@ -114,8 +125,4 @@ private extern(C) QModelIndex __qtd_QModelIndex_sibling_int_int(void* __this_nativeId, int row0, int column1); -// Just the private functions for abstract functions implemeneted in superclasses - - - -// Virtual Dispatch functions + \ No newline at end of file
--- a/qt/d2/qt/core/QPoint.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/d2/qt/core/QPoint.d Sun Feb 07 16:04:36 2010 +0000 @@ -61,7 +61,7 @@ QPoint opMulAssign(qreal c) { xp = qRound(xp*c); yp = qRound(yp*c); return this; } - bool opEquals(ref QPoint p) + bool opEquals(ref const QPoint p) const { return xp == p.xp && yp == p.yp; } QPoint opAdd(ref QPoint p) @@ -92,6 +92,19 @@ public final void readFrom(QDataStream arg__1) { qtd_QPoint_readFrom_QDataStream(&this, arg__1 is null ? null : arg__1.__nativeId); } + + // service stuff + public alias void __isNativeValueType; + + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } + private: // ### Qt 5; remove the ifdef and just have the same order on all platforms. @@ -171,7 +184,7 @@ QPointF opMulAssign(qreal c) { xp*=c; yp*=c; return this; } - bool opEquals(ref QPointF p) + bool opEquals(ref const QPointF p) const { return qFuzzyCompare(xp, p.xp) && qFuzzyCompare(yp, p.yp); } QPointF opAdd(ref QPointF p) @@ -208,6 +221,18 @@ qtd_QPointF_readFrom_QDataStream(&this, arg__1 is null ? null : arg__1.__nativeId); } + // service stuff + public alias void __isNativeValueType; + + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } + private: qreal xp; qreal yp;
--- a/qt/d2/qt/core/QRect.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/d2/qt/core/QRect.d Sun Feb 07 16:04:36 2010 +0000 @@ -300,7 +300,7 @@ return this | r; } - bool opEquals(const QRect r) + bool opEquals(ref const QRect r) const { return x1==r.x1 && x2==r.x2 && y1==r.y1 && y2==r.y2; } @@ -337,6 +337,19 @@ return qtd_QRect_normalized(&this); } + // service stuff + public alias void __isNativeValueType; + + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } + + private: version(OSX) {
--- a/qt/d2/qt/core/QRectF.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/d2/qt/core/QRectF.d Sun Feb 07 16:04:36 2010 +0000 @@ -254,7 +254,7 @@ return this | r; } - bool opEquals(ref QRectF r) + bool opEquals(ref const QRectF r) const { return qFuzzyCompare(xp, r.xp) && qFuzzyCompare(yp, r.yp) && qFuzzyCompare(w, r.w) && qFuzzyCompare(h, r.h); @@ -301,7 +301,18 @@ { return qtd_QRectF_toAlignedRect(cast(void*)&this); } + + // service stuff + public alias void __isNativeValueType; + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } private: qreal xp; qreal yp;
--- a/qt/d2/qt/core/QSize.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/d2/qt/core/QSize.d Sun Feb 07 16:04:36 2010 +0000 @@ -91,7 +91,7 @@ QSize opMulAssign(qreal c) { wd = qRound(wd*c); ht = qRound(ht*c); return this; } - bool opEquals(ref QSize s) + bool opEquals(ref const QSize s) const { return wd == s.wd && ht == s.ht; } QSize opAdd(ref QSize s) @@ -113,7 +113,18 @@ assert(!qFuzzyCompare(c + 1, 1.)); return QSize(qRound(this.wd/c), qRound(this.ht/c)); } + + // service stuff + public alias void __isNativeValueType; + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } private: int wd; int ht; @@ -214,7 +225,7 @@ QSizeF opMulAssign(qreal c) { wd *= c; ht *= c; return this; } - bool opEquals(ref QSizeF s) + bool opEquals(ref const QSizeF s) const { return qFuzzyCompare(wd, s.wd) && qFuzzyCompare(ht, s.ht); } QSizeF opAdd(ref QSizeF s) @@ -238,7 +249,18 @@ assert(!qFuzzyCompare(c + 1, 1.)); return QSizeF(this.wd/c, this.ht/c); } + + // service stuff + public alias void __isNativeValueType; + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } private: qreal wd; qreal ht;
--- a/qt/d2/qt/core/QVariant.d Sat Dec 19 18:43:32 2009 +0300 +++ b/qt/d2/qt/core/QVariant.d Sun Feb 07 16:04:36 2010 +0000 @@ -612,10 +612,42 @@ protected override void __deleteNative() { qtd_QVariant_destructor(__nativeId); } + + public alias void __isValueType; + public alias void __isQtType_QVariant; + + struct QTypeInfo + { + enum bool isComplex = true; + enum bool isStatic = false; + enum bool isLarge = true; + enum bool isPointer = false; + enum bool isDummy = false; + } + + static void* __constructNativeCopy(const void* orig) { + return qtd_QVariant_QVariant_QVariant(cast(void*)orig); + } + + static void* __constructPlacedNativeCopy(const void* orig, void* place) { + return qtd_QVariant_placed_copy(orig, place); + } + + public static void __deleteNativeObject(void* ptr) { + qtd_QVariant_destructor(ptr); + } + + public static void __callNativeDestructor(void* ptr) { + qtd_QVariant_call_destructor(ptr); + } // Injected code in class } + extern (C) void qtd_QVariant_destructor(void *ptr); +extern (C) void qtd_QVariant_call_destructor(void *ptr); + +private extern(C) void* qtd_QVariant_placed_copy(const void* orig, void* place); // C wrappers
--- a/qt/gui/UrlHandler.d Sat Dec 19 18:43:32 2009 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -module qt.gui.UrlHandler; - -import qt.core.QUrl; - -alias void delegate(QUrl) UrlHandlerDg; - -package class UrlHandler : QObject { - public this(UrlHandlerDg dg) { - if (!init_flag_UrlHandler) - static_init_UrlHandler(); - - _dg = dg; - void* __qt_return_value = qtd_UrlHandler_UrlHandler_QObject(cast(void*) this, null); - this(__qt_return_value, true); - } - - void handleUrl(QUrl url) { - _dg(url); - } - - private UrlHandlerDg _dg; - - public this(void* native_id, bool gc_managed) { - super(native_id, gc_managed); - } - - - protected void __free_native_resources() { - qtd_UrlHandler_destructor(nativeId()); - } - - void __set_native_ownership(bool ownership_) { - __no_real_delete = ownership_; - } -} -extern (C) void qtd_UrlHandler_destructor(void *ptr); - -private extern(C) void* qtd_UrlHandler_UrlHandler_QObject(void *d_ptr, - void* parent0); - -private extern(C) void qtd_UrlHandler_handleUrl_QUrl_dispatch(void *d_entity, void* name1) -{ - auto d_object = cast(UrlHandler) d_entity; - scope name1_d_ref = new QUrl(name1, true); - d_object.handleUrl(name1_d_ref); -} - -private extern (C) void qtd_UrlHandler_initCallBacks(void* virtuals, void* qobj_del); - -private bool init_flag_UrlHandler = false; -void static_init_UrlHandler() { - init_flag_UrlHandler = true; - - void*[1] virt_arr; - virt_arr[0] = &qtd_UrlHandler_handleUrl_QUrl_dispatch; - -// void *qobj_del; -// qobj_del = &qtd_D_QWidget_delete; - qtd_UrlHandler_initCallBacks(virt_arr.ptr, null); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/qtd/Atomic.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,1818 @@ +/** + * The atomic module is intended to provide some basic support for lock-free + * concurrent programming. Some common operations are defined, each of which + * may be performed using the specified memory barrier or a less granular + * barrier if the hardware does not support the version requested. This + * model is based on a design by Alexander Terekhov as outlined in + * <a href=http://groups.google.com/groups?threadm=3E4820EE.6F408B25%40web.de> + * this thread</a>. Another useful reference for memory ordering on modern + * architectures is <a href=http://www.linuxjournal.com/article/8211>this + * article by Paul McKenney</a>. + * + * Copyright: Copyright (C) 2005-2006 Sean Kelly. All rights reserved. + * License: BSD style: $(LICENSE) + * Authors: Sean Kelly + */ +module qt.qtd.Atomic; +//deprecated: +//////////////////////////////////////////////////////////////////////////////// +// Synchronization Options +//////////////////////////////////////////////////////////////////////////////// + + +/** + * Memory synchronization flag. If the supplied option is not available on the + * current platform then a stronger method will be used instead. + */ +enum msync +{ + raw, /// not sequenced + hlb, /// hoist-load barrier + hsb, /// hoist-store barrier + slb, /// sink-load barrier + ssb, /// sink-store barrier + acq, /// hoist-load + hoist-store barrier + rel, /// sink-load + sink-store barrier + seq, /// fully sequenced (acq + rel) +} + + +//////////////////////////////////////////////////////////////////////////////// +// Internal Type Checking +//////////////////////////////////////////////////////////////////////////////// + + +private +{ + version( D_Ddoc ) {} else + { + import std.traits; + + + template isValidAtomicType( T ) + { + const bool isValidAtomicType = T.sizeof == byte.sizeof || + T.sizeof == short.sizeof || + T.sizeof == int.sizeof || + T.sizeof == long.sizeof; + } + + + template isValidNumericType( T ) + { + const bool isValidNumericType = isIntegral!( T ) || + isPointer!( T ); + } + + + template isHoistOp( msync ms ) + { + const bool isHoistOp = ms == msync.hlb || + ms == msync.hsb || + ms == msync.acq || + ms == msync.seq; + } + + + template isSinkOp( msync ms ) + { + const bool isSinkOp = ms == msync.slb || + ms == msync.ssb || + ms == msync.rel || + ms == msync.seq; + } + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// DDoc Documentation for Atomic Functions +//////////////////////////////////////////////////////////////////////////////// + + +version( D_Ddoc ) +{ + //////////////////////////////////////////////////////////////////////////// + // Atomic Load + //////////////////////////////////////////////////////////////////////////// + + + /** + * Supported msync values: + * msync.raw + * msync.hlb + * msync.acq + * msync.seq + */ + template atomicLoad( msync ms, T ) + { + /** + * Refreshes the contents of 'val' from main memory. This operation is + * both lock-free and atomic. + * + * Params: + * val = The value to load. This value must be properly aligned. + * + * Returns: + * The loaded value. + */ + T atomicLoad( ref T val ) + { + return val; + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Store + //////////////////////////////////////////////////////////////////////////// + + + /** + * Supported msync values: + * msync.raw + * msync.ssb + * msync.acq + * msync.rel + * msync.seq + */ + template atomicStore( msync ms, T ) + { + /** + * Stores 'newval' to the memory referenced by 'val'. This operation + * is both lock-free and atomic. + * + * Params: + * val = The destination variable. + * newval = The value to store. + */ + void atomicStore( ref T val, T newval ) + { + + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic StoreIf + //////////////////////////////////////////////////////////////////////////// + + + /** + * Supported msync values: + * msync.raw + * msync.ssb + * msync.acq + * msync.rel + * msync.seq + */ + template atomicStoreIf( msync ms, T ) + { + /** + * Stores 'newval' to the memory referenced by 'val' if val is equal to + * 'equalTo'. This operation is both lock-free and atomic. + * + * Params: + * val = The destination variable. + * newval = The value to store. + * equalTo = The comparison value. + * + * Returns: + * true if the store occurred, false if not. + */ + bool atomicStoreIf( ref T val, T newval, T equalTo ) + { + return false; + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Increment + //////////////////////////////////////////////////////////////////////////// + + + /** + * Supported msync values: + * msync.raw + * msync.ssb + * msync.acq + * msync.rel + * msync.seq + */ + template atomicIncrement( msync ms, T ) + { + /** + * This operation is only legal for built-in value and pointer types, + * and is equivalent to an atomic "val = val + 1" operation. This + * function exists to facilitate use of the optimized increment + * instructions provided by some architecures. If no such instruction + * exists on the target platform then the behavior will perform the + * operation using more traditional means. This operation is both + * lock-free and atomic. + * + * Params: + * val = The value to increment. + * + * Returns: + * The result of an atomicLoad of val immediately following the + * increment operation. This value is not required to be equal to the + * newly stored value. Thus, competing writes are allowed to occur + * between the increment and successive load operation. + */ + T atomicIncrement( ref T val ) + { + return val; + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Decrement + //////////////////////////////////////////////////////////////////////////// + + + /** + * Supported msync values: + * msync.raw + * msync.ssb + * msync.acq + * msync.rel + * msync.seq + */ + template atomicDecrement( msync ms, T ) + { + /** + * This operation is only legal for built-in value and pointer types, + * and is equivalent to an atomic "val = val - 1" operation. This + * function exists to facilitate use of the optimized decrement + * instructions provided by some architecures. If no such instruction + * exists on the target platform then the behavior will perform the + * operation using more traditional means. This operation is both + * lock-free and atomic. + * + * Params: + * val = The value to decrement. + * + * Returns: + * The result of an atomicLoad of val immediately following the + * increment operation. This value is not required to be equal to the + * newly stored value. Thus, competing writes are allowed to occur + * between the increment and successive load operation. + */ + T atomicDecrement( ref T val ) + { + return val; + } + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// LDC Atomics Implementation +//////////////////////////////////////////////////////////////////////////////// + + +else version( LDC ) +{ + import ldc.intrinsics; + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Load + //////////////////////////////////////////////////////////////////////////// + + + template atomicLoad( msync ms = msync.seq, T ) + { + T atomicLoad(ref T val) + { + llvm_memory_barrier( + ms == msync.hlb || ms == msync.acq || ms == msync.seq, + ms == msync.hsb || ms == msync.acq || ms == msync.seq, + ms == msync.slb || ms == msync.rel || ms == msync.seq, + ms == msync.ssb || ms == msync.rel || ms == msync.seq, + false); + static if (isPointerType!(T)) + { + return cast(T)llvm_atomic_load_add!(size_t)(cast(size_t*)&val, 0); + } + else static if (is(T == bool)) + { + return llvm_atomic_load_add!(ubyte)(cast(ubyte*)&val, cast(ubyte)0) ? 1 : 0; + } + else + { + return llvm_atomic_load_add!(T)(&val, cast(T)0); + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Store + //////////////////////////////////////////////////////////////////////////// + + + template atomicStore( msync ms = msync.seq, T ) + { + void atomicStore( ref T val, T newval ) + { + llvm_memory_barrier( + ms == msync.hlb || ms == msync.acq || ms == msync.seq, + ms == msync.hsb || ms == msync.acq || ms == msync.seq, + ms == msync.slb || ms == msync.rel || ms == msync.seq, + ms == msync.ssb || ms == msync.rel || ms == msync.seq, + false); + static if (isPointerType!(T)) + { + llvm_atomic_swap!(size_t)(cast(size_t*)&val, cast(size_t)newval); + } + else static if (is(T == bool)) + { + llvm_atomic_swap!(ubyte)(cast(ubyte*)&val, newval?1:0); + } + else + { + llvm_atomic_swap!(T)(&val, newval); + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Store If + //////////////////////////////////////////////////////////////////////////// + + + template atomicStoreIf( msync ms = msync.seq, T ) + { + bool atomicStoreIf( ref T val, T newval, T equalTo ) + { + llvm_memory_barrier( + ms == msync.hlb || ms == msync.acq || ms == msync.seq, + ms == msync.hsb || ms == msync.acq || ms == msync.seq, + ms == msync.slb || ms == msync.rel || ms == msync.seq, + ms == msync.ssb || ms == msync.rel || ms == msync.seq, + false); + T oldval = void; + static if (isPointerType!(T)) + { + oldval = cast(T)llvm_atomic_cmp_swap!(size_t)(cast(size_t*)&val, cast(size_t)equalTo, cast(size_t)newval); + } + else static if (is(T == bool)) + { + oldval = llvm_atomic_cmp_swap!(ubyte)(cast(ubyte*)&val, equalTo?1:0, newval?1:0)?0:1; + } + else + { + oldval = llvm_atomic_cmp_swap!(T)(&val, equalTo, newval); + } + return oldval == equalTo; + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Increment + //////////////////////////////////////////////////////////////////////////// + + + template atomicIncrement( msync ms = msync.seq, T ) + { + // + // NOTE: This operation is only valid for integer or pointer types + // + static assert( isValidNumericType!(T) ); + + + T atomicIncrement( ref T val ) + { + static if (isPointerType!(T)) + { + llvm_atomic_load_add!(size_t)(cast(size_t*)&val, 1); + } + else + { + llvm_atomic_load_add!(T)(&val, cast(T)1); + } + return val; + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Decrement + //////////////////////////////////////////////////////////////////////////// + + + template atomicDecrement( msync ms = msync.seq, T ) + { + // + // NOTE: This operation is only valid for integer or pointer types + // + static assert( isValidNumericType!(T) ); + + + T atomicDecrement( ref T val ) + { + static if (isPointerType!(T)) + { + llvm_atomic_load_sub!(size_t)(cast(size_t*)&val, 1); + } + else + { + llvm_atomic_load_sub!(T)(&val, cast(T)1); + } + return val; + } + } +} + +//////////////////////////////////////////////////////////////////////////////// +// x86 Atomic Function Implementation +//////////////////////////////////////////////////////////////////////////////// + + +else version( D_InlineAsm_X86 ) +{ + version( X86 ) + { + version( BuildInfo ) + { + pragma( msg, "tango.core.Atomic: using IA-32 inline asm" ); + } + + version(darwin){ + extern(C) bool OSAtomicCompareAndSwap64(long oldValue, long newValue, long *theValue); + extern(C) bool OSAtomicCompareAndSwap64Barrier(long oldValue, long newValue, long *theValue); + } + version = Has64BitCAS; + version = Has32BitOps; + } + version( X86_64 ) + { + version( BuildInfo ) + { + pragma( msg, "tango.core.Atomic: using AMD64 inline asm" ); + } + + version = Has64BitOps; + } + + private + { + //////////////////////////////////////////////////////////////////////// + // x86 Value Requirements + //////////////////////////////////////////////////////////////////////// + + + // NOTE: Strictly speaking, the x86 supports atomic operations on + // unaligned values. However, this is far slower than the + // common case, so such behavior should be prohibited. + template atomicValueIsProperlyAligned( T ) + { + bool atomicValueIsProperlyAligned( size_t addr ) + { + return addr % T.sizeof == 0; + } + } + + + //////////////////////////////////////////////////////////////////////// + // x86 Synchronization Requirements + //////////////////////////////////////////////////////////////////////// + + + // NOTE: While x86 loads have acquire semantics for stores, it appears + // that independent loads may be reordered by some processors + // (notably the AMD64). This implies that the hoist-load barrier + // op requires an ordering instruction, which also extends this + // requirement to acquire ops (though hoist-store should not need + // one if support is added for this later). However, since no + // modern architectures will reorder dependent loads to occur + // before the load they depend on (except the Alpha), raw loads + // are actually a possible means of ordering specific sequences + // of loads in some instances. The original atomic<> + // implementation provides a 'ddhlb' ordering specifier for + // data-dependent loads to handle this situation, but as there + // are no plans to support the Alpha there is no reason to add + // that option here. + // + // For reference, the old behavior (acquire semantics for loads) + // required a memory barrier if: ms == msync.seq || isSinkOp!(ms) + template needsLoadBarrier( msync ms ) + { + const bool needsLoadBarrier = ms != msync.raw; + } + + + // NOTE: x86 stores implicitly have release semantics so a membar is only + // necessary on acquires. + template needsStoreBarrier( msync ms ) + { + const bool needsStoreBarrier = ms == msync.seq || isHoistOp!(ms); + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Load + //////////////////////////////////////////////////////////////////////////// + + + template atomicLoad( msync ms = msync.seq, T ) + { + T atomicLoad( ref T val ) + in + { + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof == byte.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 1 Byte Load + //////////////////////////////////////////////////////////////// + + + static if( needsLoadBarrier!(ms) ) + { + asm + { + mov DL, 42; + mov AL, 42; + mov ECX, val; + lock; + cmpxchg [ECX], DL; + } + } + else + { + synchronized + { + return val; + } + } + } + else static if( T.sizeof == short.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 2 Byte Load + //////////////////////////////////////////////////////////////// + + static if( needsLoadBarrier!(ms) ) + { + asm + { + mov DX, 42; + mov AX, 42; + mov ECX, val; + lock; + cmpxchg [ECX], DX; + } + } + else + { + synchronized + { + return val; + } + } + } + else static if( T.sizeof == int.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 4 Byte Load + //////////////////////////////////////////////////////////////// + + + static if( needsLoadBarrier!(ms) ) + { + asm + { + mov EDX, 42; + mov EAX, 42; + mov ECX, val; + lock; + cmpxchg [ECX], EDX; + } + } + else + { + synchronized + { + return val; + } + } + } + else static if( T.sizeof == long.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 8 Byte Load + //////////////////////////////////////////////////////////////// + + + version( Has64BitOps ) + { + //////////////////////////////////////////////////////////// + // 8 Byte Load on 64-Bit Processor + //////////////////////////////////////////////////////////// + + + static if( needsLoadBarrier!(ms) ) + { + asm + { + mov RAX, val; + lock; + mov RAX, [RAX]; + } + } + else + { + synchronized + { + return val; + } + } + } + else + { + //////////////////////////////////////////////////////////// + // 8 Byte Load on 32-Bit Processor + //////////////////////////////////////////////////////////// + + + pragma( msg, "This operation is only available on 64-bit platforms." ); + static assert( false ); + } + } + else + { + //////////////////////////////////////////////////////////////// + // Not a 1, 2, 4, or 8 Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Store + //////////////////////////////////////////////////////////////////////////// + + + template atomicStore( msync ms = msync.seq, T ) + { + void atomicStore( ref T val, T newval ) + in + { + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof == byte.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 1 Byte Store + //////////////////////////////////////////////////////////////// + + + static if( needsStoreBarrier!(ms) ) + { + asm + { + mov EAX, val; + mov DL, newval; + lock; + xchg [EAX], DL; + } + } + else + { + asm + { + mov EAX, val; + mov DL, newval; + mov [EAX], DL; + } + } + } + else static if( T.sizeof == short.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 2 Byte Store + //////////////////////////////////////////////////////////////// + + + static if( needsStoreBarrier!(ms) ) + { + asm + { + mov EAX, val; + mov DX, newval; + lock; + xchg [EAX], DX; + } + } + else + { + asm + { + mov EAX, val; + mov DX, newval; + mov [EAX], DX; + } + } + } + else static if( T.sizeof == int.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 4 Byte Store + //////////////////////////////////////////////////////////////// + + + static if( needsStoreBarrier!(ms) ) + { + asm + { + mov EAX, val; + mov EDX, newval; + lock; + xchg [EAX], EDX; + } + } + else + { + asm + { + mov EAX, val; + mov EDX, newval; + mov [EAX], EDX; + } + } + } + else static if( T.sizeof == long.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 8 Byte Store + //////////////////////////////////////////////////////////////// + + + version( Has64BitOps ) + { + //////////////////////////////////////////////////////////// + // 8 Byte Store on 64-Bit Processor + //////////////////////////////////////////////////////////// + + + static if( needsStoreBarrier!(ms) ) + { + asm + { + mov RAX, val; + mov RDX, newval; + lock; + xchg [RAX], RDX; + } + } + else + { + asm + { + mov RAX, val; + mov RDX, newval; + mov [RAX], RDX; + } + } + } + else + { + //////////////////////////////////////////////////////////// + // 8 Byte Store on 32-Bit Processor + //////////////////////////////////////////////////////////// + + + pragma( msg, "This operation is only available on 64-bit platforms." ); + static assert( false ); + } + } + else + { + //////////////////////////////////////////////////////////////// + // Not a 1, 2, 4, or 8 Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Store If + //////////////////////////////////////////////////////////////////////////// + + + template atomicStoreIf( msync ms = msync.seq, T ) + { + bool atomicStoreIf( ref T val, T newval, T equalTo ) + in + { + // NOTE: 32 bit x86 systems support 8 byte CAS, which only requires + // 4 byte alignment, so use size_t as the align type here. + static if( T.sizeof > size_t.sizeof ) + assert( atomicValueIsProperlyAligned!(size_t)( cast(size_t) &val ) ); + else + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof == byte.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 1 Byte StoreIf + //////////////////////////////////////////////////////////////// + + + asm + { + mov DL, newval; + mov AL, equalTo; + mov ECX, val; + lock; // lock always needed to make this op atomic + cmpxchg [ECX], DL; + setz AL; + } + } + else static if( T.sizeof == short.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 2 Byte StoreIf + //////////////////////////////////////////////////////////////// + + + asm + { + mov DX, newval; + mov AX, equalTo; + mov ECX, val; + lock; // lock always needed to make this op atomic + cmpxchg [ECX], DX; + setz AL; + } + } + else static if( T.sizeof == int.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 4 Byte StoreIf + //////////////////////////////////////////////////////////////// + + + asm + { + mov EDX, newval; + mov EAX, equalTo; + mov ECX, val; + lock; // lock always needed to make this op atomic + cmpxchg [ECX], EDX; + setz AL; + } + } + else static if( T.sizeof == long.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 8 Byte StoreIf + //////////////////////////////////////////////////////////////// + + + version( Has64BitOps ) + { + //////////////////////////////////////////////////////////// + // 8 Byte StoreIf on 64-Bit Processor + //////////////////////////////////////////////////////////// + + + asm + { + mov RDX, newval; + mov RAX, equalTo; + mov RCX, val; + lock; // lock always needed to make this op atomic + cmpxchg [RCX], RDX; + setz AL; + } + } + else version( Has64BitCAS ) + { + //////////////////////////////////////////////////////////// + // 8 Byte StoreIf on 32-Bit Processor + //////////////////////////////////////////////////////////// + version(darwin){ + static if(ms==msync.raw){ + return OSAtomicCompareAndSwap64(cast(long)equalTo, cast(long)newval, cast(long*)&val); + } else { + return OSAtomicCompareAndSwap64Barrier(cast(long)equalTo, cast(long)newval, cast(long*)&val); + } + } else { + asm + { + push EDI; + push EBX; + lea EDI, newval; + mov EBX, [EDI]; + mov ECX, 4[EDI]; + lea EDI, equalTo; + mov EAX, [EDI]; + mov EDX, 4[EDI]; + mov EDI, val; + lock; // lock always needed to make this op atomic + cmpxch8b [EDI]; + setz AL; + pop EBX; + pop EDI; + } + } + } + } + else + { + //////////////////////////////////////////////////////////////// + // Not a 1, 2, 4, or 8 Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Increment + //////////////////////////////////////////////////////////////////////////// + + + template atomicIncrement( msync ms = msync.seq, T ) + { + // + // NOTE: This operation is only valid for integer or pointer types + // + static assert( isValidNumericType!(T) ); + + + T atomicIncrement( ref T val ) + in + { + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof == byte.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 1 Byte Increment + //////////////////////////////////////////////////////////////// + + + asm + { + mov EAX, val; + lock; // lock always needed to make this op atomic + inc [EAX]; + mov AL, [EAX]; + } + } + else static if( T.sizeof == short.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 2 Byte Increment + //////////////////////////////////////////////////////////////// + + + asm + { + mov EAX, val; + lock; // lock always needed to make this op atomic + inc short ptr [EAX]; + mov AX, [EAX]; + } + } + else static if( T.sizeof == int.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 4 Byte Increment + //////////////////////////////////////////////////////////////// + + + asm + { + mov EAX, val; + lock; // lock always needed to make this op atomic + inc int ptr [EAX]; + mov EAX, [EAX]; + } + } + else static if( T.sizeof == long.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 8 Byte Increment + //////////////////////////////////////////////////////////////// + + + version( Has64BitOps ) + { + //////////////////////////////////////////////////////////// + // 8 Byte Increment on 64-Bit Processor + //////////////////////////////////////////////////////////// + + + asm + { + mov RAX, val; + lock; // lock always needed to make this op atomic + inc qword ptr [RAX]; + mov RAX, [RAX]; + } + } + else + { + //////////////////////////////////////////////////////////// + // 8 Byte Increment on 32-Bit Processor + //////////////////////////////////////////////////////////// + + + pragma( msg, "This operation is only available on 64-bit platforms." ); + static assert( false ); + } + } + else + { + //////////////////////////////////////////////////////////////// + // Not a 1, 2, 4, or 8 Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Decrement + //////////////////////////////////////////////////////////////////////////// + + + template atomicDecrement( msync ms = msync.seq, T ) + { + // + // NOTE: This operation is only valid for integer or pointer types + // + static assert( isValidNumericType!(T) ); + + + T atomicDecrement( ref T val ) + in + { + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof == byte.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 1 Byte Decrement + //////////////////////////////////////////////////////////////// + + + asm + { + mov EAX, val; + lock; // lock always needed to make this op atomic + dec [EAX]; + mov AL, [EAX]; + } + } + else static if( T.sizeof == short.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 2 Byte Decrement + //////////////////////////////////////////////////////////////// + + + asm + { + mov EAX, val; + lock; // lock always needed to make this op atomic + dec short ptr [EAX]; + mov AX, [EAX]; + } + } + else static if( T.sizeof == int.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 4 Byte Decrement + //////////////////////////////////////////////////////////////// + + + asm + { + mov EAX, val; + lock; // lock always needed to make this op atomic + dec int ptr [EAX]; + mov EAX, [EAX]; + } + } + else static if( T.sizeof == long.sizeof ) + { + //////////////////////////////////////////////////////////////// + // 8 Byte Decrement + //////////////////////////////////////////////////////////////// + + + version( Has64BitOps ) + { + //////////////////////////////////////////////////////////// + // 8 Byte Decrement on 64-Bit Processor + //////////////////////////////////////////////////////////// + + + asm + { + mov RAX, val; + lock; // lock always needed to make this op atomic + dec qword ptr [RAX]; + mov RAX, [RAX]; + } + } + else + { + //////////////////////////////////////////////////////////// + // 8 Byte Decrement on 32-Bit Processor + //////////////////////////////////////////////////////////// + + + pragma( msg, "This operation is only available on 64-bit platforms." ); + static assert( false ); + } + } + else + { + //////////////////////////////////////////////////////////////// + // Not a 1, 2, 4, or 8 Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } +} +else +{ + version( BuildInfo ) + { + pragma( msg, "tango.core.Atomic: using synchronized ops" ); + } + + private + { + //////////////////////////////////////////////////////////////////////// + // Default Value Requirements + //////////////////////////////////////////////////////////////////////// + + + template atomicValueIsProperlyAligned( T ) + { + bool atomicValueIsProperlyAligned( size_t addr ) + { + return addr % T.sizeof == 0; + } + } + + + //////////////////////////////////////////////////////////////////////// + // Default Synchronization Requirements + //////////////////////////////////////////////////////////////////////// + + + template needsLoadBarrier( msync ms ) + { + const bool needsLoadBarrier = ms != msync.raw; + } + + + template needsStoreBarrier( msync ms ) + { + const bool needsStoreBarrier = ms != msync.raw; + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Load + //////////////////////////////////////////////////////////////////////////// + + + template atomicLoad( msync ms = msync.seq, T ) + { + T atomicLoad( ref T val ) + in + { + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof <= (void*).sizeof ) + { + //////////////////////////////////////////////////////////////// + // <= (void*).sizeof Byte Load + //////////////////////////////////////////////////////////////// + + + static if( needsLoadBarrier!(ms) ) + { + synchronized + { + return val; + } + } + else + { + synchronized + { + return val; + } + } + } + else + { + //////////////////////////////////////////////////////////////// + // > (void*).sizeof Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Store + //////////////////////////////////////////////////////////////////////////// + + + template atomicStore( msync ms = msync.seq, T ) + { + void atomicStore( ref T val, T newval ) + in + { + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof <= (void*).sizeof ) + { + //////////////////////////////////////////////////////////////// + // <= (void*).sizeof Byte Store + //////////////////////////////////////////////////////////////// + + + static if( needsStoreBarrier!(ms) ) + { + synchronized + { + val = newval; + } + } + else + { + synchronized + { + val = newval; + } + } + } + else + { + //////////////////////////////////////////////////////////////// + // > (void*).sizeof Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Store If + //////////////////////////////////////////////////////////////////////////// + + + template atomicStoreIf( msync ms = msync.seq, T ) + { + bool atomicStoreIf( ref T val, T newval, T equalTo ) + in + { + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof <= (void*).sizeof ) + { + //////////////////////////////////////////////////////////////// + // <= (void*).sizeof Byte StoreIf + //////////////////////////////////////////////////////////////// + + + synchronized + { + if( val == equalTo ) + { + val = newval; + return true; + } + return false; + } + } + else + { + //////////////////////////////////////////////////////////////// + // > (void*).sizeof Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } + + + ///////////////////////////////////////////////////////////////////////////// + // Atomic Increment + //////////////////////////////////////////////////////////////////////////// + + + template atomicIncrement( msync ms = msync.seq, T ) + { + // + // NOTE: This operation is only valid for integer or pointer types + // + static assert( isValidNumericType!(T) ); + + + T atomicIncrement( ref T val ) + in + { + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof <= (void*).sizeof ) + { + //////////////////////////////////////////////////////////////// + // <= (void*).sizeof Byte Increment + //////////////////////////////////////////////////////////////// + + + synchronized + { + return ++val; + } + } + else + { + //////////////////////////////////////////////////////////////// + // > (void*).sizeof Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Decrement + //////////////////////////////////////////////////////////////////////////// + + + template atomicDecrement( msync ms = msync.seq, T ) + { + // + // NOTE: This operation is only valid for integer or pointer types + // + static assert( isValidNumericType!(T) ); + + + T atomicDecrement( ref T val ) + in + { + assert( atomicValueIsProperlyAligned!(T)( cast(size_t) &val ) ); + } + body + { + static if( T.sizeof <= (void*).sizeof ) + { + //////////////////////////////////////////////////////////////// + // <= (void*).sizeof Byte Decrement + //////////////////////////////////////////////////////////////// + + + synchronized + { + return --val; + } + } + else + { + //////////////////////////////////////////////////////////////// + // > (void*).sizeof Byte Type + //////////////////////////////////////////////////////////////// + + + pragma( msg, "Invalid template type specified." ); + static assert( false ); + } + } + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Atomic +//////////////////////////////////////////////////////////////////////////////// + + +/** + * This struct represents a value which will be subject to competing access. + * All accesses to this value will be synchronized with main memory, and + * various memory barriers may be employed for instruction ordering. Any + * primitive type of size equal to or smaller than the memory bus size is + * allowed, so 32-bit machines may use values with size <= int.sizeof and + * 64-bit machines may use values with size <= long.sizeof. The one exception + * to this rule is that architectures that support DCAS will allow double-wide + * storeIf operations. The 32-bit x86 architecture, for example, supports + * 64-bit storeIf operations. + */ +struct Atomic( T ) +{ + //////////////////////////////////////////////////////////////////////////// + // Atomic Load + //////////////////////////////////////////////////////////////////////////// + + + template load( msync ms = msync.seq ) + { + static assert( ms == msync.raw || ms == msync.hlb || + ms == msync.acq || ms == msync.seq, + "ms must be one of: msync.raw, msync.hlb, msync.acq, msync.seq" ); + + /** + * Refreshes the contents of this value from main memory. This + * operation is both lock-free and atomic. + * + * Returns: + * The loaded value. + */ + T load() + { + return atomicLoad!(ms,T)( m_val ); + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic Store + //////////////////////////////////////////////////////////////////////////// + + + template store( msync ms = msync.seq ) + { + static assert( ms == msync.raw || ms == msync.ssb || + ms == msync.acq || ms == msync.rel || + ms == msync.seq, + "ms must be one of: msync.raw, msync.ssb, msync.acq, msync.rel, msync.seq" ); + + /** + * Stores 'newval' to the memory referenced by this value. This + * operation is both lock-free and atomic. + * + * Params: + * newval = The value to store. + */ + void store( T newval ) + { + atomicStore!(ms,T)( m_val, newval ); + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Atomic StoreIf + //////////////////////////////////////////////////////////////////////////// + + + template storeIf( msync ms = msync.seq ) + { + static assert( ms == msync.raw || ms == msync.ssb || + ms == msync.acq || ms == msync.rel || + ms == msync.seq, + "ms must be one of: msync.raw, msync.ssb, msync.acq, msync.rel, msync.seq" ); + + /** + * Stores 'newval' to the memory referenced by this value if val is + * equal to 'equalTo'. This operation is both lock-free and atomic. + * + * Params: + * newval = The value to store. + * equalTo = The comparison value. + * + * Returns: + * true if the store occurred, false if not. + */ + bool storeIf( T newval, T equalTo ) + { + return atomicStoreIf!(ms,T)( m_val, newval, equalTo ); + } + } + + + //////////////////////////////////////////////////////////////////////////// + // Numeric Functions + //////////////////////////////////////////////////////////////////////////// + + + /** + * The following additional functions are available for integer types. + */ + static if( isValidNumericType!(T) ) + { + //////////////////////////////////////////////////////////////////////// + // Atomic Increment + //////////////////////////////////////////////////////////////////////// + + + template increment( msync ms = msync.seq ) + { + static assert( ms == msync.raw || ms == msync.ssb || + ms == msync.acq || ms == msync.rel || + ms == msync.seq, + "ms must be one of: msync.raw, msync.ssb, msync.acq, msync.rel, msync.seq" ); + + /** + * This operation is only legal for built-in value and pointer + * types, and is equivalent to an atomic "val = val + 1" operation. + * This function exists to facilitate use of the optimized + * increment instructions provided by some architecures. If no + * such instruction exists on the target platform then the + * behavior will perform the operation using more traditional + * means. This operation is both lock-free and atomic. + * + * Returns: + * The result of an atomicLoad of val immediately following the + * increment operation. This value is not required to be equal to + * the newly stored value. Thus, competing writes are allowed to + * occur between the increment and successive load operation. + */ + T increment() + { + return atomicIncrement!(ms,T)( m_val ); + } + } + + + //////////////////////////////////////////////////////////////////////// + // Atomic Decrement + //////////////////////////////////////////////////////////////////////// + + + template decrement( msync ms = msync.seq ) + { + static assert( ms == msync.raw || ms == msync.ssb || + ms == msync.acq || ms == msync.rel || + ms == msync.seq, + "ms must be one of: msync.raw, msync.ssb, msync.acq, msync.rel, msync.seq" ); + + /** + * This operation is only legal for built-in value and pointer + * types, and is equivalent to an atomic "val = val - 1" operation. + * This function exists to facilitate use of the optimized + * decrement instructions provided by some architecures. If no + * such instruction exists on the target platform then the behavior + * will perform the operation using more traditional means. This + * operation is both lock-free and atomic. + * + * Returns: + * The result of an atomicLoad of val immediately following the + * increment operation. This value is not required to be equal to + * the newly stored value. Thus, competing writes are allowed to + * occur between the increment and successive load operation. + */ + T decrement() + { + return atomicDecrement!(ms,T)( m_val ); + } + } + } + +private: + T m_val; +} + + +//////////////////////////////////////////////////////////////////////////////// +// Support Code for Unit Tests +//////////////////////////////////////////////////////////////////////////////// + + +private +{ + version( D_Ddoc ) {} else + { + template testLoad( msync ms, T ) + { + void testLoad( T val = T.init + 1 ) + { + T base; + Atomic!(T) atom; + + assert( atom.load!(ms)() == base ); + base = val; + atom.m_val = val; + assert( atom.load!(ms)() == base ); + } + } + + + template testStore( msync ms, T ) + { + void testStore( T val = T.init + 1 ) + { + T base; + Atomic!(T) atom; + + assert( atom.m_val == base ); + base = val; + atom.store!(ms)( base ); + assert( atom.m_val == base ); + } + } + + + template testStoreIf( msync ms, T ) + { + void testStoreIf( T val = T.init + 1 ) + { + T base; + Atomic!(T) atom; + + assert( atom.m_val == base ); + base = val; + atom.storeIf!(ms)( base, val ); + assert( atom.m_val != base ); + atom.storeIf!(ms)( base, T.init ); + assert( atom.m_val == base ); + } + } + + + template testIncrement( msync ms, T ) + { + void testIncrement( T val = T.init + 1 ) + { + T base = val; + T incr = val; + Atomic!(T) atom; + + atom.m_val = val; + assert( atom.m_val == base && incr == base ); + base = cast(T)( base + 1 ); + incr = atom.increment!(ms)(); + assert( atom.m_val == base && incr == base ); + } + } + + + template testDecrement( msync ms, T ) + { + void testDecrement( T val = T.init + 1 ) + { + T base = val; + T decr = val; + Atomic!(T) atom; + + atom.m_val = val; + assert( atom.m_val == base && decr == base ); + base = cast(T)( base - 1 ); + decr = atom.decrement!(ms)(); + assert( atom.m_val == base && decr == base ); + } + } + + + template testType( T ) + { + void testType( T val = T.init +1 ) + { + testLoad!(msync.raw, T)( val ); + testLoad!(msync.hlb, T)( val ); + testLoad!(msync.acq, T)( val ); + testLoad!(msync.seq, T)( val ); + + testStore!(msync.raw, T)( val ); + testStore!(msync.ssb, T)( val ); + testStore!(msync.acq, T)( val ); + testStore!(msync.rel, T)( val ); + testStore!(msync.seq, T)( val ); + + testStoreIf!(msync.raw, T)( val ); + testStoreIf!(msync.ssb, T)( val ); + testStoreIf!(msync.acq, T)( val ); + testStoreIf!(msync.rel, T)( val ); + testStoreIf!(msync.seq, T)( val ); + + static if( isValidNumericType!(T) ) + { + testIncrement!(msync.raw, T)( val ); + testIncrement!(msync.ssb, T)( val ); + testIncrement!(msync.acq, T)( val ); + testIncrement!(msync.rel, T)( val ); + testIncrement!(msync.seq, T)( val ); + + testDecrement!(msync.raw, T)( val ); + testDecrement!(msync.ssb, T)( val ); + testDecrement!(msync.acq, T)( val ); + testDecrement!(msync.rel, T)( val ); + testDecrement!(msync.seq, T)( val ); + } + } + } + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// Unit Tests +//////////////////////////////////////////////////////////////////////////////// + + +debug( UnitTest ) +{ + unittest + { + testType!(bool)(); + + testType!(byte)(); + testType!(ubyte)(); + + testType!(short)(); + testType!(ushort)(); + + testType!(int)(); + testType!(uint)(); + + int x; + testType!(void*)( &x ); + + version( Has64BitOps ) + { + testType!(long)(); + testType!(ulong)(); + } + else version( Has64BitCAS ) + { + testStoreIf!(msync.raw, long)(); + testStoreIf!(msync.ssb, long)(); + testStoreIf!(msync.acq, long)(); + testStoreIf!(msync.rel, long)(); + testStoreIf!(msync.seq, long)(); + + testStoreIf!(msync.raw, ulong)(); + testStoreIf!(msync.ssb, ulong)(); + testStoreIf!(msync.acq, ulong)(); + testStoreIf!(msync.rel, ulong)(); + testStoreIf!(msync.seq, ulong)(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/qtd/MOC.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,561 @@ +module qt.qtd.MOC; + +import qt.qtd.ctfe.Format; + +import std.typetuple; + +import qt.QGlobal; +import qt.Signal; +import qt.qtd.MetaMarshall; +import qt.qtd.Meta; + +public import qt.core.QString; + +public import std.traits; +/** + Utils. + */ + +bool is_digit_char(const char s) +{ + return (s >= '0' && s <= '9'); +} + +bool is_octal_char(const char s) +{ + return (s >= '0' && s <= '7'); +} + +bool is_hex_char(const char s) +{ + return ((s >= 'a' && s <= 'f') + || (s >= 'A' && s <= 'F') + || (s >= '0' && s <= '9') + ); +} + +int lastIndexOf(T)(T[] haystack, T[] needle, int from = -1) +{ + auto l = haystack.length; + auto ol = needle.length; + int delta = l - ol; + if (from < 0) + from = delta; + if (from < 0 || from > l) + return -1; + if (from > delta) + from = delta; + + while(from >= 0) + { + if (haystack[from..from+ol] == needle) + return from; + from--; + } + return -1; +} + + +T[] newArray(T)(size_t len, T[] from = []) +{ + if (len == from.length) + return from; + + if (!from.length) + from = [T.init]; + + if (from.length < len) + return newArray!T(len, from ~ from); + + return from[0..len]; +} + +string replicate(int n, char value) +{ + char[] ret = "".dup; + if (n > 0) + { +// ret = newArray!char(n); + for(int i = 0; i < n; i++) + ret ~= value; + } + return cast(string)ret; +} + +/** + CTFE MOC port. + */ + +enum MethodFlags { + AccessPrivate = 0x00, + AccessProtected = 0x01, + AccessPublic = 0x02, + MethodMethod = 0x00, + MethodSignal = 0x04, + MethodSlot = 0x08, + MethodConstructor = 0x0c, + MethodCompatibility = 0x10, + MethodCloned = 0x20, + MethodScriptable = 0x40 +} + +enum Access { Private, Protected, Public } + +struct FunctionDef +{ +/* FunctionDef(): returnTypeIsVolatile(false), access(Private), isConst(false), isVirtual(false), + inlineCode(false), wasCloned(false), isCompat(false), isInvokable(false), + isScriptable(false), isSlot(false), isSignal(false), + isConstructor(false), isDestructor(false), isAbstract(false) {} + */ +// Type type; +// string normalizedType; +// string tag; +// string name; + string sig; + string arguments; + Access access; +/* bool returnTypeIsVolatile; + + QList<ArgumentDef> arguments; + + enum Access { Private, Protected, Public }; + bool isConst; + bool isVirtual; + bool inlineCode; + bool wasCloned; + + QByteArray inPrivateClass; + bool isCompat; + bool isInvokable; + bool isScriptable; + bool isSlot; + bool isSignal; + bool isConstructor; + bool isDestructor; + bool isAbstract; + */ +} + +FunctionDef newSlot(string sig, string args) +{ + return FunctionDef(sig, args, Access.Public); +} + +FunctionDef newSignal(string sig, string args) +{ + return FunctionDef(sig, args, Access.Protected); +} + +struct Generator +{ + string output; + string[] strings; +// QByteArray purestSuperClass; +// QList<QByteArray> metaTypes; +} + +int lengthOfEscapeSequence(string s, uint i) +{ + if (s[i] != '\\' || i >= s.length - 1) + return 1; + const int startPos = i; + ++i; + auto ch = s[i]; + if (ch == 'x') { + ++i; + while (i < s.length && is_hex_char(s[i])) + ++i; + } else if (is_octal_char(ch)) { + while (i < startPos + 4 + && i < s.length + && is_octal_char(s[i])) { + ++i; + } + } else { // single character escape sequence + i = qMin(i + 1, s.length); + } + return i - startPos; +} + +int strreg(ref Generator gen, string s) +{ + int idx = 0; + foreach (str; gen.strings) { + if (str == s) + return idx; + idx += str.length + 1; + foreach (i, c; str) { + if (c == '\\') { + int cnt = lengthOfEscapeSequence(str, i) - 1; + idx -= cnt; + i += cnt; + } + } + } + gen.strings ~= s; + return idx; +} + +void generateFunctions(ref Generator gen, FunctionDef[] list, string functype, byte type) +{ + if (!list.length) + return; + gen.output ~= format_ctfe("\n // ${}s: signature, parameters, type, tag, flags\n", functype); + + foreach (i, f; list) { + byte flags = type; + + if (f.access == Access.Private) + flags |= MethodFlags.AccessPrivate; + else if (f.access == Access.Public) + flags |= MethodFlags.AccessPublic; + else if (f.access == Access.Protected) + flags |= MethodFlags.AccessProtected; + + gen.output ~= format_ctfe(" ${}, ${}, ${}, ${}, 0x${:x},\n", strreg(gen, f.sig), + strreg(gen, f.arguments), strreg(gen, ""/*f.normalizedType*/), strreg(gen, ""/*f.tag*/), flags); + } +} + +string generateCode(string className, FunctionDef[] signalList, FunctionDef[] slotList) +{ + auto gen = Generator("", []); + +/* bool isQt = (cdef->classname == "Qt"); + bool isQObject = (cdef->classname == "QObject"); + bool isConstructible = !cdef->constructorList.isEmpty(); + +// +// build the data array +// + int i = 0; + + + // filter out undeclared enumerators and sets + { + QList<EnumDef> enumList; + for (i = 0; i < cdef->enumList.count(); ++i) { + EnumDef def = cdef->enumList.at(i); + if (cdef->enumDeclarations.contains(def.name)) { + enumList += def; + } + QByteArray alias = cdef->flagAliases.value(def.name); + if (cdef->enumDeclarations.contains(alias)) { + def.name = alias; + enumList += def; + } + } + cdef->enumList = enumList; + } + + + QByteArray qualifiedClassNameIdentifier = cdef->qualified; + qualifiedClassNameIdentifier.replace(':', '_'); +*/ + bool isConstructible = false; + + FunctionDef[] propertyList, enumList, constructorList; + int index = 12; + gen.output ~= format_ctfe("static const uint[] qt_meta_data_${} = [\n", className); + gen.output ~= format_ctfe("\n // content:\n"); + gen.output ~= format_ctfe(" ${}, // revision\n", 2); + gen.output ~= format_ctfe(" ${}, // classname\n", strreg(gen, className)); + gen.output ~= format_ctfe(" ${}, ${}, // classinfo\n", 0, 0); +// index += cdef->classInfoList.count() * 2; + + int methodCount = signalList.length + slotList.length;// + cdef->methodList.count(); + gen.output ~= format_ctfe(" ${}, ${}, // methods\n", methodCount, methodCount ? index : 0); + index += methodCount * 5; + gen.output ~= format_ctfe(" ${}, ${}, // properties\n", propertyList.length, propertyList.length ? index : 0); + index += propertyList.length * 3; +// if(cdef->notifyableProperties) +// index += cdef->propertyList.count(); + gen.output ~= format_ctfe(" ${}, ${}, // enums/sets\n", enumList.length, enumList.length ? index : 0); + +// int enumsIndex = index; +// for (i = 0; i < cdef->enumList.count(); ++i) +// index += 4 + (cdef->enumList.at(i).values.count() * 2); + gen.output ~= format_ctfe(" ${}, ${}, // constructors\n", isConstructible ? constructorList.length : 0, + isConstructible ? index : 0); + +// +// Build classinfo array +// +// generateClassInfos(); + +// +// Build signals array first, otherwise the signal indices would be wrong +// + generateFunctions(gen, signalList, "signal", MethodFlags.MethodSignal); + +// +// Build slots array +// + generateFunctions(gen, slotList, "slot", MethodFlags.MethodSlot); + +// +// Build method array +// +// generateFunctions(cdef->methodList, "method", MethodMethod); + + +// +// Build property array +// +// generateProperties(); + +// +// Build enums array +// +// generateEnums(enumsIndex); + +// +// Build constructors array +// +// if (isConstructible) +// generateFunctions(cdef->constructorList, "constructor", MethodConstructor); + +// +// Terminate data array +// + gen.output ~= format_ctfe("\n 0 // eod\n];\n\n"); + +// +// Build stringdata array +// + gen.output ~= format_ctfe("static const string qt_meta_stringdata_${} = \n", className); + gen.output ~= format_ctfe(" \""); + int col = 0; + int len = 0; + foreach (i, s; gen.strings) { + len = s.length; + if (col && col + len >= 72) { + gen.output ~= format_ctfe("\"\n \""); + col = 0; + } else if (len && s[0] >= '0' && s[0] <= '9') { + gen.output ~= format_ctfe("\"\""); + len += 2; + } + int idx = 0; + while (idx < s.length) { + if (idx > 0) { + col = 0; + gen.output ~= format_ctfe("\"\n \""); + } + int spanLen = qMin(cast(uint)70, s.length - idx); + // don't cut escape sequences at the end of a line + int backSlashPos = s.lastIndexOf("\\", idx + spanLen - 1); + if (backSlashPos >= idx) { + int escapeLen = lengthOfEscapeSequence(s, backSlashPos); + spanLen = qBound(spanLen, backSlashPos + escapeLen - idx, cast(int)(s.length - idx)); + } + gen.output ~= s[idx..idx+spanLen]; + idx += spanLen; + col += spanLen; + } + + gen.output ~= "\\0"; + col += len + 2; + } + gen.output ~= "\";\n\n"; + + return gen.output; +} + +string metaCallArgs(Args...)() +{ + string res; + foreach(i, _; Args) { + if (i > 0) + res ~= ","; + res ~= metaCallArgument!(Args[i])("_a[" ~ __toString(i+1) ~ "]"); + } + return res; +} + +string qtDeclArgs(Args...)() +{ + string ret; + foreach(i, _; Args) + { + if(i > 0) + ret ~= ","; + ret ~= qtDeclArg!(Args[i]); + } + return ret; +} + +string generate_qt_metacall(alias Signals, alias Slots)() +{ + string res = " +protected int qt_metacall(QMetaObject.Call _c, int _id, void **_a) + { + _id = super.qt_metacall(_c, _id, _a); + if (_id < 0) + return _id;\n"; + + alias TypeTuple!(Signals.at, Slots.at) Methods; + enum methodCount = Methods.length; + if(methodCount) + { + res ~= " + if (_c == QMetaObject.Call.InvokeMetaMethod) { + switch (_id) {"; + foreach(i, _; Repeat!(void, methodCount)) { + res ~= " + case " ~ __toString(i) ~ ": " ~ MetaEntryName!(Methods[i].at) ~ "(" ~ metaCallArgs!(MetaEntryArgs!(Methods[i].at))() ~ "); break;"; + } + res ~= "\n default: ;\n }\n"; + res ~= " _id -= " ~ __toString(methodCount) ~ ";"; + res ~= "\n }"; + } + + res ~= "\n return _id; + }"; + return res; +} + +string dDeclArgs(Args...)() +{ + string ret; + foreach(i, _; Args) + { + if (i > 0) + ret ~= ", "; + ret ~= Args[i].stringof; + } + return ret; +} +string genMetaMethodsConstr(alias Funcs)(string className) +{ + string res; + enum funcsCount = Funcs.at.length; + foreach(i, bogus; Repeat!(void, funcsCount)) + { + res ~= " index++;\n" ~ + " _staticMetaObject.addMethod(new " ~ className ~ "(signature!(" ~ dDeclArgs!(MetaEntryArgs!(Funcs.at[i].at))()~ ")(\"" ~ MetaEntryName!(Funcs.at[i].at) ~ "\"), index));\n\n"; + } + return res; +} +string generateMetaObjectConstruction(alias Signals, alias Slots)() +{ + string res; + res ~= "\n + private static void _populateMetaInfo() { + alias BaseClassesTuple!(typeof(this))[0] BaseClass; + int index = BaseClass.staticMetaObject().methodCount() - 1;\n\n"; + + res ~= genMetaMethodsConstr!(Signals)("QMetaSignal"); + res ~= genMetaMethodsConstr!(Slots)("QMetaSlot"); + + res ~= " + }\n"; + return res; +} + +string generateQMetaObject(string className) +{ + string res; + res ~= " + public QMetaObject metaObject() { return staticMetaObject(); } + private static __gshared QMetaObject _staticMetaObject; + private static __gshared QMetaObjectNative _nativeStaticMetaObject; + public static QMetaObject staticMetaObject() + { + if(!_staticMetaObject) + createStaticMetaObject(); + return _staticMetaObject; + } + protected static void createStaticMetaObject() { + assert(!_staticMetaObject); + alias BaseClassesTuple!(typeof(this))[0] BaseClass; + if (!BaseClass._staticMetaObject) + BaseClass.createStaticMetaObject; + auto base = BaseClass._staticMetaObject; + _nativeStaticMetaObject = QMetaObjectNative(base.nativeId, qt_meta_stringdata_" ~ className ~ ".ptr, + qt_meta_data_" ~ className ~ ".ptr, null ); + + _staticMetaObject = new QMetaObject(&_nativeStaticMetaObject, base); +// _staticMetaObject.construct!(typeof(this)); + _populateMetaInfo(); + }\n\n"; + return res; +} + +size_t commaCount(int argCount) +{ + size_t ret = 0; + if(argCount > 1) + ret = argCount - 1; + return ret; +} + +FunctionDef[] genFuncDefs(alias Funcs, alias newFunc)() +{ + typeof(return) res; + enum funcsCount = Funcs.at.length; + foreach(i, bogus; Repeat!(void, funcsCount)) + { + string args = replicate(commaCount((MetaEntryArgs!(Funcs.at[i].at)).length), ','); + string funcSig = MetaEntryName!(Funcs.at[i].at) ~ "(" ~ qtDeclArgs!(MetaEntryArgs!(Funcs.at[i].at))() ~ ")"; + res ~= newFunc(funcSig, args); + } + return res; +} + +template Q_OBJECT_BIND() +{ +} + +// ------------------------------------------------------------------------------------------ + +string generateSignalEmitters(alias Funcs)() +{ + string res; + enum funcsCount = Funcs.at.length; + foreach(i, bogus; Repeat!(void, funcsCount)) + { + res ~= SignalEmitter!(MetaEntryArgs!(Funcs.at[i].at))(SignalType.NewSignal, MetaEntryName!(Funcs.at[i].at), cast(string[])[], i); + } + return res; +} + +string generateSlotAliases(alias Funcs)() +{ + string res; + enum funcsCount = Funcs.at.length; + foreach(i, bogus; Repeat!(void, funcsCount)) + { + string name = MetaEntryName!(Funcs.at[i].at); + res ~= format_ctfe(" alias slot_${} ${};\n", name, name); + } + return res; +} + + +string generateMetaInfo(T, alias Signals, alias Slots)() +{ + string res = ""; + auto signalList = genFuncDefs!(Signals, newSignal)(); + auto slotList = genFuncDefs!(Slots, newSlot)(); + res ~= generateSignalEmitters!(Signals)(); + res ~= generateSlotAliases!(Slots)(); + res ~= generateCode(T.stringof, signalList, slotList); + res ~= generate_qt_metacall!(Signals, Slots); + res ~= generateMetaObjectConstruction!(Signals, Slots); + res ~= generateQMetaObject(T.stringof); + return res; +} + +template Q_OBJECT() +{ + alias findSignals!(typeof(this)) SignalFuncs; + alias toMetaEntries!(SignalFuncs) SignalMetaEntries; + alias findSlots!(typeof(this)) SlotFuncs; + alias toMetaEntries!(SlotFuncs) SlotMetaEntries; + + mixin(generateMetaInfo!(typeof(this), SignalMetaEntries, SlotMetaEntries)()); + // debug output +// pragma(msg, generateMetaInfo!(typeof(this), SignalMetaEntries, SlotMetaEntries)()); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/qtd/Meta.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,83 @@ +module qt.qtd.Meta; + +import std.traits; +import std.typetuple; + +// Various compile time utilities + +public bool ctfeStartsWith(T)(T[] source, T[] pattern) +{ + return source.length >= pattern.length && source[0 .. pattern.length] == pattern[]; +} + +// compile-time toString, maybe to!string is already working in CT +string __toString(long v) +{ + if (v == 0) + return "0"; + + string ret; + + bool neg; + if (v < 0) + { + neg = true; + v = -v; + } + + while (v != 0) + { + ret = cast(char)(v % 10 + '0') ~ ret; + v = cast(long)(v / 10); + } + + if (neg) + ret = "-" ~ ret; + + return ret; +} + +// returns the type of a template parameter if there is one +template templateParam(U : V!(U), alias V) +{ + alias U templateParam; +} + +// to workaround buggy foreach, returns a tuple of Ts of size I +template Repeat(T, int I) +{ + static if (!I) alias TypeTuple!() Repeat; + else alias TypeTuple!(T, Repeat!(T, I - 1)) Repeat; +} + +//returns number of required function arguments, optional arguments excluded +int requiredArgCount(alias fn)() { + alias ParameterTypeTuple!(typeof(&fn)) P; + P p; + static if (P.length == 0) + return 0; + + foreach(i, _; P) + { + static if (!__traits(compiles, fn(p[0..$-i-1]))) + { + return p.length - i; + } + } + return 0; +} + +template isDg(Dg) +{ + enum isDg = is(Dg == delegate); +} + +template isFn(Fn) +{ + enum isFn = is(typeof(*Fn.init) == function); +} + +template isFnOrDg(Dg) +{ + enum isFnOrDg = isFn!(Dg) || isDg!(Dg); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/qtd/MetaMarshall.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,98 @@ +module qt.qtd.MetaMarshall; + +import std.traits; + +import qt.qtd.Meta; + +template isQObjectType(T) // is a QObject type that belongs to the library +{ + enum isQObjectType = is(T.__isQObjectType); +} + +template isObjectType(T) // is a Qt Object type that belongs to the library +{ + enum isObjectType = is(T.__isObjectType); +} + +template isValueType(T) // is a Qt Value type that belongs to the library +{ + enum isValueType = is(T.__isValueType); +} + +template isNativeType(T) // type that doesn't require conversion i.e. is the same in C++ and D +{ + enum isNativeType = isNumeric!T || is(T == bool) || is(T == struct); +} + +template isStringType(T) // string type +{ + enum isStringType = is(T == string); +} + +template isQList(T) +{ + enum isQList = ctfeStartsWith(Unqual!(T).stringof, "QList!"); +} + +// converts an argumnent from C++ to D in qt_metacall +string metaCallArgument(T)(string ptr) +{ + static if (isQObjectType!T || isObjectType!T) + return T.stringof ~ ".__getObject(*cast(void**)(" ~ ptr ~ "))"; + else static if (isValueType!T) + return "new " ~ T.stringof ~ "(" ~ T.stringof ~ ".__constructNativeCopy(" ~ ptr ~ "))"; + else static if (isNativeType!T) + return "*(cast(" ~ T.stringof ~ "*)" ~ ptr ~ ")"; + else static if (isStringType!T) + return "QStringUtil.toNativeString(" ~ ptr ~ ")"; + else + return "*(cast(" ~ T.stringof ~ "*)" ~ ptr ~ ")"; + //res = T.stringof; +} + +// converts a D argument type to C++ for registering in Qt meta system +string qtDeclArg(T)() +{ + static if (isQObjectType!T || isObjectType!T) + return T.stringof ~ "*"; + else static if (isValueType!T) + return T.stringof; + else static if (isStringType!T) + return "QString"; + else static if (isQList!T) + { + alias templateParam!T ElementType; + static if (is(ElementType == string)) + return "QStringList"; + else + return "QList<" ~ qtDeclArg!(templateParam!T)() ~ ">"; + } + else static if (isNativeType!T) + return Unqual!T.stringof; + else + return T.stringof; +} + +// converts an argument from D to C++ in a signal emitter +string convertSignalArgument(T)(string arg) +{ + static if (isQObjectType!T || isObjectType!T) + return arg ~ " ? " "&" ~ arg ~ ".__nativeId : cast(void**) &" ~ arg; // since it is a pointer type check arg for null + else static if (isValueType!T) + return arg ~ ".__nativeId"; + else static if (isStringType!T) + return "&_qt" ~ arg; + else static if (isNativeType!T) + return "&" ~ arg; + else + return "&" ~ arg; +} + +string prepareSignalArguments(Args...)() +{ + string res; + foreach(i, _; Args) + static if (isStringType!(Args[i])) + res ~= "auto _qt_t" ~ __toString(i) ~ " = QString(_t" ~ __toString(i) ~ ");\n"; + return res; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/qtd/ctfe/Format.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,693 @@ +/** + * Compile-Time String Formatting. + * + * Authors: Daniel Keep <daniel.keep@gmail.com> + * Copyright: See LICENSE. + */ +module qt.qtd.ctfe.Format; + +//debug = gb_Format_verbose; + +import Integer = qt.qtd.ctfe.Integer; +import String = qt.qtd.ctfe.String; +import Tuple = qt.qtd.util.Tuple; + +private +{ + string stringify(Args...)(size_t index, int alignment, + string opt, Args args) + { + if( index >= args.length ) + return "{invalid index " ~ Integer.format_ctfe(index) ~ "}"; + + if( alignment != 0 ) + return "{non-zero alignments not supported yet}"; + + foreach( i,_ ; Args ) + { + if( i == index ) + { + static if( is( Args[i] == char ) ) + { + string r; + r ~= args[i]; + return r; + } + else static if( is( Args[i] : long ) || is( Args[i] : ulong ) ) + { + int base = 10; + string prefix = ""; + + if( opt == "x" ) + base = 16; + + else if( opt == "xx" ) + { + base = 16; + prefix = "0x"; + } + else if( opt == "o" ) + base = 8; + + else if( opt == "b" ) + base = 2; + + return prefix ~ Integer.format_ctfe(args[i], base); + } + else static if( is( Args[i] : string ) ) + { + if( opt == "x" ) + { + return String.hexify_ctfe(args[i][]); + } + + if( opt == "q" ) + { + return String.escape_ctfe(args[i][]); + } + + if( opt == "l" ) + { + return Integer.format_ctfe(args[i].length); + } + + // If you don't slice, then the CALLER has to slice the + // string, otherwise CTFE barfs. + return args[i][]; + } + else static if( is( Args[i] Elem : Elem[] ) ) + { + if( opt == "l" ) + { + return Integer.format_ctfe(args[i].length); + } + + string r = "["; + foreach( ei, e ; args[i][] ) + { + if( ei != 0 ) + r ~= ", "; + r ~= stringify(0, alignment, opt, e); + } + r ~= "]"; + return r; + } + else + { + return "{cannot stringify "~Args[i].stringof~"}"; + } + } + } + + assert(false); + } + + version( Unittest ) + { + static assert( stringify(0, 0, "", 0) == "0" ); + static assert( stringify(0, 0, "", 1, -2, "abc") == "1" ); + static assert( stringify(1, 0, "", 1, -2, "abc") == "-2" ); + static assert( stringify(2, 0, "", 1, -2, "abc") == "abc" ); + + static assert( stringify(0, 0, "x", "abc") == `616263` ); + static assert( stringify(0, 0, "q", "abc") == `"abc"` ); + static assert( stringify(0, 0, "l", "abc") == `3` ); + + static assert( stringify(0, 0, "x", 0x4a) == "4a" ); + + static assert( stringify(0, 0, "", [1,2,3]) == "[1, 2, 3]" ); + static assert( stringify(0, 0, "l", [1,2,3]) == "3" ); + static assert( stringify(0, 0, "x", [9,10]) == "[9, a]" ); + static assert( stringify(0, 0, "", ["a","b"]) == "[a, b]" ); + static assert( stringify(0, 0, "q", ["a","b"]) == "[\"a\", \"b\"]" ); + + static assert( stringify(0, 0, "", 'a') == "a" ); + } +} + +/** + * Substitutes a set of arguments into a template string. + * + * The template string allows for the following escape forms: + * + * - $$ -- Literal dollar. + * - $* -- Next argument. + * - $n -- nth argument; 0-9 only. + * - ${} -- Next argument. + * - ${:f} -- Next argument, using format options "f". + * - ${n} -- nth argument. + * - ${n:f} -- nth argument, using format options "f". + * + * formatNamed allows the use of named arguments (given as alternating + * name,value pairs), but disallows "next" argument and indexed forms. + * + * Eventually, alignment and named arguments will be supported. + * + * Supported formatting options are: + * + * Integers: + * - x -- format integer in hexadecimal. + * - o -- format integer in octal. + * - b -- format integer in binary. + * + * Strings: + * - q -- quotes the string as a literal. + * - x -- formats as hexadecimal data. + * - l -- length of the string in decimal. + * + * Arrays: + * - l -- length of the array in decimal. + * - Other options are used to control element formatting. + * + * Params: + * tmpl = template string. + * args = arguments to substitute. + * Returns: + * formatted string. + */ + +string format_ctfe(Args...)(string tmpl, Args args) +{ + string r = ""; + int argPos = 0; + + while( tmpl.length > 0 ) + { + bool inExp = false; + + // Look for a $ + foreach( i,c ; tmpl ) + { + if (c == '$') + { + inExp = true; + r ~= tmpl[0..i]; + tmpl = tmpl[i+1..$]; + break; + } + } + + // If we didn't find a $, it's because we hit the end of the template. + if( !inExp ) + { + r ~= tmpl; + break; + } + + // So we're in an expansion/substitution. + + debug(gb_Format_verbose) r ~= "{in exp}"; + + if( tmpl.length == 0 ) + { + r ~= "{unterminated substitution}"; + break; + } + + // c is the next character, whilst tmpl is everything left in the + // template string. + char c = tmpl[0]; + tmpl = tmpl[1..$]; + + // $$ - escaped $. + if( c == '$' ) + { + debug(gb_Format_verbose) r ~= "{escaped $}"; + r ~= '$'; + continue; + } + + // $n - shortcut for ${n}. + if( '0' <= c && c <= '9' ) + { + debug(gb_Format_verbose) r ~= "{shorthand index}"; + r ~= stringify(c-'0', 0, "", args); + continue; + } + + // $* - shortcut for ${} + if( c == '*' ) + { + debug(gb_Format_verbose) r ~= "{shorthand next}"; + r ~= stringify(argPos++, 0, "", args); + continue; + } + + // This means we got a $ followed by something unexpected. + if( c != '{' ) + { + r ~= "{malformed substitution}"; + break; + } + + if( tmpl.length == 0 ) + { + r ~= "{unterminated substitution}"; + break; + } + + debug(gb_Format_verbose) + { + r ~= "{parse complex at '"; + r ~= c; + r ~= "':\"" ~ tmpl ~ "\"}"; + } + + // NOTE: We haven't updated c and tmpl yet. + + { + // arg will contain the index of the argument the user wanted + // substituted. + size_t arg = size_t.max; + // fmt will contain any additional formatting options. + string fmt = ""; + + // If we didn't get a : or }, that means we expect an index. + if( !( tmpl[0] == ':' || tmpl[0] == '}' ) ) + { + // So parse it. + auto used = Integer.parse_ctfe!(size_t)(tmpl, true); + + if( used == 0 ) + { + debug(gb_Format_verbose) r ~= "{used zero of \""~tmpl~"\"}"; + r ~= "{invalid argument index}"; + break; + } + + arg = Integer.parse_ctfe!(size_t)(tmpl); + tmpl = tmpl[used..$]; + + if( tmpl.length == 0 ) + { + r ~= "{unterminated substitution}"; + break; + } + } + else + { + // Otherwise, the index was elided, which means we want to use + // the index of the "next" argument. + arg = argPos; + ++ argPos; + } + + c = tmpl[0]; + tmpl = tmpl[1..$]; + + debug(gb_Format_verbose) + r ~= "{index " ~ Integer.format_ctfe(arg) ~ "}"; + + // If c is :, then we've got formatting options to parse + + if( c == ':' ) + { + debug(gb_Format_verbose) r ~= "{fmt string}"; + + // Look for the closing }. + size_t len = 0; + foreach( i,d ; tmpl ) + { + if( d == '}' ) + { + len = i; + break; + } + } + if( len == 0 ) + { + r ~= "{malformed format}"; + break; + } + fmt = tmpl[0..len]; + tmpl = tmpl[len..$]; + + if( tmpl.length == 0 ) + { + r ~= "{unterminated substitution}"; + break; + } + + c = tmpl[0]; + tmpl = tmpl[1..$]; + } + + // At this point, we should have the closing }. If not, someone's + // screwed up. + if( c != '}' ) + { + debug(gb_Format_verbose) + { + r ~= "{expected closing; got '"; + r ~= c; + r ~= "':\"" ~ tmpl ~ "\"}"; + } + r ~= "{malformed substitution}"; + break; + } + + // Stringify that bugger. + r ~= stringify(arg, 0, fmt, args); + + // When we fall off the end here, we'll continue with the + // remainder of tmpl, unless it's empty in which case we're + // finished. + } + } + + return r; +} + +version( Unittest ) +{ + static assert(format_ctfe("A: $$", "foo"[]) == "A: $"); + static assert(format_ctfe("B: a $$ c", "b"[]) == "B: a $ c"); + + static assert(format_ctfe("C: ${}", "foo"[]) == "C: foo"); + static assert(format_ctfe("D: a ${} c", "b"[]) == "D: a b c"); + + static assert(format_ctfe("E: $0", "foo"[]) == "E: foo"); + static assert(format_ctfe("F: a $0 c", "b"[]) == "F: a b c"); + + static assert(format_ctfe("G: $*", "foo"[]) == "G: foo"); + static assert(format_ctfe("H: a $* c", "b"[]) == "H: a b c"); + + static assert(format_ctfe("I: ${0}", "foo"[]) == "I: foo"); + static assert(format_ctfe("J: a ${0} c", "b"[]) == "J: a b c"); + + static assert(format_ctfe("K: ${} ${} ${}", 1, -2, "c"[]) == "K: 1 -2 c"); + static assert(format_ctfe("L: $* $* $*", 1, -2, "c"[]) == "L: 1 -2 c"); + static assert(format_ctfe("M: $0 $1 $2", 1, -2, "c"[]) == "M: 1 -2 c"); + static assert(format_ctfe("N: ${0} ${1} ${2}", 1, -2, "c"[]) == "N: 1 -2 c"); + + static assert(format_ctfe("O: ${2} ${0} ${1}", 1, -2, "c"[]) == "O: c 1 -2"); + + static assert(format_ctfe("P: ${:x} ${0:x} ${0:o} ${0:b}", 42) == "P: 2a 2a 52 101010"); + + static assert(format_ctfe("Q: ${0} ${0:q} ${0:x}", "abc"[]) == "Q: abc \"abc\" 616263"); + static assert(format_ctfe("R: ${0} ${0:q}", ["a","b","c"][]) == "R: [a, b, c] [\"a\", \"b\", \"c\"]"); + + const TORTURE_TMPL = ` + struct $*Enum + { + const Name = ${0:q}; + const string[${:l}] Members = ${1:q}; + + ${2} value() + { + return ${3:xx}; + } + } + `[]; + + const TORTURE_EXPECTED = ` + struct FooEnum + { + const Name = "Foo"; + const string[3] Members = ["bar", "quxx", "zyzzy"]; + + int value() + { + return 0x42; + } + } + `[]; + + const TORTURE_ACTUAL = format_ctfe(TORTURE_TMPL, + "Foo"[], ["bar"[],"quxx","zyzzy"][], + "int"[], 0x42); + + static assert( TORTURE_EXPECTED == TORTURE_ACTUAL ); +} + +private +{ + size_t findIndexByName(Args...)(string name, Args args) + { + foreach( i ; Tuple.Sequence!(0, Args.length, 2) ) + { + static if( !is( Args[i] : string ) ) + { + static assert(false, "expected string for argument " + ~ Integer.format_ctfe(i) ~ " in " ~ Args.stringof + ~ " not " ~ Args[i].stringof); + } + if( name == args[i][] ) + return i+1; + } + return size_t.max; + } + + version( Unittest ) + { + static assert( findIndexByName("a", "a", 0, "b", 1) == 1 ); + static assert( findIndexByName("b", "a", 0, "b", 1) == 3 ); + static assert( findIndexByName("c", "a", 0, "b", 1) == size_t.max ); + } +} + +/// ditto + +string formatNamed_ctfe(Args...)(string tmpl, Args args) +{ + string r = ""; + int argPos = 0; + + while( tmpl.length > 0 ) + { + bool inExp = false; + + // Look for a $ + foreach( i,c ; tmpl ) + { + if (c == '$') + { + inExp = true; + r ~= tmpl[0..i]; + tmpl = tmpl[i+1..$]; + break; + } + } + + // If we didn't find a $, it's because we hit the end of the template. + if( !inExp ) + { + r ~= tmpl; + break; + } + + // So we're in an expansion/substitution. + + debug(gb_Format_verbose) r ~= "{in exp}"; + + if( tmpl.length == 0 ) + { + r ~= "{unterminated substitution}"; + break; + } + + // c is the next character, whilst tmpl is everything left in the + // template string. + char c = tmpl[0]; + tmpl = tmpl[1..$]; + + // $$ - escaped $. + if( c == '$' ) + { + debug(gb_Format_verbose) r ~= "{escaped $}"; + r ~= '$'; + continue; + } + + // $a... - shortcut for $a... + if( String.isIdentStartChar_ctfe(c) ) + { + debug(gb_Format_verbose) r ~= "{shorthand name}"; + size_t i = 0; + while( i < tmpl.length ) + { + if( !String.isIdentChar_ctfe(tmpl[i]) ) + break; + ++ i; + } + string name = c ~ tmpl[0..i]; + tmpl = tmpl[i..$]; + r ~= stringify(findIndexByName(name, args), 0, "", args); + continue; + } + + // This means we got a $ followed by something unexpected. + if( c != '{' ) + { + r ~= "{malformed substitution}"; + break; + } + + if( tmpl.length == 0 ) + { + r ~= "{unterminated substitution}"; + break; + } + + debug(gb_Format_verbose) + { + r ~= "{parse complex at '"; + r ~= c; + r ~= "':\"" ~ tmpl ~ "\"}"; + } + + // NOTE: We haven't updated c and tmpl yet. + + { + // arg will contain the index of the argument the user wanted + // substituted. + size_t arg = size_t.max; + // fmt will contain any additional formatting options. + string fmt = ""; + + // If we didn't get a : or }, that means we expect a name. + if( !( tmpl[0] == ':' || tmpl[0] == '}' ) ) + { + // So parse it. + size_t i = 0; + while( i < tmpl.length ) + { + if( !String.isIdentChar_ctfe(tmpl[i]) ) + break; + ++ i; + } + string name = tmpl[0..i]; + tmpl = tmpl[i..$]; + + arg = findIndexByName(name, args); + + if( tmpl.length == 0 ) + { + r ~= "{unterminated substitution}"; + break; + } + } + else + { + // Otherwise, the name was elided. Kaboom! + r ~= "{substitution missing name}"; + break; + } + + c = tmpl[0]; + tmpl = tmpl[1..$]; + + debug(gb_Format_verbose) + r ~= "{index " ~ Integer.format_ctfe(arg) ~ "}"; + + // If c is :, then we've got formatting options to parse + + if( c == ':' ) + { + debug(gb_Format_verbose) r ~= "{fmt string}"; + + // Look for the closing }. + size_t len = 0; + foreach( i,d ; tmpl ) + { + if( d == '}' ) + { + len = i; + break; + } + } + if( len == 0 ) + { + r ~= "{malformed format}"; + break; + } + fmt = tmpl[0..len]; + tmpl = tmpl[len..$]; + + debug(gb_Format_verbose) r ~= "{fmt:"~fmt~"}"; + + if( tmpl.length == 0 ) + { + r ~= "{unterminated substitution}"; + break; + } + + c = tmpl[0]; + tmpl = tmpl[1..$]; + } + + // At this point, we should have the closing }. If not, someone's + // screwed up. + if( c != '}' ) + { + debug(gb_Format_verbose) + { + r ~= "{expected closing; got '"; + r ~= c; + r ~= "':\"" ~ tmpl ~ "\"}"; + } + r ~= "{malformed substitution}"; + break; + } + + // Stringify that bugger. + r ~= stringify(arg, 0, fmt, args); + + // When we fall off the end here, we'll continue with the + // remainder of tmpl, unless it's empty in which case we're + // finished. + } + } + + return r; +} + +version( Unittest ) +{ + static assert( formatNamed_ctfe("A: $$", "a"[], 0, "b"[], 1) == "A: $" ); + static assert( formatNamed_ctfe("B: $a", "a"[], 0, "b"[], 1) == "B: 0" ); + static assert( formatNamed_ctfe("C: $b", "a"[], 0, "b"[], 1) == "C: 1" ); + + static assert( formatNamed_ctfe("D: ${a}", "a"[], 0, "b"[], 1) == "D: 0" ); + static assert( formatNamed_ctfe("E: ${b}", "a"[], 0, "b"[], 1) == "E: 1" ); + + static assert( formatNamed_ctfe("F: $foo$bar", "foo"[], 0, "bar"[], 1) == "F: 01" ); + static assert( formatNamed_ctfe("G: ${foo}${bar}", "foo"[], 0, "bar"[], 1) == "G: 01" ); + + static assert( formatNamed_ctfe("H: ${foo:x}${bar:xx}", "foo"[], 0, "bar"[], 1) == "H: 00x1" ); + + const TORTURE_NAMED_TMPL = ` + struct ${name}Enum + { + const Name = ${name:q}; + const string[${members:l}] Members = ${members:q}; + + ${retType} value() + { + return ${value:xx}; + } + } + `[]; + + const TORTURE_NAMED_EXPECTED = ` + struct FooEnum + { + const Name = "Foo"; + const string[3] Members = ["bar", "quxx", "zyzzy"]; + + int value() + { + return 0x42; + } + } + `[]; + + const TORTURE_NAMED_ACTUAL = formatNamed_ctfe(TORTURE_NAMED_TMPL, + "name"[], "Foo"[], + "members"[], ["bar"[],"quxx","zyzzy"][], + "retType"[], "int"[], + "value"[], 0x42); + + static assert( TORTURE_NAMED_EXPECTED == TORTURE_NAMED_ACTUAL ); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/qtd/ctfe/Integer.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,169 @@ +/** + * CTFE Integer routines. + * + * Authors: Daniel Keep <daniel.keep@gmail.com> + * Copyright: See LICENSE. + */ +module qt.qtd.ctfe.Integer; + +/** + * Formats an integer as a string. You can optionally specify a different + * base; any value between 2 and 16 inclusive is supported. + * + * Params: + * v = value to format. + * base = base to use; defaults to 10. + * Returns: + * integer formatted as a string. + */ + +string format_ctfe(intT)(intT v, int base = 10) +{ + static if( !is( intT == ulong ) ) + { + return (v < 0) + ? "-" ~ format_ctfe(cast(ulong) -v, base) + : format_ctfe(cast(ulong) v, base); + } + else + { + assert( 2 <= base && base <= 16, + "base must be between 2 and 16; got " ~ format_ctfe(base, 10) ); + + string r = ""; + do + { + r = INT_CHARS[cast(size_t)(v % base)] ~ r; + v /= base; + } + while( v > 0 ); + return r; + } +} + +/** + * Parses an integer value from a string. You can optionally specify a + * different base; any value between 2 and 16 inclusive is supported. + * + * Note that this does not fail if it cannot consume the entire string; + * use returnUsed to determine the number of characters consumed. + * + * Params: + * str = string to parse. + * returnUsed = defaults to false; if set to true, returns the number of + * characters consumed from the string instead of the + * parsed value. + * base = base to use; defaults to 10. + * Returns: + * either the parsed integer or the number of characters consumed, + * depending on the value of returnUsed. + */ + +intT parse_ctfe(intT)(string str, bool returnUsed = false, int base = 10) +{ + auto origStr = str; + + assert( 2 <= base && base <= 16, + "base must be between 2 and 16; got " ~ format_ctfe(base, 10) ); + + bool neg = false; + if( str.length > 0 && str[0] == '-' ) + { + neg = true; + str = str[1..$]; + } + + if( intT.min == 0 && neg ) + assert(false, "underwhile while parsing \"" ~ origStr + ~ "\" as a " ~ intT.stringof ~ ": cannot represent negative " + ~ "values"); + + intT r = 0; + size_t used = 0; + + foreach( c ; str ) + { + int cv = -1; + + if( '0' <= c && c <= '9' ) + cv = c - '0'; + + else if( 'A' <= c && c <= 'Z' ) + cv = 10 + c - 'A'; + + else if( 'a' <= c && c <= 'z' ) + cv = 10 + c - 'a'; + + if( cv >= base || cv < 0 ) + break; + + auto oldR = r; + r = r*base + cast(intT) cv; + ++ used; + + if( r < oldR ) + assert(false, "overflow while parsing \"" ~ origStr + ~ "\" as a " ~ intT.stringof); + } + + if( neg ) + { + r = -r; + ++used; + } + + if( returnUsed ) + { + assert( used < intT.max, "overflow attempting to return " + ~ "number of characters consumed in a " ~ intT.stringof ); + + return used; + } + else + return r; +} + +/** + * Like parse_ctfe, except it will raise an error if the provided string + * cannot be parsed in its entirety. + * + * Params: + * str = the string to parse. + * base = base to use; defaults to 10. + * Returns: + * the parsed integer. + */ + +intT parseAll_ctfe(intT)(string str, int base = 10) +{ + auto used = parse_ctfe!(intT)(str, true, base); + assert( used == str.length, "could not parse entire string \"" ~ str + ~ "\"" ); + return parse_ctfe!(int)(str, false, base); +} + +private +{ + const INT_CHARS = "0123456789abcdef"; +} + +version( Unittest ) +{ + static assert( format_ctfe(0) == "0", "got: " ~ format_ctfe(0) ); + static assert( format_ctfe(1) == "1" ); + static assert( format_ctfe(-1) == "-1" ); + static assert( format_ctfe(42) == "42" ); + static assert( format_ctfe(0xf00, 16) == "f00" ); + static assert( format_ctfe(0123, 8) == "123" ); + + static assert( parse_ctfe!(long)("0") == 0 ); + static assert( parse_ctfe!(long)("1") == 1 ); + static assert( parse_ctfe!(long)("-1") == -1 ); + static assert( parse_ctfe!(long)("42") == 42 ); + static assert( parse_ctfe!(long)("f00", false, 16) == 0xf00 ); + static assert( parse_ctfe!(long)("123", false, 8) == 0123 ); + static assert( parse_ctfe!(long)("123ax", true) == 3 ); + static assert( parse_ctfe!(long)("123ax", true, 16) == 4 ); + + static assert( parseAll_ctfe!(long)("123") == 123 ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/qtd/ctfe/String.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,317 @@ +/** + * CTFE String routines. + * + * Authors: Daniel Keep <daniel.keep@gmail.com> + * Copyright: See LICENSE. + */ +module qt.qtd.ctfe.String; + +import Integer = qt.qtd.ctfe.Integer; + +private +{ + const HEX_CHARS = "0123456789abcdef"; +} + +/** + * Escapes a string into an equivalent string literal. + * + * Params: + * str = string to escape. + * aggressive = if set, the function will escape all non-printing + * characters, non-space whitespace and newlines. Defaults + * to true. + * Returns: + * Escaped string literal. + */ +string escape_ctfe(string str, bool aggressive=true) +{ + string head = ""; + + foreach( i,c ; str ) + { + if( c == '"' || c == '\\' || c == '\0' ) + { + head = "\""~str[0..i]; + str = str[i..$]; + break; + } + + if( aggressive ) + { + if( c < 0x20 || c == 0x7f ) + { + head = "\""~str[0..i]; + str = str[i..$]; + break; + } + } + } + + if( head.length == 0 ) + return "\"" ~ str ~ "\""; + + string tail = ""; + + foreach( c ; str ) + { + if( c == '"' ) + tail ~= `\"`; + + else if( c == '\\' ) + tail ~= "\\\\"; + + else if( c == '\0' ) + tail ~= `\0`; + + else if( aggressive ) + { + switch( c ) + { + case '\?': + tail ~= `\?`; + break; + + case '\a': + tail ~= `\a`; + break; + + case '\b': + tail ~= `\b`; + break; + + case '\f': + tail ~= `\f`; + break; + + case '\n': + tail ~= `\n`; + break; + + case '\r': + tail ~= `\r`; + break; + + case '\t': + tail ~= `\t`; + break; + + case '\v': + tail ~= `\v`; + break; + + default: + if( c < 0x20 || c == 0x75 ) + { + tail ~= `\x`; + tail ~= HEX_CHARS[c/0xf]; + tail ~= HEX_CHARS[c&0xf]; + } + else + tail ~= c; + } + } + else + tail ~= c; + } + + return head ~ tail ~ "\""; +} + +version( Unittest ) +{ + static assert( escape_ctfe("abc") == "\"abc\"" ); + static assert( escape_ctfe("a\"c") == "\"a\\\"c\"" ); +} + +/** + * Turns an array of bytes into a hexadecimal string. + * + * Params: + * arr = array to hexify. + * grouping = if non-zero, specifies after how many bytes to insert a + * space. + * Returns: + * String of hex bytes. + */ + +string hexify_ctfe(ubyte[] arr, int grouping = 0) +{ + string r = ""; + int bytes = grouping; + foreach( b ; arr ) + { + if( bytes == 0 && grouping > 0 ) + { + r ~= ' '; + bytes = grouping; + } + + auto bh = b/16; + auto bl = b&15; + + assert( bh < 16 ); + assert( bl < 16 ); + + r ~= HEX_CHARS[bh]; + r ~= HEX_CHARS[bl]; + + if( grouping > 0 ) + -- bytes; + } + return r; +} + +/// ditto + +string hexify_ctfe(string arr, int grouping = 0) +{ + string r = ""; + int bytes = grouping; + foreach( b ; arr ) + { + if( bytes == 0 && grouping > 0 ) + { + r ~= ' '; + bytes = grouping; + } + + auto bh = b/16; + auto bl = b&15; + + assert( bh < 16 ); + assert( bl < 16 ); + + r ~= HEX_CHARS[bh]; + r ~= HEX_CHARS[bl]; + + if( grouping > 0 ) + -- bytes; + } + return r; +} + +version( Unittest ) +{ + static const ubyte[] DATA_1 = [0x00,0x01,0x02,0x03]; + static const ubyte[] DATA_2 = [0x0f,0x10,0xef,0xf0]; + + static assert( hexify_ctfe(DATA_1) == "00010203" ); + static assert( hexify_ctfe(DATA_2) == "0f10eff0" ); + + static assert( hexify_ctfe(DATA_1, 1) == "00 01 02 03" ); + static assert( hexify_ctfe(DATA_2, 1) == "0f 10 ef f0" ); + + static assert( hexify_ctfe(DATA_1, 2) == "0001 0203" ); + static assert( hexify_ctfe(DATA_2, 2) == "0f10 eff0" ); + + static assert( hexify_ctfe(DATA_1, 4) == "00010203" ); + static assert( hexify_ctfe(DATA_2, 4) == "0f10eff0" ); +} + +/** + * Pads a string. padl adds padding to the left, padr adds it to the right. + * Params: + * str = string to pad. + * len = length to pad to. + * padding = character to use for padding. Defaults to space. + * Returns: + * padded string. + */ + +string padl_ctfe(string str, int len, char padding = ' ') +{ + while( str.length < len ) + str = padding ~ str; + return str; +} + +/// ditto + +string padr_ctfe(string str, int len, char padding = ' ') +{ + while( str.length < len ) + str ~= padding; + return str; +} + +version( Unittest ) +{ + static assert( padl_ctfe("abc", 2) == "abc" ); + static assert( padl_ctfe("abc", 3) == "abc" ); + static assert( padl_ctfe("abc", 4) == " abc" ); + static assert( padl_ctfe("abc", 4, 'x') == "xabc" ); + + static assert( padr_ctfe("abc", 2) == "abc" ); + static assert( padr_ctfe("abc", 3) == "abc" ); + static assert( padr_ctfe("abc", 4) == "abc " ); + static assert( padr_ctfe("abc", 4, 'x') == "abcx" ); +} + +/** + * Returns the tail of a string after a given splitting character. The Rev + * variant returns the tail after the last instance of the splitting + * character. + */ + +string tail_ctfe(string str, char split) +{ + foreach( i,c ; str ) + { + if( c == split ) + return str[i+1..$]; + } + return str; +} + +/// ditto + +string tailRev_ctfe(string str, char split) +{ + foreach_reverse( i,c ; str ) + { + if( c == split ) + return str[i+1..$]; + } + return str; +} + +/** + * Determines whether a character is valid in an identifier in a + * non-initial position. + * + * Does not support the full range of valid D identifier characters. + */ + +bool isIdentChar_ctfe(char c) +{ + return ('a' <= c && c <= 'z') + || ('A' <= c && c <= 'Z') + || ('0' <= c && c <= '9') + || (c == '_'); +} + +/** + * Determines whether a character is valid in an identifier in an + * initial position. + * + * Does not support the full range of valid D identifier characters. + */ + +bool isIdentStartChar_ctfe(char c) +{ + return ('a' <= c && c <= 'z') + || ('A' <= c && c <= 'Z') + || (c == '_'); +} + +/** + * Returns a line spec suitable for mixing in. This can be used with string + * mixins to ensure compile errors appear on the "correct" line in the source. + */ + +string linespec_ctfe(string file, long line) +{ + return "#line "~Integer.format_ctfe(line)~" \"" ~ file ~ "\"\n"; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/qt/qtd/util/Tuple.d Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,64 @@ +/** + * Tuple-related stuff. + * + * Authors: Daniel Keep <daniel.keep@gmail.com> + * Copyright: See LICENSE. + */ +module qt.qtd.util.Tuple; + +import std.typetuple; + +/** + * Sequence can be used to generate a tuple of integer values. It can be + * used in one of three forms: + * + * ----- + * Sequence!(6) // ==> (0, 1, 2, 3, 4, 5) + * Sequence!(1,6) // ==> (1, 2, 3, 4, 5) + * Sequence!(1,6,2) // ==> (1, 3, 5) + * ----- + */ + +template Sequence(int max) +{ + static if( max <= 0 ) + alias TypeTuple!() Sequence; + else + alias TypeTuple!(Sequence!(max-1), max-1) Sequence; +} + +/// ditto + +template Sequence(int min, int max) +{ + static if( max <= min ) + alias TypeTuple!() Sequence; + else + alias TypeTuple!(Sequence!(min, max-1), max-1) Sequence; +} + +/// ditto + +template Sequence(int min, int max, int stride) +{ + static if( min >= max ) + alias TypeTuple!() Sequence; + else + alias TypeTuple!(min, Sequence!(min+stride, max, stride)) Sequence; +} + +version( Unittest ) +{ + static assert( Sequence!(3)[0] == 0 ); + static assert( Sequence!(3)[1] == 1 ); + static assert( Sequence!(3)[2] == 2 ); + static assert( Sequence!(3).length == 3 ); + + static assert( Sequence!(1, 3)[0] == 1 ); + static assert( Sequence!(1, 3)[1] == 2 ); + static assert( Sequence!(1, 3).length == 2 ); + + static assert( Sequence!(1, 5, 2)[0] == 1 ); + static assert( Sequence!(1, 5, 2)[1] == 3 ); + static assert( Sequence!(1, 5, 2).length == 2 ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/todo.txt Sun Feb 07 16:04:36 2010 +0000 @@ -0,0 +1,10 @@ +Before 0.3 release + +1) Move nested classes into host classes they belong to +2) connectSlotsByName +3) docs +4) remove deprecated methods (as many as possible) +5) remove mangling of const methods - always reimplement them in D - to reduce binaries size at least a little bit +6) QList!(IQGraphicsItem) +7) const correct QMetaObject (QObject.metaObject() should be const?) +8) fix duic once value types are implemented as structs and add connectSlotsByName call