Commit 81c845da authored by Scott Wheeler's avatar Scott Wheeler

PlaylistItem and CollectionListItem are no longer QObject. This meant moving

over thier signal and slot code to normal method calls.  This code was pretty
ugly so this actually made things much more clear.

Also this required coming up with a more self contained MusicBrainz confirmation
process, so that's now been moved into MusicBrainzFileQuery.

Fixed a lot of includes along the way and removed a lot of unused cruft...

svn path=/trunk/kdemultimedia/juk/; revision=302745
parent 39a23993
......@@ -24,6 +24,7 @@
#include "collectionlist.h"
#include "splashscreen.h"
#include "stringshare.h"
#include "cache.h"
////////////////////////////////////////////////////////////////////////////////
......@@ -112,6 +113,16 @@ void CollectionList::slotCheckCache()
clearItems(invalidItems);
}
void CollectionList::slotRemoveItem(const QString &file)
{
clearItem(m_itemsDict[file]);
}
void CollectionList::slotRefreshItem(const QString &file)
{
m_itemsDict[file]->refresh();
}
////////////////////////////////////////////////////////////////////////////////
// protected methods
////////////////////////////////////////////////////////////////////////////////
......@@ -166,33 +177,48 @@ void CollectionList::addUnique(UniqueSetType t, const QString &value)
}
////////////////////////////////////////////////////////////////////////////////
// private slots
// CollectionListItem public methods
////////////////////////////////////////////////////////////////////////////////
void CollectionList::slotRemoveItem(const QString &file)
void CollectionListItem::refresh()
{
clearItem(m_itemsDict[file]);
}
CollectionList::instance()->addUnique(CollectionList::Artists, text(ArtistColumn));
CollectionList::instance()->addUnique(CollectionList::Albums, text(AlbumColumn));
CollectionList::instance()->addUnique(CollectionList::Genres, text(GenreColumn));
void CollectionList::slotRefreshItem(const QString &file)
{
m_itemsDict[file]->slotRefresh();
}
int offset = static_cast<Playlist *>(listView())->columnOffset();
int columns = lastColumn() + offset + 1;
data()->local8Bit.resize(columns);
data()->cachedWidths.resize(columns);
////////////////////////////////////////////////////////////////////////////////
// CollectionListItem public slots
////////////////////////////////////////////////////////////////////////////////
for(int i = offset; i < columns; i++) {
int id = i - offset;
if(id != TrackNumberColumn && id != LengthColumn)
{
// All columns other than track num and length need local-encoded data for sorting
void CollectionListItem::slotRefresh()
{
slotRefreshImpl();
QCString lower = text(i).lower().local8Bit();
CollectionList::instance()->addUnique(CollectionList::Artists, text(ArtistColumn));
CollectionList::instance()->addUnique(CollectionList::Albums, text(AlbumColumn));
CollectionList::instance()->addUnique(CollectionList::Genres, text(GenreColumn));
// For some columns, we may be able to share some strings
if((id == ArtistColumn) || (id == AlbumColumn) ||
(id == GenreColumn) || (id == YearColumn) ||
(id == CommentColumn))
{
lower = StringShare::tryShare(lower);
}
data()->local8Bit[id] = lower;
}
int newWidth = width(listView()->fontMetrics(), listView(), i);
data()->cachedWidths[i] = newWidth;
// This is connected to slotRefreshImpl() for all of the items children.
emit signalRefreshed();
if(newWidth != data()->cachedWidths[i])
playlist()->slotWeightDirty(i);
}
repaint();
playlist()->emitDataChanged();
}
////////////////////////////////////////////////////////////////////////////////
......@@ -201,6 +227,7 @@ void CollectionListItem::slotRefresh()
CollectionListItem::CollectionListItem(const QFileInfo &info, const QString &path) :
PlaylistItem(CollectionList::instance()),
m_shuttingDown(false),
m_path(path)
{
CollectionList *l = CollectionList::instance();
......@@ -210,8 +237,7 @@ CollectionListItem::CollectionListItem(const QFileInfo &info, const QString &pat
setFile(FileHandle(info, path));
if(file().tag()) {
slotRefresh();
connect(this, SIGNAL(signalRefreshed()), l, SIGNAL(signalDataChanged()));
refresh();
l->emitCountChanged();
// l->addWatched(m_path);
}
......@@ -227,6 +253,15 @@ CollectionListItem::CollectionListItem(const QFileInfo &info, const QString &pat
CollectionListItem::~CollectionListItem()
{
m_shuttingDown = true;
for(PlaylistItemList::ConstIterator it = m_children.begin();
it != m_children.end();
++it)
{
delete *it;
}
CollectionList *l = CollectionList::instance();
if(l) {
QString path = Playlist::resolveSymLinks(file().absFilePath());
......@@ -237,8 +272,13 @@ CollectionListItem::~CollectionListItem()
void CollectionListItem::addChildItem(PlaylistItem *child)
{
connect(child, SIGNAL(signalRefreshed()), this, SLOT(slotRefresh()));
connect(this, SIGNAL(signalRefreshed()), child, SLOT(slotRefreshImpl()));
m_children.append(child);
}
void CollectionListItem::removeChildItem(PlaylistItem *child)
{
if(!m_shuttingDown)
m_children.remove(child);
}
bool CollectionListItem::checkCurrent()
......@@ -248,7 +288,7 @@ bool CollectionListItem::checkCurrent()
if(!file().current()) {
file().refresh();
slotRefresh();
refresh();
}
return true;
......
......@@ -82,6 +82,9 @@ public slots:
virtual void clear();
void slotCheckCache();
void slotRemoveItem(const QString &file);
void slotRefreshItem(const QString &file);
protected:
CollectionList(QWidget *parent);
virtual ~CollectionList();
......@@ -114,10 +117,6 @@ signals:
*/
void signalVisibleColumnsChanged();
private slots:
void slotRemoveItem(const QString &file);
void slotRefreshItem(const QString &file);
private:
/**
* Just the size of the above enum to keep from hard coding it in several
......@@ -133,7 +132,7 @@ private:
QValueVector<QString> m_uniqueSetLast;
};
class CollectionListItem : public PlaylistItem
class CollectionListItem : /* public QObject, */ public PlaylistItem
{
friend class Playlist;
friend class CollectionList;
......@@ -144,16 +143,17 @@ class CollectionListItem : public PlaylistItem
*/
friend class QDict<CollectionListItem>;
Q_OBJECT
// Q_OBJECT
public slots:
virtual void slotRefresh();
public:
virtual void refresh();
protected:
CollectionListItem(const QFileInfo &file, const QString &path);
virtual ~CollectionListItem();
void addChildItem(PlaylistItem *child);
void removeChildItem(PlaylistItem *child);
/**
* This slot, called from a QTimer::singleShot() set in the constructor, allows for
......@@ -169,7 +169,9 @@ protected:
virtual CollectionListItem *collectionItem() { return this; }
private:
bool m_shuttingDown;
QString m_path;
PlaylistItemList m_children;
};
#endif
......@@ -8,6 +8,7 @@
*/
#include "filerenamer.h"
#include "playlistitem.h"
#include "tag.h"
#include <kapplication.h>
#include <kconfig.h>
......
......@@ -15,6 +15,8 @@
* *
***************************************************************************/
#include <config.h>
#include <kcmdlineargs.h>
#include <kstatusbar.h>
#include <kdebug.h>
......
// musicbrainzquery.cpp
//
// Copyright (C) 2003 Zack Rusin <zack@kde.org>
// Copyright (C) 2003 - 2004 Zack Rusin <wheeler@kde.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
......@@ -22,7 +23,13 @@
#if HAVE_MUSICBRAINZ
#include "musicbrainzquery.h"
#include "trackpickerdialog.h"
#include "collectionlist.h"
#include "tag.h"
#include <kmainwindow.h>
#include <kapplication.h>
#include <kstatusbar.h>
#include <kprocess.h>
#include <klocale.h>
#include <kdeversion.h>
......@@ -297,6 +304,61 @@ void MusicBrainzQuery::slotTrmGenerationFinished(KProcess *process)
slotQuery();
}
////////////////////////////////////////////////////////////////////////////////
// MusicBrainzFileQuery
////////////////////////////////////////////////////////////////////////////////
MusicBrainzFileQuery::MusicBrainzFileQuery(const FileHandle &file) :
MusicBrainzQuery(MusicBrainzQuery::File, file.absFilePath()),
m_file(file)
{
connect(this, SIGNAL(signalDone(const MusicBrainzQuery::TrackList &)),
this, SLOT(slotDone(const MusicBrainzQuery::TrackList &)));
KMainWindow *w = static_cast<KMainWindow *>(kapp->mainWidget());
connect(this, SIGNAL(signalStatusMsg(const QString &, int)),
w->statusBar(), SLOT(message(const QString &, int)));
start();
}
void MusicBrainzFileQuery::slotDone(const MusicBrainzQuery::TrackList &result)
{
KMainWindow *w = static_cast<KMainWindow *>(kapp->mainWidget());
if(result.isEmpty()) {
w->statusBar()->message(i18n("No matches found."), 2000);
return;
}
TrackPickerDialog *trackPicker =
new TrackPickerDialog(m_file.absFilePath(), result, w);
if(trackPicker->exec() != QDialog::Accepted) {
w->statusBar()->message(i18n("Canceled."), 2000);
return;
}
MusicBrainzQuery::Track track = trackPicker->selectedTrack();
if(!track.name.isEmpty())
m_file.tag()->setTitle(track.name);
if(!track.artist.isEmpty())
m_file.tag()->setArtist(track.artist);
if(!track.album.isEmpty())
m_file.tag()->setAlbum(track.album);
if(track.number)
m_file.tag()->setTrack(track.number);
m_file.tag()->save();
CollectionList::instance()->slotRefreshItem(m_file.absFilePath());
w->statusBar()->message(i18n("Done."), 2000);
deleteLater();
}
#include "musicbrainzquery.moc"
#endif
// musicbrainzquery.h
//
// Copyright (C) 2003 Zack Rusin <zack@kde.org>
// Copyright (C) 2003 - 2004 Scott Wheeler <wheeler@kde.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
......@@ -28,6 +29,8 @@
#include <qobject.h>
#include <qstringlist.h>
#include "filehandle.h"
class KProcess;
/**
......@@ -127,6 +130,24 @@ private:
bool m_tracks; //if only tracks should be extracted
};
/**
*
*/
class MusicBrainzFileQuery : public MusicBrainzQuery
{
Q_OBJECT
public:
MusicBrainzFileQuery(const FileHandle &file);
public slots:
void slotDone(const MusicBrainzQuery::TrackList &result);
private:
FileHandle m_file;
};
#endif
#endif
......@@ -44,6 +44,7 @@
#include "collectionlist.h"
#include "filerenamer.h"
#include "actioncollection.h"
#include "tag.h"
////////////////////////////////////////////////////////////////////////////////
// Playlist::SharedSettings definition
......@@ -301,7 +302,8 @@ void Playlist::clearItem(PlaylistItem *item, bool emitChanged)
m_members.remove(item->file().absFilePath());
if(!m_randomList.isEmpty() && !m_visibleChanged)
m_randomList.remove(item);
item->deleteLater();
// item->deleteLater();
delete item;
if(emitChanged)
emit signalCountChanged(this);
}
......@@ -533,7 +535,7 @@ void Playlist::slotRefresh()
KApplication::setOverrideCursor(Qt::waitCursor);
int j = 0;
for(PlaylistItemList::Iterator it = l.begin(); it != l.end(); ++it) {
(*it)->slotRefreshFromDisk();
(*it)->refreshFromDisk();
if(!(*it)->file().tag()) {
kdDebug(65432) << "Error while trying to refresh the tag. "
......@@ -1375,7 +1377,7 @@ void Playlist::editTag(PlaylistItem *item, const QString &text, int column)
}
item->file().tag()->save();
item->slotRefresh();
item->refresh();
}
void Playlist::slotInlineEditDone(QListViewItem *, const QString &, int column)
......
......@@ -295,6 +295,8 @@ public:
*/
void applySharedSettings();
void emitDataChanged() { emit signalDataChanged(); }
public slots:
/**
* Remove the currently selected items from the playlist and disk.
......@@ -682,7 +684,6 @@ ItemType *Playlist::createItem(const QFileInfo &file, const QString &absFilePath
m_randomList.append(i);
emit signalCountChanged(this);
connect(item, SIGNAL(signalAboutToDelete()), i, SLOT(slotClear()));
if(emitChanged)
emit signalCountChanged(this);
......@@ -709,7 +710,6 @@ void Playlist::createItems(const QValueList<SiblingType *> &siblings)
setupItem(newItem);
if(!m_randomList.isEmpty() && !m_visibleChanged)
m_randomList.append(newItem);
connect((*it)->collectionItem(), SIGNAL(signalAboutToDelete()), newItem, SLOT(slotClear()));
}
}
......
......@@ -15,15 +15,21 @@
* *
***************************************************************************/
#include <kstatusbar.h>
#include <kmainwindow.h>
#include <klocale.h>
#include <kdebug.h>
#include "playlistitem.h"
#include "collectionlist.h"
#include "trackpickerdialog.h"
#include "stringshare.h"
#include "musicbrainzquery.h"
#include "tag.h"
static void startMusicBrainzQuery(const FileHandle &file)
{
#if HAVE_MUSICBRAINZ
new MusicBrainzFileQuery(file);
#else
Q_UNUSED(file)
#endif
}
////////////////////////////////////////////////////////////////////////////////
// PlaylistItem public methods
......@@ -31,13 +37,13 @@
PlaylistItem::~PlaylistItem()
{
emit signalAboutToDelete();
m_collectionItem->removeChildItem(this);
}
void PlaylistItem::setFile(const FileHandle &file)
{
d->fileHandle = file;
slotRefresh();
refresh();
}
FileHandle PlaylistItem::file() const
......@@ -89,7 +95,7 @@ void PlaylistItem::setText(int column, const QString &text)
}
KListViewItem::setText(column, text);
emit signalColumnWidthChanged(column);
playlist()->slotWeightDirty(column);
}
void PlaylistItem::setSelected(bool selected)
......@@ -117,28 +123,13 @@ void PlaylistItem::guessTagInfo(TagGuesser::Type type)
d->fileHandle.tag()->setComment(guesser.comment());
d->fileHandle.tag()->save();
slotRefresh();
refresh();
break;
}
case TagGuesser::MusicBrainz:
{
#if HAVE_MUSICBRAINZ
MusicBrainzQuery *query = new MusicBrainzQuery(MusicBrainzQuery::File,
d->fileHandle.absFilePath());
connect(query, SIGNAL(signalDone(const MusicBrainzQuery::TrackList &)),
SLOT(slotTagGuessResults(const MusicBrainzQuery::TrackList &)));
KMainWindow *win = dynamic_cast<KMainWindow *>(kapp->mainWidget());
if(win)
connect(query, SIGNAL(signalStatusMsg(const QString &, int)),
win->statusBar(), SLOT(message(const QString &, int)));
else
kdWarning(65432) << "Could not find the main window." << endl;
query->start();
#endif //add message box telling users musicbrainz is not installed or keep it quiet?
startMusicBrainzQuery(d->fileHandle);
break;
}
}
}
Playlist *PlaylistItem::playlist() const
......@@ -151,25 +142,19 @@ QValueVector<int> PlaylistItem::cachedWidths() const
return d->cachedWidths;
}
////////////////////////////////////////////////////////////////////////////////
// PlaylistItem public slots
////////////////////////////////////////////////////////////////////////////////
void PlaylistItem::slotRefresh()
void PlaylistItem::refresh()
{
// This signal will be received by the "parent" CollectionListItem which will
// in turn call slotRefreshImpl() for all of its children, including this item.
emit signalRefreshed();
m_collectionItem->refresh();
repaint();
}
void PlaylistItem::slotRefreshFromDisk()
void PlaylistItem::refreshFromDisk()
{
d->fileHandle.refresh();
slotRefresh();
refresh();
}
void PlaylistItem::slotClear()
void PlaylistItem::clear()
{
static_cast<Playlist *>(listView())->clearItem(this);
}
......@@ -179,26 +164,30 @@ void PlaylistItem::slotClear()
////////////////////////////////////////////////////////////////////////////////
PlaylistItem::PlaylistItem(CollectionListItem *item, Playlist *parent) :
QObject(parent), KListViewItem(parent),
d(0), m_playing(false)
KListViewItem(parent),
d(0),
m_playing(false)
{
setup(item, parent);
setup(item);
}
PlaylistItem::PlaylistItem(CollectionListItem *item, Playlist *parent, QListViewItem *after) :
QObject(parent), KListViewItem(parent, after),
d(0), m_playing(false)
KListViewItem(parent, after),
d(0),
m_playing(false)
{
setup(item, parent);
setup(item);
}
// This constructor should only be used by the CollectionList subclass.
PlaylistItem::PlaylistItem(CollectionList *parent) :
QObject(parent), KListViewItem(parent),
d(new Data), m_collectionItem(static_cast<CollectionListItem *>(this)), m_playing(false)
KListViewItem(parent),
m_playing(false)
{
d = new Data;
m_collectionItem = static_cast<CollectionListItem *>(this);
setDragEnabled(true);
}
......@@ -296,105 +285,15 @@ bool PlaylistItem::isValid() const
return bool(d->fileHandle.tag());
}
////////////////////////////////////////////////////////////////////////////////
// PlaylistItem protected slots
////////////////////////////////////////////////////////////////////////////////
void PlaylistItem::slotRefreshImpl()
{
int offset = static_cast<Playlist *>(listView())->columnOffset();
int columns = lastColumn() + offset + 1;
d->local8Bit.resize(columns);
d->cachedWidths.resize(columns);
for(int i = offset; i < columns; i++) {
int id = i - offset;
if(id != TrackNumberColumn && id != LengthColumn)
{
// All columns other than track num and length need local-encoded data for sorting
QCString lower = text(i).lower().local8Bit();
// For some columns, we may be able to share some strings
if((id == ArtistColumn) || (id == AlbumColumn) ||
(id == GenreColumn) || (id == YearColumn) ||
(id == CommentColumn))
{
lower = StringShare::tryShare(lower);
}
d->local8Bit[id] = lower;
}
int newWidth = width(listView()->fontMetrics(), listView(), i);
d->cachedWidths[i] = newWidth;
if(newWidth != d->cachedWidths[i])
emit signalColumnWidthChanged(i);
}
repaint();
}
void PlaylistItem::slotTagGuessResults(const MusicBrainzQuery::TrackList &res)
{
#if HAVE_MUSICBRAINZ
KMainWindow *win = dynamic_cast<KMainWindow *>(kapp->mainWidget());
if(win && res.isEmpty()) {
win->statusBar()->message(i18n("No matches found."), 2000);
return;
}
TrackPickerDialog *trackPicker = new TrackPickerDialog(d->fileHandle.absFilePath(), res, win);
if(win && trackPicker->exec() != QDialog::Accepted) {
win->statusBar()->message(i18n("Canceled."), 2000);
return;
}
MusicBrainzQuery::Track track = trackPicker->selectedTrack();
if(!track.name.isEmpty())
d->fileHandle.tag()->setTitle(track.name);
if(!track.artist.isEmpty())
d->fileHandle.tag()->setArtist(track.artist);
if(!track.album.isEmpty())
d->fileHandle.tag()->setAlbum(track.album);
if(track.number)
d->fileHandle.tag()->setTrack(track.number);
d->fileHandle.tag()->save();
slotRefresh();
if(win)
win->statusBar()->message(i18n("Done."), 2000);
#else
Q_UNUSED(res)
#endif
}
////////////////////////////////////////////////////////////////////////////////
// PlaylistItem private methods
////////////////////////////////////////////////////////////////////////////////
void PlaylistItem::setup(CollectionListItem *item, Playlist *parent)
void PlaylistItem::setup(CollectionListItem *item)
{
m_collectionItem = item;
d = item->d;
item->addChildItem(this);
slotRefreshImpl();
connect(this, SIGNAL(