silvansky programming stuff

5Oct/100

Q_OBJECT special

занятная фишка: нельзя объявлять классы-наследники от QObject вне хедеров (если мы хотим использовать сигналы-слоты). если объявить такой класс в .cpp-шнике, то линковщик будет ругаться на vtable. ибо qmake плохо обрабатывает .cpp-шники...

UPD: один хороший человек подсказал солюшн: надо в конце .cpp-шника сделать #include "myfile.moc". я не проверял, но говорят, что работает.

Tagged as: , , No Comments
4Oct/100

QMenuBar, symbian

Лучше не пытайтесь кастомизировать стандартные меню (те, которые вешаются на софткеи) симбиана с помощью stylesheet'ов! Я вот попытался. В итоге вместо стандартных меню получил пустоту (просто не отрисовались они), при попытке нажать на них клик передаётся окну под моим.

В общем, для реализации своего меню со своим дизайном пришлось создавать QToolBar + QToolButton'ы с меню. Смотрится гораздо лучше. А хоткеи навесить легко с помощью QAction'ов.

18Aug/100

qt symbian plugins

Не знаю, как у вас, а у меня всегда что-то компилится.

так вот, сегодня собираем плагины под симбиан.

если хочешь собрать плагин под симбиан, то надо сделать вот что. в .pro файле плагина пишем так:

TEMPLATE        = lib
CONFIG         += plugin
TARGET          = $$qtLibraryTarget(myplugin)

symbian: {
	load(data_caging_paths)
	TARGET.EPOCALLOWDLLDATA=1
	TARGET.UID3 = 0xXXXXXXXX
	TARGET.CAPABILITY += "LocalServices Location NetworkServices ReadUserData UserEnvironment WriteUserData"
	# dummy deployment (for qt creator)
	plugin.sources = myplugin.dll
	plugin.path = !:/sys/bin
	DEPLOYMENT += plugin
}

UID3 указывается индивидально. например, получить UID можно на сайте SymbianSigned

последние три строки кода нужны для qt creator'а, чтобы он создал .sis файл. нам это не нужно, но криейтор без этого не может.

в принципе, всё. плагин готов (если конечно содержимое у него адекватное). теперь самое простое - деплой вместе с приложением. например, для деплоя плагина в папку !:/Private/XXXXXXXX/plugins (XXXXXXXX - UID приложения), надо в .pro нашей проги написать:

symbian: {
	plugins.sources = myplugin.dll \
			myplugin2.dll
	plugins.path = ./plugins
	DEPLOYMENT += plugins
}

теперь всё готово. можно собирать. искать плагины надо в QApplication::applicationDirPath() + "/plugins". и можно радоваться жизни.

10Aug/100

qt + symbian

итак, чудо из чудес: qt под symbian.
чудо качается в виде Nokia Qt SDK и устанавливается как и обычный qt sdk. при этом всё работает хорошо, даже замечательно - эмулятор, отладка на девайсе... и так далее.
но всё так только до тех пор, пока не потребуется собрать что-то сложное. тут-то и начинается веселье!

замечу, что я до того не имел дела с программированием под симбиан. только qt.

итак!

во-первых, текущая версия Nokia Qt SDK (1.0) не умеет собирать под симбиан проекты с TEMPLATE = subdirs. точнее, что-то как-то собирается, но сплошные ошибки. от этого лучше сразу отказаться.

далее. если хочешь собрать библиотеку, то столкнёшься с такой штукой: qt creator обязательно (!) выполняет в конце make sis. и это не отключить. так что даже если не хочется создавать инсталлятор отдельно для библиотеки, то делать это придётся, если собирать из криейтора. делается это просто, но всё же это излишество.

вот собственно пример:

# экспортируем хедеры
BLD_INF_RULES.prj_exports += utilsexport.h \
                             utils.h
# заглушка для qt creator'а, создаём инсталлятор
myFiles.sources = utils.dll
myFiles.path = !:/sys/bin
DEPLOYMENT += myFiles

итак, теперь у нас есть библиотека, лежит она в \Symbian\SDK\epoc32\release\gcce\udeb\ (или \urel\ если собиралась в релизе). но есть и лишний .sis файл... ну да ладно, на него забьём спокойно.
вообще, на этом этапе может возникнуть ошибка борки. но мы это поправим так (из командной строки с подключенными переменными среды из SDK - в главном меню есть ярлык):

abld freeze

после чего собираем снова - и всё, должно заработать.

заметим так же, что есть такое понятие, как капабилитиз, их надо указать, если проект будет хоть что-то делать с сетью, например. подробнее можно почитать тут.

если что-то не работает, то указываем все капабилити, доступные для самоподписанного приложения:

TARGET.CAPABILITY += "LocalServices Location NetworkServices ReadUserData UserEnvironment WriteUserData"

теперь собираем проект, который эту библиотеку цеплять будет.

в проекте пишем стандартные вещи (LIBS += -lutils), прописываем те же капабилитиз, что и у библиотеки. кроме того, опять терзаем DEPLOYMENT, т.к. автоматически в него добавляются только файлы текущего проекта (да и то только если это не библиотека):

utils.sources = utils.dll
utils.path = !:/sys/bin
DEPLOYMENT += utils

казалось бы, что всё готово. собираем. если всё хорошо, то получаем .sis файл с прогой и библиотекой. чтобы убедиться, что в нём всё это есть, юзаем утилиту dumpsis.

ну что ж, если прога относительно простая, то всё готово, можно заливать на девайс и тестить. или воспользоваться Remote Device Access. должно заработать.

в моём случае такой номер прошёл только с самым простым приложением. а вот с портированием сложного началась веселуха...

всё собралось. я обрадовался. заливаю на девайс - а он мне говорит, что не может дать приложению необходимые права для установки. почему? я ничего такого особого не юзал, чтоб так вот меня отшивать... нехорошо. ладно, почитал, погуглил, сделал Open Signed Online, установилось. ура? ан нет! не запускается. тупо молча не запускается. перевод телефона в дебаговый режим и экспериментирование с кодом ничего не дали.

что выясняется? а выясняется, что qt creator ещё слишком сырой для полноценной разработки под симбиан.
dumpsis + makesis сделали дело. всё заработало. вуаля!
поясняю. получили .sis файл, распаковываем его с помощью dumpsis и упаковываем заново с помощью makesis. круто? конечно круто! теперь опять делаем открытое подписывание и всё наконец-то работает!

чудеса техники.

Tagged as: , , , No Comments
3Jun/100

как выдрать редактор QSS (Qt StyleSheets) из QtDesigner

в QtDesigner'е есть очень хорошая штука - редактор StyleSheet'ов. он соответственно имеет подсветку CSS. а значит, это может быть полезно.
в моём случае это не только полезно, но и нужно, так как избавляет от необходимости с нуля писать эту самую подсветку.
где взять?
качаем исходники Qt, заходим в tools/designer/src/lib/shared/ и находим там файлы stylesheeteditor.cpp и stylesheeteditor_p.h
после их изучения приходим к выводу, что нужны нам другие файлы: csshighlighter.cpp и csshighlighter_p.h
дальше что делать понятно.

с подсветкой синтаксиса всё понятно. но что же делать с валидацией? тут обратим внимание на отвергнутые в начале файлы и увидим там функцию StyleSheetEditorDialog::isStyleSheetValid, которая юзает namespace QCss, который опять таки не публичный и который надо копать...

копаем сюда: src/gui/text/ файлы qcssparser_p.h и qcssparser.cpp. это всё тянет за собой qcssscanner.cpp.

в общем, теперь можно приступать к сборке "с миру по нитке" своего редактора stylesheet'ов с валидацией и подсветкой.
а если хочется ещё и вставку и редактор градиентов........... то надо копать в сторону QtGradientViewDialog. ищите и обрящете! обращем же этот диалог в tools/shared/qtgradienteditor/
пока всё.

UPD: после детального изучения данного вопроса и долгого ковыряния в исходниках Qt, был написан тестовый проект, который включает в себя этот самый редактор QSS.
вот то, что реально вошло в проект и нужно для работы редактора без интеграции с дизайнером:

csshighlighter.*
qdesigner_utils.*
stylesheeteditor.*
[DIR] qtgradienteditor

разумеется, пришлось выбросить работу с ресурсами. кроме того, градиенты хранятся только для текущего запуска. можно сделать их сохранение, но пока не хочется...

31May/100

наследование

воистину, если серьёзно не хватает функционала класса, единственно верный способ - сабклассинг!

5May/100

код

иногда можно встретить весьма специфический код:

MyClass * item = (MyClass*)true;
Tagged as: , No Comments
16Mar/100

сборка Qt под Windows Mobile (MSVS 2008)

для сборки сабжа использовал следующий батник (раздобыт на просторах инета, модифицирован, собирает так же WebKit и Phonon, всё в релизе и дебаге):

@echo off
echo Setting up a Qt environment...

set QTDIR=D:\Qt\4.6.2_CE
echo -- QTDIR set to D:\Qt\4.6.2_CE
set PATH=D:\Qt\4.6.2_CE\bin;C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN;%PATH%
echo -- Added D:\Qt\4.6.2_CE\bin to PATH
set QMAKESPEC=win32-msvc2008
echo -- QMAKESPEC set to "win32-msvc2008"

call "C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\vsvars32.bat"

echo -- Start configure
configure -platform win32-msvc2008 -xplatform wincewm50pocket-msvc2005 -opensource -stl -webkit -phonon -phonon-backend -multimedia -audio-backend -qt-style-cleanlooks -phonon-wince-ds9 -debug-and-release
echo -- Configure ok

set INCLUDE=C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\include;c:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Include\Armv4i
echo -- set INCLUDE=C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\include;c:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Include\Armv4i
set LIB=C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\lib\armv4i;c:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Lib\ARMV4I
echo -- set LIB=C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\lib\armv4i;c:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Lib\ARMV4I
set PATH=C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\bin\x86_arm;%PATH%
echo -- set PATH=C:\Program Files\Microsoft Visual Studio 9.0\VC\ce\bin\x86_arm;%PATH%

echo -- Start nmake
nmake
echo -- end nmake

12Mar/100

Qt Balloon Tip

оказывается, в Qt есть таки QBalloonTip!
только спрятан он в src/gui/util/qsystemtrayicon_p.h и src/gui/util/qsystemtrayicon.cpp
его оттуда можно извлечь и переделать, чтобы отвязать от QSystemTrayIcon и позволить ему показываться где надо.
моя реализация как раз компилится.

12Mar/100

caps lock

как программно определить, включен ли caps lock?

решение платформозависимо.

Windows:


#include <windows.h>

int i = GetKeyState(VK_CAPITAL);
bool caps_on = (i == 1);

что угодно, но с иксами (X11), будь то Linux, Unix, etc...:
(тянет за собой libx11-dev, требует -lX11)

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>

Display * Dpy = XOpenDisplay((char*)0);
bool caps_on = false;
if (Dpy)
{
    unsigned n;
    XkbGetIndicatorState(Dpy, XkbUseCoreKbd, &n);
    caps_on = (n & 0x01) == 1;
}

UPD: как показал опыт, в иксах включать достаточно XKBLib.h. при этом если это юзать в QT, то возникают глюки использования QEvent (см. X11/X.h):

#define KeyPress                2
#define KeyRelease              3
#define ButtonPress             4
#define ButtonRelease           5
#define MotionNotify            6
#define EnterNotify             7
#define LeaveNotify             8
#define FocusIn                 9
#define FocusOut                10
#define KeymapNotify            11
#define Expose                  12
#define GraphicsExpose          13
#define NoExpose                14
#define VisibilityNotify        15
#define CreateNotify            16
#define DestroyNotify           17
#define UnmapNotify             18
#define MapNotify               19
#define MapRequest              20
#define ReparentNotify          21
#define ConfigureNotify         22
#define ConfigureRequest        23
#define GravityNotify           24
#define ResizeRequest           25
#define CirculateNotify         26
#define CirculateRequest        27
#define PropertyNotify          28
#define SelectionClear          29
#define SelectionRequest        30
#define SelectionNotify         31
#define ColormapNotify          32
#define ClientMessage           33
#define MappingNotify           34
#define LASTEvent               35      /* must be bigger than any event # */

это конфликтует с этим (см. qcoreevent.h):

enum Type {
        /*
          If you get a strange compiler error on the line with None,
          it's probably because you're also including X11 headers,
          which #define the symbol None. Put the X11 includes after
          the Qt includes to solve this problem.
        */
        None = 0,                               // invalid event
        Timer = 1,                              // timer event
        MouseButtonPress = 2,                   // mouse button pressed
        MouseButtonRelease = 3,                 // mouse button released
        MouseButtonDblClick = 4,                // mouse button double click
        MouseMove = 5,                          // mouse move
        KeyPress = 6,                           // key pressed
        KeyRelease = 7,                         // key released
        FocusIn = 8,                            // keyboard focus received
        FocusOut = 9,                           // keyboard focus lost
        Enter = 10,                             // mouse enters widget
        Leave = 11,                             // mouse leaves widget
        Paint = 12,                             // paint widget
        Move = 13,                              // move widget
        Resize = 14,                            // resize widget
        Create = 15,                            // after widget creation
        Destroy = 16,                           // during widget destruction
        Show = 17,                              // widget is shown
        Hide = 18,                              // widget is hidden
        Close = 19,                             // request to close widget
        Quit = 20,                              // request to quit application
        ParentChange = 21,                      // widget has been reparented
        ParentAboutToChange = 131,              // sent just before the parent change is done
// ... etc ...

в частности в пунктах FocusIn, FocusOut, KeyPress...
так что если юзать указанный мной подход, надо делать #undef для конфликтующих имён.

#include <X11/XKBlib.h>
#undef KeyPress
#undef FocusIn
// ... etc ...

так что этот подход лишает нас возможности юзать события иксов в QT. что ж, не очень-то и хотелось ))

UPD 2: а вообще лучше это вынести в отдельный файл, тогда конфликтов не будет.