QT 4: программирование GUI на С++
Шрифт:
Функция capabilities возвращает объект, который показывает, что может делать с данным форматом изображений обработчик изображений. Существует три возможных действия (CanRead, CanWrite и CanReadIncremental), а возвращаемое значение объединяет допустимые варианты порязрадной логической операцией ИЛИ.
Если формат «cur», наша реализация возвращает CanRead. Если формат не задан, мы создаем обработчик курсора и проверяем его способность чтения данных с заданного устройства. Функция canRead только просматривает данные и проверяет возможность распознавания файла, не изменяя указатель файла. Возвращение 0
Когда файл курсора открыт (например, с помощью класса QImageReader), будет вызвана функция оболочки подключаемого модуля create с передачей указателя устройства и формата «cur». Мы создаем экземпляр CursorHandler для заданного устройства и формата. Вызывающая программа становится владельцем обработчика и удалит его, когда он не станет нужен. Если приходится считывать несколько файлов, для каждого из них создается новый обработчик.
В конце файла .cpp мы используем макрос Q_EXPORT_PLUGIN2, чтобы гарантировать распознавание в Qt подключаемого модуля. В первом параметре задается произвольное имя, используемое нами для подключаемого модуля. Второй параметр содержит имя класса подключаемого модуля.
Подкласс QImageIOPlugin создается достаточно просто. Реальная работа подключаемого модуля делается обработчиком. Обработчики форматов изображений должны создать подкласс QImageIOHandler и переопределить некоторые или все его открытые функции. Сначала рассмотрим заголовочный файл:
Открытые функции имеют фиксированную сигнатуру. Здесь нет некоторых функций, которые не надо переопределять в обработчике, обеспечивающем только чтение, в частности отсутствует функция write. Переменные—члены объявляются с ключевым словом mutable, потому что они изменяются внутри константных функций.
После создания обработчика мы сначала настраиваем его параметры. Номер текущего изображения
курсора устанавливается на первый курсор, но поскольку переменная количества изображений numImages принимает значение 0, ясно, что у нас пока еще нет изображений.Функция canRead может вызываться в любой момент для определения возможности считывания обработчиком изображений дополнительных данных с устройства. Если функция вызывается до чтения данных в состоянии BeforeHeader, выполняется проверка конкретной метки, по которой опознаются файлы курсоров в Windows. Вызов QIODevice::peek считывает первые четыре байта без изменения указателя файла на данном устройстве. Если функция canRead вызывается позже, мы возвращаем true при отсутствии ошибки.
Эта простая функция возвращает номер курсора, на который позиционирован указатель файла устройства.
После создания обработчика пользователь может вызвать любую его открытую функцию, причем последовательность вызовов функций может быть произвольной. В этом кроется потенциальная проблема, поскольку необходимо исходить из того, что файл можно читать только последовательно, поэтому сначала надо один раз считать заголовок файла и затем выполнять какие-то другие действия. Эту проблему решаем путем вызова readHeaderIfNecessary в тех функциях, для которых требуется предварительное считывание заголовка файла.
Эта функция возвращает количество изображений, содержащихся в файле. Для правильного файла, при чтении которого не возникает ошибок, она возвращает по крайней мере 1.
Рис. 19.2. Формат файла .cur.
Следующая функция довольно сложная, поэтому мы рассмотрим ее по частям:
Функция read считывает данные изображения, начинающегося в текущей позиции указателя устройства. Если успешно считан заголовок файла или указатель устройства после чтения изображения находится в начале другого изображения, можно считывать следующее изображение.