mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
6e0ede2817
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@8459 b45a01b8-16f6-495d-af2f-9b41ad6348cc
757 lines
24 KiB
C++
757 lines
24 KiB
C++
/****************************************************************************
|
|
**
|
|
** 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 <QScrollBar>
|
|
#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 = NULL;
|
|
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)
|
|
}
|