2
* Copyright 2010 by Giulio Camuffo <giuliocamuffo@gmail.com>
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU Library General Public License as
6
* published by the Free Software Foundation; either version 2, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details
14
* You should have received a copy of the GNU Library General Public
15
* License along with this program; if not, write to the
16
* Free Software Foundation, Inc.,
17
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20
#include "flowgroup.h"
22
#include <QtGui/QGraphicsLinearLayout>
23
#include <QtGui/QPainter>
25
#include <KIconLoader>
28
#include <Plasma/Theme>
29
#include <Plasma/PaintUtils>
30
#include <Plasma/ScrollWidget>
31
#include <Plasma/ToolButton>
33
#include "gridhandle.h"
34
#include "groupingcontainment.h"
37
REGISTER_GROUP(FlowGroup)
39
FlowGroup::FlowGroup(QGraphicsItem *parent, Qt::WindowFlags wFlags)
40
: AbstractGroup(parent, wFlags),
41
m_mainLayout(new QGraphicsLinearLayout(Qt::Horizontal)),
42
m_arrows(new Plasma::Svg(this)),
43
m_prevArrow(new Plasma::ToolButton(this)),
44
m_nextArrow(new Plasma::ToolButton(this)),
45
m_scrollWidget(new Plasma::ScrollWidget(this)),
46
m_container(new QGraphicsWidget(this)),
47
m_spacer(new Spacer(this)),
52
m_arrows->setImagePath("widgets/arrows");
53
m_arrows->setContainsMultipleImages(true);
54
m_arrows->resize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
56
m_prevArrow->setPreferredSize(IconSize(KIconLoader::Panel), IconSize(KIconLoader::Panel));
58
m_nextArrow->setPreferredSize(IconSize(KIconLoader::Panel), IconSize(KIconLoader::Panel));
61
connect(m_prevArrow, SIGNAL(pressed()), this, SLOT(scrollPrev()));
62
connect(m_nextArrow, SIGNAL(pressed()), this, SLOT(scrollNext()));
64
m_scrollWidget->setWidget(m_container);
65
m_scrollWidget->setMinimumSize(0, 0);
66
m_scrollWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
67
m_scrollWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
68
m_scrollWidget->setOverflowBordersVisible(false);
69
m_container->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
71
m_mainLayout->addItem(m_scrollWidget);
72
setLayout(m_mainLayout);
76
setGroupType(AbstractGroup::ConstrainedGroup);
77
setUseSimplerBackgroundForChildren(true);
79
connect(this, SIGNAL(appletRemovedFromGroup(Plasma::Applet*,AbstractGroup*)),
80
this, SLOT(appletRemoved(Plasma::Applet*)));
81
connect(this, SIGNAL(subGroupRemovedFromGroup(AbstractGroup*,AbstractGroup*)),
82
this, SLOT(groupRemoved(AbstractGroup*)));
85
FlowGroup::~FlowGroup()
90
QString FlowGroup::pluginName() const
92
return QString("flow");
95
void FlowGroup::restoreChildGroupInfo(QGraphicsWidget *child, const KConfigGroup &group)
98
if (m_mainLayout->orientation() == Qt::Horizontal) {
99
rect = QRectF(QPointF(group.readEntry("Position", 0), 0),
100
QSizeF(group.readEntry("Size", 0), m_container->size().height()));
102
child->setParentItem(m_container);
103
child->setGeometry(rect);
108
void FlowGroup::saveChildGroupInfo(QGraphicsWidget *child, KConfigGroup group) const
110
if (m_mainLayout->orientation() == Qt::Horizontal) {
111
group.writeEntry("Position", child->pos().x());
112
group.writeEntry("Size", child->size().width());
116
bool FlowGroup::showDropZone(const QPointF &pos)
118
if (pos == QPointF()) {
126
QGraphicsWidget *w = containment()->movingWidget();
129
if (children().contains(w)) {
130
pref = QSizeF(w->effectiveSizeHint(Qt::PreferredSize));
131
min = QSizeF(w->effectiveSizeHint(Qt::MinimumSize));
133
pref = QSizeF(40, 40);
136
if (m_mainLayout->orientation() == Qt::Horizontal) {
137
m_spacer->setPreferredWidth(pref.width());
138
m_spacer->setMinimumWidth(min.width());
140
m_spacer->setPreferredHeight(pref.height());
141
m_spacer->setMinimumHeight(min.height());
143
addItem(m_spacer, mapToItem(m_container, pos));
148
Handle *FlowGroup::createHandleForChild(QGraphicsWidget *child)
150
if (!children().contains(child)) {
154
Plasma::Applet *a = qobject_cast<Plasma::Applet *>(child);
156
return new GridHandle(containment(), a);
159
return new GridHandle(containment(), static_cast<AbstractGroup *>(child));
162
void FlowGroup::layoutChild(QGraphicsWidget *child, const QPointF &pos)
164
addItem(child, mapToItem(m_container, pos));
169
void FlowGroup::addItem(QGraphicsWidget *child, const QPointF &pos)
171
child->setParentItem(m_container);
172
QRectF rect(pos, child->effectiveSizeHint(Qt::PreferredSize));
173
if (m_mainLayout->orientation() == Qt::Horizontal) {
178
child->setGeometry(rect);
183
void FlowGroup::appletRemoved(Plasma::Applet *)
188
void FlowGroup::groupRemoved(AbstractGroup *)
193
void FlowGroup::scrollPrev()
195
QRectF geom(m_scrollWidget->viewportGeometry());
196
if (m_mainLayout->orientation() == Qt::Horizontal) {
197
m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.topLeft()) -
198
QPointF(40, 0), QSize(40, geom.height())));
200
m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.topLeft()) -
201
QPointF(0, 40), QSize(geom.width(), 40)));
205
void FlowGroup::scrollNext()
207
QRectF geom(m_scrollWidget->viewportGeometry());
208
if (m_mainLayout->orientation() == Qt::Horizontal) {
209
m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.topRight()),
210
QSize(40, geom.height())));
212
m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.bottomLeft()),
213
QSize(geom.width(), 40)));
217
void FlowGroup::updateContents()
219
const bool horizontal = (m_mainLayout->orientation() == Qt::Horizontal);
221
//generate a list of the children in a left-right or top-bottom order
222
QList<QGraphicsWidget *> list = children();
223
if (m_spacer->isVisible()) {
226
GroupingContainment *c = containment();
228
list.removeOne(c->movingWidget());
230
QList<QGraphicsWidget *> childs;
231
foreach (QGraphicsWidget *child, list) {
232
for (int i = 0; i < childs.count(); ++i) {
233
QGraphicsWidget *c = childs.at(i);
234
if ((horizontal && child->pos().x() < c->pos().x()) ||
235
(!horizontal && child->pos().y() < c->pos().y())) {
236
childs.insert(i, child);
240
if (!childs.contains(child)) {
245
QRectF containerRect(m_container->boundingRect());
246
for (int i = 0; i < childs.count(); ++i) {
247
QGraphicsWidget *child = childs.at(i);
248
QRectF rect(child->geometry());
249
rect.setWidth(child->effectiveSizeHint(Qt::PreferredSize).width());
251
QGraphicsWidget *next = (i < childs.count() - 1 ? childs.at(i + 1) : 0);
254
const qreal min = child->effectiveSizeHint(Qt::MinimumSize).width();
255
const qreal minRight = childs.last()->geometry().right();
256
containerRect.setRight(minRight);
257
m_container->resize(containerRect.size());
259
const qreal r = (next ? next->pos().x() - SPACING : containerRect.right());
260
if (r < rect.right() || QSizePolicy::ExpandFlag & child->sizePolicy().horizontalPolicy()) {
264
if (rect.width() < min) {
265
qreal newR = rect.x() + min;
272
const qreal min = child->effectiveSizeHint(Qt::MinimumSize).height();
273
const qreal minBottom = childs.last()->geometry().bottom();
274
containerRect.setBottom(minBottom);
275
m_container->resize(containerRect.size());
277
const qreal b = (next ? next->pos().y() - SPACING : containerRect.bottom());
278
if (b < rect.bottom() || QSizePolicy::ExpandFlag & child->sizePolicy().verticalPolicy()) {
282
if (rect.height() < min) {
283
qreal newB = rect.y() + min;
287
rect.setBottom(newB);
291
child->setGeometry(rect);
294
QRectF geom(m_scrollWidget->viewportGeometry());
296
if (m_prevArrow->isVisible()) {
297
geom.setWidth(geom.width() + m_prevArrow->geometry().width() * 2 + SPACING * 2);
299
m_container->resize(qMax(m_container->size().width(), geom.width()), geom.height());
300
m_container->setMaximumHeight(geom.height());
301
foreach (QGraphicsWidget *c, childs) {
302
c->resize(c->size().width(), geom.height());
305
if (m_prevArrow->isVisible()) {
306
geom.setHeight(geom.height() + m_prevArrow->geometry().height() * 2 + SPACING * 2);
308
m_container->resize(geom.width(), qMax(m_container->size().height(), geom.height()));
309
m_container->setMaximumWidth(geom.width());
310
foreach (QGraphicsWidget *c, childs) {
311
c->resize(geom.width(), c->size().height());
316
if (!childs.isEmpty()) {
317
r = QRectF(childs.first()->pos(), childs.last()->geometry().bottomRight());
319
if ((horizontal && m_container->size().width() > geom.width()) ||
320
(!horizontal && m_container->size().height() > geom.height())) {
321
if ((horizontal && geom.width() >= r.width()) ||
322
(!horizontal && geom.height() >= r.height())) {
323
r.setLeft(r.right() - geom.width());
324
r.setTop(r.bottom() - geom.height());
325
m_scrollWidget->ensureRectVisible(r);
326
if (m_prevArrow->isVisible()) {
327
m_mainLayout->removeItem(m_prevArrow);
328
m_mainLayout->removeItem(m_nextArrow);
333
if (!m_prevArrow->isVisible()) {
334
m_mainLayout->insertItem(0, m_prevArrow);
335
m_mainLayout->addItem(m_nextArrow);
340
} else if (m_prevArrow->isVisible()) {
341
m_mainLayout->removeItem(m_prevArrow);
342
m_mainLayout->removeItem(m_nextArrow);
348
void FlowGroup::constraintsEvent(Plasma::Constraints constraints)
350
if (constraints & Plasma::FormFactorConstraint) {
351
Plasma::FormFactor f = containment()->formFactor();
352
if (f == Plasma::Vertical) {
353
m_mainLayout->setOrientation(Qt::Vertical);
354
m_spacer->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum));
355
m_prevArrow->setIcon(KIcon(m_arrows->pixmap("up-arrow")));
356
m_nextArrow->setIcon(KIcon(m_arrows->pixmap("down-arrow")));
357
m_prevArrow->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
358
m_nextArrow->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
359
foreach (QGraphicsWidget *child, children()) {
360
child->setPos(0, child->pos().x());
363
m_mainLayout->setOrientation(Qt::Horizontal);
364
m_spacer->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred));
365
m_prevArrow->setIcon(KIcon(m_arrows->pixmap("left-arrow")));
366
m_nextArrow->setIcon(KIcon(m_arrows->pixmap("right-arrow")));
367
m_prevArrow->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
368
m_nextArrow->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
369
foreach (QGraphicsWidget *child, children()) {
370
child->setPos(child->pos().y(), 0);
377
void FlowGroup::resizeEvent(QGraphicsSceneResizeEvent *event)
379
AbstractGroup::resizeEvent(event);
384
GroupInfo FlowGroup::groupInfo()
386
GroupInfo gi("flow", i18n("Flow Group"));
387
QSet<Plasma::FormFactor> f;
388
f << Plasma::Planar << Plasma::MediaCenter << Plasma::Horizontal << Plasma::Vertical;
389
gi.setFormFactors(f);
394
#include "flowgroup.moc"