File indexing completed on 2024-05-19 05:29:59
0001 /* 0002 * SPDX-FileCopyrightText: 2001 Matthias Hoelzer-Kluepfel <mhk@caldera.de> 0003 * SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 #include "kcmusb.h" 0006 0007 #include <QHBoxLayout> 0008 #include <QHeaderView> 0009 #include <QList> 0010 #include <QSplitter> 0011 #include <QTextEdit> 0012 #include <QTimer> 0013 #include <QTreeWidget> 0014 0015 #include <KLocalizedString> 0016 #include <KPluginFactory> 0017 0018 #include "usbdevices.h" 0019 0020 K_PLUGIN_CLASS_WITH_JSON(USBViewer, "kcmusb.json") 0021 0022 USBViewer::USBViewer(QObject *parent, const KPluginMetaData &data) 0023 : KCModule(parent, data) 0024 { 0025 QHBoxLayout *mainLayout = new QHBoxLayout(widget()); 0026 mainLayout->setContentsMargins(0, 0, 0, 0); 0027 mainLayout->setSpacing(0); 0028 0029 QSplitter *splitter = new QSplitter(widget()); 0030 splitter->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding); 0031 mainLayout->addWidget(splitter); 0032 0033 _devices = new QTreeWidget(splitter); 0034 0035 QStringList headers{i18n("Device")}; 0036 _devices->setHeaderLabels(headers); 0037 _devices->setRootIsDecorated(true); 0038 _devices->header()->hide(); 0039 //_devices->setColumnWidthMode(0, Q3ListView::Maximum); 0040 0041 QList<int> sizes; 0042 sizes.append(200); 0043 splitter->setSizes(sizes); 0044 0045 _details = new QTextEdit(splitter); 0046 _details->setReadOnly(true); 0047 0048 QTimer *refreshTimer = new QTimer(this); 0049 // 1 sec seems to be a good compromise between latency and polling load. 0050 refreshTimer->start(1000); 0051 0052 connect(refreshTimer, &QTimer::timeout, this, &USBViewer::refresh); 0053 connect(_devices, &QTreeWidget::currentItemChanged, this, &USBViewer::selectionChanged); 0054 } 0055 0056 USBViewer::~USBViewer() 0057 { 0058 USBDevice::clear(); 0059 } 0060 0061 void USBViewer::load() 0062 { 0063 _items.clear(); 0064 _devices->clear(); 0065 0066 refresh(); 0067 } 0068 0069 static quint32 key(USBDevice &dev) 0070 { 0071 return dev.bus() * 256 + dev.device(); 0072 } 0073 0074 static quint32 key_parent(USBDevice &dev) 0075 { 0076 return dev.bus() * 256 + dev.parent(); 0077 } 0078 0079 static void delete_recursive(QTreeWidgetItem *item, const QMap<int, QTreeWidgetItem *> &new_items) 0080 { 0081 if (!item) 0082 return; 0083 0084 QTreeWidgetItemIterator it(item, QTreeWidgetItemIterator::All); 0085 while (*it != nullptr) { 0086 QTreeWidgetItem *currentItem = *it; 0087 if (new_items.contains(currentItem->text(1).toUInt()) == false) { 0088 delete_recursive(currentItem->child(0), new_items); 0089 delete currentItem; 0090 } 0091 ++it; 0092 } 0093 } 0094 0095 void USBViewer::refresh() 0096 { 0097 QMap<int, QTreeWidgetItem *> new_items; 0098 0099 if (!USBDevice::load()) 0100 return; 0101 0102 int level = 0; 0103 bool found = true; 0104 0105 while (found) { 0106 found = false; 0107 0108 const auto devices = USBDevice::devices(); 0109 for (USBDevice *usbDevice : devices) { 0110 if (usbDevice->level() == level) { 0111 quint32 k = key(*usbDevice); 0112 if (level == 0) { 0113 QTreeWidgetItem *item = _items.value(k); 0114 if (!item) { 0115 QStringList itemContent; 0116 itemContent << usbDevice->product() << QString::number(k); 0117 item = new QTreeWidgetItem(_devices, itemContent); 0118 } 0119 new_items.insert(k, item); 0120 found = true; 0121 } else { 0122 QTreeWidgetItem *parent = new_items.value(key_parent(*usbDevice)); 0123 if (parent) { 0124 QTreeWidgetItem *item = _items.value(k); 0125 0126 if (!item) { 0127 QStringList itemContent; 0128 itemContent << usbDevice->product() << QString::number(k); 0129 item = new QTreeWidgetItem(parent, itemContent); 0130 } 0131 new_items.insert(k, item); 0132 parent->setExpanded(true); 0133 found = true; 0134 } 0135 } 0136 } 0137 } 0138 0139 ++level; 0140 } 0141 0142 // recursive delete all items not in new_items 0143 delete_recursive(_devices->topLevelItem(0), new_items); 0144 0145 _items = new_items; 0146 0147 if (_devices->selectedItems().isEmpty() == true) 0148 selectionChanged(_devices->topLevelItem(0)); 0149 } 0150 0151 void USBViewer::selectionChanged(QTreeWidgetItem *item) 0152 { 0153 if (item) { 0154 quint32 busdev = item->text(1).toUInt(); 0155 USBDevice *dev = USBDevice::find(busdev >> 8, busdev & 255); 0156 if (dev) { 0157 _details->setHtml(dev->dump()); 0158 return; 0159 } 0160 } 0161 _details->clear(); 0162 } 0163 0164 #include "kcmusb.moc" 0165 0166 #include "moc_kcmusb.cpp"