Mac Style

August 18th, 2010 Begemot

А вот и пошли грабли с Qt look and feel in Mac OS, в принципе то было заранее известно, но все равно плохо. Описал проблему на rsdn


Поиск в SQLite без учета регистра, для русского языка

August 14th, 2010 Begemot

Не смотрю на всю свою юникодность, SQLite все-таки юникодна не до конца:( При поиске типа WHERE description LIKE “%STRING%” поиск идет без учета регистра для латинских букв, но к сожалению, он регистрозависимый для всех остальных символов. Корни этого уходят в виндовую функцию tolower(), которая правильно обрабатывает символы только текущей локали. И это весьма плохо, для целого ряда задач, например для поиска ранее скопированного текста в истории буфера обмена (извините, не удержался:))

Но к счастию способ есть. Оригинал и файлы для загрузки тут – SQLite and native UNICODE LIKE support in C/C++ . А я раскажу о том как это интегрировать и скрестить с wxDatabaselayer’om.

  1. Берем файлы sqlite3_unicode.h/c с архива по ссылке выше и добавляем в проект.
  2. Вызываем свойства sqlite3_unicode.c  и добавляем SQLITE_ENABLE_UNICODE; SQLITE_CORE в определения препроцессора c++/preprocessor/preprocessor definitions
  3. Если используете precompiled header в проекте, надо в свойствах обоих файлов отключить его использование.
  4. в с файле есть строчка #include “sqlite3.h” заменить ее на свой путь к sqlite3.h, если он у вас отличается
  5. Включить sqlite3.h в sqlite3_unicode.h, без этого у меня не компилилось.
  6. Дальше вызываете sqlite3_unicode_load();  \  sqlite3_unicode_free();  –  в начале/конце программы
  7. После открытия базы данных вызываем для нее sqlite3_unicode_init(db);

Проблема тут в том что sqlite3_unicode_init(db); хочет db типа sqlite3 *, а у нас есть только указатель на обьект датабайслаера. Тут придется править код самого wxDatabaselayer’a и заново компилить. Идем в databaselayer\include\SqliteDatabaseLayer.h, пишем:

// Added by Begemot – for using with  sqlite3_unicode
void * GetSQLiteDatabase()  { return m_pDatabase; } 

компиляем, и в нашей программе вместо строчки sqlite3_unicode_init(db); используем вот такую вот страшную конструкцию

sqlite3_unicode_init(static_cast<sqlite3*>(static_cast<SqliteDatabaseLayer*>(db)->GetSQLiteDatabase()));

Все. Теперь Like % прекрасно ищет по русским или любым другим символам без учета регистра.


Тащим wxWidgets в Qt

July 5th, 2010 Begemot

К хорошему быстро привыкаешь. Привык и я к wxCHECK*, тяжко в Qt теперь – там такого нету. Мучился, я мучился и решил – а почему бы и нет?

В итоге добавил себе

//------------------------------------------------------------------------------------------------------------------
// macros ported from wxWidgets

/*
    wxCHECK macros always check their conditions, setting debug level to 0 only
    makes them silent in case of failure, otherwise -- including at default
    debug level 1 -- they call the assert handler if the condition is false

    They are supposed to be used only in invalid situation: for example, an
    invalid parameter (e.g. a NULL pointer) is passed to a function. Instead of
    dereferencing it and causing core dump the function might use

        wxCHECK_RET( p != NULL, "pointer can't be NULL" )
*/


// the generic macro: takes the condition to check, the statement to be execute
// in case the condition is false and the message to pass to the assert handler
#define wxCHECK2_MSG(cond, op, msg)                                       \
    if ( cond )                                                           \
    {}                                                                    \
    else                                                                  \
    {                                                                     \
       Q_ASSERT_X(cond, "", msg);                                         \
       op;                                                                \
    }                                                                     \
    struct wxDummyCheckStruct /* just to force a semicolon */


// check which returns with the specified return code if the condition fails
#define wxCHECK_MSG(cond, rc, msg)   wxCHECK2_MSG(cond, return rc, msg)

// check that expression is true, "return" if not (also FAILs in debug mode)
#define wxCHECK(cond, rc)            wxCHECK_MSG(cond, rc, (const char*)NULL)

// check that expression is true, perform op if not
#define wxCHECK2(cond, op)           wxCHECK2_MSG(cond, op, (const char*)NULL)

// special form of wxCHECK2: as wxCHECK, but for use in void functions
//
// NB: there is only one form (with msg parameter) and it's intentional:
//     there is no other way to tell the caller what exactly went wrong
//     from the void function (of course, the function shouldn't be void
//     to begin with...)
#define wxCHECK_RET(cond, msg)       wxCHECK2_MSG(cond, return, msg)

//------------------------------------------------------------------------------------------------------------------

В связи с поворотами в личной жизни, пока не могу сказать что активно использую это в коде, но вроде работает. Если найду проблемы – отпишусь.


wxWidgets определение размера экрана

June 22nd, 2010 Begemot

В wxWidgets есть wxSystemSettings::GetMetric() который, кроме прочего, позволяет узнать разрешение экрана, но к сожалению не правильно 🙁

Проблемы появляются на мультимониторных конфигурациях. Вызов wxSystemSettings::GetMetric(wxSYS_SCREEN_X); дает нам ширину только первого монитора под Windows (сам проверял) и суммарную ширину обоих мониторов под Линуксом (сведенья из инета). Подозреваю что это баг, но разбиратся, формулировать и спорить некогда, поэтому просто написал воркараунд для себя

#ifdef __WIN32__  
    // wxSystemSettings::GetMetric does not support multy-monitor configuration at Windows, and return parameters only for first monitor, but it seems wots fine under Linux
    const int maxWidth = ::GetSystemMetrics(SM_CXVIRTUALSCREEN);
    const int maxHeight = ::GetSystemMetrics(SM_CYVIRTUALSCREEN);
#else
    const int maxWidth = wxSystemSettings::GetMetric(wxSYS_SCREEN_X);
    const int maxHeight = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y);
#endif

Updated:
Эхх стало стыдно за плохой стиль:(

// wxSystemSettings::GetMetric does not support multy-monitor configuration at Windows and return parameters only for first monitor, but it seems works well under Linux
wxSize BegUtils::GetVirtualDisplayResolution()
{
#ifdef __WIN32__  
    return wxSize(::GetSystemMetrics(SM_CXVIRTUALSCREEN), ::GetSystemMetrics(SM_CYVIRTUALSCREEN));
#else
    return wxSize(wxSystemSettings::GetMetricwxSYS_SCREEN_X), wxSystemSettings::GetMetricwxSYS_SCREEN_Y));
#endif
}


...

    const wxSize resolution = BegUtils::GetVirtualDisplayResolution();

QSqlRelationalTableModel – отстой, и другие грабли

May 31st, 2010 Begemot

Не хотел жаловаться, но все таки не выдержал. Да и все-таки стоит немного рассказать о популярном мифе о зрелости и вылизанности Qt.

Может конечно мне просто не повезло и я попал в самую, самую дремучую чащу. Но судя по всему QSqlRelationalTableModel более чем глючный класс. “Now I do not use QSqlRelationalTable model at all. Useless class. To many errors… and not so good design also.” Qt bugtracker, Дык вот, я полностью согласен. В попытках его освоить нашел 3 или  4 бага, потерял кучу дней. Научившись обходить часть из них и модицифировав базу данных под его “требования”, уперся в очередную проблему. Выжимка из моих проблем с QSqlRelationalTableModel  и ссылки на баги на форуме1.

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

Сегодня утром пишу код для работы с датами, выбрал формат для хранения в бд второй, для отображения на экране. В итоге не работает. Думал опять код работы с бд глючит. Оказалось нет, правду видимо мне сказали что у меня карма плохая поэтому я на баги нарываюсь – из 7 встроенных в Qt форматов перевода времени в строку и обратно, я выбрал Qt::SystemLocaleLongDate – единственный который не работает:) Добавил баг в багтрекер, можно поздравить с почином. Но на фоне QSqlRelationalTableModel, это уже мелочи – просто выбрал другой формат времени, ерунда:)

Ну и раз уж я недавно жаловался на то что взял wxCalendarCtrl и там было пару мелких проблем, то справедливости ради обязан заметить, что QCalendarWidgets – тоже не идеален, сегодня прикручивал. Есть проблемы как в отображении, так и в поведении, и я бы не сказал что совсем мелкие… Но сейчас я уже почему-то спокойнее к этому отношусь 🙂


Qt – те же яйца только в профиль?

May 21st, 2010 Begemot

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

Вернее сделал я это быстро, а потом долго пытался понять почему QDataWidgetMapper автоматически не сохраняет данные, вернее сохраняет, но только 1 раз для первого редактируемого поля. Искал где я мог накосячить, рыл интернет, мысль о баге в либе конечно возникала, но поверить в том что в Qt такая явная бага было трудно.

Похоже все таки действительно бага, вот описание проблемы и не одного ответа, вот баг репорт – обратите внимание на даты.

Или это мне так дико не везет или нет в мире совершенства 🙂

P.s. вот еще тикет по этому же багу, почему-то просто тупо закрыт…


Бег по минному полю к Qt

May 16th, 2010 Begemot

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

Обновился в транке то последней ревизии – бах. Взял компонент который раньше не юзал – бах, бах. , попробовал под мак компилять – бах, бах, бах. И это не образно, это реально то на что я попал за неделю. Каждая проблема это время, нервы, разочарование.

Сейчас повторяется недавняя история, когда я помучавшись с wxWidgets плюнул и написал программу на Objective-C\Cocoa. Потратив пару дней на написание прототипа гуи, вернее самых зачатков прототипа – для того что бы проверить архитеетуру\логику работы. GUI в принципе не самое простое, но и ничего сверх естественного.

Дальше начались проблемы, посидев полдня с напильником под виндой, перейдя с с wxNotebook на AUI версию – удалось добиться приемлемого поведения под виндой. Пошел под Mac OS – там все было достаточно печально, тот же wxAuiNoteebook ведет себя совсем не так как надо (и это я не использовал никаких продвинутых возможностей, типа открепления\перемещения вкладок, просто их показ).

Конечно, я уверен что не решаемых проблем особо нет – можно было опять же достать напильник (что в принципе нормально), изменить подход к построению гуи, вернутся на родной Noteebook, попробовать второй, третий вариант и так далее.

Но что-то я уже был злой и раздосадованный, человек (можно сказать апологет wxWidgets!) стал убеждать, что для моей задачи лучше все-таки использовать Qt, заказчик был изначально больше за Qt чем за wxWidgets…

В общем теперь я очень срочно учу Qt 🙂 Пока остановились на варианте – пишу прототип на нем и потом мы смотрим, сравниваем  и выбираем, но что-то мне подсказывает, что я знаю чем все закончится 🙂


wxPropertyGrid – довольно удобно

May 11th, 2010 Begemot

Есть у меня особенность, люблю когда поведение программы можно тонко настроить. Поэтому у меня в программах обычно куча настроек, причем часть из них скрытые и доступны только прямой правкой конфига, потому что добавлять в гуй кучу мелких опций – не всегда хорошо.

Теперь я нашел выход, делаем в опцию одну страницу Advanced, суем туда wxPropertyGrid, теперь отпадает проблема усложнения GUI кучей мелких опций. К тому же добавление новых настроек превращается в простой и быстрый процесс.

image


Как я изменил wxWidgets

April 13th, 2010 Begemot

Предложили мне тут портировать одну маленькую утилиту для автоматического выключения звука на Mac OS, я сказал что если возьмусь то только на c++\wxWidgets, зачем мне осваивать новый язык\библиотеку…

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

Сначала долго пытался вообще заставить вх собираться и давать мне собрать примеры на маке, потом изучал cmake, потом перешел с carbon версии wxWidgets на более новую cocoa сборку…

В принципе, тут дело в том что у программы достаточно специфичные требования:

  1. Программа маленькая.
  2. Иконка в трее.
  3. Глобальная горячая клавиша.

Последнее вообще не поддерживается в вхВиджетс под маком, второе недавно появилось – но работает через 1 место, ну и размер…

В общем, потратив 4-5 дней, решил плюнуть и писать нативно. Небольшой проект – как раз можно потренироваться на нем. Подумалось что если я и дальше собираюсь писать для мака, даже на wxWidgets, знание родного языка\опыт работы с нативным фремворком будет только большим плюсом.

Objective-C имеет достаточно специфический синтаксис, но в принципе не сложен. Да и в целом писать под мак мне понравилось – такое впечатление что там это как-то гораздо больше продуманнее все.

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

Если кому интересно, посмотреть что получилось, можно тут.


Еще один перевод туториала по wxWidgets

March 31st, 2010 Begemot

Появился новый учебник на русском, помнится я читал этот туториал в оригинале, теперь есть перевод на великий и могучий, замечательно. полезно для начинающих – Перевод руководства The wxWidgets programming tutorial.

Да и в целом сообщество по wxWidgets в livejournal я смотрю ожило, что тоже не может не радовать.

Posted in Учебники | Tags:
Comments Off on Еще один перевод туториала по wxWidgets