mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-25 03:12:53 +00:00
400 lines
14 KiB
C++
400 lines
14 KiB
C++
/*
|
|
* Copyright 2010 by Giulio Camuffo <giuliocamuffo@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Library General Public License as
|
|
* published by the Free Software Foundation; either version 2, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details
|
|
*
|
|
* You should have received a copy of the GNU Library General Public
|
|
* License along with this program; if not, write to the
|
|
* Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "flowgroup.h"
|
|
|
|
#include <QtGui/QGraphicsLinearLayout>
|
|
#include <QtGui/QPainter>
|
|
|
|
#include <KIconLoader>
|
|
#include <KIcon>
|
|
|
|
#include <Plasma/Theme>
|
|
#include <Plasma/PaintUtils>
|
|
#include <Plasma/ScrollWidget>
|
|
#include <Plasma/ToolButton>
|
|
|
|
#include "gridhandle.h"
|
|
#include "groupingcontainment.h"
|
|
#include "spacer.h"
|
|
|
|
REGISTER_GROUP(FlowGroup)
|
|
|
|
FlowGroup::FlowGroup(QGraphicsItem *parent, Qt::WindowFlags wFlags)
|
|
: AbstractGroup(parent, wFlags),
|
|
m_mainLayout(new QGraphicsLinearLayout(Qt::Horizontal)),
|
|
m_arrows(new Plasma::Svg(this)),
|
|
m_prevArrow(new Plasma::ToolButton(this)),
|
|
m_nextArrow(new Plasma::ToolButton(this)),
|
|
m_scrollWidget(new Plasma::ScrollWidget(this)),
|
|
m_container(new QGraphicsWidget(this)),
|
|
m_spacer(new Spacer(this)),
|
|
SPACING(4)
|
|
{
|
|
resize(200,200);
|
|
|
|
m_arrows->setImagePath("widgets/arrows");
|
|
m_arrows->setContainsMultipleImages(true);
|
|
m_arrows->resize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
|
|
|
|
m_prevArrow->setPreferredSize(IconSize(KIconLoader::Panel), IconSize(KIconLoader::Panel));
|
|
m_prevArrow->hide();
|
|
m_nextArrow->setPreferredSize(IconSize(KIconLoader::Panel), IconSize(KIconLoader::Panel));
|
|
m_nextArrow->hide();
|
|
|
|
connect(m_prevArrow, SIGNAL(pressed()), this, SLOT(scrollPrev()));
|
|
connect(m_nextArrow, SIGNAL(pressed()), this, SLOT(scrollNext()));
|
|
|
|
m_scrollWidget->setWidget(m_container);
|
|
m_scrollWidget->setMinimumSize(0, 0);
|
|
m_scrollWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
m_scrollWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
m_scrollWidget->setOverflowBordersVisible(false);
|
|
m_container->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
|
|
|
|
m_mainLayout->addItem(m_scrollWidget);
|
|
setLayout(m_mainLayout);
|
|
|
|
m_spacer->hide();
|
|
|
|
setGroupType(AbstractGroup::ConstrainedGroup);
|
|
setUseSimplerBackgroundForChildren(true);
|
|
|
|
connect(this, SIGNAL(appletRemovedFromGroup(Plasma::Applet*,AbstractGroup*)),
|
|
this, SLOT(appletRemoved(Plasma::Applet*)));
|
|
connect(this, SIGNAL(subGroupRemovedFromGroup(AbstractGroup*,AbstractGroup*)),
|
|
this, SLOT(groupRemoved(AbstractGroup*)));
|
|
}
|
|
|
|
FlowGroup::~FlowGroup()
|
|
{
|
|
|
|
}
|
|
|
|
QString FlowGroup::pluginName() const
|
|
{
|
|
return QString("flow");
|
|
}
|
|
|
|
void FlowGroup::restoreChildGroupInfo(QGraphicsWidget *child, const KConfigGroup &group)
|
|
{
|
|
QRectF rect;
|
|
if (m_mainLayout->orientation() == Qt::Horizontal) {
|
|
rect = QRectF(QPointF(group.readEntry("Position", 0), 0),
|
|
QSizeF(group.readEntry("Size", 0), m_container->size().height()));
|
|
} else {
|
|
rect = QRectF(QPointF(0, group.readEntry("Position", 0)),
|
|
QSizeF(m_container->size().width(), group.readEntry("Size", 0)));
|
|
}
|
|
child->setParentItem(m_container);
|
|
child->setGeometry(rect);
|
|
|
|
updateContents();
|
|
}
|
|
|
|
void FlowGroup::saveChildGroupInfo(QGraphicsWidget *child, KConfigGroup group) const
|
|
{
|
|
if (m_mainLayout->orientation() == Qt::Horizontal) {
|
|
group.writeEntry("Position", child->pos().x());
|
|
group.writeEntry("Size", child->size().width());
|
|
} else {
|
|
group.writeEntry("Position", child->pos().y());
|
|
group.writeEntry("Size", child->size().height());
|
|
}
|
|
}
|
|
|
|
bool FlowGroup::showDropZone(const QPointF &pos)
|
|
{
|
|
if (pos == QPointF()) {
|
|
m_spacer->hide();
|
|
updateContents();
|
|
|
|
return false;
|
|
}
|
|
|
|
m_spacer->show();
|
|
QGraphicsWidget *w = containment()->movingWidget();
|
|
QSizeF pref;
|
|
QSizeF min;
|
|
if (children().contains(w)) {
|
|
pref = QSizeF(w->effectiveSizeHint(Qt::PreferredSize));
|
|
min = QSizeF(w->effectiveSizeHint(Qt::MinimumSize));
|
|
} else {
|
|
pref = QSizeF(40, 40);
|
|
min = QSizeF(5, 5);
|
|
}
|
|
if (m_mainLayout->orientation() == Qt::Horizontal) {
|
|
m_spacer->setPreferredWidth(pref.width());
|
|
m_spacer->setMinimumWidth(min.width());
|
|
} else {
|
|
m_spacer->setPreferredHeight(pref.height());
|
|
m_spacer->setMinimumHeight(min.height());
|
|
}
|
|
addItem(m_spacer, mapToItem(m_container, pos));
|
|
|
|
return true;
|
|
}
|
|
|
|
Handle *FlowGroup::createHandleForChild(QGraphicsWidget *child)
|
|
{
|
|
if (!children().contains(child)) {
|
|
return 0;
|
|
}
|
|
|
|
Plasma::Applet *a = qobject_cast<Plasma::Applet *>(child);
|
|
if (a) {
|
|
return new GridHandle(containment(), a);
|
|
}
|
|
|
|
return new GridHandle(containment(), static_cast<AbstractGroup *>(child));
|
|
}
|
|
|
|
void FlowGroup::layoutChild(QGraphicsWidget *child, const QPointF &pos)
|
|
{
|
|
addItem(child, mapToItem(m_container, pos));
|
|
m_spacer->hide();
|
|
updateContents();
|
|
}
|
|
|
|
void FlowGroup::addItem(QGraphicsWidget *child, const QPointF &pos)
|
|
{
|
|
child->setParentItem(m_container);
|
|
QRectF rect(pos, child->effectiveSizeHint(Qt::PreferredSize));
|
|
if (m_mainLayout->orientation() == Qt::Horizontal) {
|
|
rect.setY(0);
|
|
} else {
|
|
rect.setX(0);
|
|
}
|
|
child->setGeometry(rect);
|
|
|
|
updateContents();
|
|
}
|
|
|
|
void FlowGroup::appletRemoved(Plasma::Applet *)
|
|
{
|
|
updateContents();
|
|
}
|
|
|
|
void FlowGroup::groupRemoved(AbstractGroup *)
|
|
{
|
|
updateContents();
|
|
}
|
|
|
|
void FlowGroup::scrollPrev()
|
|
{
|
|
QRectF geom(m_scrollWidget->viewportGeometry());
|
|
if (m_mainLayout->orientation() == Qt::Horizontal) {
|
|
m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.topLeft()) -
|
|
QPointF(40, 0), QSize(40, geom.height())));
|
|
} else {
|
|
m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.topLeft()) -
|
|
QPointF(0, 40), QSize(geom.width(), 40)));
|
|
}
|
|
}
|
|
|
|
void FlowGroup::scrollNext()
|
|
{
|
|
QRectF geom(m_scrollWidget->viewportGeometry());
|
|
if (m_mainLayout->orientation() == Qt::Horizontal) {
|
|
m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.topRight()),
|
|
QSize(40, geom.height())));
|
|
} else {
|
|
m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.bottomLeft()),
|
|
QSize(geom.width(), 40)));
|
|
}
|
|
}
|
|
|
|
void FlowGroup::updateContents()
|
|
{
|
|
const bool horizontal = (m_mainLayout->orientation() == Qt::Horizontal);
|
|
|
|
//generate a list of the children in a left-right or top-bottom order
|
|
QList<QGraphicsWidget *> list = children();
|
|
if (m_spacer->isVisible()) {
|
|
list << m_spacer;
|
|
}
|
|
GroupingContainment *c = containment();
|
|
if (c) {
|
|
list.removeOne(c->movingWidget());
|
|
}
|
|
QList<QGraphicsWidget *> childs;
|
|
foreach (QGraphicsWidget *child, list) {
|
|
for (int i = 0; i < childs.count(); ++i) {
|
|
QGraphicsWidget *c = childs.at(i);
|
|
if ((horizontal && child->pos().x() < c->pos().x()) ||
|
|
(!horizontal && child->pos().y() < c->pos().y())) {
|
|
childs.insert(i, child);
|
|
break;
|
|
}
|
|
}
|
|
if (!childs.contains(child)) {
|
|
childs << child;
|
|
}
|
|
}
|
|
|
|
QRectF containerRect(m_container->boundingRect());
|
|
for (int i = 0; i < childs.count(); ++i) {
|
|
QGraphicsWidget *child = childs.at(i);
|
|
QRectF rect(child->geometry());
|
|
rect.setWidth(child->effectiveSizeHint(Qt::PreferredSize).width());
|
|
|
|
QGraphicsWidget *next = (i < childs.count() - 1 ? childs.at(i + 1) : 0);
|
|
|
|
if (horizontal) {
|
|
const qreal min = child->effectiveSizeHint(Qt::MinimumSize).width();
|
|
const qreal minRight = childs.last()->geometry().right();
|
|
containerRect.setRight(minRight);
|
|
m_container->resize(containerRect.size());
|
|
|
|
const qreal r = (next ? next->pos().x() - SPACING : containerRect.right());
|
|
if (r < rect.right() || QSizePolicy::ExpandFlag & child->sizePolicy().horizontalPolicy()) {
|
|
rect.setRight(r);
|
|
}
|
|
|
|
if (rect.width() < min) {
|
|
qreal newR = rect.x() + min;
|
|
if (newR > r) {
|
|
newR = r;
|
|
}
|
|
rect.setRight(newR);
|
|
}
|
|
} else {
|
|
const qreal min = child->effectiveSizeHint(Qt::MinimumSize).height();
|
|
const qreal minBottom = childs.last()->geometry().bottom();
|
|
containerRect.setBottom(minBottom);
|
|
m_container->resize(containerRect.size());
|
|
|
|
const qreal b = (next ? next->pos().y() - SPACING : containerRect.bottom());
|
|
if (b < rect.bottom() || QSizePolicy::ExpandFlag & child->sizePolicy().verticalPolicy()) {
|
|
rect.setBottom(b);
|
|
}
|
|
|
|
if (rect.height() < min) {
|
|
qreal newB = rect.y() + min;
|
|
if (newB > b) {
|
|
newB = b;
|
|
}
|
|
rect.setBottom(newB);
|
|
}
|
|
}
|
|
|
|
child->setGeometry(rect);
|
|
}
|
|
|
|
QRectF geom(m_scrollWidget->viewportGeometry());
|
|
if (horizontal) {
|
|
if (m_prevArrow->isVisible()) {
|
|
geom.setWidth(geom.width() + m_prevArrow->geometry().width() * 2 + SPACING * 2);
|
|
}
|
|
m_container->resize(qMax(m_container->size().width(), geom.width()), geom.height());
|
|
m_container->setMaximumHeight(geom.height());
|
|
foreach (QGraphicsWidget *c, childs) {
|
|
c->resize(c->size().width(), geom.height());
|
|
}
|
|
} else {
|
|
if (m_prevArrow->isVisible()) {
|
|
geom.setHeight(geom.height() + m_prevArrow->geometry().height() * 2 + SPACING * 2);
|
|
}
|
|
m_container->resize(geom.width(), qMax(m_container->size().height(), geom.height()));
|
|
m_container->setMaximumWidth(geom.width());
|
|
foreach (QGraphicsWidget *c, childs) {
|
|
c->resize(geom.width(), c->size().height());
|
|
}
|
|
}
|
|
|
|
QRectF r;
|
|
if (!childs.isEmpty()) {
|
|
r = QRectF(childs.first()->pos(), childs.last()->geometry().bottomRight());
|
|
}
|
|
if ((horizontal && m_container->size().width() > geom.width()) ||
|
|
(!horizontal && m_container->size().height() > geom.height())) {
|
|
if ((horizontal && geom.width() >= r.width()) ||
|
|
(!horizontal && geom.height() >= r.height())) {
|
|
r.setLeft(r.right() - geom.width());
|
|
r.setTop(r.bottom() - geom.height());
|
|
m_scrollWidget->ensureRectVisible(r);
|
|
if (m_prevArrow->isVisible()) {
|
|
m_mainLayout->removeItem(m_prevArrow);
|
|
m_mainLayout->removeItem(m_nextArrow);
|
|
m_prevArrow->hide();
|
|
m_nextArrow->hide();
|
|
}
|
|
} else {
|
|
if (!m_prevArrow->isVisible()) {
|
|
m_mainLayout->insertItem(0, m_prevArrow);
|
|
m_mainLayout->addItem(m_nextArrow);
|
|
m_prevArrow->show();
|
|
m_nextArrow->show();
|
|
}
|
|
}
|
|
} else if (m_prevArrow->isVisible()) {
|
|
m_mainLayout->removeItem(m_prevArrow);
|
|
m_mainLayout->removeItem(m_nextArrow);
|
|
m_prevArrow->hide();
|
|
m_nextArrow->hide();
|
|
}
|
|
}
|
|
|
|
void FlowGroup::constraintsEvent(Plasma::Constraints constraints)
|
|
{
|
|
if (constraints & Plasma::FormFactorConstraint) {
|
|
Plasma::FormFactor f = containment()->formFactor();
|
|
if (f == Plasma::Vertical) {
|
|
m_mainLayout->setOrientation(Qt::Vertical);
|
|
m_spacer->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum));
|
|
m_prevArrow->setIcon(KIcon(m_arrows->pixmap("up-arrow")));
|
|
m_nextArrow->setIcon(KIcon(m_arrows->pixmap("down-arrow")));
|
|
m_prevArrow->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
|
m_nextArrow->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
|
foreach (QGraphicsWidget *child, children()) {
|
|
child->setPos(0, child->pos().x());
|
|
}
|
|
} else {
|
|
m_mainLayout->setOrientation(Qt::Horizontal);
|
|
m_spacer->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
|
|
m_prevArrow->setIcon(KIcon(m_arrows->pixmap("left-arrow")));
|
|
m_nextArrow->setIcon(KIcon(m_arrows->pixmap("right-arrow")));
|
|
m_prevArrow->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
|
m_nextArrow->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
|
|
foreach (QGraphicsWidget *child, children()) {
|
|
child->setPos(child->pos().y(), 0);
|
|
}
|
|
}
|
|
updateContents();
|
|
}
|
|
}
|
|
|
|
void FlowGroup::resizeEvent(QGraphicsSceneResizeEvent *event)
|
|
{
|
|
AbstractGroup::resizeEvent(event);
|
|
|
|
updateContents();
|
|
}
|
|
|
|
GroupInfo FlowGroup::groupInfo()
|
|
{
|
|
GroupInfo gi("flow", i18n("Flow Group"));
|
|
QSet<Plasma::FormFactor> f;
|
|
f << Plasma::Planar << Plasma::MediaCenter << Plasma::Horizontal << Plasma::Vertical;
|
|
gi.setFormFactors(f);
|
|
|
|
return gi;
|
|
}
|
|
|
|
#include "moc_flowgroup.cpp"
|