playlistsplitter.cpp 19.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>
Nadeem Hasan's avatar
Nadeem Hasan committed
20
#include <klineeditdlg.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 "mediafiles.h"
32 33

////////////////////////////////////////////////////////////////////////////////
34
// helper functions
35 36
////////////////////////////////////////////////////////////////////////////////

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

45
////////////////////////////////////////////////////////////////////////////////
46
// public methods
47 48
////////////////////////////////////////////////////////////////////////////////

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

    m_dirWatch = new KDirWatch();

62 63
    setupLayout();
    readConfig();
64 65

    m_editor->slotUpdateCollection();
66
}
67

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

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

79
    QStringList names = m_playlistBox->names();
80 81 82

    int playlistNumber = 1;

83
    // while the list contains more than zero instances of the generated
84 85
    // string...

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

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

96
	return startingWith + " " + QString::number(playlistNumber);
97
    }
98 99
}

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

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

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

130
    return play(i);
131 132
}

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

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

141
    return play(i);
142 143
}

144 145 146 147 148 149
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;
150
    for(PlaylistItemList::Iterator it = list.begin(); it != list.end(); ++it)
151 152 153
        menu->insertItem((*it)->tag()->track(), ++i);
}

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

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

167
    return play(i);
168 169
}

170 171 172 173 174 175 176 177 178
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));
}

179 180
void PlaylistSplitter::stop()
{
181 182
    m_nextPlaylistItem = 0;

183 184 185 186 187
    if(!m_playingItem)
	return;

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

188 189 190
    if(p)
	p->setPlaying(m_playingItem, false);

191
    m_playingItem = 0;
192 193 194 195
}

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

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

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

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

223 224 225 226 227
    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")),
228 229
				  KGuiItem(i18n("Collection"))) == KMessageBox::No)
    {
230
	slotAddToPlaylist(file, m_collection);
231
    }
232
    else
233
	slotAddToPlaylist(file, visiblePlaylist());
234 235
}

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

    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)
247
    {
248
	slotAddToPlaylist(files, m_collection);
249
    }
250
    else
251
	slotAddToPlaylist(files, visiblePlaylist());
252 253 254 255
}

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

261 262 263 264
////////////////////////////////////////////////////////////////////////////////
// public slots
////////////////////////////////////////////////////////////////////////////////

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

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

274
    m_directoryQueue.clear();
275
    m_directoryQueueRemove.clear();
276

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

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

287
	m_directoryList += m_directoryQueue;
288 289 290

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

297
Playlist *PlaylistSplitter::slotCreatePlaylist()
298 299 300
{
    bool ok;

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

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

312
void PlaylistSplitter::slotSelectPlaying()
313
{
314
    if(!m_playingItem)
315 316
	return;

317
    Playlist *l = static_cast<Playlist *>(m_playingItem->listView());
318

319 320
    if(!l)
	return;
321

322
    l->clearSelection();
323 324
    l->setSelected(m_playingItem, true);
    l->ensureItemVisible(m_playingItem);
Nadeem Hasan's avatar
Nadeem Hasan committed
325

326 327
    if(l != visiblePlaylist())
	m_playlistBox->raise(l);
328 329
}

330
void PlaylistSplitter::slotDeleteSelectedItems()
331 332 333
{
    Playlist *p = visiblePlaylist();
    if(p)
334
	p->slotDeleteSelectedItems();
335 336
}

337 338 339 340
void PlaylistSplitter::slotAddToPlaylist(const QString &file, Playlist *list)
{
    KApplication::setOverrideCursor(Qt::waitCursor);
    addImpl(file, list);
341
    list->emitNumberOfItemsChanged();
342
    KApplication::restoreOverrideCursor();
Nadeem Hasan's avatar
Nadeem Hasan committed
343

344 345 346 347 348 349 350 351 352
    if(m_editor)
	m_editor->slotUpdateCollection();
}

void PlaylistSplitter::slotAddToPlaylist(const QStringList &files, Playlist *list)
{
    KApplication::setOverrideCursor(Qt::waitCursor);
    for(QStringList::ConstIterator it = files.begin(); it != files.end(); ++it)
        addImpl(*it, list);
353
    list->emitNumberOfItemsChanged();
354 355 356 357 358 359
    KApplication::restoreOverrideCursor();

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

360 361 362 363 364 365 366
void PlaylistSplitter::slotSetSearchVisible(bool visible)
{
    m_searchWidget->setShown(visible);
    redisplaySearch();
}


367
void PlaylistSplitter::slotGuessTagInfoFile()
368
{
369 370 371 372 373 374 375 376
    visiblePlaylist()->slotGuessTagInfoFile();
    if(m_editor)
        m_editor->slotRefresh();
}

void PlaylistSplitter::slotGuessTagInfoInternet()
{
    visiblePlaylist()->slotGuessTagInfoInternet();
377 378 379 380
    if(m_editor)
        m_editor->slotRefresh();
}

381 382 383 384 385 386 387
void PlaylistSplitter::slotRenameFile()
{
    visiblePlaylist()->slotRenameFile();
    if(m_editor)
        m_editor->slotRefresh();
}

388 389 390 391 392 393
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////

void PlaylistSplitter::setupLayout()
{
394 395
    setOpaqueResize(true);

396
    m_playlistBox = new PlaylistBox(this, "playlistBox");
397 398 399 400 401 402

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

404 405
    m_playlistStack = new QWidgetStack(editorSplitter, "playlistStack");
    m_editor = new TagEditor(editorSplitter, "tagEditor");
406 407 408

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

409
    editorSplitter->setResizeMode(m_editor, QSplitter::FollowSizeHint);
410

411
    // Make the connection that will update the selected playlist when a
412 413
    // selection is made in the playlist box.

414
    connect(m_playlistBox, SIGNAL(signalCurrentChanged(const PlaylistList &)),
415
	    this, SLOT(slotChangePlaylist(const PlaylistList &)));
416

417
    connect(m_playlistBox, SIGNAL(signalDoubleClicked()), this, SIGNAL(signalListBoxDoubleClicked()));
418

419
    // Create the collection list; this should always exist.  This has a
420
    // slightly different creation process than normal playlists (since it in
421
    // fact is a subclass) so it is created here rather than by using
422
    // slotCreatePlaylist().
423

424
    CollectionList::initialize(m_playlistStack, m_restore);
425
    m_collection = CollectionList::instance();
426
    setupPlaylist(m_collection, true, "folder_sound", true);
427
    connect(m_collection, SIGNAL(signalCollectionChanged()), m_editor, SLOT(slotUpdateCollection()));
428
    connect(m_collection, SIGNAL(signalRequestPlaylistCreation(const PlaylistItemList &)),
429
	    this, SLOT(slotCreatePlaylist(const PlaylistItemList &)));
430

431 432 433 434

    // Create the search widget -- this must be done after the CollectionList is created.
    m_searchWidget = new SearchWidget(editorSplitter, CollectionList::instance(), "searchWidget");
    editorSplitter->moveToFirst(m_searchWidget);
435
    connect(m_searchWidget, SIGNAL(signalQueryChanged()), this, SLOT(slotShowSearchResults()));
436 437 438
    connect(CollectionList::instance(), SIGNAL(signalVisibleColumnsChanged()),
	    this, SLOT(slotVisibleColumnsChanged()));

439
    // Show the collection on startup.
440
    m_playlistBox->setSelected(0, true);
441 442 443 444
}

void PlaylistSplitter::readConfig()
{
445 446 447 448
    KConfig *config = KGlobal::config();
    { // block for Playlists group
	KConfigGroupSaver saver(config, "Playlists");

449 450 451 452 453 454
	QValueList<int> splitterSizes = config->readIntListEntry("PlaylistSplitterSizes");
	if(splitterSizes.isEmpty()) {
	    splitterSizes.append(100);
	    splitterSizes.append(640);
	}
	setSizes(splitterSizes);
455

456
	if(m_restore) {
457 458 459 460

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

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

462 463 464
	    if(f.open(IO_ReadOnly)) {
		QDataStream s(&f);
		while(!s.atEnd()) {
465
		    Playlist *p = new Playlist(m_playlistStack);
466 467 468 469
		    s >> *p;

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

470
		    if(p->fileName().isEmpty() || !m_playlistFiles.insert(p->fileName()))
471 472 473 474
			setupPlaylist(p);
		    else
			delete p;
		}
475
	    }
476

477
	    m_directoryList = config->readListEntry("DirectoryList");
478
	    QTimer::singleShot(0, this, SLOT(slotScanDirectories()));
479

480
	    connect(m_dirWatch, SIGNAL(dirty(const QString &)),
481
		    this, SLOT(slotDirChanged(const QString &)));
482

483 484
	    QStringList::Iterator it = m_directoryList.begin();
            for(; it != m_directoryList.end(); ++it)
485 486 487
		m_dirWatch->addDir(*it, false, true);

	    m_dirWatch->startScan();
488
	}
489 490 491

	// restore the list of hidden and shown columns

492
	if(m_collection) {
493
	    for(int i = 0; i < m_collection->columns(); i++)
494
		m_columnNames.append(m_collection->columnText(i));
495
	}
496

497
    }
498
}
499 500 501 502

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

504
    // Save the list of open playlists.
Nadeem Hasan's avatar
Nadeem Hasan committed
505

506
    if(m_restore && m_playlistBox) {
507 508 509

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

510 511
	QString playlistsFile = KGlobal::dirs()->saveLocation("appdata") + "playlists";
	QFile f(playlistsFile);
512

513 514 515 516
	if(f.open(IO_WriteOnly)) {

	    QDataStream s(&f);

517
	    PlaylistList l = m_playlistBox->playlists();
518

519 520
	    for(PlaylistList::Iterator it = l.begin(); it != l.end(); it++)
		s << *(*it);
521

522
	    f.close();
523 524 525
	}
	{ // block for Playlists group
	    KConfigGroupSaver saver(config, "Playlists");
526
	    config->writeEntry("DirectoryList", m_directoryList);
527
	    config->writeEntry("SortColumn", m_collection->sortColumn());
528
	    config->writeEntry("PlaylistSplitterSizes", sizes());
529 530
	}
    }
531 532
}

533 534 535 536 537 538 539
void PlaylistSplitter::addImpl(const QString &file, Playlist *list)
{
    processEvents();
    QFileInfo fileInfo(QDir::cleanDirPath(file));
    if(fileInfo.exists()) {
        if(fileInfo.isDir()) {
            QDir dir(fileInfo.filePath());
540
            QStringList dirContents = dir.entryList();
541 542 543 544 545
            for(QStringList::Iterator it = dirContents.begin(); it != dirContents.end(); ++it)
                if(*it != "." && *it != "..")
                    addImpl(fileInfo.filePath() + QDir::separator() + *it, list);
        }
        else {
546
            if(MediaFiles::isMediaFile(file))
547
		list->createItem(fileInfo, QString::null, 0, false);
548
	    else if(MediaFiles::isPlaylistFile(file))
549 550
		openPlaylist(fileInfo.absFilePath());
        }
Nadeem Hasan's avatar
Nadeem Hasan committed
551
    }
552 553
}

554
void PlaylistSplitter::setupPlaylist(Playlist *p, bool raise, const char *icon, bool sortedFirst)
555
{
556 557 558 559 560 561
    connect(p, SIGNAL(signalSelectionChanged(const PlaylistItemList &)),
	    m_editor, SLOT(slotSetItems(const PlaylistItemList &)));
    connect(p, SIGNAL(signalDoubleClicked()),
	    this, SIGNAL(signalDoubleClicked()));
    connect(p, SIGNAL(signalNumberOfItemsChanged(Playlist *)),
	    this, SLOT(slotPlaylistCountChanged(Playlist *)));
562
    connect(p, SIGNAL(signalAboutToRemove(PlaylistItem *)),
563
	    this, SLOT(slotPlaylistItemRemoved(PlaylistItem *)));
564
    connect(p, SIGNAL(signalFilesDropped(const QStringList &, Playlist *)),
565 566 567
	    this, SLOT(slotAddToPlaylist(const QStringList &, Playlist *)));
    connect(p, SIGNAL(signalSetNext(PlaylistItem *)),
	    this, SLOT(slotSetNextItem(PlaylistItem *)));
568

569
    if(icon)
570
	m_playlistBox->createItem(p, icon, raise, sortedFirst);
571

572 573 574 575 576
    if(raise) {
	PlaylistList l;
	l.append(p);
	slotChangePlaylist(l);
    }
577 578
}

579 580 581
Playlist *PlaylistSplitter::openPlaylist(const QString &file)
{
    QFileInfo fileInfo(file);
582 583 584
    if(!fileInfo.exists() ||
       !fileInfo.isFile() ||
       !fileInfo.isReadable() ||
585 586
       m_playlistFiles.insert(fileInfo.absFilePath()))
    {
587
	return 0;
588
    }
589

590
    Playlist *p = new Playlist(file, m_playlistStack, fileInfo.baseName(true).latin1());
591
    setupPlaylist(p);
592
    return p;
593 594
}

595 596 597 598 599 600 601
QString PlaylistSplitter::play(PlaylistItem *item)
{
    stop();

    if(!item)
	return QString::null;

602 603 604 605
    Playlist *p = static_cast<Playlist *>(item->listView());

    p->setPlaying(item, true);

606 607 608 609 610
    m_playingItem = item;

    return item->absFilePath();
}

611 612 613 614 615 616 617 618 619 620
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);
    }
}

621 622 623 624
////////////////////////////////////////////////////////////////////////////////
// private slots
////////////////////////////////////////////////////////////////////////////////

625
void PlaylistSplitter::slotChangePlaylist(const PlaylistList &l)
626
{
627 628
    if(l.isEmpty()) {
	emit signalPlaylistChanged();
629
	return;
630
    }
631

632 633
    Playlist *current = m_dynamicList;

634
    m_nextPlaylistItem = 0;
635 636 637 638
    if(l.count() == 1) {
	m_playlistStack->raiseWidget(l.first());
	m_editor->slotSetItems(playlistSelection());
	m_dynamicList = 0;
639 640 641 642 643

	if(m_searchWidget) {
	    m_searchWidget->setSearch(l.first()->search());
	    redisplaySearch();
	}
644 645
    }
    else {
646
	m_dynamicList = new DynamicPlaylist(l, m_playlistStack, i18n("Dynamic List"));
647 648 649 650 651
	setupPlaylist(m_dynamicList, true, 0);
    }

    if(current)
	delete current;
652 653

    emit signalPlaylistChanged();
654 655
}

656
void PlaylistSplitter::slotPlaylistCountChanged(Playlist *p)
657
{
658 659
    if(p && p == m_playlistStack->visibleWidget())
	emit signalSelectedPlaylistCountChanged(p->childCount());
660 661
}

662
void PlaylistSplitter::slotPlaylistItemRemoved(PlaylistItem *item)
663
{
664 665
    if(item == m_playingItem)
	m_playingItem = 0;
666 667 668

    if(item == m_nextPlaylistItem)
	m_nextPlaylistItem = 0;
669 670
}

671
void PlaylistSplitter::slotCreatePlaylist(const PlaylistItemList &items)
672
{
673 674 675
    if(items.isEmpty())
	return;

676
    Playlist *playlist = slotCreatePlaylist();
677

678
    if(!playlist)
679
        return;
680

681
    playlist->createItems(items);
682 683
}

684
void PlaylistSplitter::slotShowSearchResults()
685 686 687 688
{
    PlaylistList playlists;
    playlists.append(visiblePlaylist());

689
    PlaylistSearch search = m_searchWidget->search(playlists);
690

691 692
    visiblePlaylist()->setSearch(search);
    redisplaySearch();
693 694
}

695 696 697 698 699
void PlaylistSplitter::slotVisibleColumnsChanged()
{
    m_searchWidget->slotUpdateColumns();
    m_searchWidget->slotQueryChanged();
    if(m_searchWidget->searchedColumns(0).count() > 1)
700
        slotShowSearchResults();
701 702
}

703
#include "playlistsplitter.moc"
Nadeem Hasan's avatar
Nadeem Hasan committed
704 705

// vim:ts=8