[OpenDocString] kdeconnect-kde (cpp)
sftpplugin.cpp
SftpPlugin::SftpPlugin(QObject *parent, const QVariantList &args)
    : KdeConnectPlugin(parent, args)
    , d(new Pimpl())
    , deviceId(device()->id())
{
    addToDolphin();
    qCDebug(KDECONNECT_PLUGIN_SFTP) << "Created device:" << device()->name();
}
Constructs a plugin object and assigns its device id to its internal dolphin object and adds it to the dolphin list.
SftpPlugin::~SftpPlugin()
{
    removeFromDolphin();
    unmount();
}
This removes the plugin object from the dolphin list and unmounts the plugin.
void SftpPlugin::addToDolphin()
{
    removeFromDolphin();

    QUrl kioUrl(QStringLiteral("kdeconnect://") + deviceId + QStringLiteral("/"));
    d->m_placesModel.addPlace(device()->name(), kioUrl, QStringLiteral("kdeconnect"));
    qCDebug(KDECONNECT_PLUGIN_SFTP) << "add to dolphin";
}
Adds the device to the dolphin place list. First it removes the device and adds it to the places model. Then it adds a kdeconnect place to the places model.
void SftpPlugin::removeFromDolphin()
{
    QUrl kioUrl(QStringLiteral("kdeconnect://") + deviceId + QStringLiteral("/"));
    QModelIndex index = d->m_placesModel.closestItem(kioUrl);
    while (index.row() != -1) {
        d->m_placesModel.removePlace(index);
        index = d->m_placesModel.closestItem(kioUrl);
    }
}
This removes all places that are closest to the kdeconnect url.
void SftpPlugin::mount()
{
    qCDebug(KDECONNECT_PLUGIN_SFTP) << "Mount device:" << device()->name();
    if (d->m_mounter) {
        return;
    }

    d->m_mounter = new Mounter(this);
    connect(d->m_mounter, &Mounter::mounted, this, &SftpPlugin::onMounted);
    connect(d->m_mounter, &Mounter::unmounted, this, &SftpPlugin::onUnmounted);
    connect(d->m_mounter, &Mounter::failed, this, &SftpPlugin::onFailed);
}
This adds a Mounter object to the device object, and sets up signal/slot connections for mounted and unmounted events.
void SftpPlugin::unmount()
{
    if (d->m_mounter) {
        d->m_mounter->deleteLater();
        d->m_mounter = nullptr;
    }
}
This removes the Mounter object upon destruction. It also removes the file entry from the internal list of Mounter objects.
bool SftpPlugin::mountAndWait()
{
    mount();
    return d->m_mounter->wait();
}
This mounts the filesystem and waits for it to finish. It returns true on the first successful attempt.
bool SftpPlugin::isMounted() const
{
    return d->m_mounter && d->m_mounter->isMounted();
}
This implements checking if the filesystem is mounted.
QString SftpPlugin::getMountError()
{
    if (!mountError.isEmpty()) {
        return mountError;
    }
    return QString();
}
Returns the mount error message if it is not empty. Otherwise it creates and returns a QString.
bool SftpPlugin::startBrowsing()
{
    if (mountAndWait()) {
        auto *job = new KIO::OpenUrlJob(QUrl(QStringLiteral("kdeconnect://") + deviceId));
        job->setUiDelegate(new KNotificationJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled));
        job->start();
        return true;
    }
    return false;
}
This starts a background job if the device is mounted and waiting for it to finish. It returns true on the first successful attempt. If the device is not mounted, it returns false.
bool SftpPlugin::receivePacket(const NetworkPacket &np)
{
    if (!(fields_c - np.body().keys().toSet()).isEmpty() && !np.has(QStringLiteral("errorMessage"))) {
        // packet is invalid
        return false;
    }

    Q_EMIT packetReceived(np);

    remoteDirectories.clear();
    if (np.has(QStringLiteral("multiPaths"))) {
        QStringList paths = np.get(QStringLiteral("multiPaths"), QStringList());
        QStringList names = np.get(QStringLiteral("pathNames"), QStringList());
        int size = qMin(names.size(), paths.size());
        for (int i = 0; i < size; i++) {
            remoteDirectories.insert(mountPoint() + paths.at(i), names.at(i));
        }
    } else {
        remoteDirectories.insert(mountPoint(), i18n("All files"));
        remoteDirectories.insert(mountPoint() + QStringLiteral("/DCIM/Camera"), i18n("Camera pictures"));
    }
    return true;
}
This method receives a NetworkPacket object np and processes it. It returns true if the packet is valid. If the packet is valid, it returns false. If the packet is multiPaths, the pathNames list is split into two lists, inserting the paths and camera pictures to the remoteDirectories list. If the multiPaths list is empty, the packet is ignored. If the device is not multiPaths, the packet is a single file or multiple files, the packet is translated to the camera pictures. If the device is multiPaths, the packet is a list of remoteDirectories list is built with the i18n function. If the device is not multiPaths, the packet is split into multiple paths and a list containing the paths and names of the remoteDirectories list. The remoteDirectories list is a list of remoteDirectories list indexed by the mountpoint, the function returns true.
QString SftpPlugin::mountPoint()
{
    QString runtimePath = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
    if (runtimePath.isEmpty()) {
        runtimePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
    }
    return QDir(runtimePath).absoluteFilePath(deviceId);
}
Returns the absolute path of the device where the runtime location is located. If the runtime path is empty, the temp location is used.
void SftpPlugin::onMounted()
{
    qCDebug(KDECONNECT_PLUGIN_SFTP) << device()->name() << QStringLiteral("Remote filesystem mounted at %1").arg(mountPoint());

    Q_EMIT mounted();
}
This emits a debug message when the remote filesystem is mounted.
void SftpPlugin::onUnmounted()
{
    qCDebug(KDECONNECT_PLUGIN_SFTP) << device()->name() << "Remote filesystem unmounted";

    unmount();

    Q_EMIT unmounted();
}
This removes the remote filesystem after it has been unmounted.
void SftpPlugin::onFailed(const QString &message)
{
    mountError = message;
    KNotification::event(KNotification::Error, device()->name(), message);

    unmount();

    Q_EMIT unmounted();
}
This sets the mount error message and unmounts the plugin.
QVariantMap SftpPlugin::getDirectories()
{
    return remoteDirectories;
}
Returns a map of remote directories.