<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Eugene&#160;Rudenko</title>
	<atom:link href="http://erudenko.com/wordpress/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://erudenko.com/wordpress</link>
	<description>Research and development blog of Rudenko Eugene</description>
	<lastBuildDate>Sun, 23 May 2010 22:16:08 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Nokia Qt SDK, пишем первое приложение и запускаем его в эмуляторе и на устройстве</title>
		<link>http://erudenko.com/wordpress/?p=313</link>
		<comments>http://erudenko.com/wordpress/?p=313#comments</comments>
		<pubDate>Sun, 23 May 2010 22:13:54 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[Qt-creator]]></category>
		<category><![CDATA[Russian]]></category>
		<category><![CDATA[maemo]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[fremantle]]></category>
		<category><![CDATA[MADDE]]></category>
		<category><![CDATA[N900]]></category>
		<category><![CDATA[Nokia]]></category>
		<category><![CDATA[Nokia Qt SDK]]></category>
		<category><![CDATA[Qt]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=313</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=313">Nokia Qt SDK, пишем первое приложение и запускаем его в эмуляторе и на устройстве</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Nokia Qt SDK, пишем первое]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=313">Nokia Qt SDK, пишем первое приложение и запускаем его в эмуляторе и на устройстве</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>Как обычно, архивирую совю публикацию на <a href="http://habrahabr.ru/blogs/nokia/94075/">хабре</a>.</p>
<p>Доброго времени суток уважаемый читатель. Продолжаю писать о платформе Maemo (пока еще для Maemo Fremantle). Эта статья посвящена новости в мире Nokia &#8211; выход Nokia Qt SDK. Пока еще это TP (Technical Preview, долго силил перевод на русский, не получилось, так что пуст будет &#8220;TP&#8221; далее по тексту). Но писать на этом уже можно, но есть несколько оговорок. Подробности далее по порядку. Еще я расскажу подробней о MADDE, так как именно эта часть в Nokia Qt SDK отвечает за разработку для Maemo.</p>
<p><img src="http://erudenko.com/photo/N900/QtSimulator.jpeg" alt="image"/></p>
<p>Как результат мы напишем приложение (очень громко сказано <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> , вообще так, приложенице ), соберем и запустим его на эмуляторе и на устройстве ( точнее на Nokia N900 ).  Да и вообще разберемся что чем и как писать для устройств Nokia сейчас и в будущем.</p>
<p>Первым делом разберемся что к чему. Кто зачем и почему выпустил Nokia Qt SDK.<br />
Так вот  Nokia давно готовила этот шаг и вот первый выпуск можно уже опробовать сегодня. И так, встречаем: Nokia Qt SDK.<br />
<a href="http://labs.trolltech.com/blogs/2010/04/27/nokia-qt-sdk-what-is-in-and-what-is-not-and%E2%80%A6-what-is-it/">Официальная информация</a> (там еще две ссылки в этой статье).</p>
<p>Официальное видео(странное вообще).<br />
<p><a href="http://erudenko.com/wordpress/?p=313"><em>Click here to view the embedded video.</em></a></p></p>
<p>Теперь резюмирую. Это SDK для разработки под все официально поддерживаемые мобильные платформы с Qt на борту (на данный момент официально поддерживаются Symbian и Maemo 5, что там будет дальше, пока не ясно). Суть в том, что это единый инструмент для разработки мобильных приложений для устройств от Nokia.<br />
Составные части:</p>
<ol>
<li>Сердцем всего является Qt-Creator.</li>
<li>Под каждую платформу ставится SDK  и toolchain для сборки приложения, упаковки и отладки на устройстве.</li>
<li>Qt Simulator &#8211; для отладки без наличия устройства.</li>
</ol>
<p>Звучит вроде здорово. Немного подробностей под каждую из составляющих:<br />
1. Qt Creator:<br />
 &#8211; специальной сборки<br />
 &#8211; из коробки настроенная интеграция с целевыми SDK,  toolchain&#8217;ами и отладчиками.<br />
 &#8211; встроена поддержка эмулятора<br />
 &#8211; добавлены шаблоны для мобильных проектов<br />
 &#8211; очень удивило и порадовало наличие плагина &#8220;обновление&#8221;, который модульно обновляет SDK (сейчас Qt Creator обновляется только полностью, вышла новая версия   &#8211; качай полностью и ставь рядом или вместо старой). Надеюсь эта &#8220;обновлялка&#8221; перекочует и в настольную версию Qt SDK<br />
- поддержка технологии Quick/QML.<br />
- поддержка помошника отладчика на python&#8217;е (в чем прелесть,<a href="http://labs.trolltech.com/blogs/2010/04/22/peek-and-poke-vol-3/"> можно посмотреть тут </a>, особенно впечатляет последний пример &#8211; отладка отрисовки, все это возможно благодаря макросам на питоне в GDB), правда на устройстве еще нет gdb 7.x (обязательное условие для поддержки макросов питоновских), но будет же<br />
- в нем все еще можно писать и десктопные приложения, это нормальный Qt-Creator <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>2. SDK+toolchain<br />
 &#8211;  для Symbian  &#8211;  это урезанная версия предыдущего SDK (сильно урезанная, так как я сносил окружение для разработки под Symbian, которое у меня стояло, чтоб попробовать &#8211; Symbian SDK+ Carbon + Plugins &#8211; занимало у меня около 5 гиг на диске). Все что нужно для сборки и отладке на устройстве.<br />
 &#8211; для Maemo  используется MADDE, он сам по себе еще в бета-тестировании, но позвоялет писать приложения не только под Linux&#8217;ом, а также под любыми другими платформами. Этим он лучше нынешнего Fremantle SDK (который пока официальный инстурумент для разработки, и еще минимум пол года будет таковым).<br />
 &#8211; все намного компактней собратьев и радует что есть &#8220;обновлялка&#8221;.</p>
<p>3. Qt Simulator<br />
Достаточно интересная штуковина. По сути я ожидал увидеть действительно эмулятор, но ребята схитрили. Это не совсем эмулятор, это &#8220;песочница&#8221; с отдельным буфером экрана и поведением как у телефона (заряд, координаты, акселерометр, звонки и тд.). Он не эмулирует телефон, он по факту эмулирует Qt Mobility API (который кстати вышел из <a href="http://labs.trolltech.com/blogs/2010/04/27/qt-mobility-100-package/">бета-тестирования и зарелизился недавно</a>  )<br />
Вот что он в себя включает:</p>
<ul>
<li>   Service Framework</li>
<li>   Bearer Management</li>
<li>   Messaging</li>
<li>   Contacts</li>
<li>   Versit</li>
<li>   Publish and Subscribe</li>
<li>   Location</li>
<li>   System Information</li>
<li>   Sensors</li>
</ul>
<p>Ну и плюс Multimedia, единственная часть, которая осталась в бета состоянии, но все равно достаточно работоспособна.<br />
Задача эмулятора как раз эмулировать поведение всех вот этих API, и работать они все будут одинаково на всех устройствах с поддержкой Qt Mobility API (я в это верю <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ). Так что если нужно будет реализовать что-то вне этого API &#8211; &#8220;нативное&#8221;, то эмулятор тут не поможет.<br />
Плюс эмулятор поддерживает скриптинг и триггеринг различных системных ситуаций &#8211; входящий звонок, садится батарейка и так далее.<br />
Конечно многих это может расстроить, но с другой стороны, более 90% кода при написании мобильного приложения будет использовано  именно чистое QT API, все что &#8220;вне&#8221; прийдется отлаживать на устройстве. Так как Nokia QT SDK &#8211; инструмент для кросс-платформенной разработки, то можно предположить, что в эмуляторе можно отлаживать только кросс-платформенный функционал (я верю что такой принцип заложен). С другой стороны эмулятор стал легко переносимый на другие платформы и очень легкий по сравнению с настоящим эмулятором.<br />
Еще одна задача эмулятора &#8211; посмотреть как это все будет выглядеть на устройстве (на разных, там в списке есть N95, N97, N900 и призрачный Harmattan (MeeGo) &#8211;  призрачный потому-что устройства нет, есть только Qt-стиль).<br />
Может это еще заставит разработчика трижды задуматься, прежде чем писать не портируемый код.<br />
Ну в итоге не то что я ожидал, но меня порадовал эмулятор.</p>
<p>Ну вот сжато и сумбурно такое вот описание нового СДК. Теперь плохие новости:</p>
<ul>
<li>SDK только для PR 1.2 прошивки, которой еще нет (надеюсь ждать не долго осталось).</li>
<li>Под Linux доступна только разработка для N900 (используя MADDE).</li>
<li>Под Mac OS вообще ничего еще нет.</li>
</ul>
<p>Но так как мы в Вами пока пишем только для N900, то в пролете остаются только пользователи Mac OS (и я в их числе <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ). Но не расстраивайтесь,  MADDE доступно для MAC OS, так что все нормально, просто потребуется немножко больше ручной работы и останемся мы на  Mac OS без эмулятора (может как-то можно и его прикрутить,  я не пробовал совсем в этом направлении копать, если есть инфа или опыт &#8211; пишите).</p>
<p>Таким образом я покажу как установить SDK, написать приложение, собрать его и запустить на эмуляторе. Потом как настроить устройство и запустить на устройстве. Хоть у меня и не получится отладится на устройстве (свалится с SIGFAULT, так как библиотеки на устройстве и в SDK разные), но в скором будущем, когда я обновлю устройство до PR 1.2 это все будет работать (а вообще товарищи производители этих вот библиотек, стыдно должно быть, ибо нужно думать о бинарной совместимости новых версий). Все это под Windows.  Под Linux это делается так-же, только сетевой интерфейс настраивается по другому, но я дам ссылку с картинками как это сделать.<br />
А для пользователей Mac OS я покажу как настроить MADDE + Qt Creator чтоб получить такую же связку для разработки. Соберу приложение и запущу его на устройстве (тут оно уже будет работать). Это решение универсальное и будет работать одинаково на всех платформах. Поэтому его можно использовать как альтернативу Nokia Qt SDK, чтоб не тянуть лишнего (например Вам не нежуне ни эмулятор ни Symbian) или чтоб начать отлаживать на устройстве прямо сейчас.</p>
<p>Но обещают официальный релиз к официальному релизу MeeGo,  3-4 квартал 2010, не так долго и ждать осталось.</p>
<p>Ну и сразу <a href="http://www.forum.nokia.com/Tools_Docs_and_Code/Tools/IDEs/Nokia_Qt_SDK/">официальная ссылка</a>, с кучей информации демок и самим SDK .</p>
<h3>1. Nokia Qt SDK на Windows.</h3>
<p>Во первых, уточняю, у меня Windows XP SP3 32bit. Я не знаю  как это будет работать на других версиях, но если будет различия, то пишите &#8211; обсудим.  Я даже готов сам разобраться с возможными проблемами на Windows 7 (если они будут), если кто-нибудь подарит мне лицензию <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .<br />
Вот традиционное видео:</p>
<p><a href="http://erudenko.com/wordpress/?p=313"><em>Click here to view the embedded video.</em></a></p>
<p>Инструкции:</p>
<ol>
<li>Идем по ссылке http://forum.nokia.com и там находим секцию от SDK или заходим сразу <a href="http://www.forum.nokia.com/Tools_Docs_and_Code/Tools/IDEs/Nokia_Qt_SDK/">на страницу SDK</a> . </li>
<li>Скачиваем SDK под нужную платформу &#8211; Windows, Offline-версия.</li>
<li>Запускаем установщик.</li>
<li>Принимаем лицензионное соглашение.</li>
<li>Выбираем путь установки и выбираем &#8220;настраиваемую&#8221; установку.</li>
<li>В списке можете поизучать устанавливаемые компоненты (я убрал исходниые коды от Qt, нужны они только если собираетесь отлаживать само Qt).</li>
<li>Жмем кнопку для установки и ждем пару минут.</li>
</ol>
<p>Поздравляю !! SDK установлен и готов к эксплуатации (не правда ли легко, по сравнению с предыдущими статьями).</p>
<p>Далее пишем приложение:</p>
<ol>
<li>Открываем Qt Creator из состава Nokia Qt SDK. И создаем сессию. Если вы не знаете что это и зачем, то очень советую <a href="http://doc.trolltech.com/qtcreator-1.3/creator-session.html">ознакомиться</a>, ибо без них разработка нескольких проектов превращается в геморрой.</li>
<li>Создаем новый мобильный проект (интеграция с Mobility API).</li>
<li>Создаем формочку с кнопкой.</li>
<li>Делаем приложение. Смысл его в том, что при нажатии на кнопку, текст в строке ввода &#8220;переносится&#8221; в Label.</li>
<li>Собираем для эмулятора с MinGW 4.4, можете меня спросить почему я запустил сборку до того, как написал год. Все просто, я просто хотел чтоб запустился компилятор .ui файлов и сгенерировал мне соответствующий .h файл, чтоб сработала всплывающая подсказка для написания моего кода (до этого подсказывать не по чем, экземпляра класса ui еще нет).</li>
<li>Запускаем в эмуляторе и немного там играемся.</li>
</ol>
<p>Настраиваем окружение на устройстве (пункт 2 этой статьи, я вынес отдельно, так как настройка окружения на устройстве одинакова как для Windows Nokia Qt SDK иак и для &#8220;чистого&#8221; MADDE).</p>
<p>Отлично, теперь будем отлаживать на устройстве по USB (включим воображение и представим, что PR 1.2 уже вышел и я его уже поставил <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ).</p>
<ol>
<li> Подключаем N900  в режиме PS Suite по USB.</li>
<li> Заходим в сетевые подключения и ищем интерфейс с названием устройства &#8220;Linux USB Ethernet/RND&#8230;.&#8221;</li>
<li> Устанавливаем на этом интерфейсе статический адрес и сеть (во всех примерах это 192.168.2.14/24).</li>
<li> Предполагаю что Вы все настроили уже на устройстве, поэтому пингуем его.(пусть не смущает в видео подсеть 192.168.3.0, я потом перенастроил, так как локальный WiFi у меня был на сети 192.168.2.0).</li>
<li> Настраиваем наше устройство в Qt Creator&#8217;е. Выбирается авторизация по паролю, если не хочется каждый раз вводить пароль, то моно обменяться ключами. Для этого достаточно иметь сгенерированные ключи и настроить авторизация по паролю и после этого нажать на кнопку &#8220;Deploy Key &#8230;&#8221; и указать публичный ключ. Qt Creator подключится по паролю и заберет публичный ключ с устройства, а на устройство положит Ваш публичный ключ. Если же авторизироваться по паролю, то в этой вкладке нужно будет каждый раз вводить пароль, который сгенерировал mad-developer.</li>
<li> Проверям соединение с устройством, нажав на кнопку &#8220;Test&#8221;,  должен вывестись список установленных библиотек Qt на устройстве.</li>
<li> На видио пропустил еще один шаг, нуно зайти в &#8220;Projects&#8221;и посмотреть, чтоб во вкладке &#8220;Maemo&#8221;  был выбран нужный нам рантайм (он у нас один там, называется N900, это то что мы настраивали в предыдущих двух шагах). Если не понятно, подсмотрите в пункте 3, где мы будем настраивать связку Qt Creator+MADDE на Mac OS вручную.</li>
<li> Запускаем и все увы не работает, но непременно заработает, когда устройство прошьется до версии PR 1.2.</li>
</ol>
<h3>2. Настройка окружения на телефоне.</h3>
<p>Съемка телефона мне дается очень сложно, в данном случае было сложнее, так как подставку я зыбал в Москве и пришлось городить стационарную систему съемок из подручный материалов. Не обращайте внимание на мои трясущиеся руки со стилусом &#8211; это не от страха, а от неудобности <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>А теперь к делу, все что нам нужно &#8211; это поставить и освоить пакет mad-developer из &#8220;extras&#8221; репозитория.<br />
<p><a href="http://erudenko.com/wordpress/?p=313"><em>Click here to view the embedded video.</em></a></p></p>
<ol>
<li> Заходим в Диспечер приложений. Нажимаем &#8220;загрузить&#8221; и заходим в каталог &#8220;разработка&#8221;.</li>
<li> Ищем пакет mad-developer и ставим его (если его нет в списке, проверьте, может он уже стоит и проверьте подключен ли у Вас репозиторий extras).</li>
<li> Запускаем mad-developer.</li>
<li> Настраиваем сетевой интерфейс USB (вводим статический аддресии &#8211; в моем случае 192.168.3.15, так как вторая подсетка уже занята).</li>
<li> При разработке из-под Windows необходимо вручную загрузить USB модуль  g_ether, на Mac OS и Linux это не нужно, у Вас сетевые интерфейсы поднимутся и так.</li>
<li> Доступна консоль разработчика (зачем она, не совсем понятно).</li>
<li> Самое главное &#8211; это кнопка генерации пароля, пока пароль видно на экране &#8211; он действителен, как только нажмете кнопку &#8220;close&#8221; &#8211; подключиться к устройству по паролю вы уже не сможете.</li>
</ol>
<p>Рабочее состояние приложения такое &#8211; открываете mad-developer и открываете окно с паролем, запускаете Qt Creator и заходите во вкладку настройки Maemo  устройства и вводите этот пароль. После этого можно отлаживаться на устройстве. Если обменяться ключами как указано в предыдущей главе, то этого всего не нужно.</p>
<h3>3. Настрйка связки  Qt Creator + MADDE на Mac OS.</h3>
<p>По большому счету, если Вам не нужен эмулятор, то даже на Windows и автообновление SDK, то  можно воспользоваться этим путем вместо SDK.  По сути для Maemo разработки Nokia Qt SDK и MADDE не просто синонимы, а одно и то-же. Так что если не собираетесь писать под Symbian и не нужен эмулятор, то советую использовать чистый MADDE в целях экономии места.</p>
<p>Тем не менее, на текущий момент Nokia Qt SDK нет для Mac OS,  именно поэтому я и решил продемонстрировать установку  MADDE+QtCreator.<br />
Вот видео:<br />
<p><a href="http://erudenko.com/wordpress/?p=313"><em>Click here to view the embedded video.</em></a></p></p>
<p>Плюс видео как добавить Madde&#8217;шный qmake в Qt-Creator(забыл включить в первое видео):<br />
<p><a href="http://erudenko.com/wordpress/?p=313"><em>Click here to view the embedded video.</em></a></p></p>
<p>Тут все просто.</p>
<ol>
<li> Скачиваем MADDE скрипт-установщик и запускаем его.</li>
<li> Скачиваем и ставим последний Qt Creator (либо последний &#8220;снимок&#8221; <a href="ftp://ftp.qt.nokia.com/qtcreator/snapshots/latest">отсюда</a>  либо качаем последний официальный релиз 2.0 beta <a href="http://qt.nokia.com/developer/qt-qtcreator-prerelease">отсюда</a>  (там внизу страницы ссылки на сборки для разных ОС)).</li>
<li> Настраиваем mad-developer на N900 (предыдущая глава).</li>
<li> Настраиваем Qt-creator, добавляем Qt из MADDE пакета.</li>
<li> Настраиваем среду запуска на устройстве.</li>
<li> Пишем собственно приложение.</li>
<li> Запускаем и отлаживаем его на компьютере.</li>
<li> Запускаем и отлаживаем его на устройстве.</li>
</ol>
<p>Хоть все и просто, но есть пару нюансов.</p>
<ul>
<li> В qmake.conf в MADDE не прописан флаг &#8220;-g&#8221;  для gcc,  при сборке приложения в режиме отладки. Поэтому в файл .pro нужно добавить такую вот строчку:</li>
<li>QMAKE_CXXFLAGS_DEBUG+=-g</li>
<li>эта переманная &#8211; флаги для gcc, при сборке в режиме отладки.</li>
<li> Нужно &#8220;вручную&#8221; добавить qmake, который нужен для сборки приложения для запуска на устройстве.</li>
<li> Необходимо пересобрать (помощник отладчика).</li>
</ul>
<h3>4. Отладка, live video.</h3>
<p>Ну вот привожу еще одно видео, как выглядел последний параграф моими глазами. Весь процесс запуска и отладки на устройстве.</p>
<p><a href="http://erudenko.com/wordpress/?p=313"><em>Click here to view the embedded video.</em></a></p>
<h3>Заключение.</h3>
<p>В итоге могу сказать  Bravo!, компании Nokia. Все сделано очень дельно и хорошо, даже учитывая, что это beta, все равно разрабатывать приложения даже для коммерческого проекта можно.<br />
Процесс установки и настройки очень простой. Разработка для мобильный и настольных приложений ведется одними инструментами. Qt Mobility API принес возможность абстрагироваться от уровня мобильной ОС до уровня &#8220;коммуникатор&#8221;.<br />
Статья я надеюсь скоро устареет, но принципы заложенные в бета версию продуктов не должны изменится. По сути нужно будет делать то-же самое, только в файлах-установщиках будут другие версии.</p>
<p>Вот в принципе можно считать цикл статей на тему &#8220;как поставить и настроить чтоб можно было написать программку&#8221; я считаю завершенной. В следующих статьях мы наконец-то начнем писать приложение, приложение будет надеюсь интересное и полезное, но то что оно будет охватывать практически все темы (не глубоко, но достаточно для понимания куда копать дальше, в случае чего) &#8211; это я обещаю.</p>
<p>Всем удачного коддинга/хаккинга.</p>
<p>UPD: баги конечно есть, это первый официальный выпуск (хоть и бета). Так что те кому это интересно  и кто нашел ошибки, имеет вопросы или просто хочет узнать больше вот необходимые ссылки:<br />
<a href="http://wiki.forum.nokia.com/index.php/Nokia_Qt_SDK_v1.0_Beta">Официальная WiKi страничка.</a><br />
<a href="http://www.forum.nokia.com/Tools_Docs_and_Code/Tools/IDEs/Nokia_Qt_SDK/">Официальная страница проекта.</a><br />
<a href="http://www.forum.nokia.com/info/sw.nokia.com/id/a075d8cc-dc4e-4926-8faa-9d926c20a3d7/Getting_Started_with_Nokia_Qt_SDK.html">Руководство по &#8220;быстрому старту&#8221;.</a><br />
<a href="http://discussion.forum.nokia.com/forum/forumdisplay.php?f=221">Форум, посвященный инструментам, входящим в состав этоко SDK.</a></p>
<p>Ну и конечно <a href="http://bugreports.qt.nokia.com/secure/Dashboard.jspa">Qt bug-tracker.</a></p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>368</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=313</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Быстрая установка Fremantle SDK (Maemo 5). Установка Qt 4.6. Запуск и отладка в эмуляторе и на устройстве</title>
		<link>http://erudenko.com/wordpress/?p=309</link>
		<comments>http://erudenko.com/wordpress/?p=309#comments</comments>
		<pubDate>Fri, 12 Mar 2010 23:15:49 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[Russian]]></category>
		<category><![CDATA[maemo]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[fremantle]]></category>
		<category><![CDATA[maemo5]]></category>
		<category><![CDATA[manual]]></category>
		<category><![CDATA[N900]]></category>
		<category><![CDATA[Nokia]]></category>
		<category><![CDATA[Qt]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=309</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=309">Быстрая установка Fremantle SDK (Maemo 5). Установка Qt 4.6. Запуск и отладка в эмуляторе и на устройстве</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Быстрая установка Fremantle SDK (Maemo]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=309">Быстрая установка Fremantle SDK (Maemo 5). Установка Qt 4.6. Запуск и отладка в эмуляторе и на устройстве</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>Продолжаю цикл статей по программированию для Maemo.</p>
<p>Некоторым показалось, что начать программировать для Maemo тяжело. Именно поэтому я решил начать с демонстрации легкого пути &#8220;Easy way&#8221; (c), чтоб показать как легко начать. Далее, учитывая выход <a href="http://habrahabr.ru/blogs/qt_software/84316/">официального релиза t 4.6.2 для maemo 5</a>, я покажу как поставить этот релиз на Fremantle SDK. Продемонстрирую отладку в эмуляторе. И самое главное, как отлаживать приложение на устройстве используя обычное сетевое подключение и подключение по USB.</p>
<p>Результатом нашего труда будет вот такое вот окошечко на устройстве:</p>
<p><img src="http://labs.emich.be/wp-content/uploads/2010/01/screenshot05.png" alt="image"/></p>
<p>Примечание: в качестве IDE используется Scratchbox, так как речь идет о Fremantle SDK. QtQreator можно использовать, но как таковой поддержки Fremantle в нем нет и не будет. Почему ? Да потому-что в нем делают поддержку нового, кросс-платформенного SDK &#8211; MADDE, о котором я уже упоминал (и упомяну еще в заключении). </p>
<p>Ну раз вы под катом, то значит решились на прочтение моей статьи.</p>
<h2>1. Установка SDK  и запуск HelloWorld в эмуляторе. </h2>
<p>Все видео здесь не очень хорошего качества, на YouTube&#8217;e  можно посмотреть их в HD формате, для этого достаточно два раза кликнуть по видео.</p>
<p>Начнем с начала, в данной точке предположим, что<a href="http://habrahabr.ru/blogs/nokia/83448/"> предыдущую статью</a> вы либо не читали, либо решили не проходить <s>тернистый</s> немножко длинный путь по установке SDK. Но если бы вы прошли по первому пути, то в качестве <s>приза</s> результата Вы получили бы удобную среду для разработки в родной ОС (лично мое мнение конечно).<br />
Но если <s>Вы ленивый</s> по каким-либо причинам Вам не подходит описанный мной вариант, предлагаю другой, более легкий и простой.</p>
<p>Если у Вас уже стоит Fremantle SDK, то можете пропустить этот шаг и перейти сразу ко второму шагу.</p>
<p>Для установки SDK необходимо скачать:</p>
<ol>
<li> <a href="http://tablets-dev.nokia.com/maemo-dev-env-downloads.php">Fremantle SDK Virtual Image</a> &#8211; файл по имени <b>Maemo_Ubuntu_Intrepid_Desktop_SDK_Virtual_Image_Final.7z</b>.</li>
<li>опционально 7ip архиватор, если у вас его нет (берите любой).</li>
<li><a href="http://www.virtualbox.org/wiki/Downloads">VirtualBox </a> или quemu или VMWare. В моем примере я использую VirtualBox.</li>
</ol>
<p>и далее действуем согласно видео, там вроде все наглядно:<br />
<p><a href="http://erudenko.com/wordpress/?p=309"><em>Click here to view the embedded video.</em></a></p></p>
<p>Заметки: устанавливайте дополнения гостевой ОС непосредственно из самого VirtualBox, а не те, которые включены в сам SDK (ссылка на них на рабочем столе). Их нигде качать не нужно, они уже идут с самим VirtualBox и дистрибутив подключается как виртуальный образ диска.</p>
<p>Как Вы видите, установка, настройка и запуск приложения занимает менее 10 минут, в отличие от описанного мною ранее метода. Все очень просто</p>
<h2>2. Установка  Qt 4.6.2,  и создание и запуск Qt приложения в эмуляторе. </h2>
<p>С этого момента не важно, используете вы способ установки предложенный из предыдущей статьи или же из пункта 1. Всё актуально для обоих случаев установки.</p>
<p><a href="http://erudenko.com/wordpress/?p=309"><em>Click here to view the embedded video.</em></a></p>
<p>тут последовательность такова:</p>
<p>Сначала мы удаляем установленный в SDK Qt 4.5.</p>
<blockquote><p>
fakeroot apt-get remove libqtv4*
</p></blockquote>
<p>и затем установить официальный Qt 4.6.2 для Maemo5:</p>
<blockquote><p>
fakeroot apt-get install libqt4-maemo5-dev
</p></blockquote>
<p>Причем сделать это нужно для обоих целей ARMEL и x86. Цель x86 нужна для запуска и отладки в эмуляторе, а цель ARMEL для запуска и отладки на устройстве (кросскомпиляция). Переключаться между целями в scratchbox можно с помощью меню:</p>
<blockquote><p>
sb-menu
</p></blockquote>
<p><b>Теперь внимание!!!!</b> Сеть в scratchbox может не работать (при запуске команды для установки пакетов могут быть ошибки с сетью). Это связано с небольшими проблемами в scratchbox. Их легко устранить. Для этого <b> вне scratchbox</b> нужно скопировать для каждой цели и для самого scratchbox файлик resolv.conf, который вы получили по  DHCP либо сформировали в процессе настройки статической сети (явно или косвенно через утилиты):</p>
<blockquote><p>
sudo cp /etc/resolv.conf /scratchbox/etc<br />
sudo cp /etc/resolv.conf /scratchbox/users/maemo/targets/FREMANTLE_ARMEL/etc<br />
sudo cp /etc/resolv.conf /scratchbox/users/maemo/targets/FREMANTLE_X86/etc
</p></blockquote>
<p>Еще имейте ввиду, что в случае использования прокси, Вам нужно экспортировать переменные окружения:</p>
<blockquote><p>
export http_proxy=&#8230;<br />
export https_proxy=&#8230;
</p></blockquote>
<p>Это можно вынести в отдельный скрипт или добавить эти строки в  ~/.bashrc файл или указать proxy для apt-get:</p>
<blockquote>
<pre>
 echo 'Acquire::http::Proxy "http://aptcache:3142";' > /etc/apt/apt.conf.d/99proxy
</pre>
</blockquote>
<p>В этом случае apt-get будет работать через этот proxy.</p>
<p> также перед установкой пакетов Qt будет не лишним обновить пакеты для каждой цели в scratchbox (вообще все команды, начинающиеся с &#8220;fakeroot&#8221; выполняются только внутри scratchbox, а sudo вне его):</p>
<blockquote><p>
fakeroot apt-get update
</p></blockquote>
<p>После этого создаем проект Qt &#8211; &#8220;Qt Hello World&#8221; и в качестве конфигураций сборки выбираем все цели для ARMEL и X86 (ведь мы планируем отлаживать как в эмуляторе так и на устройстве).</p>
<h2>3. Настройка и запуск приложения в локальном эмуляторе и на на устройстве через сеть (по WiFi в моем случае). </h2>
<p><p><a href="http://erudenko.com/wordpress/?p=309"><em>Click here to view the embedded video.</em></a></p><br />
Для сборки проекта Qt этого недостаточно, дело в том, что ESBox не знает о существовании официального Qt, который устанавливается в /opt/qt4-maemo5 в отличие от неофициального, который интегрируется в систему (раскидывается по разным каталогам, qmake допустим лежит в /usr/local/bin, include лежит в /usrt/include/qt4 и тд.). В принципе, поведение неофициального пакета Qt  &#8211; стандартное, но в таком случае тяжело иметь дело с несколькими версиями,видимо поэтому Qt-шники решили не раскидывать пакет по всей системе. Поправить это можно двумя методами, при создании проекта просто поменять все пути к Include и qmake, но можно сделать проще, а точнее сделать символические ссылки:<br />
для qmake (внимание у меня опечатка в комментариях на видео, там в пути вместо &#8220;dev&#8221; нужно писать &#8220;bin&#8221;, увы поправить не могу по техническим причинам):</p>
<blockquote><p>
ln -s /opt/qt4-maemo5/bin/qmake /usr/local/bin
</p></blockquote>
<p>проверяем, что qmake доступен без указания пути:</p>
<blockquote><p>
qmake
</p></blockquote>
<p>должна появиться подсказка для qmake, и в начале указан версия Qt, должна быть 4.6.2</p>
<p>для include:</p>
<blockquote><p>
ln -s /opt/qt4-maemo5/include  /usr/local/qt4
</p></blockquote>
<p>это нужно для ESBox.</p>
<p>Проделать эту операцию нужно для каждой цели сборки scratchbox (ARMEL и X86), чтоб не оказалось, что в терминале вы отлаживаетесь с одной версией Qt, а на устройстве с другой <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Вы помните, что для переключения цели в scratchbox нужно воспользоваться утилиткой &#8220;sb-menu&#8221;.</p>
<p>Потом собираем наше приложение для эмулятора (X86-develop) и создаем конфигурацию отладки (локальную). Запускаем, соглашаемся на приглашение запустить эмулятор. Вы увидите что программа остановилась на точке входа в &#8220;main&#8221; функцию и заработал HelloWorld. Все работает хорошо. Ура!!!</p>
<p>Теперь запустим отладку на устройстве. Сначала я решил продемонстрировать отладку по сети. Все что для этого нужно &#8211; это установить gdb сервер на устройстве (для отладки) и ssh server (и клиент тоже не помешает).<br />
Open SSH клиент и сервер можно установить с помощью этого метапакета: http://maemo.org/downloads/product/Maemo5/openssh/. Находятся он в репозитории http://repository.maemo.org/extras/. Как установить новый репозиторий вы можете подсмотреть в <a href="http://habrahabr.ru/blogs/nokia/85393/">моей статье.</a> Также можно зайти по ссылке на приложение и нажать кнопку &#8220;Install&#8221; прям на устройстве.</p>
<p>Установить gdb можно из репозиториев maemo прям на устройстве, находится он в репозиториях </p>
<blockquote><p>
deb http://repository.maemo.org/ fremantle/sdk free non-free<br />
deb http://repository.maemo.org/ fremantle/tools free non-free
</p></blockquote>
<p>Просто добавьте эти строки в файл /etc/apt/sources.list на устройстве (или через стандартный менеджер пакетов), для этого надо быть суперпользователем, чтоб перейти в этот режим на устройстве нужно ввести команду:</p>
<blockquote><p>
sudo gainroot
</p></blockquote>
<p>и  потом ввести:</p>
<blockquote><p>
apt-get update<br />
apt-get install gdb
</p></blockquote>
<p>Все это можно сделать через ssh, не обязательно писать это все руками на клавиатурке <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
<p>Второй путь &#8211; это вручную скачать пакет gdb и поставить его с помощью dpkg (я сделал именно так).<br />
Заходим и скачиваем на устройство по э<a href="http://maemo.org/packages/package_instance/view/fremantle_extras-devel_free_armel/gdb/6.8.50.20090417-0maemo2+0m5/">той ссылке пакет</a>.  И сохраните на устройстве. Потому в консоли (опять же можно по ssh)  зайдите туда и введите:</p>
<blockquote><p>
dpkg -i gdb_6.8.50.20090417-0maemo2+0m5_armel.deb
</p></blockquote>
<p>В scratchbox  GDB уже стоит.</p>
<p>В настройках ESBox создаем устройство и прописываем IP N900 в качестве &#8220;Host Name&#8221;. Создаем конфигурацию запуска на удаленном хосте (в нашем случае это N900)  выставляем способ доставки приложения SSH.<br />
Есть два вариант &#8211; SBRSH и SSH.<br />
SBRSH &#8211; это когда устройство монтируем папку с приложением у себя в файловой системе и с этого места запускает. Плюс: быстрее все происходит. Минус: устройство должно видеть ваш компьютер (для виртуальной системы должен стоять режим Bridge а не NAT или же перебросить порты) и на SDK-хосте должен стоять SSH сервер.<br />
SSH &#8211; проект копируется по SCP на N900 и оттуда запускается. Плюс: виртуальная машина может быть в режиме Bridge. Минус: немного медленнее.<br />
Я выбрал второй вариант, но вы можете выбирать сами, настройки там не сильно отличаются (правда в видео я сначала создал SBRSH,  но потом поменял на SSH).<br />
В качестве &#8220;Remote Connection&#8221;,  удаленного соединения, выбираем ранее настроенное устройство и запускаем на отладку.</p>
<p>При старте попросят ввести пароль для пользователя user. (Пароль &#8220;maemo&#8221;). Лучше кликнуть чекбокс &#8220;Save password&#8221;,  а то он много раз будет спрашивать пароль, напрягает <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>И вуаааалляяяя, запустилось и остановилось на точке останова, и на экране устройства появилось тоже приложение, что и на эмуляторе (поверьте мне на слово, а лучше проверьте у себя сами <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ).</p>
<h2>4. Настройка и запуск приложения на устройстве через USB соединение. </h2>
<p>Недостаток отладки по сети: медленно. Но на помощь на придет USB  соединение. По факту это тоже отладка по сети, так как создается сетевой интерфейс по USB, через который и отлаживается приложение. Но так, как он по факту &#8220;точка-точка&#8221;, то за счет этого и быстрее происходит.</p>
<p>Подготовка: необходимо поставить пакет pc-connectivity на устройстве, на виртуалке она уже стоит. Находится она в репозитории Extras. Очень мощный инструмент, унаследованный с предыдущих версий Maemo. Вкратце: он позволяет создавать профили соединений, для каждого профиля можно отдельно настроить соединения по USB, Wifi и Bluetooth. Да, отлаживаться можно и по bluetooth, но я не пробовал. Отладка по Wifi создает точку доступа с DHCP сервером. Полную документацию можно найти <a href="http://pc-connectivity.garage.maemo.org/2nd_edition/index.html">тут</a>. Но не пугайтесь очень большим объемом документации. В нашем случае ее читать не обязательно <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
<p><p><a href="http://erudenko.com/wordpress/?p=309"><em>Click here to view the embedded video.</em></a></p><br />
Необходимо запустить из строки состояния (то меню, которое появиться если нажать на ту область, где часики <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ) pc-connectivity и установить чекбокс &#8220;USB&#8221;, нажать  кнопку &#8220;Apply&#8221;  и подключить устройство по USB к компьютеру (скриншот сделать не получилось, сфоткал на другой телефон).<br />
<img src="http://erudenko.com/photo/N900/N900_PCN.jpg" alt="image"/><br />
После этого у нас появится новый интерфейс &#8220;usb&#8221; сетевой. По умолчанию все уже настроено и в качестве устройств в ESBox можно использовать уже предустановленное устройство USB  c с сетевым адресом 192.168.2.15, виртуальная таблица получит адрес 192.168.2.14. Но если у вас это адресное пространство уже занято, то придется поменять его на другое. Настройки PC-connectivity можно найти в стандартном меню настроек N900.</p>
<p>После этого проверяем соединение &#8211; заходим на устройство по SSH.<br />
Ну и все что осталось &#8211; это создать конфигурацию отладки для этого соединения и запустить непосредственно на устройстве.</p>
<h2>Заключение. </h2>
<p>Как вы можете видеть, все очень просто. Начать писать для Maemo5, имея при себе устройство или нет, не составляет особого труда. Но лично мне не нравиться, что я не могу использовать Qt-creator. Конечно можно код править даже на расшареных папках между виртуальной машиной и хостом, а потом руками все это запускать либо в эмуляторе или на устройстве и уже отлаживать в Gdb руками, или использовать ESBox. Но я уже сильно привык к Qt-Creator&#8217;у.<br />
Но решение есть &#8211; MADDE. Это совсем другая SDK и официальной поддержки еще нет (находится в Developer Preview) и в Qt-Creator&#8217;е нет поддержки MADDE (в официальном релизе), но все это обещают к релизу версии Qt 4.7. Но тем не менее, этим всем можно пользоваться прямо сейчас (используя main ветку из git-репозитория или использую последние &#8220;снимки&#8221;), причем на любой ОС без использования виртуальных машин. Qt-Creator в Gitorious в master ветке уже достаточно неплохо работает с MADDE. Сейчас в MADDE не хватает двух основных вещей &#8211; эмулятора и обновления пакетов. Если у вас есть устройство, на котором вы хотите отлаживаться и готовы устанавливать нужные пакеты руками, то MADDE вам подойдет.<br />
В следующей статье для разработчиков я опишу процесс настройки и работы с MADDE.</p>
<p>Всем приятного коддинга <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>135</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=309</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Как настроить Maemo 5(4) SDK и начать писать приложения под Windows/Linux/MacOS менее чем за полчаса!</title>
		<link>http://erudenko.com/wordpress/?p=297</link>
		<comments>http://erudenko.com/wordpress/?p=297#comments</comments>
		<pubDate>Thu, 18 Feb 2010 09:01:53 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[Russian]]></category>
		<category><![CDATA[maemo]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[fremantle]]></category>
		<category><![CDATA[maemo5]]></category>
		<category><![CDATA[manual]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=297</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=297">Как настроить Maemo 5(4) SDK и начать писать приложения под Windows/Linux/MacOS менее чем за полчаса!</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Как настроить Maemo 5(4) SDK]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=297">Как настроить Maemo 5(4) SDK и начать писать приложения под Windows/Linux/MacOS менее чем за полчаса!</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p><img src="http://upload.wikimedia.org/wikipedia/commons/thumb/2/27/Maemo_logo_color.svg/200px-Maemo_logo_color.svg.png" alt="image"/></p>
<p>Уже нет смысла, я думаю, объяснять что такое  Maemo и где он работает. Всем понятно, что это Linux, который сейчас работает на таблетках от Nokia и на новом Nokia N900. Но так как проект open-source, то думаю другим производителям ничто не мешает сделать свое устройство под этой платформой (кто знает, может появится HTC или Motorolla на базе Maemo).</p>
<p>Речь в этой статье пойдет о том как настроить окружение для разработки для Maemo.</p>
<p>Начнем с того, что сейчас существуют два типа SDK &#8211; текущий стабильный для Maemo5/4 (Fremantle/Diablo) и  новый SDK, который сейчас в бете &#8211; MADDE.</p>
<p>Ну давайте начнем со стабильного (относительно и спорно, позже покажу почему) и текущего &#8211; Fremantle (на момент написания статьи но был  &#8220;pre-final 2&#8243;, теперь в &#8220;final&#8221;). Он базируется на Diablo и поэтому процесс установки и нструменты те же. И если вам нужен Diablo &#8211; инструкция подойдет эта, а далее я буду говорить только о Fremantle, подозревая что по желанию можно использовать Diablo.</p>
<p>Хорошо, предположим, что мы выбрали SDK Fremantle (MADDE я посвящу последующие статьи). У этого SDK есть один недостаток &#8211; он моно-платформенный. Он работает только под Linux x86 (желательно debian based, но не обязательно). Для счастливый пользователей этой системы существует простой путь для установки SDK нужно скачать скрипт с <a href="http://www.forum.nokia.com/info/sw.nokia.com/id/c05693a1-265c-4c7f-a389-fc227db4c465/Maemo_5_SDK.html">этой</a> страницы и действовать согласно <a href="http://wiki.forum.nokia.com/index.php/How_to_install_Maemo_5_SDK_using_GUI_Installer">этой</a> инструкции.</p>
<p>Что же делать, если рабочая система у нас Windows(самая популярная)/Linux x64/MacOs? Не отчаивайтесь. У вас и тут есть выбор. Самый легкий путь &#8211; это скачать <a href="http://maemovmware.garage.maemo.org/2nd_edition/">отсюда</a> виртуальный образ с настроенным окружением и в нем работать. Все предельно просто &#8211; качаем, запускаем из-под VMWare, QEMU, VirtualBox. Там уже стоит ESBox и SDK. Если вы не знаете как установить систему в виртуальной машине, можно подсмотреть в этой статье далее.</p>
<p><img src="http://esbox.garage.maemo.org/2nd_edition/images/marca.jpg" alt="image"/><br />
Ну и последний вариант &#8211; если Вы хотите разрабатывать приложения на своей родной платформе &#8211; нет проблем! ESBox (забыл представить &#8211; это Eclipse+плагины для разработки под Maemo5/4) умеет работать с виртуальной машиной. То есть получается, что вы пишите код в ESBox, он собирает это в виртуальной машине и запускает там, а результат отображается опять же в вашей родной системе. Виртуальная система работает &#8220;в тени&#8221;. Идея прекрасна, не правда ли?</p>
<p>На деле все не так гладко в Windows, <b>под Mac OS и Linux все работает как надо</b>  (надеюсь в скором будущем для Windows все отмеченные мною баги будут исправленны). Я столкнулся с несколькими неприятными моментами, плюс часть документации, которую можно найти в разных местах создана не Нокиа, а open source community и иногда встречаются неточности и несоответствия версий</p>
<p>Вот в этой статье далее пойдет речь о том как установить Maemo SDK под Windows (будут замечания, если процесс будет отличатся от Linux, Mac OS вариантов) и более того, я при вас это сделаю менее чем за пол часа. Всё видео и нотации к ним под катом.</p>
<p>Да кстати, это все можно установить не только для разработки, но и для того чтобы познакомится с Maemo не имея реального устройства.</p>
<p><b>Некоторым кажется, что процесс утсановки сложен и много букв. В действительности не так, просто я постарался описать как можно подробней. В действительности достаточно посмотреть видео, и если что-то непонятно &#8211; прочитать описание к этому видео.</b></p>
<p><b>UPD:На момент написания статьи образ виртуально системы был &#8220;PreFinal2&#8243;, несколько дней назад вышла версия Final. Но инструкция остается полностью актуальна, так как для данного вида установки ничего не изменилось. Поменялось лишь содержимое образа виртуальной системы, с настроенным окружением maemo.</b></p>
<p>Порядок руководства такой: сначала видео, потом пояснения к нему и ссылки. Так что не надо их все запоминать, я их приведу после видео (советую смотреть в HD, ссылку привожу перед видео, как добавить HD-видео сразу сюда &#8211; не нашел).</p>
<h3>Итак шаг первы: установка и первичная настройка виртуальной машины:</h3>
<p><a href="http://www.youtube.com/watch?v=F6HcvRM2o6c&#038;hd=1">Сслыка на HD YouTube версию.</a><br />
<p><a href="http://erudenko.com/wordpress/?p=297"><em>Click here to view the embedded video.</em></a></p><br />
Последовательность действий такова:<br />
скачиваем Maemo Virtual Image с <a href="http://tablets-dev.nokia.com/maemo-dev-env-downloads.php">сайта</a> (при переходе по ссылке необходимо принять лицензионное соглашение). Скачиваем файл &#8220;Maemo_Ubuntu_Intrepid_Server_SDK_Virtual_Image.zip&#8221;. Это образ с некоторыми добавлениями, в частности:</p>
<blockquote><p>
       Ubuntu Server 8.10 Intrepid Ibex<br />
       Maemo Host PC Connectivity release without GUI applications<br />
       Installation wizards for virtualization performance tools<br />
       Installer for Official VMWare Tools<br />
       Installer for Open VMWare Tools<br />
       Installer for VirtuaBox GuestAdditions
</p></blockquote>
<p>Плюс там установлены некоторые патчи.</p>
<p>Далее заходим на сайт <a href="http://VirtualBox.org">VirtualBox</a> и в секции Download скачиваем установщик под Вашу платформу. Ну и соответственно устанавливаем его со всеми параметрами по умолчанию (осторожно: во время установки VirtualBox отвалятся на время сетевые интерфейсы).</p>
<p>Потом распаковываем скачанный виртуальный образ Ubuntu в удобное для вас место (zip формат поддерживается всеми ОС прям &#8220;из коробки&#8221;). </p>
<p>Запускаем VirtualBox и создаем новую виртуальную машину, в качестве диска подключаем только что скачанный образ.</p>
<p>Запускаем виртуальную машину: логин и пароль: maemo.</p>
<p>запускаем инструмент ~/install_guest_additions_server.sh командой:</p>
<blockquote><p>
    sudo /home/maemo/ToolsInstallers/install_guest_additions_server.sh
</p></blockquote>
<p>Далее отвечаем на все вопросы положительно и принимаем все лицензионные соглашения.<br />
После завершения процесса установки перезагружаем виртуальную машину командой:</p>
<blockquote><p>
    sudo reboot
</p></blockquote>
<h3>Шаг второй: установка и настройка ESbox+SDK для работы с виртуальной машиной.</h3>
<p><a href="http://www.youtube.com/watch?v=6wdMnw4VVd4&#038;hd=1">Ссылка на HD версию на YouTube.</a><br />
<p><a href="http://erudenko.com/wordpress/?p=297"><em>Click here to view the embedded video.</em></a></p></p>
<p>Заходим в настройки виртуальной машины и в секции &#8220;Сеть&#8221; меняем тип сетевого подключения с &#8220;NAT&#8221; на &#8220;Сетевой мост&#8221;.<br />
Вообще, нужно организовать кросс-шару между хост-системой и виртуальной системой. Схема шары такова:<br />
<img src="http://esbox.garage.maemo.org/2nd_edition/images/vm/shared_folders.png" alt="image"/></p>
<p>Мы маунтим workspace ESbox&#8217;a (на схеме &#8211; это &#8220;C:\maemo\shared&#8221;) на соответствующие папки на виртуальной машине, для того, чтобы SDK мог добраться до них для компиляции и запуска из виртуальной системы. Шара организована через smb-протокол.</p>
<p>Но для комфортной работы можно еще сделать обратную шару из виртуальной машины на хост машину, чтобы подключить заголовочные файлы из SDK и таким образом можно было их видеть из ESBox  и задействовать автозавершение. Это не обязательно, но удобно. </p>
<p>Если будет сетевое подключение через NAT на виртуальной машине, то придется делать перенаправление 22 порта, поэтому проще сделать &#8220;Bridge&#8221; сеть, таким образом виртуальная машина появится в сети как отдельный экземпляр. Это даст возможность по сети с другого компа вести разработку (например повесить жене на компьютер этот виртуальный образ, а самому на буке кодить, зачем мощностям простаивать <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  или удаленно работать с виртуальной машиной (вариантов много)).</p>
<p>НО стоит учесть один момент. Сеть может такое не позволить или если рутер не сильно умный, то передача данных между хостом и виртуальной машиной может спокойно идти через интернет (через провайдера) &#8211; даже при небольшом трафике в таком случае могут быть жуткие тормоза. Поэтому не отбрасываю и вариант использования NAT Networking, <a href="http://maemovmware.garage.maemo.org/2nd_edition/create_vbox_machine.html#portforwarding">инструкция по настройке перенаправлению портов можно найти здесь</a>. </p>
<p>Далее необходимо скачать ESbox с <a href="https://garage.maemo.org/frs/?group_id=192">этого сайта.</a>.<br />
Необходимо скачать два файла:</p>
<blockquote><p>
    esbox_2.0.0-R20091216-common.zip<br />
    esbox_2.0.0-R20091216-win32.win32.x86.zip &#8211; для Windows (или соответсвующий для вашей платформы).
</p></blockquote>
<p><b><i>R20091216</i></b> &#8211;  номер доступной версии на момент написания статьи, естественно нужно качать последнюю.</p>
<p>Первый архив &#8211; это плагины и фичи, а второй платформо-зависимые файлы (выполняемые и сопутствующие).<br />
Распаковываем оба файла в одну и ту же папку ( если например распаковать в C:\, то программа будет находиться в C:\ESBox), архив zip поддерживается всеми платформами без сторонних продуктов.</p>
<p>Запускаем распакованный ESBox и приступим к его первичной настройке.<br />
Сначала нас спросят, где находится наше рабочее пространство (workspace). Рекомендую указать C:\maemo\shared. (В видео выбран неправильный каталог, но в субтитрах написан правильный путь, я позже за кадром поменял путь к workspace&#8217;у).<br />
Ставим галочку, сообщая что это рабочее пространство по умолчанию, и больше не нужно спрашивать при запуске о его размещение.</p>
<p>Далее подключаем справку (не обязательно).<br />
Сначала подключается on-line репозиторий справки, параметры при заполнении:</p>
<blockquote><p>
   Name: Maemo Docs Libraray<br />
Host: library.maemodocs.nokia.com<br />
Path: /fremantle
</p></blockquote>
<p>Так же по желанию можно установить off-line помощь.<br />
Для этого добавляем новый репозиторий:</p>
<blockquote><p>
Location: http://maemoide.nokia.com/downloads/fremantle
</p></blockquote>
<p>Выбираем нужные пакеты (в моем случае все), принимаем лицензионное соглашение и устанавливаем.</p>
<p>После этого закрываем ESBox.</p>
<p>Следующее действие только для пользователей Windows &#8211;  установка X-server. Под Mac OS сервер идет &#8220;из коробки&#8221; и работает нормально (проверял). Для Linux необходимо установить Xephyr:</p>
<blockquote><p>
 sudo apt-get install xserver-xephyr
</p></blockquote>
<p>Под Windows у вас есть выбор между XServer&#8217;ами. Разработчики Maemo SDK предлагают Cygwin/X, я предлагаю XMing. Оба работают одинаково (одинаково неправильно, смотри следующую главу). </p>
<p>Чтобы установить Cygwin/X, необходимо зайти на сайт http://cygwin.org и скачать <a href="http://www.cygwin.com/setup.exe">файл по этой ссылке.</a></p>
<p>После этого запускаем инсталятор и добавляем три пакета: X11/xorg-server, X11/xinit, X11/xdpyinfo.<br />
Внимание для пользователей Windows 7. Cygwin/X версии 1.7 <a href="https://garage.maemo.org/tracker/index.php?func=detail&#038;aid=4897&#038;group_id=192&#038;atid=1420">падает из-за бага</a>. Он связан с composition расширением (об этом подробней в четвертой шаге).</p>
<p>Чтоб установить XMing, скачайте установщик с <a href="http://sourceforge.net/projects/xming/">sourceforge.net</a>. Запустите установщик и действуйте согласно инструкции (я оставил все параметры по умолчанию).</p>
<p>Как по мне, так XMing установить проще и быстрее.</p>
<p>Далее необходимо настроить виртуальную машину, идем в настройки ESbox->Build Machines и выбираем в списке виртуальных машин VirtualBox.</p>
<p>В первой вкладке нужно изменить путь к выполняемому файлу Virtual Box (убираем лишние символы &#8220;xVM &#8220;, если вы установили все по умолчанию, как я)  и выбираем из списка нашу виртуальную машину.<br />
Во второй вкладке настраиваем сетевые интерфейсы.<br />
Для этого запускаем виртуальную машину и заходим  на нее: логин/пароль &#8211; maemo/maemo.<br />
набираем команду:</p>
<blockquote><p>
 ifconfig
</p></blockquote>
<p>Команда выведет нам адрес виртуальной машины, а в выпадающем списке интерфейсов для хост машины, выбираем соответствующий IP адрес.<br />
И обязательно нажимаем кнопочку &#8220;Apply&#8221;.<br />
Далее щелкаем по ссылке сверху &#8220;Click here for maemo installers&#8221;.<br />
Сначала устанавливаем Scratchbox.<br />
Выбираем целевую платформу (Fremantle или Diablo). Соглашаемся на предложенный патч autoconfs&#8217;a,и перезагружаем виртуальную машину.</p>
<p>Опять щелкаем по этой ссылке и устанавливаем цели для Scratchbox (соответственно Fremantle или Diablo).<br />
Тут необходимо принять лицензионное соглашение.<br />
После установки целей будет предложено установить комерческие(закрытые) двоичные файлы от Nokia.<br />
Это необходимый шаг для Fremantle.<br />
Тут хитрое лицензионное соглашение, необходимо перейти по ссылке сверху, прочитать в броузере лицензионное соглашение, ввести код проверки и получить путь на deb-репозиторий. Вот этот путь нужно скопировать и ввести в соответствующее поле инсталятора.<br />
После этого уже устанавливаются нужные пакеты.</p>
<p>Настройки сетевых ресурсов пока не трогаем, с этого мы начнем в следующей главе.</p>
<h3>Шаг третий: окончание настройки и попытка собрать и отладить первое приложение.</h3>
<p>Внимание: следующее видео предполагает, что вы сделали сетевой доступ к  папке C:/maemo/shared и дали локальному пользователю права на изменение файлов.<br />
Сетевой ресурс должен быть организован по протоколу Samba.  Как это сделать на Windows/Linux/Mac Os вы можете легко найти в <a href="http://google.com">гугле</a>.<br />
<a href="http://www.youtube.com/watch?v=bboMlgeR300&#038;hd=1">Ссылка на HD версию на YouTube.</a><br />
<p><a href="http://erudenko.com/wordpress/?p=297"><em>Click here to view the embedded video.</em></a></p></p>
<p>Заходим в настройки виртуальной машины во вкладку &#8220;Shared Folders&#8221; (смотри схемку выше). Проверяем пути и нажимаем кнопочку &#8220;Validate Machine&#8221;.<br />
ESbox попробует смонтировать C:\Maemo\shared в соответствующие каталоги на виртуальной машине и спросит имя пользователя и пароль для подключения (он их запомнит и больше спрашивать не будет).<br />
Вот Mac OS и  Linux все должно пройти без ошибок.<br />
На Windows он выдаст сообщение, что все смонтировалось хорошо, но недоступно. Игнорируем это сообщение. Ну и потом выскочит исключение. Баг номер 1. Не обращаем на это внимание, просто проверим, что в Windows появилось два диска T и S (или другие, если вы изменили настройки).</p>
<p>Дальше создаем новый проект Maemo C++ -> Hello World.<br />
ESbox попросит проверить установленные зависимости. Если вы запускаете первый раз, то он поставит несколько пакетов (у меня уже стоит).</p>
<p>Запускаем среду maemo, нажав на кнопочку с логотипом maemo.  Будет предложено убрать не поддерживаемые параметры для запуска X-server (я пробовал ни на что они не влияют, но лучше согласиться ).<br />
Если вы установили XMing по моей рекомендации, у вас ничего не запустится, то ничего страшного. Все равно работать оно как надо не будет, просто посмотрите видео. А инструкции по настройке ESbox  для работы c XMing читайте в следующей главе.</p>
<p>На видео там куча значков сбилась в левом углу (у меня уже установлены виджеты), у вас будет только значок твиттера. Нажав на него снизу будет полоса прокрутки (это броузер запустится).<br />
Это баг номер 2, как его обойти я опишу в следующей главе. Этот баг проявляется только под Windows, на Linux и Mac OS у вас все красиво должно отображаться (если нет, то смотри в конце этого шага).</p>
<p>Как вы видите, оконный менеджер не работает как нужно. Приложение &#8220;погода&#8221; показывается без заголовка.</p>
<p>Выключаем среду Maemo и закрываем руками X-server(еще один баг, ESBox не может закрыть X-server).</p>
<p>Теперь пытаемся собрать приложение, в качестве цели используем выбранный FREMANTLE_X86(Debug). И опс, ничего не происходит. У нас ошибка в консоли (не может найти скрипт) и исключение плагина (еще баг).<br />
Не переживайте. Просто нужно выбрать другую цель сборки и все заработает, после этого будет собираться и цель, которая не собиралась. Я думаю это связано с тем, что не инициализируются какие-то начальные значения, а при переключении целей они заполняются.<br />
После долгой отработки autoconf&#8217;a мы готовы запустить наше приложение.</p>
<p>Стартуем среду Maemo и запускаем в режиме отладки наше приложение.<br />
Приложение остановится в точке останова, значит gdb работает как надо, но после выполнения на экране черным-черно. Так и должно быть. Это приложение имеет только один элемент управления в заголовке окна, но так как заголовков у нас нет(не запустился оконный менеджер, но об этом позже), то его не видно.</p>
<p>Для пользователей Mac OS и Linux все должно уже работать и правильно отображаться. Если у вас отображается также, то проверьте, чтоб не стояло опции -extension Composite при запуске X-server. Эта опция была в Diablo, а в Fremantle она не нужна.</p>
<h3>Шаг четвертый, окончательный: настройка XMing, обходим баги и отлаживаем наше приложение.</h3>
<p><a href="http://www.youtube.com/watch?v=y_c4gNrJPEs&#038;hd=1">Ссылка на HD версию на YouTube.</a><br />
<p><a href="http://erudenko.com/wordpress/?p=297"><em>Click here to view the embedded video.</em></a></p></p>
<p>Сначала инструкция для тех, кто меня послушал и поставил XMing.<br />
Заходим в настройки ESbox->X Server и меняем значения:</p>
<blockquote><p>
 Command template to launch server: &#8220;C:\\Program Files\\XMing\\XMing.exe&#8221;<br />
Additional PAth entries for server: &#8220;&#8221;C:\\Program Files\\XMing&#8221;
</p></blockquote>
<p>Теперь для всех видов иксов нужно дописать такие параметры:</p>
<blockquote><p>
+extension Composite +extension &#8220;Generic Events&#8221;
</p></blockquote>
<p>Запустим, должен запустится XMing.</p>
<p>Поставьте на паузу видео и послушайте немножко мои рассуждения.</p>
<p>Теперь разберемся, почему не отображается все правильно.<br />
С Cygwin/X есть проблема, что matchbox (оконный менеджер на maemo) не может распознать, что установлено расширение composite на X-server. И не запускается. Результат &#8211; сбившиеся иконки и нет заголовков и всего прочего. <a href="https://garage.maemo.org/tracker/index.php?func=detail&#038;aid=4897&#038;group_id=192&#038;atid=1420">Баг этот известен, но немного другой. Суть такова, что нужно проверить поддержку Cygwin 1.7 с Fremantle SDK</a>.</p>
<p>Вроде написано <a href="http://esbox.garage.maemo.org/2nd_edition/installation_x_setup_windows.html">,что вместо Cygwin 1.7 лучше использовать версию 1.5.25-15</a>. Но старые версии Cygwin нельзя установить официальным установщиком (самая старая версия Xorg-server в официальном репозитории &#8211; <a href="http://cygwin.com/packages/xorg-server/">xorg-server-1.6.5-1</a>), а найти и скачать по быстрому у меня не удалось. Да и не факт что это решит проблему (описано было в багах падение, а не отсутствие поддержки composite extension). Если кто попробует, отпишитесь пожалуйста об успехах.</p>
<p>Второй вариант &#8211; это XMing. Тут у нас не поддерживается Generic Events (XGE) и он вообще падает с включенным расширением Composition. Без ошибок, просто молча падает. Дебажить его нет желания, тем более, что разработка его ушла уже очень далеко вперед, и судя по анонсам, в версии 7.5.0.14  это уже поправлено (последняя версия 7.5.0.16). Может и проблему с Composite Extension тоже поправили. Но в публичный доступ выкладываются версии с большим опозданием(сейчас лежит версия 6.9.0.31), и чтобы получить доступ к последним версиям, нужно получить донорский код (для этого нужно внести пожертвование в проект). Если бы я пользовался X сервером под Windows, то обязательно бы это сделал. Но моя основная платформа &#8211; Mac Os. Опять же, если у кого появится возможность проверить на последнем XMing &#8211;  отпишитесь, очень интересно.<br />
Да ,кстати, в XMing можно добавить опцию -clipboard, чтоб задействовать буфер обмена.<br />
Ну а теперь как же сделать, чтоб все работало.</p>
<p>Схема такая. Среда Maemo, запускается на виртуальной машине, но экран она должна использовать не тот, который ему передаст ESBox, а локальный. Локально будет запущен Xephyr (этот X-server, который встраивается в другой XServer (вложены, nested)). Экраном для XServer будет уже XMing/Cygwin. Получается между maemo средой и виндовым XServer теперь вставляем Xephyr на виртуальной машине.</p>
<p>Сделать это достаточно несложно.<br />
Теперь отпустите паузу с видео, поехали дальше настраивать.</p>
<p>Заходим на виртуальную машину и устанавливаем Xephyr:</p>
<blockquote><p>
sudo apt-get install xserver-xephyr
</p></blockquote>
<p>Потом создаем скрипт для его запуска:</p>
<blockquote><p>
touch ./start1.sh<br />
chmod a+x ./start1.sh<br />
vim ./start1.sh
</p></blockquote>
<p>Естественно вместо vim можете использовать другой редактор: nano, mcedit.</p>
<p>Содержание скрипта будет выглядеть таким образом:</p>
<blockquote><p>
#!/bin/bash<br />
export DISPLAY=192.168.1.152:2<br />
Xephyr :2 -host-cursor -screen 800x600x16 -dpi 96 -ac -kb
</p></blockquote>
<p>Вместо 192.168.1.152 &#8211; укажите айпишник Вашей хост машины.<br />
И запускаем скрипт, он должен выругаться, что не может подключится к экрану.<br />
Запускаем XServer из-под ESbox и запускаем скрипт снова.<br />
Должен появится вывод как у меня в консоль.<br />
Чтоб завершить работу Xephyr, нажмите Ctr+C (для переключения между консолями в виртуальной машине, используйте комбинацию Alt+<стрелка врпаво/влево>).</p>
<p>Теперь нам нужно поправить зайти в scratchbox и поправить там скрипт запуска среды maemo,  чтоб он отображался в локальном Xephyr-сервера, а не в нашем Xming.</p>
<blockquote><p>
/scratchbox/login<br />
vim /usr/bin/af-sb-init.sh
</p></blockquote>
<p>в начале добавляем такую строку</p>
<blockquote><p>
export DISPLAY=127.0.0.1:2
</p></blockquote>
<p>Ну теперь запускаем Xming на Windows, запускаем наш скрипт для Xephyr на виртуальной машине и запускаем среду Maemo из ESbox.</p>
<p>Вот у нас почти рабочая Maemo (некоторые приложения все же не запустились, например браузер и аудиоплеер).</p>
<p>Теперь давайте запусти наш helloworld в режиме отладки, тут тоже немножко нужно изменить параметры. В переменные окружения нужно добавить такую строку:</p>
<blockquote><p>
DISPLAY=127.0.0.1:2
</p></blockquote>
<p>Для того, чтоб наше приложение тоже отображалось в Xephyr а не на XMing.<br />
Как вы видите все работает как надо.</p>
<p>Кстати вы можете в менеджере приложений наставить всякого софта, как это сделал я и таким образом познакомится с системой.</p>
<h3>Заключение.</h3>
<p>Поздравляю Вас, если вы дошли до заключения.<br />
Конечно мы получили не идеальное окружение, но оно работает.<br />
Из основных недостатков:<br />
при компиляции используется мощность виртуальной машины, а не полная мощность всего компьютера<br />
отображение не так красиво и быстро работает, как должно<br />
достаточно сложно настроить (общее время на видео 25 минут, но оно не учитывает время на загрузку пакетов)<br />
среда Eclipse(ESBox) сама по себе не лишена недостатков (скорость, память, ошибки)</p>
<p>Но есть альтернатива &#8211; это MADDE. Эта SDK еще находится в разработке, но ее уже можно использовать.<br />
Она кросс-платформенная. Требует минимум установки и существует поддержка этого SDK в Qt-creator&#8217;e (но пока экспериментально). На сегодняшний момент на MADDE можно писать приложения, но только имея реальное устройство. О том как установить и пользоваться MADDE я расскажу в последующих статьях.</p>
<p>В следующей статье я расскажу как написать Qt-приложени и собрать пакет, чтоб другие могли его установить.</p>
<p>Также жду ваших советов и соображений по поводу решения проблемы с XMing и Cygwin/X.</p>
<p>Приятного вам знакомства с Maemo.</p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>253</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=297</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Qt-creators&#8217;s shortcut reference card.</title>
		<link>http://erudenko.com/wordpress/?p=274</link>
		<comments>http://erudenko.com/wordpress/?p=274#comments</comments>
		<pubDate>Tue, 12 Jan 2010 17:37:50 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Qt-creator]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[manual]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[reference]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=274</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=274">Qt-creators&#8217;s shortcut reference card.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Qt-creators&#8217;s shortcut reference card. is]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=274">Qt-creators&#8217;s shortcut reference card.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p><a href="http://erudenko.com/wordpress/?p=257">In previous post </a> I wrote how to create plugins for Qt-creator. In this mini post I&#8217;d like to share one more helpful information about Qt-creator.<br />
Good guys form <a href="http://www.kdab.com">KDAB</a> created and shared  <a href="http://www.kdab.com/index.php?option=com_content&#038;view=article&#038;id=126"> Qt Creator reference card</a>. This nice reference card helps you to easily adapt to new IDE. </p>
<p>Links for download:<br />
<a href="http://www.kdab.com/images/free_downloads/qtcreator.pdf">Qt Creator Reference Card &#8211; A4</a><br />
<a href="http://www.kdab.com/images/free_downloads/qtcreator-letter.pdf">Qt Creator Reference Card &#8211; US Letter</a><br />
<a href="http://www.kdab.com/images/free_downloads/qtcreator-mac.pdf">Qt Creator Reference Card Mac  &#8211; A4</a><br />
<a href="http://www.kdab.com/images/free_downloads/qtcreator-mac-letter.pdf">Qt Creator Reference Card Mac  &#8211; US Letter</a><br />
<div id="attachment_267" class="wp-caption alignleft" style="width: 310px"><a href="http://erudenko.com/wordpress/wp-content/uploads/2010/01/qtcreator.png"><img src="http://erudenko.com/wordpress/wp-content/uploads/2010/01/qtcreator-300x212.png" alt="qtcreator reference card" title="qtcreator reference card" width="300" height="212" class="size-medium wp-image-267" /></a><p class="wp-caption-text">qtcreator reference card</p></div><br />
You can click to picture to view how it&#8217;s looks.</p>
<p>I wish you a fan development with Qt-creator.</p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>16</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=274</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Qt-creator, шпаргалка по комбинациям клавиш.</title>
		<link>http://erudenko.com/wordpress/?p=262</link>
		<comments>http://erudenko.com/wordpress/?p=262#comments</comments>
		<pubDate>Tue, 12 Jan 2010 17:27:04 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[Qt-creator]]></category>
		<category><![CDATA[Russian]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[manual]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[reference]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=262</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=262">Qt-creator, шпаргалка по комбинациям клавиш.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Qt-creator, шпаргалка по комбинациям клавиш.]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=262">Qt-creator, шпаргалка по комбинациям клавиш.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p><a href="http://erudenko.com/wordpress/?p=248">В предыдущем посте </a> я отписался о том как создавать свои плагины для Qt-creator. В этом мини посте хочу продолжить тему и поделится находкой.<br />
Хорошие ребята из <a href="http://www.kdab.com">KDAB</a> создали и выложили <a href="http://www.kdab.com/index.php?option=com_content&#038;view=article&#038;id=126"> Qt Creator reference card</a>. Шпаргалка по IDE, которая поможет очень быстро адаптироваться  к новой среде.</p>
<p>Ссылки для скачивания:<br />
<a href="http://www.kdab.com/images/free_downloads/qtcreator.pdf">Qt Creator Reference Card &#8211; A4</a><br />
<a href="http://www.kdab.com/images/free_downloads/qtcreator-letter.pdf">Qt Creator Reference Card &#8211; US Letter</a><br />
<a href="http://www.kdab.com/images/free_downloads/qtcreator-mac.pdf">Qt Creator Reference Card Mac  &#8211; A4</a><br />
<a href="http://www.kdab.com/images/free_downloads/qtcreator-mac-letter.pdf">Qt Creator Reference Card Mac  &#8211; US Letter</a><br />
<div id="attachment_267" class="wp-caption alignleft" style="width: 310px"><a href="http://erudenko.com/wordpress/wp-content/uploads/2010/01/qtcreator.png"><img src="http://erudenko.com/wordpress/wp-content/uploads/2010/01/qtcreator-300x212.png" alt="qtcreator reference card" title="qtcreator reference card" width="300" height="212" class="size-medium wp-image-267" /></a><p class="wp-caption-text">qtcreator reference card</p></div><br />
Кликнув по картинке слева можно посмотреть как это выглядит на примере &#8220;Qt Creator Reference Card &#8211; A4&#8243;.</p>
<p>Всем приятной работы в Qt-creator&#8217;e.</p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>18</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=262</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How-to write your own plugin for Qt-Creator.</title>
		<link>http://erudenko.com/wordpress/?p=257</link>
		<comments>http://erudenko.com/wordpress/?p=257#comments</comments>
		<pubDate>Tue, 12 Jan 2010 16:48:44 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Qt-creator]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[plug-in]]></category>
		<category><![CDATA[Qt]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=257</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=257">How-to write your own plugin for Qt-Creator.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
How-to write your own plugin]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=257">How-to write your own plugin for Qt-Creator.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>Qt-creator is rather new and extremely dynamic growing project. The main benefits: cross-platform, suitable, fast and scalable. </p>
<p><a href="http://qt.nokia.com/products/developer-tools">It&#8217;s a link to official page of project.</a><br />
Small video preview:<br />
<p><a href="http://erudenko.com/wordpress/?p=257"><em>Click here to view the embedded video.</em></a></p><br />
<a href="http://qt.nokia.com/files/pdf/qt-creator-1.3-whitepaper">Qt-creator&#8217;s whitepaper.</a><br />
<a href="ftp://ftp.qt.nokia.com/qtcreator/snapshots/latest"> Here you can download latest snapshots. </a><br />
Manual about writing plugins inside (traffic warning, 2.5Mb will be loaded).</p>
<p>But the main benefit, is that it open source. You can download it and look inside or maybe improve. Also you can become a contributor of Qt-Creator, more info on <a href="http://qt.gitorious.org/qt-creator/qt-creator">Gitorious&#8217;s project page.</a>.</p>
<p>Guys from vcreatelogic wrote the good manual about writing plugins for Qt-creator. This manual is very simple, organised step-by-step. There are a lot of pictures an examples.  I hope to see more manuals like this.<br />
Vcreatelogiс site &#8211; http://www.vcreatelogic.com/, and the link <a href="http://www.vcreatelogic.com/resources/downloads/">to download the manual &#8211; http://www.vcreatelogic.com/resources/downloads</a>. You need to click on &#8220;Other Downloads&#8221; tab, following this link.</p>
<p>You can preview this document in this window:<br />
<iframe class='pdf-ppt-viewer' src='http://docs.google.com/gview?url=http://erudenko.com/doc/develop/qt/Writing-Qt-Creator-Plugins.pdf&embedded=true' style='width:800px; height:800px;' frameborder='0'></iframe></p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>41</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=257</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Как написать свой плагин для Qt-creator.</title>
		<link>http://erudenko.com/wordpress/?p=248</link>
		<comments>http://erudenko.com/wordpress/?p=248#comments</comments>
		<pubDate>Tue, 12 Jan 2010 16:24:44 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[Qt-creator]]></category>
		<category><![CDATA[Russian]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[plug-in]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=248</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=248">Как написать свой плагин для Qt-creator.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Как написать свой плагин для]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=248">Как написать свой плагин для Qt-creator.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>Qt-creator это очень динамически развивающийся проект. Он кросс-платформенный, удобный, быстрый и хорошо настраиваемый.</p>
<p><a href="http://qt.nokia.com/products/developer-tools">Вот ссылка на официальную страницу проекта.</a><br />
Небольшое видео превью:<br />
<p><a href="http://erudenko.com/wordpress/?p=248"><em>Click here to view the embedded video.</em></a></p><br />
<a href="http://qt.nokia.com/files/pdf/qt-creator-1.3-whitepaper">Презентация по Qt-creator.</a><br />
<a href="ftp://ftp.qt.nokia.com/qtcreator/snapshots/latest"> Вот тут можно скачать последние snapshor&#8217;ы.</a><br />
Инструкцию по написанию плагина смотри внутри поста (осторожно, будет загружено 2,5 Мб).</p>
<p>Но самое главное, что проект является Open Source. Вы можете скачать исходники и посмотреть что там внутри. Также вы можете принять участие в разработке самого проекта на <a href="http://qt.gitorious.org/qt-creator/qt-creator">Gitorious</a>.</p>
<p>Товарищи из vcreatelogic написали очень хороший документ по написанию плагинов для Qt-Creator. Очень доступно, пошагово  и логично. Есть много иллюстраций  и примеров. Эх, если бы все так писали документацию.<br />
Сайт vcreatelogiс  &#8211; http://www.vcreatelogic.com/, а вот ссылка <a href="http://www.vcreatelogic.com/resources/downloads/">для скачивания документа &#8211; http://www.vcreatelogic.com/resources/downloads</a>. По ссылке необходимо  нажать вкладку &#8220;Other Downloads&#8221;.</p>
<p>Проглядеть его можно вот в этом окошке:<br />
<iframe class='pdf-ppt-viewer' src='http://docs.google.com/gview?url=http://erudenko.com/doc/develop/qt/Writing-Qt-Creator-Plugins.pdf&embedded=true' style='width:800px; height:800px;' frameborder='0'></iframe></p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>279</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=248</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Я добавил свою фичу в Qt-creator. Мой первый опыт.</title>
		<link>http://erudenko.com/wordpress/?p=241</link>
		<comments>http://erudenko.com/wordpress/?p=241#comments</comments>
		<pubDate>Wed, 30 Dec 2009 14:19:02 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[Qt-creator]]></category>
		<category><![CDATA[Russian]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[cpp]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=241</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=241">Я добавил свою фичу в Qt-creator. Мой первый опыт.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Я добавил свою фичу в]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=241">Я добавил свою фичу в Qt-creator. Мой первый опыт.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>Всем привет. Пару дней назад я начал немного &#8220;похачивать&#8221; Qt-creator. Чтобы понять в общих чертах внутренности прилось потратить вечер. Еще один вечер ушел чтобы понять как реализовать эту фичу. Ну и в конечном итоге реализация заняла около часа.</p>
<p>Смысл этой фичи заключается в том, что теперь можно с помощью соотвественного переключателя соеденить деревья исходных файлов и заголовчных файлов. Мне было неудобно иметь два дерева &#8211; одно для заголовочных файлов &#8211; другое для исходных, и это сподвинуло меня реализовать эту маленьку переделку.<br />
Результаты можно посмотреть в моем <a href="http://qt.gitorious.org/qt-creator/qt-creator/merge_requests/2159"> &#8220;merge request&#8221; на gitorious&#8217;е </a>.</p>
<p>Вот небольшая видео-демка, демонстрирующая мою фичу.</p>
<p><a href="http://erudenko.com/wordpress/?p=241"><em>Click here to view the embedded video.</em></a></p>
<p>Я поменял калсс FolderNode, теперь в нем есть свойство FileType contentType(). Это свойство определяет тип содержимого папки (исходники, заголовочные файлы, ресурси и тд.). Еще я добавил свойство excludeFolderType в FlatMode. Это свойство служит для того, чтоб исключить все папки, у которых контент соостветсвующего типа, из модели со всеми наследниками.</p>
<p>Зачем мне это было нужно.<br />
1. Хотелось понять как устроен Qt-creator.<br />
2. Повысить свои навыки (поучится на чужом коде).<br />
3. Помочь сделать Qt-creator лучше.</p>
<p>Дальше планирую реализовать еще парочку небольших улучшений:<br />
1. Панель файловой системы сделать древовидной.<br />
2. Состояние файла в проекте в системе контроля версий. </p>
<p>P.S:Это был мой первый опыт работы с git и gitorious.</p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>23</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=241</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://erudenko.com/video/qtcreator/QtCreatorMyFeature.mov" length="4604682" type="video/quicktime" />
		</item>
		<item>
		<title>I added new feature to Qt-creator.</title>
		<link>http://erudenko.com/wordpress/?p=205</link>
		<comments>http://erudenko.com/wordpress/?p=205#comments</comments>
		<pubDate>Wed, 30 Dec 2009 14:08:01 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Qt-creator]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[Qt]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=205</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=205">I added new feature to Qt-creator.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
I added new feature to]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=205">I added new feature to Qt-creator.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>Hello. I started qt-creator hacking two days ago. It took one evening to understand internal basics and one evening to decide hw to realise this feature. And so one hour to implement it.</p>
<p>You can see results in my <a href="http://qt.gitorious.org/qt-creator/qt-creator/merge_requests/2159"> &#8220;merge request&#8221; on gitorious </a>.</p>
<p>I recorded small video to show this feature.<br />
<p><a href="http://erudenko.com/wordpress/?p=205"><em>Click here to view the embedded video.</em></a></p></p>
<p>I changed FolderNode class, now it has property FileType contentType(). This property represent content type of folder. And added excludeFolderType property to FlatMode. This property exclude Folder with children with appropriate type from model.</p>
<p>Why I did it:<br />
1. I&#8217;d like to understand internals of Qt-creator.<br />
2. Got some experiences and skill.<br />
3. Help to make Qt-creator better.</p>
<p>Also I planing to add version control system status to project tree and Tree view of File system view plane.<br />
Hope to see this feature in master branch in near future.</p>
<p>P.S.: It was my first experience with gitorious.</p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>10</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=205</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://erudenko.com/video/qtcreator/QtCreatorMyFeature.mov" length="4604682" type="video/quicktime" />
		</item>
		<item>
		<title>Private slot implementation in pimpl pattern by Qt-way.</title>
		<link>http://erudenko.com/wordpress/?p=191</link>
		<comments>http://erudenko.com/wordpress/?p=191#comments</comments>
		<pubDate>Fri, 27 Nov 2009 10:45:47 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Qt embedded]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Pimpl]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[Q_D]]></category>
		<category><![CDATA[Q_Q]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=191</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=191">Private slot implementation in pimpl pattern by Qt-way.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Private slot implementation in pimpl]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=191">Private slot implementation in pimpl pattern by Qt-way.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<h1>Introduction.</h1>
<p>Some time before I wrote about <a href="http://erudenko.com/wordpress/?p=113"> pimp pattern by Qt-way</a>. In that post I was trying to show you the good way of using pimpl pattern, and use it at all. Especially when you implement your own library. Binary compatibility is good idea and d-pointers help to make it easily. Now I&#8217;ll try to extend you knowledges about this pattern, and show you new useful tool for making d-pointers better and more flexible. The next post is finally will close the pimpl topic: it will be about shared d-pointers and implicit sharing. But this topic is about private slots, the mechanism, that common used by Qt classes. </p>
<h1>What is it? And why to use it?</h1>
<p>Private slot is extension of d-pointers. Private slots give you way to realize slots in private class, even if private class is not QObject ( it&#8217;s not QObject almast in all classes ). But public class have to be QObject. Really the slot is not Private&#8217;s class slot, it is part of public class.<br />
Why we need slot in private class? Let&#8217;s look at some example. There is exists QAbstractScrollArea class.It&#8217;s simply displays it&#8217;s view<br />
port widget, and move it, if it has large geometry. QAbstractScrollAreaPrivate has two QScrollBars to make opportunity to user move viewport&#8217;s widget. Ok, and what to do when user changed scrollbar&#8217;s value ? In common way we need to connect appropriate signal of scrollbar to slot of our class, that implement necessary behaviour (scroll in our case). But this slots will became available outside our class in this case. It&#8217;s not good idea to show private implementation outside. The other possible solution is to make private class derived from QObject. Don&#8217;t do this (you have very heavy reasons to do it, and private slots is not one of them)!!!<br />
Don&#8217;t worry, Trolls made a grade solution &#8211; private slots! This is very simple and flexible way to resolve this issue.</p>
<h1>How does it work?</h1>
<p>To implement private slot there is exists Q_PRIVATE_SLO macros. As usual, let&#8217;s look inside this macro:</p>
<pre name="code" class="cpp:nogutter">
# define Q_PRIVATE_SLOT(d, signature)
</pre>
<p>Wow!!! it&#8217; empty. Why? Where is our macros&#8217;s definition? Hmmmm. The real man doesn&#8217;t afraid to come up against an obstacle. That&#8217;s why let&#8217;s look inside Qt&#8217;s moc preprocessor&#8217;s source code. The internal model of moc is looks like any lexer parser. But It&#8217;s not look like it made by QLALR, yacc or something else. I know that Trolls used QLALR ( their internal software ) to generate parsers &#8211; Qt Script Engine, QXMLStreamReader and maybe something else. But not moc. I&#8217;m not very strong with parsers, and it&#8217;s not our target ( at this moment <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ), that&#8217;s why I&#8217;ll only notice you about our research on Q_PRIVATE_SLOT macros.<br />
Tokens are generated by generate_keywords. You can find it in util subfolder of moc&#8217;s source folder.<br />
The output of this tool is array of such structures:</p>
<pre name="code" class="cpp:nogutter">
static const struct
{
   Token token;
   short next;
   char defchar;
   short defnext;
   Token ident;
}
</pre>
<p>Here are records about slots, signals and our private signal:</p>
<pre name="code" class="cpp:nogutter">
    {Q_SIGNAL_TOKEN, 0, 83, 470, CHARACTER},
    {Q_SIGNALS_TOKEN, 0, 0, 0, CHARACTER},
    {Q_SLOT_TOKEN, 0, 83, 474, CHARACTER},
    {Q_SLOTS_TOKEN, 0, 0, 0, CHARACTER},
    {Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER},
</pre>
<p>Now we know that tokenizer generates token Q_PRIVATE_SLOT_TOKEN for our macros during parsing of code. </p>
<p>here it is in  token.cpp:</p>
<pre name="code" class="cpp:nogutter">
        case Q_PRIVATE_SLOT_TOKEN: return "Q_PRIVATE_SLOT_TOKEN";
</pre>
<p>End then let&#8217;s find logic of parser. What parser has doing when met this token. This implementation is in  MOC::parse() method:</p>
<pre name="code" class="cpp:nogutter">
              case Q_PRIVATE_SLOT_TOKEN:
                    parseSlotInPrivate(&#038;def, access);
                    break;
</pre>
<p>Yes! We have found it!<br />
the parseSlotInPrivate method is what we have been looking for. Let&#8217;s look at definition:</p>
<pre name="code" class="cpp:nogutter">
void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access)
{
    next(LPAREN);
    FunctionDef funcDef;
    next(IDENTIFIER);
    funcDef.inPrivateClass = lexem();
    // also allow void functions
    if (test(LPAREN)) {
        next(RPAREN);
        funcDef.inPrivateClass += "()";
    }
    next(COMMA);
    funcDef.access = access;
    parseFunction(&#038;funcDef, true);
    def->slotList += funcDef;
    while (funcDef.arguments.size() > 0 &#038;&#038; funcDef.arguments.last().isDefault) {
        funcDef.wasCloned = true;
        funcDef.arguments.removeLast();
        def->slotList += funcDef;
    }
}
</pre>
<p>It&#8217;s all clear and rather simple.  As you can see, this function is fills funcDef class/struct with appropriate values and adds this funvDef to regular slot List, like for normal slot does. And after moc did it, preprocessor replaced this macro with empty string regarding macros definition. And when compile build it, there is nothing left. But the slot&#8217;s meta definition has been realized in moc_.cpp file.<br />
Very nice approach. Also you have opportunity to extend moc&#8217;s preprocessing functionality by hacking it <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
Ok. Now we know how it works, let&#8217;s look how to use it.</p>
<h1>How to use it in your code?</h1>
<p>It&#8217;s totally simple. Let&#8217;s extend <a href="http://erudenko.com/wordpress/?p=151">my previous example.</a><br />
1. Let&#8217;s make new method void _q_boo() in  MyClassPrivare class:</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClass);
public:
	MyClassPrivate();
	virtual ~MyClassPrivate();

	void foo();
	void _q_boo();
	int i;
	MyClass * q_ptr;
};
</pre>
<p>definition is in myclass.cpp looks like:</p>
<pre name="code" class="cpp:nogutter">
void MyClassPrivate::_q_boo()
{
	qDebug()&lt;&lt;i;
	QCoreApplication::exit(1);
}
</pre>
<p>Don&#8217;t forget to include QDebug and QCoreApplication headers.<br />
Some words about strange name _q_boo. It&#8217;s Qt&#8217;s naming rule for private slots. Name have to start with &#8220;_q_&#8221;. In this case it&#8217;s easy to recognize it in class&#8217;s declaration and definition.<br />
I added QCoreApplication::exit(1) to exit application when slot will execute. But keep in mind that is not a good decision at all. It&#8217;s only for testing and demonstrationg of our library.<br />
2. To make it more realistic ( in other case it&#8217;s too simple ) let&#8217;s invoke this slot from derived class.We have to declare macros in classes declaration:</p>
<pre name="code" class="cpp:nogutter">
	Q_PRIVATE_SLOT(d_func(),void _q_boo());
</pre>
<p>Regarding previous research about moc, we can explain that we need two arguments: first &#8211; target object, second &#8211; target method.</p>
<p>3. Let&#8217;s try to build our project:</p>
<pre name="code" class="cpp:nogutter">
moc_myclassderived.cpp: In member function ‘virtual int MyClassDerived::qt_metacall(QMetaObject::Call, int, void**)’:
moc_myclassderived.cpp:70: error: invalid use of incomplete type ‘struct MyClassDerivedPrivate’
myclassderived.h:5: error: forward declaration of ‘struct MyClassDerivedPrivate’
</pre>
<p>Don&#8217;t be afraid. That all ok. Moc doesn&#8217;t know anything about our private class, that&#8217;s why when it generates the moc file it only generate code regarding parsed .h file without checking cpp model at all. And it includes only header, that was target of moc generation process. myclassderived.h in our case. And there is only forward declaration in private header. But we unable to say to moc compiler to add extra header to include section.<br />
The generated moc file &#8220;moc_myclassderived.cpp&#8221; is simply extension to our myclassderived.cpp file. That&#8217;s why it&#8217;s save to add it at end of .cpp file. From this place the parivate class is accessible, because we have included it&#8217;s header at the top of .cpp file.</p>
<pre name="code" class="cpp:nogutter">
..................
#include "moc_myclassderived.cpp"
</pre>
<p>Let&#8217;s build project one more. O-o-o-u. The same error <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> . Don&#8217;t be despairing of success ! Simply run command &#8220;make distclean&#8221; and build it again.<br />
That&#8217;s all. O, no! I forgot about example. Ok, let&#8217;s go next.<br />
First let&#8217;s look on moc&#8217;s generated code for our slot (as I promised before).</p>
<pre name="code" class="cpp:nogutter">
int MyClassDerived::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = MyClass::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        switch (_id) {
        case 0: signal2((*reinterpret_cast< int(*)>(_a[1]))); break;
        case 1: d_func()->_q_boo(); break;
        default: ;
        }
        _id -= 2;
    }
    return _id;
}
</pre>
<p>Keep attention, when method receives query to invoke slot with _id=1, it simply invoke method _q_boo() from our private class directly. Without any additional steps and callings, like it is native Private Class&#8217;s meta call system (It&#8217;s not totally true, because there is little overhead, when calling d_func(), because it casts d_ptr to our Private Class&#8217;s type). </p>
<p>4. Let&#8217;s start timer in constructor, which will emit signal and execute our slot after 1 second.<br />
First of all we need add init() method in private class.<br />
Definition in  myclassderived.cpp is look&#8217;s like this:</p>
<pre name="code" class="cpp:nogutter">
void MyClassDerivedPrivate::init()
{
	Q_Q(MyClassDerived);
	QTimer::singleShot(1000,q,SLOT(_q_boo()));
}
</pre>
<p>And now let&#8217;s add initialization of private class in constructors of public one:</p>
<pre name="code" class="cpp:nogutter">
MyClassDerived::MyClassDerived(QObject *parent)
	:MyClass(*new MyClassDerivedPrivate(), parent)
{
  Q_D(MyClassDerived);
  d->init();

}

MyClassDerived::MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent)
		:MyClass(dd, parent)
{
	Q_D(MyClassDerived);
	d->init();
}
</pre>
<p>Of course it&#8217;s better to add only one line in each constructor:</p>
<pre name="code" class="cpp:nogutter">
    QTimer::singleShot(1000,this,SLOT(_q_boo()));
</pre>
<p>But I tried to show you concept at all, and there are usually more than one line of code in initialization method.<br />
Believe it or not, that&#8217;s all. In the next section I&#8217;ll show you test application for our library.</p>
<h1>Testing our library.</h1>
<p>Lets&#8217; make new project (subfolder &#8220;main&#8221; in my case).<br />
main.pro</p>
<pre name="code" class="cpp">
TEMPLATE = app
LIBS += -lhabrhabr -L..
INCLUDEPATH += ../
TARGET = main

SOURCES += main.cpp
</pre>
<p>and the main.cpp:</p>
<pre name="code" class="cpp">
#include "myclassderived.h"
#include &lt;QApplication&gt;

int main(int argc, char ** argv) {
	QApplication a(argc,argv);
	MyClassDerived d(0);
	return a.exec();
}
</pre>
<p>Why I made QApplication&#8217;s instance. Because signals and slots are working in context of thread loop, and we need this loop for our code. In our case we use main loop of application.<br />
Build, Run, and having results:</p>
<pre name="code" class="cpp:nogutter">
7
exit-code:1
</pre>
<p>Ta-a-a-T-a-a-m! We made it!</p>
<p>Warning: I noticed about headers order in .pro file before. Here I&#8217;m repeating about it. Headers of private  class HAVE TO BE AFTER THEIR  PUBLIC headers in HEADERS section of .pro file. Also headers have to be in order they include each  other. For example, myclass.h have to be before myclassderived.h, because myclassderived.h include&#8217;s it.<br />
Keep in mind, that Q_PRIVATE_SLOT is not a part of public API, and Trolls are not make any guaranties, that it will have the same behavior in next releases. But don&#8217;t be afraid, I noticed in the post about pimpl, that it&#8217;s a base of all Qt&#8217;s realization, that&#8217;s why It might be changed only at next major releases, for example in Qt5.</p>
<p>And now source code, as usual (source code of test program is in previous section):<br />
habrhabr.pro:</p>
<pre name="code" class="cpp">
TEMPLATE = lib
HEADERS += myclass.h \
    myclass_p.h \
	myclassderived.h \
    myclassderived_p.h
SOURCES += myclass.cpp \
    myclassderived.cpp
</pre>
<p>myclass.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASS_H
#define MYCLASS_H

#include &lt;QObject&gt;

class MyClassPrivate;
class MyClass : public QObject
{
Q_OBJECT
public:
    explicit MyClass(QObject *parent = 0);
	int foo() const;
signals:
	void signal(int);
protected:
	MyClassPrivate * const d_ptr;
	MyClass(MyClassPrivate &#038;dd, QObject * parent);
private:
	Q_DECLARE_PRIVATE(MyClass);
};

#endif // MYCLASS_H
</pre>
<p>myclass_p.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASS_P_H
#define MYCLASS_P_H
#include "myclass.h"

class MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClass);
public:
	MyClassPrivate();
	virtual ~MyClassPrivate();

	void foo();

	void _q_boo();

	int i;
	MyClass * q_ptr;
};

#endif // MYCLASS_P_H
</pre>
<p>myclass.cpp</p>
<pre name="code" class="cpp">
#include "myclass.h"
#include "myclass_p.h"
#include &lt;QDebug&gt;
#include &lt;QCoreApplication&gt;
MyClassPrivate::MyClassPrivate()
{
   i = 5;
}

MyClassPrivate::~MyClassPrivate()
{
	//nothing to do
}

void MyClassPrivate::foo()
{
	Q_Q(MyClass);
	emit(q->signal(i));
}

void MyClassPrivate::_q_boo()
{
	qDebug()&lt;&lt;i;
	QCoreApplication::exit(1);
}

MyClass::MyClass(QObject *parent)
	:QObject(parent)
	,d_ptr(new MyClassPrivate())
{
	Q_D(MyClass);
	d->q_ptr = this;
}

MyClass::MyClass(MyClassPrivate &#038;dd, QObject * parent)
	:QObject(parent)
	,d_ptr(&#038;dd)
{
	Q_D(MyClass);
	d->q_ptr = this;
}

int MyClass::foo() const
{
	Q_D(const MyClass);
	return d->i;
}
</pre>
<p>myclassderived.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASSDERIVED_H
#define MYCLASSDERIVED_H
#include "myclass.h"

class MyClassDerivedPrivate;
class MyClassDerived : public MyClass
{
Q_OBJECT
public:
    explicit MyClassDerived(QObject *parent = 0);
signals:
	void signal2(int);
protected:
	MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent);
private:
	Q_DECLARE_PRIVATE(MyClassDerived);
	Q_PRIVATE_SLOT(d_func(),void _q_boo());
};

#endif // MYCLASSDERIVED_H
</pre>
<p>myclassderived_p.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASSDERIVED_P_H
#define MYCLASSDERIVED_P_H

#include "myclassderived.h"
#include "myclass_p.h"

class MyClassDerivedPrivate: public MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClassDerived);
public:
	MyClassDerivedPrivate();
	virtual ~MyClassDerivedPrivate();

	void foo2();
	void init();
	int j;
};

#endif // MYCLASSDERIVED_P_H
</pre>
<p>myclassderived.cpp</p>
<pre name="code" class="cpp">

#include "myclassderived.h"
#include "myclassderived_p.h"
#include &lt;QTimer&gt;

MyClassDerivedPrivate::MyClassDerivedPrivate()
{
	j=6;
	i=7;
}

MyClassDerivedPrivate::~MyClassDerivedPrivate()
{

}

void MyClassDerivedPrivate::foo2()
{
	Q_Q(MyClassDerived);
	emit(q->signal2(j));
	emit(q->signal(j));
}

void MyClassDerivedPrivate::init()
{
	Q_Q(MyClassDerived);
	QTimer::singleShot(1000,q,SLOT(_q_boo()));
}

MyClassDerived::MyClassDerived(QObject *parent)
	:MyClass(*new MyClassDerivedPrivate(), parent)
{
  Q_D(MyClassDerived);
  d->init();

}

MyClassDerived::MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent)
		:MyClass(dd, parent)
{
	Q_D(MyClassDerived);
	d->init();
}

#include "moc_myclassderived.cpp"
</pre>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>132</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=191</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Приватные слоты в паттерне Pimpl от Qt.</title>
		<link>http://erudenko.com/wordpress/?p=162</link>
		<comments>http://erudenko.com/wordpress/?p=162#comments</comments>
		<pubDate>Thu, 26 Nov 2009 17:39:55 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[Qt embedded]]></category>
		<category><![CDATA[Russian]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Pimpl]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[Q_D]]></category>
		<category><![CDATA[Q_Q]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=162</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=162">Приватные слоты в паттерне Pimpl от Qt.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Приватные слоты в паттерне Pimpl]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=162">Приватные слоты в паттерне Pimpl от Qt.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<h1>Вступление.</h1>
<p>Недавно я писал по поводу реализации <a href="http://erudenko.com/wordpress/?p=100">паттерна Pimpl в библиотеке Qt</a> и призывал людей следовать такому подходу при разработке их собственных бибиотек. Теперь я хочу поговорить о таком понятии, как приватные слоты и тем самым продолжить эту тему. Заключительной статьей на эту тему будет реализация механизма Implicit Sharing и shared d-pointer. </p>
<h1>Что это и зачем это нужно.</h1>
<p>Приватные слоты &#8211; это механизм дополняющий функционал d-указателей. Он позволяет реализовать слоты для приватного класса, даже если он не является наследником от QObject  (обычно он им и не является), но для этого публичный класс должен быть наследником от QObject. Тоесть по факту создается некий приватный слот в публичном классе и он непосредственно дергает нужный метод приватного класса.<br />
Зачем это нужно? Ну рассмотрим на примере. Есть класс QAbstractScrollArea. Он просто отображает некий виджет (viewport) и обеспечивает прокрутку. Прокрутка обеспечивается с помощью двух экземпляров класса QScrollBar. Сами эти скролбары он хранит в приватном классе. Теперь проблемма: как подключить сигнал от скроллбара об изменение его позиции с классом QAbstractScrollAreaPrivate, ведь он не является QObject&#8217;ом ? Сделать его наследником от QObject &#8211; лучше не делайте это <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Можно сделать слот в публичном классе и повесить на него, то в таком случае это не очень красиво &#8211; так как наружу выходят слоты от внутренней реализации. Вот ту Qt-шниками был придуман достаточно разумный и элегантный подход &#8211; приватные слоты.</p>
<h1>Как это работает.</h1>
<p>Для реализации приватного слота служит макрос Q_PRIVATE_SLOT. Ну по нашему обычаю залазим в исходники Qt  и смотрим что он из себя представляет:</p>
<pre name="code" class="cpp:nogutter">
# define Q_PRIVATE_SLOT(d, signature)
</pre>
<p>Опа !!!! Пусто <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Но настоящие мужчины никогда не отчаиваются и лезут в исходники глубже, а точнее в исходники moc. Кто не знает, moc &#8211; это некая реализация некого парсера. Только немного хитрая. В отличие от инструментов использующих QLALR (QSA и QXmlStreamReader ) &#8211; эта штука оказалась своеобразной. Я не силент в парсерах поэтому более глобальный анализ провести не могу. Но он точно не похож на LALR потому-что я не нашел лексики его.  Таблица токенов генерится некой утилитой generate_keywords, которую можно найти в исходниках moc в папке util.<br />
Насколько я понял он просто генерит из любого текста токены и формирует из них структуру вида:</p>
<pre name="code" class="cpp:nogutter">
static const struct
{
   Token token;
   short next;
   char defchar;
   short defnext;
   Token ident;
}
</pre>
<p>Вот пример записей этого генератора:</p>
<pre name="code" class="cpp:nogutter">
    {Q_SIGNAL_TOKEN, 0, 83, 470, CHARACTER},
    {Q_SIGNALS_TOKEN, 0, 0, 0, CHARACTER},
    {Q_SLOT_TOKEN, 0, 83, 474, CHARACTER},
    {Q_SLOTS_TOKEN, 0, 0, 0, CHARACTER},
    {Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER},
</pre>
<p>Кто хочет покапать дальше или вообще уже знает ответ &#8211; прошу высказыватся.<br />
Кстати очень просто оказалось это все дело расширить <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  можно добавить свой препроцессинг. Вот что значит писать красиво. </p>
<p>в token.cpp находим наш токен:</p>
<pre name="code" class="cpp:nogutter">
        case Q_PRIVATE_SLOT_TOKEN: return "Q_PRIVATE_SLOT_TOKEN";
</pre>
<p>И далее в реализации метода MOC::parse() находим что же он делает, когда встречает этот парсер:</p>
<pre name="code" class="cpp:nogutter">
              case Q_PRIVATE_SLOT_TOKEN:
                    parseSlotInPrivate(&#038;def, access);
                    break;
</pre>
<p>Ну вот и добрались до сути, она находится в методе parseSlotInPrivate(&#038;def, access);<br />
Вот и она:</p>
<pre name="code" class="cpp:nogutter">
void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access)
{
    next(LPAREN);
    FunctionDef funcDef;
    next(IDENTIFIER);
    funcDef.inPrivateClass = lexem();
    // also allow void functions
    if (test(LPAREN)) {
        next(RPAREN);
        funcDef.inPrivateClass += "()";
    }
    next(COMMA);
    funcDef.access = access;
    parseFunction(&#038;funcDef, true);
    def->slotList += funcDef;
    while (funcDef.arguments.size() > 0 &#038;&#038; funcDef.arguments.last().isDefault) {
        funcDef.wasCloned = true;
        funcDef.arguments.removeLast();
        def->slotList += funcDef;
    }
}
</pre>
<p>Вот теперь все ясно. Как вы видите эта директива заполняет нужные значения для определения метафункции, которая генерируется moc&#8217;ом ( таким же образом как и для обычных слотов ). А пустой дефайн просто делает эту запись пустой, когда moc прошел и настает время предкомпилятору. Тоесть на момент стандартной компиляции там уже пусто, но реализация слота сгенерирована в moc файле. Далее я покажу как она выглядит в нашем примере.<br />
Ну вобщем разобрались с тем как это устроено, далее будет смотреть как это использовать.</p>
<h1>Как реализовать это в своем коде.</h1>
<p>Тут в дейсвтительности все очень просто. В качестве примера берем классы из моей <a href="http://erudenko.com/wordpress/?p=100"> предыдущей статьи </a>. И добавляем новый функционал.<br />
1. Добавляем метод void _q_boo() в MyClassPrivare:</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClass);
public:
	MyClassPrivate();
	virtual ~MyClassPrivate();

	void foo();
	void _q_boo();
	int i;
	MyClass * q_ptr;
};
</pre>
<p>Реализация в myclass.cpp будет выглядеть таким образом:</p>
<pre name="code" class="cpp:nogutter">
void MyClassPrivate::_q_boo()
{
	qDebug()&lt;&lt;i;
	QCoreApplication::exit(1);
}
</pre>
<p>Не забудте добавить QDebug  и QCoreApplication в инклуды.<br />
По поводу имени _q_boo. Это правило именования приватных слотов от qt. Имя должно начинатся на &#8220;_q_&#8221;. Тогда при просмотре объявления приватного класса можно определить что это слот.<br />
QCoreApplication::exit(1) &#8211; я добавил для того чтобы при сраватывании мы завершили основной цикл приложения (далее напишу листинг этого приложения для тестирования нашей библиотеки).<br />
2. Для большей запутаности ( а то сильно просто все получается ) давайте дерганье этого слота реализуем в наследнике &#8211; MyClassDerived. Для этого объявим у него в приватной секции такой вот макрос:</p>
<pre name="code" class="cpp:nogutter">
	Q_PRIVATE_SLOT(d_func(),void _q_boo());
</pre>
<p>Из вышеуказанного реверс инжиниринга moc мы тут видим, что нам нужен указатель на класс и имя его метода. По факту это простой текстовый анализ на основании которого потом сгенерируется код moc_myclassderived.cpp.<br />
3. Попробуем собрать наш проект:</p>
<pre name="code" class="cpp:nogutter">
moc_myclassderived.cpp: In member function ‘virtual int MyClassDerived::qt_metacall(QMetaObject::Call, int, void**)’:
moc_myclassderived.cpp:70: error: invalid use of incomplete type ‘struct MyClassDerivedPrivate’
myclassderived.h:5: error: forward declaration of ‘struct MyClassDerivedPrivate’
</pre>
<p>Это нормально, ведь moc ничего не знает о нашем Private классе, ведь он инклудид в себя только тот заголовочный файл, на основании которого он был сгенерированый. А в публичном заголовочном файле только forward объявление. Так как moc &#8211; это по сути добавка к нашей реализации, просто включим его в конец нашего .cpp файла:</p>
<pre name="code" class="cpp:nogutter">
..................
#include "moc_myclassderived.cpp"
</pre>
<p>Теперь запускаем сборку и &#8230; Опять та же ошибка !!! Не отчаивайтесь. Просто сделайте make distclean и соберите снова.<br />
Ну вот вобщем и все &#8230; аааа конечно, пример использования. Тогда идем дальше.<br />
Как и общела смотрим, что же нагенерил нам moc:</p>
<pre name="code" class="cpp:nogutter">
int MyClassDerived::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = MyClass::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        switch (_id) {
        case 0: signal2((*reinterpret_cast< int(*)>(_a[1]))); break;
        case 1: d_func()->_q_boo(); break;
        default: ;
        }
        _id -= 2;
    }
    return _id;
}
</pre>
<p>Обратите внимание: когда к нам приходит запрос на вызов слота с _id=1, то мы дергаем метод приватного класса напрямую, без никаких потерь, как будто эта система метавызовов является родной для приватного класса а не для публичногою (немного завираю, так как все таки небольшой оверхед есть в преобразовании типов, во время вызова функции d_func() ).</p>
<p>4. Давайте запустим таймер, чтоб он дернул наш метод при создании класса MyClassDerived через одну секунду.<br />
В первую очередь объявим  init() метод в MyClassDerivedPrivate.<br />
Реализация в myclassderived.cpp  выглядит таким образом:</p>
<pre name="code" class="cpp:nogutter">
void MyClassDerivedPrivate::init()
{
	Q_Q(MyClassDerived);
	QTimer::singleShot(1000,q,SLOT(_q_boo()));
}
</pre>
<p>Ну и добавим вызов инициализации в наш конструктор (раньше они у нас были пустые):</p>
<pre name="code" class="cpp:nogutter">
MyClassDerived::MyClassDerived(QObject *parent)
	:MyClass(*new MyClassDerivedPrivate(), parent)
{
  Q_D(MyClassDerived);
  d->init();

}

MyClassDerived::MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent)
		:MyClass(dd, parent)
{
	Q_D(MyClassDerived);
	d->init();
}
</pre>
<p>Конечно в данном случае можно было не городить конструкцию с init(), просто бы в каждом конструкторе бы была такая запись:</p>
<pre name="code" class="cpp:nogutter">
    QTimer::singleShot(1000,this,SLOT(_q_boo()));
</pre>
<p> Но я хотел показать подход, когда в инициализации необходимо выполнить более чем одно действие.</p>
<p>Не поверите <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Но это все. В следующем пункте покажу программку, которая это все оттестирует.</p>
<h1>Тестируем наш код</h1>
<p>Ну вот создаем новый проект (в моем случае я его сделал в подкаталоге main моего проекта habrahabra):<br />
main.pro</p>
<pre name="code" class="cpp">
TEMPLATE = app
LIBS += -lhabrhabr -L..
INCLUDEPATH += ../
TARGET = main

SOURCES += main.cpp
</pre>
<p>ну и сам main.cpp:</p>
<pre name="code" class="cpp">
#include "myclassderived.h"
#include &lt;QApplication&gt;

int main(int argc, char ** argv) {
	QApplication a(argc,argv);
	MyClassDerived d(0);
	return a.exec();
}
</pre>
<p>Почему нужно было делать QApplication? Да потому как система сигналов и слотов не будет работать без цикла выполнения потока в контексте которого он будет выполнятся (в нашем случае mainloop&#8217;a).<br />
Собираем, запускаем, получаем результат:</p>
<pre name="code" class="cpp:nogutter">
7
exit-code:1
</pre>
<p>Урааа!!! Все работает.</p>
<h1>Заключение.</h1>
<p>Может вас испугало что я так много написал по этой теме ? В таком случае могу вас успокоить, все намного проще чем вам кажется. Просто я хотел показать как работает этот механизм, а не просто инструкции по применению вроде: &#8220;Вставтье это сюда и это сюда и ура у вас все работает&#8221;. В действительности необходимо проделать всего три шага.<br />
1. Объявить макрос Q_PRIVATE_SLOT(d_func(),_q_method());<br />
2. Реализовать этот метод в приватном классе.<br />
3. Добавить в конец  cpp файла #include &#8220;moc_classname.cpp&#8221;</p>
<p>И все !!! Все просто.</p>
<p>Важно: я уже указывать порядок следования заголовочных файлов в статье касательно pimpl. Но тут напомню, что все приватные заголовочные файлы должны строго следовать за публичными и в списке HEADERS они должны идти в порядке включения. В нашем примере derived класс включает в себя заголовки базового класса, поэтому в списке HEADERS файла проекта он идет после заголовков родителя.<br />
Ну и так же как и макросы d-указателя, макросы приватного слота не являются частью публичного API и могут быть изменены в любой момент. Но не пугайтесь, я успокаивал по этому поводу в статье по pimpl.</p>
<p>Ну и по традиции исходники (исходники тестовой програмки полностью опубликованы выше, поэтому тут их не буду писать):<br />
habrhabr.pro:</p>
<pre name="code" class="cpp">
TEMPLATE = lib
HEADERS += myclass.h \
    myclass_p.h \
	myclassderived.h \
    myclassderived_p.h
SOURCES += myclass.cpp \
    myclassderived.cpp
</pre>
<p>myclass.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASS_H
#define MYCLASS_H

#include &lt;QObject&gt;

class MyClassPrivate;
class MyClass : public QObject
{
Q_OBJECT
public:
    explicit MyClass(QObject *parent = 0);
	int foo() const;
signals:
	void signal(int);
protected:
	MyClassPrivate * const d_ptr;
	MyClass(MyClassPrivate &#038;dd, QObject * parent);
private:
	Q_DECLARE_PRIVATE(MyClass);
};

#endif // MYCLASS_H
</pre>
<p>myclass_p.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASS_P_H
#define MYCLASS_P_H
#include "myclass.h"

class MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClass);
public:
	MyClassPrivate();
	virtual ~MyClassPrivate();

	void foo();

	void _q_boo();

	int i;
	MyClass * q_ptr;
};

#endif // MYCLASS_P_H
</pre>
<p>myclass.cpp</p>
<pre name="code" class="cpp">
#include "myclass.h"
#include "myclass_p.h"
#include &lt;QDebug&gt;
#include &lt;QCoreApplication&gt;
MyClassPrivate::MyClassPrivate()
{
   i = 5;
}

MyClassPrivate::~MyClassPrivate()
{
	//nothing to do
}

void MyClassPrivate::foo()
{
	Q_Q(MyClass);
	emit(q->signal(i));
}

void MyClassPrivate::_q_boo()
{
	qDebug()&lt;&lt;i;
	QCoreApplication::exit(1);
}

MyClass::MyClass(QObject *parent)
	:QObject(parent)
	,d_ptr(new MyClassPrivate())
{
	Q_D(MyClass);
	d->q_ptr = this;
}

MyClass::MyClass(MyClassPrivate &#038;dd, QObject * parent)
	:QObject(parent)
	,d_ptr(&#038;dd)
{
	Q_D(MyClass);
	d->q_ptr = this;
}

int MyClass::foo() const
{
	Q_D(const MyClass);
	return d->i;
}
</pre>
<p>myclassderived.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASSDERIVED_H
#define MYCLASSDERIVED_H
#include "myclass.h"

class MyClassDerivedPrivate;
class MyClassDerived : public MyClass
{
Q_OBJECT
public:
    explicit MyClassDerived(QObject *parent = 0);
signals:
	void signal2(int);
protected:
	MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent);
private:
	Q_DECLARE_PRIVATE(MyClassDerived);
	Q_PRIVATE_SLOT(d_func(),void _q_boo());
};

#endif // MYCLASSDERIVED_H
</pre>
<p>myclassderived_p.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASSDERIVED_P_H
#define MYCLASSDERIVED_P_H

#include "myclassderived.h"
#include "myclass_p.h"

class MyClassDerivedPrivate: public MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClassDerived);
public:
	MyClassDerivedPrivate();
	virtual ~MyClassDerivedPrivate();

	void foo2();
	void init();
	int j;
};

#endif // MYCLASSDERIVED_P_H
</pre>
<p>myclassderived.cpp</p>
<pre name="code" class="cpp">

#include "myclassderived.h"
#include "myclassderived_p.h"
#include &lt;QTimer&gt;

MyClassDerivedPrivate::MyClassDerivedPrivate()
{
	j=6;
	i=7;
}

MyClassDerivedPrivate::~MyClassDerivedPrivate()
{

}

void MyClassDerivedPrivate::foo2()
{
	Q_Q(MyClassDerived);
	emit(q->signal2(j));
	emit(q->signal(j));
}

void MyClassDerivedPrivate::init()
{
	Q_Q(MyClassDerived);
	QTimer::singleShot(1000,q,SLOT(_q_boo()));
}

MyClassDerived::MyClassDerived(QObject *parent)
	:MyClass(*new MyClassDerivedPrivate(), parent)
{
  Q_D(MyClassDerived);
  d->init();

}

MyClassDerived::MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent)
		:MyClass(dd, parent)
{
	Q_D(MyClassDerived);
	d->init();
}

#include "moc_myclassderived.cpp"
</pre>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>58</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=162</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Pimpl&#8217;s, d-pointer&#8217;s, cheshire cat&#8217;s source code example.</title>
		<link>http://erudenko.com/wordpress/?p=151</link>
		<comments>http://erudenko.com/wordpress/?p=151#comments</comments>
		<pubDate>Fri, 20 Nov 2009 21:07:56 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Pimpl]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[Q_D]]></category>
		<category><![CDATA[Q_Q]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=151</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=151">Pimpl&#8217;s, d-pointer&#8217;s, cheshire cat&#8217;s source code example.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Pimpl&#8217;s, d-pointer&#8217;s, cheshire cat&#8217;s source]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=151">Pimpl&#8217;s, d-pointer&#8217;s, cheshire cat&#8217;s source code example.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>This post is part of <a href="http://erudenko.com/wordpress/?p=113">this post</a><br />
.pro file:</p>
<pre name="code" class="cpp">
TEMPLATE = lib
HEADERS += myclass.h \
    myclass_p.h \
    myclassderived.h \
    myclassderived_p.h
SOURCES += myclass.cpp \
    myclassderived.cpp
</pre>
<p>myclass.h:</p>
<pre name="code" class="cpp">
#ifndef MYCLASS_H
#define MYCLASS_H

#include &lt;QObject&gt;

class MyClassPrivate;
class MyClass : public QObject
{
Q_OBJECT
public:
    explicit MyClass(QObject *parent = 0);
	int foo() const;
signals:
	void signal(int);
protected:
	MyClassPrivate * const d_ptr;
	MyClass(MyClassPrivate &#038;dd, QObject * parent);
private:
	Q_DECLARE_PRIVATE(MyClass);
};

#endif // MYCLASS_H
</pre>
<p>myclass_p.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASS_P_H
#define MYCLASS_P_H
#include "myclass.h"

class MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClass);
public:
	MyClassPrivate();
	virtual ~MyClassPrivate();

	void foo();

	int i;
	MyClass * q_ptr;
};

#endif // MYCLASS_P_H
</pre>
<p>myclass.cpp</p>
<pre name="code" class="cpp">
#include "myclass.h"
#include "myclass_p.h"

MyClassPrivate::MyClassPrivate()
{
   i = 5;
}

MyClassPrivate::~MyClassPrivate()
{
	//nothing to do
}

void MyClassPrivate::foo()
{
	Q_Q(MyClass);
	emit(q->signal(i));
}

MyClass::MyClass(QObject *parent)
	:QObject(parent)
	,d_ptr(new MyClassPrivate())
{
	Q_D(MyClass);
	d->q_ptr = this;
}

MyClass::MyClass(MyClassPrivate &#038;dd, QObject * parent)
	:QObject(parent)
	,d_ptr(&#038;dd)
{
	Q_D(MyClass);
	d->q_ptr = this;
}

int MyClass::foo() const
{
	Q_D(const MyClass);
	return d->i;
}
</pre>
<p>myclassderived.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASSDERIVED_H
#define MYCLASSDERIVED_H
#include "myclass.h"

class MyClassDerivedPrivate;
class MyClassDerived : public MyClass
{
Q_OBJECT
public:
    explicit MyClassDerived(QObject *parent = 0);
signals:
	void signal2(int);
protected:
	MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent);
private:
	Q_DECLARE_PRIVATE(MyClassDerived);
};

#endif // MYCLASSDERIVED_H
</pre>
<p>myclassderived_p.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASSDERIVED_P_H
#define MYCLASSDERIVED_P_H

#include "myclassderived.h"
#include "myclass_p.h"

class MyClassDerivedPrivate: public MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClassDerived);
public:
	MyClassDerivedPrivate();
	virtual ~MyClassDerivedPrivate();

	void foo2();
	int j;
};

#endif // MYCLASSDERIVED_P_H
</pre>
<p>myclassderived.cpp</p>
<pre name="code" class="cpp">
#include "myclassderived.h"
#include "myclassderived_p.h"

MyClassDerivedPrivate::MyClassDerivedPrivate()
{
	j=6;
	i=7;
}

MyClassDerivedPrivate::~MyClassDerivedPrivate()
{

}

void MyClassDerivedPrivate::foo2()
{
	Q_Q(MyClassDerived);
	emit(q->signal2(j));
	emit(q->signal(j));
}

MyClassDerived::MyClassDerived(QObject *parent)
	:MyClass(*new MyClassDerivedPrivate(), parent)
{
 //Empty
}

MyClassDerived::MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent)
		:MyClass(dd, parent)
{
 //Empty
}
</pre>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>37</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=151</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Pimpl. D-pointer. Or Cheshire cat by Qt.</title>
		<link>http://erudenko.com/wordpress/?p=113</link>
		<comments>http://erudenko.com/wordpress/?p=113#comments</comments>
		<pubDate>Fri, 20 Nov 2009 21:01:48 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Pimpl]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[Q_D]]></category>
		<category><![CDATA[Q_Q]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=113</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=113">Pimpl. D-pointer. Or Cheshire cat by Qt.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Pimpl. D-pointer. Or Cheshire cat]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=113">Pimpl. D-pointer. Or Cheshire cat by Qt.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<h1>Introduction.</h1>
<p><div id="attachment_110" class="wp-caption alignleft" style="width: 184px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/11/qtlogo.png" alt="Qt Logo" title="Qt Logo" width="174" height="71" class="size-full wp-image-110" /><p class="wp-caption-text">Qt Logo</p></div><br />
You can find Pimpl declaration in Qt documentation, while serfing in Assistent or qt doc site. Also those, Who looked inside in source code of Qt libraries, can found some strange macros: Q_DECLARE_PRIVATE, Q_D, and strange header files with names, ended with &#8220;_p.h&#8221;. Do you want to know something about this Qt&#8217;s Magic ?<br />
In this post I am going to light this magic, and show you that it&#8217;s raser simple and useful (And why Qt hide this from us? <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ).<br />
Also this post may be useful for hacking or reversing Qt source code. This information helps you better understand of structure and relaying of Qt classes.<br />
<a href="http://erudenko.com/wordpress/?p=113">Русская версия</a></p>
<h1>Pimpl, what is it?</h1>
<p>Pimpl &#8211; Pointer to implementation. It&#8217;s one of the programming patterns. The other name is &#8220;opaque pointer&#8221;, &#8220;handle classes&#8221;, &#8220;&#8221;Compiler firewall idiom&#8221;" and my favourite &#8211; &#8220;Cheshire Cat&#8221;. You can find more on <a href="http://en.wikipedia.org/wiki/Opaque_pointer">Wikipedia</a>.The main Idea of this pattern is to hide all private members and internal implementation from &#8220;main&#8221; class&#8217;s declaration. You can see only smile ,like Cheshire Cat&#8217;s smile. The cat is exists, he can speak, but you can see only his smile <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> (Do you remember Alice ? <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  &#8211; &#8220;Alice&#8217;s Adventures in Wonderland&#8221; ).<br />
What it get for us?</p>
<ol>
<li>If class hierarchy is wide and deep, then it get us more complex class hierarchy, increasing code reusing and making separate implementation of internal functionality and external class interface. </li>
<li>It makes ability to hide platform depended implementation from end-user.</li>
<li>One of the most useful features is binary compatibility of library while changing it&#8217;s realization.More about binary compatibility and Application Binary Interface (ABI) you can find  <a href="http://www.codesourcery.com/public/cxx-abi/abi.html">here (Itanium C++ ABI)</a>  and <a href="http://www.agner.org/optimize/calling_conventions.pdf"> here (an article about calling conversion)</a>.And the main rules about making library binary compatibility is described on KDE techbase  <a href="http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B">Binary Compatibility Issues With C++ </a> with the list of rules what you may to do and what not, while making library binary compatibility-enabled. </li>
<li>Next plus Is that there are less export symbols (depending on compiler and target platform), this decrease library loading time and emmory footprint.</li>
<li>Very useful feature is less time for project building.</li>
<li>All private implementation is hided from end-user, as private declaration makes it only unusable.</li>
<li>Implicitly sharing mechanism is based on Shared d-pointer pattern, which is the advanced implementation of d-pointers. The benefit of sharing is that a program does not need to duplicate data unnecessarily, which results in lower memory use and less copying of data. (This topic is for separate post <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  )</li>
</ol>
<p>And what about lacks? Yes! Here they are:</p>
<ol>
<li>Every Constructor/Destructor increase execution time by allocation and releasing memory, in this pattern it&#8217;s making twice on each class. </li>
<li>Method of public class needs one extra instruction for accessing to private class implementation variable.</li>
</ol>
<p>There are some situation when using Pimpl pattern adds  unnecessary overhead. For example,  when a lot of classes&#8217;s implementations created and released  for storing some kind of simple data. In this case This classes have to be as simple as possible. And changing of interface of this kind of class is means changing of data exchange protocol. In this case It&#8217;s better to use plugins to have flexibility. You can find a lot of such examples. The main rule for all patterns is to use it in right place and in right situation.<br />
As for my own opinion, Pimpl is useful only in library implementation or if you plan to move this code in library later.</p>
<h1>How did Qt implement Pimpl in Qt library?</h1>
<p>Qt uses &#8220;d-pointer&#8221; way. The main idea in making private class for base class with XXXXPrivate name. The main class has protected variable that point on this class&#8217;s instance. This private class declared in separate header or in .cpp file (I&#8217;ll explain what better to do). There are exists two class hierarchy &#8211; first is public and second is private. The private hierarchy is situated in _p.h (private headers )files. Private headers are used only for building library. They are absent in &#8220;include&#8221; folder and you aren&#8217;t able to use them in common way.</p>
<h1>What the main benefits of using d-pointer by Qt&#8217;s way.</h1>
<p>D-pointers way might to be some difficult to understand for first look. But it is rather simple and evident. Also code become more readable while using D-pointers, because the code is separated for public and private functionality.<br />
Benefits:</p>
<ol>
<li>Simple and evident.</li>
<li>Direct access to whole private class hierarchy (Actually the are not private, the are protected ^-))</li>
<li>Ability to access to public class from private.</li>
<li>Ability to make slots for private class (also if it not QObject) and hide it from public access by using Q_PRIVATE_SLOT(topic for separate discussion). </li>
</ol>
<h1>Yes, I want it. Give me one please! </h1>
<p>Now, if you are ready to use this pattern and wanted to know how to make it I&#8217;ll show you right way <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  &#8211; Qt way !(I really hope so !).<br />
Here are steps for implementing d-pointer powered class or let&#8217;s make cheshire cat&#8217;s:<br />
1. Forward declare private class for our main class MyClass:</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate;
class MyClassPrivate: public QObject
{ ..............
</pre>
<p>2.  Next, declare protected pointer variable of private class in first class of hierarchy:</p>
<pre name="code" class="cpp:nogutter">
protected:
    MyClassPrivate * const d_ptr;
</pre>
<p>Pay attention, that d_ptr is constant pointer. Actually  we are unable to change this pointer.<br />
3. Declare protected constructor, with firs parameter of reference to private class. This constructor makes ability to send inherited implementation of private class to all base classes as Pimpl object.</p>
<pre name="code" class="cpp:nogutter">
protected:
    MyClass(MyClassPrivate &#038;dd, QObject *parent);
</pre>
<p>4. Declare macros Q_DECLARE_PRIVATE in private section:</p>
<pre name="code" class="cpp:nogutter">
Q_DECLARE_PRIVATE(MyClass);
</pre>
<p>Lat&#8217;s look inside this macros:</p>
<pre name="code" class="cpp:nogutter">
#define Q_DECLARE_PRIVATE(Class) \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } \
    friend class Class##Private;
</pre>
<p>We can find there declaration and implementation of &#8220;d_func()&#8221;  and &#8220;d_func() const&#8221; methods. They are using to retrieve private class instance and cast it to class&#8217;s Private class&#8217;s type. Also declare Private class as friend of our public class.<br />
There are exists similar macros Q_DECLARE_PRIVATE_D. The difference is that _D macros accept&#8217;s two parameters. First is class name too, and the second is name of d-pointer variable. It&#8217;s make ability to use some another name for d-pointer instead of &#8220;d_ptr&#8221;. But name of function  d_func() is same. Here is implementation of Q_DECLARE_PRIVATE_D macros:</p>
<pre name="code" class="cpp:nogutter">
#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(Dptr); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(Dptr); } \
    friend class Class##Private;
</pre>
<p>5. Then you need to declare Private class in _p.h or .cpp file. If you plan to inherit this class then you need _p.h file, in other case declare private class inside of .cpp file.  Pay attention, that header file have to be declared before private header in project file. And I&#8217;ts better to have right ordered headers in project files. Headers that include other headers have to be declared after headers they are include. It&#8217;s important when you are include moc file right in your .cpp file when using Q_PRIVATE_SLOT macro (a&#8217;ll discuss it in other post, just keep this rule).</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate
{
    MyClassPrivate();
    virtual ~MyClassPrivate();

    int i;
}
</pre>
<p>Also you need to make destructor virtual. Why? It&#8217;s subject for separate post. But believe me it&#8217;s important. Please use C++  documentation to make it clear for you. You can find this topic in  Bjarne Stroustrup&#8217;s book.<br />
7. Realization of protected constructor is:</p>
<pre name="code" class="cpp:nogutter">
MyClass::MyClass(MyClassPrivate &#038;dd, QObject* parent)
              :QObject(parent)
              ,d_ptr(&#038;dd)
{ .....
</pre>
<p>And the public constructor&#8217;s realization (Pay attention on &#8220;explicit&#8221; keyword, please make it&#8217;s clear for you, you have to understand what is it ):</p>
<pre name="code" class="cpp:nogutter">
MyClass::MyClass(QObject * parent)
         :QObject(parent)
         ,d_ptr(new MyClassPrivate())
{........
</pre>
<p>Derived Class&#8217;s realization of such constructor is:</p>
<pre name="code" class="cpp:nogutter">
MyClassDerived::MyClassDerived(QObject * parent)
         :MyClass(*new MyClassDerivedPrivate(),parent)
{........
</pre>
<p>As you can see Derived class creates private class instance and send it to base class as it&#8217;s private class&#8217;s instance.Private class of derived class is derived from private class of base class. And it&#8217;s sends to whole hierarchy.<br />
8. To access to private classes&#8217;s instance from public class you can use Q_D macros.</p>
<pre name="code" class="cpp:nogutter">
#define Q_D(Class) Class##Private * const d = d_func()
</pre>
<p>As you can see, this macros get pointer to private class and cast it to our Private class type. As result we got variable d that points to our Private class instance (here you are: D-pointer !!! <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ).</p>
<pre name="code" class="cpp:nogutter">
int MyClass::foo() const
{
    Q_D(const MyClass);
    return d->i;
}
</pre>
<p>Pay attention that you have to declare add &#8220;const&#8221; to class name when you use it from const method. We got const d-pointer to const private class (if it&#8217;s not clear about &#8220;consts&#8221;, you have to make it clear for your about &#8220;const&#8221;, it&#8217;s very important).<br />
9. Let&#8217;s go deeper. Let me introduce new character Q-pointer. Q-pointer is similar to d-pointer, only difference that it points to public(main) class from private class. You can use it from private class&#8217;es methods to access to public class (to emit signal, for example).<br />
To implement it you have to declare pointer variable to public class&#8217;s instance in your first class of private hierarchy.</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate
{
public:
    MyClassPrivate();
    virtual ~MyClassPrivate();

    int i;
    MyClass *q_ptr;
}
</pre>
<p>And declare macros Q_DECLARE_PUBLIC in all private classes, where you going to use q-pointer.</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate
{
    Q_DECLARE_PUBLIC(MyClass);
public:
    MyClassPrivate();
    virtual ~MyClassPrivate();

    int i;
    MyClass *q_ptr;
}
</pre>
<p>Here are Q_DECLARE_PUBLIC macro:</p>
<pre name="code" class="cpp:nogutter">
#define Q_DECLARE_PUBLIC(Class)                                    \
    inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
    inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
    friend class Class;
</pre>
<p>As you can see it&#8217;s similar to Q_DECLARE_PRIVATE. but instead of d_ptr there is q_ptr and instead of d_func() is q_func().  And also there are no analog of Q_DECLARE_PRIVATE_D for Q_DECLARE_PUBLIC.<br />
Warning: don&#8217;t forget to initialize q_ptr variable in all constructors of base class of your first class of hierarchy:</p>
<pre name="code" class="cpp:nogutter">
MyClass::MyClass(QObject * parent)
         :QObject(parent)
         ,d_ptr(new MyClassPrivate())
{
    Q_D(MyClass);
    d->q_ptr = this;
.......
}
</pre>
<p>10. To access to public class from private one use macros Q_Q. </p>
<pre name="code" class="cpp:nogutter">
#define Q_Q(Class) Class * const q = q_func()
</pre>
<p>Behavior and rules are the same as for d-pointer (don&#8217;t forget add &#8220;const&#8221; when use it from const method).</p>
<pre name="code" class="cpp:nogutter">
void MyClassPrivate::foo()
{
    Q_Q(MyClass);
    q->foo();
    emit(q->signal(i));
}
</pre>
<h1>Conclusion.</h1>
<p>Keep in mind that all macros are part of non-public Qt API, and might change in any time. But I can console you. These macros are basement of all Qt libs, and in worst way they can change only in Qt5. In any case you have to port application from Qt4 to Qt5. Another consolation is KDE use&#8217;s this macros in own source code. But if you paranoiac, you can rename this macros and fit it in your source code.<br />
Also keep in mind that the class My class is derived from QObject. And QObject has it&#8217;s own private class hierarchy. QObjectData is most base class in it.It keeps pointer to parent, object state and other base properties. But Qt&#8217;s private class hierarchy is isolated from mine, because I close QObject&#8217;s d_ptr variable by mine. And when my classes use d_ptr, they use my private classes, but QObject still use it&#8217;s own private class.<br />
Why not use Qt&#8217;s private hierarchy and make our MyClassPrivate derived from QObjectPrivate class. It is possible but it is bad decision. First of all We lose Qt lib&#8217;s binary compatibility and have to recompile our lib for every change of Qt&#8217;s private implementation, in this case. The second reason why to not to do so is private headers of Qt classes are unavailable by common way, we need Qt sources to compile our library. And what you&#8217;ll get doing it ? It&#8217;s unnecessary at all(Maybe I&#8217;m wrong, please let me know if it&#8217;s true).</p>
<p>Later I&#8217;ll tell you about some other interesting things:<br />
What is QFlag and why to use it.<br />
Qt&#8217;s code style.<br />
How to implement implicit sharing in your classes and how it works.<br />
Qt&#8217;s useful macros.<br />
Qt Creator inside and outside (tips and tricks).<br />
How to create application and easy port it to 7 platforms, using Qt.<br />
And more interesting things.</p>
<p>Don&#8217;t lose it, subscribe to RSS on top of this page.<br />
PS: Excuse me for my English, I&#8217;ll be glad to receive corrections and remarks about my publications. English is not my native language, be patient, because it&#8217;s rather difficult to write on English for me.</p>
<h1>Source code examples.</h1>
<p>I wrote a lot of text, to help you understand better there are code examples:<br />
<a href="http://erudenko.com/wordpress/?p=151">this post</a><br />
I&#8217;m unable to put it in this post because WordPress doesn&#8217;t  show it <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>258</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=113</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Pimpl. D-pointer. Или чеширский кот по версии Qt.</title>
		<link>http://erudenko.com/wordpress/?p=100</link>
		<comments>http://erudenko.com/wordpress/?p=100#comments</comments>
		<pubDate>Fri, 20 Nov 2009 17:30:43 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[Qt embedded]]></category>
		<category><![CDATA[Russian]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Pimpl]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[Q_D]]></category>
		<category><![CDATA[Q_Q]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=100</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=100">Pimpl. D-pointer. Или чеширский кот по версии Qt.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Pimpl. D-pointer. Или чеширский кот]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=100">Pimpl. D-pointer. Или чеширский кот по версии Qt.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p><a href="http://erudenko.com/wordpress/?p=113">English version.</a></p>
<h1>Вступление.</h1>
<div id="attachment_110" class="wp-caption alignleft" style="width: 184px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/11/qtlogo.png" alt="Qt Logo" title="Qt Logo" width="174" height="71" class="size-full wp-image-110" /><p class="wp-caption-text">Qt Logo</p></div>
<p>Часто в документации от Qt встречается термин Pimpl. Кроме того, те кто хоть немного копался в исходном коде Qt часто видел такие макросы как: Q_DECLARE_PRIVATE, Q_D. А также встречал так называемые приватные заголовочные файлы, название  которых заканчивается на &#8220;_p.h&#8221;.<br />
В этой статье я попробую приоткрыть ширму за всей это структурой.</p>
<h1>Pimpl, что это?</h1>
<p>Pimpl &#8211; Private implementation. Это одно из названий паттерна программирования. Еще его называют чеширским котом(это название мне больше нравится). В чем суть этого паттерна? Основная идея этого паттерна &#8211; это вынести все приватные члены класса и , в не которых случаях, функционала в приватный класс.<br />
Отсюда название &#8220;чеширский кот&#8221; &#8211; видно только улыбку, а все остальное остается невидимым, но оно несомненно есть <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Кто не помнит этого замечательного кота, может обратится к первоисточнику, к книге Льюиса Кэрролла «Алиса в стране чудес». Очень интересная книга, особенно если читать в оригинале.<br />
Что это дает? </p>
<ol>
<li>Если иерархия классов &#8220;широкая&#8221; или &#8220;глубокая&#8221; получается более комплексная структура классов и тем самым повышается удобство &#8220;переиспользование &#8211; reuse&#8221; кода. </li>
<li>Также это дает возможность спрятать платформо-зависимую реализацию от конечного пользователя. 		  </li>
<li>Одним из самых основных достоинств &#8211; это сохранение бинарной совместимости библиотеки при изменение ее реализации(достигается за счет того что вся реализация находится в приватном классе). Более подробно о бинарной совместимости и бинарном интерфейсе приложения (ABI) можно ознакомится <a href="http://www.codesourcery.com/public/cxx-abi/abi.html">здесь (Itanium C++ ABI)</a>  и <a href="http://www.agner.org/optimize/calling_conventions.pdf"> здесь (an article about calling conversion)</a>. И основные правила о бинарной совместимости от KDE  разработчиков <a href="http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B">Binary Compatibility Issues With C++ </a> с кратким сборником того что нужно и чего нельзя делать для сохранения бинарной совместимости. </li>
<li>Следующим достоинством является то что количество экспортируемых символов в классе становится меньше и скорость загрузки библиотеки увеличивается, ну и плюс меньший размер конечно.</li>
<li>Увеличивается скорость сборки приложения (что очень актуально). </li>
<li>Прячется вся ненужная реализация от клиента, в отличие от приватных методов, pimpl  объявление и реализацию не видно вообще.</li>
<li>Этот паттерн очень сильно облегчает реализацию механизма implicit-sharing (не буду переводить, чтоб не плодить лишней терминологии). Механизм при котором при копировании классов не происходит копирование данных, а копирование происходит лишь тогда, когда копии класса потребуется изменить эти данные. Implicit-sharing реализован во всех контейнерных классах Qt. Для его реализации используется реализация Pimpl под названием &#8220;shared D-pointers&#8221;. Вообще это емкая тема и требует отдельной статьи.</li>
</ol>
<p>Но ведь должны же быть и минусы, скрывать их не буду, выложу как есть:</p>
<ol>
<li>Каждый конструктор, деструктор вызывают выделение и освобождение памяти, что увеличивают время создания класса. </li>
<li>Каждый метод, который содержит доступ к приватной реализации добавляет плюс одну экстра инструкцию.</li>
</ol>
<p>Учитывая эти недостатки, по мнению автора, использование этого паттерна для классов, которые будут содержатся в коде в большом количестве и создаваться/удалятся в процессе жизнедеятельности программы нецелесообразно. Допустим примером такой реализации может служить загрузка и хранение неких данных, вот классы, которые реализуют эти данные лучше сделать как можно проще. А любое изменение в таких классах предполагает что изменяется протокол самой передачи этих данных. Но могут быть и другие примеры такого рода классов. Поэтому основное правило при использование любого паттерна распространяется и на этот тоже: использовать необходимо оптимально, там где это действительно необходимо.<br />
То есть этот паттерн необходимо использовать в том случае, если вы пишете библиотеку или планируете вынести этот функционал в будущем в отдельную библиотеку. В других случаях, по личному мнению автора, использование такого подхода избыточно.</p>
<h1>Как это реализовано в библиотеках Qt.</h1>
<p>В Qt коде используется подход d-указателей. Смысл в том что объявляется класс XXXPrivate и переменная публичного класса в защищенной секции. В отдельном заголовочном файле или в .cpp файле уже пишется реализация приватного класса (в чем разница  я объясню позже).<br />
Иерархия классов идет как по публичным так и по приватным классам. Для этого объявление приватного класса обычно делается в отдельном .h файле, который называется так-же как публичный, но добавляется приставка _p: qclassname_p.h. И эти классы не устанавливаются вместе с библиотекой, а служат лишь для сборки библиотеки. Поэтому вы их не найдете в пути, куда установились библиотеки QT (Prefix-PATH).</p>
<h1>В чем достоинства подхода d-указателей (d-pointers) от Qt?</h1>
<p>Этот подход с первого взгляда может показаться немного запутанным, но я вас уверяю, что он в действительности очень простой и наглядный, и даже облегчает читабельность кода (это свойство я отношу к субъективным, поэтому спорно, все зависит от восприятия конкретного человека).<br />
Достоинства:</p>
<ol>
<li>Простой и наглядный.</li>
<li>Прямой доступ ко всей иерархии приватных классов (в действительности они не приватные <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> , а защищенные).</li>
<li>Возможность доступа к публичному классу из приватного.</li>
<li>Возможность реализовать систему сигналов и слотов для приватного класса и спрятать их от внешнего использования с помощью Q_PRIVATE_SLOT макроса (тема для отдельной статьи).</li>
</ol>
<h1>Хочу такую же, но с перламутровыми пуговицами! (с) х/ф &#8220;Брильянтовая рука&#8221; </h1>
<p>Если я вас убедил, что Pimpl &#8211; это хорошо, и вы хотите попробовать и посмотреть как это работает, тогда давайте я вас посвящу в реализацию Pimpl по версии Qt.<br />
Что нужно сделать:<br />
1. Сделать forward &#8211; объявление вашего приватного класса перед объявлением публичного класса:</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate;
class MyClass: public QObject
{ ..............
</pre>
<p>2. Далее в первом классе иерархии в защищенной секции необходимо объявить переменную, ссылающуюся на приватный класс:</p>
<pre name="code" class="cpp:nogutter">
protected:
    MyClassPrivate * const d_ptr;
</pre>
<p>Обратите внимание, что указатель  константный, во избежании всяких там случайных нелепостей.<br />
3. Также в защищенной секции (как первого класса иерархии так и всех его наследников) необходимо объявить конструктор, принимающий в качестве параметра приватный член класса. Это необходимо для того чтобы обеспечить возможность создание наследников приватного класса  и использование их как приватных классов во всей иерархии:</p>
<pre name="code" class="cpp:nogutter">
protected:
    MyClass(MyClassPrivate &#038;dd, QObject *parent);
</pre>
<p>4. В приватной секции объявляем макрос доступа к d-указателю:</p>
<pre name="code" class="cpp:nogutter">
Q_DECLARE_PRIVATE(MyClass);
</pre>
<p>Вот теперь разберемся что он из себя представляет:</p>
<pre name="code" class="cpp:nogutter">
#define Q_DECLARE_PRIVATE(Class) \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(d_ptr); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(d_ptr); } \
    friend class Class##Private;
</pre>
<p>Как мы видим тут объявляется функция d_func() и d_func() const, с помощью которой мы получаем указатель на приватный класс и константный приватный класс соответственно. Причем получаем его уже приведенным к типу приватного класса этого объекта. Ну и объявляем наш приватный класс другом для публичного.<br />
Также существует макрос Q_DECLARE_PRIVATE_D. Разница в том что в качестве второго параметра вы указываете переменную d-указатель, таким образом вместо  d_ptr  в качестве D-указателя может быть использована переменная с любым именем. Но название функции  d_func остается неизменным.<br />
Реализация макроса выглядит таким образом:</p>
<pre name="code" class="cpp:nogutter">
#define Q_DECLARE_PRIVATE_D(Dptr, Class) \
    inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(Dptr); } \
    inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(Dptr); } \
    friend class Class##Private;
</pre>
<p>5. Теперь необходимо объявить наш приватный класс в .cpp или _p.h файле. Если вы предполагаете дальнейшее наследование от вашего класса или собираетесь использовать приватные слоты, то необходимо вынести все в отдельный _p.h файл. Если же нет, то достаточно объявить приватный файл в .cpp файле. Также имейте ввиду, что в .pro файле .h файл должен идти до _p.h файла и до всех файлов, которые его включат в себя. Это можно взять вообще за правило, так как облегчает работу компилятору.</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate
{
    MyClassPrivate();
    virtual ~MyClassPrivate();

    int i;
}
</pre>
<p>Также рекомендую сделать деструктор виртуальным, если вы планируете строить иерархию приватных классов. Почему? Это тема отдельной статьи и таких статей уже написано достаточно, ну и конечно если не верите или не доверяете интернету, то обратитесь  к Страуструпу, у него подробно излагается эта тема.<br />
7. Реализация конструктора из защищенной секции будет выглядеть примерно таким образом:</p>
<pre name="code" class="cpp:nogutter">
MyClass::MyClass(MyClassPrivate &#038;dd, QObject* parent)
              :QObject(parent)
              ,d_ptr(&#038;dd)
{ .....
</pre>
<p>Ну и обычный конструктор с таким объявлением (обратите внимание на ключевое слово explicit, если не знаете что это и зачем, поинтересуйтесь &#8211; это полезно):</p>
<pre name="code" class="cpp:nogutter">
explicit MyClass(QObject * parent);
</pre>
<p>Будет выглядеть таким образом:</p>
<pre name="code" class="cpp:nogutter">
MyClass::MyClass(QObject * parent)
         :QObject(parent)
         ,d_ptr(new MyClassPrivate())
{........
</pre>
<p>В наследнике реализация такого конструктора будет выглядеть таким образом:</p>
<pre name="code" class="cpp:nogutter">
MyClassDerived::MyClassDerived(QObject * parent)
         :MyClass(*new MyClassDerivedPrivate(),parent)
{........
</pre>
<p>Как вы видите соответствующий конструктор наследника передает экземпляр своего приватного класса во все базовые классы по цепочке иерархии наследования (так же устроено и в Qt  иерархии классов; самым первым классом в иерархии приватных классов является QObjectData, который содержит в себе родителя, состояние объекта и другие базовые свойства).<br />
8. Для доступа к экземпляру приватного класса из метода публичного класса существует макрос Q_D().Вот что он из себя представляет:</p>
<pre name="code" class="cpp:nogutter">
#define Q_D(Class) Class##Private * const d = d_func()
</pre>
<p>Как вы видите мы получаем константный указатель на наш приватный класс в виде переменной &#8220;d&#8221; (вот он D-указатель <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  !!! ).</p>
<pre name="code" class="cpp:nogutter">
int MyClass::foo() const
{
    Q_D(const MyClass);
    return d->i;
}
</pre>
<p>Обратите внимание, что в константных методах необходимо в Q_D макросе дописывать const перед именем класса, чтобы получить константный указатель на константный экземпляр приватного класса (если вас эта формулировка напугала или не до конца ясна, обратитесь к документации по  &#8220;const&#8221;, поверьте &#8211; это очень важно ).<br />
9. Теперь погрузимся глубже. Разрешите представить еще одного зверя <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> : Q-указатель. Q-pointer (он же Q-указатель) &#8211; это тот же D-pointer (он же D-указатель), только с точностью наоборот. Он служит для доступа из методов приватного класса к экземпляру публичного (используется обычно в тех случаях, если логика тоже вынесена в приватный класс, или планируется это сделать в дальнейшем по цепочке иерархии).<br />
Для его реализации необходимо в самом первом  классе приватной иерархии объявить переменную-указатель на базовый класс:</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate
{
public:
    MyClassPrivate();
    virtual ~MyClassPrivate();

    int i;
    MyClass *q_ptr;
}
</pre>
<p>И во всех классах иерархии объявить макрос  Q_DECLARE_PUBLIC, в который планируется использовать Q-указатель.</p>
<pre name="code" class="cpp:nogutter">
class MyClassPrivate
{
    Q_DECLARE_PUBLIC(MyClass);
public:
    MyClassPrivate();
    virtual ~MyClassPrivate();

    int i;
    MyClass *q_ptr;
}
</pre>
<p>Вот что из себя представляет макрос Q_DECLARE_PUBLIC:</p>
<pre name="code" class="cpp:nogutter">
#define Q_DECLARE_PUBLIC(Class)                                    \
    inline Class* q_func() { return static_cast<Class *>(q_ptr); } \
    inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \
    friend class Class;
</pre>
<p>Как вы можете видеть, все тоже самое, как и в Q_DECLARE_PRIVATE, кроме названий. Ну и макроса для альтернативного названия q_ptr, наподобие Q_DECLARE_PRIVATE_D нет.<br />
Важно: не забудьте позаботится во всех конструкторах первого класса публичной иерархии о инициализации переменной q_ptr:</p>
<pre name="code" class="cpp:nogutter">
MyClass::MyClass(QObject * parent)
         :QObject(parent)
         ,d_ptr(new MyClassPrivate())
{
    Q_D(MyClass);
    d->q_ptr = this;
.......
}
</pre>
<p>10. Для доступа из методов приватного класса к публичному классу (например чтобы сделать вызов сигнала публичного класса  ) существует макрос Q_Q, вот как он выглядит:</p>
<pre name="code" class="cpp:nogutter">
#define Q_Q(Class) Class * const q = q_func()
</pre>
<p>Логика та же что и для D-указателей, и те же правила. Ну и в коде он будет выглядеть таким образом:</p>
<pre name="code" class="cpp:nogutter">
void MyClassPrivate::foo()
{
    Q_Q(MyClass);
    q->foo();
    emit(q->signal(i));
}
</pre>
<h1>Заключение.</h1>
<p>Имейте ввиду, что все эти макросы не являются частью публичного API, и могут быть в любой момент изменены. Но могу вас успокоить. Во первых это всё является настолько базовым фундаментом, что как минимум поменяется это к новой мажорной версии, но в этом случае все равно придется портировать приложение. А во вторых, очень многие крупные проекты используют эти макросы: например KDE. Ну а если вы являетесь убежденным параноиком и никому не доверяете, то можете объявить в своем глобальном файле похожие макросы, изменив их имя и использовать их в коде, тогда боятся точно нечего (кроме изменения поведения компиляторов по отношения к макросам <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> , ибо настоящему параноику всегда есть чего боятся <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  ).<br />
Также имейте ввиду что в моем примере я наследуюсь от QObject, который использует те же макросы для построения своей иерархии как публичных так и приватных классов. Но моя иерархия приватных классов ничего общего не имеет с приватной иерархией классов Qt.  Они стоят в стороне и не мешают друг-другу. Так как я перекрыл переменную d_ptr в своем классе, и для всех наследников от моего класса d_ptr будет указателем на мою иерархию, а для QObject нет. Для него d_ptr будет Qt иерархией приватных классов (точнее указателем на QObjectPrivate).<br />
Может возникнуть резонный вопрос, а почему бы наш приватный класс не унаследовать от QObjectPrivate. Ответ: можно, но во первых потеряется бинарная совместимость с библиотекой Qt(нужно будет иметь нашу библиотеку для каждой версии приватной реализации в Qt (она тоже меняется, QWidget точно) ).И вторым аргументом против является то, что для сборки нашей библиотеки потребуются приватные заголовочные файлы библиотеки Qt, которые находятся в папке src исходников, а не include установленных библиотек Qt. Да и трудно себе представить зачем это нужно(может кто-нибудь представит контр-аргументы, буду рад).</p>
<p>В дальнейшем я вам расскажу еще немного интересных вещей:<br />
что такое QFlag, в чем его преимущество и что с ним едят.<br />
Правила оформления кода в Qt-style.<br />
Как реализовать Implicit Sharing и что такое Shared D-pointer.<br />
Полезные макросы в QT.<br />
Qt Creator снаружи и изнутри.<br />
Как с минимальными усилиями написать приложение для 7 платформ.<br />
И много всего другого интересного.</p>
<p>PPS:Приношу свои извинения за мой русский язык, возможные неверные обороты речи и ошибки (как орфографические так и синтаксические) &#8211; это не мой родной язык <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Фуууууух, ну вот вроде и все. В качестве дополнения простой пример реализации, а то я написал много букв, а на примере всегда наглядней:</p>
<p>.pro файл:</p>
<pre name="code" class="cpp">
TEMPLATE = lib
HEADERS += myclass.h \
    myclass_p.h \
    myclassderived.h \
    myclassderived_p.h
SOURCES += myclass.cpp \
    myclassderived.cpp
</pre>
<p>файл myclass.h:</p>
<pre name="code" class="cpp">
#ifndef MYCLASS_H
#define MYCLASS_H

#include &lt;QObject&gt;

class MyClassPrivate;
class MyClass : public QObject
{
Q_OBJECT
public:
    explicit MyClass(QObject *parent = 0);
	int foo() const;
signals:
	void signal(int);
protected:
	MyClassPrivate * const d_ptr;
	MyClass(MyClassPrivate &#038;dd, QObject * parent);
private:
	Q_DECLARE_PRIVATE(MyClass);
};

#endif // MYCLASS_H
</pre>
<p>файл myclass_p.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASS_P_H
#define MYCLASS_P_H
#include "myclass.h"

class MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClass);
public:
	MyClassPrivate();
	virtual ~MyClassPrivate();

	void foo();

	int i;
	MyClass * q_ptr;
};

#endif // MYCLASS_P_H
</pre>
<p>файл myclass.cpp</p>
<pre name="code" class="cpp">
#include "myclass.h"
#include "myclass_p.h"

MyClassPrivate::MyClassPrivate()
{
   i = 5;
}

MyClassPrivate::~MyClassPrivate()
{
	//nothing to do
}

void MyClassPrivate::foo()
{
	Q_Q(MyClass);
	emit(q->signal(i));
}

MyClass::MyClass(QObject *parent)
	:QObject(parent)
	,d_ptr(new MyClassPrivate())
{
	Q_D(MyClass);
	d->q_ptr = this;
}

MyClass::MyClass(MyClassPrivate &#038;dd, QObject * parent)
	:QObject(parent)
	,d_ptr(&#038;dd)
{
	Q_D(MyClass);
	d->q_ptr = this;
}

int MyClass::foo() const
{
	Q_D(const MyClass);
	return d->i;
}
</pre>
<p>файл myclassderived.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASSDERIVED_H
#define MYCLASSDERIVED_H
#include "myclass.h"

class MyClassDerivedPrivate;
class MyClassDerived : public MyClass
{
Q_OBJECT
public:
    explicit MyClassDerived(QObject *parent = 0);
signals:
	void signal2(int);
protected:
	MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent);
private:
	Q_DECLARE_PRIVATE(MyClassDerived);
};

#endif // MYCLASSDERIVED_H
</pre>
<p>файл myclassderived_p.h</p>
<pre name="code" class="cpp">
#ifndef MYCLASSDERIVED_P_H
#define MYCLASSDERIVED_P_H

#include "myclassderived.h"
#include "myclass_p.h"

class MyClassDerivedPrivate: public MyClassPrivate
{
	Q_DECLARE_PUBLIC(MyClassDerived);
public:
	MyClassDerivedPrivate();
	virtual ~MyClassDerivedPrivate();

	void foo2();
	int j;
};

#endif // MYCLASSDERIVED_P_H
</pre>
<p>файл myclassderived.cpp</p>
<pre name="code" class="cpp">
#include "myclassderived.h"
#include "myclassderived_p.h"

MyClassDerivedPrivate::MyClassDerivedPrivate()
{
	j=6;
	i=7;
}

MyClassDerivedPrivate::~MyClassDerivedPrivate()
{

}

void MyClassDerivedPrivate::foo2()
{
	Q_Q(MyClassDerived);
	emit(q->signal2(j));
	emit(q->signal(j));
}

MyClassDerived::MyClassDerived(QObject *parent)
	:MyClass(*new MyClassDerivedPrivate(), parent)
{
 //Empty
}

MyClassDerived::MyClassDerived(MyClassDerivedPrivate &#038;dd, QObject * parent)
		:MyClass(dd, parent)
{
 //Empty
}
</pre>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>241</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=100</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Code less, Create more, Deploy everywhere. Indeed ? Part 1: Introduction.</title>
		<link>http://erudenko.com/wordpress/?p=44</link>
		<comments>http://erudenko.com/wordpress/?p=44#comments</comments>
		<pubDate>Tue, 27 Oct 2009 17:40:25 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[English]]></category>
		<category><![CDATA[Qt embedded]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[embedded]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[MacOs]]></category>
		<category><![CDATA[maemo]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[symbian]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=44</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=44">Code less, Create more, Deploy everywhere. Indeed ? Part 1: Introduction.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Code less, Create more, Deploy]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=44">Code less, Create more, Deploy everywhere. Indeed ? Part 1: Introduction.</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>Hello All. I just think about Cross-platform development of end-user application. And found that it&#8217;s much more difficult than might be. I think it&#8217;s terrible and it&#8217;s break&#8217;s IT evolution at all. <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />  It&#8217;s very sad, and It&#8217;s time to think about decision.<br />
Maybe you think I&#8217;m drank or it&#8217;s paranoia ? Maybe, But let&#8217;s see more detailed on it.</p>
<h2><strong> What we haver now ?</strong></h2>
<p><strong> </strong>In our days we have two main branches of end-user hardware devices:<br />
1. portable/embedded/low-resources devices<br />
2. desktop/laptop devices</p>
<p>First category is handled devices, PDA, communicators, Set Top Boxes, industrial devices, Digital Secure Systems, Smart Houses, Phones, Multimedia centers, etc&#8230; Let&#8217;s call them embedded systems: ES.<br />
The second category is personal  computers and laptops. Let&#8217;s call them desktop systems: DS.</p>
<h2>1. Desktops.</h2>
<p>We have two main end-user desktop systems:</p>
<ol>
<li>Windows</li>
<li>Linux</li>
<li>Mac OS</li>
</ol>
<table>
<tr>
<td>
<div id="attachment_27" class="wp-caption alignleft" style="width: 130px"><img class="size-full wp-image-27" title="Windows Logo" src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-5.jpeg" alt="Windows Logo" width="120" height="106" /><p class="wp-caption-text">Windows</p></div>
</td>
<td>
<strong>Windows</strong>: Now almost all users use Windows XP, Vista and Seven.<br />
Main language: C++.<br />
Main development environment: Visual Studio.<br />
In last years Microsoft promote .NET Framework.<br />
Now .NET almost cross-platform (Later about it).<br />
Target devices: i386 arch.
</td>
</tr>
<tr>
<td>
<div id="attachment_25" class="wp-caption alignleft" style="width: 105px"><img class="size-full wp-image-25" title="Mac Os Logo" src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-7.jpeg" alt="Mac Os Logo" width="95" height="125" /><p class="wp-caption-text">Mac Os</p></div>
</td>
<td>
<strong>Mac Os:</strong> Almost All users use Leopard and Snow Leopard (but sometimes I sow 10.4).<br />
Main Language: Objective-C + Cocoa (C for system development).<br />
Family: Unix (BSD based Darwin OS)<br />
Main development environment: XCode + XTools<br />
Target Device: IBM Power PC (old versions) and Intel&#8217;s x386 arch based.
</td>
</tr>
<tr>
<td>
<div id="attachment_26" class="wp-caption alignleft" style="width: 126px"><img class="size-full wp-image-26" title="Linux Logo" src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-6.jpeg" alt="Linux Logo" width="116" height="115" /><p class="wp-caption-text">Linux</p></div>
</td>
<td>
<strong>Linux:</strong> Almost all users use 2.6.x kernel.<br />
GUI: XServer + desktop environment<br />
Most popular desktop environments: KDE (Qt based), Gnome (GTK+ based), XFce (GTK+ based) &#8230;<br />
Main Language: C (both for system and GUI develop), C++.<br />
Main development environment: I don&#8217;t really know, for KDE &#8211; KDevelop + vim, for GTK+ maybe Anjuta, very popular are emacs and vim. Also Eclipse(CDT) hase popularity.
</td>
</tr>
</table>
<h2>2. Embedded Systems.</h2>
<p>Now we have these most popular embedded systems:</p>
<ol>
<li>Windows Mobile.</li>
<li>Symbian.</li>
<li>iPhone&#8217;s Darwin.</li>
<li>Maemo.</li>
<li>Android.</li>
<li>Moblin.</li>
<li>Embedded Linux.</li>
</ol>
<table>
<tr>
<td>
<div id="attachment_28" class="wp-caption alignleft" style="width: 128px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-4.jpeg" alt="Windows Mobile Logo" title="Windows Mobile" width="118" height="109" class="size-full wp-image-28" /><p class="wp-caption-text">Windows Mobile</p></div>
</td>
<td>
<strong>Windows Mobile</strong> also known as Windows CE.<br />
Main language: C++.<br />
Main development environment: Visual Studio.<br />
In last years Microsoft promote .NET Framework.<br />
Now .NET almost cross-platform (Later about it).<br />
Target devices: SuperH, X86, MIPS, ARM etc.
</td>
</tr>
<tr>
<td>
<div id="attachment_29" class="wp-caption alignleft" style="width: 134px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-3.jpeg" alt="Symbian Logo" title="Symbian" width="124" height="124" class="size-full wp-image-29" /><p class="wp-caption-text">Symbian</p></div>
</td>
<td>
<strong>Symbian</strong>: Most popular on Nokia, Samsung and Sony Erricsson mobile devices, most popular version: S60.<br />
It&#8217;s the most popular mobile platform now.<br />
Most popular IDE: Carbide и CodeWarrior.<br />
Native Language:C++ (with Nokia&#8217;s SDK for Symbian).<br />
Target platform: wide rage inc. x386.
</td>
</tr>
<tr>
<td>
<div id="attachment_24" class="wp-caption alignleft" style="width: 114px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-8.jpeg" alt="iPhone" title="iPhone" width="104" height="58" class="size-full wp-image-24" /><p class="wp-caption-text">iPhone</p></div>
</td>
<td>
<strong>Iphone OS: </strong> latest IPhone OS 3.1. (The similar OS uses on Ipod touch).<br />
Main Language: Objective-C + Cocoa (C for system development).<br />
Family: Unix (BSD based Darwin OS).<br />
Main development environment: XCode + XTools.<br />
Target Device: ARM.
</td>
</tr>
<tr>
<td>
<div id="attachment_30" class="wp-caption alignleft" style="width: 140px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-2.jpeg" alt="Maemo Logo" title="Maemo Logo" width="130" height="65" class="size-full wp-image-30" /><p class="wp-caption-text">Maemo</p></div>
</td>
<td>
<strong>Maemo</strong> &#8211; Debian Linux based OS. KErnel 2.6.<br />
GUI: XServer + Gnome desktop environment<br />
Main Language: C (both for system and GUI develop), C++.<br />
Main development environment: The same as for linux, and regarding <a href="http://wiki.maemo.org/Documentation/devtools/maemo5"> maemo.org </a> vi(m) and nano.<br />
New version is coming: Maemo 5.<br />
Target platform: a wide range, but now work only on  nokia tablet&#8217;s.
</td>
</tr>
<tr>
<td>
<div id="attachment_61" class="wp-caption alignleft" style="width: 140px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-101.jpeg" alt="Android Logo" title="Android Logo" width="130" height="126" class="size-full wp-image-61" /><p class="wp-caption-text">Android</p></div>
</td>
<td>
<strong>Android OS:</strong> Current version: 1.6 SDK. 2.0 is Ready.<br />
Linux based OS. With Java SDK.<br />
Native Language: Java (in newer version added NDK for C/C++ dev, but for system tools coding).<br />
IDE: Eclipse + ADT plugin.<br />
Target Devices: as linux it’s can feet on wide range devices, including x386.<br />
But now it’s few commercial devices(G1 and some HTC devices), but Device manufactures announced a lot of new, android powered devices.<br />
This OS is very interesting, because language is Java. Patron is Google. Why they choose this strategy is clear. Google tried to make android stable and easy for developers.
</td>
</tr>
<tr>
<td>
<div id="attachment_31" class="wp-caption alignleft" style="width: 98px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-1.jpeg" alt="Moblin Logo" title="Moblin Logo" width="88" height="79" class="size-full wp-image-31" /><p class="wp-caption-text">Moblin</p></div>
</td>
<td>
<strong>Moblin:</strong>Linux based (2.6 kernel) OS, with GTK+ and CLutter powered GUI.<br />
Windowing system based on GNome mobile.(As I know Moblin 2 is used Xfce ).<br />
Main Language: C/C++ and variety of bindings to Clutter.<br />
Main IDE: as for Linux.<br />
Target devices: Intel Atom from Intel, but I think can be ported to all Linux supported platforms.<br />
Main Idea is to make fast, stable and looks-good OS for netbooks.
</td>
</tr>
<tr>
<td>
<div id="attachment_64" class="wp-caption alignleft" style="width: 111px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/images-11.jpeg" alt="Linux Embedded" title="Linux Embedded" width="101" height="111" class="size-full wp-image-64" /><p class="wp-caption-text">Linux Embedded</p></div>
</td>
<td>
<strong>Embedded Linux:</strong> Most popular is 2.6 kernel based devices, but most resource limited devices use 2.4 kernel.<br />
Main language: C/C++<br />
Might have no windowing system at all.<br />
There are the list of GUI implementations: TinyX, DirectFB, GTKFB, Microwindows, FLTK2, QT with QWS, etc.<br />
In some cases GUI may be realised via browser: Dillo, Konqueror embedded, Opera, Fresco, etc.<br />
At all Android, Maemo and Moblin are Embedded Linuxes too.<br />
But I highlighted Linux Embedded because there are a lot of different systems, that are Embedded Linux and the main task of GUI is to interact with user with one application, and this application makes all hardwork instead of user. And there are not importent which GUI Framework is used. The main task for GUI is user-friendly, lightweight, fast and easy and fast for develop.
</td>
</tr>
</table>
<p>Also I know about Blackberry and Palm Pre.<br />
Blackberry offer develop on web applications and java. Palm Pre and Palm Pixi work on WebOs with JavaScript style development. Also there are exists Palm treo with Palm OS, but I think time is gone from Palm. What about blackberry, I never seen it at all, As far as I know it has popularity in US in corporate users, but not in other world. That&#8217;s why I&#8217;m unable discuss this platforms.<br />
I think it’s completed list of main platforms for end-users. Yes I know about BSD (open BSD), minix, Solaris and some others, but this list is mainstream. Looks great, so much different platforms and OSs. But what wrong with this list? Maybe you think:”Nevermind. It&#8217;s not a problem to have so wide range of platforms.”<br />
Ok, Let’s find problem at this platforms list.</p>
<h2><strong> Problems !!!</strong></h2>
<p>And now imagine: I&#8217;m software developer, software company or maybe somebody who needs some kind of application. Let&#8217;s call it X-body.<br />
If i need desktop application (Mac OS, Windows, Linux), then I have choice :<br />
1. Develop separate product for each platform.<br />
2. Choose cross platform tool.<br />
At my own opinion, first choice is overheading. First of all it took at three time more resources (time and human) to develop, and second is future development of products become difficult.  In some point these branches can grow in three totally different products.<br />
That&#8217;s why let&#8217;s see what about cross-platform tools.<br />
<strong>Java</strong>   &#8211; powerful and good decision, but java applications much more slower and need more resources. Also Java applications rely on Java Virtual Machine implementation and version. Developer in some time unable to be sure that application will work on all platforms, JVMs and different JVM versions in the same way. The next thing I really don&#8217;t like in  java &#8211; GUI. There are no good GUI tools and Frameworks (maybe I mistake ?). I know about AWT, SWT and Swing.<br />
<strong>GTK/GObjects/C/C++</strong>Really nice Framework, but it&#8217;s mostly GUI and have only community support. The same is about wxWidgets. What may happend with it tomorrow ?<br />
<strong>.NET/Mono</strong>Really good try. But it still not full-featured Language, and it&#8217;s not so flexible as native applications.<br />
<strong>Adobe Flash/Flex/Air</strong> Hmm, this one hase it&#8217;s own piece of pie in IT industry.<br />
<strong>Scripting:Tcl/Tk, Perl, Python, Ruby &#8230;</strong> Not fast as native, not have direct access to OS specific features.</p>
<p><strong>TAAAATAAAAM</strong><br />
<strong>Qt !!!!!</strong>   Great Job Trolls. Qt is enough to build almost any application, and also it still C++, if some very specific features needed. But almost 95% of regular project is realised only with Qt classes. More about Qt on <a href="http://qt.nokia.com">official site</a>.</p>
<p>In my own opinion Qt is easiest way to implement cross platform application on desktop systems almost for all desktop applications (and not only GUI). Also Qt is natively inside in all modern Linux distributives. Qt hase native look on alien systems: GTK+ based windows managers, Win32, Cocoa.  And please believe me, Qt classes really work the same on every platform. Also Qt is good documented. And the main bonus that QT is LGPL licensed !!! Totally free for commercial and free development. Thank you Nokia !!! And there are exists commercial licence for Qt too.<br />
So many pluses, where is minuses?<br />
I think there are:<br />
1. Not good promoted, that&#8217;s why not so popular. I hope Nokia take some attention not only for symbian integration.<br />
2. Good documentation about API and classes, but I think It will be better to have more  tutorials, webcasts, examples and guidelines. Like Microsoft and Apple.<br />
3. Poor documentation about some useful tools, like makeqpf, macdeployqt, qconfig, qtconfig, qmake and so on. Some times I looked in source code to understand how some feature works.<br />
4. Not very suitable GUI designer, please look on Interface Builder for Mac Os and Delphi with one click for all needed code generation.<br />
5. Not enough 3rd party widgets(especially commercial). It can be fixed by first item.<br />
6. There are no any cross platform deployment tool from Qt. I know only one good : BitRock, but it very expensive, I think. For more information visit <a href="http://bitrock.com/">official BitRock site</a>.</p>
<p>Also I really like QtCreator. A grate step. I&#8217;m also took a part of improving of this product and hope it become most powerful IDE in near future !!!  </p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>12</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=44</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Old Friends grate meeting (Встреча старых друзей :-) )</title>
		<link>http://erudenko.com/wordpress/?p=19</link>
		<comments>http://erudenko.com/wordpress/?p=19#comments</comments>
		<pubDate>Fri, 23 Oct 2009 13:55:27 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[I and my family]]></category>
		<category><![CDATA[me]]></category>
		<category><![CDATA[photo]]></category>
		<category><![CDATA[PVIZ]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=19</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=19">Old Friends grate meeting (Встреча старых друзей :-) )</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Old Friends grate meeting (Встреча]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=19">Old Friends grate meeting (Встреча старых друзей :-) )</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>Hi All. I added photo gallery on meeting with old friends.<br />
Добрый день всем. Вот состоялась встреча выпускников ПВИЗ 2004 года выпуска, группы в которой я учился <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Фотоотчет выложил по адресу:<br />
<a href="http://erudenko.com/photo/2009/pviz">Путь к фоотчетам <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  </a></p>
<p>Комменты можно писать здесь <img src='http://erudenko.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
<div id="attachment_21" class="wp-caption aligncenter" style="width: 510px"><img src="http://erudenko.com/wordpress/wp-content/uploads/2009/10/picture-40.jpg" alt="PVIZ meeting 2009" title="PVIZ2009" width="500" height="333" class="size-full wp-image-21" /><p class="wp-caption-text">PVIZ meeting 2009</p></div></p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>8</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=19</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hello world, from my blog!</title>
		<link>http://erudenko.com/wordpress/?p=3</link>
		<comments>http://erudenko.com/wordpress/?p=3#comments</comments>
		<pubDate>Tue, 23 Jun 2009 21:01:19 +0000</pubDate>
		<dc:creator>Rudenko Eugene</dc:creator>
				<category><![CDATA[About blog life]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[entry]]></category>
		<category><![CDATA[me]]></category>
		<category><![CDATA[moderation]]></category>

		<guid isPermaLink="false">http://erudenko.com/wordpress/?p=3</guid>
		<description><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=3">Hello world, from my blog!</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
Hello world, from my blog!]]></description>
			<content:encoded><![CDATA[<p><a href="http://erudenko.com/wordpress/?p=3">Hello world, from my blog!</a> is an article from: <a href="http://erudenko.com/wordpress">Eugene&nbsp;Rudenko's blog</a>.
The article is produced by Eugene Rudenko, please contact me via my blog, if you have any questions about copy or republish this information.

</p>
<p>Hello. It&#8217;s my first blog post.</p>
<p>First of all a couple of words about me. My name Rudenko Eugene. I&#8217;m software developer. The main target of this blog is to share for everyone me research and development experiences.</p>
<p>And now start. I choose for blog GoDaddy&#8217;s hosting. I like it and I&#8217;ll see what will be in future. I found that WordPress is great blogging system, thanks guys for this product and thank a lot for people that make it more extended with a great collection of plugins and extensions.</p>
<p>And now, the main question !!! What is this block about ? The answer: about me and my research and development (R&amp;D). I&#8217;ll try to tell  you about interesting hacks and show you how to do it and where to find info to get more information.</p>
<p>It&#8217;s was an entry, First hack I going provide you is Word Press hacking.</p>
<p>First of all I&#8217;m going to share my photo gallery in this blog. I&#8217;m using Mac on my main working machine. That&#8217;s why I&#8217;ll going to create export plugin for Apperture and iPhoto to make share process easily for me.</p>
<p>See you soon, have a nice time.</p>
<br/><a href='http://wordpress.org/extend/plugins/mystat/'><img src='http://erudenko.com/wordpress/wp-content/plugins/mystat/images/admin.png' style='vertical-align:middle;' title='myStat statistic for WordPress' border='0' /></a> Unique visitors to post: <b>18</b><br/><br/>]]></content:encoded>
			<wfw:commentRss>http://erudenko.com/wordpress/?feed=rss2&amp;p=3</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
