Про грабли

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

QGIS и SpatiaLite

Собирающие QGIS самостоятельно знают, что не так давно произошел переход на использование внешних библиотек spatialindex и SpatiaLite. Первая была выпилена целиком и полностью. Вторая пока осталась, т.к. в некоторых дистрибутивах (а именно Debian Squeeze, а также Ubuntu Lucid, Maverick, Natty и Oneiric) SpatiaLite либо отсутствует, либо слишком древняя.

По историческим причинам, SpatiaLite можно собрать двумя способами:

  • как модуль расширения к системной SQLite
  • как самостоятельную библиотеку «все-в-одном», объединяющую полноценный движок SQLite и пространственные возможности SpatiaLite

Так вот. Если у вас SpatiaLite собрана как библиотека «все-в-одном», можете распрощаться с поддержкой SpatiaLite в QGIS. Создать новый слой или открыть существующий вы не сможете. Пикантности добавляет тот факт, что и конфигурирование, и сборка проходят идеально: ни отсутствующих файлов, ни ошибок. Выход — пересобрать SpatiaLite в качестве загружаемого модуля, а затем пересобрать QGIS. Правда, на этом шаге можно наступить на другие грабли…

SpatiaLite и Dynamic Linker

Если при сборке загружаемого модуля SpatiaLite в Linux скрипт configure упорно не находит SQLite, GEOS и PROJ.4, хотя они установлены и имеют нужный номер версии, скорее всего ваш дистрибутив придерживается политики использования максимально «чистых» исходных текстов (т.е. при создании пакетов дополнительные патчи накладываются только в случае крайней необходимости).

Помочь должен запуск configure при помощи следующей строки

LDFLAGS=-ldl ./configure

PyQt4 и new style signal-slot connection

Начиная с версии 4.5 в PyQt введен «новый» стиль подключения сигналов и  слотов (подробнее), впрочем и привычный старый никуда не делся. Новый стиль, что называется более Pythonic и всячески рекомендуется к использованию. Только вот… если интерфейс сгененрирован в Qt Designer, а затем сконвертирован в код при помощи pyuic4 и в коде используется новый стиль, то при попытке отсоединить сигнал от слота, можно нарваться на сообщение о невозможности выполнить операцию. Ситуацию прояснило обращение к разработчикам

PyQt allows connections to be made to any Python callable.

With old style connections a proxy slot is created under the covers whenever a callable is used (as opposed to when SLOT() is used to refer to a C++ slot). Therefore, in your example, a proxy is always created for the connection to Dialog.reject even though that refers to the object that wraps the C++ slot (as there is no Python reimplementation of reject()).

New style connections are a bit smarter in that they treat slot objects that refer to a wrapped C++ slot and objects that refer to some real Python code differently – a proxy is only created in the latter case.

So the rule is that if you make a connection old style then you must disconnect old style as well and the same for new style. You also need to be aware that pyuic4 uses old style connections.

Вообще это баг, но исправлять его не будут

I accept that this is a bug, but I don't want to fix it. The reason is that the changes required to the old style support code would be quite significant and I don’t think the risk to the stability of that code is worth it at this stage of the life of PyQt4 particularly as the workaround is straightforward.

Упомянутый workaround заключается в создании слота-заглушки, который просто вызывает слот родительского объекта. Т.е. если надо отключить слот reject() диалога от сигнала rejected(), при использовании старого стиля было достаточно выполнить

QObject.disconnect(self.buttonBox, SIGNAL("rejected()"), self.reject)

и не важно, реализован в вашем диалоге reject() или нет. При использовании нового стиля обязательно надо реализовать reject()

def reject(self):
    QDialog.reject(self)