<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.linuxformat.ru/wiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF112%3AKDE4</id>
		<title>LXF112:KDE4 - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF112%3AKDE4"/>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF112:KDE4&amp;action=history"/>
		<updated>2026-05-13T13:06:59Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.19.20+dfsg-0+deb7u3</generator>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/index.php?title=LXF112:KDE4&amp;diff=8831&amp;oldid=prev</id>
		<title>Yaleks в 15:31, 4 октября 2009</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF112:KDE4&amp;diff=8831&amp;oldid=prev"/>
				<updated>2009-10-04T15:31:52Z</updated>
		
		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;http://wiki.linuxformat.ru/wiki/index.php?title=LXF112:KDE4&amp;amp;diff=8831&amp;amp;oldid=8830&quot;&gt;Внесённые изменения&lt;/a&gt;</summary>
		<author><name>Yaleks</name></author>	</entry>

	<entry>
		<id>http://wiki.linuxformat.ru/wiki/index.php?title=LXF112:KDE4&amp;diff=8830&amp;oldid=prev</id>
		<title>Yaleks: Новая: {{Цикл/KDE4}} == Солидная аппаратура == : ''ЧАСТЬ 5 Plasma, о которой мы много говорили на прошлых уроках – самая ...</title>
		<link rel="alternate" type="text/html" href="http://wiki.linuxformat.ru/wiki/index.php?title=LXF112:KDE4&amp;diff=8830&amp;oldid=prev"/>
				<updated>2009-10-04T13:33:14Z</updated>
		
		<summary type="html">&lt;p&gt;Новая: {{Цикл/KDE4}} == Солидная аппаратура == : &amp;#039;&amp;#039;ЧАСТЬ 5 Plasma, о которой мы много говорили на прошлых уроках – самая ...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Цикл/KDE4}}&lt;br /&gt;
== Солидная аппаратура ==&lt;br /&gt;
: ''ЧАСТЬ 5 Plasma, о которой мы много говорили на прошлых уроках – самая яркая, но далеко не единственная подсистема KDE4. В качестве финального аккорда '''Андрей Боровский''' припас для вас слой аппаратной абстракции под названием Solid.''&lt;br /&gt;
&lt;br /&gt;
Не так давно один известный в Рунете писатель задал сооб-&lt;br /&gt;
ществу программистов Linux вопрос: почему новые версии&lt;br /&gt;
KDE все более и более громоздки и прожорливы? Ведь&lt;br /&gt;
улучшение программы предполагает, в том числе, оптимизацию ее&lt;br /&gt;
кода... Можно, конечно, ответить – мол, новые версии оболочки&lt;br /&gt;
удовлетворяют растущим потребностям пользователей. Что, я пола-&lt;br /&gt;
гаю, будет лукавством: не так уж сильно эти потребности и выросли.&lt;br /&gt;
Вспомните, когда в последний раз менялся интерфейс самой попу-&lt;br /&gt;
лярной текстовой оболочки – Midnight Commander? Следует при-&lt;br /&gt;
знать, что в стремлении к свободному творчеству, которое и при-&lt;br /&gt;
влекает многих программистов в мир открытого ПО, разработчики&lt;br /&gt;
будут охотнее добавлять новые функции, нежели оптимизировать&lt;br /&gt;
старые. Вот почему KDE постоянно растет и вширь, и вглубь, и, в&lt;br /&gt;
частности, обзавелся системой управления устройствами Solid.&lt;br /&gt;
Зачем нужен Solid? Разумеется, его смысл и польза заключаются&lt;br /&gt;
вовсе не в том, чтобы удовлетворять амбиции KDE-программистов.&lt;br /&gt;
Как вы, конечно, знаете, KDE портируется на множество ОС, в том&lt;br /&gt;
числе Windows и Mac OS X, и у каждой из них есть собственные&lt;br /&gt;
средства управления оборудованием. Solid представляет собой&lt;br /&gt;
универсальный способ взаимодействия с устройствами всюду, где&lt;br /&gt;
работает KDE. В идеале, система Solid должна сократить количе-&lt;br /&gt;
ство непереносимого кода в вашем приложении (хотя свести его к&lt;br /&gt;
нулю все равно не удастся). В этом и заключается ответ на вопрос&lt;br /&gt;
о том, не лучше ли использовать HAL (на котором основана система&lt;br /&gt;
Solid) напрямую. Linux HAL поддерживается не на всех платформах,&lt;br /&gt;
которые намерен завоевать KDE. Кроме того, Linux HAL базируется&lt;br /&gt;
на Dbus, и эффективная работа с ним предполагает хорошее зна-&lt;br /&gt;
ние этой своеобразной системы. В процессе же общения с Solid&lt;br /&gt;
мы находимся в знакомой среде с сигналами, слотами и объектной&lt;br /&gt;
моделью Qt/KDE.&lt;br /&gt;
Исследуем дерево устройств&lt;br /&gt;
Центральным классом Solid является Solid::Device (все классы&lt;br /&gt;
Solid объявлены в пространстве имен Solid), который представляет&lt;br /&gt;
устройство. Дать четкое определение того, что является устрой-&lt;br /&gt;
ством с точки зрения Solid, не так-то просто. Это и процессор, и&lt;br /&gt;
его загружаемый микрокод, и видеокамера, и ее аудиоподсисте-&lt;br /&gt;
ма, оптический привод и диск в нем, винчестер и каждый его раз-&lt;br /&gt;
дел... Если такая модель кажется вам запутанной, вспомните, что&lt;br /&gt;
в других системах дело обстоит не лучше (в Диспетчер оборудо-&lt;br /&gt;
вания Windows давно заглядывали?). Устройства Solid образуют&lt;br /&gt;
иерархию, корнем которой является, конечно, Computer. Чтобы&lt;br /&gt;
еще больше вас запутать – каждое устройство предоставляет один&lt;br /&gt;
или несколько интерфейсов, представляемых потомками класса&lt;br /&gt;
Solid::DeviceInterface.&lt;br /&gt;
Пока вы еще не успели разочароваться в Solid, поспешим уточ-&lt;br /&gt;
нить, что может и чего не может эта система. Solid позволяет полу-&lt;br /&gt;
чать различные сведения об устройствах, в том числе отслеживать&lt;br /&gt;
их состояние в режиме реального времени. При этом Solid не пре-&lt;br /&gt;
доставляет собственных средств для обмена данными с устрой-&lt;br /&gt;
ствами. С помощью Solid вы можете получить имя файла, соответ-&lt;br /&gt;
ствующего устройству, его идентификатор или другую информа-&lt;br /&gt;
цию, необходимую для того, чтобы наладить обмен информацией,&lt;br /&gt;
но его придется выполнять с помощью интерфейса, предостав-&lt;br /&gt;
ляемого операционной системой. Например, все известные Solid&lt;br /&gt;
устройства, способные записывать и воспроизводить аудиоданные,&lt;br /&gt;
предоставляют интерфейс Solid::AudioInterface. У него есть метод&lt;br /&gt;
driverHandle(), который возвращает значение типа QVariant. Для&lt;br /&gt;
устройств, которые обслуживают драйверы ALSA, фактическим зна-&lt;br /&gt;
чением driverHandle() будет запись, содержащая имя звуковой кар-&lt;br /&gt;
ты (в системе ALSA) и номера первичного и вторичного устройств.&lt;br /&gt;
Если устройство работает под управлением драйвера OSS, метод&lt;br /&gt;
driverHandle() вернет строку с именем файла устройства.&lt;br /&gt;
Практическое знакомство с Solid мы начнем с программы обзо-&lt;br /&gt;
ра всех устройств, присутствующих в системе. Приложение devtree,&lt;br /&gt;
чьи исходные тексты вы найдете на диске, покажет вам полный спи-&lt;br /&gt;
сок устройств с учетом их иерархии (рис. 1).&lt;br /&gt;
&lt;br /&gt;
Доступ к полному списку устройств, поддерживаемых Solid, можно&lt;br /&gt;
получить с помощью статического метода Solid::Device::allDevices().&lt;br /&gt;
Он возвращает нам объект типа QList&amp;lt;Solid::Device&amp;gt;. Простая&lt;br /&gt;
конструкция&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp-qt&amp;quot;&amp;gt;foreach (const Solid::Device &amp;amp;device, Solid::Device::allDevices()) {&lt;br /&gt;
...&lt;br /&gt;
}&amp;lt;/source&amp;gt;&lt;br /&gt;
позволит перебрать все элементы данного списка (роль итератора играет переменная device). Однако последовательный перебор&lt;br /&gt;
перечня устройств не так уж и интересен. Дело в том, что расположе-&lt;br /&gt;
ние устройств в списке Solid::Device::allDevices() не учитывает иерар-&lt;br /&gt;
хических отношений между ними. В программе devtree мы использу-&lt;br /&gt;
ем рекурсивный метод заполнения виджета QTreeWidget элементами&lt;br /&gt;
списка (он не самый эффективный, но самый простой – альтернативу&lt;br /&gt;
рассмотрим в конце статьи):&lt;br /&gt;
void devtreeView::enumDevices()&lt;br /&gt;
{&lt;br /&gt;
ui_devtreeview_base.treeWidget-&amp;gt;setColumnCount(3);&lt;br /&gt;
QStringList hsl;&lt;br /&gt;
hsl &amp;lt;&amp;lt; &amp;quot;UDI&amp;quot; &amp;lt;&amp;lt; &amp;quot;Vendor&amp;quot; &amp;lt;&amp;lt; &amp;quot;Name&amp;quot;;&lt;br /&gt;
ui_devtreeview_base.treeWidget-&amp;gt;setHeaderLabels(hsl);&lt;br /&gt;
QTreeWidgetItem * root = NULL;&lt;br /&gt;
foreach (const Solid::Device &amp;amp;device, Solid::Device::allDevices())&lt;br /&gt;
{&lt;br /&gt;
QStringList sl;&lt;br /&gt;
if(device.parentUdi() == &amp;quot;&amp;quot;) {&lt;br /&gt;
sl &amp;lt;&amp;lt; device.udi() &amp;lt;&amp;lt; device.vendor() &amp;lt;&amp;lt; device.product();&lt;br /&gt;
root = new QTreeWidgetItem(ui_devtreeview_base.treeWidget, sl);&lt;br /&gt;
break;&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
findChildren(root);&lt;br /&gt;
}&lt;br /&gt;
void devtreeView::findChildren(QTreeWidgetItem * root) {&lt;br /&gt;
foreach (const Solid::Device &amp;amp;device, Solid::Device::allDevices()) {&lt;br /&gt;
if(device.parentUdi() == root-&amp;gt;text(0)) {&lt;br /&gt;
QStringList sl;&lt;br /&gt;
sl &amp;lt;&amp;lt; device.udi() &amp;lt;&amp;lt; device.vendor() &amp;lt;&amp;lt; device.product();&lt;br /&gt;
findChildren(new QTreeWidgetItem(root, sl));&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
Один из наиболее часто используемых методов класса&lt;br /&gt;
Solid::Device, udi(), возвращает уникальный идентификатор устрой-&lt;br /&gt;
ства. В Linux, где Solid основан на FreeDesktop HAL, идентифика-&lt;br /&gt;
тором устройства служит HAL-адрес устройства (строка вида “/&lt;br /&gt;
org/freedestop/Hal/...”). Нам не обязательно разбираться в том, как&lt;br /&gt;
формируются эти адреса: важно знать, что именно они идентифи-&lt;br /&gt;
цируют устройства. Метод parentUdi() класса Solid::Device возвра-&lt;br /&gt;
щает идентификатор родительского устройства, а соответствую-&lt;br /&gt;
щий ему объект класса Solid::Device можно получить с помощью&lt;br /&gt;
метода Solid::Device::parent(). Для корневого устройства метод&lt;br /&gt;
parentUdi() возвращает пустую строку, чем мы и пользуемся в мето-&lt;br /&gt;
де enumDevices(). После того как корневое устройство найдено,&lt;br /&gt;
мы вызываем рекурсивно метод findChildren(), который добавляет&lt;br /&gt;
в виджет ui_devtreeview_base.treeWidget устройства, являющиеся&lt;br /&gt;
непосредственными потомками корневого. Для каждого найденного&lt;br /&gt;
устройства наша программа отображает три элемента данных: иден-&lt;br /&gt;
тификатор устройства, наименование изготовителя (возвращается&lt;br /&gt;
методом Solid::Device::vendor()) и описание устройства (возвраща-&lt;br /&gt;
ется методом product()). У класса Solid::Device есть еще и метод&lt;br /&gt;
icon(), который возвращает строку с именем пиктограммы устрой-&lt;br /&gt;
ства (пока что непустая строка возвращается только для корневого&lt;br /&gt;
устройства Computer).&lt;br /&gt;
Если бы система Solid позволяла только перечислить имею-&lt;br /&gt;
щиеся в наличии устройства, пользы от нее было бы не очень&lt;br /&gt;
много. Однако основная задача Solid заключается в том, что-&lt;br /&gt;
бы информировать систему о различных событиях, связанных с&lt;br /&gt;
устройствами. Делается это, естественно, с помощью сигналов и&lt;br /&gt;
слотов. Сигналы, оповещающие систему о событиях, связанных с&lt;br /&gt;
устройствами, эмитируются объектами специальных классов. На&lt;br /&gt;
момент написания статьи их существовало три: Solid::DeviceNotifier,&lt;br /&gt;
Solid::Networking::Notifier и Solid::PowerManagement::Notifier. Объект&lt;br /&gt;
класса Solid::DeviceNotifier информирует программу о подключении&lt;br /&gt;
и отключении устройств. Объект класса Solid::Networking::Notifier&lt;br /&gt;
сообщает о подключении и отключении системы от сети, а объект&lt;br /&gt;
класса Solid::PowerManagement::Notifier позволяет программе отсле-&lt;br /&gt;
живать режим работы системы питания. Особняком стоит класс&lt;br /&gt;
WebcamWatcher, который выполняет функции Solid::DeviceNotifier&lt;br /&gt;
исключительно для web-камер.&lt;br /&gt;
На первый взгляд может показаться, что возможности Solid в&lt;br /&gt;
плане оповещения программ о событиях устройств крайне скромны,&lt;br /&gt;
но это не так. Помните, что устройствами в Solid считаются самые&lt;br /&gt;
разные вещи. Объект класса Solid::DeviceNotifier может оповещать&lt;br /&gt;
программу о таких событиях, как установка нового CD-диска в при-&lt;br /&gt;
вод, подключение USB-устройства или монтирование нового разде-&lt;br /&gt;
ла файловой системы.&lt;br /&gt;
Вполне логично задействовать объект класса Solid::DeviceNotifier&lt;br /&gt;
в программе devtree для обновления дерева устройств в случае&lt;br /&gt;
изменения оного. Система Solid предоставляет каждой программе&lt;br /&gt;
один объект класса Solid::DeviceNotifier. Для получения указателя&lt;br /&gt;
на него мы воспользуемся статическим методом Solid::DeviceNotif&lt;br /&gt;
ier::instance():&lt;br /&gt;
Solid::DeviceNotifier * dn = Solid::DeviceNotifier::instance();&lt;br /&gt;
Объект класса Solid::DeviceNotifier эмитирует два сигнала:&lt;br /&gt;
deviceAdded() (добавлено новое устройство) и deviceRemoved()&lt;br /&gt;
(устройство отключено). В качестве аргумента оба сигнала передают&lt;br /&gt;
строку с идентификатором устройства. Мы связываем оба сигнала&lt;br /&gt;
со слотом update(), который мы добавили в главный класс нашей&lt;br /&gt;
программы:&lt;br /&gt;
dn-&amp;gt;connect(dn, SIGNAL(deviceAdded(const QString)), this,&lt;br /&gt;
SLOT(update()));&lt;br /&gt;
dn-&amp;gt;connect(dn, SIGNAL(deviceRemoved(const QString)), this,&lt;br /&gt;
SLOT(update()));&lt;br /&gt;
Слот update() не обрабатывает переданный ему параметр, а про-&lt;br /&gt;
сто очищает виджет ui_devtreeview_base.treeWidget и заново строит&lt;br /&gt;
дерево устройств. Разумеется, такой подход нельзя назвать самым&lt;br /&gt;
эффективным. Для ускорения работы программы можно было бы&lt;br /&gt;
найти для добавленного/удаленного родительское устройство и&lt;br /&gt;
перестроить только соответствующую ему часть дерева.&lt;br /&gt;
Для сборки программы devtree в файл CMakeLists.txt следу-&lt;br /&gt;
ет добавить данные о заголовочных файлах и библиотеках Solid.&lt;br /&gt;
Вопреки тому, что говорит документация, все заголовочные фай-&lt;br /&gt;
лы Solid API хранятся в поддиректории solid стандартной директо-&lt;br /&gt;
рии include. Переменная CMake KDE4_INCLUDE_DIR уже содержит&lt;br /&gt;
ее имя. Единственное изменение, которое нужно внести в файл&lt;br /&gt;
CMakeLists.txt по сравнению со стандартным файлом приложения&lt;br /&gt;
KDE 4 – это добавить переменную KDE4_SOLID_LIBS в качестве&lt;br /&gt;
аргумента команды target_link_libraries(). Теперь программу devtree&lt;br /&gt;
можно компилировать.&lt;br /&gt;
Интерфейсы устройств&lt;br /&gt;
В модели Solid объекты класса Solid::Device соответствуют общему&lt;br /&gt;
понятию «устройство» и позволяют непосредственно получить толь-&lt;br /&gt;
ко те данные, которые имеют смысл для всех устройств, независи-&lt;br /&gt;
мо от их типа. Более подробную информацию о каждом устройстве&lt;br /&gt;
можно извлечь с помощью интерфейсов, которые представлены в&lt;br /&gt;
Solid объектами класса Solid::DeviceInterface и его потомков. Каждое&lt;br /&gt;
устройство (то есть корректно созданный объект Solid::Device) пре-&lt;br /&gt;
доставляет как минимум один интерфейс. Узнать, поддерживает ли&lt;br /&gt;
устройство определенный интерфейс, можно с помощью метода&lt;br /&gt;
isDeviceInterface() класса Solid::Device. Его аргументом должно быть&lt;br /&gt;
значение типа Solid::DeviceInterface::Type, указывающее тип требуе-&lt;br /&gt;
мого интерфейса. Полный список типов интерфейсов можно найти&lt;br /&gt;
в документации Solid и файле solid/deviceinterface.h. Например, тип&lt;br /&gt;
Processor определяет интерфейс ЦП, Block – блочное устройство,&lt;br /&gt;
StorageVolume – раздел на диске, Battery – аккумулятор. Учитывая&lt;br /&gt;
структуру Solid, вы не должны удивляться, что среди поддержива-&lt;br /&gt;
емых типов интерфейсов одновременно присутствуют интерфейсы&lt;br /&gt;
логических и физических устройств. Если объект Solid::Device поддерживает запрошенный интерфейс, метод isDeviceInterface() воз-&lt;br /&gt;
вращает значение true.&lt;br /&gt;
После того как вы выяснили, поддерживает ли устройство неко-&lt;br /&gt;
торый интерфейс, вы, скорее всего, захотите получить объект, его&lt;br /&gt;
реализующий. Сделать это можно с помощью метода Solid::Device:&lt;br /&gt;
:asDeviceInterface(), аргументом которого выступает тип требуемого&lt;br /&gt;
интерфейса. В случае успеха метод возвращает указатель на объ-&lt;br /&gt;
ект класса, производного от Solid::DeviceInterface, соответствующе-&lt;br /&gt;
го запрошенному интерфейсу. Имейте в виду, что не для каждого&lt;br /&gt;
значения Solid::DeviceInterface::Type существует свой класс (так, по&lt;br /&gt;
крайней мере, обстояло дело на момент написания статьи).&lt;br /&gt;
В приложениях, использующих Solid, довольно часто требует-&lt;br /&gt;
ся получить список устройств, поддерживающих определенный&lt;br /&gt;
интерфейс (вполне логично, что программа, которая обрабатыва-&lt;br /&gt;
ет изображение, поступающее с видеокамер, захочет иметь пол-&lt;br /&gt;
ный список устройств, поддерживающих интерфейс Camera, а не&lt;br /&gt;
вообще всех устройств). Для этого можно было бы, конечно, пере-&lt;br /&gt;
брать полный список устройств системы (как мы делали выше),&lt;br /&gt;
проверяя, поддерживает ли каждое из них требуемый интерфейс,&lt;br /&gt;
однако Solid предоставляет нам более простой и эффективный&lt;br /&gt;
способ. Класс Solid::Device экспортирует несколько статических&lt;br /&gt;
методов, предназначенных для управления не конкретным устрой-&lt;br /&gt;
ством, а всем списком устройств Solid (с одним из них, allDevices(),&lt;br /&gt;
мы уже знакомы). Статические методы Solid::Device::listFromType()&lt;br /&gt;
и Solid::Device::listFromQuery() позволяют получить подмножество&lt;br /&gt;
списка устройств, заданное специальными признаками. Нас инте-&lt;br /&gt;
ресует метод listFromType(), который возвращает список устройств,&lt;br /&gt;
поддерживающих определенный интерфейс (говоря «устройство»,&lt;br /&gt;
я, разумеется, имею в виду объект класса Solid::Device). Вот как,&lt;br /&gt;
например, мы можем получить список устройств, поддерживающих&lt;br /&gt;
интерфейс NetworkInterface:&lt;br /&gt;
QList&amp;lt;Solid::Device&amp;gt; devlist =&lt;br /&gt;
Solid::Device::listFromType(Solid::DeviceInterface::NetworkInterface,&lt;br /&gt;
QString());&lt;br /&gt;
Если во втором параметре listFromType() передать идентифика-&lt;br /&gt;
тор устройства, в результирующий список войдут только сетевые&lt;br /&gt;
устройства, являющиеся потомками заданного (пустая строка, раз-&lt;br /&gt;
умеется, означает, что нас интересуют все сетевые устройства).&lt;br /&gt;
Solid и Plasma&lt;br /&gt;
Работу с интерфейсами устройств мы продемонстрируем на при-&lt;br /&gt;
мере динамического плазмоида. Как уже говорилось в LXF110,&lt;br /&gt;
плазмоиды хорошо подходят для того, чтобы информировать поль-&lt;br /&gt;
зователя о важных событиях, происходящих в системе. Solid, как&lt;br /&gt;
мы уже видели, может служить источником такого рода событий.&lt;br /&gt;
&lt;br /&gt;
Для передачи данных от Solid плазмоиду мы воспользуемся стан-&lt;br /&gt;
дартным механизмом поставщиков данных Plasma (LXF110). Наш&lt;br /&gt;
плазмоид будет информировать пользователя о состоянии сетевых&lt;br /&gt;
интерфейсов системы (рис. 2).&lt;br /&gt;
Полные исходные тексты поставщика данных (архив&lt;br /&gt;
networkengine) и плазмоида ncview вы найдете на LXFDVD.&lt;br /&gt;
Networkengine предоставляет один источник по имени NCs. Данные&lt;br /&gt;
представляют собой массив строк (QStringList), в котором содер-&lt;br /&gt;
жится перечень сетевых устройств, имена соответствующих сете-&lt;br /&gt;
вых интерфейсов Linux и MAC-адреса устройств (это, собственно&lt;br /&gt;
говоря, вся информация, которую можно извлечь из интерфейса&lt;br /&gt;
NetworkInterface). Рассмотрим объявление главного класса постав-&lt;br /&gt;
щика данных NetStatEngine:&lt;br /&gt;
class NetStatEngine : public Plasma::DataEngine {&lt;br /&gt;
Q_OBJECT&lt;br /&gt;
public:&lt;br /&gt;
NetStatEngine(QObject* parent, const QVariantList&amp;amp;);&lt;br /&gt;
protected:&lt;br /&gt;
bool sourceRequestEvent(const QString&amp;amp; name);&lt;br /&gt;
bool updateSourceEvent(const QString&amp;amp; source);&lt;br /&gt;
private slots:&lt;br /&gt;
void updateDevices();&lt;br /&gt;
};&lt;br /&gt;
Основные элементы этого класса должны быть знакомы вам по&lt;br /&gt;
LXF110 ( в отличие от той статьи, здесь мы используем только син-&lt;br /&gt;
таксис KDE 4.1.x: пришла пора обновиться, если вы до сих пор этого&lt;br /&gt;
не сделали). Новый элемент здесь – только слот updateDevices(). В&lt;br /&gt;
конструкторе класса мы вызываем метод updateSourceEvent(), как&lt;br /&gt;
и в любом поставщике данных, а затем получаем указатель на гло-&lt;br /&gt;
бальный объект Solid::DeviceNotifier:&lt;br /&gt;
NetStatEngine::NetStatEngine(QObject* parent, const QVariantList&amp;amp;)&lt;br /&gt;
: Plasma::DataEngine(parent)&lt;br /&gt;
{&lt;br /&gt;
updateSourceEvent(&amp;quot;NCs&amp;quot;);&lt;br /&gt;
Solid::DeviceNotifier * dn = Solid::DeviceNotifier::instance();&lt;br /&gt;
dn-&amp;gt;connect(dn, SIGNAL(deviceAdded(const QString)), this,&lt;br /&gt;
SLOT(updateDevices()));&lt;br /&gt;
dn-&amp;gt;connect(dn, SIGNAL(deviceRemoved(const QString)), this,&lt;br /&gt;
SLOT(updateDevices()));&lt;br /&gt;
}&lt;br /&gt;
Как и в рассмотренном выше случае, этот объект нужен нам для&lt;br /&gt;
того, чтобы связать слот updateDevices() с сигналами deviceAdded()&lt;br /&gt;
и deviceRemoved(). Рабочая лошадка нашего поставщика данных –&lt;br /&gt;
метод updateSourceEvent():&lt;br /&gt;
bool NetStatEngine::updateSourceEvent(const QString &amp;amp;name)&lt;br /&gt;
{&lt;br /&gt;
if (name == &amp;quot;NCs&amp;quot;) {&lt;br /&gt;
QList&amp;lt;Solid::Device&amp;gt; devlist =&lt;br /&gt;
Solid::Device::listFromType(Solid::DeviceInterface::NetworkInterface,&lt;br /&gt;
QString());&lt;br /&gt;
QStringList sl;&lt;br /&gt;
foreach (const Solid::Device &amp;amp;device, devlist) {&lt;br /&gt;
sl &amp;lt;&amp;lt; &amp;quot;Device: &amp;quot; + device.parent().product();&lt;br /&gt;
Solid::NetworkInterface * ni = (Solid::NetworkInterface *) device.as&lt;br /&gt;
DeviceInterface(Solid::DeviceInterface::NetworkInterface);&lt;br /&gt;
sl &amp;lt;&amp;lt; &amp;quot;Interface: &amp;quot; + ni-&amp;gt;ifaceName();&lt;br /&gt;
sl &amp;lt;&amp;lt; &amp;quot;Address: &amp;quot; + ni-&amp;gt;hwAddress();&lt;br /&gt;
sl &amp;lt;&amp;lt; QString(&amp;quot;Type: &amp;quot;) + (ni-&amp;gt;isWireless() ? &amp;quot;Wireless&amp;quot; : &amp;quot;Wired&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
setData(name, sl);&lt;br /&gt;
return true;&lt;br /&gt;
}&lt;br /&gt;
return false;&lt;br /&gt;
}&lt;br /&gt;
Наша первая задача – получить список устройств, поддер-&lt;br /&gt;
живающих интерфейс NetworkInterface, как было описано выше.&lt;br /&gt;
&lt;br /&gt;
Далее мы перебираем все элементы списка сетевых устройств&lt;br /&gt;
и для каждого из них получаем указатель на объект класса&lt;br /&gt;
Solid::NetworkInterface посредством метода asDeviceInterface().&lt;br /&gt;
Данные, полученные с помощью интерфейсов, заносятся в список&lt;br /&gt;
QStringList, который передается методу setData(). Метод ifaceName()&lt;br /&gt;
класса Solid::NetworkInterface возвращает строку с именем интер-&lt;br /&gt;
фейса (“eth0”, “eth1” и т.д.). С помощью метода hwAddress()&lt;br /&gt;
мы можем получить MAC-адрес устройства в текстовом виде&lt;br /&gt;
(метод macAddress() возвращает MAC-адрес в виде числа). Метод&lt;br /&gt;
isWireless() вернет значение true, если сетевой интерфейс является&lt;br /&gt;
беспроводным, и false – в противном случае. Чтобы сделать спи-&lt;br /&gt;
сок сетевых устройств более информативным, мы выводим назва-&lt;br /&gt;
ние каждого устройства. Его можно получить с помощью метода&lt;br /&gt;
product() класса Solid::Device; однако для всех устройств, соответ-&lt;br /&gt;
ствующих сетевым интерфейсам, он возвращает строку “Network&lt;br /&gt;
Interface”, что, конечно, не очень интересно. Для получения имени&lt;br /&gt;
физического устройства, предоставляющего сетевой интерфейс,&lt;br /&gt;
мы вызываем метод product() устройства, являющегося «родите-&lt;br /&gt;
лем» сетевого интерфейса.&lt;br /&gt;
Нам осталось рассмотреть вопрос о том, как поставщик данных&lt;br /&gt;
оповещает плазмоид о подключении и отключении сетевых интер-&lt;br /&gt;
фейсов (в LXF110, напомним, это происходило в результате перио-&lt;br /&gt;
дического опроса). Для такого нечастого события, как добавление&lt;br /&gt;
и удаление сетевых интерфейсов, регулярный опрос, выполняемый&lt;br /&gt;
плазмоидом, явно избыточен. Для нерегулярных и нечастых собы-&lt;br /&gt;
тий лучше подходит модель, при которой поставщик сам информи-&lt;br /&gt;
рует заинтересованный плазмоид об изменении данных. Наладить&lt;br /&gt;
этот механизм очень просто. Ниже приводится исходный текст сло-&lt;br /&gt;
та updateDevices(), который обрабатывает сигналы deviceAdded() и&lt;br /&gt;
deviceRemoved():&lt;br /&gt;
void NetStatEngine::updateDevices()&lt;br /&gt;
{&lt;br /&gt;
updateSourceEvent(&amp;quot;NCs&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
Не удивляйтесь – это действительно все, что необходимо для&lt;br /&gt;
оповещения плазмоида. Метод updateSourceEvent() вызывает метод&lt;br /&gt;
setData(), который с помощью соответствующего сигнала активиру-&lt;br /&gt;
ет слот dataUpdated() в плазмоиде.&lt;br /&gt;
Наконец, зная про метод listFromType(), мы можем написать&lt;br /&gt;
улучшенный вариант метода findChildren() для программы devtree:&lt;br /&gt;
void devtreeView::findChildren(QTreeWidgetItem * root) {&lt;br /&gt;
QList&amp;lt;Solid::Device&amp;gt; children =&lt;br /&gt;
Solid::Device::listFromType(Solid::DeviceInterface::GenericInterface,&lt;br /&gt;
root-&amp;gt;text(0));&lt;br /&gt;
foreach (const Solid::Device &amp;amp;device, children) {&lt;br /&gt;
QStringList sl;&lt;br /&gt;
sl &amp;lt;&amp;lt; device.udi() &amp;lt;&amp;lt; device.vendor() &amp;lt;&amp;lt; device.product();&lt;br /&gt;
findChildren(new QTreeWidgetItem(root, sl));&lt;br /&gt;
}&lt;br /&gt;
}&lt;br /&gt;
Значение Solid::DeviceInterface::GenericInterface соответствует интерфейсу базового типа, который поддерживается всеми&lt;br /&gt;
устройствами.&lt;br /&gt;
&lt;br /&gt;
На тему программирования для KDE 4 можно было бы написать&lt;br /&gt;
еще очень много, но мы завершаем наш обзор. Того, что вы узнали&lt;br /&gt;
о новой версии KDE из этих уроков, вполне достаточно, чтобы написать расширение KDE, которое, возможно, даже оправдает утяжеление будущего дистрибутива на несколько мегабайт. Не забудьте&lt;br /&gt;
сообщить нам, если получится что-то стоящее!&lt;/div&gt;</summary>
		<author><name>Yaleks</name></author>	</entry>

	</feed>