~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to plasma/desktop/containments/panel/panel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
*   Copyright 2007 by Alex Merry <alex.merry@kdemail.net>
 
3
*   Copyright 2008 by Alexis Ménard <darktears31@gmail.com>
 
4
*
 
5
*   This program is free software; you can redistribute it and/or modify
 
6
*   it under the terms of the GNU Library General Public License version 2,
 
7
*   or (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 "panel.h"
 
21
 
 
22
#include <limits>
 
23
 
 
24
#include <QAction>
 
25
#include <QApplication>
 
26
#include <QGraphicsLinearLayout>
 
27
#include <QGraphicsLayout>
 
28
#include <QGraphicsSceneDragDropEvent>
 
29
#include <QTimer>
 
30
#include <QPainter>
 
31
 
 
32
#include <KDebug>
 
33
#include <KIcon>
 
34
#include <KIconLoader>
 
35
 
 
36
#include <Plasma/Corona>
 
37
#include <Plasma/FrameSvg>
 
38
#include <Plasma/Theme>
 
39
#include <Plasma/AbstractToolBox>
 
40
#include <Plasma/View>
 
41
#include <Plasma/PaintUtils>
 
42
#include <Plasma/WindowEffects>
 
43
 
 
44
#include <kephal/screens.h>
 
45
 
 
46
using namespace Plasma;
 
47
 
 
48
class Spacer : public QGraphicsWidget
 
49
{
 
50
public:
 
51
    Spacer(QGraphicsWidget *parent)
 
52
         : QGraphicsWidget(parent),
 
53
           m_visible(true)
 
54
    {
 
55
        setAcceptDrops(true);
 
56
    }
 
57
 
 
58
    ~Spacer()
 
59
    {}
 
60
 
 
61
    Panel *panel;
 
62
    bool m_visible;
 
63
 
 
64
protected:
 
65
    void dropEvent(QGraphicsSceneDragDropEvent *event)
 
66
    {
 
67
        event->setPos(mapToParent(event->pos()));
 
68
        panel->dropEvent(event);
 
69
    }
 
70
 
 
71
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * widget = 0)
 
72
    {
 
73
        Q_UNUSED(option)
 
74
        Q_UNUSED(widget)
 
75
 
 
76
        if (!m_visible) {
 
77
            return;
 
78
        }
 
79
 
 
80
        //TODO: make this a pretty gradient?
 
81
        painter->setRenderHint(QPainter::Antialiasing);
 
82
        QPainterPath p = Plasma::PaintUtils::roundedRectangle(contentsRect().adjusted(1, 1, -2, -2), 4);
 
83
        QColor c = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
 
84
        c.setAlphaF(0.3);
 
85
 
 
86
        painter->fillPath(p, c);
 
87
    }
 
88
};
 
89
 
 
90
Panel::Panel(QObject *parent, const QVariantList &args)
 
91
    : Containment(parent, args),
 
92
      m_configureAction(0),
 
93
      m_currentSize(QSize(Kephal::ScreenUtils::screenSize(screen()).width(), 35)),
 
94
      m_maskDirty(true),
 
95
      m_canResize(true),
 
96
      m_spacerIndex(-1),
 
97
      m_spacer(0),
 
98
      m_lastSpace(0),
 
99
      m_layout(0),
 
100
      m_resizedApplets(0)
 
101
{
 
102
    setContainmentType(Containment::PanelContainment);
 
103
    setDrawWallpaper(false);
 
104
 
 
105
    m_background = new Plasma::FrameSvg(this);
 
106
    m_background->setImagePath("widgets/panel-background");
 
107
    m_background->setEnabledBorders(Plasma::FrameSvg::AllBorders);
 
108
    connect(m_background, SIGNAL(repaintNeeded()), this, SLOT(backgroundChanged()));
 
109
 
 
110
    m_lastSpaceTimer = new QTimer(this);
 
111
    m_lastSpaceTimer->setSingleShot(true);
 
112
    connect(m_lastSpaceTimer, SIGNAL(timeout()), this, SLOT(adjustLastSpace()));
 
113
 
 
114
    m_enableUpdateResizeTimer = new QTimer(this);
 
115
    m_enableUpdateResizeTimer->setSingleShot(true);
 
116
    m_enableUpdateResizeTimer->setInterval(400);
 
117
    connect(m_enableUpdateResizeTimer, SIGNAL(timeout()), this, SLOT(enableUpdateSize()));
 
118
 
 
119
    m_updateSizeTimer = new QTimer(this);
 
120
    m_updateSizeTimer->setSingleShot(true);
 
121
    m_updateSizeTimer->setInterval(10);
 
122
    connect(m_updateSizeTimer, SIGNAL(timeout()), this, SLOT(updateSize()));
 
123
 
 
124
    connect(this, SIGNAL(appletRemoved(Plasma::Applet*)), this, SLOT(appletWasRemoved(Plasma::Applet*)));
 
125
}
 
126
 
 
127
Panel::~Panel()
 
128
{
 
129
}
 
130
 
 
131
void Panel::init()
 
132
{
 
133
    Containment::init();
 
134
    //FIXME: This should be enabled, but in that case proxywidgets won't get rendered
 
135
    //setFlag(ItemClipsChildrenToShape, true);
 
136
 
 
137
    m_layout = new QGraphicsLinearLayout(this);
 
138
    m_layout->setSpacing(4);
 
139
    m_layout->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding));
 
140
    updateBorders(geometry().toRect());
 
141
    setLayout(m_layout);
 
142
    m_layout->setMaximumSize(size());
 
143
 
 
144
    KConfigGroup cg = config("Configuration");
 
145
 
 
146
    m_currentSize = cg.readEntry("minimumSize", m_currentSize);
 
147
    if (formFactor() == Plasma::Vertical) {
 
148
        m_currentSize.expandedTo(QSize(0, 35));
 
149
    } else {
 
150
        m_currentSize.expandedTo(QSize(35, 0));
 
151
    }
 
152
 
 
153
    setMinimumSize(cg.readEntry("minimumSize", m_currentSize));
 
154
    setMaximumSize(cg.readEntry("maximumSize", m_currentSize));
 
155
}
 
156
 
 
157
QList<QAction*> Panel::contextualActions()
 
158
{
 
159
    if (!m_configureAction) {
 
160
        m_configureAction = new QAction(i18n("Panel Settings"), this);
 
161
        m_configureAction->setIcon(KIcon("configure"));
 
162
        connect(m_configureAction, SIGNAL(triggered()), this, SIGNAL(toolBoxToggled()));
 
163
 
 
164
        constraintsEvent(Plasma::ImmutableConstraint);
 
165
    }
 
166
 
 
167
    QList<QAction*> actions;
 
168
 
 
169
    actions.append(m_configureAction);
 
170
 
 
171
    return actions;
 
172
}
 
173
 
 
174
void Panel::backgroundChanged()
 
175
{
 
176
    constraintsEvent(Plasma::LocationConstraint);
 
177
    update();
 
178
}
 
179
 
 
180
void Panel::adjustLastSpace()
 
181
{
 
182
    if (!m_layout) {
 
183
        return;
 
184
    }
 
185
 
 
186
    bool useSpacer = true;
 
187
 
 
188
    if (formFactor() == Plasma::Vertical) {
 
189
        foreach (Applet *applet, applets()) {
 
190
            if (applet->sizePolicy().verticalPolicy() & QSizePolicy::ExpandFlag) {
 
191
                useSpacer = false;
 
192
                break;
 
193
            }
 
194
        }
 
195
    } else {
 
196
        foreach (Applet *applet, applets()) {
 
197
            if (applet->sizePolicy().horizontalPolicy() & QSizePolicy::ExpandFlag) {
 
198
                useSpacer = false;
 
199
                break;
 
200
            }
 
201
        }
 
202
    }
 
203
 
 
204
    if (useSpacer) {
 
205
        if (!m_lastSpace) {
 
206
            m_lastSpace = new Spacer(this);
 
207
            m_lastSpace->panel = this;
 
208
            m_lastSpace->m_visible = false;
 
209
            m_lastSpace->setPreferredSize(0,0);
 
210
            m_lastSpace->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
211
            m_layout->addItem(m_lastSpace);
 
212
        }
 
213
    } else {
 
214
        m_layout->removeItem(m_lastSpace);
 
215
        delete m_lastSpace;
 
216
        m_lastSpace = 0;
 
217
    }
 
218
}
 
219
 
 
220
void Panel::enableUpdateSize()
 
221
{
 
222
    m_canResize = true;
 
223
    if (m_resizedApplets > 0) {
 
224
        updateSize();
 
225
    }
 
226
}
 
227
 
 
228
void Panel::layoutApplet(Plasma::Applet* applet, const QPointF &pos)
 
229
{
 
230
    // this gets called whenever an applet is added, and we add it to our layout
 
231
    if (!m_layout) {
 
232
        return;
 
233
    }
 
234
 
 
235
    Plasma::FormFactor f = formFactor();
 
236
    int insertIndex = -1;
 
237
 
 
238
    //Enlarge the panel if possible and needed
 
239
    QSizeF appletHint = applet->preferredSize();
 
240
    QSizeF panelHint = m_layout->preferredSize();
 
241
    if (f == Plasma::Horizontal) {
 
242
        if (panelHint.width() + appletHint.width() > size().width()) {
 
243
            resize(panelHint.width() + appletHint.width(), size().height());
 
244
        }
 
245
    } else {
 
246
        if (panelHint.height() + appletHint.height() > size().height()) {
 
247
            resize(size().width(), panelHint.height() + appletHint.height());
 
248
        }
 
249
    }
 
250
 
 
251
    m_layout->setMinimumSize(size());
 
252
    m_layout->setMaximumSize(size());
 
253
 
 
254
    //if pos is (-1,-1) insert at the end of the panel
 
255
    if (pos != QPoint(-1, -1)) {
 
256
        for (int i = 0; i < m_layout->count(); ++i) {
 
257
            QRectF siblingGeometry = m_layout->itemAt(i)->geometry();
 
258
            if (f == Plasma::Horizontal) {
 
259
                qreal middle = (siblingGeometry.left() + siblingGeometry.right()) / 2.0;
 
260
                if (QApplication::layoutDirection() == Qt::RightToLeft) {
 
261
                    if (pos.x() > middle) {
 
262
                        insertIndex = i;
 
263
                    } else if (pos.x() >= siblingGeometry.left()) {
 
264
                        insertIndex = i + 1;
 
265
                    }
 
266
                } else if (pos.x() < middle) {
 
267
                    insertIndex = i;
 
268
                    break;
 
269
                } else if (pos.x() <= siblingGeometry.right()) {
 
270
                    insertIndex = i + 1;
 
271
                    break;
 
272
                }
 
273
            } else { // Plasma::Vertical
 
274
                qreal middle = (siblingGeometry.top() + siblingGeometry.bottom()) / 2.0;
 
275
                if (pos.y() < middle) {
 
276
                    insertIndex = i;
 
277
                    break;
 
278
                } else if (pos.y() <= siblingGeometry.bottom()) {
 
279
                    insertIndex = i + 1;
 
280
                    break;
 
281
                }
 
282
            }
 
283
        }
 
284
    }
 
285
 
 
286
    m_layout->removeItem(m_lastSpace);
 
287
 
 
288
    if (insertIndex == -1 || insertIndex >= m_layout->count()) {
 
289
        m_layout->addItem(applet);
 
290
    } else {
 
291
        m_layout->insertItem(insertIndex, applet);
 
292
    }
 
293
 
 
294
    if (m_lastSpace) {
 
295
        m_layout->addItem(m_lastSpace);
 
296
    }
 
297
 
 
298
    //FIXME: there must be some beter way to do this rather than this rather error prone arbitrary wait
 
299
    m_lastSpaceTimer->start(2000);
 
300
 
 
301
    connect(applet, SIGNAL(sizeHintChanged(Qt::SizeHint)), this, SLOT(delayedUpdateSize()), Qt::UniqueConnection);
 
302
}
 
303
 
 
304
void Panel::delayedUpdateSize()
 
305
{
 
306
    ++m_resizedApplets;
 
307
 
 
308
    if (!m_updateSizeTimer->isActive()) {
 
309
        m_updateSizeTimer->start();
 
310
    }
 
311
}
 
312
 
 
313
void Panel::appletWasRemoved(Plasma::Applet* applet)
 
314
{
 
315
    disconnect(applet, SIGNAL(sizeHintChanged(Qt::SizeHint)), this, SLOT(delayedUpdateSize()));
 
316
 
 
317
    if (!m_layout) {
 
318
        return;
 
319
    }
 
320
 
 
321
    m_layout->removeItem(applet);
 
322
 
 
323
    //shrink the panel if possible
 
324
    if (formFactor() == Plasma::Horizontal) {
 
325
        resize(size().width() - applet->size().width(), size().height());
 
326
    } else {
 
327
        resize(size().width(), size().height() - applet->size().height());
 
328
    }
 
329
 
 
330
    m_layout->setMaximumSize(size());
 
331
    m_lastSpaceTimer->start(200);
 
332
}
 
333
 
 
334
void Panel::updateSize()
 
335
{
 
336
    if (!m_canResize || m_resizedApplets < 1) {
 
337
        m_resizedApplets = 0;
 
338
        return;
 
339
    }
 
340
 
 
341
    m_resizedApplets = 0;
 
342
    m_canResize = false;
 
343
 
 
344
    const bool horizontal = formFactor() != Plasma::Vertical;
 
345
    int delta = horizontal ? size().width() : size().height();
 
346
    foreach (Applet *applet, applets()) {
 
347
        if (horizontal) {
 
348
            delta -= applet->preferredSize().width();
 
349
        } else {
 
350
            delta -= applet->preferredSize().height();
 
351
        }
 
352
    }
 
353
    delta *= -1;
 
354
 
 
355
    //setting the preferred width when delta = 0 and preferredWidth() < minimumWidth()
 
356
    // leads to the same thing as setPreferredWidth(minimumWidth())
 
357
 
 
358
    if (delta != 0) {
 
359
        // amazing but true: preferedSize doesn't take into consideration margins.
 
360
        qreal l, t, r, b;
 
361
        m_layout->getContentsMargins(&l, &t, &r, &b);
 
362
 
 
363
        if (horizontal) {
 
364
            setPreferredWidth(preferredWidth() + delta + l + r);
 
365
        } else {
 
366
            setPreferredHeight(preferredHeight() + delta + t + b);
 
367
        }
 
368
    }
 
369
 
 
370
    //kDebug() << "resize to" << preferredSize() << delta << ", was" << size();
 
371
    resize(preferredSize());
 
372
 
 
373
    //for a while we won't execute updateSize() again
 
374
    m_enableUpdateResizeTimer->start();
 
375
}
 
376
 
 
377
void Panel::updateBorders(const QRect &geom, bool inPaintEvent)
 
378
{
 
379
    Plasma::Location loc = location();
 
380
    FrameSvg::EnabledBorders enabledBorders = FrameSvg::AllBorders;
 
381
 
 
382
    int s = screen();
 
383
    //kDebug() << loc << s << formFactor() << geometry();
 
384
 
 
385
    qreal topHeight = m_background->marginSize(Plasma::TopMargin);
 
386
    qreal bottomHeight = m_background->marginSize(Plasma::BottomMargin);
 
387
    qreal leftWidth = m_background->marginSize(Plasma::LeftMargin);
 
388
    qreal rightWidth = m_background->marginSize(Plasma::RightMargin);
 
389
 
 
390
    //remove unwanted borders
 
391
    if (s < 0) {
 
392
        // do nothing in this case, we want all the borders
 
393
    } else if (loc == BottomEdge || loc == TopEdge) {
 
394
        QRect r = Kephal::ScreenUtils::screenGeometry(s);
 
395
 
 
396
        if (loc == BottomEdge) {
 
397
            enabledBorders ^= FrameSvg::BottomBorder;
 
398
            bottomHeight = 0;
 
399
        } else {
 
400
            enabledBorders ^= FrameSvg::TopBorder;
 
401
            topHeight = 0;
 
402
        }
 
403
 
 
404
        if (geom.x() <= r.x()) {
 
405
            enabledBorders ^= FrameSvg::LeftBorder;
 
406
            leftWidth = 0;
 
407
        }
 
408
        if (geom.right() >= r.right()) {
 
409
            enabledBorders ^= FrameSvg::RightBorder;
 
410
            rightWidth = 0;
 
411
        }
 
412
 
 
413
        //kDebug() << "top/bottom: Width:" << width << ", height:" << height;
 
414
    } else if (loc == LeftEdge || loc == RightEdge) {
 
415
        QRect r = Kephal::ScreenUtils::screenGeometry(s);
 
416
 
 
417
        if (loc == RightEdge) {
 
418
            enabledBorders ^= FrameSvg::RightBorder;
 
419
            rightWidth = 0;
 
420
        } else {
 
421
            enabledBorders ^= FrameSvg::LeftBorder;
 
422
            leftWidth = 0;
 
423
        }
 
424
 
 
425
        if (geom.y() <= r.y()) {
 
426
            enabledBorders ^= FrameSvg::TopBorder;
 
427
            topHeight = 0;
 
428
        }
 
429
 
 
430
        if (geom.bottom() >= r.bottom()) {
 
431
            enabledBorders ^= FrameSvg::BottomBorder;
 
432
            bottomHeight = 0;
 
433
        }
 
434
 
 
435
        //kDebug() << "left/right: Width:" << width << ", height:" << height;
 
436
    } else {
 
437
        kDebug() << "no location!?";
 
438
    }
 
439
 
 
440
    //activate borders and fetch sizes again
 
441
    m_background->setEnabledBorders(enabledBorders);
 
442
    m_background->getMargins(leftWidth, topHeight, rightWidth, bottomHeight);
 
443
 
 
444
    //calculation of extra margins has to be done after getMargins
 
445
    const QGraphicsItem *box = toolBox();
 
446
    if (box && immutability() == Mutable) {
 
447
        QSizeF s = box->boundingRect().size();
 
448
        if (formFactor() == Vertical) {
 
449
            //hardcoded extra margin for the toolbox right now
 
450
            bottomHeight += s.height() + 2;
 
451
            //Default to horizontal for now
 
452
        } else {
 
453
            rightWidth += s.width() + 2;
 
454
        }
 
455
    }
 
456
 
 
457
    //invalidate the layout and set again
 
458
    if (m_layout) {
 
459
        switch (location()) {
 
460
        case LeftEdge:
 
461
            rightWidth = qMin(rightWidth, qMax(qreal(2), size().width() - KIconLoader::SizeMedium));
 
462
            break;
 
463
        case RightEdge:
 
464
            leftWidth = qMin(leftWidth, qMax(qreal(2), size().width() - KIconLoader::SizeMedium));
 
465
            break;
 
466
        case TopEdge:
 
467
            bottomHeight = qMin(bottomHeight, qMax(qreal(2), size().height() - KIconLoader::SizeMedium));
 
468
            break;
 
469
        case BottomEdge:
 
470
            topHeight = qMin(topHeight, qMax(qreal(2), size().height() - KIconLoader::SizeMedium));
 
471
            break;
 
472
        default:
 
473
            break;
 
474
        }
 
475
 
 
476
        m_layout->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
 
477
 
 
478
        if (!inPaintEvent) {
 
479
            resize(preferredSize());
 
480
        }
 
481
    }
 
482
}
 
483
 
 
484
void Panel::constraintsEvent(Plasma::Constraints constraints)
 
485
{
 
486
    if (constraints & Plasma::FormFactorConstraint) {
 
487
        m_maskDirty = true;
 
488
 
 
489
        Plasma::FormFactor form = formFactor();
 
490
        Qt::Orientation layoutDirection = form == Plasma::Vertical ? Qt::Vertical : Qt::Horizontal;
 
491
        // create or set up our layout!
 
492
        if (m_layout) {
 
493
            m_layout->setMaximumSize(size());
 
494
            m_layout->setOrientation(layoutDirection);
 
495
        }
 
496
    }
 
497
 
 
498
    //we need to know if the width or height is 100%
 
499
    if (constraints & Plasma::LocationConstraint || constraints & Plasma::SizeConstraint) {
 
500
        m_maskDirty = true;
 
501
        m_currentSize = geometry().size().toSize();
 
502
        QRectF screenRect = screen() >= 0 ? Kephal::ScreenUtils::screenGeometry(screen()) :
 
503
                                            geometry();
 
504
 
 
505
        if ((formFactor() == Horizontal && m_currentSize.width() >= screenRect.width()) ||
 
506
            (formFactor() == Vertical && m_currentSize.height() >= screenRect.height())) {
 
507
            m_background->setElementPrefix(location());
 
508
        } else {
 
509
            switch (location()) {
 
510
            case LeftEdge:
 
511
                //this call will automatically fallback at no prefix if the element isn't available
 
512
                m_background->setElementPrefix("west-mini");
 
513
                break;
 
514
            case RightEdge:
 
515
                m_background->setElementPrefix("east-mini");
 
516
                break;
 
517
            case TopEdge:
 
518
                m_background->setElementPrefix("north-mini");
 
519
                break;
 
520
            case BottomEdge:
 
521
            default:
 
522
                m_background->setElementPrefix("south-mini");
 
523
                break;
 
524
            }
 
525
        }
 
526
 
 
527
        m_background->resizeFrame(m_currentSize);
 
528
 
 
529
        //FIXME: this seems the only way to correctly resize the layout the first time when the
 
530
        // saved panel size is less than the default is to setting a maximum size.
 
531
        // this shouldn't happen. maybe even a qgraphicslayout bug?
 
532
        if (m_layout && (constraints & Plasma::SizeConstraint)) {
 
533
            m_layout->setMaximumSize(size());
 
534
        }
 
535
 
 
536
        if (constraints & Plasma::LocationConstraint) {
 
537
            setFormFactorFromLocation(location());
 
538
        }
 
539
    }
 
540
 
 
541
    if (constraints & Plasma::StartupCompletedConstraint) {
 
542
        connect(this, SIGNAL(appletAdded(Plasma::Applet*,QPointF)),
 
543
                this, SLOT(layoutApplet(Plasma::Applet*,QPointF)));
 
544
    }
 
545
 
 
546
    if (constraints & Plasma::ImmutableConstraint) {
 
547
        bool unlocked = immutability() == Plasma::Mutable;
 
548
 
 
549
        if (m_configureAction) {
 
550
            m_configureAction->setEnabled(unlocked);
 
551
            m_configureAction->setVisible(unlocked);
 
552
        }
 
553
 
 
554
        m_maskDirty = true;
 
555
        updateBorders(geometry().toRect());
 
556
    }
 
557
}
 
558
 
 
559
void Panel::saveState(KConfigGroup &config) const
 
560
{
 
561
    config.writeEntry("minimumSize", minimumSize());
 
562
    config.writeEntry("maximumSize", maximumSize());
 
563
}
 
564
 
 
565
void Panel::paintInterface(QPainter *painter,
 
566
                           const QStyleOptionGraphicsItem *option,
 
567
                           const QRect& contentsRect)
 
568
{
 
569
    Q_UNUSED(contentsRect)
 
570
    //FIXME: this background drawing is bad and ugly =)
 
571
    // draw the background untransformed (saves lots of per-pixel-math)
 
572
    painter->resetTransform();
 
573
 
 
574
    const Containment::StyleOption *containmentOpt = qstyleoption_cast<const Containment::StyleOption *>(option);
 
575
 
 
576
    QRect viewGeom;
 
577
    if (containmentOpt && containmentOpt->view) {
 
578
        viewGeom = containmentOpt->view->geometry();
 
579
    } else {
 
580
        viewGeom = m_lastViewGeom;
 
581
    }
 
582
 
 
583
    if (m_maskDirty || m_lastViewGeom != viewGeom) {
 
584
        m_maskDirty = false;
 
585
        m_lastViewGeom = viewGeom;
 
586
 
 
587
        updateBorders(viewGeom, true);
 
588
        if (containmentOpt && containmentOpt->view && !m_background->mask().isEmpty()) {
 
589
            const QRegion mask = m_background->mask();
 
590
            containmentOpt->view->setMask(mask);
 
591
            Plasma::WindowEffects::enableBlurBehind(containmentOpt->view->winId(), true, mask);
 
592
        }
 
593
    }
 
594
 
 
595
    // blit the background (saves all the per-pixel-products that blending does)
 
596
    painter->setCompositionMode(QPainter::CompositionMode_Source);
 
597
    painter->setRenderHint(QPainter::Antialiasing);
 
598
 
 
599
    m_background->paintFrame(painter, option->exposedRect);
 
600
}
 
601
 
 
602
void Panel::setFormFactorFromLocation(Plasma::Location loc) {
 
603
    switch (loc) {
 
604
        case BottomEdge:
 
605
        case TopEdge:
 
606
            //kDebug() << "setting horizontal form factor";
 
607
            setFormFactor(Plasma::Horizontal);
 
608
            break;
 
609
        case RightEdge:
 
610
        case LeftEdge:
 
611
            //kDebug() << "setting vertical form factor";
 
612
            setFormFactor(Plasma::Vertical);
 
613
            break;
 
614
        case Floating:
 
615
            //TODO: implement a form factor for floating panels
 
616
            kDebug() << "Floating is unimplemented.";
 
617
            break;
 
618
        default:
 
619
            kDebug() << "invalid location!!";
 
620
    }
 
621
}
 
622
 
 
623
void Panel::showDropZone(const QPoint pos)
 
624
{
 
625
    if (!scene() || !m_layout) {
 
626
        return;
 
627
    }
 
628
 
 
629
    if (pos == QPoint()) {
 
630
        if (m_spacer) {
 
631
            m_layout->removeItem(m_spacer);
 
632
            m_spacer->hide();
 
633
        }
 
634
        return;
 
635
    }
 
636
 
 
637
    //lucky case: the spacer is already in the right position
 
638
    if (m_spacer && m_spacer->geometry().contains(pos)) {
 
639
        return;
 
640
    }
 
641
 
 
642
    Plasma::FormFactor f = formFactor();
 
643
    int insertIndex = m_layout->count();
 
644
 
 
645
    //FIXME: needed in two places, make it a function?
 
646
    for (int i = 0; i < m_layout->count(); ++i) {
 
647
        QRectF siblingGeometry = m_layout->itemAt(i)->geometry();
 
648
 
 
649
        if (f == Plasma::Horizontal) {
 
650
            qreal middle = siblingGeometry.left() + (siblingGeometry.width() / 2.0);
 
651
            if (pos.x() < middle) {
 
652
                insertIndex = i;
 
653
                break;
 
654
            } else if (pos.x() <= siblingGeometry.right()) {
 
655
                insertIndex = i + 1;
 
656
                break;
 
657
            }
 
658
        } else { // Plasma::Vertical
 
659
            qreal middle = siblingGeometry.top() + (siblingGeometry.height() / 2.0);
 
660
            if (pos.y() < middle) {
 
661
                insertIndex = i;
 
662
                break;
 
663
            } else if (pos.y() <= siblingGeometry.bottom()) {
 
664
                insertIndex = i + 1;
 
665
                break;
 
666
            }
 
667
        }
 
668
    }
 
669
 
 
670
    m_spacerIndex = insertIndex;
 
671
    if (insertIndex != -1) {
 
672
        if (!m_spacer) {
 
673
            m_spacer = new Spacer(this);
 
674
            m_spacer->panel = this;
 
675
        } else {
 
676
            m_layout->removeItem(m_spacer);
 
677
        }
 
678
 
 
679
        m_spacer->show();
 
680
        m_layout->insertItem(insertIndex, m_spacer);
 
681
    }
 
682
}
 
683
 
 
684
void Panel::restore(KConfigGroup &group)
 
685
{
 
686
    Containment::restore(group);
 
687
 
 
688
    KConfigGroup appletsConfig(&group, "Applets");
 
689
 
 
690
    QMap<int, Applet *> oderedApplets;
 
691
    QList<Applet *> unoderedApplets;
 
692
 
 
693
    foreach (Applet *applet, applets()) {
 
694
        KConfigGroup appletConfig(&appletsConfig, QString::number(applet->id()));
 
695
        KConfigGroup layoutConfig(&appletConfig, "LayoutInformation");
 
696
 
 
697
        int order = layoutConfig.readEntry("Order", -1);
 
698
 
 
699
        if (order > -1) {
 
700
            oderedApplets[order] = applet;
 
701
        //if LayoutInformation is not available use the usual way, as a bonus makes it retrocompatible with oler configs
 
702
        } else {
 
703
            unoderedApplets.append(applet);
 
704
        }
 
705
 
 
706
        connect(applet, SIGNAL(sizeHintChanged(Qt::SizeHint)), this, SLOT(delayedUpdateSize()), Qt::UniqueConnection);
 
707
    }
 
708
 
 
709
    foreach (Applet *applet, oderedApplets) {
 
710
        if (m_lastSpace) {
 
711
            m_layout->insertItem(m_layout->count()-1, applet);
 
712
        } else {
 
713
            m_layout->addItem(applet);
 
714
        }
 
715
    }
 
716
 
 
717
    foreach (Applet *applet, unoderedApplets) {
 
718
        layoutApplet(applet, applet->pos());
 
719
    }
 
720
 
 
721
    updateSize();
 
722
}
 
723
 
 
724
void Panel::saveContents(KConfigGroup &group) const
 
725
{
 
726
    Containment::saveContents(group);
 
727
 
 
728
    KConfigGroup appletsConfig(&group, "Applets");
 
729
    for (int order = 0; order < m_layout->count(); ++order) {
 
730
        const Applet *applet = dynamic_cast<Applet *>(m_layout->itemAt(order));
 
731
        if (applet) {
 
732
            KConfigGroup appletConfig(&appletsConfig, QString::number(applet->id()));
 
733
            KConfigGroup layoutConfig(&appletConfig, "LayoutInformation");
 
734
 
 
735
            layoutConfig.writeEntry("Order", order);
 
736
        }
 
737
    }
 
738
}
 
739
 
 
740
K_EXPORT_PLASMA_APPLET(panel, Panel)
 
741
 
 
742
#include "panel.moc"
 
743