~ubuntu-branches/ubuntu/oneiric/kdeplasma-addons/oneiric

« back to all changes in this revision

Viewing changes to containments/groupingdesktop/lib/groups/flowgroup.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-11-26 13:35:18 UTC
  • mfrom: (1.1.37 upstream)
  • Revision ID: james.westby@ubuntu.com-20101126133518-oxz33xjsoi02ty9f
Tags: 4:4.5.80-0ubuntu1
* New upstream beta release
* Disable kubuntu_02_microblog_default_configuration.diff does not apply
* New package plasma-containments-addons

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *   Copyright 2010 by Giulio Camuffo <giuliocamuffo@gmail.com>
 
3
 *
 
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.
 
8
 *
 
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
 
13
 *
 
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.
 
18
 */
 
19
 
 
20
#include "flowgroup.h"
 
21
 
 
22
#include <QtGui/QGraphicsLinearLayout>
 
23
#include <QtGui/QPainter>
 
24
 
 
25
#include <KIconLoader>
 
26
#include <KIcon>
 
27
 
 
28
#include <Plasma/Theme>
 
29
#include <Plasma/PaintUtils>
 
30
#include <Plasma/ScrollWidget>
 
31
#include <Plasma/ToolButton>
 
32
 
 
33
#include "gridhandle.h"
 
34
#include "groupingcontainment.h"
 
35
#include "spacer.h"
 
36
 
 
37
REGISTER_GROUP(FlowGroup)
 
38
 
 
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)),
 
48
            SPACING(4)
 
49
{
 
50
    resize(200,200);
 
51
 
 
52
    m_arrows->setImagePath("widgets/arrows");
 
53
    m_arrows->setContainsMultipleImages(true);
 
54
    m_arrows->resize(KIconLoader::SizeSmall, KIconLoader::SizeSmall);
 
55
 
 
56
    m_prevArrow->setPreferredSize(IconSize(KIconLoader::Panel), IconSize(KIconLoader::Panel));
 
57
    m_prevArrow->hide();
 
58
    m_nextArrow->setPreferredSize(IconSize(KIconLoader::Panel), IconSize(KIconLoader::Panel));
 
59
    m_nextArrow->hide();
 
60
 
 
61
    connect(m_prevArrow, SIGNAL(pressed()), this, SLOT(scrollPrev()));
 
62
    connect(m_nextArrow, SIGNAL(pressed()), this, SLOT(scrollNext()));
 
63
 
 
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));
 
70
 
 
71
    m_mainLayout->addItem(m_scrollWidget);
 
72
    setLayout(m_mainLayout);
 
73
 
 
74
    m_spacer->hide();
 
75
 
 
76
    setGroupType(AbstractGroup::ConstrainedGroup);
 
77
    setUseSimplerBackgroundForChildren(true);
 
78
 
 
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*)));
 
83
}
 
84
 
 
85
FlowGroup::~FlowGroup()
 
86
{
 
87
 
 
88
}
 
89
 
 
90
QString FlowGroup::pluginName() const
 
91
{
 
92
    return QString("flow");
 
93
}
 
94
 
 
95
void FlowGroup::restoreChildGroupInfo(QGraphicsWidget *child, const KConfigGroup &group)
 
96
{
 
97
    QRectF rect;
 
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()));
 
101
    }
 
102
    child->setParentItem(m_container);
 
103
    child->setGeometry(rect);
 
104
 
 
105
    updateContents();
 
106
}
 
107
 
 
108
void FlowGroup::saveChildGroupInfo(QGraphicsWidget *child, KConfigGroup group) const
 
109
{
 
110
    if (m_mainLayout->orientation() == Qt::Horizontal) {
 
111
        group.writeEntry("Position", child->pos().x());
 
112
        group.writeEntry("Size", child->size().width());
 
113
    }
 
114
}
 
115
 
 
116
bool FlowGroup::showDropZone(const QPointF &pos)
 
117
{
 
118
    if (pos == QPointF()) {
 
119
        m_spacer->hide();
 
120
        updateContents();
 
121
 
 
122
        return false;
 
123
    }
 
124
 
 
125
    m_spacer->show();
 
126
    QGraphicsWidget *w = containment()->movingWidget();
 
127
    QSizeF pref;
 
128
    QSizeF min;
 
129
    if (children().contains(w)) {
 
130
        pref = QSizeF(w->effectiveSizeHint(Qt::PreferredSize));
 
131
        min = QSizeF(w->effectiveSizeHint(Qt::MinimumSize));
 
132
    } else {
 
133
        pref = QSizeF(40, 40);
 
134
        min = QSizeF(5, 5);
 
135
    }
 
136
    if (m_mainLayout->orientation() == Qt::Horizontal) {
 
137
        m_spacer->setPreferredWidth(pref.width());
 
138
        m_spacer->setMinimumWidth(min.width());
 
139
    } else {
 
140
        m_spacer->setPreferredHeight(pref.height());
 
141
        m_spacer->setMinimumHeight(min.height());
 
142
    }
 
143
    addItem(m_spacer, mapToItem(m_container, pos));
 
144
 
 
145
    return true;
 
146
}
 
147
 
 
148
Handle *FlowGroup::createHandleForChild(QGraphicsWidget *child)
 
149
{
 
150
    if (!children().contains(child)) {
 
151
        return 0;
 
152
    }
 
153
 
 
154
    Plasma::Applet *a = qobject_cast<Plasma::Applet *>(child);
 
155
    if (a) {
 
156
        return new GridHandle(containment(), a);
 
157
    }
 
158
 
 
159
    return new GridHandle(containment(), static_cast<AbstractGroup *>(child));
 
160
}
 
161
 
 
162
void FlowGroup::layoutChild(QGraphicsWidget *child, const QPointF &pos)
 
163
{
 
164
    addItem(child, mapToItem(m_container, pos));
 
165
    m_spacer->hide();
 
166
    updateContents();
 
167
}
 
168
 
 
169
void FlowGroup::addItem(QGraphicsWidget *child, const QPointF &pos)
 
170
{
 
171
    child->setParentItem(m_container);
 
172
    QRectF rect(pos, child->effectiveSizeHint(Qt::PreferredSize));
 
173
    if (m_mainLayout->orientation() == Qt::Horizontal) {
 
174
        rect.setY(0);
 
175
    } else {
 
176
        rect.setX(0);
 
177
    }
 
178
    child->setGeometry(rect);
 
179
 
 
180
    updateContents();
 
181
}
 
182
 
 
183
void FlowGroup::appletRemoved(Plasma::Applet *)
 
184
{
 
185
    updateContents();
 
186
}
 
187
 
 
188
void FlowGroup::groupRemoved(AbstractGroup *)
 
189
{
 
190
    updateContents();
 
191
}
 
192
 
 
193
void FlowGroup::scrollPrev()
 
194
{
 
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())));
 
199
    } else {
 
200
        m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.topLeft()) -
 
201
                                                 QPointF(0, 40), QSize(geom.width(), 40)));
 
202
    }
 
203
}
 
204
 
 
205
void FlowGroup::scrollNext()
 
206
{
 
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())));
 
211
    } else {
 
212
        m_scrollWidget->ensureRectVisible(QRectF(m_scrollWidget->mapToItem(m_container, geom.bottomLeft()),
 
213
                                                 QSize(geom.width(), 40)));
 
214
    }
 
215
}
 
216
 
 
217
void FlowGroup::updateContents()
 
218
{
 
219
    const bool horizontal = (m_mainLayout->orientation() == Qt::Horizontal);
 
220
 
 
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()) {
 
224
        list << m_spacer;
 
225
    }
 
226
    GroupingContainment *c = containment();
 
227
    if (c) {
 
228
        list.removeOne(c->movingWidget());
 
229
    }
 
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);
 
237
                break;
 
238
            }
 
239
        }
 
240
        if (!childs.contains(child)) {
 
241
            childs << child;
 
242
        }
 
243
    }
 
244
 
 
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());
 
250
 
 
251
        QGraphicsWidget *next = (i < childs.count() - 1 ? childs.at(i + 1) : 0);
 
252
 
 
253
        if (horizontal) {
 
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());
 
258
 
 
259
            const qreal r = (next ? next->pos().x() - SPACING : containerRect.right());
 
260
            if (r < rect.right() || QSizePolicy::ExpandFlag & child->sizePolicy().horizontalPolicy()) {
 
261
                rect.setRight(r);
 
262
            }
 
263
 
 
264
            if (rect.width() < min) {
 
265
                qreal newR = rect.x() + min;
 
266
                if (newR > r) {
 
267
                    newR = r;
 
268
                }
 
269
                rect.setRight(newR);
 
270
            }
 
271
        } else {
 
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());
 
276
 
 
277
            const qreal b = (next ? next->pos().y() - SPACING : containerRect.bottom());
 
278
            if (b < rect.bottom() || QSizePolicy::ExpandFlag & child->sizePolicy().verticalPolicy()) {
 
279
                rect.setBottom(b);
 
280
            }
 
281
 
 
282
            if (rect.height() < min) {
 
283
                qreal newB = rect.y() + min;
 
284
                if (newB > b) {
 
285
                    newB = b;
 
286
                }
 
287
                rect.setBottom(newB);
 
288
            }
 
289
        }
 
290
 
 
291
        child->setGeometry(rect);
 
292
    }
 
293
 
 
294
    QRectF geom(m_scrollWidget->viewportGeometry());
 
295
    if (horizontal) {
 
296
        if (m_prevArrow->isVisible()) {
 
297
            geom.setWidth(geom.width() + m_prevArrow->geometry().width() * 2 + SPACING * 2);
 
298
        }
 
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());
 
303
        }
 
304
    } else {
 
305
        if (m_prevArrow->isVisible()) {
 
306
            geom.setHeight(geom.height() + m_prevArrow->geometry().height() * 2 + SPACING * 2);
 
307
        }
 
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());
 
312
        }
 
313
    }
 
314
 
 
315
    QRectF r;
 
316
    if (!childs.isEmpty()) {
 
317
        r = QRectF(childs.first()->pos(), childs.last()->geometry().bottomRight());
 
318
    }
 
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);
 
329
                m_prevArrow->hide();
 
330
                m_nextArrow->hide();
 
331
            }
 
332
        } else {
 
333
            if (!m_prevArrow->isVisible()) {
 
334
                m_mainLayout->insertItem(0, m_prevArrow);
 
335
                m_mainLayout->addItem(m_nextArrow);
 
336
                m_prevArrow->show();
 
337
                m_nextArrow->show();
 
338
            }
 
339
        }
 
340
    } else if (m_prevArrow->isVisible()) {
 
341
        m_mainLayout->removeItem(m_prevArrow);
 
342
        m_mainLayout->removeItem(m_nextArrow);
 
343
        m_prevArrow->hide();
 
344
        m_nextArrow->hide();
 
345
    }
 
346
}
 
347
 
 
348
void FlowGroup::constraintsEvent(Plasma::Constraints constraints)
 
349
{
 
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());
 
361
            }
 
362
        } else {
 
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);
 
371
            }
 
372
        }
 
373
        updateContents();
 
374
    }
 
375
}
 
376
 
 
377
void FlowGroup::resizeEvent(QGraphicsSceneResizeEvent *event)
 
378
{
 
379
    AbstractGroup::resizeEvent(event);
 
380
 
 
381
    updateContents();
 
382
}
 
383
 
 
384
GroupInfo FlowGroup::groupInfo()
 
385
{
 
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);
 
390
 
 
391
    return gi;
 
392
}
 
393
 
 
394
#include "flowgroup.moc"