Открытые функции имеют фиксированную сигнатуру. Здесь нет некоторых функций, которые не надо переопределять в обработчике, обеспечивающем только чтение, в частности отсутствует функция
01 CursorHandler::CursorHandler()
02 {
03 state = BeforeHeader;
04 currentImageNo = 0;
05 numImages = 0;
06 }
После создания обработчика мы сначала настраиваем его параметры. Номер текущего изображения курсора устанавливается на первый курсор, но поскольку переменная количества изображений
01 bool CursorHandler::canRead() const
02 {
03 if (state == BeforeHeader) {
04 return device()->peek(4) == QByteArray("\0\0\2\0", 4);
05 } else {
06 return state != Error;
07 }
08 }
Функция
01 int CursorHandler::currentImageNumber() const
02 {
03 return currentImageNo;
04 }
Эта простая функция возвращает номер курсора, на который позиционирован указатель файла устройства.
После создания обработчика пользователь может вызвать любую его открытую функцию, причем последовательность вызовов функций может быть произвольной. В этом кроется потенциальная проблема, поскольку необходимо исходить из того, что файл можно читать только последовательно, поэтому сначала надо один раз считать заголовок файла и затем выполнять какие-то другие действия. Эту проблему решаем путем вызова
01 int CursorHandler::imageCount() const
02 {
03 readHeaderIfNecessary();
04 return numImages;
05 }
Эта функция возвращает количество изображений, содержащихся в файле. Для правильного файла, при чтении которого не возникает ошибок, она возвращает по крайней мере 1.
Следующая функция довольно сложная, поэтому мы рассмотрим ее по частям:
01 bool CursorHandler::read(QImage *image)
02 {
03 readHeaderIfNecessary();
04 if (state != BeforeImage)
05 return false;
Функция
06 quint32 size;
07 quint32 width;
08 quint32 height;
09 quint16 numPlanes;
10 quint16 bitsPerPixel;
11 quint32 compression;
12 QDataStream in(device());
13 in.setByteOrder(QDataStream::LittleEndian);
14 in >> size;
15 if (size != 40) {
16 enterErrorState();
17 return false;
18 }
19 in >> width >> height >> numPlanes >> bitsPerPixel >> compression;
20 height /= 2;
21 if (numPlanes != 1 || bitsPerPixel != 1 || compression != 0) {
22 enterErrorState();
23 return false;
24 }
25 in.skipRawData((size - 20) + 8);