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

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

18
#include <kstandarddirs.h>
19
#include <kmessagebox.h>
20
#include <kinputdialog.h>
21
#include <kcmdlineargs.h>
22 23
#include <kdebug.h>

24
#include <qpopupmenu.h>
25

26
#include "playlistsplitter.h"
27
#include "searchwidget.h"
28
#include "directorylist.h"
29
#include "playlistsearch.h"
30
#include "dynamicplaylist.h"
31
#include "searchplaylist.h"
32
#include "mediafiles.h"
33
#include "advancedsearchdialog.h"
34 35

////////////////////////////////////////////////////////////////////////////////
36
// helper functions
37 38
////////////////////////////////////////////////////////////////////////////////

39
void processEvents()
40
{
41 42 43
    static int processed = 0;
    if(processed == 0)
        kapp->processEvents();
44
    processed = (processed + 1) % 5;
45 46
}

47
////////////////////////////////////////////////////////////////////////////////
48
// public methods
49 50
////////////////////////////////////////////////////////////////////////////////

51
PlaylistSplitter::PlaylistSplitter(QWidget *parent, const char *name) :
52
    QSplitter(Qt::Horizontal, parent, name),
53
    m_playingItem(0), m_searchWidget(0), m_dynamicList(0),
54
    m_nextPlaylistItem(0)
55
{
56 57 58 59 60 61 62 63
#ifndef NO_DEBUG
    m_restore = KCmdLineArgs::parsedArgs()->isSet("restore");
#else
    m_restore = true;
#endif

    m_dirWatch = new KDirWatch();

64 65
    setupLayout();
    readConfig();
66 67

    m_editor->slotUpdateCollection();
68
}
69

70
PlaylistSplitter::~PlaylistSplitter()
71
{
Scott Wheeler's avatar
Scott Wheeler committed
72
    delete m_dirWatch;
73
    saveConfig();
74 75
}

76
QString PlaylistSplitter::uniquePlaylistName(const QString &startingWith, bool useParenthesis)
77
{
78
    if(!m_playlistBox)
79
	return QString::null;
80

81
    QStringList names = m_playlistBox->names();
82 83 84

    int playlistNumber = 1;

85
    // while the list contains more than zero instances of the generated
86 87
    // string...

88 89 90
    if(useParenthesis) {
	while(names.contains(startingWith + " (" + QString::number(playlistNumber) + ")") != 0)
	    playlistNumber++;
91 92

	return startingWith + " (" + QString::number(playlistNumber) + ")";
93
    }
94
    else {
95 96
	while(names.contains(startingWith + ' ' + QString::number(playlistNumber)) != 0)
	    playlistNumber++;
97

98
	return startingWith + " " + QString::number(playlistNumber);
99
    }
100 101
}

102
QString PlaylistSplitter::playNextFile(bool random, bool loopPlaylist)
103
{
104 105
    PlaylistItem *i;

106
    // Four basic cases here:  (1) We've asked for a specific next item, (2) play
107
    // the item that's after the currently playing item, (3) play the selected
108
    // item or (4) play the first item in the list.
109

110
    // (1) we've asked for a specific next item
111
    if(m_nextPlaylistItem && m_nextPlaylistItem != m_playingItem) {
112 113 114
        i = m_nextPlaylistItem;
        m_nextPlaylistItem = 0;
    }
115
    // (2) play the item after the currently selected item
116
    else if(m_playingItem) {
117 118
        Playlist *p = static_cast<Playlist *>(m_playingItem->listView());
        i = p->nextItem(m_playingItem, random);
119
        if(!i && loopPlaylist)
120
            i = static_cast<PlaylistItem *>(p->firstChild());
121
    }
122 123
    // (3) play the selected item
    else if(playlistSelection().size() > 0) {
124
        i = playlistSelection().first();
125 126
        if(!i)
            i = static_cast<PlaylistItem *>(visiblePlaylist()->firstChild());
127
    }
128 129 130
    // (4) play the first item in the list
    else
        i = static_cast<PlaylistItem *>(visiblePlaylist()->firstChild());
131

132
    return play(i);
133 134
}

135
QString PlaylistSplitter::playPreviousFile(bool random)
136
{
137
    if(!m_playingItem)
138
	return QString::null;
139

140 141
    Playlist *p = static_cast<Playlist *>(m_playingItem->listView());
    PlaylistItem *i = p->previousItem(m_playingItem, random);
142

143
    return play(i);
144 145
}

146 147 148 149 150 151
void PlaylistSplitter::populatePlayHistoryMenu(QPopupMenu* menu, bool random)
{
    Playlist *p = static_cast<Playlist *>(m_playingItem->listView());
    PlaylistItemList list = p->historyItems(m_playingItem, random);
    menu->clear();
    int i = 0;
152
    for(PlaylistItemList::Iterator it = list.begin(); it != list.end(); ++it)
153 154 155
        menu->insertItem((*it)->tag()->track(), ++i);
}

156 157 158 159 160 161 162 163
QString PlaylistSplitter::playSelectedFile()
{
    if(playlistSelection().isEmpty())
	return QString::null;
    else
	return play(playlistSelection().first());
}

164 165 166 167
QString PlaylistSplitter::playFirstFile()
{
    Playlist *p = visiblePlaylist();
    PlaylistItem *i = static_cast<PlaylistItem *>(p->firstChild());
168

169
    return play(i);
170 171
}

172 173 174 175 176 177 178 179 180
QString PlaylistSplitter::playRandomFile()
{
    Playlist *p = visiblePlaylist();
    PlaylistItem *i = static_cast<PlaylistItem *>(p->firstChild());

    // Not exactly random (the first item won't be taken into account)
    return play(p->nextItem(i, true));
}

181 182
void PlaylistSplitter::stop()
{
183 184
    m_nextPlaylistItem = 0;

185 186 187 188 189
    if(!m_playingItem)
	return;

    Playlist *p = static_cast<Playlist *>(m_playingItem->listView());

190 191 192
    if(p)
	p->setPlaying(m_playingItem, false);

193
    m_playingItem = 0;
194 195 196 197
}

QString PlaylistSplitter::playingArtist() const
{
198 199
    if(m_playingItem)
	return m_playingItem->text(PlaylistItem::ArtistColumn);
200
    else
201
	return QString::null;
202 203 204 205
}

QString PlaylistSplitter::playingTrack() const
{
206 207
    if(m_playingItem)
	return m_playingItem->text(PlaylistItem::TrackColumn);
208
    else
209
	return QString::null;
210 211 212 213
}

QString PlaylistSplitter::playingList() const
{
214 215
    if(m_playingItem)
	return static_cast<Playlist *>(m_playingItem->listView())->name();
216
    else
217
	return QString::null;
218 219
}

220
void PlaylistSplitter::open(const QString &file)
221
{
222 223 224
    if(file.isEmpty())
	return;

225 226 227 228 229
    if(visiblePlaylist() == m_collection ||
       KMessageBox::questionYesNo(this,
				  i18n("Do you want to add this item to the current list or to the collection list?"),
				  QString::null,
				  KGuiItem(i18n("Current")),
230 231
				  KGuiItem(i18n("Collection"))) == KMessageBox::No)
    {
232
	slotAddToPlaylist(file, m_collection);
233
    }
234
    else
235
	slotAddToPlaylist(file, visiblePlaylist());
236 237
}

238
void PlaylistSplitter::open(const QStringList &files)
239
{
240 241
    if(files.isEmpty())
	return;
242 243 244 245 246 247 248

    if(visiblePlaylist() == m_collection ||
       KMessageBox::questionYesNo(this,
				  i18n("Do you want to add these items to the current list or to the collection list?"),
				  QString::null,
				  KGuiItem(i18n("Current")),
				  KGuiItem(i18n("Collection"))) == KMessageBox::No)
249
    {
250
	slotAddToPlaylist(files, m_collection);
251
    }
252
    else
253
	slotAddToPlaylist(files, visiblePlaylist());
254 255 256 257
}

Playlist *PlaylistSplitter::createPlaylist(const QString &name)
{
258
    Playlist *p = new Playlist(m_playlistStack, name);
259 260
    setupPlaylist(p, true);
    return p;
261 262
}

263 264 265 266
////////////////////////////////////////////////////////////////////////////////
// public slots
////////////////////////////////////////////////////////////////////////////////

267
void PlaylistSplitter::slotOpen()
268
{
269
    open(MediaFiles::openDialog(this));
270 271
}

272
void PlaylistSplitter::slotOpenDirectory()
273
{
274
    DirectoryList *l = new DirectoryList(m_directoryList, this, "directoryList");
275

276
    m_directoryQueue.clear();
277
    m_directoryQueueRemove.clear();
278

279
    connect(l, SIGNAL(signalDirectoryAdded(const QString &)),
280
	    this, SLOT(slotQueueDirectory(const QString &)));
281
    connect(l, SIGNAL(signalDirectoryRemoved(const QString &)),
282
	    this, SLOT(slotQueueDirectoryRemove(const QString &)));
283 284

    if(l->exec() == QDialog::Accepted) {
285
	open(m_directoryQueue);
286 287
	for(QStringList::Iterator it = m_directoryQueue.begin(); it !=  m_directoryQueue.end(); it++)
	    m_dirWatch->addDir(*it, false, true);
288

289
	m_directoryList += m_directoryQueue;
290 291 292

	QStringList::Iterator it = m_directoryQueueRemove.begin();
	for(; it !=  m_directoryQueueRemove.end(); it++) {
293
	    m_dirWatch->removeDir(*it);
294
	    m_directoryList.remove(*it);
295
	}
296 297
    }
}
298

299
Playlist *PlaylistSplitter::slotCreatePlaylist()
300 301 302
{
    bool ok;

303
    // If this text is changed, please also change it in PlaylistBox::duplicate().
304

305
    QString name = KInputDialog::getText(i18n("Create New Playlist"),
Nadeem Hasan's avatar
Nadeem Hasan committed
306 307
	i18n("Please enter a name for the new playlist:"),
	uniquePlaylistName(), &ok);
308
    if(ok)
309
	return createPlaylist(name);
310
    else
311
	return 0;
312 313
}

314 315 316 317 318 319 320 321 322 323
Playlist *PlaylistSplitter::slotCreatePlaylistFromDir()
{
    const QString dirName = KFileDialog::getExistingDirectory();
    if(dirName.isEmpty())
        return 0;

    Playlist *playlist = slotCreatePlaylist();
    if(!playlist)
        return 0;

324
    slotAddToPlaylist(dirName, playlist);
325 326 327 328

    return playlist;
}

329
void PlaylistSplitter::slotSelectPlaying()
330
{
331
    if(!m_playingItem)
332 333
	return;

334
    Playlist *l = static_cast<Playlist *>(m_playingItem->listView());
335

336 337
    if(!l)
	return;
338

339
    l->clearSelection();
340 341
    l->setSelected(m_playingItem, true);
    l->ensureItemVisible(m_playingItem);
Nadeem Hasan's avatar
Nadeem Hasan committed
342

343 344
    if(l != visiblePlaylist())
	m_playlistBox->raise(l);
345 346
}

347
void PlaylistSplitter::slotDeleteSelectedItems()
348 349 350
{
    Playlist *p = visiblePlaylist();
    if(p)
351
	p->slotRemoveSelectedItems();
352 353
}

354
void PlaylistSplitter::slotAddToPlaylist(const QString &file, Playlist *list, PlaylistItem *after)
355
{
356 357 358
    if(!after)
	after = static_cast<PlaylistItem *>(list->lastItem());

359
    KApplication::setOverrideCursor(Qt::waitCursor);
360
    addImpl(file, list, after);
361
    list->emitCountChanged();
362
    KApplication::restoreOverrideCursor();
Nadeem Hasan's avatar
Nadeem Hasan committed
363

364 365 366 367
    if(m_editor)
	m_editor->slotUpdateCollection();
}

368 369 370 371 372
void PlaylistSplitter::slotDeletePlaylist()
{
    if(m_playingItem && m_playingItem->listView() == visiblePlaylist())
	m_playingItem = 0;

373
    m_playlistBox->deleteItems();
374 375
}

376
void PlaylistSplitter::slotAddToPlaylist(const QStringList &files, Playlist *list, PlaylistItem *after)
377
{
378 379 380
    if(!after)
	after = static_cast<PlaylistItem *>(list->lastItem());

381
    KApplication::setOverrideCursor(Qt::waitCursor);
382

383
    for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it)
384 385
        after = addImpl(*it, list, after);

386
    list->emitCountChanged();
387

388 389 390 391 392 393
    KApplication::restoreOverrideCursor();

    if(m_editor)
	m_editor->slotUpdateCollection();
}

394 395 396 397 398 399
void PlaylistSplitter::slotSetSearchVisible(bool visible)
{
    m_searchWidget->setShown(visible);
    redisplaySearch();
}

400 401 402 403 404 405
void PlaylistSplitter::slotAdvancedSearch()
{
    AdvancedSearchDialog *d = new AdvancedSearchDialog(this);
    d->exec();
    delete d;
}
406

407
void PlaylistSplitter::slotGuessTagInfo(TagGuesser::Type type)
408
{
409
    visiblePlaylist()->slotGuessTagInfo(type);
410 411 412 413
    if(m_editor)
        m_editor->slotRefresh();
}

414 415 416 417 418 419 420
void PlaylistSplitter::slotRenameFile()
{
    visiblePlaylist()->slotRenameFile();
    if(m_editor)
        m_editor->slotRefresh();
}

421 422 423 424 425 426
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

void PlaylistSplitter::setupLayout()
{
427 428
    setOpaqueResize(true);

429
    m_playlistBox = new PlaylistBox(this, "playlistBox");
430

431 432 433
    connect(m_playlistBox, SIGNAL(signalCreateSearchList(const PlaylistSearch &, const QString &, const QString &)),
            this, SLOT(slotCreateSearchList(const PlaylistSearch &, const QString &, const QString &)));

434 435 436
    connect(m_playlistBox, SIGNAL(signalCreatePlaylist(const QStringList &)),
	    this, SLOT(slotCreatePlaylist(const QStringList &)));

437 438 439 440 441
    // Create a splitter to go between the playlists and the editor.

    QSplitter *editorSplitter = new QSplitter(Qt::Vertical, this, "editorSplitter");

    // Create the playlist and the editor.
442

443 444
    m_playlistStack = new QWidgetStack(editorSplitter, "playlistStack");
    m_editor = new TagEditor(editorSplitter, "tagEditor");
445 446 447

    // Make the editor as small as possible (or at least as small as recommended)

448
    editorSplitter->setResizeMode(m_editor, QSplitter::FollowSizeHint);
449

450
    // Make the connection that will update the selected playlist when a
451 452
    // selection is made in the playlist box.

453
    connect(m_playlistBox, SIGNAL(signalCurrentChanged(const PlaylistList &)),
454
	    this, SLOT(slotChangePlaylist(const PlaylistList &)));
455

456
    connect(m_playlistBox, SIGNAL(signalDoubleClicked()), this, SIGNAL(signalListBoxDoubleClicked()));
457

458
    // Create the collection list; this should always exist.  This has a
459
    // slightly different creation process than normal playlists (since it in
460
    // fact is a subclass) so it is created here rather than by using
461
    // slotCreatePlaylist().
462

463
    CollectionList::initialize(m_playlistStack, m_restore);
464
    m_collection = CollectionList::instance();
465
    setupPlaylist(m_collection, true, "folder_sound", true);
466
    connect(m_collection, SIGNAL(signalCollectionChanged()), m_editor, SLOT(slotUpdateCollection()));
467
    connect(m_collection, SIGNAL(signalRequestPlaylistCreation(const PlaylistItemList &)),
468
	    this, SLOT(slotCreatePlaylist(const PlaylistItemList &)));
469

470 471

    // Create the search widget -- this must be done after the CollectionList is created.
472
    m_searchWidget = new SearchWidget(editorSplitter, "searchWidget");
473
    editorSplitter->moveToFirst(m_searchWidget);
474
    connect(m_searchWidget, SIGNAL(signalQueryChanged()), this, SLOT(slotShowSearchResults()));
475 476 477
    connect(CollectionList::instance(), SIGNAL(signalVisibleColumnsChanged()),
	    this, SLOT(slotVisibleColumnsChanged()));

478
    // Show the collection on startup.
479
    m_playlistBox->setSelected(0, true);
480 481 482 483
}

void PlaylistSplitter::readConfig()
{
484 485 486 487
    KConfig *config = KGlobal::config();
    { // block for Playlists group
	KConfigGroupSaver saver(config, "Playlists");

488 489 490 491 492 493
	QValueList<int> splitterSizes = config->readIntListEntry("PlaylistSplitterSizes");
	if(splitterSizes.isEmpty()) {
	    splitterSizes.append(100);
	    splitterSizes.append(640);
	}
	setSizes(splitterSizes);
494

495
	if(m_restore) {
496 497 498 499

	    QString playlistsFile = KGlobal::dirs()->saveLocation("appdata") + "playlists";

	    QFile f(playlistsFile);
Nadeem Hasan's avatar
Nadeem Hasan committed
500

501 502 503
	    if(f.open(IO_ReadOnly)) {
		QDataStream s(&f);
		while(!s.atEnd()) {
504
		    Playlist *p = new Playlist(m_playlistStack);
505 506 507 508
		    s >> *p;

		    // check to see if we've alredy loaded this item before continuing

509
		    if(p->fileName().isEmpty() || !m_playlistFiles.insert(p->fileName()))
510 511 512 513
			setupPlaylist(p);
		    else
			delete p;
		}
514
	    }
515

516
	    m_directoryList = config->readListEntry("DirectoryList");
517
	    QTimer::singleShot(0, this, SLOT(slotScanDirectories()));
518

519
	    connect(m_dirWatch, SIGNAL(dirty(const QString &)),
520
		    this, SLOT(slotDirChanged(const QString &)));
521

522 523
	    QStringList::Iterator it = m_directoryList.begin();
            for(; it != m_directoryList.end(); ++it)
524 525 526
		m_dirWatch->addDir(*it, false, true);

	    m_dirWatch->startScan();
527
	}
528 529 530

	// restore the list of hidden and shown columns

531
	if(m_collection) {
532
	    for(int i = 0; i < m_collection->columns(); i++)
533
		m_columnNames.append(m_collection->columnText(i));
534
	}
535

536
    }
537
}
538 539 540 541

void PlaylistSplitter::saveConfig()
{
    KConfig *config = KGlobal::config();
542

543
    // Save the list of open playlists.
Nadeem Hasan's avatar
Nadeem Hasan committed
544

545
    if(m_restore && m_playlistBox) {
546 547 548

	// Start at item 1.  We want to skip the collection list.

549 550
	QString playlistsFile = KGlobal::dirs()->saveLocation("appdata") + "playlists";
	QFile f(playlistsFile);
551

552 553 554 555
	if(f.open(IO_WriteOnly)) {

	    QDataStream s(&f);

556
	    PlaylistList l = m_playlistBox->playlists();
557

558 559
	    for(PlaylistList::Iterator it = l.begin(); it != l.end(); it++)
		s << *(*it);
560

561
	    f.close();
562 563 564
	}
	{ // block for Playlists group
	    KConfigGroupSaver saver(config, "Playlists");
565
	    config->writeEntry("DirectoryList", m_directoryList);
566
	    config->writeEntry("SortColumn", m_collection->sortColumn());
567
	    config->writeEntry("PlaylistSplitterSizes", sizes());
568 569
	}
    }
570 571
}

572
PlaylistItem *PlaylistSplitter::addImpl(const QString &file, Playlist *list, PlaylistItem *after)
573 574 575 576 577 578
{
    processEvents();
    QFileInfo fileInfo(QDir::cleanDirPath(file));
    if(fileInfo.exists()) {
        if(fileInfo.isDir()) {
            QDir dir(fileInfo.filePath());
579
            QStringList dirContents = dir.entryList();
580 581
            for(QStringList::Iterator it = dirContents.begin(); it != dirContents.end(); ++it)
                if(*it != "." && *it != "..")
582
                    after = addImpl(fileInfo.filePath() + QDir::separator() + *it, list, after);
583 584
        }
        else {
585
            if(MediaFiles::isMediaFile(file))
586
		after = list->createItem(fileInfo, QString::null, after, false);
587
	    else if(MediaFiles::isPlaylistFile(file))
588 589
		openPlaylist(fileInfo.absFilePath());
        }
Nadeem Hasan's avatar
Nadeem Hasan committed
590
    }
591
    return after;
592 593
}

594
void PlaylistSplitter::setupPlaylist(Playlist *p, bool raise, const char *icon, bool sortedFirst)
595
{
596 597
    connect(p, SIGNAL(signalSelectionChanged(const PlaylistItemList &)),
	    m_editor, SLOT(slotSetItems(const PlaylistItemList &)));
598 599 600 601 602 603 604

    connect(p, SIGNAL(doubleClicked(QListViewItem *)),
	    this, SIGNAL(signalActivated()));

    connect(p, SIGNAL(returnPressed(QListViewItem *)), 
	    this, SIGNAL(signalActivated()));

605
    connect(p, SIGNAL(signalCountChanged(Playlist *)),
606
	    this, SLOT(slotPlaylistCountChanged(Playlist *)));
607

608
    connect(p, SIGNAL(signalAboutToRemove(PlaylistItem *)),
609
	    this, SLOT(slotPlaylistItemRemoved(PlaylistItem *)));
610

611 612
    connect(p, SIGNAL(signalFilesDropped(const QStringList &, Playlist *, PlaylistItem *)),
	    this, SLOT(slotAddToPlaylist(const QStringList &, Playlist *, PlaylistItem *)));
613

614 615
    connect(p, SIGNAL(signalSetNext(PlaylistItem *)),
	    this, SLOT(slotSetNextItem(PlaylistItem *)));
616

617 618 619
    connect(p, SIGNAL(itemRenamed(QListViewItem *)),
	    m_editor, SLOT(slotRefresh()));

620
    if(icon)
621
	m_playlistBox->createItem(p, icon, raise, sortedFirst);
622

623 624 625 626 627
    if(raise) {
	PlaylistList l;
	l.append(p);
	slotChangePlaylist(l);
    }
628 629
}

630 631 632
Playlist *PlaylistSplitter::openPlaylist(const QString &file)
{
    QFileInfo fileInfo(file);
633 634 635
    if(!fileInfo.exists() ||
       !fileInfo.isFile() ||
       !fileInfo.isReadable() ||
636 637
       m_playlistFiles.insert(fileInfo.absFilePath()))
    {
638
	return 0;
639
    }
640

641
    Playlist *p = new Playlist(file, m_playlistStack, fileInfo.baseName(true));
642
    setupPlaylist(p);
643
    return p;
644 645
}

646 647 648 649 650 651 652
QString PlaylistSplitter::play(PlaylistItem *item)
{
    stop();

    if(!item)
	return QString::null;

653 654
    Playlist *p = static_cast<Playlist *>(item->listView());

655
    if(!p)
656 657
	return QString::null;

658 659
    p->setPlaying(item, true);

660 661 662 663 664
    m_playingItem = item;

    return item->absFilePath();
}

665 666 667 668 669 670 671 672 673 674
void PlaylistSplitter::redisplaySearch()
{
    if(!m_searchWidget->isVisible() || visiblePlaylist()->search().isEmpty())
	visiblePlaylist()->setItemsVisible(visiblePlaylist()->items(), true);
    else {
	Playlist::setItemsVisible(visiblePlaylist()->search().matchedItems(), true);
	Playlist::setItemsVisible(visiblePlaylist()->search().unmatchedItems(), false);
    }
}

675 676 677 678
////////////////////////////////////////////////////////////////////////////////
// private slots
////////////////////////////////////////////////////////////////////////////////

679
void PlaylistSplitter::slotChangePlaylist(const PlaylistList &l)
680
{
681 682
    if(l.isEmpty()) {
	emit signalPlaylistChanged();
683
	return;
684
    }
685

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
    // Save the current dynamic list so that we can delete it when we're done
    // showing the next list.  The two situations are that we're either showing
    // an existing, non-dynamic list or that we're creating a dynamic list; in 
    // both cases we want to get rid of the current one.
    //
    // If in fact the currently visible list *is not* a dynamic list, then
    // m_dyanmicList will simply be zero, making deleting it at the end of this
    // method just a no-op.
    //
    // And finally, because we will end up doing a recursive call to this method
    // to show the dynamic playlist (second case calls the first case), we want
    // to make sure that in that case we don't delete the very thing we're
    // being asked to show.  (Hence the conditional assignment.)

    Playlist *current = l.first() != m_dynamicList ? m_dynamicList : 0;
701

702
    m_nextPlaylistItem = 0;
703 704 705

    // First case:  We're just showing one, currently existing list.

706 707 708
    if(l.count() == 1) {
	m_playlistStack->raiseWidget(l.first());
	m_editor->slotSetItems(playlistSelection());
709 710 711

	if(m_dynamicList != l.first())
	   m_dynamicList = 0;
712 713 714 715 716

	if(m_searchWidget) {
	    m_searchWidget->setSearch(l.first()->search());
	    redisplaySearch();
	}
717
    }
718 719 720 721

    // Second case: There are multiple playlists in our list, so we need to create
    // a new "dynamic list" that is the union of these playlists.

722
    else {
723
	m_dynamicList = new DynamicPlaylist(l, m_playlistStack, i18n("Dynamic List"));
724 725 726 727 728

	// Note that this call will end up making a recursive call to this
	// method, but in that call since there will only be one list, it will
	// take the "first case" above.
	
729 730 731
	setupPlaylist(m_dynamicList, true, 0);
    }

732
    delete current;
733 734

    emit signalPlaylistChanged();
735 736
}

737
void PlaylistSplitter::slotPlaylistCountChanged(Playlist *p)
738
{
739 740
    if(p && p == m_playlistStack->visibleWidget())
	emit signalSelectedPlaylistCountChanged(p->childCount());
741 742
}

743
void PlaylistSplitter::slotPlaylistItemRemoved(PlaylistItem *item)
744
{
745 746
    if(item == m_playingItem)
	m_playingItem = 0;
747 748 749

    if(item == m_nextPlaylistItem)
	m_nextPlaylistItem = 0;
750 751
}

752 753 754 755 756 757 758 759
void PlaylistSplitter::slotCreatePlaylist(const QStringList &files)
{
    Playlist *p = slotCreatePlaylist();
    if(p)
	slotAddToPlaylist(files, p);
}


760
void PlaylistSplitter::slotCreatePlaylist(const PlaylistItemList &items)
761
{
762 763 764
    if(items.isEmpty())
	return;

765
    Playlist *playlist = slotCreatePlaylist();
766

767
    if(!playlist)
768
        return;
769

770
    playlist->createItems(items);
771 772
}

773
void PlaylistSplitter::slotShowSearchResults()
774 775 776 777
{
    PlaylistList playlists;
    playlists.append(visiblePlaylist());

778
    PlaylistSearch search = m_searchWidget->search(playlists);
779

780 781
    visiblePlaylist()->setSearch(search);
    redisplaySearch();
782 783
}

784 785
void PlaylistSplitter::slotVisibleColumnsChanged()
{
786 787 788
    m_searchWidget->updateColumns();
    // if(m_searchWidget->searchedColumns(0).count() > 1)
    slotShowSearchResults();
789 790
}

791 792 793 794 795 796 797 798 799
void PlaylistSplitter::slotCreateSearchList(const PlaylistSearch &search, 
					    const QString &searchCategory,
					    const QString &name)
{
    SearchPlaylist *p = new SearchPlaylist(search, m_playlistStack, name);
    m_playlistBox->createSearchItem(p, searchCategory);
    setupPlaylist(p, false, 0);
}

800
#include "playlistsplitter.moc"
Nadeem Hasan's avatar
Nadeem Hasan committed
801 802

// vim:ts=8