File indexing completed on 2024-03-24 17:00:26

0001 /*
0002  * This file is part of the KDE project
0003  *
0004  * SPDX-FileCopyrightText: 2010-2011 Alejandro Fiestas Olivares <afiestas@kde.org>
0005  * SPDX-FileCopyrightText: 2010-2011 UFO Coders <info@ufocoders.com>
0006  *
0007  * SPDX-License-Identifier: LGPL-2.0-or-later
0008  */
0009 
0010 #include "sendfilewizard.h"
0011 #include "bluedevil_sendfile.h"
0012 #include "sendfilesjob.h"
0013 
0014 #include "pages/connectingpage.h"
0015 #include "pages/failpage.h"
0016 #include "pages/selectdeviceandfilespage.h"
0017 #include "pages/selectdevicepage.h"
0018 #include "pages/selectfilespage.h"
0019 
0020 #include <QApplication>
0021 #include <QPushButton>
0022 #include <QUrl>
0023 
0024 #include <KIO/JobTracker>
0025 #include <KLocalizedString>
0026 #include <KStatusBarJobTracker>
0027 
0028 #include <BluezQt/Adapter>
0029 #include <BluezQt/Device>
0030 #include <BluezQt/InitManagerJob>
0031 #include <BluezQt/ObexManager>
0032 #include <BluezQt/PendingCall>
0033 
0034 SendFileWizard::SendFileWizard(const QString &device, const QStringList &files)
0035     : QWizard()
0036     , m_deviceUrl(device)
0037     , m_files(files)
0038     , m_job(nullptr)
0039 {
0040     setOption(NoCancelButton, false);
0041     setButton(QWizard::NextButton, new QPushButton(QIcon::fromTheme(QStringLiteral("document-export")), i18n("Send Files")));
0042     setButton(QWizard::CancelButton, new QPushButton(QIcon::fromTheme(QStringLiteral("dialog-cancel")), i18n("Cancel")));
0043     setOption(QWizard::DisabledBackButtonOnLastPage);
0044     setOption(QWizard::NoBackButtonOnStartPage);
0045 
0046     qCDebug(BLUEDEVIL_SENDFILE_LOG) << "Device" << m_deviceUrl;
0047     qCDebug(BLUEDEVIL_SENDFILE_LOG) << "Files" << m_files;
0048 
0049     // Initialize BluezQt
0050     m_manager = new BluezQt::Manager(this);
0051     BluezQt::InitManagerJob *initJob = m_manager->init();
0052     initJob->start();
0053     connect(initJob, &BluezQt::InitManagerJob::result, this, &SendFileWizard::initJobResult);
0054 
0055     // Make sure that obexd is running
0056     BluezQt::PendingCall *servicePendingCall = BluezQt::ObexManager::startService();
0057     connect(servicePendingCall, &BluezQt::PendingCall::finished, this, &SendFileWizard::slotServicePendingCallFinished);
0058 }
0059 
0060 SendFileWizard::~SendFileWizard()
0061 {
0062     if (m_job) {
0063         m_job->doKill();
0064     }
0065 }
0066 
0067 void SendFileWizard::done(int result)
0068 {
0069     qCDebug(BLUEDEVIL_SENDFILE_LOG) << "Wizard done: " << result;
0070 
0071     QWizard::done(result);
0072 
0073     if (!m_job) {
0074         qApp->quit();
0075     }
0076 }
0077 
0078 BluezQt::Manager *SendFileWizard::manager() const
0079 {
0080     return m_manager;
0081 }
0082 
0083 QStringList SendFileWizard::files() const
0084 {
0085     return m_files;
0086 }
0087 
0088 void SendFileWizard::setFiles(const QStringList &files)
0089 {
0090     m_files = files;
0091 }
0092 
0093 BluezQt::DevicePtr SendFileWizard::device() const
0094 {
0095     return m_device;
0096 }
0097 
0098 void SendFileWizard::setDevice(BluezQt::DevicePtr device)
0099 {
0100     m_device = device;
0101 }
0102 
0103 void SendFileWizard::startTransfer(const QDBusObjectPath &session)
0104 {
0105     if (m_files.isEmpty()) {
0106         qCDebug(BLUEDEVIL_SENDFILE_LOG) << "No files to send";
0107         return;
0108     }
0109 
0110     if (!m_device) {
0111         qCDebug(BLUEDEVIL_SENDFILE_LOG) << "No device selected";
0112         return;
0113     }
0114 
0115     m_job = new SendFilesJob(m_files, m_device, session);
0116     connect(m_job, &SendFilesJob::destroyed, qApp, &QCoreApplication::quit);
0117 
0118     KIO::getJobTracker()->registerJob(m_job);
0119     m_job->start();
0120 
0121     done(1);
0122 }
0123 
0124 void SendFileWizard::initJobResult(BluezQt::InitManagerJob *job)
0125 {
0126     if (job->error()) {
0127         qCWarning(BLUEDEVIL_SENDFILE_LOG) << "Error initializing manager:" << job->errorText();
0128         qApp->exit();
0129         return;
0130     }
0131 
0132     qCDebug(BLUEDEVIL_SENDFILE_LOG) << "Manager initialized";
0133 
0134     if (!m_obexServiceInitialized) {
0135         // org.bluez.obex is not ready yet, so init the wizard later
0136         connect(this, &SendFileWizard::obexServiceInitialized, this, &SendFileWizard::initWizard);
0137         return;
0138     }
0139 
0140     initWizard();
0141 }
0142 
0143 void SendFileWizard::slotServicePendingCallFinished(BluezQt::PendingCall *call)
0144 {
0145     m_obexServiceInitialized = true;
0146     m_obexdServiceError = static_cast<BluezQt::PendingCall::Error>(call->error());
0147 
0148     if (m_obexdServiceError != BluezQt::PendingCall::NoError) {
0149         setErrorMessage(i18nc("@info:status %1 error message", "Failed to start org.bluez.obex service: %1", call->errorText()));
0150     }
0151 
0152     Q_EMIT obexServiceInitialized();
0153 }
0154 
0155 void SendFileWizard::initWizard()
0156 {
0157     if (m_obexdServiceError != BluezQt::PendingCall::NoError) {
0158         // Error message is set in slotServicePendingCallFinished
0159         auto earlyFailPage = new FailPage(this);
0160         earlyFailPage->setErrorMessage(errorMessage());
0161         addPage(earlyFailPage);
0162         show();
0163         return;
0164     }
0165 
0166     // KIO address: bluetooth://40-87-2b-1a-39-28/00001105-0000-1000-8000-00805F9B34FB
0167     if (m_deviceUrl.startsWith(QLatin1String("bluetooth"))) {
0168         QString address = QUrl(m_deviceUrl).host();
0169         address.replace(QLatin1Char('-'), QLatin1Char(':'));
0170         m_device = m_manager->deviceForAddress(address.toUpper());
0171     } else {
0172         m_device = m_manager->deviceForUbi(m_deviceUrl);
0173     }
0174 
0175     // If the device's adapter is powered off, sending file would fail.
0176     // Let the user know about it!
0177     if (m_device && !m_device->adapter()->isPowered()) {
0178         m_device.clear();
0179     }
0180 
0181     if (m_device) {
0182         if (m_files.isEmpty()) {
0183             addPage(new SelectFilesPage(this));
0184         }
0185     } else {
0186         if (m_files.isEmpty()) {
0187             addPage(new SelectDeviceAndFilesPage(this));
0188         } else {
0189             addPage(new SelectDevicePage(this));
0190         }
0191     }
0192 
0193     addPage(new ConnectingPage(this));
0194     addPage(new FailPage(this));
0195 
0196     // Only show wizard after init is completed
0197     show();
0198 }
0199 
0200 QString SendFileWizard::errorMessage() const
0201 {
0202     return m_errorMessage;
0203 }
0204 
0205 void SendFileWizard::setErrorMessage(const QString &message)
0206 {
0207     m_errorMessage = message;
0208 }