#ifndef TRANSACTIONTHREAD_H
#define TRANSACTIONTHREAD_H
#include <QThread>
#include <QMutex>
#include <QImage>
#include <QQueue>
#include <QWaitCondition>
class Transaction
{
public:
virtual ~Transaction() { }
virtual QImage apply(const QImage &image) = 0;
virtual QString message() = 0;
};
class FlipTransaction : public Transaction
{
public:
FlipTransaction(Qt::Orientation orientationC);
QImage apply(const QImage &image);
QString message();
private:
Qt::Orientation orientation;
};
class transactionthread : public QThread
{
Q_OBJECT
public:
transactionthread(/*QObject *parent*/);
~transactionthread();
void addTransaction(Transaction *transact);
void setImage(const QImage &image);
QImage image();
signals:
void transactionStarted(const QString &message);
void allTransactionsDone();
protected:
void run();
private:
QImage currentImage;
QQueue<Transaction *> transactions;
QWaitCondition transactionAdded;
QMutex mutex;
};
#endif // TRANSACTIONTHREAD_H
#include "transactionthread.h"
Transaction * const EndTransaction = 0;
transactionthread::transactionthread(/*QObject *parent*/)
: QThread(/*parent*/)
{
start();
}
transactionthread::~transactionthread()
{
//{
// QMutexLocker locker(&mutex);
// while (!transactions.isEmpty())
// delete transactions.dequeue();
// transactions.enqueue(EndTransaction);
// transactionAdded.wakeOne();
//}
//wait();
}
void transactionthread::addTransaction(Transaction *transact)
{
QMutexLocker locker(&mutex);
transactions.enqueue(transact);
transactionAdded.wakeOne();
}
void transactionthread::setImage(const QImage &image)
{
QMutexLocker locker(&mutex);
currentImage=image;
}
QImage transactionthread::image()
{
QMutexLocker locker(&mutex);
return currentImage;
}
void transactionthread::run()
{
Transaction *transact = 0;
QImage oldImage;
forever {
{
QMutexLocker locker(&mutex);
if (transactions.isEmpty())
transactionAdded.wait(&mutex);
transact = transactions.dequeue();
if (transact == EndTransaction)
break;
oldImage = currentImage;
}
emit transactionStarted(transact->message());
QImage newImage = transact->apply(oldImage);
delete transact;
{
QMutexLocker locker(&mutex);
currentImage = newImage;
if (transactions.isEmpty())
emit allTransactionsDone();
}
}
}
FlipTransaction::FlipTransaction(Qt::Orientation orientationC)
{
this->orientation=orientationC;
}
QImage FlipTransaction::apply(const QImage &image)
{
return image.mirrored(orientation == Qt::Horizontal,
orientation == Qt::Vertical);
}
QString FlipTransaction::message()
{
if (orientation == Qt::Horizontal) {
return QObject::tr("Flipping image horizontally...");
} else {
return QObject::tr("Flipping image vertically...");
}
}
#ifndef IMAGEPRO_H
#define IMAGEPRO_H
#include <QtGui/QMainWindow>
#include "transactionthread.h"
#include "ui_imagepro.h"
class imagePro : public QMainWindow
{
Q_OBJECT
public:
imagePro(QWidget *parent = 0, Qt::WFlags flags = 0);
~imagePro();
private slots:
void open();
void flipHorizontally();
void flipVertically();
void allTransactionsDone2();
private:
Ui::imageProClass ui;
void loadFile(const QString &fileName);
void addTransactionC(Transaction *transactC);
transactionthread thread/*QObject *parent*/;
};
#endif // IMAGEPRO_H
#include "imagepro.h"
#include <QtGui>
imagePro::imagePro(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
connect(ui.actionOpen,SIGNAL(triggered()),this,SLOT(open()));
connect(ui.actionH,SIGNAL(triggered()),this,SLOT(flipHorizontally()));
connect(ui.actionV,SIGNAL(triggered()),this,SLOT(flipVertically()));
connect(&thread, SIGNAL(allTransactionsDone()),
this, SLOT(allTransactionsDone2()));
}
imagePro::~imagePro()
{
}
void imagePro::open()
{
// QMessageBox::about(this, tr("About Image Pro"),
//tr("<h2>Image Pro 1.1</h2>"
//"<p>Copyright © 2008 Software Inc."
//"<p>Image Pro is a small application that demonstrates "
//"signal-slot connections across threads."));
QString fileName = QFileDialog::getOpenFileName(this);
if (!fileName.isEmpty())
loadFile(fileName);
}
void imagePro::flipHorizontally()
{
addTransactionC(new FlipTransaction(Qt::Horizontal));
}
void imagePro::flipVertically()
{
addTransactionC(new FlipTransaction(Qt::Vertical));
}
void imagePro::allTransactionsDone2()
{
ui.label->setPixmap(QPixmap::fromImage(thread.image()));
//setWindowModified(true);
//statusBar()->showMessage(tr("Ready"), 2000);
}
void imagePro::loadFile(const QString &fileName)
{
QImage newImage;
bool loaded=newImage.load(fileName);
thread.setImage(newImage);
ui.label->setPixmap(QPixmap::fromImage(newImage));
}
void imagePro::addTransactionC(Transaction *transactC)
{
thread.addTransaction(transactC);
}
#include "imagepro.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
imagePro w;
w.show();
return a.exec();
}