File indexing completed on 2024-04-28 16:43:18

0001 /*
0002     SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "devicesproxymodel.h"
0008 
0009 #include <BluezQt/Adapter>
0010 #include <BluezQt/Device>
0011 
0012 DevicesProxyModel::DevicesProxyModel(QObject *parent)
0013     : QSortFilterProxyModel(parent)
0014 {
0015     setDynamicSortFilter(true);
0016     sort(0, Qt::DescendingOrder);
0017 }
0018 
0019 QHash<int, QByteArray> DevicesProxyModel::roleNames() const
0020 {
0021     QHash<int, QByteArray> roles = QSortFilterProxyModel::roleNames();
0022     roles[SectionRole] = QByteArrayLiteral("Section");
0023     roles[DeviceFullNameRole] = QByteArrayLiteral("DeviceFullName");
0024     return roles;
0025 }
0026 
0027 QVariant DevicesProxyModel::data(const QModelIndex &index, int role) const
0028 {
0029     switch (role) {
0030     case SectionRole:
0031         if (index.data(BluezQt::DevicesModel::ConnectedRole).toBool()) {
0032             return QStringLiteral("Connected");
0033         }
0034         return QStringLiteral("Available");
0035 
0036     case DeviceFullNameRole:
0037         if (duplicateIndexAddress(index)) {
0038             const QString &name = QSortFilterProxyModel::data(index, BluezQt::DevicesModel::NameRole).toString();
0039             const QString &ubi = QSortFilterProxyModel::data(index, BluezQt::DevicesModel::UbiRole).toString();
0040             const QString &hci = adapterHciString(ubi);
0041 
0042             if (!hci.isEmpty()) {
0043                 return QStringLiteral("%1 - %2").arg(name, hci);
0044             }
0045         }
0046         return QSortFilterProxyModel::data(index, BluezQt::DevicesModel::NameRole);
0047 
0048     default:
0049         return QSortFilterProxyModel::data(index, role);
0050     }
0051 }
0052 
0053 bool DevicesProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
0054 {
0055     bool leftConnected = left.data(BluezQt::DevicesModel::ConnectedRole).toBool();
0056     bool rightConnected = right.data(BluezQt::DevicesModel::ConnectedRole).toBool();
0057 
0058     if (leftConnected < rightConnected) {
0059         return true;
0060     } else if (leftConnected > rightConnected) {
0061         return false;
0062     }
0063 
0064     const QString &leftName = left.data(BluezQt::DevicesModel::NameRole).toString();
0065     const QString &rightName = right.data(BluezQt::DevicesModel::NameRole).toString();
0066 
0067     return QString::localeAwareCompare(leftName, rightName) > 0;
0068 }
0069 
0070 // Returns "hciX" part from UBI "/org/bluez/hciX/dev_xx_xx_xx_xx_xx_xx"
0071 QString DevicesProxyModel::adapterHciString(const QString &ubi) const
0072 {
0073     int startIndex = ubi.indexOf(QLatin1String("/hci")) + 1;
0074 
0075     if (startIndex < 1) {
0076         return QString();
0077     }
0078 
0079     int endIndex = ubi.indexOf(QLatin1Char('/'), startIndex);
0080 
0081     if (endIndex == -1) {
0082         return ubi.mid(startIndex);
0083     }
0084     return ubi.mid(startIndex, endIndex - startIndex);
0085 }
0086 
0087 bool DevicesProxyModel::duplicateIndexAddress(const QModelIndex &idx) const
0088 {
0089     const QModelIndexList &list = match(index(0, 0), //
0090                                         BluezQt::DevicesModel::AddressRole,
0091                                         idx.data(BluezQt::DevicesModel::AddressRole).toString(),
0092                                         2,
0093                                         Qt::MatchExactly);
0094     return list.size() > 1;
0095 }
0096 
0097 bool DevicesProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
0098 {
0099     const QModelIndex index = sourceModel()->index(source_row, 0, source_parent);
0100     // Only show paired and connected devices in the KCM and applet
0101     return index.data(BluezQt::DevicesModel::PairedRole).toBool() || index.data(BluezQt::DevicesModel::ConnectedRole).toBool();
0102 }