File indexing completed on 2024-05-12 05:35:54
0001 /* 0002 SPDX-FileCopyrightText: 2009-2010 Trever Fischer <tdfischer@fedoraproject.org> 0003 SPDX-FileCopyrightText: 2015 Kai UWe Broulik <kde@privat.broulik.de> 0004 SPDX-FileCopyrightText: 2021 Ismael Asensio <isma.af@gmail.com> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "DeviceAutomounterKCM.h" 0010 #include <QDBusConnection> 0011 #include <QDBusMessage> 0012 #include <QItemSelectionModel> 0013 #include <QStandardItem> 0014 #include <QStandardItemModel> 0015 #include <kconfigwidgets_version.h> 0016 0017 #include <KAboutData> 0018 #include <KConfigGroup> 0019 #include <Solid/DeviceNotifier> 0020 #include <Solid/StorageVolume> 0021 0022 #include <KPluginFactory> 0023 0024 #include "AutomounterSettings.h" 0025 #include "DeviceAutomounterData.h" 0026 #include "DeviceModel.h" 0027 #include "LayoutSettings.h" 0028 0029 K_PLUGIN_FACTORY_WITH_JSON(DeviceAutomounterKCMFactory, "device_automounter_kcm.json", registerPlugin<DeviceAutomounterKCM>(); 0030 registerPlugin<DeviceAutomounterData>();) 0031 0032 DeviceAutomounterKCM::DeviceAutomounterKCM(QObject *parent, const KPluginMetaData &data) 0033 : KCModule(parent, data) 0034 , m_settings(new AutomounterSettings(widget())) 0035 , m_devices(new DeviceModel(m_settings, this)) 0036 { 0037 setupUi(widget()); 0038 0039 addConfig(m_settings, widget()); 0040 0041 deviceView->setModel(m_devices); 0042 0043 deviceView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); 0044 deviceView->header()->setSectionResizeMode(0, QHeaderView::Stretch); 0045 0046 connect(kcfg_AutomountUnknownDevices, &QCheckBox::stateChanged, this, [this](int state) { 0047 m_devices->setAutomaticUnknown(state == Qt::Checked); 0048 }); 0049 0050 connect(deviceView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &DeviceAutomounterKCM::updateForgetDeviceButton); 0051 connect(forgetDevice, &QAbstractButton::clicked, this, &DeviceAutomounterKCM::forgetSelectedDevices); 0052 0053 connect(m_devices, &QAbstractItemModel::dataChanged, this, &DeviceAutomounterKCM::updateState); 0054 } 0055 0056 DeviceAutomounterKCM::~DeviceAutomounterKCM() 0057 { 0058 saveLayout(); 0059 } 0060 0061 void DeviceAutomounterKCM::updateState() 0062 { 0063 kcfg_AutomountUnknownDevices->setEnabled(m_settings->automountOnLogin() || m_settings->automountOnPlugin()); 0064 0065 unmanagedWidgetChangeState(m_unmanagedChanges || m_settings->usrIsSaveNeeded()); 0066 unmanagedWidgetDefaultState(m_settings->isDefaults()); 0067 } 0068 0069 void DeviceAutomounterKCM::updateForgetDeviceButton() 0070 { 0071 const auto selectedIndexes = deviceView->selectionModel()->selectedIndexes(); 0072 const bool isAnyDettached = std::any_of(selectedIndexes.cbegin(), selectedIndexes.cend(), [](const auto &idx) { 0073 return idx.data(DeviceModel::TypeRole) == DeviceModel::Detached; 0074 }); 0075 forgetDevice->setEnabled(isAnyDettached); 0076 } 0077 0078 void DeviceAutomounterKCM::forgetSelectedDevices() 0079 { 0080 QItemSelectionModel *selected = deviceView->selectionModel(); 0081 int offset = 0; 0082 while (!selected->selectedIndexes().isEmpty() && selected->selectedIndexes().size() > offset) { 0083 if (selected->selectedIndexes()[offset].data(DeviceModel::TypeRole) == DeviceModel::Attached) { 0084 offset++; 0085 } else { 0086 m_devices->forgetDevice(selected->selectedIndexes()[offset].data(DeviceModel::UdiRole).toString()); 0087 } 0088 } 0089 0090 m_unmanagedChanges = true; 0091 updateState(); 0092 } 0093 0094 void DeviceAutomounterKCM::load() 0095 { 0096 KCModule::load(); 0097 0098 m_devices->reload(); 0099 loadLayout(); 0100 0101 kcfg_AutomountUnknownDevices->setChecked(m_settings->automountUnknownDevices()); 0102 0103 m_unmanagedChanges = false; 0104 updateState(); 0105 } 0106 0107 void DeviceAutomounterKCM::save() 0108 { 0109 KCModule::save(); 0110 saveLayout(); 0111 0112 // Housekeeping before saving. 0113 // 1. Detect if any of the automount options is set to globally enable automounting 0114 // 2. Clean-up removed setting groups 0115 bool enabled = m_settings->automountOnLogin() || m_settings->automountOnPlugin(); 0116 QStringList validDevices; 0117 0118 for (const QModelIndex &idx : {m_devices->index(DeviceModel::RowAttached, 0), m_devices->index(DeviceModel::RowDetached, 0)}) { 0119 for (int j = 0; j < m_devices->rowCount(idx); ++j) { 0120 const QString udi = m_devices->index(j, 0, idx).data(DeviceModel::UdiRole).toString(); 0121 validDevices << udi; 0122 enabled |= m_settings->deviceSettings(udi)->mountOnLogin() | m_settings->deviceSettings(udi)->mountOnAttach(); 0123 } 0124 } 0125 0126 m_settings->setAutomountEnabled(enabled); 0127 0128 const auto knownDevices = m_settings->knownDevices(); 0129 for (const QString &possibleDevice : knownDevices) { 0130 if (!validDevices.contains(possibleDevice)) { 0131 m_settings->removeDeviceGroup(possibleDevice); 0132 } 0133 } 0134 0135 m_settings->save(); 0136 0137 // Now tell kded to automatically load the module if loaded 0138 QDBusConnection dbus = QDBusConnection::sessionBus(); 0139 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kded6"), 0140 QStringLiteral("/kded"), 0141 QStringLiteral("org.kde.kded6"), 0142 QStringLiteral("setModuleAutoloading")); 0143 msg.setArguments({QVariant(QStringLiteral("device_automounter")), QVariant(enabled)}); 0144 dbus.call(msg, QDBus::NoBlock); 0145 0146 // Load or unload right away 0147 msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kded6"), 0148 QStringLiteral("/kded"), 0149 QStringLiteral("org.kde.kded6"), 0150 enabled ? QStringLiteral("loadModule") : QStringLiteral("unloadModule")); 0151 msg.setArguments({QVariant(QStringLiteral("device_automounter"))}); 0152 dbus.call(msg, QDBus::NoBlock); 0153 } 0154 0155 void DeviceAutomounterKCM::defaults() 0156 { 0157 KCModule::defaults(); 0158 0159 m_settings->setDefaults(); 0160 m_devices->updateCheckedColumns(); 0161 } 0162 0163 void DeviceAutomounterKCM::saveLayout() 0164 { 0165 QList<int> widths; 0166 const int nbColumn = m_devices->columnCount(); 0167 widths.reserve(nbColumn); 0168 0169 for (int i = 0; i < nbColumn; ++i) { 0170 widths << deviceView->columnWidth(i); 0171 } 0172 0173 LayoutSettings::setHeaderWidths(widths); 0174 LayoutSettings::setAttachedExpanded(deviceView->isExpanded(m_devices->index(DeviceModel::RowAttached, 0))); 0175 LayoutSettings::setDetachedExpanded(deviceView->isExpanded(m_devices->index(DeviceModel::RowDetached, 0))); 0176 LayoutSettings::self()->save(); 0177 } 0178 0179 void DeviceAutomounterKCM::loadLayout() 0180 { 0181 LayoutSettings::self()->load(); 0182 // Reset it first, just in case there isn't any layout saved for a particular column. 0183 int nbColumn = m_devices->columnCount(); 0184 for (int i = 0; i < nbColumn; ++i) { 0185 deviceView->resizeColumnToContents(i); 0186 } 0187 0188 QList<int> widths = LayoutSettings::headerWidths(); 0189 nbColumn = m_devices->columnCount(); 0190 for (int i = 0; i < nbColumn && i < widths.size(); ++i) { 0191 deviceView->setColumnWidth(i, widths[i]); 0192 } 0193 0194 deviceView->setExpanded(m_devices->index(DeviceModel::RowAttached, 0), LayoutSettings::attachedExpanded()); 0195 deviceView->setExpanded(m_devices->index(DeviceModel::RowDetached, 0), LayoutSettings::detachedExpanded()); 0196 } 0197 0198 #include "DeviceAutomounterKCM.moc"