Commit 41b4b29d4aed16d44a8f9fc3097d5fac8dd449f9

  • avatar
  • swiesner <swiesner @283d02a7-25f6-0310…ecb5cbfe19da.>
  • Wed Aug 04 21:40:31 CEST 2010
Replaced HAL with libudev for mouse device monitoring

git-svn-id: svn+ssh://svn.kde.org/home/kde/trunk/playground/utils/synaptiks@1159226 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
  
2020include_directories(${X11_X11_INCLUDE_PATH})
2121include_directories(${X11_Xinput_INCLUDE_PATH})
2222
23include(CheckPrototypeExists)
24
25find_package(PkgConfig)
26if(PKG_CONFIG_FOUND)
27 # rely on pkg-config if possible
28 pkg_search_module(UDEV "libudev")
29else(PKG_CONFIG_FOUND)
30 # if pkg-config is not available, check if we can compile against libudev
31 # in standard include and library directories
32 check_prototype_exists(udev_new libudev.h UDEV_FOUND)
33 set(UDEV_LIBRARIES "udev")
34endif(PKG_CONFIG_FOUND)
35if(UDEV_FOUND)
36 include_directories(${UDEV_INCLUDE_DIRS})
37 link_directories(${UDEV_LIBRARY_DIRS})
38endif(UDEV_FOUND)
39
2340option(WITH_XINPUT2 "Search for XInput2" OFF)
2441
2542# determine availability of XInput device property API
26include(CheckPrototypeExists)
2743check_prototype_exists(XChangeDeviceProperty X11/extensions/XInput.h
2844 HAVE_DEVICE_PROPERTIES)
2945if(WITH_XINPUT2)
5555macro_log_feature(HAVE_DEVICE_PROPERTIES_V2 "Device properties 2"
5656 "XInput device properties 2.x" "http://www.x.org/")
5757macro_bool_to_01(HAVE_DEVICE_PROPERTIES_V2 HAVE_XINPUT2)
58# udev
59macro_log_feature(UDEV_FOUND "libudev" "UDev library"
60 "http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html"
61 TRUE)
5862
5963configure_file(
6064 "${CMAKE_CURRENT_SOURCE_DIR}/config-synaptiks.h.cmake"
  
1212kde4_add_plugin(kded_synaptiks ${kded_synaptiks_sources})
1313
1414target_link_libraries(kded_synaptiks
15 ${KDE4_KDEUI_LIBS} ${X11_X11_LIB} ${X11_Xinput_LIB})
15 ${KDE4_KDEUI_LIBS} ${X11_X11_LIB} ${X11_Xinput_LIB} ${UDEV_LIBRARIES})
1616
1717install(TARGETS kded_synaptiks DESTINATION ${PLUGIN_INSTALL_DIR})
1818install(FILES synaptiks.desktop DESTINATION ${SERVICES_INSTALL_DIR}/kded)
  
2727 * POSSIBILITY OF SUCH DAMAGE.
2828 */
2929
30#define QT_NO_CAST_TO_ASCII 1
3031#include "mousedevicesmonitor.h"
32#include "qudevpointer.h"
3133#include <KDebug>
32#include <QtDBus/QDBusInterface>
33#include <QtDBus/QDBusServiceWatcher>
34#include <QtDBus/QDBusReply>
3534#include <QtCore/QStringList>
36#include <QtCore/QPointer>
35#include <QtCore/QSocketNotifier>
3736
3837
3938using namespace synaptiks;
4039
4140
42static const char HAL_SERVICE[] = "org.freedesktop.Hal";
43static const char HAL_MANAGER_PATH[] = "/org/freedesktop/Hal/Manager";
44static const char HAL_MANAGER_IFACE[] = "org.freedesktop.Hal.Manager";
45static const char HAL_DEVICE_IFACE[] = "org.freedesktop.Hal.Device";
46
47
48#define DEVICE_INTERFACE(device, udi) \
49 QDBusInterface device(HAL_SERVICE, udi, HAL_DEVICE_IFACE, \
50 QDBusConnection::systemBus()); \
51
52
5341namespace synaptiks {
5442 class MouseDevicesMonitorPrivate {
5543 public:
4747
4848 virtual ~MouseDevicesMonitorPrivate() {};
4949
50 void _k_deviceAdded(const QString &udi);
51 void _k_deviceRemoved(const QString &udi);
52 void _k_halRegistered();
53 void _k_halUnregistered();
54 QStringList pluggedMouseDevices() const;
55 bool queryCapability(const QString &udi,
56 const QString &capability) const;
57 QString getProperty(const QString &udi,
58 const QString &property) const;
50 void _k_udevDataAvailable();
5951
60 QPointer<QDBusInterface> hal_manager;
61 QDBusServiceWatcher *hal_watcher;
52 QUDevDevicePtr findDeviceBySerial(const QByteArray &serial) const;
53
6254 QSet<QString> mouseDevices;
55 QUDevContextPtr context;
56 QUDevMonitorPtr monitor;
57 QSocketNotifier *monitorNotifier;
6358 MouseDevicesMonitor *q_ptr;
6459 };
6560}
6363MouseDevicesMonitorPrivate::MouseDevicesMonitorPrivate(
6464 MouseDevicesMonitor *qq): q_ptr(qq) {
6565 Q_Q(MouseDevicesMonitor);
66 this->hal_manager = new QDBusInterface(
67 HAL_SERVICE, HAL_MANAGER_PATH, HAL_MANAGER_IFACE, QDBusConnection::systemBus(), q);
68 q->connect(this->hal_manager, SIGNAL(DeviceAdded(const QString&)),
69 SLOT(_k_deviceAdded(const QString&)));
70 q->connect(this->hal_manager, SIGNAL(DeviceRemoved(const QString&)),
71 SLOT(_k_deviceRemoved(const QString&)));
72 // watch the HAL service for (un-)registration to re-initialize the
73 // connection to this service if required (e.g. HAL was restarted due to
74 // an update or HAL crashed or whatever)
75 this->hal_watcher = new QDBusServiceWatcher(q);
76 this->hal_watcher->addWatchedService(HAL_SERVICE);
77 q->connect(this->hal_watcher, SIGNAL(serviceRegistered(const QString&)),
78 SLOT(_k_halRegistered()));
79 q->connect(
80 this->hal_watcher, SIGNAL(serviceUnregistered(const QString&)),
81 SLOT(_k_halUnregistered()));
82 this->hal_watcher->setConnection(this->hal_manager->connection());
83 this->mouseDevices = QSet<QString>::fromList(
84 this->pluggedMouseDevices());
66 this->context = udev_new();
67 this->monitor = udev_monitor_new_from_netlink(this->context, "udev");
68 this->monitorNotifier = new QSocketNotifier(
69 udev_monitor_get_fd(this->monitor), QSocketNotifier::Read, q);
70 q->connect(this->monitorNotifier, SIGNAL(activated(int)),
71 SLOT(_k_udevDataAvailable()));
72 udev_monitor_filter_add_match_subsystem_devtype(
73 this->monitor, "input", 0);
74 udev_monitor_enable_receiving(this->monitor);
8575}
8676
87void MouseDevicesMonitorPrivate::_k_deviceAdded(const QString& udi) {
88 if (this->queryCapability(udi, "input.mouse")) {
89 Q_Q(MouseDevicesMonitor);
90 this->mouseDevices.insert(udi);
91 emit q->mousePlugged(udi);
92 }
77/**
78 * @return @c true, if @p device is a mouse (not a touchpad!), @c false
79 * otherwise
80 */
81inline bool isMouse(const QUDevDevicePtr &device) {
82 QByteArray sysName = udev_device_get_sysname(device);
83 // check, if the device really is a mouse
84 QByteArray isMouse = udev_device_get_property_value(
85 device, "ID_INPUT_MOUSE");
86 QByteArray isTouchpad = udev_device_get_property_value(
87 device, "ID_INPUT_TOUCHPAD");
88 return (isMouse.toInt() && (!isTouchpad.toInt())
89 && sysName.startsWith("mouse"));
9390}
9491
95void MouseDevicesMonitorPrivate::_k_deviceRemoved(const QString& udi) {
96 if (this->mouseDevices.contains(udi)) {
97 Q_Q(MouseDevicesMonitor);
98 this->mouseDevices.remove(udi);
99 emit q->mouseUnplugged(udi);
100 }
92inline QByteArray getSerial(const QUDevDevicePtr &device) {
93 return udev_device_get_property_value(device, "ID_SERIAL");
10194}
10295
103void MouseDevicesMonitorPrivate::_k_halRegistered() {
104 // HAL is available now, create the interface and "connect" all mouses
96void MouseDevicesMonitorPrivate::_k_udevDataAvailable() {
10597 Q_Q(MouseDevicesMonitor);
106 this->hal_manager = new QDBusInterface(
107 HAL_SERVICE, HAL_MANAGER_PATH, HAL_MANAGER_IFACE,
108 this->hal_watcher->connection(), q);
109 this->mouseDevices = QSet<QString>::fromList(
110 this->pluggedMouseDevices());
111 foreach (const QString &udi, this->mouseDevices) {
112 emit q->mousePlugged(udi);
98 kDebug() << "udev data available";
99 QUDevDevicePtr device = udev_monitor_receive_device(this->monitor);
100 if (!device)
101 return;
102 kDebug() << "udev device received";
103 if (isMouse(device)) {
104 QByteArray action = udev_device_get_action(device);
105 QByteArray serial = getSerial(device);
106 if (action == "add") {
107 kDebug() << "mouse added:" << serial;
108 emit q->mousePlugged(QString::fromAscii(serial));
109 } else if (action == "remove") {
110 kDebug() << "mouse removed:" << serial;
111 emit q->mouseUnplugged(QString::fromAscii(serial));
112 }
113113 }
114114}
115115
116void MouseDevicesMonitorPrivate::_k_halUnregistered() {
117 // HAL is gone, so we consider all mouses being disconnected now, just
118 // to be on the safe side, because we can't montor mouse devices
119 // anymore.
120 Q_Q(MouseDevicesMonitor);
121 foreach (const QString &udi, this->mouseDevices) {
122 emit q->mouseUnplugged(udi);
116QUDevDevicePtr MouseDevicesMonitorPrivate::findDeviceBySerial(
117 const QByteArray &serial) const {
118 kDebug() << "searching device for serial" << serial;
119 QUDevDevicePtr device;
120 QUDevEnumeratePtr enumerator = udev_enumerate_new(this->context);
121 Q_ASSERT(enumerator);
122 // filter for the given serial number
123 udev_enumerate_add_match_subsystem(enumerator, "input");
124 udev_enumerate_add_match_property(enumerator, "ID_SERIAL", serial);
125 udev_enumerate_scan_devices(enumerator);
126 // iterate over all matching devices
127 udev_list_entry *device_entries =
128 udev_enumerate_get_list_entry(enumerator);
129 udev_list_entry *current_entry = 0;
130 udev_list_entry_foreach(current_entry, device_entries) {
131 device = udev_device_new_from_syspath(
132 this->context, udev_list_entry_get_name(current_entry));
133 // we have a matching mouse device
134 if (device && isMouse(device)) {
135 kDebug() << "found device for serial:" << serial;
136 break;
137 }
123138 }
124 this->mouseDevices.clear();
125 // delete the now invalid interface
126 delete this->hal_manager;
139 return device;
127140}
128141
129QStringList MouseDevicesMonitorPrivate::pluggedMouseDevices() const {
130 kDebug() << "enumerating plugged devices";
131 if (!this->hal_manager)
132 return QStringList();
133 QDBusReply<QStringList> devices = this->hal_manager->call(
134 "FindDeviceByCapability", "input.mouse");
135 if (!devices.isValid()) {
136 kError() << "dbus error:" << devices.error().name()
137 << ":" << devices.error().message();
138 return QStringList();
139 } else
140 return devices.value();
141}
142
143bool MouseDevicesMonitorPrivate::queryCapability(
144 const QString &udi, const QString &capability) const {
145 DEVICE_INTERFACE(device, udi);
146 QDBusReply<bool> hasCapability = device.call("QueryCapability",
147 capability);
148 if (!hasCapability.isValid()) {
149 kError() << "dbus error:" << hasCapability.error().name()
150 << ":" << hasCapability.error().message();
151 return false;
152 } else {
153 return hasCapability.value();
154 }
155}
156
157QString MouseDevicesMonitorPrivate::getProperty(
158 const QString &udi, const QString &property) const {
159 DEVICE_INTERFACE(device, udi);
160 QDBusReply<QString> value = device.call("GetProperty", property);
161 if (!value.isValid()) {
162 kError() << "dbus error:" << value.error().name()
163 << ":" << value.error().message();
164 return QString();
165 } else {
166 return value.value();
167 }
168}
169
170142MouseDevicesMonitor::MouseDevicesMonitor(QObject *parent):
171143 QObject(parent), d_ptr(new MouseDevicesMonitorPrivate(this)) {}
172144
148148
149149QStringList MouseDevicesMonitor::pluggedMouseDevices() const {
150150 Q_D(const MouseDevicesMonitor);
151 return d->pluggedMouseDevices();
151 QStringList devices;
152 kDebug() << "enumerating plugged devices";
153 QUDevEnumeratePtr enumerator = udev_enumerate_new(d->context);
154 Q_ASSERT(enumerator);
155 // filter for mouse devices
156 udev_enumerate_add_match_subsystem(enumerator, "input");
157 udev_enumerate_add_match_property(enumerator, "ID_INPUT_MOUSE", "1");
158 udev_enumerate_scan_devices(enumerator);
159 udev_list_entry *device_entries =
160 udev_enumerate_get_list_entry(enumerator);
161 // iterate over all mouse devices
162 udev_list_entry *current_entry = 0;
163 udev_list_entry_foreach(current_entry, device_entries) {
164 QUDevDevicePtr device = udev_device_new_from_syspath(
165 d->context, udev_list_entry_get_name(current_entry));
166 // a true mouse device
167 if (device && isMouse(device)) {
168 QByteArray serial = getSerial(device);
169 kDebug() << "found device with serial" << serial;
170 devices << QString::fromAscii(serial);
171 }
172 }
173 return devices;
152174}
153175
154176QString MouseDevicesMonitor::productName(const QString &id) const {
155177 Q_D(const MouseDevicesMonitor);
156 return d->getProperty(id, "info.product");
157}
158
159bool MouseDevicesMonitor::isTouchpad(const QString &id) const {
160 Q_D(const MouseDevicesMonitor);
161 return d->queryCapability(id, "input.touchpad");
178 kDebug() << "querying product name for serial" << id;
179 QString name;
180 QUDevDevicePtr device = d->findDeviceBySerial(id.toAscii());
181 if (device) {
182 // no need for a guarded pointer here, the parent device is freed
183 // together with the child
184 udev_device *parent = udev_device_get_parent(device);
185 if (parent) {
186 kDebug() << "got" << name << "for serial" << id;
187 name = QString::fromAscii(
188 udev_device_get_property_value(parent, "NAME"));
189 }
190 }
191 return name;
162192}
163193
164194#include "moc_mousedevicesmonitor.cpp"
  
3838 */
3939
4040#include <QtCore/QObject>
41#include <QtCore/QString>
4142
4243namespace synaptiks {
4344
116116 */
117117 Q_SCRIPTABLE QString productName(const QString &id) const;
118118
119 /**
120 * @brief Is the given device a touchpad?
121 *
122 * @warning
123 *
124 * Only use this method with @em plugged devices. This class cannot
125 * obtain information about devices, which are not currently
126 * plugged.
127 *
128 * @param id the device id
129 * @return @c true, if the given device is a touchpad, @c false
130 * otherwise
131 */
132 Q_SCRIPTABLE bool isTouchpad(const QString &id) const;
133
134119 Q_SIGNALS:
135120 /**
136121 * @brief A mouse device was plugged.
141141 Q_DECLARE_PRIVATE(MouseDevicesMonitor)
142142 Q_DISABLE_COPY(MouseDevicesMonitor)
143143
144 Q_PRIVATE_SLOT(d_func(), void _k_deviceAdded(const QString&))
145 Q_PRIVATE_SLOT(d_func(), void _k_deviceRemoved(const QString&))
146 Q_PRIVATE_SLOT(d_func(), void _k_halRegistered())
147 Q_PRIVATE_SLOT(d_func(), void _k_halUnregistered())
144 Q_PRIVATE_SLOT(d_func(), void _k_udevDataAvailable())
148145
149146 MouseDevicesMonitorPrivate * const d_ptr;
150147 };
  
1414 <arg type="s" direction="out"/>
1515 <arg name="id" type="s" direction="in"/>
1616 </method>
17 <method name="isTouchpad">
18 <arg type="b" direction="out"/>
19 <arg name="id" type="s" direction="in"/>
20 </method>
2117 </interface>
2218</node>
  
1/*
2 * synaptiks -- a touchpad control tool
3 *
4 *
5 * Copyright (C) 2010 Sebastian Wiesner <lunaryorn@googlemail.com>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#ifndef QUDEVPOINTER_H
31#define QUDEVPOINTER_H
32
33extern "C" {
34#include <libudev.h>
35}
36
37/**
38 * @brief A managed pointer a-top of libudev
39 *
40 * @param T the pointer type
41 * @param Ref a function which increases the reference count on T*
42 * @param Unref a function which decreases the reference count on T*
43 */
44template<class T, T* (*Ref)(T*), void (*Unref)(T*)> class QUDevPointer {
45public:
46 /**
47 * @brief Default constructor
48 */
49 QUDevPointer(): m_ptr(0) {
50 }
51
52 /**
53 * @brief Copy constructor.
54 *
55 * Copy internal pointer of @p other to this object and increase ref
56 * count.
57 */
58 QUDevPointer(const QUDevPointer<T, Ref, Unref> &other) {
59 this->m_ptr = other.m_ptr;
60 Ref(this->m_ptr);
61 }
62
63 /**
64 * @brief Construct a managed udev pointer from a raw pointer.
65 *
66 * The reference count of @p ptr is @em not increased.
67 *
68 * @param ptr the raw pointer
69 */
70 QUDevPointer(T *ptr) {
71 this->m_ptr = ptr;
72 }
73
74 /**
75 * @brief Destroy this pointer and decrease reference count on internal
76 * pointer.
77 */
78 ~QUDevPointer() {
79 Unref(this->m_ptr);
80 }
81
82 /**
83 * @brief Assignment operator.
84 *
85 * Decrease reference count on the current internal pointer of this
86 * object (if it has one), copy the internal pointer of @p other into
87 * this object, and increase the reference count on the new internal
88 * pointer.
89 *
90 * @param other managed pointer to assign to this pointer
91 */
92 QUDevPointer &operator=(const QUDevPointer<T, Ref, Unref> &other) {
93 if (this->m_ptr)
94 Unref(this->m_ptr);
95 this->m_ptr = other->m_ptr;
96 Ref(this->m_ptr);
97 return *this;
98 }
99
100 /**
101 * Decrease reference count on the current internal pointer of this
102 * object (if it has one) and set internal pointer to @p ptr.
103 *
104 * @param ptr the raw pointer to assign to this pointer
105 */
106 QUDevPointer &operator=(T *ptr) {
107 if (this->m_ptr)
108 Unref(this->m_ptr);
109 this->m_ptr = ptr;
110 return *this;
111 }
112
113 /**
114 * @brief Forcibly increase the reference count on the underlying
115 * pointer.
116 */
117 void ref() {
118 Ref(this->m_ptr);
119 }
120
121 /**
122 * @brief Conversion operator to T*
123 *
124 * A managed udev pointer implicitly converts to T*.
125 *
126 * @return the underlying raw pointer
127 */
128 operator T*() const {
129 return this->m_ptr;
130 }
131
132 /**
133 * @brief Get the underyling raw pointer.
134 *
135 * @return the underlying raw pointer.
136 */
137 T *data() const {
138 return this->m_ptr;
139 }
140
141 /**
142 * @brief Implicit conversion to bool.
143 *
144 * @return @c true, if the internal pointer is not 0, @c false
145 * otherwise.
146 */
147 operator bool() const {
148 return this->m_ptr;
149 }
150
151 /**
152 * @brief Test, if this pointer is 0.
153 *
154 * @return @c true, if the internal pointer is not 0, @false otherwise.
155 */
156 bool isNull() const {
157 return !this->m_ptr;
158 }
159
160private:
161 /** internal pointer */
162 T *m_ptr;
163};
164
165/** Managed pointer to @c udev_context* */
166typedef QUDevPointer<struct udev, udev_ref, udev_unref> QUDevContextPtr;
167/** Managed pointer to @c udev_enumerate* */
168typedef QUDevPointer<struct udev_enumerate, udev_enumerate_ref,
169 udev_enumerate_unref> QUDevEnumeratePtr;
170/** Managed pointer to @c udev_monitor* */
171typedef QUDevPointer<struct udev_monitor, udev_monitor_ref,
172 udev_monitor_unref> QUDevMonitorPtr;
173/** Managed pointer to @c udev_device* */
174typedef QUDevPointer<struct udev_device, udev_device_ref,
175 udev_device_unref> QUDevDevicePtr;
176
177#endif /* QUDEVPOINTER_H */
  
6464 }
6565
6666 bool shallIgnoreMouse(const QString &mouse) {
67 return (this->mouseDevices->isTouchpad(mouse) ||
68 this->ignoredMouseDevices.contains(mouse) ||
67 return (this->ignoredMouseDevices.contains(mouse) ||
6968 // don't register the same mouse twice
7069 this->pluggedMouses.contains(mouse));
7170 }
  
5252
5353 void resetDeviceIndex();
5454
55 void _k_mousePlugged(const QString &udi);
56 void _k_mouseUnplugged(const QString &udi);
55 void _k_mousePlugged(const QString &id);
56 void _k_mouseUnplugged(const QString &id);
5757
58 /**
59 * Check, whether udi may be added to the device index.
60 *
61 * A device may be added, if ignoreTouchpads is @c false or the
62 * device is not a touchpad.
63 *
64 * @return @c true, if the device may be added, @c false otherwise
65 */
66 bool mayAddDevice(const QString &udi) {
67 if (this->touchpadsIgnored) {
68 QDBusReply<bool> isTouchpad =
69 this->devices->call("isTouchpad", udi);
70 return !(isTouchpad.isValid() && isTouchpad.value());
71 }
72 return true;
73 };
74
7558 MouseDevicesModel *q_ptr;
7659 QDBusInterface *devices;
7760 QStringList deviceIndex;
7979 }
8080}
8181
82void MouseDevicesModelPrivate::_k_mousePlugged(const QString &udi) {
82void MouseDevicesModelPrivate::_k_mousePlugged(const QString &id) {
8383 Q_Q(MouseDevicesModel);
84 if (this->mayAddDevice(udi)) {
85 int position = q->rowCount();
86 q->beginInsertRows(QModelIndex(), position, position);
87 this->deviceIndex.append(udi);
88 q->endInsertRows();
89 }
84 int position = q->rowCount();
85 q->beginInsertRows(QModelIndex(), position, position);
86 this->deviceIndex.append(id);
87 q->endInsertRows();
9088}
9189
92void MouseDevicesModelPrivate::_k_mouseUnplugged(const QString &udi) {
90void MouseDevicesModelPrivate::_k_mouseUnplugged(const QString &id) {
9391 Q_Q(MouseDevicesModel);
94 int position = this->deviceIndex.indexOf(udi);
92 int position = this->deviceIndex.indexOf(id);
9593 if (position >= 0) {
9694 q->beginRemoveRows(QModelIndex(), position, position);
9795 this->deviceIndex.removeAt(position);
103103 this->devices->call("pluggedMouseDevices");
104104 if (!pluggedMouses.isValid())
105105 return;
106 foreach (const QString &udi, pluggedMouses.value()) {
107 if (this->mayAddDevice(udi)) {
108 this->deviceIndex.append(udi);
109 }
106 foreach (const QString &id, pluggedMouses.value()) {
107 this->deviceIndex.append(id);
110108 }
111109}
112110
131131QVariant MouseDevicesModel::data(const QModelIndex &index, int role) const {
132132 Q_D(const MouseDevicesModel);
133133 if (index.isValid()) {
134 QString udi = d->deviceIndex.at(index.row());
134 QString id = d->deviceIndex.at(index.row());
135135 QDBusReply<QString> productName =
136 d->devices->call("productName", udi);
136 d->devices->call("productName", id);
137137 switch (role) {
138138 case Qt::DisplayRole:
139139 if (productName.isValid())
141141 else
142142 return QString();
143143 case Qt::ToolTipRole:
144 return udi;
144 return id;
145145 case Qt::CheckStateRole:
146 if (d->checkedDevices.contains(udi)) {
146 if (d->checkedDevices.contains(id)) {
147147 return Qt::Checked;
148148 } else {
149149 return Qt::Unchecked;
161161 Q_D(MouseDevicesModel);
162162 bool changed = false;
163163 if (index.isValid() && role == Qt::CheckStateRole) {
164 QString udi = d->deviceIndex.at(index.row());
164 QString id = d->deviceIndex.at(index.row());
165165 int state = value.toInt();
166166 if (state == Qt::Checked) {
167 kDebug() << "checking device" << udi;
168 d->checkedDevices.insert(udi);
167 kDebug() << "checking device" << id;
168 d->checkedDevices.insert(id);
169169 changed = true;
170170 } else if (state == Qt::Unchecked) {
171 kDebug() << "unchecking device" << udi;
172 d->checkedDevices.remove(udi);
171 kDebug() << "unchecking device" << id;
172 d->checkedDevices.remove(id);
173173 changed = true;
174174 }
175175 }
178178 emit this->checkedDevicesChanged(this->checkedDevices());
179179 }
180180 return changed;
181}
182
183bool MouseDevicesModel::touchpadsIgnored() const {
184 Q_D(const MouseDevicesModel);
185 return d->touchpadsIgnored;
186}
187
188void MouseDevicesModel::setTouchpadsIgnored(bool ignore) {
189 Q_D(MouseDevicesModel);
190 if (this->touchpadsIgnored() != ignore) {
191 d->touchpadsIgnored = ignore;
192 d->resetDeviceIndex();
193 }
194181}
195182
196183QStringList MouseDevicesModel::checkedDevices() const {
  
22 * synaptiks -- a touchpad control tool
33 *
44 *
5 * Copyright (C) 2009 Sebastian Wiesner <lunaryorn@googlemail.com>
5 * Copyright (C) 2009, 2010 Sebastian Wiesner <lunaryorn@googlemail.com>
66 * All rights reserved.
77 *
88 * Redistribution and use in source and binary forms, with or without
4747 */
4848 class MouseDevicesModel: public QAbstractListModel {
4949 Q_OBJECT
50 /**
51 * @brief Whether touchpads are ignored or not.
52 *
53 * @sa setTouchpadsIgnored(bool)
54 * @sa touchpadsIgnored()
55 */
56 Q_PROPERTY(bool touchpadsIgnored
57 READ touchpadsIgnored
58 WRITE setTouchpadsIgnored)
5950
6051 /**
6152 * @brief A list of devices checked by the user.
114114 */
115115 bool setData(const QModelIndex &index, const QVariant &value,
116116 int role);
117
118 /**
119 * Are touchpads ignored by this model?
120 *
121 * @return @c true, if this model ignores touchpads, @c false
122 * otherwise
123 */
124 bool touchpadsIgnored() const;
125
126 /**
127 * Ignore touchpads. Generally touchpads are mouses too and
128 * displayed by this model. However, there are cases, in which
129 * touchpads should not be considered as mouse devices. For such
130 * cases, you can have the model ignore touchpads with this
131 * function.
132 *
133 * Setting this will reset the model.
134 *
135 * By default, mouse devices are not ignored.
136 *
137 * @param ignore if @c true, ignore touchpads
138 */
139 void setTouchpadsIgnored(bool ignore);
140117
141118 /**
142119 * Query the checked devices.
  
6161 checkedDevices();
6262}
6363
64void MouseDevicesView::setTouchpadsIgnored(bool ignored) {
65 qobject_cast<MouseDevicesModel *>(this->model())->
66 setTouchpadsIgnored(ignored);
67}
68
69bool MouseDevicesView::touchpadsIgnored() const {
70 return qobject_cast<MouseDevicesModel *>(this->model())->
71 touchpadsIgnored();
72}
73
74
7564#include "moc_mousedevicesview.cpp"
  
8181 */
8282 QStringList checkedDevices();
8383
84 /**
85 * @brief Ignore touchpads.
86 *
87 * @param ignored if @c true, touchpads are ignored
88 */
89 void setTouchpadsIgnored(bool ignored);
90
91 /**
92 * @brief Are touchpads ignored?
93 *
94 * @return @c true, if touchpads are ignored, @c false otherwise
95 */
96 bool touchpadsIgnored() const;
97
9884 Q_SIGNALS:
9985 /**
10086 * @brief Signal a change of checked devices.
  
119119 QWidget(parent) {
120120 Ui::AutoTouchpadControlPage ui;
121121 ui.setupUi(this);
122 ui.kcfg_IgnoredMouseDevices->setTouchpadsIgnored(true);
123122}
124123
125124GeneralPage::GeneralPage(QWidget *parent): QWidget(parent) {