Jump to content

Qt for HarmonyOS/qtohosextras doc/Want FDs Sender Example - main.cpp

From Qt Wiki

< Qt for HarmonyOS / qtohosextras doc

Want FDs Sender 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 <QFile>
 #include <QFileDialog>
 #include <QFormLayout>
 #include <QHBoxLayout>
 #include <QJsonDocument>
 #include <QJsonObject>
 #include <QLabel>
 #include <QLineEdit>
 #include <QPushButton>
 #include <QSharedPointer>
 #include <QTextEdit>
 #include <QVBoxLayout>
 #include <QWidget>
 #include <QtOhosExtras>
 #include <cerrno>
 #include <cstring>
 #include <sys/stat.h>

 namespace {

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

 private:
     void sendWant();
     void appendLog(const QString &message);
     void selectFiles();

     QLineEdit *m_bundleNameEdit;
     QLineEdit *m_moduleNameEdit;
     QLineEdit *m_abilityNameEdit;
     QLabel *m_pathsLabel;
     QTextEdit *m_logEdit;
     QStringList m_selectedFiles;
 };

 FdSenderWindow::FdSenderWindow(QWidget *parent)
     : QWidget(parent)
     , m_bundleNameEdit(new QLineEdit(QStringLiteral("com.ohos.wantfdsreceiver"), this))
     , m_moduleNameEdit(new QLineEdit(QStringLiteral("entry"), this))
     , m_abilityNameEdit(new QLineEdit(QStringLiteral("QAbility"), this))
     , m_pathsLabel(new QLabel(QStringLiteral("<none>"), this))
     , m_logEdit(new QTextEdit(this))
 {
     setWindowTitle(QStringLiteral("Want FD Sender"));

     auto *mainLayout = new QVBoxLayout(this);
     auto *formLayout = new QFormLayout();

     formLayout->addRow(QStringLiteral("bundleName:"), m_bundleNameEdit);
     formLayout->addRow(QStringLiteral("moduleName:"), m_moduleNameEdit);
     formLayout->addRow(QStringLiteral("abilityName:"), m_abilityNameEdit);

     auto *filePathLayout = new QHBoxLayout();
     auto *browseButton = new QPushButton(QStringLiteral("Browse..."), this);
     m_pathsLabel->setWordWrap(true);
     filePathLayout->addWidget(m_pathsLabel, 1);
     filePathLayout->addWidget(browseButton);

     auto *filePathWidget = new QWidget(this);
     filePathWidget->setLayout(filePathLayout);
     formLayout->addRow(QStringLiteral("paths:"), filePathWidget);

     QObject::connect(browseButton, &QPushButton::clicked, this, &FdSenderWindow::selectFiles);

     auto *sendButton = new QPushButton(QStringLiteral("Send FD"), this);
     QObject::connect(sendButton, &QPushButton::clicked, this, &FdSenderWindow::sendWant);

     mainLayout->addLayout(formLayout);
     mainLayout->addWidget(sendButton);

     m_logEdit->setReadOnly(true);
     mainLayout->addWidget(m_logEdit);
 }

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

 void FdSenderWindow::selectFiles()
 {
     const QStringList filePaths = QFileDialog::getOpenFileNames(this, QStringLiteral("Select Files"));
     if (filePaths.isEmpty()) {
         return;
     }

     m_selectedFiles = filePaths;
     m_pathsLabel->setText(filePaths.join(QLatin1Char('\n')));
 }

 void FdSenderWindow::sendWant()
 {
     const QString bundleName = m_bundleNameEdit->text().trimmed();
     const QString abilityName = m_abilityNameEdit->text().trimmed();
     const QStringList filePaths = m_selectedFiles;

     if (bundleName.isEmpty() || abilityName.isEmpty()) {
         appendLog(QStringLiteral("status: missing bundleName/abilityName"));
         return;
     }

     if (filePaths.isEmpty()) {
         appendLog(QStringLiteral("status: no selected files"));
         return;
     }

     QtOhosExtras::QOhosWant want;
     want.bundleName = bundleName;
     want.moduleName = m_moduleNameEdit->text().trimmed();
     want.abilityName = abilityName;

     QList<QSharedPointer<QFile>> openFiles;
     QStringList fdDetails;
     int openedCount = 0;
     for (const auto &filePath : filePaths) {
         auto file = QSharedPointer<QFile>::create(filePath);
         if (!file->open(QIODevice::ReadOnly)) {
             appendLog(QStringLiteral("fd_open: path=%1 result=error error=%2").arg(filePath, file->errorString()));
             continue;
         }

         const int fd = file->handle();
         if (fd < 0) {
             appendLog(QStringLiteral("fd_open: path=%1 result=error error=invalid_fd").arg(filePath));
             continue;
         }

         const QString fdKey = QStringLiteral("keyFd%1").arg(openedCount);
         want.fds.insert(fdKey, fd);

         struct stat statInfo;
         const int fstatResult = ::fstat(fd, &statInfo);
         const int fstatErrno = errno;
         if (fstatResult == 0) {
             fdDetails.append(
                 QStringLiteral("fd_info: key=%1 fd=%2 path=%3 dev=%4 ino=%5")
                     .arg(fdKey)
                     .arg(fd)
                     .arg(filePath)
                     .arg(static_cast<qulonglong>(statInfo.st_dev))
                     .arg(static_cast<qulonglong>(statInfo.st_ino)));
         } else {
             fdDetails.append(
                 QStringLiteral("fd_detail: key=%1 fd=%2 path=%3 stat_error=%4 message=%5")
                     .arg(fdKey)
                     .arg(fd)
                     .arg(filePath)
                     .arg(fstatErrno)
                     .arg(QString::fromLocal8Bit(strerror(fstatErrno))));
         }

         openFiles.append(file);
         ++openedCount;
     }

     if (openedCount == 0) {
         appendLog(QStringLiteral("status: no_open_fds"));
         return;
     }

     const auto operationStatus = QtOhosExtras::startAbility(want);
     appendLog(QStringLiteral("startAbility: success=%1").arg(!operationStatus.isNull() && operationStatus->success()));
     for (const auto &detail : fdDetails) {
         appendLog(detail);
     }
 }

 }

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

     FdSenderWindow window;
     window.show();

     return app.exec();
 }