queuelist.cpp 27 KB
Newer Older
1
2
3
4
5
6
7
8
/* ============================================================
 *
 * This file is a part of digiKam project
 * http://www.digikam.org
 *
 * Date        : 2008-11-21
 * Description : Batch Queue Manager items list.
 *
Gilles Caulier's avatar
Gilles Caulier committed
9
 * Copyright (C) 2008-2012 by Gilles Caulier <caulier dot gilles at gmail dot com>
10
 * Copyright (C)      2014 by Mohamed Anwer <mohammed dot ahmed dot anwer at gmail dot com>
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU 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.
 *
 * ============================================================ */

#include "queuelist.moc"

27
// Qt includes
28
29
30
31

#include <QDragEnterEvent>
#include <QFileInfo>
#include <QHeaderView>
32
#include <QPainter>
33
#include <QTimer>
34
#include <QUrl>
35

36
// KDE includes
37

38
#include <kpixmapsequence.h>
39
40
#include <kaction.h>
#include <kactioncollection.h>
41
42
43
#include <kiconloader.h>
#include <klocale.h>
#include <kmenu.h>
44
#include <kurl.h>
45
#include <kdebug.h>
46

47
// Local includes
48
49

#include "albumdb.h"
50
51
#include "databasechangesets.h"
#include "databasewatch.h"
52
#include "ddragobjects.h"
Andi Clemens's avatar
Andi Clemens committed
53
#include "defaultrenameparser.h"
54
#include "queuemgrwindow.h"
Michael Georg Hansen's avatar
Michael Georg Hansen committed
55
#include "queuesettings.h"
56
#include "queuetooltip.h"
57
58
#include "thumbnailloadthread.h"
#include "thumbnailsize.h"
59
#include "workflowmanager.h"
60
61
62
63

namespace Digikam
{

Gilles Caulier's avatar
Gilles Caulier committed
64
class QueueListViewItem::Private
65
66
67
68
{

public:

Gilles Caulier's avatar
Gilles Caulier committed
69
    Private() :
70
        isBusy(false),
71
        done(false),
72
73
74
        hasThumb(false),
        progressIndex(0),
        view(0)
75
76
77
    {
    }

78
    bool           isBusy;
79
80
    bool           done;
    bool           hasThumb;
81

82
    int            progressIndex;
83

84
    QString        destFileName;
85

86
87
88
89
90
    QPixmap        preview;

    QueueListView* view;

    ImageInfo      info;
91
92
};

93
QueueListViewItem::QueueListViewItem(QueueListView* const view, const ImageInfo& info)
Gilles Caulier's avatar
Gilles Caulier committed
94
    : QTreeWidgetItem(view), d(new Private)
95
{
96
    d->view = view;
97
    setThumb(SmallIcon("image-x-generic", KIconLoader::SizeLarge, KIconLoader::DisabledState), false);
98
99
100
101
102
103
104
105
    setInfo(info);
}

QueueListViewItem::~QueueListViewItem()
{
    delete d;
}

Gilles Caulier's avatar
Gilles Caulier committed
106
bool QueueListViewItem::hasValidThumbnail() const
107
{
Gilles Caulier's avatar
Gilles Caulier committed
108
    return d->hasThumb;
109
110
}

111
112
void QueueListViewItem::setInfo(const ImageInfo& info)
{
113
    d->info = info;
114
115
116
117
118
119
120
121
    setText(1, d->info.name());
}

ImageInfo QueueListViewItem::info() const
{
    return d->info;
}

122
123
124
125
126
127
128
129
130
131
132
133
134
void QueueListViewItem::setPixmap(const QPixmap& pix)
{
    QIcon icon = QIcon(pix);
    //  We make sure the preview icon stays the same regardless of the role
    icon.addPixmap(pix, QIcon::Selected, QIcon::On);
    icon.addPixmap(pix, QIcon::Selected, QIcon::Off);
    icon.addPixmap(pix, QIcon::Active,   QIcon::On);
    icon.addPixmap(pix, QIcon::Active,   QIcon::Off);
    icon.addPixmap(pix, QIcon::Normal,   QIcon::On);
    icon.addPixmap(pix, QIcon::Normal,   QIcon::Off);
    setIcon(0, icon);
}

Gilles Caulier's avatar
Gilles Caulier committed
135
void QueueListViewItem::setThumb(const QPixmap& pix, bool hasThumb)
136
{
137
    QSize iSize = treeWidget()->iconSize();
Andi Clemens's avatar
Andi Clemens committed
138
    QPixmap pixmap(iSize.width() + 2, iSize.height() + 2);
Gilles Caulier's avatar
polish    
Gilles Caulier committed
139
    pixmap.fill(Qt::transparent);
140
    QPainter p(&pixmap);
Andi Clemens's avatar
Andi Clemens committed
141
    p.drawPixmap((pixmap.width() / 2) - (pix.width() / 2), (pixmap.height() / 2) - (pix.height() / 2), pix);
Gilles Caulier's avatar
Gilles Caulier committed
142
    d->preview  = pixmap;
143
    setPixmap(d->preview);
Gilles Caulier's avatar
Gilles Caulier committed
144
    d->hasThumb = hasThumb;
145
146
}

147
void QueueListViewItem::animProgress()
148
{
149
150
151
152
153
154
155
156
    QPixmap icon(d->view->progressPixmapForIndex(d->progressIndex));
    d->progressIndex++;

    if (d->view->progressPixmapForIndex(d->progressIndex).isNull())
    {
        d->progressIndex = 0;
    }

157
158
159
160
161
    QPixmap preview = d->preview;
    QPixmap mask(preview.size());
    mask.fill(QColor(128, 128, 128, 192));
    QPainter p(&preview);
    p.drawPixmap(0, 0, mask);
Andi Clemens's avatar
Andi Clemens committed
162
    p.drawPixmap((preview.width() / 2) - (icon.width() / 2), (preview.height() / 2) - (icon.height() / 2), icon);
163
    setPixmap(preview);
164
165
166
167
}

void QueueListViewItem::setCanceled()
{
168
    setPixmap(d->preview);
169
    setIcon(1, SmallIcon("dialog-cancel"));
170
    d->done          = false;
171
    d->isBusy        = false;
172
    d->progressIndex = 0;
173
174
}

175
void QueueListViewItem::setFailed()
176
{
177
    setPixmap(d->preview);
178
    setIcon(1, SmallIcon("dialog-error"));
179
    d->done          = false;
180
    d->isBusy        = false;
181
    d->progressIndex = 0;
182
183
}

Gilles Caulier's avatar
Gilles Caulier committed
184
void QueueListViewItem::setDone()
185
{
186
    setPixmap(d->preview);
187
    setIcon(1, SmallIcon("dialog-ok"));
188
    d->done          = true;
189
    d->isBusy        = false;
190
    d->progressIndex = 0;
191
192
}

Gilles Caulier's avatar
Gilles Caulier committed
193
bool QueueListViewItem::isDone() const
194
195
196
197
{
    return d->done;
}

198
199
void QueueListViewItem::reset()
{
200
    setPixmap(d->preview);
201
    setIcon(1, QIcon());
202
    d->done          = false;
203
    d->isBusy        = false;
204
    d->progressIndex = 0;
205
206
}

207
208
209
210
211
212
213
214
215
216
void QueueListViewItem::setBusy()
{
    d->isBusy = true;
}

bool QueueListViewItem::isBusy() const
{
    return d->isBusy;
}

217
218
219
220
221
222
223
224
225
226
227
void QueueListViewItem::setDestFileName(const QString& str)
{
    d->destFileName = str;
    setText(2, d->destFileName);
}

QString QueueListViewItem::destFileName() const
{
    return d->destFileName;
}

228
229
230
231
232
233
234
235
236
237
238
239
QString QueueListViewItem::destBaseName() const
{
    QFileInfo fi(d->destFileName);
    return fi.completeBaseName();
}

QString QueueListViewItem::destSuffix() const
{
    QFileInfo fi(d->destFileName);
    return fi.suffix();
}

240
241
// ---------------------------------------------------------------------------

Gilles Caulier's avatar
Gilles Caulier committed
242
class QueueListView::Private
243
244
245
246
247
248
249
250
251
252
253
254
255
{

public:

    enum RemoveItemsType
    {
        ItemsSelected = 0,
        ItemsDone,
        ItemsAll
    };

public:

Gilles Caulier's avatar
Gilles Caulier committed
256
    Private()
257
        : iconSize(64)
258
    {
259
260
        showTips        = false;
        toolTipTimer    = 0;
261
        progressTimer   = 0;
262
263
        toolTip         = 0;
        toolTipItem     = 0;
264
        thumbLoadThread = ThumbnailLoadThread::defaultThread();
265
        progressPix     = KPixmapSequence("process-working", KIconLoader::SizeSmallMedium);
266
267
    }

268
269
    bool                 showTips;

270
271
    const int            iconSize;

Andi Clemens's avatar
polish    
Andi Clemens committed
272
    QTimer*              toolTipTimer;
273
    QTimer*              progressTimer;
274

Andi Clemens's avatar
polish    
Andi Clemens committed
275
    ThumbnailLoadThread* thumbLoadThread;
276
277

    QueueSettings        settings;
278
279

    AssignedBatchTools   toolsList;
280

Andi Clemens's avatar
polish    
Andi Clemens committed
281
    QueueToolTip*        toolTip;
282

Andi Clemens's avatar
polish    
Andi Clemens committed
283
    QueueListViewItem*   toolTipItem;
284
285

    KPixmapSequence      progressPix;
286
287
};

Gilles Caulier's avatar
Gilles Caulier committed
288
289
QueueListView::QueueListView(QWidget* const parent)
    : QTreeWidget(parent), d(new Private)
290
{
291
    setIconSize(QSize(d->iconSize, d->iconSize));
292
293
294
295
296
297
    setSelectionMode(QAbstractItemView::ExtendedSelection);
    setWhatsThis(i18n("This is the list of images to batch process."));

    setAcceptDrops(true);
    viewport()->setAcceptDrops(true);
    setDropIndicatorShown(true);
298
    setDragEnabled(true);
299
    viewport()->setMouseTracking(true);
300

301
    setSortingEnabled(true);
302
303
304
    setAllColumnsShowFocus(true);
    setRootIsDecorated(false);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
305
    setColumnCount(3);
306
    setContextMenuPolicy(Qt::CustomContextMenu);
307
308
309
310

    QStringList titles;
    titles.append(i18n("Thumbnail"));
    titles.append(i18n("File Name"));
311
    titles.append(i18n("Target"));
312
    setHeaderLabels(titles);
313
314
315
    header()->setResizeMode(0, QHeaderView::ResizeToContents);
    header()->setResizeMode(1, QHeaderView::Stretch);
    header()->setResizeMode(2, QHeaderView::Stretch);
316

317
318
319
    d->toolTip       = new QueueToolTip(this);
    d->toolTipTimer  = new QTimer(this);
    d->progressTimer = new QTimer(this);
320
321
322

    // -----------------------------------------------------------

Laurent Montel's avatar
Laurent Montel committed
323
324
    connect(DatabaseAccess::databaseWatch(), SIGNAL(collectionImageChange(CollectionImageChangeset)),
            this, SLOT(slotCollectionImageChange(CollectionImageChangeset)),
325
326
            Qt::QueuedConnection);

Laurent Montel's avatar
Laurent Montel committed
327
328
    connect(d->thumbLoadThread, SIGNAL(signalThumbnailLoaded(LoadingDescription,QPixmap)),
            this, SLOT(slotThumbnailLoaded(LoadingDescription,QPixmap)));
329

Laurent Montel's avatar
Laurent Montel committed
330
    connect(this, SIGNAL(customContextMenuRequested(QPoint)),
331
            this, SLOT(slotContextMenu()));
332
333
334

    connect(d->toolTipTimer, SIGNAL(timeout()),
            this, SLOT(slotToolTip()));
335
336
337

    connect(d->progressTimer, SIGNAL(timeout()),
            this, SLOT(slotProgressTimerDone()));
338
339
340
341
}

QueueListView::~QueueListView()
{
342
    delete d->toolTip;
343
344
345
    delete d;
}

346
347
348
349
350
351
352
353
QPixmap QueueListView::progressPixmapForIndex(int index) const
{
    if (index >= 0 && index < d->progressPix.frameCount())
        return (d->progressPix.frameAt(index));

    return QPixmap();
}

354
355
Qt::DropActions QueueListView::supportedDropActions() const
{
356
357
358
359
360
361
362
363
    return Qt::CopyAction | Qt::MoveAction;
}

QMimeData* QueueListView::mimeData(const QList<QTreeWidgetItem*> items) const
{
    KUrl::List urls;
    KUrl::List kioURLs;
    QList<int> albumIDs;
364
    QList<qlonglong> imageIDs;
365

Gilles Caulier's avatar
Gilles Caulier committed
366
    foreach(QTreeWidgetItem* const itm, items)
367
    {
Gilles Caulier's avatar
Gilles Caulier committed
368
        QueueListViewItem* const vitem = dynamic_cast<QueueListViewItem*>(itm);
369

370
371
372
373
374
375
376
377
378
        if (vitem)
        {
            urls.append(vitem->info().fileUrl());
            kioURLs.append(vitem->info().databaseUrl());
            albumIDs.append(vitem->info().albumId());
            imageIDs.append(vitem->info().id());
        }
    }

Gilles Caulier's avatar
Gilles Caulier committed
379
    DItemDrag* const mimeData = new DItemDrag(urls, kioURLs, albumIDs, imageIDs);
380
381
382
383
384
385
    return mimeData;
}

void QueueListView::startDrag(Qt::DropActions /*supportedActions*/)
{
    QList<QTreeWidgetItem*> items = selectedItems();
386

387
    if (items.isEmpty())
388
    {
389
        return;
390
    }
391
392
393
394
395

    QPixmap icon(DesktopIcon("image-jp2", 48));
    int w = icon.width();
    int h = icon.height();

Andi Clemens's avatar
Andi Clemens committed
396
    QPixmap pix(w + 4, h + 4);
397
398
399
    QString text(QString::number(items.count()));

    QPainter p(&pix);
Andi Clemens's avatar
Andi Clemens committed
400
    p.fillRect(0, 0, pix.width() - 1, pix.height() - 1, QColor(Qt::white));
401
    p.setPen(QPen(Qt::black, 1));
Andi Clemens's avatar
Andi Clemens committed
402
    p.drawRect(0, 0, pix.width() - 1, pix.height() - 1);
403
    p.drawPixmap(2, 2, icon);
Andi Clemens's avatar
Andi Clemens committed
404
    QRect r = p.boundingRect(2, 2, w, h, Qt::AlignLeft | Qt::AlignTop, text);
405
406
407
408
409
410
411
412
413
414
    r.setWidth(qMax(r.width(), r.height()));
    r.setHeight(qMax(r.width(), r.height()));
    p.fillRect(r, QColor(0, 80, 0));
    p.setPen(Qt::white);
    QFont f(font());
    f.setBold(true);
    p.setFont(f);
    p.drawText(r, Qt::AlignCenter, text);
    p.end();

415
    QDrag* drag = new QDrag(this);
416
417
418
    drag->setMimeData(mimeData(items));
    drag->setPixmap(pix);
    drag->exec();
419
420
}

421
void QueueListView::dragEnterEvent(QDragEnterEvent* e)
422
{
423
    QTreeWidget::dragEnterEvent(e);
424
425
426
    e->accept();
}

427
void QueueListView::dragMoveEvent(QDragMoveEvent* e)
428
{
Gilles Caulier's avatar
Gilles Caulier committed
429
430
    int              albumID;
    QList<int>       albumIDs;
431
    QList<qlonglong> imageIDs;
Gilles Caulier's avatar
Gilles Caulier committed
432
433
    KUrl::List       urls;
    KUrl::List       kioURLs;
434
435

    if (DItemDrag::decode(e->mimeData(), urls, kioURLs, albumIDs, imageIDs) ||
Gilles Caulier's avatar
Gilles Caulier committed
436
        DAlbumDrag::decode(e->mimeData(), urls, albumID)                    ||
437
        DTagListDrag::canDecode(e->mimeData()))
438
    {
439
440
441
442
        if (DItemDrag::decode(e->mimeData(), urls, kioURLs, albumIDs, imageIDs))
        {
            ImageInfoList imageInfoList;

443
            for (QList<qlonglong>::const_iterator it = imageIDs.constBegin();
444
                 it != imageIDs.constEnd(); ++it)
445
446
            {
                ImageInfo info(*it);
447

448
                if (!findItemByInfo(info))
449
                {
450
                    imageInfoList.append(info);
451
                }
452
453
454
455
456
457
458
459
460
            }

            if (!imageInfoList.isEmpty())
            {
                QTreeWidget::dragMoveEvent(e);
                e->accept();
                return;
            }
        }
461
    }
462
463
464
465
466
467
    else if (e->mimeData()->formats().contains("digikam/workflow"))
    {
        QTreeWidget::dragMoveEvent(e);
        e->accept();
        return;
    }
468

469
470
471
    e->ignore();
}

472
void QueueListView::dropEvent(QDropEvent* e)
473
{
Gilles Caulier's avatar
Gilles Caulier committed
474
475
    int              albumID;
    QList<int>       albumIDs;
476
    QList<qlonglong> imageIDs;
Gilles Caulier's avatar
Gilles Caulier committed
477
478
    KUrl::List       urls;
    KUrl::List       kioURLs;
479
480
481
482
483

    if (DItemDrag::decode(e->mimeData(), urls, kioURLs, albumIDs, imageIDs))
    {
        ImageInfoList imageInfoList;

484
        for (QList<qlonglong>::const_iterator it = imageIDs.constBegin();
485
486
487
             it != imageIDs.constEnd(); ++it)
        {
            ImageInfo info(*it);
488

489
490
491
492
493
494
            if (!findItemByInfo(info))
            {
                imageInfoList.append(info);
            }
        }

495
496
        if (!imageInfoList.isEmpty())
        {
497
            slotAddItems(imageInfoList);
498
            e->acceptProposedAction();
499

Gilles Caulier's avatar
Gilles Caulier committed
500
            QueueListView* const vitem = dynamic_cast<QueueListView*>(e->source());
501

502
503
504
            if (vitem && vitem != this)
            {
                foreach(ImageInfo info, imageInfoList)
505
                {
506
                    vitem->removeItemByInfo(info);
507
                }
508
            }
509
        }
510
511
512
513
514
515
516
517
518
519
    }
    else if (DAlbumDrag::decode(e->mimeData(), urls, albumID))
    {
        QList<qlonglong> itemIDs = DatabaseAccess().db()->getItemIDsInAlbum(albumID);
        ImageInfoList imageInfoList;

        for (QList<qlonglong>::const_iterator it = itemIDs.constBegin();
             it != itemIDs.constEnd(); ++it)
        {
            ImageInfo info(*it);
520

521
522
523
524
525
526
            if (!findItemByInfo(info))
            {
                imageInfoList.append(info);
            }
        }

527
528
        if (!imageInfoList.isEmpty())
        {
529
            slotAddItems(imageInfoList);
530
531
            e->acceptProposedAction();
        }
532
    }
533
    else if (DTagListDrag::canDecode(e->mimeData()))
534
    {
535
        QList<int> tagIDs;
536

537
        if (!DTagListDrag::decode(e->mimeData(), tagIDs))
538
        {
539
            return;
540
        }
541

542
        QList<qlonglong> itemIDs = DatabaseAccess().db()->getItemIDsInTag(tagIDs.first(), true);
543
544
545
546
547
548
        ImageInfoList imageInfoList;

        for (QList<qlonglong>::const_iterator it = itemIDs.constBegin();
             it != itemIDs.constEnd(); ++it)
        {
            ImageInfo info(*it);
549

550
551
552
553
554
555
            if (!findItemByInfo(info))
            {
                imageInfoList.append(info);
            }
        }

556
557
        if (!imageInfoList.isEmpty())
        {
558
            slotAddItems(imageInfoList);
559
560
            e->acceptProposedAction();
        }
561
    }
562
563
564
565
566
567
568
569
570
571
572
573
574
575
    else if (e->mimeData()->formats().contains("digikam/workflow"))
    {
        QByteArray ba = e->mimeData()->data("digikam/workflow");

        if (ba.size())
        {
            QDataStream ds(ba);
            QString     title;
            ds >> title;
            QueueMgrWindow::queueManagerWindow()->slotAssignQueueSettings(title);

            e->acceptProposedAction();
        }
    }
576
577
578
579
580
    else
    {
        e->ignore();
    }

581
    emit signalQueueContentsChanged();
582
583
}

584
585
586
void QueueListView::setEnableToolTips(bool val)
{
    d->showTips = val;
587

588
    if (!val)
589
    {
590
        hideToolTip();
591
    }
592
593
594
595
596
597
598
599
600
}

void QueueListView::hideToolTip()
{
    d->toolTipItem = 0;
    d->toolTipTimer->stop();
    slotToolTip();
}

Gilles Caulier's avatar
Gilles Caulier committed
601
bool QueueListView::acceptToolTip(const QPoint& pos) const
602
603
{
    if (columnAt(pos.x()) == 0)
604
    {
605
        return true;
606
    }
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

    return false;
}

void QueueListView::slotToolTip()
{
    d->toolTip->setQueueItem(d->toolTipItem);
}

void QueueListView::mouseMoveEvent(QMouseEvent* e)
{
    if (e->buttons() == Qt::NoButton)
    {
        QueueListViewItem* item = dynamic_cast<QueueListViewItem*>(itemAt(e->pos()));

Andi Clemens's avatar
polish    
Andi Clemens committed
622
        if (d->showTips)
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
        {
            if (!isActiveWindow())
            {
                hideToolTip();
                return;
            }

            if (item != d->toolTipItem)
            {
                hideToolTip();

                if (acceptToolTip(e->pos()))
                {
                    d->toolTipItem = item;
                    d->toolTipTimer->setSingleShot(true);
                    d->toolTipTimer->start(500);
                }
            }

Andi Clemens's avatar
polish    
Andi Clemens committed
642
            if (item == d->toolTipItem && !acceptToolTip(e->pos()))
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
            {
                hideToolTip();
            }
        }

        return;
    }

    hideToolTip();
    QTreeWidget::mouseMoveEvent(e);
}

void QueueListView::wheelEvent(QWheelEvent* e)
{
    hideToolTip();
    QTreeWidget::wheelEvent(e);
}

void QueueListView::keyPressEvent(QKeyEvent* e)
{
    hideToolTip();
    QTreeWidget::keyPressEvent(e);
}

void QueueListView::focusOutEvent(QFocusEvent* e)
{
    hideToolTip();
    QTreeWidget::focusOutEvent(e);
}

void QueueListView::leaveEvent(QEvent* e)
{
    hideToolTip();
    QTreeWidget::leaveEvent(e);
}

679
void QueueListView::slotAddItems(const ImageInfoList& list)
680
{
Andi Clemens's avatar
Andi Clemens committed
681
    if (list.count() == 0)
682
683
684
    {
        return;
    }
685

Andi Clemens's avatar
Andi Clemens committed
686
    for (ImageInfoList::ConstIterator it = list.begin(); it != list.end(); ++it)
687
688
689
690
691
692
    {
        ImageInfo info = *it;

        // Check if the new item already exist in the list.

        bool find               = false;
693
        QueueListViewItem* item = 0;
694
695

        QTreeWidgetItemIterator iter(this);
696

697
698
699
700
        while (*iter)
        {
            item = dynamic_cast<QueueListViewItem*>(*iter);

701
            if (item && item->info() == info)
702
            {
703
                find = true;
704
            }
705
706
707
708
709
710

            ++iter;
        }

        if (!find)
        {
Gilles Caulier's avatar
Gilles Caulier committed
711
            new QueueListViewItem(this, info);
712
713
        }
    }
714

Eva Brucherseifer's avatar
Eva Brucherseifer committed
715
    updateDestFileNames();
Gilles Caulier's avatar
Gilles Caulier committed
716

717
    emit signalQueueContentsChanged();
718
719
}

720
721
void QueueListView::drawRow(QPainter* p, const QStyleOptionViewItem& opt, const QModelIndex& index) const
{
Gilles Caulier's avatar
Gilles Caulier committed
722
    QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(itemFromIndex(index));
Andi Clemens's avatar
Andi Clemens committed
723

Gilles Caulier's avatar
Gilles Caulier committed
724
    if (item && !item->hasValidThumbnail())
725
726
727
728
    {
        ImageInfo info = item->info();
        d->thumbLoadThread->find(info.fileUrl().toLocalFile());
    }
Andi Clemens's avatar
Andi Clemens committed
729

730
731
732
    QTreeWidget::drawRow(p, opt, index);
}

733
734
735
void QueueListView::slotThumbnailLoaded(const LoadingDescription& desc, const QPixmap& pix)
{
    QTreeWidgetItemIterator it(this);
736

737
738
    while (*it)
    {
Gilles Caulier's avatar
Gilles Caulier committed
739
        QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(*it);
740

741
        if (item && item->info().fileUrl() == KUrl(desc.filePath))
742
743
        {
            if (pix.isNull())
744
            {
745
                item->setThumb(SmallIcon("image-x-generic", d->iconSize, KIconLoader::DisabledState));
746
            }
747
            else
748
            {
749
                item->setThumb(pix.scaled(d->iconSize, d->iconSize, Qt::KeepAspectRatio));
750
            }
751
752
753

            return;
        }
754

755
756
757
758
759
760
        ++it;
    }
}

void QueueListView::slotClearList()
{
Gilles Caulier's avatar
Gilles Caulier committed
761
    removeItems(Private::ItemsAll);
762
    emit signalQueueContentsChanged();
763
764
765
766
}

void QueueListView::slotRemoveSelectedItems()
{
Gilles Caulier's avatar
Gilles Caulier committed
767
    removeItems(Private::ItemsSelected);
768
    emit signalQueueContentsChanged();
769
770
771
772
}

void QueueListView::slotRemoveItemsDone()
{
Gilles Caulier's avatar
Gilles Caulier committed
773
    removeItems(Private::ItemsDone);
774
    emit signalQueueContentsChanged();
775
776
777
778
}

void QueueListView::removeItems(int removeType)
{
779
780
    hideToolTip();

781
    bool find;
782

783
784
785
786
    do
    {
        find = false;
        QTreeWidgetItemIterator it(this);
787

788
789
        while (*it)
        {
Gilles Caulier's avatar
Gilles Caulier committed
790
            QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(*it);
791

792
            if (item)
793
            {
794
                switch (removeType)
795
                {
796
                    case Private::ItemsSelected:
797
                    {
798
799
800
801
802
803
                        if (item->isSelected())
                        {
                            delete item;
                            find = true;
                        }
                        break;
804
                    }
805

806
807
808
809
810
811
812
813
814
                    case Private::ItemsDone:
                    {
                        if (item->isDone())
                        {
                            delete item;
                            find = true;
                        }
                        break;
                    }
Andi Clemens's avatar
Andi Clemens committed
815

816
                    default:  // ItemsAll
817
818
819
                    {
                        delete item;
                        find = true;
820
                        break;
821
822
823
                    }
                }
            }
824

825
826
827
            ++it;
        }
    }
828
    while (find);
829

830
    emit signalQueueContentsChanged();
831
832
833
}

void QueueListView::removeItemByInfo(const ImageInfo& info)
834
835
836
837
838
{
    removeItemById(info.id());
}

void QueueListView::removeItemById(qlonglong id)
839
{
840
841
    hideToolTip();

842
    bool find;
843

844
845
846
847
    do
    {
        find = false;
        QTreeWidgetItemIterator it(this);
848

849
850
        while (*it)
        {
Gilles Caulier's avatar
Gilles Caulier committed
851
            QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(*it);
852

853
            if (item && item->info().id() == id)
854
855
856
857
858
            {
                delete item;
                find = true;
                break;
            }
859

860
861
862
            ++it;
        }
    }
863
    while (find);
864

865
    emit signalQueueContentsChanged();
866
867
868
}

bool QueueListView::findItemByInfo(const ImageInfo& info)
869
{
870
    return (findItemById(info.id()) ? true : false);
871
872
}

873
QueueListViewItem* QueueListView::findItemById(qlonglong id)
874
875
{
    QTreeWidgetItemIterator it(this);
876

877
878
    while (*it)
    {
Gilles Caulier's avatar
Gilles Caulier committed
879
        QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(*it);
880

881
        if (item && item->info().id() == id)
882
        {
883
            return item;
884
        }
885
886
887

        ++it;
    }
888

889
    return 0;
890
891
892
893
894
}

QueueListViewItem* QueueListView::findItemByUrl(const KUrl& url)
{
    QTreeWidgetItemIterator it(this);
895

896
897
    while (*it)
    {
Gilles Caulier's avatar
Gilles Caulier committed
898
        QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(*it);
899

900
        if (item && item->info().fileUrl() == url)
901
        {
902
            return item;
903
        }
904
905
906
907
908
909
910
911
912
913
914

        ++it;
    }

    return 0;
}

int QueueListView::itemsCount()
{
    int count = 0;
    QTreeWidgetItemIterator it(this);
915

916
917
    while (*it)
    {
Gilles Caulier's avatar
Gilles Caulier committed
918
        QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(*it);
919
920
921
922
923
924

        if (item)
        {
            ++count;
        }

925
926
        ++it;
    }
927

928
929
930
    return count;
}

931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
void QueueListView::cancelItems()
{
    QTreeWidgetItemIterator it(this);

    while (*it)
    {
        QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(*it);

        if (item && item->isBusy())
        {
            item->setCanceled();
        }

        ++it;
    }
}

948
949
950
951
ImageInfoList QueueListView::pendingItemsList()
{
    ImageInfoList list;
    QTreeWidgetItemIterator it(this);
952

953
954
    while (*it)
    {
Gilles Caulier's avatar
Gilles Caulier committed
955
        QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(*it);
956

957
        if (item && !item->isDone())
958
        {
959
            list.append(item->info());
960
961
        }

962
963
        ++it;
    }
964

965
966
967
    return list;
}

968
969
970
971
972
int QueueListView::pendingItemsCount()
{
    return pendingItemsList().count();
}

973
974
975
976
int QueueListView::pendingTasksCount()
{
    int count = 0;
    QTreeWidgetItemIterator it(this);
977

978
979
    while (*it)
    {
Gilles Caulier's avatar
Gilles Caulier committed
980
        QueueListViewItem* const item = dynamic_cast<QueueListViewItem*>(*it);
981

982
        if (item && !item->isDone())
983
        {
984
            count += assignedTools().m_toolsList.count();
985
986
        }

987
988
        ++it;
    }
989

990
991
992
    return count;
}

993
void QueueListView::setSettings(const QueueSettings& settings)
994
995
{
    d->settings = settings;
996
    resetQueue();
997
    updateDestFileNames();
998
999
}

Gilles Caulier's avatar
Gilles Caulier committed
1000
QueueSettings QueueListView::settings() const