diff options
Diffstat (limited to 'examples/animation/photobrowser')
-rw-r--r-- | examples/animation/photobrowser/main.cpp | 52 | ||||
-rw-r--r-- | examples/animation/photobrowser/menu.cpp | 125 | ||||
-rw-r--r-- | examples/animation/photobrowser/menu.h | 50 | ||||
-rw-r--r-- | examples/animation/photobrowser/photobrowser.pro | 17 | ||||
-rw-r--r-- | examples/animation/photobrowser/river.cpp | 561 | ||||
-rw-r--r-- | examples/animation/photobrowser/river.h | 81 | ||||
-rw-r--r-- | examples/animation/photobrowser/riveritem.cpp | 95 | ||||
-rw-r--r-- | examples/animation/photobrowser/riveritem.h | 36 |
8 files changed, 1017 insertions, 0 deletions
diff --git a/examples/animation/photobrowser/main.cpp b/examples/animation/photobrowser/main.cpp new file mode 100644 index 0000000..98f2a9e --- /dev/null +++ b/examples/animation/photobrowser/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include <QtGui> + +#include "river.h" +#include "menu.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + if (app.arguments().size() == 1) { + qWarning("you have to specifiy a path to look for the photos"); + return 0; + } + + + QGraphicsScene scene; + scene.setSceneRect(QRectF(QPointF(), River::fixedSize())); + + QGraphicsView view(&scene); + view.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + view.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + const int fw = view.frameWidth() * 2; + view.setFixedSize(River::fixedSize() + QSize(fw,fw)); + + River river(app.arguments()[1]); + scene.addItem(&river); + + Menu menu(&river); + menu.addAction(QLatin1String("River Mode"), &river, SLOT(setRiverMode())); + menu.addAction(QLatin1String("Grid Mode"), &river, SLOT(setGridMode())); + menu.addAction(QLatin1String("Cover Flow"), &river, SLOT(setCoverMode())); + menu.addAction(QLatin1String("Hide Menu"), &menu, SLOT(hide())); + menu.addAction(QLatin1String("Exit"), &app, SLOT(quit())); + menu.setZValue(2); + menu.setFocus(); + + river.menu = &menu; + view.show(); + + return app.exec(); +} diff --git a/examples/animation/photobrowser/menu.cpp b/examples/animation/photobrowser/menu.cpp new file mode 100644 index 0000000..d4efe9c --- /dev/null +++ b/examples/animation/photobrowser/menu.cpp @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "menu.h" + +Menu::Menu(QGraphicsItem *parent) : QGraphicsWidget(parent), m_selected(0) +{ + setFlag(QGraphicsItem::ItemIsFocusable); + m_selection = new QGraphicsRectItem(this); + QLinearGradient linearGrad(QPointF(0, 0), QPointF(0,50)); + linearGrad.setColorAt(0, QColor(255,255,255,128)); + linearGrad.setColorAt(1, QColor(255,255,255,16)); + m_selection->setBrush(linearGrad); + m_selection->setPen(QPen(Qt::transparent)); +} + +Menu::~Menu() +{ +} + + +MenuAction *Menu::addAction(const QString &text, QObject *receiver, const char* slot) +{ + MenuAction *action = new MenuAction(text, this); + if (!m_actions.isEmpty()) { + MenuAction *last = m_actions.last(); + action->setPos(last->pos() + last->boundingRect().bottomLeft()); + } + m_actions.append(action); + if (m_selection->boundingRect().width() < action->boundingRect().width()) + m_selection->setRect(action->boundingRect()); + + QObject::connect(action, SIGNAL(triggered()), receiver, slot); + return action; +} + +QRectF Menu::boundingRect() const +{ + QRectF res; + foreach (MenuAction *a, m_actions) + res |= a->boundingRect(); + return res; +} + +void Menu::keyPressEvent (QKeyEvent * event) +{ + switch (event->key()) { + case Qt::Key_Escape: + hide(); + break; + case Qt::Key_Up: + m_selected -= 2; + case Qt::Key_Down: + if (!m_actions.isEmpty()) { + m_selected = (m_selected + 1 + m_actions.count()) % m_actions.count(); + QItemAnimation *anim = new QItemAnimation(m_selection, QItemAnimation::Position); + anim->setEndValue(m_actions.at(m_selected)->pos()); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + break; + case Qt::Key_Enter: + case Qt::Key_Return: + if (!m_actions.isEmpty()) { + QItemAnimation *anim = new QItemAnimation(m_selection, QItemAnimation::RotationX); + anim->setEndValue(m_selection->xRotation() < 180 ? qreal(360) : qreal(0)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + m_actions.at(m_selected)->trigger(); + hide(); + } + break; + default: + QGraphicsItem::keyPressEvent(event); + } +} + +void Menu::show() +{ + QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::Opacity); + anim->setEndValue(qreal(1.)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorX); + anim->setEndValue(qreal(1)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorY); + anim->setEndValue(qreal(1)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + setFocus(); +} + +void Menu::hide() +{ + QItemAnimation *anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorX); + anim->setEndValue(qreal(.1)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(m_selection, QItemAnimation::ScaleFactorY); + anim->setEndValue(qreal(.1)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(this, QItemAnimation::Opacity); + anim->setEndValue(qreal(0)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + parentItem()->setFocus(); +} + + +MenuAction::MenuAction(const QString &text, Menu * parent) + : QGraphicsTextItem(text,parent) +{ + QFont f = font(); + f.setPointSize(18); + setFont(f); + setDefaultTextColor(Qt::white); +} + +void MenuAction::trigger() +{ + emit triggered(); +} diff --git a/examples/animation/photobrowser/menu.h b/examples/animation/photobrowser/menu.h new file mode 100644 index 0000000..9514cfe --- /dev/null +++ b/examples/animation/photobrowser/menu.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef __MENU__H__ +#define __MENU__H__ + +#include <QtGui> + +class MenuAction; + +class Menu : public QGraphicsWidget +{ + Q_OBJECT +public: + Menu(QGraphicsItem *parent); + ~Menu(); + + MenuAction *addAction(const QString&, QObject *receiver = 0, const char* slot = 0 ); + + QRectF boundingRect() const; + void keyPressEvent ( QKeyEvent * event ); +public slots: + void show(); + void hide(); +private: + QList<MenuAction*> m_actions; + QGraphicsRectItem *m_selection; + int m_selected; +}; + +class MenuAction : public QGraphicsTextItem +{ + Q_OBJECT +public: + MenuAction(const QString &text, Menu * parent); + void trigger(); +signals: + void triggered(); +}; + + +#endif //__RIVERITEM__H__ diff --git a/examples/animation/photobrowser/photobrowser.pro b/examples/animation/photobrowser/photobrowser.pro new file mode 100644 index 0000000..21f03d6 --- /dev/null +++ b/examples/animation/photobrowser/photobrowser.pro @@ -0,0 +1,17 @@ +###################################################################### +# Automatically generated by qmake (2.01a) ven. 22. août 13:09:33 2008 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp \ + river.cpp \ + riveritem.cpp \ + menu.cpp +HEADERS += river.h \ + riveritem.h \ + menu.h diff --git a/examples/animation/photobrowser/river.cpp b/examples/animation/photobrowser/river.cpp new file mode 100644 index 0000000..f3dd0746 --- /dev/null +++ b/examples/animation/photobrowser/river.cpp @@ -0,0 +1,561 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "river.h" +#include "riveritem.h" + +#include "qvariantanimation.h" + +#include <QtCore/QDebug> +#include <QtGui/QKeyEvent> +#include <QtGui/QGraphicsScene> +#include <QtGui/QPainter> + + +#define GRID_ROW_COUNT 3 +#define GRID_COLUMN_COUNT 2 +#define GRID_DIMENSIONS (GRID_ROW_COUNT * GRID_COLUMN_COUNT) +#define ITEM_COUNT 12 + +#define RIVER_MAGNIFY(ITEM) (qreal(0.50) + (ITEM)->zValue()*2 ) +#define GRID_MAGNIFY qreal(1.5) +#define GRID_CURRENT_MAGNIFY 2 + +River::River(const QString &path) : +m_images(QDir(path).entryInfoList(QStringList() << QLatin1String("*.jpg") << QLatin1String("*.png"))), +m_currentImage(0), m_mode(RiverMode), m_selectedItem(-1) , m_topLeftIndex(-1) +{ + setFocusPolicy(Qt::StrongFocus); + setGeometry(QRectF( QPointF(), fixedSize())); + + + for (int i = 0; i < ITEM_COUNT; ++i) { + RiverItem * item = new RiverItem(this); + + //here we also randomize the x position (not when looping) + const int x = qrand() % fixedSize().width(); + item->setPos(x, -1); + + m_items.insert(m_currentImage, item); + addUnusedRiverItem(item); + } + +} + +QPointF River::gridItemPosition(int row, int col) const +{ + if (col < 0) { + col += GRID_COLUMN_COUNT; + row --; + } + return QPointF(rect().width()*(col*2 + 1)/(GRID_COLUMN_COUNT*2), + rect().height()*(row*2 + 1)/(GRID_ROW_COUNT*2)); +} + +QPixmap River::pixmap(int index) const +{ + if (index < 0 || index >= m_images.size()) + return QPixmap(); + + if (m_pixmaps.size() <= index) { + m_pixmaps.resize(index+1); + } + + if (m_pixmaps.at(index).isNull()) { + m_pixmaps[index] = QPixmap(m_images.at(index).absoluteFilePath()); + } + + return m_pixmaps.at(index); +} + +void River::addUnusedRiverItem(RiverItem * item) +{ + if (m_images.isEmpty()) + return; + + QRectF realItemRect = item->mapToParent(item->boundingRect()).boundingRect(); + + int y = item->pos().y(); + int x = item->pos().x(); + if (x >= fixedSize().width() || x < -realItemRect.width() || y < 0) { + //we set the new pixmap + + m_items.remove(m_items.key(item)); + + while (m_items.contains(m_currentImage)) + m_currentImage = (m_currentImage + 1 ) % m_images.size(); + + item->setPixmap(pixmap(m_currentImage)); + + m_items.insert(m_currentImage, item); + //this manages looping as well + m_currentImage = (m_currentImage + 1 ) % m_images.size(); + + item->setZValue(qreal(qrand()%100)/200.0); + + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(RIVER_MAGNIFY(item)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(RIVER_MAGNIFY(item)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + + realItemRect = item->mapToParent(item->boundingRect()).boundingRect(); + + y = -realItemRect.y() + qrand() % (fixedSize().height() - int(realItemRect.height())); + if (x >= fixedSize().width()) { + x = -realItemRect.width()/2; + } + } + + item->setPos(x, y); + + const QPointF target(QPointF(fixedSize().width() + realItemRect.width()/2, y)); + + const int distance = target.x() - x; + + const int duration = (40 - 50*item->zValue() ) * distance; + QItemAnimation *a = new QItemAnimation(item, QItemAnimation::Position, scene()); + a->setEndValue(target); + a->setDuration(duration); + a->start(QAbstractAnimation::DeleteWhenStopped); + connect(a, SIGNAL(finished()), SLOT(animationFinished())); +} + +void River::animationFinished() +{ + QItemAnimation *anim = qobject_cast<QItemAnimation*>(sender()); + if (!anim || anim->propertyName() != QItemAnimation::Position) + return; + + /*RiverItem *item = static_cast<RiverItem*>(anim->graphicsItem()); + if (m_mode != RiverMode) {*/ + /*int key = m_items.key(item); + if (key < m_topLeftIndex || key >= m_topLeftIndex + GRID_DIMENSIONS) { + delete item; + m_items.remove(key); + }*/ + //return; + + //} + + addUnusedRiverItem(static_cast<RiverItem*>(anim->targetItem())); +} + +void River::switchPaused() +{ + const bool paused = m_pausedAnimations.isEmpty(); + if (paused) + m_pausedAnimations = scene()->findChildren<QItemAnimation*>(); + + foreach(QItemAnimation *anim, m_pausedAnimations) { + if (paused) + anim->pause(); + else + anim->resume(); + } + + if (!paused) + m_pausedAnimations.clear(); +} + +void River::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + painter->fillRect(option->rect, Qt::black); +} + +void River::setMode(Mode m) +{ + if (m_mode == m) + return; + + Mode oldMode = m_mode; + m_mode = m; + switch(m) + { + case RiverMode: + m_mode = oldMode; //some animation may be stopt, and we don't want that animationFinished we were in that mode yet + foreach (RiverItem *item, m_items) { + const int x = qrand() % fixedSize().width(); + const int y = qrand() % fixedSize().width(); + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(RIVER_MAGNIFY(item)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(RIVER_MAGNIFY(item)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(QPointF(x, y)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + connect(anim, SIGNAL(finished()), SLOT(animationFinished())); + } + m_mode = m; + break; + + case GridMode: + + if (oldMode == GridFullScreenMode) { + currentItem()->setFullScreen(false, GRID_CURRENT_MAGNIFY); + } else { + m_topLeftIndex = -GRID_DIMENSIONS; + foreach (RiverItem *item, m_items) { + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + adjustGrid(m_currentImage - GRID_DIMENSIONS + 1); + setCurrentItem(m_topLeftIndex); + } + break; + case GridFullScreenMode: + //let's put the current item fullscreen + currentItem()->setFullScreen(true, GRID_CURRENT_MAGNIFY); + break; + case CoverMode: + m_gridItem = m_items.values(); + setCurrentItem(m_gridItem.count()/2); + default: + break; + } +} + +River::Mode River::mode() const +{ + return m_mode; +} + +QSize River::fixedSize() +{ + return QSize(352, 416); +} + +//the name of this method is not that good... +void River::makeCenterAvailable(qreal size) +{ + QRectF center(QPointF(), QSizeF(size, size)); + center.moveCenter(rect().center()); + + const QList<QGraphicsItem*> list = scene()->items(center); + + foreach(QGraphicsItem *item, m_items) { + + if (!list.contains(item)) + continue; + + QPointF pos = item->pos(); + + if (pos.y() < rect().center().y()) { + //item is above center + pos.ry() = center.top() - item->boundingRect().height() - 1; + } else { + //item is below the center + pos.ry() = center.bottom() + 1; + } + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(pos); + anim->setDuration(150); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } +} + + +//this is there just to test small interaction +void River::keyPressEvent ( QKeyEvent * keyEvent ) +{ + switch(keyEvent->key()) + { + case Qt::Key_O: + { + QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::Opacity, scene()); + anim->setDuration(2000); + anim->setEndValue(qreal(.5)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + break; + case Qt::Key_N: + //that's a test + makeCenterAvailable(60); + break; + case Qt::Key_P: + switchPaused(); + break; + case Qt::Key_V: + setMode(GridMode); + break; + case Qt::Key_R: + setMode(RiverMode); + break; + case Qt::Key_C: + setMode(CoverMode); + break; + case Qt::Key_Return: + case Qt::Key_Enter: + if (m_mode == RiverMode) { + setMode(GridMode); + } else if (m_mode == GridMode) { + setMode(GridFullScreenMode); + } else if (m_mode == GridFullScreenMode) { + setMode(GridMode); + } + break; + case Qt::Key_Escape: + if (m_mode == GridFullScreenMode) { + setMode(GridMode); + } else if (m_mode == GridMode || m_mode == CoverMode) { + setMode(RiverMode); + } else if (m_mode == RiverMode) { + menu->show(); + } + break; + case Qt::Key_Right: + if (m_mode == GridMode) { + navigateBy(+1); + } else if (m_mode == CoverMode) { + setCurrentItem(m_selectedItem + 1); + } + break; + case Qt::Key_Left: + if (m_mode == GridMode) { + navigateBy(-1); + } else if (m_mode == CoverMode) { + setCurrentItem(m_selectedItem - 1); + } + break; + case Qt::Key_Down: + if (m_mode == GridMode) { + navigateBy(GRID_COLUMN_COUNT); + } + break; + case Qt::Key_Up: + if (m_mode == GridMode) { + navigateBy(-GRID_COLUMN_COUNT); + } + break; +// case Qt::Key_PageUp: + case Qt::Key_M: + menu->show(); + break; + case Qt::Key_Space: + if (m_mode == GridMode) { + RiverItem *item = currentItem(); + if(!item) + break; + + //stupid sequence. + QPointF pos = item->pos(); + QAnimationGroup *group = new QSequentialAnimationGroup(); + //item->animator()->beginSequence(); + + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(pos); + group->addAnimation(anim); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(qreal(1.)); + anim->setDuration(500); + group->addAnimation(anim); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(qreal(1.)); + anim->setDuration(500); + group->addAnimation(anim); + anim = new QItemAnimation(item, QItemAnimation::RotationX, scene()); + anim->setEndValue(qreal(0)); + group->addAnimation(anim); + group->start(QAbstractAnimation::DeleteWhenStopped); + } + default: + break; + } + + QGraphicsItem::keyPressEvent(keyEvent); +} + + +void River::setGridMode() +{ + setMode(GridMode); +} + +void River::setRiverMode() +{ + setMode(RiverMode); +} + +void River::setCoverMode() +{ + setMode(CoverMode); +} + + +void River::adjustGrid(int newTopLeft) +{ + for (int i = newTopLeft ; i < newTopLeft + GRID_DIMENSIONS; i++) { + if (!m_items.contains(i)) { + RiverItem *item = createItem(i); + int row = (i - m_topLeftIndex) / GRID_COLUMN_COUNT; + int col = (i - m_topLeftIndex) % GRID_COLUMN_COUNT; + item->setPos(gridItemPosition(row, col)); + item->setXScale(0); + item->setYScale(0); + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + } + newTopLeft = newTopLeft - newTopLeft % GRID_COLUMN_COUNT; + + QHash<int, RiverItem *>::iterator it = m_items.begin(); + while (it != m_items.constEnd()) { + const int imageIdx = it.key(); + RiverItem *item = *it; + QSizeF itemSize = item->boundingRect().size(); + if ((imageIdx >= newTopLeft && imageIdx < newTopLeft + GRID_DIMENSIONS) + || boundingRect().adjusted(-itemSize.width()/2, -itemSize.height()/2, itemSize.width()/2, itemSize.height()/2) + .contains(item->pos())) { + int row = (imageIdx-newTopLeft) / GRID_COLUMN_COUNT; + int col = (imageIdx-newTopLeft) % GRID_COLUMN_COUNT; + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(gridItemPosition(row, col)); + anim->start(QAbstractAnimation::DeleteWhenStopped); + ++it; + } else { + ++it; /* ### ideally we should remove the items, but this cause the photobrowser to crash + because the QItemAnimations are not notified the item is deleted + delete item; + it = m_items.erase(it); + */ + } + } + + m_topLeftIndex = newTopLeft; +} + + +RiverItem *River::createItem(int imageIndex) +{ + Q_ASSERT(!m_items.contains(imageIndex)); + RiverItem * item = new RiverItem(this); + item->setPixmap(pixmap(imageIndex)); + m_items.insert(imageIndex,item); + return item; +} + +void River::setCurrentItem(int newCurrentItem) +{ + if (m_mode == CoverMode) + { + m_selectedItem = newCurrentItem; + for (int i = 0; i < m_gridItem.count(); i++) { + QVariantAnimation *anim; + RiverItem *item = m_gridItem.at(i); + + qreal rotation = 0; + qreal width = boundingRect().width() / 2; + qreal x = width; + qreal scale = 3; + qreal z = 1; + qreal y = boundingRect().height()/2; + + if (i < newCurrentItem - 4) { + item->setVisible(false); + item->setPos(QPointF(0, y)); + continue; + } else if(i > newCurrentItem + 4) { + item->setVisible(false); + item->setPos(QPointF(boundingRect().width(), y)); + continue; + } else if (i < newCurrentItem) { + x = (i - newCurrentItem + 4) * width/7; + rotation = -75; + scale = 2; + z = 1.+qreal(i-newCurrentItem)/10.; + } else if (i > newCurrentItem) { + x = width + (i - newCurrentItem + 3) * width/7; + rotation = 75; + scale = 2; + z = 1.-qreal(i-newCurrentItem)/8.; + } + + item->setVisible(true); + item->setZValue(z); + + anim = new QItemAnimation(item, QItemAnimation::RotationY, scene()); + anim->setEndValue(rotation); + anim->start(QAbstractAnimation::DeleteWhenStopped); + + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(scale); + anim->start(QVariantAnimation::DeleteWhenStopped); + + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(scale); + anim->start(QVariantAnimation::DeleteWhenStopped); + + anim = new QItemAnimation(item, QItemAnimation::Position, scene()); + anim->setEndValue(QPointF(x,y)); + anim->start(QVariantAnimation::DeleteWhenStopped); + } + return; + } + + + //deselect the current item + if (m_selectedItem >= 0 && m_items.contains(m_selectedItem)) { + RiverItem *item = m_items.value(m_selectedItem); + item->setZValue(qreal(qrand()%100)/200.0); + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(GRID_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + } + + if (newCurrentItem < 0) { + m_selectedItem = newCurrentItem; + return; + } + + //ensure visible; + if (newCurrentItem < m_topLeftIndex) { + adjustGrid(newCurrentItem); + } else if (newCurrentItem >= m_topLeftIndex + GRID_DIMENSIONS) { + adjustGrid(newCurrentItem - GRID_DIMENSIONS + GRID_COLUMN_COUNT); + } + + //select the new one + m_selectedItem = newCurrentItem; + RiverItem *item = currentItem(); + Q_ASSERT(item); + item->setZValue(1); + + QItemAnimation *anim = new QItemAnimation(item, QItemAnimation::ScaleFactorX, scene()); + anim->setEndValue(GRID_CURRENT_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); + anim = new QItemAnimation(item, QItemAnimation::ScaleFactorY, scene()); + anim->setEndValue(GRID_CURRENT_MAGNIFY); + anim->start(QAbstractAnimation::DeleteWhenStopped); +} + +void River::navigateBy(int offset) +{ + int newSelection = m_selectedItem + offset; + const int imageCount = m_images.size(); + while (newSelection < 0) + newSelection += imageCount; + newSelection %= imageCount; + setCurrentItem(newSelection); +} diff --git a/examples/animation/photobrowser/river.h b/examples/animation/photobrowser/river.h new file mode 100644 index 0000000..25bf62a --- /dev/null +++ b/examples/animation/photobrowser/river.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef __RIVER__H__ +#define __RIVER__H__ + +#include <QtCore/QDirIterator> +#include <QtGui/QGraphicsWidget> + +#include "menu.h" + +class RiverItem; + +class River : public QGraphicsWidget +{ + Q_OBJECT +public: + enum Mode + { + RiverMode, + GridMode, + GridFullScreenMode, + CoverMode + }; + + River(const QString &path); + void addUnusedRiverItem(RiverItem * item); + + static QSize fixedSize(); + + void switchPaused(); + + void setMode(Mode m); + Mode mode() const; + + Menu *menu; + +protected: + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void keyPressEvent ( QKeyEvent * keyEvent ); + void makeCenterAvailable(qreal size); + QPointF gridItemPosition(int row, int col) const; + QPixmap pixmap(int index) const; + +protected slots: + void animationFinished(); +public slots: + void setRiverMode(); + void setGridMode(); + void setCoverMode(); + +private: + const QFileInfoList m_images; + int m_currentImage; + mutable QVector<QPixmap> m_pixmaps; + QHash<int, RiverItem*> m_items; + QList<RiverItem*> m_gridItem; + QList<QItemAnimation*> m_pausedAnimations; + Mode m_mode; + + void adjustGrid(int topRight); + RiverItem *currentItem() { return m_items.value(m_selectedItem); } + RiverItem *createItem(int imageIndex); + void setCurrentItem(int currentItem); + void navigateBy(int offset); + + int m_selectedItem; + int m_topLeftIndex; + +}; + + +#endif //__RIVERITEM__H__ diff --git a/examples/animation/photobrowser/riveritem.cpp b/examples/animation/photobrowser/riveritem.cpp new file mode 100644 index 0000000..f6523a7 --- /dev/null +++ b/examples/animation/photobrowser/riveritem.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "riveritem.h" +#include "river.h" + +RiverItem::RiverItem(QGraphicsItem *parent) : QGraphicsPixmapItem(parent), m_fullscreen(false) +{ + setCacheMode(DeviceCoordinateCache); +} + +RiverItem::~RiverItem() +{ +} + +void RiverItem::setPixmap(const QPixmap &pix) +{ + const QSize oldSize = pixmap().size(); + const QSize newSize = pix.size(); + QGraphicsPixmapItem::setPixmap(pix); + + if (newSize != oldSize) { + setOffset(-newSize.width()/2, -newSize.height()/2); + const qreal scaleFactor = qreal(River::fixedSize().height())/(qreal(pix.height()*7)); + setTransform(QTransform().scale(scaleFactor, scaleFactor)); + prepareGeometryChange(); + } +} + + +void RiverItem::setFullScreen(bool b, qreal originScaleFactor) +{ + if (m_fullscreen == b) + return; + + m_fullscreen = b; + + QPointF newPos; + qreal rotationZ; + qreal scaleX, scaleY; + + if (b) { + const QSizeF basePixmapSize = transform().map(boundingRect()).boundingRect().size(); + + newPos = parentItem()->boundingRect().center(); + rotationZ = 90; + scaleY = qreal(River::fixedSize().width()) / basePixmapSize.height() * yScale(); + scaleX = qreal(River::fixedSize().height()) / basePixmapSize.width() * xScale(); + + if (m_nonFSPos.isNull()) { + m_nonFSPos = pos(); //let's save our current (non fullscreen) position + } + + } else { + Q_ASSERT(!m_nonFSPos.isNull()); + rotationZ = 0; + scaleX = originScaleFactor; + scaleY = originScaleFactor; + newPos = m_nonFSPos; + } + + QAnimationGroup *group = new QParallelAnimationGroup(scene()); + QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::Position); + anim->setEndValue(newPos); + group->addAnimation(anim); + anim = new QItemAnimation(this, QItemAnimation::RotationZ); + anim->setEndValue(rotationZ); + group->addAnimation(anim); + anim = new QItemAnimation(this, QItemAnimation::ScaleFactorX); + anim->setEndValue(scaleX); + group->addAnimation(anim); + anim = new QItemAnimation(this, QItemAnimation::ScaleFactorY); + anim->setEndValue(scaleY); + group->addAnimation(anim); + group->start(QAbstractAnimation::DeleteWhenStopped); +} + +void RiverItem::mousePressEvent(QGraphicsSceneMouseEvent*) +{ + //just let it rotate on itself + QItemAnimation *anim = new QItemAnimation(this, QItemAnimation::RotationY); + anim->setEndValue(yRotation() < 180 ? 360 : 0); + anim->setDuration(500); + anim->start(QAbstractAnimation::DeleteWhenStopped); +} + + diff --git a/examples/animation/photobrowser/riveritem.h b/examples/animation/photobrowser/riveritem.h new file mode 100644 index 0000000..39fdcc2 --- /dev/null +++ b/examples/animation/photobrowser/riveritem.h @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef __RIVERITEM__H__ +#define __RIVERITEM__H__ + +#include <QtGui/QGraphicsPixmapItem> + +class RiverItemAnimator; + +class RiverItem : public QGraphicsPixmapItem +{ +public: + RiverItem(QGraphicsItem *parent); + ~RiverItem(); + + void setPixmap(const QPixmap &); + void setFullScreen(bool b, qreal originScaleFactor); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent*); + +private: + QPointF m_nonFSPos; //to save the position when not in fullscreen + bool m_fullscreen; +}; + +#endif //__RIVERITEM__H__ |