частью конструктора ImageWindow являются два соединения сигнал—слот. В обоих случаях сигнал генерируется объектом TransactionThread, который мы вскоре рассмотрим.
Слот flipHorizontally создает транзакцию зеркального отражения и регистрирует ее при помощи закрытой функции addTransaction. Функции flipVertically, resizeImage, convertTo32Bit, convertTo8Bit и convertTo1Bit реализуются аналогично.
Функция addTransaction добавляет транзакцию в очередь транзакций вторичного потока и отключает команды Open, Save и Save As на время обработки транзакций.
Функция addTransaction добавляет транзакцию в очередь транзакций и запускает поток транзакции, если он еще не выполняется. Доступ к переменной—члену transactions защищается мьютексом, потому что главный поток мог бы ее модифицировать функцией addTransaction во время прохода по транзакциям transactions вторичного потока.
Функции setImage и image позволяют главному потоку установить изображение, для которого будут выполняться транзакции, и получить обработанное изображение после завершения всех транзакций. И вновь мы защищаем доступ к переменной—члену при помощи мьютекса.
01 void TransactionThread::run
02 {
03 Transaction *transact;
04 forever {
05 mutex.lock;
06 if (transactions.isEmpty) {
07 mutex.unlock;
08 break;
09 }
10 QImage oldImage = currentImage;
11 transact = transactions.dequeue;
12 mutex.unlock;
13 emit transactionStarted(transact->message);
14 QImage newImage = transact->apply(oldImage);
15 delete transact;
16 mutex.lock;
17 currentImage = newImage;
18 mutex.unlock;
19 }
20 }
Функция run просматривает очередь транзакций и по очереди выполняет все транзакции путем вызова для них функции apply.
После старта транзакции мы генерируем сигнал transactionStarted с сообщением, выводимым в строке состояния приложения. Когда обработка всех транзакций завершается, функция run возвращает управление и QThread генерирует сигнал finished.