class InformationWindow : public QDialog
{
Q_OBJECT
public:
InformationWindow(int id, QSqlRelationalTableModel *offices,QWidget *parent = 0);
int id();
signals:
void imageChanged(int id, const QString &fileName);
private slots:
void revert();
void submit();
void enableButtons(bool enable = true);
private:
void createButtons();
int locationId;
QString displayedImage;
QComboBox *imageFileEditor;
QLabel *locationText;
QLabel *countryText;
QTextEdit *descriptionEditor;
QPushButton *closeButton;
QPushButton *submitButton;
QPushButton *revertButton;
QDialogButtonBox *buttonBox;
QDataWidgetMapper *mapper;
};
InformationWindow::InformationWindow(int id, QSqlRelationalTableModel *offices,
QWidget *parent)
: QDialog(parent)
{
QLabel *locationLabel = new QLabel(tr("Location: "));
QLabel *countryLabel = new QLabel(tr("Country: "));
QLabel *descriptionLabel = new QLabel(tr("Description: "));
QLabel *imageFileLabel = new QLabel(tr("Image file: "));
createButtons();
locationText = new QLabel;
countryText = new QLabel;
descriptionEditor = new QTextEdit;
imageFileEditor = new QComboBox;
imageFileEditor->setModel(offices->relationModel(1)); imageFileEditor->setModelColumn(offices->relationModel(1)->fieldIndex("file"));
mapper = new QDataWidgetMapper(this);
mapper->setModel(offices);
mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
mapper->setItemDelegate(new QSqlRelationalDelegate(mapper));
mapper->addMapping(imageFileEditor, 1);
mapper->addMapping(locationText, 2);
mapper->addMapping(countryText, 3);
mapper->addMapping(descriptionEditor, 4);
mapper->setCurrentIndex(id);
connect(descriptionEditor, SIGNAL(textChanged()),
this, SLOT(enableButtons()));
connect(imageFileEditor, SIGNAL(currentIndexChanged(int)),
this, SLOT(enableButtons()));
QGridLayout *layout = new QGridLayout;
layout->addWidget(locationLabel, 0, 0, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(countryLabel, 1, 0, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(imageFileLabel, 2, 0, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(descriptionLabel, 3, 0, Qt::AlignLeft | Qt::AlignTop);
layout->addWidget(locationText, 0, 1);
layout->addWidget(countryText, 1, 1);
layout->addWidget(imageFileEditor, 2, 1);
layout->addWidget(descriptionEditor, 3, 1);
layout->addWidget(buttonBox, 4, 0, 1, 2);
setLayout(layout);
locationId = id;
displayedImage = imageFileEditor->currentText();
setWindowFlags(Qt::Window);
enableButtons(false);
setWindowTitle(tr("Trolltech Office: %1").arg(locationText->text()));
resize(320, sizeHint().height());
}
int InformationWindow::id()
{
return locationId;
}
void InformationWindow::revert()
{
mapper->revert();
enableButtons(false);
}
void InformationWindow::submit()
{
QString newImage(imageFileEditor->currentText());
if (displayedImage != newImage) {
displayedImage = newImage;
emit imageChanged(locationId, newImage);
}
mapper->submit();
mapper->setCurrentIndex(locationId);
enableButtons(false);
}
void InformationWindow::createButtons()
{
closeButton = new QPushButton(tr("&Close"));
revertButton = new QPushButton(tr("&Revert"));
submitButton = new QPushButton(tr("&Submit"));
closeButton->setDefault(true);
connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
connect(revertButton, SIGNAL(clicked()), this, SLOT(revert()));
connect(submitButton, SIGNAL(clicked()), this, SLOT(submit()));
buttonBox = new QDialogButtonBox;
buttonBox->addButton(submitButton, QDialogButtonBox::ResetRole);
buttonBox->addButton(revertButton, QDialogButtonBox::ResetRole);
buttonBox->addButton(closeButton, QDialogButtonBox::RejectRole);
}
void InformationWindow::enableButtons(bool enable)
{
revertButton->setEnabled(enable);
submitButton->setEnabled(enable);
}
class View : public QGraphicsView
{
Q_OBJECT
public:
View(const QString &offices, const QString &images, QWidget *parent = 0);
protected:
void mouseReleaseEvent(QMouseEvent *event);
private slots:
void updateImage(int id, const QString &fileName);
private:
void addItems();
InformationWindow* findWindow(int id);
void showInformation(ImageItem *image);
QGraphicsScene *scene;
QList informationWindows;
QSqlRelationalTableModel *officeTable;
};
View::View(const QString &offices, const QString &images, QWidget *parent)
: QGraphicsView(parent)
{
officeTable = new QSqlRelationalTableModel(this);
officeTable->setTable(offices);
officeTable->setRelation(1, QSqlRelation(images, "locationid", "file"));
officeTable->select();
scene = new QGraphicsScene(this);
scene->setSceneRect(0, 0, 465, 615);
setScene(scene);
addItems();
QGraphicsPixmapItem *logo = scene->addPixmap(QPixmap(":/logo.png"));
logo->setPos(30, 515);
setMinimumSize(470, 620);
setMaximumSize(470, 620);
setWindowTitle(tr("Trolltech World Wide"));
}
void View::addItems()
{
int officeCount = officeTable->rowCount();
int imageOffset = 150;
int leftMargin = 70;
int topMargin = 40;
for (int i = 0; i < officeCount; i++) {
ImageItem *image;
QGraphicsTextItem *label;
QSqlRecord record = officeTable->record(i);
int id = record.value("id").toInt();
QString file = record.value("file").toString();
QString location = record.value("location").toString();
int columnOffset = ((i / 3) * 37);
int x = ((i / 3) * imageOffset) + leftMargin + columnOffset;
int y = ((i % 3) * imageOffset) + topMargin;
image = new ImageItem(id, QPixmap(":/" + file));
image->setData(0, i);
image->setPos(x, y);
scene->addItem(image);
label = scene->addText(location);
QPointF labelOffset((150 - label->boundingRect().width()) / 2, 120.0);
label->setPos(QPointF(x, y) + labelOffset);
}
}
void View::mouseReleaseEvent(QMouseEvent *event)
{
if (QGraphicsItem *item = itemAt(event->pos())) {
if (ImageItem *image = qgraphicsitem_cast(item))
showInformation(image);
}
QGraphicsView::mouseReleaseEvent(event);
}
void View::showInformation(ImageItem *image)
{
int id = image->id();
if (id < 0 || id >= officeTable->rowCount())
return;
InformationWindow *window = findWindow(id);
if (window && window->isVisible()) {
window->raise();
window->activateWindow();
} else if (window && !window->isVisible()) {
window->show();
} else {
InformationWindow *window;
window = new InformationWindow(id, officeTable, this);
connect(window, SIGNAL(imageChanged(int, QString)),
this, SLOT(updateImage(int, QString)));
window->move(pos() + QPoint(20, 40));
window->show();
informationWindows.append(window);
}
}
void View::updateImage(int id, const QString &fileName)
{
QList items = scene->items();
while(!items.empty()) {
QGraphicsItem *item = items.takeFirst();
if (ImageItem *image = qgraphicsitem_cast(item)) {
if (image->id() == id){
image->setPixmap(QPixmap(":/" +fileName));
image->adjust();
break;
}
}
}
}
InformationWindow* View::findWindow(int id)
{
QList::iterator i, beginning, end;
beginning = informationWindows.begin();
end = informationWindows.end();
for (i = beginning; i != end; ++i) {
InformationWindow *window = (*i);
if (window && (window->id() == id))
return window;
}
return 0;
}
class ImageItem : public QObject, public QGraphicsPixmapItem
{
Q_OBJECT
public:
ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent = 0,
QGraphicsScene *scene = 0);
void adjust();
int id();
protected:
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
private slots:
void setFrame(int frame);
void updateItemPosition();
private:
QTimeLine timeLine;
int recordId;
double z;
};
ImageItem::ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent,
QGraphicsScene *scene)
: QGraphicsPixmapItem(pixmap, parent, scene)
{
recordId = id;
setAcceptsHoverEvents(true);
timeLine.setDuration(150);
timeLine.setFrameRange(0, 150);
connect(&timeLine, SIGNAL(frameChanged(int)), this, SLOT(setFrame(int)));
connect(&timeLine, SIGNAL(finished()), this, SLOT(updateItemPosition()));
adjust();
}
void ImageItem::hoverEnterEvent(QGraphicsSceneHoverEvent * /*event*/)
{
timeLine.setDirection(QTimeLine::Forward);
if (z != 1.0) {
z = 1.0;
updateItemPosition();
}
if (timeLine.state() == QTimeLine::NotRunning)
timeLine.start();
}
void ImageItem::hoverLeaveEvent(QGraphicsSceneHoverEvent * /*event*/)
{
timeLine.setDirection(QTimeLine::Backward);
if (z != 0.0)
z = 0.0;
if (timeLine.state() == QTimeLine::NotRunning)
timeLine.start();
}
void ImageItem::setFrame(int frame)
{
adjust();
QPointF center = boundingRect().center();
translate(center.x(), center.y());
scale(1 + frame / 330.0, 1 + frame / 330.0);
translate(-center.x(), -center.y());
}
void ImageItem::adjust()
{
QMatrix matrix;
matrix.scale(150/ boundingRect().width(), 120/ boundingRect().height());
setMatrix(matrix);
}
int ImageItem::id()
{
return recordId;
}
void ImageItem::updateItemPosition()
{
setZValue(z);
}