#include "Bindings.h" #include "SortedModel.h" #ifdef QT_CHARTS_LIB #include #endif #ifdef QT_QUICK_LIB #include #include #include #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct Model { QStringListModel styles; Demo demo; SortedModel sortedFileSystem; SortedModel sortedProcesses; }; void setStyle(QWidget* w, QStyle* style) { for (QObject* o: w->children()) { QWidget* c = dynamic_cast(o); if (c) { setStyle(c, style); } } w->setStyle(style); } QWindow* getWindow(QWidget* w) { QWidget* top = w; while (top && top->parentWidget()) { top = top->parentWidget(); } return top->windowHandle(); } #ifdef QT_QUICK_LIB void copyWindowGeometry(const QRect& rect, QObject* c) { if (rect.width() && rect.height()) { c->setProperty("x", rect.x()); c->setProperty("y", rect.y()); c->setProperty("width", rect.width()); c->setProperty("heigth", rect.height()); } } void createQtQuick(const QString& name, const QString& qml, Model* model, QWidget* widgets, const QString& initialTab) { QQmlApplicationEngine* engine = new QQmlApplicationEngine(); QQmlContext* c = engine->rootContext(); c->setContextProperty("styles", &model->styles); c->setContextProperty("demo", &model->demo); c->setContextProperty("sortedFileSystem", &model->sortedFileSystem); c->setContextProperty("widgets", widgets); QRect geometry; QWindow* window = getWindow(widgets); if (window) { geometry = window->geometry(); } else { geometry = QRect(0, 0, 500, 500); } engine->load(QUrl(qml)); QObject* root = engine->rootObjects().first(); copyWindowGeometry(geometry, root); root->setProperty("initialTab", initialTab); root->setProperty("qtquickIndex", QVariant(model->styles.stringList().indexOf(name))); root->setProperty("processes", QVariant::fromValue(&model->sortedProcesses)); } #endif QComboBox* createStyleComboBox(Model* model) { QComboBox* box = new QComboBox(); box->setModel(&model->styles); auto styles = QStyleFactory::keys(); QString currentStyle = QApplication::style()->objectName().toLower(); for (auto v: styles) { box->addItem("QWidgets " + v); if (v.toLower() == currentStyle) { box->setCurrentText(v); } } #ifdef QT_QUICK_LIB box->addItem("QtQuick"); #endif #ifdef QTQUICKCONTROLS2 box->addItem("QtQuick Controls 2"); #endif return box; } QStatusBar* createStatusBar(Model* model, QWidget* main, QComboBox* box, const QString& initialTab) { QRect windowRect; auto f = [windowRect, box, main, model, initialTab](const QString &text) mutable { QWindow* window = getWindow(main); bool visible = main->isVisible(); if (text.startsWith("QWidgets ")) { main->setVisible(true); if (window && !visible) { window->setX(windowRect.x()); window->setY(windowRect.y()); window->setWidth(windowRect.width()); window->setHeight(windowRect.height()); } setStyle(main, QStyleFactory::create(text.mid(9))); #ifdef QT_QUICK_LIB } else { if (window) { windowRect.setX(window->x()); windowRect.setY(window->y()); windowRect.setWidth(window->width()); windowRect.setHeight(window->height()); } main->setVisible(false); #ifdef QTQUICKCONTROLS2 if (text == "QtQuick Controls 2") { createQtQuick("QtQuick Controls 2", "qrc:///qml/demo-qtquick2.qml", model, box, initialTab); } else #endif createQtQuick("QtQuick", "qrc:///qml/demo.qml", model, box, initialTab); #endif } }; box->connect(box, &QComboBox::currentTextChanged, box, f); QSvgWidget* rust_qt_binding_generator = new QSvgWidget(":/rust_qt_binding_generator.svg"); rust_qt_binding_generator->setFixedSize(rust_qt_binding_generator->renderer()->defaultSize() / 4); QStatusBar* statusBar = new QStatusBar; statusBar->addPermanentWidget(rust_qt_binding_generator); statusBar->addPermanentWidget(box); return statusBar; } QWidget* createObjectTab(Model* model) { QWidget* view = new QWidget; Fibonacci* fibonacci = model->demo.fibonacci(); QLabel* label = new QLabel; label->setText(QCoreApplication::translate("main", "Calculate the nth Fibonacci number")); QLineEdit* input = new QLineEdit; input->setPlaceholderText("Your number"); input->setValidator(new QIntValidator(0, 100)); input->connect(input, &QLineEdit::textChanged, fibonacci, [fibonacci](const QString& text) { fibonacci->setInput(text.toInt()); }); fibonacci->connect(fibonacci, &Fibonacci::inputChanged, input, [input, fibonacci]() { input->setText(QString::number(fibonacci->input())); }); QLabel* result = new QLabel; fibonacci->connect(fibonacci, &Fibonacci::resultChanged, result, [result, fibonacci]() { result->setText(QCoreApplication::translate("main", "The Fibonacci number: ") + QString::number(fibonacci->result())); }); input->setText(QString::number(model->demo.fibonacci()->input())); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(label); layout->addWidget(input); layout->addWidget(result); view->setLayout(layout); return view; } QWidget* createListTab(Model* model) { QTableView* view = new QTableView(); model->demo.fibonacciList()->setHeaderData(0, Qt::Horizontal, QCoreApplication::translate("main", "Row"), Qt::DisplayRole); model->demo.fibonacciList()->setHeaderData(1, Qt::Horizontal, QCoreApplication::translate("main", "Fibonacci number"), Qt::DisplayRole); view->setModel(model->demo.fibonacciList()); view->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); return view; } QWidget* createTreeTab(Model* model) { QTreeView* view = new QTreeView(); model->demo.fileSystemTree()->setHeaderData(0, Qt::Horizontal, QCoreApplication::translate("main", "Name"), Qt::DisplayRole); model->demo.fileSystemTree()->setHeaderData(1, Qt::Horizontal, QCoreApplication::translate("main", "Size"), Qt::DisplayRole); view->setUniformRowHeights(true); view->setSortingEnabled(true); view->setModel(&model->sortedFileSystem); view->header()->setSectionHidden(2, true); view->header()->setSectionHidden(3, true); view->header()->setSectionHidden(4, true); auto root = model->sortedFileSystem.index(0, 0); view->expand(root); view->sortByColumn(0, Qt::AscendingOrder); view->header()->setSectionResizeMode(QHeaderView::ResizeToContents); return view; } QWidget* createProcessesTab(Model* model) { QTreeView* view = new QTreeView(); view->setUniformRowHeights(true); view->setSortingEnabled(true); view->setModel(&model->sortedProcesses); // expand when the model is populated view->connect(&model->sortedProcesses, &QAbstractItemModel::rowsInserted, view, [view](const QModelIndex& index) { if (!index.isValid()) { view->expandAll(); } }); view->expandAll(); view->sortByColumn(0, Qt::AscendingOrder); return view; } #ifdef QT_CHARTS_LIB using namespace QtCharts; QWidget* createChartTab(Model* model) { QLineSeries *sin = new QLineSeries(); sin->setName("sin"); QVXYModelMapper *sinMapper = new QVXYModelMapper(sin); sinMapper->setXColumn(0); sinMapper->setYColumn(1); sinMapper->setSeries(sin); sinMapper->setModel(model->demo.timeSeries()); QLineSeries *cos = new QLineSeries(); cos->setName("cos"); QVXYModelMapper *cosMapper = new QVXYModelMapper(cos); cosMapper->setXColumn(0); cosMapper->setYColumn(2); cosMapper->setSeries(cos); cosMapper->setModel(model->demo.timeSeries()); QChart* chart = new QChart; chart->addSeries(sin); chart->addSeries(cos); QValueAxis *axisX = new QValueAxis; axisX->setLabelFormat("%i"); axisX->setTitleText("time [s]"); chart->addAxis(axisX, Qt::AlignBottom); sin->attachAxis(axisX); cos->attachAxis(axisX); QValueAxis *axisY = new QValueAxis; axisY->setLabelFormat("%i"); axisY->setTitleText("electric potential [V]"); chart->addAxis(axisY, Qt::AlignLeft); sin->attachAxis(axisY); cos->attachAxis(axisY); QWidget* view = new QWidget; QTableView* data = new QTableView; data->setModel(model->demo.timeSeries()); QChartView *chartView = new QChartView(chart); QHBoxLayout *layout = new QHBoxLayout; layout->addWidget(data); layout->addWidget(chartView); view->setLayout(layout); return view; } #endif QTabWidget* createTabs(Model* model) { QTabWidget* tabs = new QTabWidget(); tabs->addTab(createObjectTab(model), "object"); tabs->addTab(createListTab(model), "list"); tabs->addTab(createTreeTab(model), "tree"); const int procTab = tabs->addTab(createProcessesTab(model), "processes"); tabs->connect(tabs, &QTabWidget::currentChanged, model->demo.processes(), [model, procTab](int current) { model->demo.processes()->setActive(current == procTab); }); #ifdef QT_CHARTS_LIB tabs->addTab(createChartTab(model), "chart"); #endif 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); main->setCentralWidget(tabs); main->show(); box->setCurrentText(initialStyle); for (int i = 0; i < tabs->count(); ++i) { if (tabs->tabText(i) == initialTab) { tabs->setCurrentIndex(i); } } } int main (int argc, char *argv[]) { QApplication app(argc, argv); app.setWindowIcon(QIcon(":/rust_qt_binding_generator.svg")); #ifdef QT_QUICK_LIB qmlRegisterType("org.qtproject.example", 1, 0, "SortFilterProxyModel"); qmlRegisterType("rust", 1, 0, "Fibonacci"); qmlRegisterType("rust", 1, 0, "FibonacciList"); #endif QCommandLineParser parser; parser.setApplicationDescription("Demo application for Qt and RUst"); parser.addHelpOption(); parser.addVersionOption(); // --initial-style QCommandLineOption initialStyleOption(QStringList() << "initial-style", QCoreApplication::translate("main", "Initial widget style."), QCoreApplication::translate("main", "style")); parser.addOption(initialStyleOption); // --initial-tab QCommandLineOption initialTabOption(QStringList() << "initial-tab", QCoreApplication::translate("main", "Initial tab."), QCoreApplication::translate("main", "tab")); parser.addOption(initialTabOption); 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); createMainWindow(&model, parser.value(initialStyleOption), parser.value(initialTabOption)); return app.exec(); }