Big progress for People dialog. Phenom work.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7573 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2014-09-28 20:46:56 +00:00
parent 28277c53df
commit 9efc43f41c
15 changed files with 3630 additions and 133 deletions

View file

@ -0,0 +1,755 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "gui/common/FlowLayout.h"
#include <QApplication>
#include <QtGui>
#include <QDebug>
//*** FlowLayoutItem **********************************************************
void FlowLayoutItem::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
m_startPos = event->pos();
}//if (event->button() == Qt::LeftButton)
QWidget::mousePressEvent(event);
}
void FlowLayoutItem::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton) {
int distance = (event->pos() - m_startPos).manhattanLength();
if (distance >= QApplication::startDragDistance())
performDrag();
}//if (event->buttons() & Qt::LeftButton)
QWidget::mouseMoveEvent(event);
}
void FlowLayoutItem::performDrag()
{
QMimeData *mimeData = new QMimeData;
mimeData->setText(m_myName);
QDrag *drag = new QDrag(this);
drag->setMimeData(mimeData);
QPixmap pixmap=getDragImage();
drag->setPixmap(pixmap.scaled(50,50,Qt::KeepAspectRatio, Qt::SmoothTransformation));
/// Warning On Windows, Drag Pixmap size cannot exceed 50*50. ///
drag->setHotSpot(QPoint(0, 0));
Qt::DropAction dropAction = drag->exec(Qt::CopyAction);
qDebug()<<dropAction;
}
void FlowLayoutItem::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event);
QWidget::mouseReleaseEvent(event);
}
void FlowLayoutItem::dragEnterEvent(QDragEnterEvent *event)
{
FlowLayoutItem *source =
qobject_cast<FlowLayoutItem *>(event->source());
if (source && source != this) {
event->setDropAction(Qt::CopyAction);
event->acceptProposedAction();
return;
}//if (source && source != this)
QWidget *wid =
qobject_cast<QWidget *>(event->source());//QT5 return QObject
FlowLayout *layout = 0;
if (wid) layout =
qobject_cast<FlowLayout *>(wid->layout());
if (layout) {
event->setDropAction(Qt::CopyAction);
event->acceptProposedAction();
return;
}//if (layout)
}
void FlowLayoutItem::dragMoveEvent(QDragMoveEvent *event)
{
FlowLayoutItem *source =
qobject_cast<FlowLayoutItem *>(event->source());
if (source && source != this) {
event->setDropAction(Qt::CopyAction);
event->acceptProposedAction();
return;
}//if (source && source != this)
QWidget *wid =
qobject_cast<QWidget *>(event->source());//QT5 return QObject
FlowLayout *layout = 0;
if (wid) layout =
qobject_cast<FlowLayout *>(wid->layout());
if (layout) {
event->setDropAction(Qt::CopyAction);
event->acceptProposedAction();
return;
}//if (layout)
}
void FlowLayoutItem::dropEvent(QDropEvent *event)
{
QList <FlowLayoutItem*> list;
FlowLayoutItem *source =
qobject_cast<FlowLayoutItem *>(event->source());
if (source && source != this) {
event->setDropAction(Qt::CopyAction);
list << source;
} else {//if (source && source != this)
QWidget *wid =
qobject_cast<QWidget *>(event->source());//QT5 return QObject
FlowLayout *layout;
if (wid) layout =
qobject_cast<FlowLayout *>(wid->layout());
if (layout) {
QList<QLayoutItem *> listSel = layout->selectionList();
int count = listSel.count();
for (int curs = 0; curs < count; ++curs){
QLayoutItem *layoutItem = listSel.at(curs);
FlowLayoutItem *flItem = 0;
if (layoutItem) flItem = qobject_cast<FlowLayoutItem*>(layoutItem->widget());
if (flItem) list << flItem;
}//for (int curs = 0; curs < count; ++curs)
}//if (layout)
}//else (source && source != this)
if (!list.isEmpty()) {
event->setDropAction(Qt::CopyAction);
bool bAccept=true;
emit flowLayoutItemDropped(list, bAccept);
if (bAccept) event->acceptProposedAction();
}//if (!list.empty())
}
//*** FlowLayoutWidget **********************************************************
FlowLayoutWidget::FlowLayoutWidget(QWidget *parent, int margin/*=-1*/, int hSpacing/*=-1*/, int vSpacing/*=-1*/)
: QWidget(parent)
{
FlowLayoutWidget(margin, hSpacing, vSpacing);
}
FlowLayoutWidget::FlowLayoutWidget(int margin/*=-1*/, int hSpacing/*=-1*/, int vSpacing/*=-1*/)
{
FlowLayout *fl = new FlowLayout(this, margin, hSpacing, vSpacing);
Q_UNUSED(fl)
this->installEventFilter(this);
this->setMouseTracking(true);
this->setAcceptDrops(true);
m_saParent = 0;
m_sbVertical = 0;
}
FlowLayoutWidget::~FlowLayoutWidget()
{
}
bool FlowLayoutWidget::eventFilter(QObject *obj, QEvent *event)
{
qDebug() << "FlowLayoutWidget:: obj type:" << obj->metaObject()->className() << " event type:" << event->type();
updateParent();
if (event->type() == QEvent::DragEnter) {
QDragEnterEvent *dragEnterEvent = static_cast<QDragEnterEvent *>(event);
if (dragEnterEvent){
dragEnterEvent->setDropAction(Qt::IgnoreAction);
dragEnterEvent->accept();
}//if (dragEnterEvent)
}//if (event->type() == QEvent::DragEnter)
if (event->type() == QEvent::DragMove) {
QDragMoveEvent *dragMoveEvent = static_cast<QDragMoveEvent *>(event);
const int border = 20;
if (obj==this && dragMoveEvent){
if (m_sbVertical){
int maxY = m_sbVertical->maximum();
int currentY = m_sbVertical->value();
int height = m_saParent->height();
int topBorder = currentY + border;
int bottomBorder = currentY + height - border;
int dragY = dragMoveEvent->pos().y();
qDebug() <<"Drag event:" << dragY ;
int dY = (dragY<topBorder)?dragY - topBorder:((dragY>bottomBorder)?dragY - bottomBorder:0);
qDebug() << "dY:" << dY << " m_lastYPos:" << m_lastYPos << "(dragY-m_lastYPos)*dY:" << (dragY-m_lastYPos)*dY;
int newValue=currentY+dY;
if ((abs(dY)<border) && ((dragY-m_lastYPos)*dY >= 0)){
if (newValue>maxY) newValue=maxY;
if (newValue<0) newValue=0;
m_sbVertical->setValue(newValue);
} else {
newValue=currentY;
}//if ((abs(dY)<border) && ((dragY-m_lastYPos)*dY >= 0))
m_lastYPos = dragY+(newValue-currentY);
}//if (sbVertical)
}//if (obj==this && dragMoveEvent)
if (obj==m_sbVertical && dragMoveEvent){
if (m_sbVertical->isVisible()){
int maxY = m_sbVertical->maximum();
double height = m_sbVertical->height()*1.0;
double scale = (maxY/height);
int dragY = dragMoveEvent->pos().y();
qDebug() << "Drag maxY:" << maxY << "height:" << height << "scale:" << scale << "dragY:" << dragY;
m_sbVertical->setValue(dragY*scale);
}//if (sbVertical->isVisible())
}//if (obj==this && dragMoveEvent)
}//if (event->type() == QEvent::DragMove)
// standard event processing
return QObject::eventFilter(obj, event);
}
void FlowLayoutWidget::updateParent()
{
if (parent()){
if (!m_saParent){
if (parent()->objectName() == "qt_scrollarea_viewport"){
m_saParent = qobject_cast<QScrollArea*>(parent()->parent());
} else {
m_saParent = qobject_cast<QScrollArea*>(parent());
}//if (parent()->objectName() == "qt_scrollarea_viewport")
if (m_saParent){
m_saParent->installEventFilter(this);
m_saParent->setAcceptDrops(true);
m_saParent->setMouseTracking(true);
}//if (saParent)
}//if (!saParent)
if (m_saParent && !m_sbVertical){
m_sbVertical= m_saParent->verticalScrollBar();
if (m_sbVertical){
m_sbVertical->installEventFilter(this);
m_sbVertical->setAcceptDrops(true);
m_sbVertical->setMouseTracking(true);
}//if (sbVertical)
}//if (saParent && !sbVertical)
}//if (parent())
}
//*** FlowLayout **********************************************************
FlowLayout::FlowLayout(QWidget *parent, int margin/*=-1*/, int hSpacing/*=-1*/, int vSpacing/*=-1*/)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
this->installEventFilter(this);
}
FlowLayout::FlowLayout(int margin/*=-1*/, int hSpacing/*=-1*/, int vSpacing/*=-1*/)
: m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
this->installEventFilter(this);
}
FlowLayout::~FlowLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}
bool FlowLayout::eventFilter(QObject *obj, QEvent *event)
{
qDebug() << "FlowLayout::obj type:" << obj->metaObject()->className() << " event type:" << event->type();
if (event->type() == QEvent::MouseButtonPress) {
m_startPos = QCursor::pos();
}//if (event->type() == QEvent::MouseButtonPress)
if (event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
int distance = (QCursor::pos() - m_startPos).manhattanLength();
if (distance < QApplication::startDragDistance()){
unsetCurrent();
m_currentIndex=indexAtGlobal(QCursor::pos());
setCurrent();
bool invert = (mouseEvent->modifiers() &= Qt::ControlModifier);
if (mouseEvent->modifiers() &= Qt::ShiftModifier){
m_selStartIndex=(m_selStartIndex<m_currentIndex)?m_selStartIndex:m_currentIndex;
m_selStopIndex=(m_selStopIndex>m_currentIndex)?m_selStopIndex:m_currentIndex;
} else {
m_selStartIndex=m_selStopIndex=m_currentIndex;
if (mouseEvent->modifiers() != Qt::ControlModifier){
foreach (QLayoutItem *item, m_selectionList) {
FlowLayoutItem *fli = qobject_cast<FlowLayoutItem *>(item->widget());
if (fli) fli->setIsSelected(false);
m_selectionList.removeOne(item);
}
}//if (mouseEvent->modifiers() != Qt::ControlModifier)
}//if (mouseEvent->modifiers()
addSelection(invert);
setCurrent();
}//if (distance < QApplication::startDragDistance())
doLayout(geometry(),false);
}//if (event->type() == QEvent::MouseButtonRelease)
if (event->type() == QEvent::MouseMove) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
if (mouseEvent->buttons() & Qt::LeftButton) {
int distance = (QCursor::pos() - m_startPos).manhattanLength();
if (distance >= QApplication::startDragDistance()){
if (!m_selectionList.isEmpty()) {
QLayoutItem *item=itemAtGlobal(m_startPos);
if (item) {
if (m_selectionList.contains(item)){
performDrag();
return true; // eat event
}//if (m_selectionList.contains(item))
}//if (item)
}//if (!m_selectionList.isEmpty())
}//if (distance >= QApplication::startDragDistance())
}//if (mouseEvent->buttons() & Qt::LeftButton)
}//if (event->type() == QEvent::MouseMove)
if (event->type() == QEvent::KeyRelease) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if ((keyEvent->key()==Qt::Key_A) && (keyEvent->modifiers() &= Qt::ControlModifier)){
int count = m_itemList.count();
int selected = m_selectionList.count();
if (count != selected){
for (int curs=0; curs<count; ++curs){
QLayoutItem *item=itemAt(curs);
if (item) {
if (!m_selectionList.contains(item)){
FlowLayoutItem *fli = qobject_cast<FlowLayoutItem *>(item->widget());
if (fli) fli->setIsSelected(true);
m_selectionList.append(item);
}//if (!m_selectionList.contains(item))
}//if (item)
}//for (int curs=0; curs<count; ++curs)
} else {
foreach (QLayoutItem *item, m_selectionList) {
FlowLayoutItem *fli = qobject_cast<FlowLayoutItem *>(item->widget());
if (fli) fli->setIsSelected(false);
m_selectionList.removeOne(item);
}
}//if (count != selected)
doLayout(geometry(),false);
event->accept();
}//if ((keyEvent->key()==Qt::Key_A) && (keyEvent->modifiers() &= Qt::ControlModifier))
if ((keyEvent->key()==Qt::Key_Space)){
if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier)){
addSelection((keyEvent->modifiers() &= Qt::ControlModifier));
}//if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier))
doLayout(geometry(),false);
m_selStartIndex = m_selStopIndex = m_currentIndex;
event->accept();
}//if ((keyEvent->key()==Qt::Key_Space))
if ((keyEvent->key()==Qt::Key_Left)){
unsetCurrent();
if (m_currentIndex>0) m_currentIndex-=1;
if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier)){
m_selStartIndex=m_currentIndex;
addSelection((keyEvent->modifiers() &= Qt::ControlModifier));
}//if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier))
doLayout(geometry(),false);
m_selStartIndex = m_selStopIndex = m_currentIndex;
event->accept();
setCurrent();
}//if ((keyEvent->key()==Qt::Key_Left))
if ((keyEvent->key()==Qt::Key_Right)){
unsetCurrent();
if (m_currentIndex<(m_itemList.count()-1)) m_currentIndex+=1;
if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier)){
m_selStopIndex=m_currentIndex;
addSelection((keyEvent->modifiers() &= Qt::ControlModifier));
}//if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier))
doLayout(geometry(),false);
m_selStartIndex = m_selStopIndex = m_currentIndex;
event->accept();
setCurrent();
}//if ((keyEvent->key()==Qt::Key_Right))
if ((keyEvent->key()==Qt::Key_Up)){
unsetCurrent();
QLayoutItem* item = currentItem();
if (item) {
QRect loc = item->geometry();
int vSpace = verticalSpacing();
QPoint pos = QPoint(loc.left()+loc.width()/2, loc.top()-vSpace-2);
int index = -1;
while ((pos.y()>0) && (index < 0)){
index = indexAtParent(pos);
pos.setY(pos.y()-2);
}//while ((pos.y()>0) && (index < 0))
m_currentIndex = (index>0)?index:0;
m_currentIndex = (index<=m_itemList.count())?index:m_itemList.count();
if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier)){
m_selStopIndex = m_currentIndex;
addSelection((keyEvent->modifiers() &= Qt::ControlModifier));
}//if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier))
doLayout(geometry(),false);
m_selStartIndex = m_selStopIndex = m_currentIndex;
event->accept();
}//if (wid)
setCurrent();
}//if ((keyEvent->key()==Qt::Key_Right))
if ((keyEvent->key()==Qt::Key_Down)){
unsetCurrent();
QLayoutItem* item = currentItem();
if (item){
QRect loc = item->geometry();
int vSpace = verticalSpacing();
QPoint pos = QPoint(loc.left()+loc.width()/2, loc.bottom()+vSpace+2);
int index = -1;
while ((pos.y()<geometry().bottom()) && (index < 0)){
index = indexAtParent(pos);
pos.setY(pos.y()+2);
}//while ((pos.y()<geometry().bottom()) && (index < 0))
m_currentIndex = (index>0)?index:0;
m_currentIndex = (index<=m_itemList.count())?index:m_itemList.count();
if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier)){
m_selStopIndex = m_currentIndex;
addSelection((keyEvent->modifiers() &= Qt::ControlModifier));
}//if ((keyEvent->modifiers() &= Qt::ShiftModifier) || (keyEvent->modifiers() &= Qt::ControlModifier))
doLayout(geometry(),false);
m_selStartIndex = m_selStopIndex = m_currentIndex;
event->accept();
}//if (wid)
setCurrent();
}//if ((keyEvent->key()==Qt::Key_Right))
}//if (event->type() == QEvent::KeyRelease)
// standard event processing
return QObject::eventFilter(obj, event);
}
void FlowLayout::unsetCurrent()
{
QLayoutItem *oldItem = currentItem();
if (oldItem) {
FlowLayoutItem *fli = qobject_cast<FlowLayoutItem *>(oldItem->widget());
if (fli) fli->setIsCurrent(false);
}//if (oldItem)
}
void FlowLayout::setCurrent()
{
QLayoutItem *newItem = currentItem();
if (newItem) {
FlowLayoutItem *fli = qobject_cast<FlowLayoutItem *>(newItem->widget());
if (fli) fli->setIsCurrent(true);
}//if (newItem)
}
void FlowLayout::addItem(QLayoutItem *item)
{
m_itemList.append(item);
item->widget()->installEventFilter(this);
}
void FlowLayout::addItem(FlowLayoutItem *item)
{
QWidget *widget = qobject_cast<QWidget *>(item);
addWidget(widget);
}
int FlowLayout::horizontalSpacing() const
{
if (m_hSpace >= 0) {
return m_hSpace;
} else {
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
}//if (m_hSpace >= 0)
}
void FlowLayout::setHorizontalSpacing(int &h)
{
if (h>=0) {
m_hSpace = h;
} else {
m_hSpace = -1;
}//if (h>=0)
doLayout(geometry(), false);
}
int FlowLayout::verticalSpacing() const
{
if (m_vSpace >= 0) {
return m_vSpace;
} else {
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}//if (m_vSpace >= 0)
}
void FlowLayout::setVerticalSpacing(int &v)
{
if (v>=0) {
m_vSpace = v;
} else {
m_vSpace = -1;
}//if (v>=0)
doLayout(geometry(), false);
}
int FlowLayout::count() const
{
return m_itemList.size();
}
QLayoutItem *FlowLayout::itemAt(int index) const
{
return m_itemList.value(index);
}
QLayoutItem *FlowLayout::itemAtGlobal(const QPoint &p) const
{
return m_itemList.value(indexAtGlobal(p));
}
QLayoutItem *FlowLayout::itemAtParent(const QPoint &p) const
{
return m_itemList.value(indexAtParent(p));
}
int FlowLayout::indexAtGlobal(const QPoint &p) const
{
int count = m_itemList.size();
for(int curs=0; curs<count; ++curs){
QWidget *widget = m_itemList.value(curs)->widget();
if(widget) {
QPoint pos = widget->mapFromGlobal(p);
if((pos.x()>0) && (pos.x()<widget->width()))
if((pos.y()>0) && (pos.y()<widget->height()))
return curs;
}//if(widget)
}//for(int curs=0; curs<count; ++curs)
return -1;
}
int FlowLayout::indexAtParent(const QPoint &p) const
{
int count = m_itemList.size();
for(int curs=0; curs<count; ++curs){
QWidget *widget = m_itemList.value(curs)->widget();
if(widget) {
QPoint pos = widget->mapFromParent(p);
if((pos.x()>=0) && (pos.x()<=widget->width()))
if((pos.y()>=0) && (pos.y()<=widget->height()))
return curs;
if (pos.y()<0) break;//In line below so don't check other item.
}//if(widget)
}//for(int curs=0; curs<count; ++curs)
return -1;
}
QLayoutItem *FlowLayout::takeAt(int index)
{
if (index >= 0 && index < m_itemList.size())
return m_itemList.takeAt(index);
else
return 0;
}
Qt::Orientations FlowLayout::expandingDirections() const
{
return Qt::Horizontal;
}
bool FlowLayout::hasHeightForWidth() const
{
return true;
}
int FlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true);
return height;
}
void FlowLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize FlowLayout::sizeHint() const
{
return minimumSize();
}
QSize FlowLayout::minimumSize() const
{
QSize size;
QLayoutItem *item;
foreach (item, m_itemList)
size = size.expandedTo(item->minimumSize());
size += QSize(2*margin(), 2*margin());
return size;
}
void FlowLayout::addSelection(bool invert){
for (int curs=m_selStartIndex; curs<=m_selStopIndex; ++curs){
QLayoutItem *item=itemAt(curs);
if (item) {
FlowLayoutItem *fli = qobject_cast<FlowLayoutItem *>(item->widget());
if (invert && m_selectionList.contains(item)){
if (fli) fli->setIsSelected(false);
m_selectionList.removeOne(item);
} else {
if (fli) fli->setIsSelected(true);
m_selectionList.append(item);
}//if (m_selectionList.contains(item))
}//if (item)
}//for (int curs=m_selStartIndex; curs<=m_selStopIndex; ++curs)
}
void FlowLayout::performDrag()
{
QPixmap dragPixmap;
bool atLeastOnePixmap = false;
int count = m_selectionList.count();
for (int curs=0; curs<count; ++curs){
QLayoutItem *layoutItem = m_selectionList.at(curs);
if (layoutItem){
QWidget *widget = layoutItem->widget();
if (widget) {
QPixmap itemPixmap;
FlowLayoutItem *item = qobject_cast<FlowLayoutItem *>(widget);
if (item){
itemPixmap = item->getDragImage();
} else {
#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0)
itemPixmap = widget->grab();//QT5
#else
itemPixmap = QPixmap::grabWidget(widget);
#endif
}//if (item)
itemPixmap = itemPixmap.scaled(50,50,Qt::KeepAspectRatio, Qt::SmoothTransformation);
/// Warning On Windows, Drag Pixmap size cannot exceed 50*50. ///
if (curs==0) dragPixmap = itemPixmap;
QPixmap oldPixmap = dragPixmap;
if (curs!=0) dragPixmap = QPixmap(oldPixmap.width() + 20 , oldPixmap.height());
dragPixmap.fill(widget->palette().background().color());
QPainter painter(&dragPixmap);
painter.drawPixmap(0, 0, oldPixmap);
if (curs!=0) painter.drawPixmap((20 * curs), 0, itemPixmap);
atLeastOnePixmap = true;
}//if (widget)
}//if (layoutItem)
}//for (int curs=0; curs<count; ++curs)
if (atLeastOnePixmap) {
QMimeData *mimeData = new QMimeData;
mimeData->setText("");
QDrag *drag = new QDrag(this->parentWidget());
drag->setMimeData(mimeData);
drag->setPixmap(dragPixmap);
drag->setHotSpot(QPoint(0, 0));
drag->exec(Qt::CopyAction);
}//if (atLeastOnePixmap)
}
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{
int left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;
int count = m_itemList.size();
for (int curs=0; curs<count; ++curs) {
QLayoutItem *item=m_itemList.value(curs);
QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeight = 0;
}//if (nextX - spaceX > effectiveRect.right() && lineHeight > 0)
if (!testOnly){
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
bool selected = m_selectionList.contains(item);
bool isCurrent = (curs==currentIndex());
QString solid = isCurrent?"dot-dash":"inset";
QString color = selected?"blue":isCurrent?"gray":"";
QString border = (selected||isCurrent)?QString("border: 1px %1 %2").arg(solid).arg(color):"";
QString widName = wid->objectName();
QString style;
if (widName.isEmpty()){
style=border;
} else {
//For Custom QWidget, change paintEvent as FlowLayoutItem. cf:http://qt-project.org/doc/qt-4.8/stylesheet-reference.html
style = QString("QWidget#%1\n{\n%2\n}\n").arg(wid->objectName(),border);
}//if (widName.isEmpty())
///Warning: Test if != to not ask a new redraw all time ///
if (wid->styleSheet()!=style) wid->setStyleSheet(style);
}//if (!testOnly)
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}//for (curs=0; curs<count; ++curs)
return y + lineHeight - rect.y() + bottom;
}
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
QObject *parent = this->parent();
if (!parent) {
return -1;
} else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm, 0, pw);
} else {
return static_cast<QLayout *>(parent)->spacing();
}//if (!parent)
}

View file

@ -0,0 +1,344 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
/** WARNING: QT Designer don't accept Custom Layout, maybe on QT5
*You can get widget's children like this:
* FlowLayout *flowLayout = new FlowLayout;
* //First Get Item in Qt Designer
* int count = ui->id->children().count();
* for (int curs = 0; curs < count; ++curs){
* QObject *obj = ui->id->children().at(curs);
* QWidget *wid = qobject_cast<QWidget *>(obj);
* if (wid) flowLayout->addWidget(wid);
* }//for (int curs = 0; curs < count; ++curs)
*/
#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H
#include <QKeyEvent>
#include <QLayout>
#include <QPainter>
#include <QRect>
#include <QScrollArea>
#include <QStyle>
#include <QStyleOption>
#include <QWidget>
#include <QWidgetItem>
/// \class FlowLayoutItem
/// \brief The FlowLayoutItem class
///FlowLayoutItem represents FlowLayout item.
///Derivatives from it to make a custom widget
///and to get Drag and Drop better.
class FlowLayoutItem : public QWidget
{
Q_OBJECT
public:
FlowLayoutItem(QString name=QString(), QWidget *parent=0) : QWidget(parent), m_myName(name){
setFocusPolicy(Qt::StrongFocus);
setAcceptDrops(true);
}
~FlowLayoutItem(){}
/// \brief getImage
/// \return Image to represent your widget (not necessary all the widget).
virtual const QPixmap getImage() =0;
/// \brief getDragImage
/// \return Image to represent your widget when dragged (not necessary all the widget).
virtual const QPixmap getDragImage() =0;
/// \brief setName
/// \param value
virtual void setName(QString value) {m_myName=value;}
/// \brief getName
/// \return the name of your widget;
virtual const QString getName() const {return m_myName;}
/// \brief setIsSelected
/// \param value
virtual void setIsSelected(bool value) {m_isSelected=value;}
/// \brief getSelected
/// \return if item is selected
virtual bool isSelected() const {return m_isSelected;}
/// \brief setCurrent
/// \param value
virtual void setIsCurrent(bool value) {m_isCurrent=value;}
/// \brief isCurrent
/// \return if item is the current one
virtual bool isCurrent() const {return m_isCurrent;}
/// \brief paintEvent
///To get Style working on widget and not on all children.
void paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
signals:
/// \brief flowLayoutItemDropped
/// \param listItem: QList with all item dropped.
/// \param bAccept: set it to true to accept drop event.
///Signales when the widget is dropped.
void flowLayoutItemDropped(QList <FlowLayoutItem*> listItem, bool &bAccept);
protected:
void keyPressEvent(QKeyEvent *event){event->ignore();}
void keyReleaseEvent(QKeyEvent *event){event->ignore();}
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
QString m_myName;
bool m_isSelected;
bool m_isCurrent;
private:
void performDrag();
private:
QPoint m_startPos;
};
/// \class FlowLayout
/// \brief The FlowLayout class
///Class FlowLayout arranges child widgets from left to right
///and top to bottom in a top-level widget.
///The items are first laid out horizontally and
///then vertically when each line in the layout runs out of space.
class FlowLayout : public QLayout
{
Q_OBJECT
Q_PROPERTY(int horizontalSpacing READ horizontalSpacing WRITE setHorizontalSpacing)
Q_PROPERTY(int verticalSpacing READ verticalSpacing WRITE setVerticalSpacing)
Q_PROPERTY(Qt::Orientations expandingDirections READ expandingDirections)
Q_PROPERTY(int count READ count)
Q_PROPERTY(QSize minimumSize READ minimumSize)
Q_PROPERTY(QLayoutItem *currentItem READ currentItem)
Q_PROPERTY(int currentIndex READ currentIndex)
public:
FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
///
/// \brief addItem QLayoutItem
/// \param item
///to add a new item. (normally called by addWidget)
void addItem(QLayoutItem *item);
///
/// \brief addItem FlowLayoutItem
/// \param item
///To add a new FlowLayoutItem item.
void addItem(FlowLayoutItem *item);
///
/// \brief horizontalSpacing
/// \return int
///Returns the horizontal spacing of items in the layout.
int horizontalSpacing() const;
///
/// \brief setHorizontalSpacing
/// \param h
///To set the horizontal spacing of items in the layout.
void setHorizontalSpacing(int &h);
///
/// \brief verticalSpacing
/// \return int
///Returns the vertical spacing of items in the layout.
int verticalSpacing() const;
///
/// \brief setVerticalSpacing
/// \param v
///To set the horizontal spacing of items in the layout.
void setVerticalSpacing(int &v);
///
/// \brief expandingDirections
/// \return Qt::Orientations
///Returns the Qt::Orientations in which the layout can make
/// use of more space than its sizeHint().
Qt::Orientations expandingDirections() const;
///
/// \brief hasHeightForWidth
/// \return bool
///Indicates if heightForWidth() is implemented.
bool hasHeightForWidth() const;
///
/// \brief heightForWidth
/// \return int
///To adjust to widgets of which height is dependent on width.
int heightForWidth(int) const;
///
/// \brief count
/// \return int
///Returns items count.
int count() const;
///
/// \brief itemAt
/// \param index
/// \return QLayoutItem*
///Returns item at index position.
QLayoutItem *itemAt(int index) const;
///
/// \brief itemAtGlobal
/// \param p
/// \return QLayoutItem*
///Returns item at position indicate with p. This position is on global screen coordinates.
QLayoutItem *itemAtGlobal(const QPoint &p) const;
///
/// \brief itemAtParent
/// \param p
/// \return QLayoutItem*
///Returns item at position indicate with p. This position is on parent screen coordinates.
QLayoutItem *itemAtParent(const QPoint &p) const;
///
/// \brief indexAtGlobal
/// \param p
/// \return int
///Returns index of item at position indicate with p. This position is on global screen coordinates.
int indexAtGlobal(const QPoint &p) const;
///
/// \brief indexAtParent
/// \param p
/// \return int
///Returns index of item at position indicate with p. This position is on parent screen coordinates.
int indexAtParent(const QPoint &p) const;
///
/// \brief minimumSize
/// \return QSize
///Returns the minimum size of all child items.
QSize minimumSize() const;
///
/// \brief setGeometry
/// \param rect
///Set the geometry of the layout relative to its parent and excluding the window frame.
///It's for redraw item list when it was resized.
void setGeometry(const QRect &rect);
///
/// \brief sizeHint
/// \return QSize
///Returns recommended (minimum) size.
QSize sizeHint() const;
///
/// \brief takeAt
/// \param index
/// \return QLayoutItem*
///Take an item in list (erase it).
QLayoutItem *takeAt(int index);
///
/// \brief selectionList
/// \return QList<QLayoutItem *>
///Returns the list of selected items.
QList<QLayoutItem *> selectionList() const { return m_selectionList;}
///
/// \brief currentItem
/// \return QLayoutItem *
///Returns the current (only one) item.
QLayoutItem *currentItem() const { return m_itemList.value(m_currentIndex);}
///
/// \brief currentIndex
/// \return int
///Returns index of current item.
int currentIndex() const { return m_currentIndex;}
protected:
bool eventFilter(QObject *obj, QEvent *event);
void unsetCurrent();
void setCurrent();
private:
// Redraw all the layout
int doLayout(const QRect &rect, bool testOnly) const;
//To get the default spacing for either the top-level layouts or the sublayouts.
//The default spacing for top-level layouts, when the parent is a QWidget,
//will be determined by querying the style.
//The default spacing for sublayouts, when the parent is a QLayout,
//will be determined by querying the spacing of the parent layout.
int smartSpacing(QStyle::PixelMetric pm) const;
//Execute drag action.
void performDrag();
//Update selection with m_selStartIndex and m_selStopIndex.
//If invert, item selection is toggled.
void addSelection(bool invert);
QList<QLayoutItem *> m_itemList;
QList<QLayoutItem *> m_selectionList;
int m_selStartIndex;
int m_selStopIndex;
int m_currentIndex;
QPoint m_startPos;
int m_hSpace;
int m_vSpace;
};
///
/// \brief The FlowLayoutWidget class
///Class FlowLayoutWidget provide a simple widget with FlowLayout as layout.
///This could be integrate on QtDesigner
class FlowLayoutWidget : public QWidget
{
Q_OBJECT
public:
FlowLayoutWidget(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
FlowLayoutWidget(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayoutWidget();
protected:
bool eventFilter(QObject *obj, QEvent *event);
private:
void updateParent();
QScrollArea *m_saParent;
QScrollBar *m_sbVertical;
int m_lastYPos;
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,263 @@
/*From version of May 16 2010
ORIGINAL COPYRIGHT HEADER
PictureFlow - animated image show widget
http://pictureflow.googlecode.com
Copyright (C) 2008 Ariya Hidayat (ariya@kde.org)
Copyright (C) 2007 Ariya Hidayat (ariya@kde.org)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef PICTUREFLOW_H
#define PICTUREFLOW_H
#include <QWidget>
class PictureFlowPrivate;
/// \class PictureFlow
/// \brief The PictureFlow class
///Class PictureFlow implements an image show widget with animation effect
///like Apple's CoverFlow (in iTunes and iPod). Images are arranged in form
///of slides, one main slide is shown at the center with few slides on
///the left and right sides of the center slide. When the next or previous
///slide is brought to the front, the whole slides flow to the right or
///the right with smooth animation effect; until the new slide is finally
///placed at the center.
class PictureFlow : public QWidget
{
Q_OBJECT
Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
Q_PROPERTY(QSize slideSize READ slideSize)
Q_PROPERTY(float slideSizeRatio READ slideSizeRatio WRITE setSlideSizeRatio)
Q_PROPERTY(int slideCount READ slideCount)
Q_PROPERTY(int centerIndex READ centerIndex WRITE setCenterIndex)
public:
enum ReflectionEffect
{
NoReflection,
PlainReflection,
BlurredReflection
};
///
/// \brief PictureFlow
/// \param parent
///Creates a new PictureFlow widget.
PictureFlow(QWidget* parent = 0);
///
/// \brief ~PictureFlow
///Destroys the widget.
~PictureFlow();
///
/// \brief backgroundColor
/// \return QColor
///Returns the background color.
QColor backgroundColor() const;
///
/// \brief setBackgroundColor
/// \param c
///Sets the background color. By default it is black.
void setBackgroundColor(const QColor& c);
/*!
Returns the dimension of each slide (in pixels).
*/
///
/// \brief slideSize
/// \return QSize
///Returns the dimension of each slide (in pixels).
QSize slideSize() const;
///
/// \brief slideSizeRatio
/// \return float
///Returns the ratio dimension of each slide (Height/Width).
float slideSizeRatio() const;
///
/// \brief setSlideSizeRatio
/// \param ratio
///Sets the ratio of dimension of each slide (in pixels).
void setSlideSizeRatio(float ratio);
///
/// \brief slideCount
/// \return int
///Returns the total number of slides.
int slideCount() const;
///
/// \brief slide
/// \param index
/// \return QImage
///Returns QImage of specified slide.
QImage slide(int index) const;
///
/// \brief slideAt
/// \param point
/// \return int
///Returns QImage of specified slide.
int slideAt(QPoint point) const;
///
/// \brief centerIndex
/// \return int
///Returns the index of slide currently shown in the middle of the viewport.
int centerIndex() const;
///
/// \brief reflectionEffect
/// \return ReflectionEffect
///Returns the effect applied to the reflection.
ReflectionEffect reflectionEffect() const;
///
/// \brief setReflectionEffect
/// \param effect
///Sets the effect applied to the reflection. The default is PlainReflection.
void setReflectionEffect(ReflectionEffect effect);
public slots:
///
/// \brief addSlide
/// \param image QImage of slide
///Adds a new slide.
void addSlide(const QImage& image);
///
/// \brief addSlide
/// \param pixmap QPixmap of slide
///Adds a new slide.
void addSlide(const QPixmap& pixmap);
///
/// \brief setSlide
/// \param index index of slide
/// \param image QImage of slide
///Sets an image for specified slide. If the slide already exists,
///it will be replaced.
void setSlide(int index, const QImage& image);
///
/// \brief setSlide
/// \param index index of slide
/// \param pixmap QPixmap of slide
///Sets a pixmap for specified slide. If the slide already exists,
///it will be replaced.
void setSlide(int index, const QPixmap& pixmap);
///
/// \brief setCenterIndex
/// \param index Index of slide to center
///Sets slide to be shown in the middle of the viewport. No animation
///effect will be produced, unlike using showSlide.
void setCenterIndex(int index);
///
/// \brief clear
///Clears all slides.
void clear();
///
/// \brief showPrevious
///Shows previous slide using animation effect.
void showPrevious();
///
/// \brief showNext
///Shows next slide using animation effect.
void showNext();
///
/// \brief showSlide
/// \param index
///Go to specified slide using animation effect.
void showSlide(int index);
///
/// \brief render
///Rerender the widget. Normally this function will be automatically invoked
///whenever necessary, e.g. during the transition animation.
void render();
///
/// \brief triggerRender
///Schedules a rendering update. Unlike render(), this function does not cause
///immediate rendering.
void triggerRender();
signals:
///
/// \brief centerIndexChanged
/// \param index
///Signals when index was changed.
void centerIndexChanged(int index);
///
/// \brief mouseMoveOverSlideEvent
/// \param event
/// \param slideIndex
///Signals when mouse move over a slide.
void mouseMoveOverSlideEvent(QMouseEvent* event, int slideIndex);
///
/// \brief dragEnterEventOccurs
/// \param event
///Signals when a drag enters on a slide.
void dragEnterEventOccurs(QDragEnterEvent *event);
///
/// \brief dragMoveEventOccurs
/// \param event
///Signals when a drag move over a slide.
void dragMoveEventOccurs(QDragMoveEvent *event);
///
/// \brief dropEventOccurs
/// \param event
///Signals when something is dropped on slide.
void dropEventOccurs(QDropEvent *event);
protected:
void paintEvent(QPaintEvent* event);
void keyPressEvent(QKeyEvent* event);
void mouseMoveEvent(QMouseEvent* event);
void mousePressEvent(QMouseEvent* event);
void resizeEvent(QResizeEvent* event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
private slots:
void updateAnimation();
private:
PictureFlowPrivate* d;
QPoint dragMoveLastPos;
};
#endif // PICTUREFLOW_H