~neon/kdeplasma-addons/trunk

« back to all changes in this revision

Viewing changes to applets/frame/frame.cpp

  • Committer: asouza
  • Date: 2011-02-01 19:41:58 UTC
  • Revision ID: svn-v4:283d02a7-25f6-0310-bc7c-ecb5cbfe19da:trunk/KDE/kdeplasma-addons:1218275
Move kdeplasma-addons to git

- You can find information about the project in the link below:

https://projects.kde.org/projects/kde/kdeplasma-addons/repository

- And you can clone the repository using:

git clone git://anongit.kde.org/kdeplasma-addons


Thanks eean and all the sysadmins for the help.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 *   Copyright  2007 by Anne-Marie Mahfouf <annma@kde.org>                 *
3
 
 *   Copyright  2007 by Antonio Vinci <mercurio@personellarete.it>         *
4
 
 *   Copyright  2008 by Thomas Coopman <thomas.coopman@gmail.com>          *
5
 
 *                                                                         *
6
 
 *   This program is free software; you can redistribute it and/or modify  *
7
 
 *   it under the terms of the GNU General Public License as published by  *
8
 
 *   the Free Software Foundation; either version 2 of the License, or     *
9
 
 *   (at your option) any later version.                                   *
10
 
 *                                                                         *
11
 
 *   This program is distributed in the hope that it will be useful,       *
12
 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 
 *   GNU General Public License for more details.                          *
15
 
 *                                                                         *
16
 
 *   You should have received a copy of the GNU General Public License     *
17
 
 *   along with this program; if not, write to the                         *
18
 
 *   Free Software Foundation, Inc.,                                       *
19
 
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
20
 
 ***************************************************************************/
21
 
 
22
 
#include "frame.h"
23
 
 
24
 
#include <QPainter>
25
 
#include <QPixmap>
26
 
#include <QStyleOptionGraphicsItem>
27
 
#include <QGraphicsSceneDragDropEvent>
28
 
#include <QGraphicsLinearLayout>
29
 
#include <QPen>
30
 
#include <QCheckBox>
31
 
#include <QFileInfo>
32
 
#include <QStandardItemModel>
33
 
#include <QThreadPool>
34
 
 
35
 
#include <KDebug>
36
 
#include <KConfigDialog>
37
 
#include <KSharedConfig>
38
 
#include <KRun>
39
 
#include <KUrl>
40
 
#include <KDirSelectDialog>
41
 
#include <KServiceTypeTrader>
42
 
#include <kglobalsettings.h>
43
 
 
44
 
#include <Plasma/PaintUtils>
45
 
#include <Plasma/DataEngine>
46
 
#include <Plasma/ToolButton>
47
 
#include <Plasma/Frame>
48
 
#include <Plasma/ToolTipContent>
49
 
#include <Plasma/ToolTipManager>
50
 
 
51
 
#include <math.h>
52
 
 
53
 
#include "configdialog.h"
54
 
#include "picture.h"
55
 
#include "slideshow.h"
56
 
#include "imagescaler.h"
57
 
 
58
 
Frame::Frame(QObject *parent, const QVariantList &args)
59
 
        : Plasma::Applet(parent, args),
60
 
        m_configDialog(0),
61
 
        m_slideFrame(0)
62
 
{
63
 
    setHasConfigurationInterface(true);
64
 
    setAcceptDrops(true);
65
 
    setAcceptsHoverEvents(true);
66
 
    setCacheMode(QGraphicsItem::DeviceCoordinateCache);
67
 
    resize(400, 300);
68
 
    //make size()==contentssize(), resolves auto-shrinking once for all
69
 
    setContentsMargins(0, 0, 0, 0);
70
 
    m_mySlideShow = new SlideShow(this);
71
 
    if (args.count()) {
72
 
        m_currentUrl = args.value(0).toString();
73
 
    } else {
74
 
        m_currentUrl = KUrl();
75
 
    }
76
 
    setAssociatedApplicationUrls(m_currentUrl);
77
 
 
78
 
    m_updateTimer = new QTimer(this);
79
 
    m_updateTimer->setSingleShot(true);
80
 
    connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(delayedUpdateSize()));
81
 
 
82
 
    m_autoUpdateTimer = new QTimer(this);
83
 
    m_autoUpdateTimer->setSingleShot(true);
84
 
    connect(m_autoUpdateTimer, SIGNAL(timeout()), this, SLOT(reloadImage()));
85
 
}
86
 
 
87
 
Frame::~Frame()
88
 
{
89
 
    m_autoUpdateTimer->stop();
90
 
}
91
 
 
92
 
void Frame::init()
93
 
{
94
 
    bool frameReceivedUrlArgs = false;
95
 
    if (!m_currentUrl.isEmpty()) {
96
 
        frameReceivedUrlArgs = true;
97
 
    }
98
 
 
99
 
    m_currentDay = QDate::currentDate();
100
 
    
101
 
    m_slideNumber = 0;
102
 
 
103
 
    // Frame & Shadow dimensions
104
 
    m_frameOutline = 8;
105
 
    m_swOutline = 8;
106
 
 
107
 
    // Initialize the slideshow timer
108
 
    connect(m_mySlideShow, SIGNAL(pictureUpdated()), this, SLOT(scalePictureAndUpdate()));
109
 
 
110
 
    connect(&m_waitForResize, SIGNAL(timeout()), this, SLOT(scalePictureAndUpdate()));
111
 
    m_waitForResize.setSingleShot(true);
112
 
    m_waitForResize.setInterval(200);
113
 
    
114
 
    configChanged();
115
 
    initSlideShow();
116
 
    
117
 
    KConfigGroup cg = config();
118
 
    if (frameReceivedUrlArgs) {
119
 
        cg.writeEntry("url", m_currentUrl);
120
 
        emit configNeedsSaving();
121
 
    }
122
 
 
123
 
    m_menuPresent = false;
124
 
 
125
 
    QAction *openAction = action("run associated application");
126
 
    openAction->setIcon(SmallIcon("image-x-generic"));
127
 
    openAction->setText(i18n("&Open Picture..."));    
128
 
}
129
 
 
130
 
void Frame::configChanged()
131
 
{
132
 
    // Get config values
133
 
    KConfigGroup cg = config();
134
 
    m_frameColor = cg.readEntry("frameColor", QColor(70, 90, 130)); //theme?
135
 
    m_frame = cg.readEntry("frame", false);
136
 
    m_shadow = cg.readEntry("shadow", true);
137
 
    m_roundCorners = cg.readEntry("roundCorners", false);
138
 
    m_slideShow = cg.readEntry("slideshow", false);
139
 
    m_random = cg.readEntry("random", false);
140
 
    m_recursiveSlideShow = cg.readEntry("recursive slideshow", false);
141
 
    m_slideShowPaths = cg.readEntry("slideshow paths", QStringList());
142
 
    m_slideshowTime = cg.readEntry("slideshow time", 60); // default to 1 minute
143
 
    m_currentUrl = cg.readEntry("url", m_currentUrl);
144
 
    setAssociatedApplicationUrls(m_currentUrl);
145
 
    m_potdProvider = cg.readEntry("potdProvider", QString());
146
 
    m_potd = cg.readEntry("potd", false);
147
 
    m_autoUpdateIntervall = cg.readEntry("autoupdate time", 0);
148
 
}
149
 
 
150
 
void Frame::slotOpenPicture()
151
 
{
152
 
    if (!hasAuthorization("LaunchApp")) {
153
 
        return;
154
 
    }
155
 
    KUrl url;
156
 
 
157
 
    if (m_slideShow) {
158
 
        url = m_mySlideShow->currentUrl();
159
 
    } else {
160
 
        url = m_currentUrl;
161
 
    }
162
 
 
163
 
    if (!url.path().isEmpty()) {
164
 
        new KRun(url, 0);
165
 
    }
166
 
}
167
 
 
168
 
void Frame::constraintsEvent(Plasma::Constraints constraints)
169
 
{
170
 
    if (constraints & Plasma::FormFactorConstraint) {
171
 
        setBackgroundHints(Plasma::Applet::NoBackground);
172
 
        if (formFactor() == Plasma::Horizontal) {
173
 
            m_frameOutline = 0;
174
 
            m_swOutline = 4;
175
 
        } else if (formFactor() == Plasma::Vertical) {
176
 
            m_frameOutline = 0;
177
 
            m_swOutline = 4;
178
 
        } else {
179
 
            m_frameOutline = 8;
180
 
            m_swOutline = 8;
181
 
            //Restore widget geometry to image proportions
182
 
            QSizeF sizeHint = contentSizeHint();
183
 
            if (sizeHint != geometry().size()) {
184
 
                resize(sizeHint);
185
 
                emit appletTransformedItself();
186
 
            }
187
 
        }
188
 
        m_updateTimer->start(400);
189
 
    }
190
 
 
191
 
    if (constraints & Plasma::SizeConstraint) {
192
 
        //If on panel, keep geometry to 4:3 ratio
193
 
        if (formFactor() == Plasma::Vertical) {
194
 
            setMinimumSize(QSizeF(0, contentsRect().width()/1.33));
195
 
            setMaximumSize(QSizeF(-1, contentsRect().width()/1.33));
196
 
        } else if (formFactor() == Plasma::Horizontal) {
197
 
            setMinimumSize(QSizeF(contentsRect().height()*1.33,0));
198
 
            setMaximumSize(QSizeF(contentsRect().height()*1.33,-1));
199
 
        } else {
200
 
            int min = 48;
201
 
            if (m_shadow) {
202
 
                min += m_swOutline;
203
 
            }
204
 
            if (m_frame) {
205
 
                min += m_frameOutline;
206
 
            }
207
 
            setMinimumSize(QSizeF(min, min));
208
 
            setMaximumSize(QSizeF());
209
 
        }
210
 
 
211
 
        if (m_slideShow) {
212
 
            checkSlideFrame();
213
 
 
214
 
            int x = contentsRect().center().x() - (m_slideFrame->size().width() / 2);
215
 
            int y = contentsRect().bottom() - m_slideFrame->size().height() - 5;
216
 
            m_slideFrame->setPos(x, y);
217
 
        }
218
 
 
219
 
        m_waitForResize.start();
220
 
        m_updateTimer->start(400);
221
 
    }
222
 
}
223
 
 
224
 
QSizeF Frame::contentSizeHint() const
225
 
{
226
 
    if (!m_pictureSize.isEmpty() && (formFactor() == Plasma::Planar || formFactor() == Plasma::MediaCenter)) {
227
 
        const qreal maxSize = qMax(contentsRect().width(), contentsRect().height());
228
 
        QSize size = m_pictureSize;
229
 
        size.scale(maxSize, maxSize, Qt::KeepAspectRatio);
230
 
        return size;
231
 
    } else {
232
 
        return contentsRect().size();
233
 
    }
234
 
}
235
 
 
236
 
QSizeF Frame::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
237
 
{
238
 
    if (which != Qt::PreferredSize) {
239
 
        return Applet::sizeHint(which, constraint);
240
 
    } else {
241
 
        return m_pictureSize;
242
 
    }
243
 
}
244
 
 
245
 
void Frame::scalePictureAndUpdate()
246
 
{
247
 
    QImage img = m_mySlideShow->image();
248
 
    ImageScaler *scaler = new ImageScaler(img, contentSizeHint().toSize());
249
 
    connect(scaler, SIGNAL(scaled(const QImage&)), this, SLOT(imageScaled(const QImage&)));
250
 
    QThreadPool::globalInstance()->start(scaler);
251
 
}
252
 
 
253
 
void Frame::imageScaled(const QImage &img)
254
 
{
255
 
    m_scaledImage = img;
256
 
    updatePicture();
257
 
}
258
 
 
259
 
void Frame::updatePicture()
260
 
{
261
 
    m_pictureSize = m_mySlideShow->image().size();
262
 
    QSizeF sizeHint = contentSizeHint();
263
 
    int frameLines = qMin(m_frameOutline, (int)(sizeHint.height()/10));
264
 
    const QSize contentsSize = sizeHint.toSize();
265
 
 
266
 
    if (m_currentUrl.url().isEmpty() && m_mySlideShow->currentUrl().isEmpty()) {
267
 
        setAssociatedApplicationUrls(KUrl::List());
268
 
    } else {
269
 
        setAssociatedApplicationUrls(m_mySlideShow->currentUrl());
270
 
    }
271
 
 
272
 
    if (sizeHint != geometry().size()) {
273
 
        emit sizeHintChanged(Qt::PreferredSize);
274
 
        resize(sizeHint);
275
 
    }
276
 
 
277
 
    kDebug() << "Rendering picture";
278
 
    Plasma::ToolTipContent toolTipData;
279
 
    toolTipData.setSubText(m_mySlideShow->currentUrl().fileName());
280
 
    Plasma::ToolTipManager::self()->setContent(this, toolTipData);
281
 
 
282
 
    // create a QPixmap which can be drawn in paintInterface()
283
 
    QPixmap picture = QPixmap::fromImage(m_scaledImage);
284
 
 
285
 
    if (picture.isNull()) {
286
 
        return;
287
 
    }
288
 
 
289
 
    m_pixmap = QPixmap(contentsSize);
290
 
    m_pixmap.fill(Qt::transparent);
291
 
    QPainter *p = new QPainter();
292
 
    p->begin(&m_pixmap);
293
 
 
294
 
    int roundingFactor = qMin(qreal(sizeHint.height() / 10), qreal(12.0)) * m_roundCorners;
295
 
    int swRoundness = roundingFactor + frameLines / 2 * m_frame * m_roundCorners;
296
 
 
297
 
    QRectF frameRect(QPoint(0, 0), contentsSize);
298
 
    frameRect.adjust(m_swOutline, m_swOutline, -m_swOutline, -m_swOutline); //Pretty useless.
299
 
 
300
 
    QSizeF scaledSize = frameRect.size();
301
 
    scaledSize.scale(frameRect.size(), Qt::KeepAspectRatio);
302
 
    frameRect = QRectF(QPoint(frameRect.x() + (frameRect.width() - scaledSize.width()) / 2,
303
 
                              frameRect.y() + (frameRect.height() - scaledSize.height()) / 2), scaledSize);
304
 
 
305
 
    QRectF shadowRect;
306
 
    if (m_frame) {
307
 
        shadowRect = frameRect.adjusted(-frameLines, -frameLines,
308
 
                                        frameLines, frameLines);
309
 
    } else {
310
 
        shadowRect = frameRect;
311
 
    }
312
 
 
313
 
    // The frame path. It will be used to draw the frame and clip the image.
314
 
    QPainterPath framePath = Plasma::PaintUtils::roundedRectangle(frameRect, roundingFactor);
315
 
 
316
 
    p->setRenderHint(QPainter::SmoothPixmapTransform, true);
317
 
    p->setRenderHint(QPainter::Antialiasing, true);
318
 
 
319
 
    // Shadow
320
 
    if (m_shadow) {
321
 
        // The shadow is a couple of lines with decreasing opacity painted around the path
322
 
        p->setBrush(Qt::NoBrush);
323
 
        QPen pen = QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::RoundJoin);
324
 
        int shadowLines = qMin((int)(sizeHint.height() / 6), m_swOutline);
325
 
 
326
 
        // The shadow is drawn from inside to the outside
327
 
        shadowRect.adjust(+shadowLines, +shadowLines, -shadowLines, -shadowLines);
328
 
 
329
 
        // Make the path to paint the frame in a bit smaller so it's inside the shadow
330
 
        frameRect.adjust(+shadowLines, +shadowLines, -shadowLines, -shadowLines);
331
 
        framePath = Plasma::PaintUtils::roundedRectangle(frameRect, roundingFactor);
332
 
 
333
 
        // Paint the shadow's lines around the picture
334
 
        for (int i = m_swOutline - shadowLines; i <= m_swOutline; i += 1) {
335
 
            // It's important to change the opacity using the QColor, as
336
 
            // QPainter->setOpacity() kills performance
337
 
            qreal opacity = 0.7 * exp(-(i / (double)(m_swOutline / 3)));
338
 
            pen.setColor(QColor(0, 0, 0, opacity * 254));
339
 
            p->setPen(pen);
340
 
            QPainterPath tr = Plasma::PaintUtils::roundedRectangle(shadowRect, swRoundness + i);
341
 
            p->drawPath(tr);
342
 
            shadowRect.adjust(-1, -1, + 1, + 1);
343
 
        }
344
 
    }
345
 
 
346
 
    p->setBrush(Qt::NoBrush);
347
 
 
348
 
    // Frame
349
 
    if (m_frame) {
350
 
        m_frameColor.setAlphaF(0.5);
351
 
        // The frame is painted twice as thick, the inner half lies behind the picture
352
 
        // This is important to not make the corners look "cut out" when rounded
353
 
        p->setPen(QPen(m_frameColor, frameLines * 2, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
354
 
        p->drawPath(framePath);
355
 
    }
356
 
 
357
 
    // Picture
358
 
    // We save the painter here so the clipping only happens on the pixmap,
359
 
    // not on pixmap, frame, shadow, etc
360
 
    p->save();
361
 
    if (m_roundCorners) {
362
 
        p->setClipPath(framePath);
363
 
    }
364
 
 
365
 
    // Respect the smoothScaling setting
366
 
    p->setRenderHint(QPainter::SmoothPixmapTransform, true);
367
 
    // draw our pixmap into the computed rectangle
368
 
    p->drawPixmap(frameRect.toRect(), picture);
369
 
    p->restore();
370
 
 
371
 
    // black frame
372
 
    if (m_frame) {
373
 
        p->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
374
 
        p->drawPath(framePath);
375
 
    } else if (m_roundCorners) {
376
 
        p->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
377
 
        p->drawPath(framePath);
378
 
    }
379
 
 
380
 
    // Paint status text on top of it all
381
 
    if (!m_mySlideShow->message().isEmpty()) {
382
 
        int dist = frameRect.width() / 10;
383
 
        QRect bgRect = frameRect.adjusted(dist-1, dist-1, -dist, -dist).toRect();
384
 
 
385
 
        // The text's background rounded rectangle
386
 
        QPainterPath bgPath = Plasma::PaintUtils::roundedRectangle(bgRect, bgRect.height()/15);
387
 
 
388
 
        QColor c = Plasma::Theme::defaultTheme()->color(Plasma::Theme::BackgroundColor);
389
 
        c.setAlphaF(.3);
390
 
        QColor outline = Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor);
391
 
        outline.setAlphaF(.5);
392
 
        p->setBrush(c);
393
 
        p->setPen(outline);
394
 
        p->setPen(QPen(outline, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
395
 
        p->drawPath(bgPath);
396
 
        QString message = m_mySlideShow->message();
397
 
 
398
 
        // Set the font and draw text
399
 
        p->setRenderHint(QPainter::Antialiasing);
400
 
        QFont textFont = Plasma::Theme::defaultTheme()->font(Plasma::Theme::DefaultFont);
401
 
        textFont.setPointSize(qMax(KGlobalSettings::smallestReadableFont().pointSize(), bgRect.height() / 6));
402
 
        p->setFont(textFont);
403
 
 
404
 
        QTextOption option;
405
 
        option.setAlignment(Qt::AlignCenter);
406
 
        option.setWrapMode(QTextOption::WordWrap);
407
 
 
408
 
        preparePainter(p, bgRect, textFont, message);
409
 
 
410
 
        p->setPen(QPen(Plasma::Theme::defaultTheme()->color(Plasma::Theme::TextColor), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
411
 
        p->drawText(bgRect, message, option);
412
 
    }
413
 
 
414
 
    p->end();
415
 
    delete p;
416
 
    update();
417
 
 
418
 
    if (m_doAutoUpdate && !m_autoUpdateTimer->isActive()) {
419
 
        kDebug() << "Autoupdate timer restarted:" << m_autoUpdateIntervall << "s";
420
 
        m_autoUpdateTimer->start(m_autoUpdateIntervall * 1000);
421
 
    }
422
 
}
423
 
 
424
 
QRect Frame::preparePainter(QPainter *p, const QRect &rect, const QFont &font, const QString &text)
425
 
{
426
 
    QRect tmpRect;
427
 
    QFont tmpFont = font;
428
 
    bool first = true;
429
 
 
430
 
    // Starting with the given font, decrease its size until it'll fit in the
431
 
    // given rect allowing wrapping where possible
432
 
    do {
433
 
        if (first) {
434
 
            first = false;
435
 
        } else  {
436
 
            tmpFont.setPointSize(qMax(KGlobalSettings::smallestReadableFont().pointSize(), tmpFont.pointSize() - 1));
437
 
        }
438
 
 
439
 
        const QFontMetrics fm(tmpFont);
440
 
        int flags = Qt::TextWordWrap;
441
 
 
442
 
        tmpRect = fm.boundingRect(rect, flags, text);
443
 
    } while (tmpFont.pointSize() > KGlobalSettings::smallestReadableFont().pointSize() &&
444
 
             (tmpRect.width() > rect.width() || tmpRect.height() > rect.height()));
445
 
    
446
 
    p->setFont(tmpFont);
447
 
    return tmpRect;
448
 
}
449
 
 
450
 
 
451
 
void Frame::nextPicture()
452
 
{
453
 
    m_mySlideShow->setUpdateInterval(0);
454
 
    m_mySlideShow->nextPicture();
455
 
    m_mySlideShow->setUpdateInterval(m_slideshowTime * 1000);
456
 
}
457
 
 
458
 
void Frame::previousPicture()
459
 
{
460
 
    m_mySlideShow->setUpdateInterval(0);
461
 
    m_mySlideShow->previousPicture();
462
 
    m_mySlideShow->setUpdateInterval(m_slideshowTime * 1000);
463
 
}
464
 
 
465
 
void Frame::addDir()
466
 
{
467
 
    QPointer<KDirSelectDialog> dialog = new KDirSelectDialog(KUrl(), true);
468
 
    if (dialog->exec()) {
469
 
        QString path = dialog->url().url();
470
 
        if (!m_slideShowPaths.contains(path)) {
471
 
            m_configDialog->imageUi.slideShowDirList->addItem(path);
472
 
        }
473
 
        updateButtons();
474
 
    }
475
 
    delete dialog;
476
 
}
477
 
 
478
 
void Frame::removeDir()
479
 
{
480
 
    int row = m_configDialog->imageUi.slideShowDirList->currentRow();
481
 
    if (row != -1) {
482
 
        m_configDialog->imageUi.slideShowDirList->takeItem(row);
483
 
        updateButtons();
484
 
    }
485
 
}
486
 
 
487
 
void Frame::updateButtons()
488
 
{
489
 
    int row = m_configDialog->imageUi.slideShowDirList->currentRow();
490
 
    m_configDialog->imageUi.removeDirButton->setEnabled(row != -1);
491
 
}
492
 
 
493
 
void Frame::createConfigurationInterface(KConfigDialog *parent)
494
 
{
495
 
    m_configDialog = new ConfigDialog(parent);
496
 
 
497
 
    KService::List services = KServiceTypeTrader::self()->query("PlasmaPoTD/Plugin");
498
 
    foreach(const KService::Ptr &service, services) {
499
 
        const QString service_name(service->name());
500
 
        const QVariant service_identifier(service->property("X-KDE-PlasmaPoTDProvider-Identifier", QVariant::String).toString());
501
 
        m_configDialog->imageUi.potdComboBox->insertItem(m_configDialog->imageUi.potdComboBox->count(), service_name, service_identifier);
502
 
    }
503
 
 
504
 
    QStandardItemModel* model = static_cast<QStandardItemModel*>(m_configDialog->imageUi.pictureComboBox->model());
505
 
    QStandardItem* item = model->item(2);
506
 
 
507
 
    if (item) {
508
 
        if (services.isEmpty())
509
 
            item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
510
 
        else
511
 
            item->setFlags(item->flags() | Qt::ItemIsEnabled);
512
 
    }
513
 
 
514
 
    parent->addPage(m_configDialog->imageSettings, i18n("Image"), icon());
515
 
    parent->addPage(m_configDialog->appearanceSettings, i18n("Appearance"), "preferences-desktop-theme");
516
 
    parent->setDefaultButton(KDialog::Ok);
517
 
    parent->showButtonSeparator(true);
518
 
    connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
519
 
    connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
520
 
 
521
 
    connect(m_configDialog->imageUi.removeDirButton, SIGNAL(clicked()), this, SLOT(removeDir()));
522
 
    connect(m_configDialog->imageUi.addDirButton, SIGNAL(clicked()), this, SLOT(addDir()));
523
 
    connect(m_configDialog->imageUi.slideShowDirList, SIGNAL(currentRowChanged(int)), this, SLOT(updateButtons()));
524
 
 
525
 
    m_configDialog->setRoundCorners(m_roundCorners);
526
 
    m_configDialog->setShadow(m_shadow);
527
 
    m_configDialog->setShowFrame(m_frame);
528
 
    m_configDialog->setFrameColor(m_frameColor);
529
 
 
530
 
    if (m_slideShow) {
531
 
        m_configDialog->imageUi.pictureComboBox->setCurrentIndex(1);
532
 
    } else if (m_potd) {
533
 
        m_configDialog->imageUi.pictureComboBox->setCurrentIndex(2);
534
 
    } else {
535
 
        m_configDialog->imageUi.pictureComboBox->setCurrentIndex(0);
536
 
    }
537
 
 
538
 
    m_configDialog->imageUi.randomCheckBox->setCheckState(m_random ? Qt::Checked : Qt::Unchecked);
539
 
    m_configDialog->imageUi.recursiveCheckBox->setCheckState(m_recursiveSlideShow ? Qt::Checked : Qt::Unchecked);
540
 
 
541
 
    if (!m_potdProvider.isEmpty())
542
 
        m_configDialog->imageUi.potdComboBox->setCurrentIndex(m_configDialog->imageUi.potdComboBox->findData(m_potdProvider));
543
 
    else 
544
 
        m_configDialog->imageUi.potdComboBox->setCurrentIndex(0);
545
 
    
546
 
    m_configDialog->setCurrentUrl(m_currentUrl);
547
 
    m_configDialog->imageUi.slideShowDirList->clear();
548
 
    m_configDialog->imageUi.slideShowDirList->addItems(m_slideShowPaths);
549
 
    m_configDialog->imageUi.removeDirButton->setEnabled(!m_slideShowPaths.isEmpty());
550
 
    m_configDialog->imageUi.slideShowDelay->setTime(QTime(m_slideshowTime / 3600, (m_slideshowTime / 60) % 60, m_slideshowTime % 60));
551
 
    m_configDialog->previewPicture(m_mySlideShow->image());
552
 
    m_configDialog->imageUi.autoUpdateTime->setTime(QTime(m_autoUpdateIntervall / 3600, (m_autoUpdateIntervall / 60) % 60));
553
 
}
554
 
 
555
 
void Frame::configAccepted()
556
 
{
557
 
    KConfigGroup cg = config();
558
 
    // Appearance
559
 
    m_roundCorners = m_configDialog->roundCorners();
560
 
    cg.writeEntry("roundCorners", m_roundCorners);
561
 
    m_shadow = m_configDialog->shadow();
562
 
    cg.writeEntry("shadow", m_shadow);
563
 
    m_frame = m_configDialog->showFrame();
564
 
    cg.writeEntry("frame", m_frame);
565
 
    m_frameColor = m_configDialog->frameColor();
566
 
    cg.writeEntry("frameColor", m_frameColor);
567
 
 
568
 
    bool wasPotd = m_potd;
569
 
 
570
 
    if (m_configDialog->imageUi.pictureComboBox->currentIndex() == 1) {
571
 
        m_slideShow = true;
572
 
        m_potd = false;
573
 
    }  else if (m_configDialog->imageUi.pictureComboBox->currentIndex() == 2)   {
574
 
        m_slideShow = false;
575
 
        m_potd = true;
576
 
    }  else {
577
 
        m_slideShow = false;
578
 
        m_potd = false;
579
 
    }
580
 
 
581
 
    m_random = m_configDialog->random();
582
 
    cg.writeEntry("random", m_random);
583
 
    m_currentUrl = m_configDialog->currentUrl();
584
 
    setAssociatedApplicationUrls(m_currentUrl);
585
 
    cg.writeEntry("url", m_currentUrl);
586
 
    cg.writeEntry("slideshow", m_slideShow);
587
 
    m_recursiveSlideShow = m_configDialog->imageUi.recursiveCheckBox->checkState() == Qt::Checked ? true : false;
588
 
    cg.writeEntry("recursive slideshow", m_recursiveSlideShow);
589
 
    m_slideShowPaths.clear();
590
 
    QStringList dirs;
591
 
    for (int i = 0; i < m_configDialog->imageUi.slideShowDirList->count(); i++) {
592
 
        m_slideShowPaths << m_configDialog->imageUi.slideShowDirList->item(i)->text();
593
 
    }
594
 
    cg.writeEntry("slideshow paths", m_slideShowPaths);
595
 
 
596
 
    QTime timerTime = m_configDialog->imageUi.slideShowDelay->time();
597
 
    m_slideshowTime = timerTime.second() + timerTime.minute() * 60 + timerTime.hour() * 3600;
598
 
    cg.writeEntry("slideshow time", m_slideshowTime);
599
 
 
600
 
    m_autoUpdateTimer->stop();
601
 
 
602
 
    QTime AutoUpdateTimer = m_configDialog->imageUi.autoUpdateTime->time();
603
 
    m_autoUpdateIntervall = AutoUpdateTimer.minute() * 60 + AutoUpdateTimer.hour() * 3600;
604
 
    cg.writeEntry("autoupdate time", m_autoUpdateIntervall);
605
 
 
606
 
    QString potdProvider = m_configDialog->imageUi.potdComboBox->itemData(m_configDialog->imageUi.potdComboBox->currentIndex()).toString();
607
 
 
608
 
    if ((wasPotd && !m_potd) || (m_potd && potdProvider != m_potdProvider)) {
609
 
        // if we go from potd to no potd, or if the provider changes, then we first want to
610
 
        // stop the potd engine
611
 
        stopPotd();
612
 
    }
613
 
 
614
 
    m_potdProvider = potdProvider;
615
 
    cg.writeEntry("potdProvider", m_potdProvider);
616
 
    cg.writeEntry("potd", m_potd);
617
 
 
618
 
    initSlideShow();
619
 
 
620
 
    emit configNeedsSaving();
621
 
}
622
 
 
623
 
void Frame::stopPotd()
624
 
{
625
 
    Plasma::DataEngine *engine = dataEngine("potd");
626
 
    const QString identifier = m_potdProvider + ':' + m_currentDay.toString(Qt::ISODate);
627
 
    engine->disconnectSource(identifier, m_mySlideShow);
628
 
    m_autoUpdateTimer->stop();
629
 
}
630
 
 
631
 
void Frame::initSlideShow()
632
 
{
633
 
    m_mySlideShow->setUpdateInterval(0);
634
 
    m_doAutoUpdate = false;
635
 
 
636
 
    if (m_slideShow) {
637
 
        m_mySlideShow->setRandom(m_random);
638
 
        m_mySlideShow->setDirs(m_slideShowPaths, m_recursiveSlideShow);
639
 
        m_mySlideShow->setUpdateInterval(m_slideshowTime * 1000);
640
 
    } else if (m_potd) {
641
 
        m_dateChangedTimer = new QTimer( this );//change picture at midnight
642
 
        connect( m_dateChangedTimer, SIGNAL( timeout() ), this, SLOT( checkDayChanged() ) );
643
 
        m_dateChangedTimer->start( 60 * 60 * 1000 ); // every hour
644
 
        Plasma::DataEngine *engine = dataEngine("potd");
645
 
        const QString identifier = m_potdProvider + ':' + m_currentDay.toString(Qt::ISODate);
646
 
        engine->connectSource(identifier, m_mySlideShow);
647
 
    } else { //no slideshow so no random stuff
648
 
        m_mySlideShow->setRandom(false);
649
 
        m_mySlideShow->setImage(m_currentUrl.url());
650
 
 
651
 
        if (m_autoUpdateIntervall > 0) {
652
 
            m_doAutoUpdate = true;
653
 
        }
654
 
    }
655
 
    
656
 
    scalePictureAndUpdate();
657
 
}
658
 
 
659
 
void Frame::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
660
 
{
661
 
    // kDebug() << event->mimeData()->formats();
662
 
    if (event->mimeData()->hasUrls()) {
663
 
        event->acceptProposedAction();
664
 
    } else {
665
 
        event->ignore();
666
 
    }
667
 
}
668
 
 
669
 
void Frame::dropEvent(QGraphicsSceneDragDropEvent *event)
670
 
{
671
 
    if (m_slideFrame) {
672
 
        m_slideFrame->hide();
673
 
    }
674
 
    KUrl droppedUrl = (KUrl::List::fromMimeData(event->mimeData())).at(0);
675
 
    kDebug() << "dropped URL" << droppedUrl.url();
676
 
    if (droppedUrl.protocol() == "desktop") {
677
 
        KUrl tmpUrl = KGlobalSettings::desktopPath() + droppedUrl.path();
678
 
        droppedUrl = tmpUrl;
679
 
    }
680
 
    // If the url is a local directory start slideshowmode
681
 
    if (droppedUrl.isLocalFile() && QFileInfo(droppedUrl.path()).isDir()) {
682
 
        m_slideShowPaths.clear();
683
 
        m_slideShowPaths.append(droppedUrl.path());
684
 
        m_slideShow = true;
685
 
    } else {
686
 
        kDebug() << "Remote URL" << droppedUrl.url();
687
 
        m_currentUrl = droppedUrl;
688
 
        setAssociatedApplicationUrls(m_currentUrl);
689
 
        m_slideShow = false;
690
 
    }
691
 
 
692
 
    stopPotd();
693
 
    m_potd = false;
694
 
    initSlideShow();
695
 
 
696
 
    KConfigGroup cg = config();
697
 
    cg.writeEntry("url", m_currentUrl);
698
 
    cg.writeEntry("slideshow", m_slideShow);
699
 
    cg.writeEntry("slideshow paths", m_slideShowPaths);
700
 
    emit configNeedsSaving();
701
 
}
702
 
 
703
 
void Frame::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
704
 
{
705
 
    checkSlideFrame();
706
 
    if (m_slideShow) {
707
 
        m_slideFrame->show();
708
 
    }
709
 
    Applet::hoverEnterEvent(event);
710
 
}
711
 
 
712
 
void Frame::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
713
 
{
714
 
    if (m_slideShow) {
715
 
        checkSlideFrame();
716
 
        m_slideFrame->hide();
717
 
    }
718
 
    Applet::hoverLeaveEvent( event );
719
 
}
720
 
 
721
 
void Frame::checkSlideFrame()
722
 
{
723
 
    if (m_slideFrame) {
724
 
        m_slideFrame->hide();
725
 
        return;
726
 
    }
727
 
    m_slideFrame = new Plasma::Frame( this );
728
 
    m_slideFrame->setZValue( 10 );
729
 
 
730
 
    m_backButton = new Plasma::ToolButton(m_slideFrame);
731
 
    m_backButton->setImage("widgets/arrows", "left-arrow");
732
 
    m_backButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
733
 
    m_backButton->setMaximumSize(IconSize(KIconLoader::MainToolbar), IconSize(KIconLoader::MainToolbar));
734
 
    connect(m_backButton, SIGNAL(clicked()), this , SLOT(previousPicture()));
735
 
 
736
 
    m_nextButton = new Plasma::ToolButton(m_slideFrame);
737
 
    m_nextButton->setImage("widgets/arrows", "right-arrow");
738
 
    m_nextButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
739
 
    m_nextButton->setMaximumSize(IconSize(KIconLoader::MainToolbar), IconSize(KIconLoader::MainToolbar));
740
 
    connect(m_nextButton, SIGNAL(clicked()), this , SLOT(nextPicture()));
741
 
 
742
 
    QGraphicsLinearLayout *buttonsLayout = new QGraphicsLinearLayout();
743
 
    buttonsLayout->addItem(m_backButton);
744
 
    buttonsLayout->addItem(m_nextButton);
745
 
    m_slideFrame->setLayout(buttonsLayout);
746
 
    buttonsLayout->activate();
747
 
 
748
 
    m_slideFrame->setFrameShadow( Plasma::Frame::Raised );
749
 
    m_slideFrame->hide();
750
 
 
751
 
    constraintsEvent(Plasma::SizeConstraint);
752
 
}
753
 
 
754
 
void Frame::paintInterface(QPainter *p, const QStyleOptionGraphicsItem *option, const QRect &rect)
755
 
{
756
 
    Q_UNUSED(option)
757
 
    if (m_slideShow) {
758
 
        // temporarily suspend the slideshow to allow time for loading the image
759
 
        m_mySlideShow->setUpdateInterval(0);
760
 
    }
761
 
 
762
 
    p->drawPixmap(rect, m_pixmap);
763
 
 
764
 
    if (m_slideShow) {
765
 
        // unsuspend the slideshow to allow time for loading the image
766
 
        m_mySlideShow->setUpdateInterval(m_slideshowTime * 1000);
767
 
    }
768
 
}
769
 
 
770
 
void Frame::delayedUpdateSize()
771
 
{
772
 
    QSizeF sizeHint = contentSizeHint();
773
 
    if (sizeHint != geometry().size()) {
774
 
        resize(sizeHint);
775
 
        emit appletTransformedItself();
776
 
    }
777
 
}
778
 
 
779
 
void Frame::checkDayChanged()
780
 
{
781
 
    if ( ( m_currentDay != QDate::currentDate() ) ) {
782
 
        reloadImage();
783
 
        //keep after reloadImage()
784
 
        m_currentDay = QDate::currentDate();
785
 
    }
786
 
}
787
 
 
788
 
void Frame::reloadImage()
789
 
{
790
 
    if (m_potd) {
791
 
        Plasma::DataEngine *engine = dataEngine("potd");
792
 
        //disconnect yesterday's source
793
 
        QString identifier = m_potdProvider + ':' + m_currentDay.toString(Qt::ISODate);
794
 
        engine->disconnectSource(identifier, m_mySlideShow);
795
 
        //connect today's source
796
 
        identifier = m_potdProvider + ':' + QDate::currentDate().toString(Qt::ISODate); 
797
 
        engine->connectSource(identifier, m_mySlideShow);
798
 
    } else {
799
 
        m_mySlideShow->updateImage(m_currentUrl.url());
800
 
    }
801
 
}
802
 
 
803
 
#include "frame.moc"