Jump to content

Qt for HarmonyOS/qtohosextras doc/Start Options Example - main.cpp

From Qt Wiki
Revision as of 02:58, 17 September 2026 by Shawn Luo (talk | contribs) (Publish example source listings and restore Files lists (QTFOROH-2307))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

< Qt for HarmonyOS / qtohosextras doc

Start Options Example - main.cpp

 // Copyright (C) 2026 The Qt Company Ltd.
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

 #include <QApplication>
 #include <QCheckBox>
 #include <QColor>
 #include <QColorDialog>
 #include <QComboBox>
 #include <QFormLayout>
 #include <QFrame>
 #include <QGroupBox>
 #include <QHBoxLayout>
 #include <QImage>
 #include <QLabel>
 #include <QLineEdit>
 #include <QList>
 #include <QMetaEnum>
 #include <QMetaObject>
 #include <QPushButton>
 #include <QScrollArea>
 #include <QSharedPointer>
 #include <QSpinBox>
 #include <QStringList>
 #include <QTextEdit>
 #include <QVBoxLayout>
 #include <QWidget>
 #include <QtOhosExtras>
 #include <algorithm>
 #include <functional>

 namespace {

 struct CheckedSpinBox
 {
     QCheckBox *setCheckBox;
     QSpinBox *spinBox;
 };

 struct OptionsGroup
 {
     QGroupBox *box;
     QFormLayout *layout;
 };

 QPushButton *createTestButton(const QString &title, std::function<void()> callback)
 {
     auto *button = new QPushButton(title);
     QObject::connect(button, &QPushButton::clicked, std::move(callback));
     return button;
 }

 QWidget *createOptionsRow(QWidget *parent, const QList<QWidget *> &widgets)
 {
     auto *widget = new QWidget(parent);
     auto *layout = new QHBoxLayout(widget);
     layout->setContentsMargins(0, 0, 0, 0);
     for (auto *childWidget : widgets) {
         layout->addWidget(childWidget);
     }
     layout->addStretch();
     return widget;
 }

 QWidget *createVerticalOptionsColumn(QWidget *parent, const QList<QWidget *> &widgets)
 {
     auto *widget = new QWidget(parent);
     auto *layout = new QVBoxLayout(widget);
     layout->setContentsMargins(0, 0, 0, 0);
     layout->setSpacing(4);
     for (auto *childWidget : widgets) {
         layout->addWidget(childWidget);
     }
     return widget;
 }

 QFrame *createHorizontalSeparator(QWidget *parent)
 {
     auto *separator = new QFrame(parent);
     separator->setFrameShape(QFrame::HLine);
     separator->setFrameShadow(QFrame::Sunken);
     return separator;
 }

 void bindEnabledState(QCheckBox *checkBox, const QList<QWidget *> &controlledWidgets)
 {
     auto updateEnabledState = [checkBox, controlledWidgets]() {
         const bool enabled = checkBox->isChecked();
         for (auto *widget : controlledWidgets) {
             widget->setEnabled(enabled);
         }
     };

     QObject::connect(checkBox, &QCheckBox::toggled, checkBox, updateEnabledState);
     updateEnabledState();
 }

 QString operationStatusText(const QString &operationName, const QSharedPointer<QtOhosExtras::QOhosOperationStatus> &operationStatus)
 {
     return QStringLiteral("%1: %2")
         .arg(operationName)
         .arg(operationStatus->success() ? QStringLiteral("true") : QStringLiteral("false"));
 }

 QComboBox *createBooleanComboBox(QWidget *parent, bool defaultValue = true)
 {
     auto *comboBox = new QComboBox(parent);
     comboBox->addItem(QStringLiteral("false"), false);
     comboBox->addItem(QStringLiteral("true"), true);
     comboBox->setCurrentIndex(defaultValue ? 1 : 0);
     return comboBox;
 }

 template<typename Enum>
 QComboBox *createEnumComboBox(QWidget *parent)
 {
     auto *comboBox = new QComboBox(parent);
     const QMetaEnum metaEnum = QMetaEnum::fromType<Enum>();
     for (int i = 0; i < metaEnum.keyCount(); ++i) {
         comboBox->addItem(QString::fromLatin1(metaEnum.key(i)), metaEnum.value(i));
     }
     return comboBox;
 }

 OptionsGroup createOptionsGroup(QWidget *parent, const QString &title)
 {
     auto *box = new QGroupBox(title, parent);
     auto *layout = new QFormLayout(box);
     layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
     layout->setLabelAlignment(Qt::AlignRight | Qt::AlignTop);
     layout->setFormAlignment(Qt::AlignTop | Qt::AlignLeft);
     return {box, layout};
 }

 CheckedSpinBox createCheckedSpinBox(QWidget *parent, int minimum, int maximum, int value)
 {
     auto *setCheckBox = new QCheckBox(QStringLiteral("Set"), parent);
     auto *spinBox = new QSpinBox(parent);
     spinBox->setRange(minimum, maximum);
     spinBox->setValue(value);
     bindEnabledState(setCheckBox, {spinBox});
     return {setCheckBox, spinBox};
 }

 class StartOptionsWidget : public QWidget
 {
 public:
     StartOptionsWidget(QWidget *parent = nullptr);

 private:
     QtOhosExtras::QOhosWant configuredWant() const;
     QSharedPointer<QtOhosExtras::QOhosStartOptions> configuredStartOptionsWithoutCompletionHandler() const;
     QString configuredStartOptionsDescription() const;
     QString configuredStartOptionsValidationError() const;
     void appendLog(const QString &message);
     void releaseStartRequest(QtOhosExtras::QOhosStartRequest *startRequest);
     void startConfiguredAbility();

     QLineEdit *m_bundleNameEdit;
     QLineEdit *m_abilityNameEdit;

     QCheckBox *m_setWindowModeCheckBox;
     QComboBox *m_windowModeComboBox;
     CheckedSpinBox m_displayId;
     QCheckBox *m_setWithAnimationCheckBox;
     QComboBox *m_withAnimationValueComboBox;
     CheckedSpinBox m_windowLeft;
     CheckedSpinBox m_windowTop;
     CheckedSpinBox m_windowWidth;
     CheckedSpinBox m_windowHeight;
     QCheckBox *m_setProcessModeAndStartupVisibilityCheckBox;
     QComboBox *m_processModeComboBox;
     QComboBox *m_startupVisibilityComboBox;
     QCheckBox *m_setStartWindowIconCheckBox;
     QCheckBox *m_setStartWindowBackgroundColorCheckBox;
     QLineEdit *m_startWindowBackgroundColorEdit;
     QPushButton *m_pickStartWindowBackgroundColorButton;
     QCheckBox *m_setSupportWindowModesCheckBox;
     QCheckBox *m_fullScreenModeCheckBox;
     QCheckBox *m_splitModeCheckBox;
     QCheckBox *m_floatingModeCheckBox;
     CheckedSpinBox m_minWindowWidth;
     CheckedSpinBox m_minWindowHeight;
     CheckedSpinBox m_maxWindowWidth;
     CheckedSpinBox m_maxWindowHeight;
     QCheckBox *m_setHideStartWindowCheckBox;
     QComboBox *m_hideStartWindowValueComboBox;
     QCheckBox *m_setWindowCreateParamsCheckBox;
     QCheckBox *m_setCompletionHandlerCheckBox;

     QTextEdit *m_logEdit;
     QList<QSharedPointer<QtOhosExtras::QOhosStartRequest>> m_pendingStartRequests;
 };

 StartOptionsWidget::StartOptionsWidget(QWidget *parent)
     : QWidget(parent)
 {
     setWindowTitle(QStringLiteral("Start Options Example"));
     resize(1700, 900);

     auto *mainLayout = new QHBoxLayout(this);
     mainLayout->setContentsMargins(8, 8, 8, 8);
     mainLayout->setSpacing(8);

     auto *scrollArea = new QScrollArea(this);
     scrollArea->setWidgetResizable(true);
     scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
     scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
     scrollArea->setMinimumWidth(980);
     mainLayout->addWidget(scrollArea, 3);

     auto *configurationWidget = new QWidget(scrollArea);
     auto *configurationLayout = new QVBoxLayout(configurationWidget);
     configurationLayout->setContentsMargins(12, 12, 12, 12);
     configurationLayout->setSpacing(10);
     scrollArea->setWidget(configurationWidget);
     configurationWidget->setMinimumWidth(980);

     auto *wantGroup = new QGroupBox(QStringLiteral("Want"), configurationWidget);
     auto *wantLayout = new QFormLayout(wantGroup);
     wantLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
     wantLayout->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter);
     m_bundleNameEdit = new QLineEdit(QStringLiteral("com.start.ability.for.result.target"), this);
     m_abilityNameEdit = new QLineEdit(QStringLiteral("EntryAbility"), this);
     m_bundleNameEdit->setMinimumWidth(360);
     m_abilityNameEdit->setMinimumWidth(360);
     wantLayout->addRow(QStringLiteral("Bundle Name:"), m_bundleNameEdit);
     wantLayout->addRow(QStringLiteral("Ability Name:"), m_abilityNameEdit);
     configurationLayout->addWidget(wantGroup);

     configurationLayout->addWidget(createHorizontalSeparator(configurationWidget));

     configurationLayout->addWidget(
         new QLabel(QStringLiteral("All StartOptions fields")));

     const auto windowPlacement = createOptionsGroup(configurationWidget, QStringLiteral("Window Placement And Mode"));
     const auto process = createOptionsGroup(configurationWidget, QStringLiteral("Process And Visibility"));
     const auto startupWindow = createOptionsGroup(configurationWidget, QStringLiteral("Startup Window"));
     const auto windowLimits = createOptionsGroup(configurationWidget, QStringLiteral("Window Size And Limits"));
     const auto completionHandler = createOptionsGroup(configurationWidget, QStringLiteral("Completion Handler"));

     m_setWindowModeCheckBox = new QCheckBox(QStringLiteral("Set"), this);
     m_windowModeComboBox = createEnumComboBox<QtOhosExtras::QOhosStartOptions::WindowMode>(this);
     m_windowModeComboBox->setMinimumContentsLength(32);
     windowPlacement.layout->addRow(QStringLiteral("windowMode:"), createOptionsRow(this, {m_setWindowModeCheckBox, m_windowModeComboBox}));
     bindEnabledState(m_setWindowModeCheckBox, {m_windowModeComboBox});

     m_displayId = createCheckedSpinBox(this, -1, 9999, 0);
     windowPlacement.layout->addRow(
         QStringLiteral("displayId:"),
         createOptionsRow(this, {m_displayId.setCheckBox, m_displayId.spinBox}));

     m_setWithAnimationCheckBox = new QCheckBox(QStringLiteral("Set"), this);
     m_withAnimationValueComboBox = createBooleanComboBox(this);
     windowPlacement.layout->addRow(QStringLiteral("withAnimation:"), createOptionsRow(this, {m_setWithAnimationCheckBox, m_withAnimationValueComboBox}));
     bindEnabledState(m_setWithAnimationCheckBox, {m_withAnimationValueComboBox});

     m_windowLeft = createCheckedSpinBox(this, -10000, 10000, 0);
     windowPlacement.layout->addRow(
         QStringLiteral("windowLeft:"),
         createOptionsRow(this, {m_windowLeft.setCheckBox, m_windowLeft.spinBox}));

     m_windowTop = createCheckedSpinBox(this, -10000, 10000, 0);
     windowPlacement.layout->addRow(
         QStringLiteral("windowTop:"),
         createOptionsRow(this, {m_windowTop.setCheckBox, m_windowTop.spinBox}));

     m_windowWidth = createCheckedSpinBox(this, 0, 10000, 800);
     windowPlacement.layout->addRow(
         QStringLiteral("windowWidth:"),
         createOptionsRow(this, {m_windowWidth.setCheckBox, m_windowWidth.spinBox}));

     m_windowHeight = createCheckedSpinBox(this, 0, 10000, 600);
     windowPlacement.layout->addRow(
         QStringLiteral("windowHeight:"),
         createOptionsRow(this, {m_windowHeight.setCheckBox, m_windowHeight.spinBox}));

     m_setProcessModeAndStartupVisibilityCheckBox = new QCheckBox(QStringLiteral("Set"), this);
     m_processModeComboBox = createEnumComboBox<QtOhosExtras::QOhosStartOptions::ProcessMode>(this);
     m_processModeComboBox->setMinimumContentsLength(40);
     m_startupVisibilityComboBox = createEnumComboBox<QtOhosExtras::QOhosStartOptions::StartupVisibility>(this);
     m_startupVisibilityComboBox->setMinimumContentsLength(18);
     process.layout->addRow(QStringLiteral("processMode:"), createOptionsRow(this, {m_setProcessModeAndStartupVisibilityCheckBox, m_processModeComboBox}));
     auto *startupVisibilityHintLabel = new QLabel(QStringLiteral("Requires processMode"), this);
     process.layout->addRow(QStringLiteral("startupVisibility:"), createOptionsRow(this, {startupVisibilityHintLabel, m_startupVisibilityComboBox}));
     bindEnabledState(
         m_setProcessModeAndStartupVisibilityCheckBox,
         {m_processModeComboBox, startupVisibilityHintLabel, m_startupVisibilityComboBox});

     m_setStartWindowIconCheckBox = new QCheckBox(QStringLiteral("Set"), this);
     startupWindow.layout->addRow(QStringLiteral("startWindowIcon:"), m_setStartWindowIconCheckBox);

     m_setStartWindowBackgroundColorCheckBox = new QCheckBox(QStringLiteral("Set"), this);
     m_startWindowBackgroundColorEdit = new QLineEdit(QStringLiteral("#00ff00"), this);
     m_startWindowBackgroundColorEdit->setMinimumWidth(220);
     m_pickStartWindowBackgroundColorButton = new QPushButton(QStringLiteral("Pick..."), this);
     startupWindow.layout->addRow(
         QStringLiteral("startWindowBackgroundColor:"),
         createOptionsRow(this, {m_setStartWindowBackgroundColorCheckBox, m_startWindowBackgroundColorEdit, m_pickStartWindowBackgroundColorButton}));
     bindEnabledState(
         m_setStartWindowBackgroundColorCheckBox,
         {m_startWindowBackgroundColorEdit, m_pickStartWindowBackgroundColorButton});
     QObject::connect(
         m_pickStartWindowBackgroundColorButton, &QPushButton::clicked, this,
         [this]() {
             const QColor currentColor(m_startWindowBackgroundColorEdit->text().trimmed());
             const QColor selectedColor = QColorDialog::getColor(currentColor.isValid() ? currentColor : QColor(Qt::white), this, QStringLiteral("Select Start Window Background Color"));
             if (selectedColor.isValid()) {
                 const auto colorFormat =
                     selectedColor.alpha() == 255 ? QColor::HexRgb : QColor::HexArgb;
                 m_startWindowBackgroundColorEdit->setText(selectedColor.name(colorFormat));
             }
         });

     m_setSupportWindowModesCheckBox = new QCheckBox(QStringLiteral("Set"), this);
     m_fullScreenModeCheckBox = new QCheckBox(QStringLiteral("FULL_SCREEN"), this);
     m_splitModeCheckBox = new QCheckBox(QStringLiteral("SPLIT"), this);
     m_floatingModeCheckBox = new QCheckBox(QStringLiteral("FLOATING"), this);
     startupWindow.layout->addRow(
         QStringLiteral("supportWindowModes:"),
         createVerticalOptionsColumn(
             this,
             {
                 m_setSupportWindowModesCheckBox,
                 m_fullScreenModeCheckBox,
                 m_splitModeCheckBox,
                 m_floatingModeCheckBox,
             }));
     bindEnabledState(
         m_setSupportWindowModesCheckBox,
         {m_fullScreenModeCheckBox, m_splitModeCheckBox, m_floatingModeCheckBox});

     m_minWindowWidth = createCheckedSpinBox(this, 0, 10000, 320);
     windowLimits.layout->addRow(
         QStringLiteral("minWindowWidth:"),
         createOptionsRow(this, {m_minWindowWidth.setCheckBox, m_minWindowWidth.spinBox}));

     m_minWindowHeight = createCheckedSpinBox(this, 0, 10000, 240);
     windowLimits.layout->addRow(
         QStringLiteral("minWindowHeight:"),
         createOptionsRow(this, {m_minWindowHeight.setCheckBox, m_minWindowHeight.spinBox}));

     m_maxWindowWidth = createCheckedSpinBox(this, 0, 10000, 2560);
     windowLimits.layout->addRow(
         QStringLiteral("maxWindowWidth:"),
         createOptionsRow(this, {m_maxWindowWidth.setCheckBox, m_maxWindowWidth.spinBox}));

     m_maxWindowHeight = createCheckedSpinBox(this, 0, 10000, 2560);
     windowLimits.layout->addRow(
         QStringLiteral("maxWindowHeight:"),
         createOptionsRow(this, {m_maxWindowHeight.setCheckBox, m_maxWindowHeight.spinBox}));

     m_setHideStartWindowCheckBox = new QCheckBox(QStringLiteral("Set"), this);
     m_hideStartWindowValueComboBox = createBooleanComboBox(this);
     startupWindow.layout->addRow(QStringLiteral("hideStartWindow:"), createOptionsRow(this, {m_setHideStartWindowCheckBox, m_hideStartWindowValueComboBox}));
     bindEnabledState(m_setHideStartWindowCheckBox, {m_hideStartWindowValueComboBox});

     m_setWindowCreateParamsCheckBox = new QCheckBox(QStringLiteral("Set animationType=FADE_IN_OUT"), this);
     startupWindow.layout->addRow(QStringLiteral("windowCreateParams:"), m_setWindowCreateParamsCheckBox);

     m_setCompletionHandlerCheckBox = new QCheckBox(QStringLiteral("Set"), this);
     completionHandler.layout->addRow(QStringLiteral("completionHandler:"), m_setCompletionHandlerCheckBox);

     configurationLayout->addWidget(windowPlacement.box);
     configurationLayout->addWidget(process.box);
     configurationLayout->addWidget(startupWindow.box);
     configurationLayout->addWidget(windowLimits.box);
     configurationLayout->addWidget(completionHandler.box);

     configurationLayout->addStretch();

     auto *logPanel = new QWidget(this);
     auto *logLayout = new QVBoxLayout(logPanel);
     logLayout->setContentsMargins(12, 12, 12, 12);
     logLayout->addWidget(new QLabel(QStringLiteral("Actions")));

     logLayout->addWidget(
         createTestButton(
             QStringLiteral("Start Ability - configured start options"),
             [this]() {
                 startConfiguredAbility();
             }));
     logLayout->addWidget(createHorizontalSeparator(logPanel));
     logLayout->addWidget(new QLabel(QStringLiteral("Log")));

     m_logEdit = new QTextEdit(logPanel);
     m_logEdit->setReadOnly(true);
     m_logEdit->setMinimumWidth(520);
     logLayout->addWidget(m_logEdit);
     mainLayout->addWidget(logPanel, 2);
 }

 QtOhosExtras::QOhosWant StartOptionsWidget::configuredWant() const
 {
     QtOhosExtras::QOhosWant want;
     want.bundleName = m_bundleNameEdit->text().trimmed();
     want.abilityName = m_abilityNameEdit->text().trimmed();
     return want;
 }

 QSharedPointer<QtOhosExtras::QOhosStartOptions> StartOptionsWidget::configuredStartOptionsWithoutCompletionHandler() const
 {
     auto startOptions = QtOhosExtras::createStartOptions();

     if (m_setWindowModeCheckBox->isChecked()) {
         startOptions->setWindowMode(static_cast<QtOhosExtras::QOhosStartOptions::WindowMode>(m_windowModeComboBox->currentData().toInt()));
     }
     if (m_displayId.setCheckBox->isChecked()) {
         startOptions->setDisplayId(m_displayId.spinBox->value());
     }
     if (m_setWithAnimationCheckBox->isChecked()) {
         startOptions->setWithAnimation(m_withAnimationValueComboBox->currentData().toBool());
     }
     if (m_windowLeft.setCheckBox->isChecked()) {
         startOptions->setWindowLeft(m_windowLeft.spinBox->value());
     }
     if (m_windowTop.setCheckBox->isChecked()) {
         startOptions->setWindowTop(m_windowTop.spinBox->value());
     }
     if (m_windowWidth.setCheckBox->isChecked()) {
         startOptions->setWindowWidth(m_windowWidth.spinBox->value());
     }
     if (m_windowHeight.setCheckBox->isChecked()) {
         startOptions->setWindowHeight(m_windowHeight.spinBox->value());
     }
     if (m_setProcessModeAndStartupVisibilityCheckBox->isChecked()) {
         startOptions->setProcessMode(static_cast<QtOhosExtras::QOhosStartOptions::ProcessMode>(m_processModeComboBox->currentData().toInt()));
         startOptions->setStartupVisibility(static_cast<QtOhosExtras::QOhosStartOptions::StartupVisibility>(m_startupVisibilityComboBox->currentData().toInt()));
     }

     if (m_setStartWindowIconCheckBox->isChecked()) {
         QImage startWindowIcon(QStringLiteral(":/startoptions/qt-logo.png"));
         startOptions->setStartWindowIcon(startWindowIcon);
     }
     if (m_setStartWindowBackgroundColorCheckBox->isChecked()) {
         const QColor backgroundColor(m_startWindowBackgroundColorEdit->text().trimmed());
         startOptions->setStartWindowBackgroundColor(backgroundColor);
     }
     if (m_setSupportWindowModesCheckBox->isChecked()) {
         QList<QtOhosExtras::QOhosStartOptions::SupportWindowMode> supportWindowModes;
         if (m_fullScreenModeCheckBox->isChecked()) {
             supportWindowModes.append(QtOhosExtras::QOhosStartOptions::SupportWindowMode::FULL_SCREEN);
         }
         if (m_splitModeCheckBox->isChecked()) {
             supportWindowModes.append(QtOhosExtras::QOhosStartOptions::SupportWindowMode::SPLIT);
         }
         if (m_floatingModeCheckBox->isChecked()) {
             supportWindowModes.append(QtOhosExtras::QOhosStartOptions::SupportWindowMode::FLOATING);
         }
         if (!supportWindowModes.isEmpty()) {
             startOptions->setSupportWindowModes(supportWindowModes);
         }
     }
     if (m_minWindowWidth.setCheckBox->isChecked()) {
         startOptions->setMinWindowWidth(m_minWindowWidth.spinBox->value());
     }
     if (m_minWindowHeight.setCheckBox->isChecked()) {
         startOptions->setMinWindowHeight(m_minWindowHeight.spinBox->value());
     }
     if (m_maxWindowWidth.setCheckBox->isChecked()) {
         startOptions->setMaxWindowWidth(m_maxWindowWidth.spinBox->value());
     }
     if (m_maxWindowHeight.setCheckBox->isChecked()) {
         startOptions->setMaxWindowHeight(m_maxWindowHeight.spinBox->value());
     }
     if (m_setHideStartWindowCheckBox->isChecked()) {
         startOptions->setHideStartWindow(m_hideStartWindowValueComboBox->currentData().toBool());
     }
     if (m_setWindowCreateParamsCheckBox->isChecked()) {
         auto windowCreateParams = QtOhosExtras::createWindowCreateParams();
         windowCreateParams->setAnimationType(QtOhosExtras::QOhosWindowCreateParams::AnimationType::FADE_IN_OUT);
         startOptions->setWindowCreateParams(*windowCreateParams);
     }

     return startOptions;
 }

 QString StartOptionsWidget::configuredStartOptionsValidationError() const
 {
     if (m_setStartWindowBackgroundColorCheckBox->isChecked()) {
         const QColor backgroundColor(m_startWindowBackgroundColorEdit->text().trimmed());
         if (!backgroundColor.isValid()) {
             return QStringLiteral("Invalid configuration: startWindowBackgroundColor is not a valid color.");
         }
     }

     return QString();
 }

 QString StartOptionsWidget::configuredStartOptionsDescription() const
 {
     QStringList fields;

     if (m_setWindowModeCheckBox->isChecked()) {
         fields.append(QStringLiteral("windowMode=%1").arg(m_windowModeComboBox->currentText()));
     }
     if (m_displayId.setCheckBox->isChecked()) {
         fields.append(QStringLiteral("displayId=%1").arg(m_displayId.spinBox->value()));
     }
     if (m_setWithAnimationCheckBox->isChecked()) {
         fields.append(QStringLiteral("withAnimation=%1")
             .arg(m_withAnimationValueComboBox->currentText()));
     }
     if (m_windowLeft.setCheckBox->isChecked()) {
         fields.append(QStringLiteral("windowLeft=%1").arg(m_windowLeft.spinBox->value()));
     }
     if (m_windowTop.setCheckBox->isChecked()) {
         fields.append(QStringLiteral("windowTop=%1").arg(m_windowTop.spinBox->value()));
     }
     if (m_windowWidth.setCheckBox->isChecked()) {
         fields.append(QStringLiteral("windowWidth=%1").arg(m_windowWidth.spinBox->value()));
     }
     if (m_windowHeight.setCheckBox->isChecked()) {
         fields.append(QStringLiteral("windowHeight=%1").arg(m_windowHeight.spinBox->value()));
     }
     if (m_setProcessModeAndStartupVisibilityCheckBox->isChecked()) {
         fields.append(QStringLiteral("processMode=%1").arg(m_processModeComboBox->currentText()));
         fields.append(QStringLiteral("startupVisibility=%1").arg(m_startupVisibilityComboBox->currentText()));
     }
     if (m_setStartWindowIconCheckBox->isChecked()) {
         fields.append(QStringLiteral("startWindowIcon=:/startoptions/qt-logo.png"));
     }
     if (m_setStartWindowBackgroundColorCheckBox->isChecked()) {
         fields.append(QStringLiteral("startWindowBackgroundColor=%1")
             .arg(m_startWindowBackgroundColorEdit->text().trimmed()));
     }
     if (m_setSupportWindowModesCheckBox->isChecked()) {
         QStringList supportWindowModes;
         if (m_fullScreenModeCheckBox->isChecked()) {
             supportWindowModes.append(QStringLiteral("FULL_SCREEN"));
         }
         if (m_splitModeCheckBox->isChecked()) {
             supportWindowModes.append(QStringLiteral("SPLIT"));
         }
         if (m_floatingModeCheckBox->isChecked()) {
             supportWindowModes.append(QStringLiteral("FLOATING"));
         }
         if (!supportWindowModes.isEmpty()) {
             fields.append(QStringLiteral("supportWindowModes=[%1]")
                 .arg(supportWindowModes.join(QStringLiteral(","))));
         }
     }
     if (m_minWindowWidth.setCheckBox->isChecked()) {
         fields.append(QStringLiteral("minWindowWidth=%1").arg(m_minWindowWidth.spinBox->value()));
     }
     if (m_minWindowHeight.setCheckBox->isChecked()) {
         fields.append(QStringLiteral("minWindowHeight=%1").arg(m_minWindowHeight.spinBox->value()));
     }
     if (m_maxWindowWidth.setCheckBox->isChecked()) {
         fields.append(QStringLiteral("maxWindowWidth=%1").arg(m_maxWindowWidth.spinBox->value()));
     }
     if (m_maxWindowHeight.setCheckBox->isChecked()) {
         fields.append(QStringLiteral("maxWindowHeight=%1").arg(m_maxWindowHeight.spinBox->value()));
     }
     if (m_setHideStartWindowCheckBox->isChecked()) {
         fields.append(QStringLiteral("hideStartWindow=%1")
             .arg(m_hideStartWindowValueComboBox->currentText()));
     }
     if (m_setWindowCreateParamsCheckBox->isChecked()) {
         fields.append(QStringLiteral("windowCreateParams.animationType=FADE_IN_OUT"));
     }
     if (m_setCompletionHandlerCheckBox->isChecked()) {
         fields.append(QStringLiteral("completionHandler=QOhosStartRequest"));
     }
     return QStringLiteral("Configured StartOptions: %1")
         .arg(fields.isEmpty() ? QStringLiteral("<none>") : fields.join(QStringLiteral(", ")));
 }

 void StartOptionsWidget::appendLog(const QString &message)
 {
     m_logEdit->append(message);
 }

 void StartOptionsWidget::releaseStartRequest(QtOhosExtras::QOhosStartRequest *startRequest)
 {
     QMetaObject::invokeMethod(
         this,
         [this, startRequest]() {
             const auto it = std::find_if(
                 m_pendingStartRequests.begin(), m_pendingStartRequests.end(),
                 [startRequest](const QSharedPointer<QtOhosExtras::QOhosStartRequest> &pendingStartRequest) {
                     return pendingStartRequest.get() == startRequest;
                 });
             if (it != m_pendingStartRequests.end()) {
                 m_pendingStartRequests.erase(it);
             }
         },
         Qt::QueuedConnection);
 }

 void StartOptionsWidget::startConfiguredAbility()
 {
     auto want = configuredWant();
     const auto validationError = configuredStartOptionsValidationError();
     if (!validationError.isEmpty()) {
         appendLog(validationError);
         return;
     }
     auto startOptions = configuredStartOptionsWithoutCompletionHandler();
     appendLog(configuredStartOptionsDescription());

     if (m_setCompletionHandlerCheckBox->isChecked()) {
         auto startRequest = QtOhosExtras::createStartRequest(*startOptions);

         m_pendingStartRequests.append(startRequest);
         auto *requestPtr = startRequest.get();
         QObject::connect(
             requestPtr, &QtOhosExtras::QOhosStartRequest::requestSucceeded, this,
             [this, requestPtr](QtOhosExtras::QOhosElementName elementName, const QString &message) {
                 appendLog(QStringLiteral("requestSucceeded: %1/%2/%3 %4")
                     .arg(elementName.bundleName)
                     .arg(elementName.moduleName)
                     .arg(elementName.abilityName)
                     .arg(message));
                 releaseStartRequest(requestPtr);
             });
         QObject::connect(
             requestPtr, &QtOhosExtras::QOhosStartRequest::requestFailed, this,
             [this, requestPtr](QtOhosExtras::QOhosElementName elementName, const QString &message) {
                 appendLog(QStringLiteral("requestFailed: %1/%2/%3 %4")
                     .arg(elementName.bundleName)
                     .arg(elementName.moduleName)
                     .arg(elementName.abilityName)
                     .arg(message));
                 releaseStartRequest(requestPtr);
             });

         auto operationStatus = QtOhosExtras::startAbility(want, *startRequest);
         appendLog(operationStatusText(QStringLiteral("startAbility(want, startRequest)"), operationStatus));
         if (!operationStatus->success()) {
             releaseStartRequest(requestPtr);
         }
         return;
     }

     auto operationStatus = QtOhosExtras::startAbility(want, *startOptions);
     appendLog(operationStatusText(QStringLiteral("startAbility(want, configuredStartOptions)"), operationStatus));
 }

 }

 int main(int argc, char *argv[])
 {
     QApplication app(argc, argv);

     StartOptionsWidget widget;
     widget.show();

     return app.exec();
 }