diff --git a/CMakeLists.txt b/CMakeLists.txt index 592ed4e..b92d4a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ find_package(Qt5 ${QT_MIN_VERSION} CONFIG find_package(Qt5QuickControls2 EXACT ${Qt5Core_VERSION}) find_package(Qt5Charts EXACT ${Qt5Core_VERSION}) set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) if (ECM_FOUND) # Find KDE Modules diff --git a/README.md b/README.md index 8487913..7afb968 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Rust Qt Binding Generator -![Rust Qt Binding](logo.svg) +![Rust Qt Binding](demo/logo.svg) This code generator gets you started quickly to use Rust code from Qt and QML. In other words, it helps to create a Qt based GUI on top of Rust code. diff --git a/demo/demo-qtquick2.qml b/demo/demo-qtquick2.qml deleted file mode 100644 index 8ade85d..0000000 --- a/demo/demo-qtquick2.qml +++ /dev/null @@ -1,65 +0,0 @@ -import QtQuick 2.6 -import QtQuick.Controls 2.0 -import QtQuick.Layouts 1.3 - -ApplicationWindow { - id: application - x: windowX - y: windowY - width: windowWidth - height: windowHeight - visible: true - TabBar { - id: bar - width: parent.width - TabButton { text: "style" } - TabButton { text: "object" } - TabButton { text: "list" } - TabButton { text: "tree" } - } - StackLayout { - width: parent.width - anchors.top: bar.bottom - anchors.bottom: parent.bottom - currentIndex: bar.currentIndex - ColumnLayout { - ComboBox { - currentIndex: qtquickIndex - model: styles - textRole: "display" - onCurrentIndexChanged: { - if (currentIndex != qtquickIndex) { - widgets.currentIndex = currentIndex; - application.close(); - } - } - } - Image { - source: "logo.svg" - } - } - RowLayout { - TextField { - id: fibonacciInput - placeholderText: "Your number" - validator: IntValidator {bottom: 0; top: 100;} - Component.onCompleted: { text = demo.fibonacci.input } - onTextChanged: { demo.fibonacci.input = parseInt(text, 10) } - } - Text { - text: "The Fibonacci number: " + demo.fibonacci.result - } - } - ListView { - id: listView - model: demo.fibonacciList - delegate: Row { - Text { text: result } - } - } - Text { - id: treeView - text: "No TreeView in QtQuick Controls 2" - } - } -} diff --git a/logo.svg b/demo/logo.svg similarity index 100% rename from logo.svg rename to demo/logo.svg diff --git a/demo/qml/Fibonacci.qml b/demo/qml/Fibonacci.qml new file mode 100644 index 0000000..929a132 --- /dev/null +++ b/demo/qml/Fibonacci.qml @@ -0,0 +1,27 @@ +import QtQuick 2.6 +import QtQuick.Controls 1.5 +import QtQuick.Layouts 1.3 + +Column { + Text { + text: qsTr("Calculate the nth Fibonacci number") + } + TextField { + id: fibonacciInput + placeholderText: qsTr("Your number") + validator: IntValidator { + bottom: 0 + top: 100 + } + text: demo.fibonacci.input + onTextChanged: { + var val = parseInt(text, 10) + if (val !== demo.fibonacci.input) { + demo.fibonacci.input = val + } + } + } + Text { + text: qsTr("The Fibonacci number: ") + demo.fibonacci.result + } +} diff --git a/demo/qml/FibonacciList.qml b/demo/qml/FibonacciList.qml new file mode 100644 index 0000000..1b6e77a --- /dev/null +++ b/demo/qml/FibonacciList.qml @@ -0,0 +1,23 @@ +import QtQuick 2.6 +import QtQml.Models 2.2 +import QtQuick.Controls 1.5 +import QtQuick.Layouts 1.3 + +TableView { + id: listView + model: demo.fibonacciList + TableViewColumn { + delegate: Text { + text: styleData.row + 1 + } + title: "Row" + width: 100 + Component.onCompleted: resizeToContents() + } + TableViewColumn { + role: "display" + title: "Fibonacci Number" + width: 100 + Component.onCompleted: resizeToContents() + } +} diff --git a/demo/qml/StyleSwitcher.qml b/demo/qml/StyleSwitcher.qml new file mode 100644 index 0000000..7a9b667 --- /dev/null +++ b/demo/qml/StyleSwitcher.qml @@ -0,0 +1,25 @@ +import QtQuick 2.6 +import QtQuick.Controls 1.5 +import QtQuick.Layouts 1.3 + +RowLayout { + id: content + Layout.fillWidth: true + Image { + sourceSize.height: 2* box.height + fillMode: Image.PreserveAspectFit + source: "../logo.svg" + } + ComboBox { + id: box + currentIndex: qtquickIndex + model: styles + textRole: "display" + onCurrentIndexChanged: { + if (currentIndex !== qtquickIndex) { + widgets.currentIndex = currentIndex; + application.close(); + } + } + } +} diff --git a/demo/chart.qml b/demo/qml/chart.qml similarity index 100% rename from demo/chart.qml rename to demo/qml/chart.qml diff --git a/demo/qml/demo-qtquick2.qml b/demo/qml/demo-qtquick2.qml new file mode 100644 index 0000000..a4f1c12 --- /dev/null +++ b/demo/qml/demo-qtquick2.qml @@ -0,0 +1,82 @@ +import QtQuick 2.6 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.3 + +ApplicationWindow { + id: application + property string initialTab: "style" + property int qtquickIndex: 0 + visible: true + footer: StyleSwitcher { + anchors.fill: parent + } + contentItem { + TabBar { + id: bar + width: parent.width + TabButton { + text: "object" + } + TabButton { + text: "list" + } + TabButton { + text: "tree" + } + } + StackLayout { + width: parent.width + anchors.top: bar.bottom + anchors.bottom: parent.bottom + currentIndex: bar.currentIndex + ColumnLayout { + ComboBox { + currentIndex: qtquickIndex + model: styles + textRole: "display" + onCurrentIndexChanged: { + if (currentIndex != qtquickIndex) { + widgets.currentIndex = currentIndex + application.close() + } + } + } + Image { + source: "../logo.svg" + } + } + RowLayout { + TextField { + id: fibonacciInput + placeholderText: "Your number" + validator: IntValidator { + bottom: 0 + top: 100 + } + Component.onCompleted: { + text = demo.fibonacci.input + } + onTextChanged: { + demo.fibonacci.input = parseInt(text, 10) + } + } + Text { + text: "The Fibonacci number: " + demo.fibonacci.result + } + } + ListView { + id: listView + model: demo.fibonacciList + delegate: Row { + Text { + text: result + } + } + } + Text { + id: treeView + text: "No TreeView in QtQuick Controls 2" + } + } + } +} diff --git a/demo/demo.qml b/demo/qml/demo.qml similarity index 72% rename from demo/demo.qml rename to demo/qml/demo.qml index 29fd565..ceddeaa 100644 --- a/demo/demo.qml +++ b/demo/qml/demo.qml @@ -7,11 +7,15 @@ ApplicationWindow { id: application property string initialTab: "style" property int qtquickIndex: 0 - property var processes: ListModel { ListElement{ name: "init"} } + property var processes: ListModel { + ListElement { + name: "init" + } + } onInitialTabChanged: { for (var i = 0; i < tabView.count; ++i) { if (tabView.getTab(i).title === initialTab) { - tabView.currentIndex = i; + tabView.currentIndex = i } } } @@ -26,55 +30,24 @@ ApplicationWindow { id: processSelection model: processes } + statusBar: StatusBar { + StyleSwitcher { + anchors.right: parent.right + } + } TabView { id: tabView anchors.fill: parent - Tab { - title: "style" - Column { - anchors.fill: parent - anchors.margins: 5 - ComboBox { - currentIndex: qtquickIndex - model: styles - textRole: "display" - onCurrentIndexChanged: { - if (currentIndex !== qtquickIndex) { - widgets.currentIndex = currentIndex; - application.close(); - } - } - } - Image { - source: "logo.svg" - } - } - } Tab { title: "object" - RowLayout { - TextField { - id: fibonacciInput - placeholderText: "Your number" - validator: IntValidator {bottom: 0; top: 100;} - Component.onCompleted: { text = demo.fibonacci.input } - onTextChanged: { demo.fibonacci.input = parseInt(text, 10) } - } - Text { - text: "The Fibonacci number: " + demo.fibonacci.result - } + Fibonacci { + anchors.fill: parent } } Tab { title: "list" - TableView { - id: listView - model: demo.fibonacciList - TableViewColumn { - role: "display" - title: "Row" - width: 100 - } + FibonacciList { + anchors.fill: parent } } Tab { @@ -94,15 +67,15 @@ ApplicationWindow { role: "fileSize" } Component.onCompleted: { - var root = treeView.rootIndex; - var first = sortedFileSystem.index(0, 0, root); - treeView.expand(first); + var root = treeView.rootIndex + var first = sortedFileSystem.index(0, 0, root) + treeView.expand(first) } onSortIndicatorColumnChanged: sort() onSortIndicatorOrderChanged: sort() function sort() { - var role = getColumn(treeView.sortIndicatorColumn).role; - model.sortByRole(role, treeView.sortIndicatorOrder); + var role = getColumn(treeView.sortIndicatorColumn).role + model.sortByRole(role, treeView.sortIndicatorOrder) } } } @@ -116,13 +89,13 @@ ApplicationWindow { width: parent.width placeholderText: "Filter processes" onTextChanged: { - processes.filterRegExp - = new RegExp(processFilterInput.text); + processes.filterRegExp = new RegExp(processFilterInput.text) } } TreeView { onClicked: { - processSelection.select(index, ItemSelectionModel.ToggleCurrent); + processSelection.select( + index, ItemSelectionModel.ToggleCurrent) } Binding { target: demo.processes @@ -136,7 +109,7 @@ ApplicationWindow { model: processes selection: processSelection selectionMode: SelectionMode.ExtendedSelection -// selectionMode: SelectionMode.SingleSelection + // selectionMode: SelectionMode.SingleSelection sortIndicatorVisible: true alternatingRowColors: true TableViewColumn { @@ -154,17 +127,20 @@ ApplicationWindow { onSortIndicatorColumnChanged: sort() onSortIndicatorOrderChanged: sort() function sort() { - var role = getColumn(processView.sortIndicatorColumn).role; - model.sortByRole(role, processView.sortIndicatorOrder); + var role = getColumn( + processView.sortIndicatorColumn).role + model.sortByRole(role, processView.sortIndicatorOrder) } Timer { - interval: 100; running: true; repeat: true + interval: 100 + running: true + repeat: true onTriggered: { - var root = processView.rootIndex; - var systemd = processes.index(1, 0, root); + var root = processView.rootIndex + var systemd = processes.index(1, 0, root) if (processes.data(systemd) === "systemd") { - processView.expand(systemd); - running = false; + processView.expand(systemd) + running = false } } } @@ -190,14 +166,14 @@ ApplicationWindow { target: loaderEditor.item onEditingFinished: { if (!demo) { - return; + return } - var val = loaderEditor.item.text; - var row = styleData.row; + var val = loaderEditor.item.text + var row = styleData.row if (styleData.column === 0) { - demo.timeSeries.setInput(row, val); + demo.timeSeries.setInput(row, val) } else { - demo.timeSeries.setResult(row, val); + demo.timeSeries.setResult(row, val) } } } @@ -230,7 +206,7 @@ ApplicationWindow { title: "result" } itemDelegate: { - return editableDelegate; + return editableDelegate } } Item { @@ -238,7 +214,7 @@ ApplicationWindow { Layout.fillHeight: true Text { anchors.centerIn: parent - text: "QtChart is not available."; + text: "QtChart is not available." visible: chartLoader.status !== Loader.Ready } Loader { diff --git a/demo/resource_file.qrc b/demo/resource_file.qrc index 5851961..dc79c44 100644 --- a/demo/resource_file.qrc +++ b/demo/resource_file.qrc @@ -1,8 +1,11 @@ - demo.qml - chart.qml - demo-qtquick2.qml - ../logo.svg + qml/demo.qml + qml/chart.qml + qml/demo-qtquick2.qml + logo.svg + qml/Fibonacci.qml + qml/FibonacciList.qml + qml/StyleSwitcher.qml diff --git a/demo/rust/src/implementation/fibonacci.rs b/demo/rust/src/implementation/fibonacci.rs index 10d4181..f3c1d46 100644 --- a/demo/rust/src/implementation/fibonacci.rs +++ b/demo/rust/src/implementation/fibonacci.rs @@ -73,9 +73,9 @@ impl FibonacciListTrait for FibonacciList { &self.emit } fn row_count(&self) -> usize { - 94 + 93 } fn result(&self, row: usize) -> u64 { - fibonacci(row as u32) as u64 + fibonacci(row as u32 + 1) as u64 } } diff --git a/demo/src/main.cpp b/demo/src/main.cpp index 2dc2600..48e19e8 100644 --- a/demo/src/main.cpp +++ b/demo/src/main.cpp @@ -117,21 +117,21 @@ QComboBox* createStyleComboBox(Model* model) { return box; } -QWidget* createStyleTab(Model* model, QWidget* tabs, QComboBox* box, +QStatusBar* createStatusBar(Model* model, QWidget* main, QComboBox* box, const QString& initialTab) { QRect windowRect; - auto f = [windowRect, box, tabs, model, initialTab](const QString &text) mutable { - QWindow* window = getWindow(tabs); - bool visible = tabs->isVisible(); + auto f = [windowRect, box, main, model, initialTab](const QString &text) mutable { + QWindow* window = getWindow(main); + bool visible = main->isVisible(); if (text.startsWith("QWidgets ")) { - tabs->setVisible(true); + main->setVisible(true); if (window && !visible) { window->setX(windowRect.x()); window->setY(windowRect.y()); window->setWidth(windowRect.width()); window->setHeight(windowRect.height()); } - setStyle(tabs, QStyleFactory::create(text.mid(9))); + setStyle(main, QStyleFactory::create(text.mid(9))); #ifdef QT_QUICK_LIB } else { if (window) { @@ -140,28 +140,26 @@ QWidget* createStyleTab(Model* model, QWidget* tabs, QComboBox* box, windowRect.setWidth(window->width()); windowRect.setHeight(window->height()); } - tabs->setVisible(false); + main->setVisible(false); #ifdef QTQUICKCONTROLS2 if (text == "QtQuick Controls 2") { - createQtQuick("QtQuick Controls 2", "qrc:///demo-qtquick2.qml", + createQtQuick("QtQuick Controls 2", "qrc:///qml/demo-qtquick2.qml", model, box, initialTab); } else #endif - createQtQuick("QtQuick", "qrc:///demo.qml", model, box, initialTab); + createQtQuick("QtQuick", "qrc:///qml/demo.qml", model, box, initialTab); #endif } }; box->connect(box, &QComboBox::currentTextChanged, box, f); QSvgWidget* logo = new QSvgWidget(":/logo.svg"); - logo->setFixedSize(logo->renderer()->defaultSize()); + logo->setFixedSize(logo->renderer()->defaultSize() / 4); - QWidget* tab = new QWidget; - QVBoxLayout *layout = new QVBoxLayout; - layout->addWidget(box); - layout->addWidget(logo); - tab->setLayout(layout); - return tab; + QStatusBar* statusBar = new QStatusBar; + statusBar->addPermanentWidget(logo); + statusBar->addPermanentWidget(box); + return statusBar; } QWidget* createObjectTab(Model* model) { @@ -270,12 +268,8 @@ QWidget* createChartTab(Model* model) { } #endif -void createWidgets(Model* model, const QString& initialStyle, - const QString& initialTab) { +QTabWidget* createTabs(Model* model, QComboBox* box) { QTabWidget* tabs = new QTabWidget(); - - QComboBox* box = createStyleComboBox(model); - tabs->addTab(createStyleTab(model, tabs, box, initialTab), "style"); tabs->addTab(createObjectTab(model), "object"); tabs->addTab(createListTab(model), "list"); tabs->addTab(createTreeTab(model), "tree"); @@ -287,8 +281,20 @@ void createWidgets(Model* model, const QString& initialStyle, #ifdef QT_CHARTS_LIB tabs->addTab(createChartTab(model), "chart"); #endif - tabs->setMinimumSize(QSize(500, 500)); - tabs->show(); + return tabs; +} + +void createMainWindow(Model* model, const QString& initialStyle, + const QString& initialTab) { + QMainWindow* main = new QMainWindow(); + main->setMinimumSize(QSize(500, 500)); + + QComboBox* box = createStyleComboBox(model); + QStatusBar* statusBar = createStatusBar(model, main, box, initialTab); + main->setStatusBar(statusBar); + QTabWidget* tabs = createTabs(model, box); + main->setCentralWidget(tabs); + main->show(); box->setCurrentText(initialStyle); for (int i = 0; i < tabs->count(); ++i) { if (tabs->tabText(i) == initialTab) { @@ -327,14 +333,15 @@ int main (int argc, char *argv[]) parser.process(app); Model model; + model.demo.fibonacci()->setInput(1); model.demo.fileSystemTree()->setPath("/"); model.sortedFileSystem.setSourceModel(model.demo.fileSystemTree()); model.sortedFileSystem.setDynamicSortFilter(true); model.sortedProcesses.setSourceModel(model.demo.processes()); model.sortedProcesses.setDynamicSortFilter(true); - createWidgets(&model, parser.value(initialStyleOption), - parser.value(initialTabOption)); + createMainWindow(&model, parser.value(initialStyleOption), + parser.value(initialTabOption)); return app.exec(); }