Warning, file /plasma/plasma-desktop/solid-device-automounter/kcm/DeviceAutomounterKCM.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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(QWidget *parent, const QVariantList &args)
0033     : KCModule(parent, args) // DeviceAutomounterKCMFactory::componentData(), parent)
0034     , m_settings(new AutomounterSettings(this))
0035     , m_devices(new DeviceModel(m_settings, this))
0036 {
0037     KAboutData *about = new KAboutData(QStringLiteral("kcm_device_automounter"),
0038                                        i18n("Device Automounter"),
0039                                        QStringLiteral("2.0"),
0040                                        QString(),
0041                                        KAboutLicense::GPL_V2,
0042                                        i18n("(c) 2009 Trever Fischer, (c) 2015 Kai Uwe Broulik"));
0043     about->addAuthor(i18n("Trever Fischer"), i18n("Original Author"));
0044     about->addAuthor(i18n("Kai Uwe Broulik"), i18n("Plasma 5 Port"), QStringLiteral("kde@privat.broulik.de"));
0045 
0046     setAboutData(about);
0047     setupUi(this);
0048 
0049     addConfig(m_settings, this);
0050 
0051     deviceView->setModel(m_devices);
0052 
0053     deviceView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
0054     deviceView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
0055 
0056     connect(kcfg_AutomountUnknownDevices, &QCheckBox::stateChanged, this, [this](int state) {
0057         m_devices->setAutomaticUnknown(state == Qt::Checked);
0058     });
0059 
0060     connect(deviceView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &DeviceAutomounterKCM::updateForgetDeviceButton);
0061     connect(forgetDevice, &QAbstractButton::clicked, this, &DeviceAutomounterKCM::forgetSelectedDevices);
0062 
0063     connect(m_devices, &QAbstractItemModel::dataChanged, this, &DeviceAutomounterKCM::updateState);
0064 }
0065 
0066 DeviceAutomounterKCM::~DeviceAutomounterKCM()
0067 {
0068     saveLayout();
0069 }
0070 
0071 void DeviceAutomounterKCM::updateState()
0072 {
0073     kcfg_AutomountUnknownDevices->setEnabled(m_settings->automountOnLogin() || m_settings->automountOnPlugin());
0074 
0075     unmanagedWidgetChangeState(m_unmanagedChanges || m_settings->usrIsSaveNeeded());
0076     unmanagedWidgetDefaultState(m_settings->isDefaults());
0077 }
0078 
0079 void DeviceAutomounterKCM::updateForgetDeviceButton()
0080 {
0081     const auto selectedIndexes = deviceView->selectionModel()->selectedIndexes();
0082     const bool isAnyDettached = std::any_of(selectedIndexes.cbegin(), selectedIndexes.cend(), [](const auto &idx) {
0083         return idx.data(DeviceModel::TypeRole) == DeviceModel::Detached;
0084     });
0085     forgetDevice->setEnabled(isAnyDettached);
0086 }
0087 
0088 void DeviceAutomounterKCM::forgetSelectedDevices()
0089 {
0090     QItemSelectionModel *selected = deviceView->selectionModel();
0091     int offset = 0;
0092     while (!selected->selectedIndexes().isEmpty() && selected->selectedIndexes().size() > offset) {
0093         if (selected->selectedIndexes()[offset].data(DeviceModel::TypeRole) == DeviceModel::Attached) {
0094             offset++;
0095         } else {
0096             m_devices->forgetDevice(selected->selectedIndexes()[offset].data(DeviceModel::UdiRole).toString());
0097         }
0098     }
0099 
0100     m_unmanagedChanges = true;
0101     updateState();
0102 }
0103 
0104 void DeviceAutomounterKCM::load()
0105 {
0106     KCModule::load();
0107 
0108     m_devices->reload();
0109     loadLayout();
0110 
0111     kcfg_AutomountUnknownDevices->setChecked(m_settings->automountUnknownDevices());
0112 
0113     m_unmanagedChanges = false;
0114     updateState();
0115 }
0116 
0117 void DeviceAutomounterKCM::save()
0118 {
0119     KCModule::save();
0120     saveLayout();
0121 
0122     // Housekeeping before saving.
0123     // 1. Detect if any of the automount options is set to globally enable automounting
0124     // 2. Clean-up removed setting groups
0125     bool enabled = m_settings->automountOnLogin() || m_settings->automountOnPlugin();
0126     QStringList validDevices;
0127 
0128     for (const QModelIndex &idx : {m_devices->index(DeviceModel::RowAttached, 0), m_devices->index(DeviceModel::RowDetached, 0)}) {
0129         for (int j = 0; j < m_devices->rowCount(idx); ++j) {
0130             const QString udi = m_devices->index(j, 0, idx).data(DeviceModel::UdiRole).toString();
0131             validDevices << udi;
0132             enabled |= m_settings->deviceSettings(udi)->mountOnLogin() | m_settings->deviceSettings(udi)->mountOnAttach();
0133         }
0134     }
0135 
0136     m_settings->setAutomountEnabled(enabled);
0137 
0138     const auto knownDevices = m_settings->knownDevices();
0139     for (const QString &possibleDevice : knownDevices) {
0140         if (!validDevices.contains(possibleDevice)) {
0141             m_settings->removeDeviceGroup(possibleDevice);
0142         }
0143     }
0144 
0145     m_settings->save();
0146 
0147     // Now tell kded to automatically load the module if loaded
0148     QDBusConnection dbus = QDBusConnection::sessionBus();
0149     QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kded5"),
0150                                                       QStringLiteral("/kded"),
0151                                                       QStringLiteral("org.kde.kded5"),
0152                                                       QStringLiteral("setModuleAutoloading"));
0153     msg.setArguments({QVariant(QStringLiteral("device_automounter")), QVariant(enabled)});
0154     dbus.call(msg, QDBus::NoBlock);
0155 
0156     // Load or unload right away
0157     msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kded5"),
0158                                          QStringLiteral("/kded"),
0159                                          QStringLiteral("org.kde.kded5"),
0160                                          enabled ? QStringLiteral("loadModule") : QStringLiteral("unloadModule"));
0161     msg.setArguments({QVariant(QStringLiteral("device_automounter"))});
0162     dbus.call(msg, QDBus::NoBlock);
0163 }
0164 
0165 void DeviceAutomounterKCM::defaults()
0166 {
0167     KCModule::defaults();
0168 
0169     m_settings->setDefaults();
0170     m_devices->updateCheckedColumns();
0171 }
0172 
0173 void DeviceAutomounterKCM::saveLayout()
0174 {
0175     QList<int> widths;
0176     const int nbColumn = m_devices->columnCount();
0177     widths.reserve(nbColumn);
0178 
0179     for (int i = 0; i < nbColumn; ++i) {
0180         widths << deviceView->columnWidth(i);
0181     }
0182 
0183     LayoutSettings::setHeaderWidths(widths);
0184     LayoutSettings::setAttachedExpanded(deviceView->isExpanded(m_devices->index(DeviceModel::RowAttached, 0)));
0185     LayoutSettings::setDetachedExpanded(deviceView->isExpanded(m_devices->index(DeviceModel::RowDetached, 0)));
0186     LayoutSettings::self()->save();
0187 }
0188 
0189 void DeviceAutomounterKCM::loadLayout()
0190 {
0191     LayoutSettings::self()->load();
0192     // Reset it first, just in case there isn't any layout saved for a particular column.
0193     int nbColumn = m_devices->columnCount();
0194     for (int i = 0; i < nbColumn; ++i) {
0195         deviceView->resizeColumnToContents(i);
0196     }
0197 
0198     QList<int> widths = LayoutSettings::headerWidths();
0199     nbColumn = m_devices->columnCount();
0200     for (int i = 0; i < nbColumn && i < widths.size(); ++i) {
0201         deviceView->setColumnWidth(i, widths[i]);
0202     }
0203 
0204     deviceView->setExpanded(m_devices->index(DeviceModel::RowAttached, 0), LayoutSettings::attachedExpanded());
0205     deviceView->setExpanded(m_devices->index(DeviceModel::RowDetached, 0), LayoutSettings::detachedExpanded());
0206 }
0207 
0208 #include "DeviceAutomounterKCM.moc"