playlistbox.cpp 23.7 KB
Newer Older
1 2
/***************************************************************************
    begin                : Thu Sep 12 2002
3
    copyright            : (C) 2002 - 2004 by Scott Wheeler,
4
    email                : wheeler@kde.org
5 6 7 8 9 10 11 12 13 14 15 16
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <kiconloader.h>
Laurent Montel's avatar
Laurent Montel committed
17
#include <k3urldrag.h>
18
#include <kmessagebox.h>
Laurent Montel's avatar
Laurent Montel committed
19
#include <kmenu.h>
20
#include <kaction.h>
21
#include <kdebug.h>
22

Laurent Montel's avatar
Laurent Montel committed
23
#include <q3header.h>
24
#include <qpainter.h>
25
#include <qtimer.h>
26

Laurent Montel's avatar
Laurent Montel committed
27 28 29 30
#include <QDragLeaveEvent>
#include <QDragMoveEvent>
#include <QKeyEvent>
#include <QDropEvent>
31
#include <Q3ValueList>
Laurent Montel's avatar
Laurent Montel committed
32 33
#include <Q3PopupMenu>
#include <QMouseEvent>
34 35

#include "playlistbox.h"
36
#include "playlist.h"
37
#include "collectionlist.h"
38
#include "covermanager.h"
39
#include "dynamicplaylist.h"
40
#include "historyplaylist.h"
41
#include "upcomingplaylist.h"
42
#include "viewmode.h"
43
#include "searchplaylist.h"
44
#include "treeviewitemplaylist.h"
45
#include "actioncollection.h"
46
#include "cache.h"
47
#include "k3bexporter.h"
48
#include "tracksequencemanager.h"
49
#include "tagtransactionmanager.h"
50 51

using namespace ActionCollection;
52 53 54 55 56

////////////////////////////////////////////////////////////////////////////////
// PlaylistBox public methods
////////////////////////////////////////////////////////////////////////////////

57
PlaylistBox::PlaylistBox(QWidget *parent, Q3WidgetStack *playlistStack) :
Laurent Montel's avatar
Laurent Montel committed
58
    K3ListView(parent),
59
    PlaylistCollection(playlistStack),
60
    m_viewModeIndex(0),
61
    m_hasSelection(false),
62
    m_doingMultiSelect(false),
63
    m_dropItem(0),
64
    m_showTimer(0)
65
{
66
    readConfig();
67
    addColumn("Playlists", width());
68 69

    header()->blockSignals(true);
70
    header()->hide();
71
    header()->blockSignals(false);
72

73
    setSorting(0);
74 75
    setFullWidth(true);
    setItemMargin(3);
Laurent Montel's avatar
Laurent Montel committed
76

77 78
    setAcceptDrops(true);
    setSelectionModeExt(Extended);
Laurent Montel's avatar
Laurent Montel committed
79

80
    m_contextMenu = new KMenu(this);
81

82 83
    K3bPlaylistExporter *exporter = new K3bPlaylistExporter(this);
    m_k3bAction = exporter->action();
84

85 86
    action("file_new")->plug(m_contextMenu);
    action("renamePlaylist")->plug(m_contextMenu);
87
    action("editSearch")->plug(m_contextMenu);
88 89 90 91 92
    action("duplicatePlaylist")->plug(m_contextMenu);
    action("reloadPlaylist")->plug(m_contextMenu);
    action("deleteItemPlaylist")->plug(m_contextMenu);
    action("file_save")->plug(m_contextMenu);
    action("file_save_as")->plug(m_contextMenu);
93
    if(m_k3bAction)
94
        m_k3bAction->plug(m_contextMenu);
Laurent Montel's avatar
Laurent Montel committed
95

96 97
    m_contextMenu->insertSeparator();

98
    // add the view modes stuff
Laurent Montel's avatar
Laurent Montel committed
99

100
    KSelectAction *viewModeAction =
101
        new KSelectAction(i18n("View Modes"), "view_choose", KShortcut(), ActionCollection::actions(), "viewModeMenu");
Laurent Montel's avatar
Laurent Montel committed
102

103 104 105
    m_viewModes.append(new ViewMode(this));
    m_viewModes.append(new CompactViewMode(this));
    m_viewModes.append(new TreeViewMode(this));
106
    // m_viewModes.append(new CoverManagerMode(this));
107 108 109

    QStringList modeNames;

110
    for(QList<ViewMode *>::Iterator it = m_viewModes.begin(); it != m_viewModes.end(); ++it)
111
        modeNames.append((*it)->name());
112

113
    viewModeAction->setItems(modeNames);
114

115
    QMenu *p = viewModeAction->popupMenu();
116 117 118 119
    p->changeItem(0, SmallIconSet("view_detailed"), modeNames[0]);
    p->changeItem(1, SmallIconSet("view_text"), modeNames[1]);
    p->changeItem(2, SmallIconSet("view_tree"), modeNames[2]);

120 121 122
    CollectionList::initialize(this);
    Cache::loadPlaylists(this);

123
    viewModeAction->setCurrentItem(m_viewModeIndex);
124
    m_viewModes[m_viewModeIndex]->setShown(true);
Laurent Montel's avatar
Laurent Montel committed
125

126 127 128
    TrackSequenceManager::instance()->setCurrentPlaylist(CollectionList::instance());
    raise(CollectionList::instance());

129 130
    viewModeAction->plug(m_contextMenu);
    connect(viewModeAction, SIGNAL(activated(int)), this, SLOT(slotSetViewMode(int)));
131

132
    connect(this, SIGNAL(selectionChanged()),
133
            this, SLOT(slotPlaylistChanged()));
Laurent Montel's avatar
Laurent Montel committed
134

Laurent Montel's avatar
Laurent Montel committed
135
    connect(this, SIGNAL(doubleClicked(Q3ListViewItem *)),
136
            this, SLOT(slotDoubleClicked()));
Laurent Montel's avatar
Laurent Montel committed
137

Laurent Montel's avatar
Laurent Montel committed
138
    connect(this, SIGNAL(contextMenuRequested(Q3ListViewItem *, const QPoint &, int)),
139
            this, SLOT(slotShowContextMenu(Q3ListViewItem *, const QPoint &, int)));
140

141 142 143 144
    TagTransactionManager *tagManager = TagTransactionManager::instance();
    connect(tagManager, SIGNAL(signalAboutToModifyTags()), SLOT(slotFreezePlaylists()));
    connect(tagManager, SIGNAL(signalDoneModifyingTags()), SLOT(slotUnfreezePlaylists()));

145
    setupUpcomingPlaylist();
146 147

    connect(CollectionList::instance(), SIGNAL(signalNewTag(const QString &, unsigned)),
148 149 150
            this, SLOT(slotAddItem(const QString &, unsigned)));
    connect(CollectionList::instance(), SIGNAL(signalRemovedTag(const QString &, unsigned)),
            this, SLOT(slotRemoveItem(const QString &, unsigned)));
151

152
    QTimer::singleShot(0, object(), SLOT(slotScanFolders()));
153
    enableDirWatch(true);
154 155 156

    // Auto-save playlists after 10 minutes
    QTimer::singleShot(600000, this, SLOT(slotSavePlaylists()));
157 158 159

    m_showTimer = new QTimer(this);
    connect(m_showTimer, SIGNAL(timeout()), SLOT(slotShowDropTarget()));
160 161 162 163
}

PlaylistBox::~PlaylistBox()
{
164 165
    PlaylistList l;
    CollectionList *collection = CollectionList::instance();
Laurent Montel's avatar
Laurent Montel committed
166
    for(Q3ListViewItem *i = firstChild(); i; i = i->nextSibling()) {
167 168 169
        Item *item = static_cast<Item *>(i);
        if(item->playlist() && item->playlist() != collection)
            l.append(item->playlist());
170
    }
171

172 173
    Cache::savePlaylists(l);
    saveConfig();
174 175
}

176 177 178
void PlaylistBox::raise(Playlist *playlist)
{
    if(!playlist)
179
        return;
180

181
    Item *i = m_playlistDict.find(playlist);
182

183
    if(i) {
184 185
        clearSelection();
        setSelected(i, true);
186

187 188
        setSingleItem(i);
        ensureItemVisible(currentItem());
189 190
    }
    else
191 192
        PlaylistCollection::raise(playlist);

193
    slotPlaylistChanged();
194 195
}

196
void PlaylistBox::duplicate()
197
{
198 199
    Item *item = static_cast<Item *>(currentItem());
    if(!item || !item->playlist())
200
        return;
201

202
    QString name = playlistNameDialog(i18n("Duplicate"), item->text(0));
203

204
    if(name.isNull())
205
        return;
206

207 208
    Playlist *p = new Playlist(this, name);
    p->createItems(item->playlist()->items());
209 210
}

211 212 213 214
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox public slots
////////////////////////////////////////////////////////////////////////////////

215 216
void PlaylistBox::paste()
{
Scott Wheeler's avatar
Scott Wheeler committed
217
    Item *i = static_cast<Item *>(currentItem());
218 219 220
    decode(kapp->clipboard()->data(), i);
}

221 222 223 224
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox protected methods
////////////////////////////////////////////////////////////////////////////////

225 226
void PlaylistBox::slotFreezePlaylists()
{
227
    setDynamicListsFrozen(true);
228 229 230 231
}

void PlaylistBox::slotUnfreezePlaylists()
{
232
    setDynamicListsFrozen(false);
233 234
}

235 236
void PlaylistBox::setupPlaylist(Playlist *playlist, const QString &iconName)
{
237 238 239 240 241 242
    setupPlaylist(playlist, iconName, 0);
}

void PlaylistBox::setupPlaylist(Playlist *playlist, const QString &iconName, Item *parentItem)
{
    connect(playlist, SIGNAL(signalPlaylistItemsDropped(Playlist *)),
243
            SLOT(slotPlaylistItemsDropped(Playlist *)));
244

245
    PlaylistCollection::setupPlaylist(playlist, iconName);
246 247

    if(parentItem)
248
        new Item(parentItem, iconName, playlist->name(), playlist);
249
    else
250
        new Item(this, iconName, playlist->name(), playlist);
251 252
}

253
void PlaylistBox::removePlaylist(Playlist *playlist)
254
{
255 256 257
    removeNameFromDict(m_playlistDict[playlist]->text(0));
    removeFileFromDict(playlist->fileName());
    m_playlistDict.remove(playlist);
258
}
259

260 261 262 263
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox private methods
////////////////////////////////////////////////////////////////////////////////

264 265
void PlaylistBox::readConfig()
{
266
    KConfigGroup config(KGlobal::config(), "PlaylistBox");
267
    m_viewModeIndex = config.readEntry("ViewMode", 0);
268 269 270 271
}

void PlaylistBox::saveConfig()
{
272
    KConfigGroup config(KGlobal::config(), "PlaylistBox");
273
    config.writeEntry("ViewMode", action<KSelectAction>("viewModeMenu")->currentItem());
274
    KGlobal::config()->sync();
275 276
}

277
void PlaylistBox::remove()
278
{
279
    ItemList items = selectedItems();
280

281
    if(items.isEmpty())
282
        return;
283

284
    QStringList files;
285
    QStringList names;
286 287

    for(ItemList::ConstIterator it = items.begin(); it != items.end(); ++it) {
288 289 290 291 292 293 294
        if(*it && (*it)->playlist() &&
           !(*it)->playlist()->fileName().isEmpty() &&
           QFileInfo((*it)->playlist()->fileName()).exists())
        {
            files.append((*it)->playlist()->fileName());
        }
        names.append((*it)->playlist()->name());
295 296
    }

297
    if(!files.isEmpty()) {
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
        int remove = KMessageBox::warningYesNoCancelList(
            this, i18n("Do you want to delete these files from the disk as well?"), files, QString::null, KStdGuiItem::del(), i18n("Keep"));

        if(remove == KMessageBox::Yes) {
            QStringList couldNotDelete;
            for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it) {
                if(!QFile::remove(*it))
                    couldNotDelete.append(*it);
            }

            if(!couldNotDelete.isEmpty())
                KMessageBox::errorList(this, i18n("Could not delete these files."), couldNotDelete);
        }
        else if(remove == KMessageBox::Cancel)
            return;
313
    }
314
    else if(items.count() > 1 || items.front()->playlist() != upcomingPlaylist()) {
315 316 317 318 319 320 321 322 323
        if(KMessageBox::warningContinueCancelList(this,
                                                  i18n("Are you sure you want to remove these "
                                                       "playlists from your collection?"),
                                                  names,
                                                  i18n("Remove Items?"),
                                                  KGuiItem(i18n("&Remove"), "edittrash")) == KMessageBox::Cancel)
        {
            return;
        }
324
    }
325

326
    PlaylistList removeQueue;
327

328
    for(ItemList::ConstIterator it = items.begin(); it != items.end(); ++it) {
329 330 331 332 333 334
        if(*it != Item::collectionItem() &&
           (*it)->playlist() &&
           (!(*it)->playlist()->readOnly()))
        {
            removeQueue.append((*it)->playlist());
        }
335
    }
336

337
    if(items.back()->nextSibling() && static_cast<Item *>(items.back()->nextSibling())->playlist())
338
        setSingleItem(items.back()->nextSibling());
339
    else {
340 341 342
        Item *i = static_cast<Item *>(items.front()->itemAbove());
        while(i && !i->playlist())
            i = static_cast<Item *>(i->itemAbove());
343

344 345
        if(!i)
            i = Item::collectionItem();
346

347
        setSingleItem(i);
348
    }
349

350
    for(PlaylistList::ConstIterator it = removeQueue.begin(); it != removeQueue.end(); ++it) {
351 352 353 354 355 356
        if(*it != upcomingPlaylist())
            delete *it;
        else {
            action<KToggleAction>("showUpcoming")->setChecked(false);
            setUpcomingPlaylistEnabled(false);
        }
357
    }
358 359
}

360
void PlaylistBox::setDynamicListsFrozen(bool frozen)
361
{
362
    for(QList<ViewMode *>::Iterator it = m_viewModes.begin();
363 364
        it != m_viewModes.end();
        ++it)
365
    {
366
        (*it)->setDynamicListsFrozen(frozen);
367
    }
368 369
}

370 371
void PlaylistBox::slotSavePlaylists()
{
Scott Wheeler's avatar
Scott Wheeler committed
372
    kDebug(65432) << "Auto-saving playlists and covers.\n";
373 374 375

    PlaylistList l;
    CollectionList *collection = CollectionList::instance();
Laurent Montel's avatar
Laurent Montel committed
376
    for(Q3ListViewItem *i = firstChild(); i; i = i->nextSibling()) {
377 378 379
        Item *item = static_cast<Item *>(i);
        if(item->playlist() && item->playlist() != collection)
            l.append(item->playlist());
380 381 382
    }

    Cache::savePlaylists(l);
383 384
    CoverManager::saveCovers();

385 386 387
    QTimer::singleShot(600000, this, SLOT(slotSavePlaylists()));
}

388 389 390
void PlaylistBox::slotShowDropTarget()
{
    if(!m_dropItem) {
391 392
        kError(65432) << "Trying to show the playlist of a null item!\n";
        return;
393 394
    }

395
    raise(m_dropItem->playlist());
396 397
}

398 399
void PlaylistBox::slotAddItem(const QString &tag, unsigned column)
{
400 401
    for(QList<ViewMode *>::Iterator it = m_viewModes.begin(); it != m_viewModes.end(); ++it)
        (*it)->addItems(QStringList(tag), column);
402 403 404 405
}

void PlaylistBox::slotRemoveItem(const QString &tag, unsigned column)
{
406
    for(QList<ViewMode *>::Iterator it = m_viewModes.begin(); it != m_viewModes.end(); ++it)
407
        (*it)->removeItem(tag, column);
408 409
}

410
void PlaylistBox::decode(QMimeSource *s, Item *item)
411
{
412
    if(!s || (item && item->playlist() && item->playlist()->readOnly()))
413
        return;
414

415
    KUrl::List urls;
Laurent Montel's avatar
Laurent Montel committed
416

417
    if(K3URLDrag::decode(s, urls) && !urls.isEmpty()) {
418
        QStringList files;
419
        for(KUrl::List::Iterator it = urls.begin(); it != urls.end(); ++it)
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
            files.append((*it).path());

        if(item) {
            TreeViewItemPlaylist *playlistItem;
            playlistItem = dynamic_cast<TreeViewItemPlaylist *>(item->playlist());
            if(playlistItem) {
                playlistItem->retag(files, currentPlaylist());
                TagTransactionManager::instance()->commit();
                currentPlaylist()->update();
                return;
            }
        }

        if(item && item->playlist())
            item->playlist()->addFiles(files);
        else {
            QString name = playlistNameDialog();
            if(!name.isNull()) {
                Playlist *p = new Playlist(this, name);
                p->addFiles(files);
            }
        }
442 443 444
    }
}

445
void PlaylistBox::contentsDropEvent(QDropEvent *e)
446
{
447 448
    m_showTimer->stop();

449
    Item *i = static_cast<Item *>(itemAt(contentsToViewport(e->pos())));
450
    decode(e, i);
451 452

    if(m_dropItem) {
453 454 455
        Item *old = m_dropItem;
        m_dropItem = 0;
        old->repaint();
456
    }
457 458
}

459
void PlaylistBox::contentsDragMoveEvent(QDragMoveEvent *e)
460 461
{
    // If we can decode the input source, there is a non-null item at the "move"
Laurent Montel's avatar
Laurent Montel committed
462
    // position, the playlist for that Item is non-null, is not the
463 464 465
    // selected playlist and is not the CollectionList, then accept the event.
    //
    // Otherwise, do not accept the event.
Laurent Montel's avatar
Laurent Montel committed
466

467
    if(!K3URLDrag::canDecode(e)) {
468 469
        e->accept(false);
        return;
470 471
    }

472 473 474
    Item *target = static_cast<Item *>(itemAt(contentsToViewport(e->pos())));

    if(target) {
475

476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
        if(target->playlist() && target->playlist()->readOnly())
            return;

        // This is a semi-dirty hack to check if the items are coming from within
        // JuK.  If they are not coming from a Playlist (or subclass) then the
        // dynamic_cast will fail and we can safely assume that the item is
        // coming from outside of JuK.

        if(dynamic_cast<Playlist *>(e->source())) {
            if(target->playlist() &&
               target->playlist() != CollectionList::instance() &&
               !target->isSelected())
            {
                e->accept(true);
            }
            else
                e->accept(false);
        }
        else // the dropped items are coming from outside of JuK
            e->accept(true);

        if(m_dropItem != target) {
            Item *old = m_dropItem;
            m_showTimer->stop();

            if(e->isAccepted()) {
                m_dropItem = target;
                target->repaint();
                m_showTimer->start(1500, true);
            }
            else
                m_dropItem = 0;

            if(old)
                old->repaint();
        }
512
    }
513 514
    else {

515 516
        // We're dragging over the whitespace.  We'll use this case to make it
        // possible to create new lists.
517

518
        e->accept(true);
519
    }
520 521
}

522 523 524
void PlaylistBox::contentsDragLeaveEvent(QDragLeaveEvent *e)
{
    if(m_dropItem) {
525 526 527
        Item *old = m_dropItem;
        m_dropItem = 0;
        old->repaint();
528
    }
Laurent Montel's avatar
Laurent Montel committed
529
    K3ListView::contentsDragLeaveEvent(e);
530 531
}

532 533
void PlaylistBox::contentsMousePressEvent(QMouseEvent *e)
{
534
    if(e->button() == Qt::LeftButton)
535
        m_doingMultiSelect = true;
Laurent Montel's avatar
Laurent Montel committed
536
    K3ListView::contentsMousePressEvent(e);
537 538 539 540
}

void PlaylistBox::contentsMouseReleaseEvent(QMouseEvent *e)
{
541
    if(e->button() == Qt::LeftButton) {
542 543
        m_doingMultiSelect = false;
        slotPlaylistChanged();
544
    }
Laurent Montel's avatar
Laurent Montel committed
545
    K3ListView::contentsMouseReleaseEvent(e);
546 547
}

548 549
void PlaylistBox::keyPressEvent(QKeyEvent *e)
{
550
    if((e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) && e->state() == Qt::ShiftButton)
551
        m_doingMultiSelect = true;
Laurent Montel's avatar
Laurent Montel committed
552
    K3ListView::keyPressEvent(e);
553 554 555 556
}

void PlaylistBox::keyReleaseEvent(QKeyEvent *e)
{
557
    if(m_doingMultiSelect && e->key() == Qt::Key_Shift) {
558 559
        m_doingMultiSelect = false;
        slotPlaylistChanged();
560
    }
Laurent Montel's avatar
Laurent Montel committed
561
    K3ListView::keyReleaseEvent(e);
562 563
}

564
PlaylistBox::ItemList PlaylistBox::selectedItems() const
565
{
566
    ItemList l;
567

Laurent Montel's avatar
Laurent Montel committed
568
    for(Q3ListViewItemIterator it(const_cast<PlaylistBox *>(this),
569 570
                                 Q3ListViewItemIterator::Selected); it.current(); ++it)
        l.append(static_cast<Item *>(*it));
571

572 573 574
    return l;
}

Laurent Montel's avatar
Laurent Montel committed
575
void PlaylistBox::setSingleItem(Q3ListViewItem *item)
576
{
577
    setSelectionModeExt(Single);
Laurent Montel's avatar
Laurent Montel committed
578
    K3ListView::setCurrentItem(item);
579
    setSelectionModeExt(Extended);
580 581
}

582 583 584 585
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox private slots
////////////////////////////////////////////////////////////////////////////////

586
void PlaylistBox::slotPlaylistChanged()
587
{
588 589
    // Don't update while the mouse is pressed down.

590
    if(m_doingMultiSelect)
591
        return;
592 593 594 595

    ItemList items = selectedItems();
    m_hasSelection = !items.isEmpty();

596 597
    bool allowReload = false;

598
    PlaylistList playlists;
599
    for(ItemList::ConstIterator it = items.begin(); it != items.end(); ++it) {
600

601 602 603 604 605 606
        Playlist *p = (*it)->playlist();
        if(p) {
            if(p->canReload())
                allowReload = true;
            playlists.append(p);
        }
607 608
    }

609 610
    bool singlePlaylist = playlists.count() == 1;

611
    if(playlists.isEmpty() ||
612
       (singlePlaylist &&
613 614
        (playlists.front() == CollectionList::instance() ||
         playlists.front()->readOnly())))
615 616 617 618 619 620 621 622 623 624 625
    {
        action("file_save")->setEnabled(false);
        action("file_save_as")->setEnabled(false);
        action("renamePlaylist")->setEnabled(false);
        action("deleteItemPlaylist")->setEnabled(false);
    }
    else {
        action("file_save")->setEnabled(true);
        action("file_save_as")->setEnabled(true);
        action("renamePlaylist")->setEnabled(playlists.count() == 1);
        action("deleteItemPlaylist")->setEnabled(true);
626
    }
627 628
    action("reloadPlaylist")->setEnabled(allowReload);
    action("duplicatePlaylist")->setEnabled(!playlists.isEmpty());
629 630

    if(m_k3bAction)
631
        m_k3bAction->setEnabled(!playlists.isEmpty());
632

633
    action("editSearch")->setEnabled(singlePlaylist &&
634
                                     playlists.front()->searchIsEditable());
635

636
    if(singlePlaylist) {
637
        PlaylistCollection::raise(playlists.front());
638

639 640 641 642
        if(playlists.front() == upcomingPlaylist())
            action("deleteItemPlaylist")->setText(i18n("Hid&e"));
        else
            action("deleteItemPlaylist")->setText(i18n("R&emove"));
643
    }
644
    else if(!playlists.isEmpty())
645
        createDynamicPlaylist(playlists);
646 647
}

648
void PlaylistBox::slotDoubleClicked()
649
{
650 651
    action("stop")->activate();
    action("play")->activate();
652 653
}

Laurent Montel's avatar
Laurent Montel committed
654
void PlaylistBox::slotShowContextMenu(Q3ListViewItem *, const QPoint &point, int)
655
{
656
    m_contextMenu->popup(point);
657 658
}

659 660 661 662 663
void PlaylistBox::slotPlaylistItemsDropped(Playlist *p)
{
    raise(p);
}

664
void PlaylistBox::slotSetViewMode(int index)
665
{
666
    if(index == m_viewModeIndex)
667
        return;
668 669 670

    viewMode()->setShown(false);
    m_viewModeIndex = index;
Laurent Montel's avatar
Laurent Montel committed
671
    viewMode()->setShown(true);
672 673
}

674
void PlaylistBox::setupItem(Item *item)
675
{
676 677
    m_playlistDict.insert(item->playlist(), item);
    viewMode()->queueRefresh();
678 679
}

680 681 682
void PlaylistBox::setupUpcomingPlaylist()
{
    KConfigGroup config(KGlobal::config(), "Playlists");
683
    bool enable = config.readEntry("showUpcoming", false);
684 685 686 687 688

    setUpcomingPlaylistEnabled(enable);
    action<KToggleAction>("showUpcoming")->setChecked(enable);
}

689
////////////////////////////////////////////////////////////////////////////////
690
// PlaylistBox::Item protected methods
691 692
////////////////////////////////////////////////////////////////////////////////

693 694
PlaylistBox::Item *PlaylistBox::Item::m_collectionItem = 0;

695
PlaylistBox::Item::Item(PlaylistBox *listBox, const QString &icon, const QString &text, Playlist *l)
Laurent Montel's avatar
Laurent Montel committed
696
    : QObject(listBox), K3ListViewItem(listBox, 0, text),
697
      m_playlist(l), m_text(text), m_iconName(icon), m_sortedFirst(false)
698
{
699 700
    init();
}
701

702
PlaylistBox::Item::Item(Item *parent, const QString &icon, const QString &text, Playlist *l)
Laurent Montel's avatar
Laurent Montel committed
703
    : QObject(parent->listView()), K3ListViewItem(parent, text),
704
    m_playlist(l), m_text(text), m_iconName(icon), m_sortedFirst(false)
705 706
{
    init();
707 708
}

709
PlaylistBox::Item::~Item()
710 711 712 713
{

}

Laurent Montel's avatar
Laurent Montel committed
714
int PlaylistBox::Item::compare(Q3ListViewItem *i, int col, bool) const
715
{
716
    Item *otherItem = static_cast<Item *>(i);
717 718 719
    PlaylistBox *playlistBox = static_cast<PlaylistBox *>(listView());

    if(m_playlist == playlistBox->upcomingPlaylist() && otherItem->m_playlist != CollectionList::instance())
720
        return -1;
721
    if(otherItem->m_playlist == playlistBox->upcomingPlaylist() && m_playlist != CollectionList::instance())
722
        return 1;
723 724

    if(m_sortedFirst && !otherItem->m_sortedFirst)
725
        return -1;
726
    else if(otherItem->m_sortedFirst && !m_sortedFirst)
727
        return 1;
728 729 730 731

    return text(col).lower().localeAwareCompare(i->text(col).lower());
}

732 733
void PlaylistBox::Item::paintCell(QPainter *painter, const QColorGroup &colorGroup, int column, int width, int align)
{
734 735
    PlaylistBox *playlistBox = static_cast<PlaylistBox *>(listView());
    playlistBox->viewMode()->paintCell(this, painter, colorGroup, column, width, align);
736 737 738 739 740
}

void PlaylistBox::Item::setText(int column, const QString &text)
{
    m_text = text;
Laurent Montel's avatar
Laurent Montel committed
741
    K3ListViewItem::setText(column, text);
742 743
}

744 745 746 747 748
void PlaylistBox::Item::setup()
{
    listView()->viewMode()->setupItem(this);
}

749 750 751 752 753 754 755
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox::Item protected slots
////////////////////////////////////////////////////////////////////////////////

void PlaylistBox::Item::slotSetName(const QString &name)
{
    if(listView()) {
756 757
        setText(0, name);
        setSelected(true);
758

759 760 761
        listView()->sort();
        listView()->ensureItemVisible(listView()->currentItem());
        listView()->viewMode()->queueRefresh();
762 763 764
    }
}

765 766 767 768 769 770
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox::Item private methods
////////////////////////////////////////////////////////////////////////////////

void PlaylistBox::Item::init()
{
771
    PlaylistBox *list = listView();
772 773 774 775

    list->setupItem(this);

    int iconSize = list->viewModeIndex() == 0 ? 32 : 16;
776
    setPixmap(0, SmallIcon(m_iconName, iconSize));
777
    list->addNameToDict(m_text);
778

779
    if(m_playlist) {
780 781 782 783 784
        connect(m_playlist, SIGNAL(signalNameChanged(const QString &)),
                this, SLOT(slotSetName(const QString &)));
        connect(m_playlist, SIGNAL(destroyed()), this, SLOT(deleteLater()));
        connect(m_playlist, SIGNAL(signalEnableDirWatch(bool)),
                list->object(), SLOT(slotEnableDirWatch(bool)));
785
    }
786

787
    if(m_playlist == CollectionList::instance()) {
788 789 790
        m_sortedFirst = true;
        m_collectionItem = this;
        list->viewMode()->setupDynamicPlaylists();
791
    }
792

793
    if(m_playlist == list->historyPlaylist() || m_playlist == list->upcomingPlaylist())
794
        m_sortedFirst = true;
795 796
}

797
#include "playlistbox.moc"
798 799

// vim: set et sw=4 tw=0 sta: