/* * SPDX-License-Identifier: Apache-2.0 * Copyright (C) 2020 Raspberry Pi (Trading) Limited */ #include "drivelistmodel.h" #include "config.h" #include "dependencies/drivelist/src/drivelist.hpp" #include #include DriveListModel::DriveListModel(QObject *parent) : QAbstractListModel(parent) { _rolenames = { {deviceRole, "device"}, {descriptionRole, "description"}, {sizeRole, "size"}, {isUsbRole, "isUsb"}, {isScsiRole, "isScsi"}, {mountpointsRole, "mountpoints"} }; // Enumerate drives in seperate thread, but process results in UI thread connect(&_thread, SIGNAL(newDriveList(std::vector)), SLOT(processDriveList(std::vector))); } int DriveListModel::rowCount(const QModelIndex &) const { return _drivelist.count(); } QHash DriveListModel::roleNames() const { return _rolenames; } QVariant DriveListModel::data(const QModelIndex &index, int role) const { int row = index.row(); if (row < 0 || row >= _drivelist.count()) return QVariant(); QByteArray propertyName = _rolenames.value(role); if (propertyName.isEmpty()) return QVariant(); else return _drivelist.values().at(row)->property(propertyName); } void DriveListModel::processDriveList(std::vector l) { bool changes = false; bool filterSystemDrives = DRIVELIST_FILTER_SYSTEM_DRIVES; QSet drivesInNewList; for (auto &i: l) { // Convert STL vector to Qt QStringList QStringList mountpoints; for (auto &s: i.mountpoints) { mountpoints.append(QString::fromStdString(s)); } if (filterSystemDrives) { if (i.isSystem || i.isReadOnly) continue; // Should already be caught by isSystem variable, but just in case... if (mountpoints.contains("/") || mountpoints.contains("C://")) continue; } // Skip zero-sized and virtual devices if (i.size == 0 || i.isVirtual) continue; #ifdef Q_OS_DARWIN // Skip time machine backup. FIXME: is this best way to detect them? if (i.mountpointLabels.size() && i.mountpointLabels.front() == "Time Machine Backups") continue; #endif QString deviceNamePlusSize = QString::fromStdString(i.device)+":"+QString::number(i.size); drivesInNewList.insert(deviceNamePlusSize); if (!_drivelist.contains(deviceNamePlusSize)) { // Found new drive if (!changes) { beginResetModel(); changes = true; } _drivelist[deviceNamePlusSize] = new DriveListItem(QString::fromStdString(i.device), QString::fromStdString(i.description), i.size, i.isUSB, i.isSCSI, mountpoints, this); } } // Look for drives removed QStringList drivesInOldList = _drivelist.keys(); for (auto &device: drivesInOldList) { if (!drivesInNewList.contains(device)) { if (!changes) { beginResetModel(); changes = true; } _drivelist.value(device)->deleteLater(); _drivelist.remove(device); } } if (changes) endResetModel(); } void DriveListModel::startPolling() { _thread.start(); } void DriveListModel::stopPolling() { _thread.stop(); }