Commit 70fb715d authored by Scott Wheeler's avatar Scott Wheeler

Made the PlaylistSplitter mostly a propper mediator. There's a second half

to this process that will come in a few days...

svn path=/trunk/kdemultimedia/juk/; revision=193493
parent 11dbf250
......@@ -36,7 +36,6 @@
class AudioData
{
public:
AudioData(const char* filein);
virtual ~AudioData();
......@@ -54,7 +53,6 @@ public:
bool getResult() const;
private:
bool success;
char* fileglob;
int length;
......
......@@ -18,7 +18,6 @@
#ifndef CACHE_H
#define CACHE_H
#include <qstring.h>
#include <qdict.h>
#include "tag.h"
......
......@@ -42,6 +42,7 @@ class CollectionList : public Playlist
friend class CollectionListItem;
Q_OBJECT
public:
static CollectionList *instance();
static void initialize(PlaylistSplitter *s, QWidget *parent, bool restoreOnLoad = true);
......@@ -93,12 +94,12 @@ class CollectionListItem : public PlaylistItem
public:
virtual ~CollectionListItem();
public slots:
virtual void refresh();
protected:
CollectionListItem(const QFileInfo &file);
void addChildItem(PlaylistItem *child);
public slots:
virtual void refresh();
};
#endif
......@@ -15,6 +15,8 @@
* *
***************************************************************************/
#include <ktoolbar.h>
#include "customaction.h"
////////////////////////////////////////////////////////////////////////////////
......
......@@ -19,9 +19,7 @@
#define CUSTOMACTION_H
#include <kaction.h>
#include <ktoolbar.h>
#include <qstring.h>
#include <qobject.h>
// Many months after writing this, despite having felt rather clever at the time
......@@ -44,12 +42,11 @@ protected:
QWidget *customWidget;
KToolBar *toolbar;
private:
virtual QWidget *createWidget(QWidget *parent) = 0;
signals:
void pluggedIn(QWidget *parent);
private:
virtual QWidget *createWidget(QWidget *parent) = 0;
};
#endif
......@@ -19,7 +19,6 @@
#define GENRELIST_H
#include <qvaluelist.h>
#include <qstring.h>
#include <qvaluevector.h>
#include "genre.h"
......
......@@ -27,6 +27,7 @@ class GenreList;
class GenreListEditor : public GenreListEditorBase
{
Q_OBJECT
public:
GenreListEditor(QWidget *parent = 0, const char *name = 0);
~GenreListEditor();
......@@ -36,11 +37,12 @@ private:
void loadLists();
void updateGenreList();
QDict<GenreList> listDict;
private slots:
virtual void updateGenreBoxes(QListViewItem *item);
virtual void updateGenreName(const QString &name);
private:
QDict<GenreList> listDict;
};
#endif
......@@ -15,9 +15,10 @@
* *
***************************************************************************/
#include "kdebug.h"
#include <kdebug.h>
#include "genrelistreader.h"
#include "genrelist.h"
////////////////////////////////////////////////////////////////////////////////
// public members
......
......@@ -20,7 +20,7 @@
#include <qxml.h>
#include "genrelist.h"
class GenreList;
/**
* A SAX2 based XML reader to read GenreLists. Since there's little use to keep
......
......@@ -23,12 +23,12 @@
#include <kconfig.h>
#include <kdebug.h>
#include <qtimer.h>
#include <qlistview.h>
#include <qinputdialog.h>
#include <qslider.h>
#include "juk.h"
#include "playlist.h"
#include "playlistsplitter.h"
#include "collectionlist.h"
#include "slideraction.h"
#include "cache.h"
#include "statuslabel.h"
......@@ -71,7 +71,8 @@ void JuK::setupLayout()
setCentralWidget(splitter);
// playlist item activation connection
connect(splitter, SIGNAL(playlistDoubleClicked(QListViewItem *)), this, SLOT(playItem(QListViewItem *)));
connect(splitter, SIGNAL(doubleClicked()), this, SLOT(playSelectedFile()));
connect(splitter, SIGNAL(listBoxDoubleClicked()), this, SLOT(playFirstFile()));
// create status bar
statusLabel = new StatusLabel(statusBar());
......@@ -79,6 +80,8 @@ void JuK::setupLayout()
connect(splitter, SIGNAL(selectedPlaylistCountChanged(int)), statusLabel, SLOT(setPlaylistCount(int)));
updatePlaylistInfo();
splitter->setFocus();
}
......@@ -88,11 +91,11 @@ void JuK::setupActions()
KStdAction::open(splitter, SLOT(open()), actionCollection());
new KAction(i18n("Open &Directory..."), "fileopen", 0, splitter, SLOT(openDirectory()), actionCollection(), "openDirectory");
KStdAction::save(splitter, SLOT(save()), actionCollection());
new KAction(i18n("Delete"), "editdelete", 0, this, SLOT(remove()), actionCollection(), "remove");
new KAction(i18n("Delete"), "editdelete", 0, splitter, SLOT(removeSelectedItems()), actionCollection(), "remove");
KStdAction::quit(this, SLOT(quit()), actionCollection());
// edit menu
KStdAction::cut(this, SLOT(cut()), actionCollection());
KStdAction::cut(splitter, SLOT(clearSelectedItems()), actionCollection());
KStdAction::copy(this, SLOT(copy()), actionCollection());
KStdAction::paste(this, SLOT(paste()), actionCollection());
KStdAction::selectAll(splitter, SLOT(selectAll()), actionCollection());
......@@ -127,8 +130,7 @@ void JuK::setupActions()
restoreOnLoadAction = new KToggleAction(i18n("Restored Playlists on Load"), 0, actionCollection(), "restoreOnLoad");
new KAction(i18n("Genre List Editor"), 0, this, SLOT(showGenreListEditor()), actionCollection(), "showGenreListEditor");
playlistChanged(0);
connect(splitter, SIGNAL(playlistChanged(Playlist *)), this, SLOT(playlistChanged(Playlist *)));
connect(splitter, SIGNAL(playlistChanged()), this, SLOT(playlistChanged()));
// just in the toolbar
......@@ -143,8 +145,6 @@ void JuK::setupActions()
void JuK::setupPlayer()
{
playingItem = 0;
trackPositionDragging = false;
noSeek = false;
pauseAction->setEnabled(false);
......@@ -247,9 +247,9 @@ bool JuK::queryClose()
// private slot definitions
////////////////////////////////////////////////////////////////////////////////
void JuK::playlistChanged(Playlist *list)
void JuK::playlistChanged()
{
if(!list || list == CollectionList::instance()) {
if(splitter->collectionListSelected()) {
savePlaylistAction->setEnabled(false);
saveAsPlaylistAction->setEnabled(false);
renamePlaylistAction->setEnabled(false);
......@@ -267,52 +267,18 @@ void JuK::playlistChanged(Playlist *list)
void JuK::updatePlaylistInfo()
{
statusLabel->setPlaylistName(splitter->selectedPlaylistName());
statusLabel->setPlaylistCount(splitter->selectedPlaylistCount());
statusLabel->setPlaylistInfo(splitter->selectedPlaylistName(), splitter->selectedPlaylistCount());
}
////////////////////////////////////////////////////////////////////////////////
// private action slot implementations - file menu
////////////////////////////////////////////////////////////////////////////////
void JuK::remove()
{
PlaylistItemList items(splitter->playlistSelection());
PlaylistItem *item = items.first();
while(item) {
if(item == playingItem)
playingItem = 0;
item = items.next();
}
splitter->remove();
}
void JuK::quit()
{
// delete(this);
// kapp->quit();
close();
}
////////////////////////////////////////////////////////////////////////////////
// edit menu
////////////////////////////////////////////////////////////////////////////////
void JuK::cut()
{
PlaylistItemList items = splitter->playlistSelection();
PlaylistItem *item = items.first();
while(item) {
if(item == playingItem)
playingItem = 0;
item = items.next();
}
splitter->clearSelectedItems();
}
////////////////////////////////////////////////////////////////////////////////
// player menu
////////////////////////////////////////////////////////////////////////////////
......@@ -333,13 +299,8 @@ void JuK::playFile()
}
else if(player.playing())
player.seekPosition(0);
else if(splitter) {
PlaylistItemList items = splitter->playlistSelection();
if(items.count() > 0)
playItem(items.at(0));
else
playItem(splitter->playlistFirstItem());
}
else
playFile(splitter->playNextFile(randomPlayAction->isChecked()));
}
void JuK::pauseFile()
......@@ -353,30 +314,28 @@ void JuK::stopFile()
{
playTimer->stop();
player.stop();
pauseAction->setEnabled(false);
stopAction->setEnabled(false);
backAction->setEnabled(false);
forwardAction->setEnabled(false);
sliderAction->getTrackPositionSlider()->setValue(0);
sliderAction->getTrackPositionSlider()->setEnabled(false);
if(playingItem)
playingItem->setPixmap(0, 0);
playingItem = 0;
splitter->stop();
statusLabel->clear();
}
void JuK::backFile()
{
PlaylistItem *i = Playlist::previousItem(playingItem, randomPlayAction->isChecked());
if(i)
playItem(i);
playFile(splitter->playPreviousFile(randomPlayAction->isChecked()));
}
void JuK::forwardFile()
{
PlaylistItem *i = Playlist::nextItem(playingItem, randomPlayAction->isChecked());
playItem(i);
playFile(splitter->playNextFile(randomPlayAction->isChecked()));
}
////////////////////////////////////////////////////////////////////////////////
......@@ -410,36 +369,41 @@ void JuK::trackPositionSliderUpdate(int position)
player.seekPosition(position);
}
// This method is called when the play timer has expired.
void JuK::pollPlay()
{
// Our locking mechanism. Since this method adjusts the play slider, we
// want to make sure that our adjustments
noSeek = true;
if(!player.playing()) {
playTimer->stop();
if(player.paused())
pauseFile();
else if(playingItem) {
PlaylistItem *next = Playlist::nextItem(playingItem, randomPlayAction->isChecked());
playingItem->setPixmap(0, 0);
if(!player.paused()) {
QString nextFile = splitter->playNextFile();
if(!nextFile.isEmpty()) {
if(next) {
playingItem = next;
backAction->setEnabled(true);
sliderAction->getTrackPositionSlider()->setValue(0);
player.play(playingItem->absFilePath(), player.getVolume());
if(player.playing()) {
player.play(nextFile, player.getVolume());
// Check to make sure that the file actually starts playing.
if(player.playing())
playTimer->start(pollInterval);
playingItem->setPixmap(0, QPixmap(UserIcon("playing")));
}
else
stopFile();
}
statusLabel->setPlayingItem(playingItem);
else
stopFile();
}
else
stopFile();
}
else if(!trackPositionDragging) {
sliderAction->getTrackPositionSlider()->setValue(player.position());
......@@ -452,7 +416,7 @@ void JuK::pollPlay()
// last interval, we want to check a lot -- to figure out that we've hit the
// end of the song as soon as possible.
if(player.playing() && float(player.totalTime() - player.currentTime()) < pollInterval * 2)
if(player.playing() && player.totalTime() > 0 && float(player.totalTime() - player.currentTime()) < pollInterval * 2)
playTimer->changeInterval(50);
noSeek = false;
......@@ -468,37 +432,25 @@ void JuK::setVolume(int volume)
}
}
void JuK::playItem(QListViewItem *item)
{
playItem(dynamic_cast<PlaylistItem *>(item));
}
void JuK::playItem(PlaylistItem *item)
void JuK::playFile(const QString &file)
{
if(player.playing() || player.paused())
stopFile();
if(item) {
float volume = float(sliderAction->getVolumeSlider()->value()) / float(sliderAction->getVolumeSlider()->maxValue());
player.play(item->absFilePath(), volume);
// Make sure that the player actually starts before doing anything.
if(player.playing()) {
pauseAction->setEnabled(true);
stopAction->setEnabled(true);
float volume = float(sliderAction->getVolumeSlider()->value()) / float(sliderAction->getVolumeSlider()->maxValue());
player.play(file, volume);
backAction->setEnabled(true);
forwardAction->setEnabled(true);
// Make sure that the player actually starts before doing anything.
playingItem = item;
if(player.playing()) {
pauseAction->setEnabled(true);
stopAction->setEnabled(true);
backAction->setEnabled(true);
forwardAction->setEnabled(true);
sliderAction->getTrackPositionSlider()->setEnabled(true);
playTimer->start(pollInterval);
sliderAction->getTrackPositionSlider()->setEnabled(true);
item->setPixmap(0, QPixmap(UserIcon("playing")));
playTimer->start(pollInterval);
statusLabel->setPlayingItem(item);
}
statusLabel->setPlayingItemInfo(splitter->playingTrack(), splitter->playingArtist(), splitter->playingList());
}
}
......
......@@ -22,32 +22,30 @@
#include <config.h>
#endif
#include <kapp.h>
#include <kaction.h>
#include <kstdaction.h>
#include <kmainwindow.h>
#include <qtimer.h>
#include <qlistview.h>
#include <qlabel.h>
#include "player.h"
#include "playlistsplitter.h"
class QTimer;
class QListViewItem;
class Playlist;
class PlaylistSplitter;
class PlaylistItem;
class SliderAction;
class StatusLabel;
class JuK : public KMainWindow
{
Q_OBJECT
public:
JuK(QWidget* parent = 0, const char *name = 0);
virtual ~JuK();
private:
// private methods
void setupLayout();
void setupActions();
......@@ -63,47 +61,14 @@ private:
virtual bool queryClose();
// layout objects
PlaylistSplitter *splitter;
StatusLabel *statusLabel;
// actions
KToggleAction *showEditorAction;
KToggleAction *restoreOnLoadAction;
SliderAction *sliderAction;
KToggleAction *randomPlayAction;
KAction *playAction;
KAction *pauseAction;
KAction *stopAction;
KAction *backAction;
KAction *forwardAction;
KAction *savePlaylistAction;
KAction *saveAsPlaylistAction;
KAction *renamePlaylistAction;
KAction *deleteItemPlaylistAction;
QTimer *playTimer;
Player player;
PlaylistItem *playingItem;
bool trackPositionDragging;
bool noSeek;
bool restore;
static const int pollInterval = 800;
private slots:
void playlistChanged(Playlist *list);
void playlistChanged();
void updatePlaylistInfo();
// file menu
void remove();
void quit();
// edit menu
void cut();
void copy() {};
void paste() {};
......@@ -121,17 +86,58 @@ private slots:
void trackPositionSliderClick();
void trackPositionSliderRelease();
void trackPositionSliderUpdate(int position);
/**
* This method is called to check our progress in the playing file. It uses
* playTimer to know when to call itself again.
*/
void pollPlay();
void setVolume(int volume);
/**
* This is just a wrapper around the below method to take a QListViewItem.
* This method is called by the slider to set the volume of the player. Its
* value is relative to the maxValue() of the volume slider.
*/
void playItem(QListViewItem *item);
void setVolume(int volume);
/**
* This is the main method to play stuff. All of the other play related
* members in this class ultimately call this method.
* This is the main method to play stuff. Everything else is just a wrapper
* around this.
*/
void playItem(PlaylistItem *item);
void playFile(const QString &file);
void playSelectedFile() { playFile(splitter->playSelectedFile()); }
void playFirstFile() { playFile(splitter->playFirstFile()); }
private:
// layout objects
PlaylistSplitter *splitter;
StatusLabel *statusLabel;
// actions
KToggleAction *showEditorAction;
KToggleAction *restoreOnLoadAction;
SliderAction *sliderAction;
KToggleAction *randomPlayAction;
KAction *playAction;
KAction *pauseAction;
KAction *stopAction;
KAction *backAction;
KAction *forwardAction;
KAction *savePlaylistAction;
KAction *saveAsPlaylistAction;
KAction *renamePlaylistAction;
KAction *deleteItemPlaylistAction;
QTimer *playTimer;
Player player;
bool trackPositionDragging;
bool noSeek;
bool restore;
static const int pollInterval = 800;
};
#endif
......@@ -20,6 +20,7 @@
#include <kdebug.h>
#include <qpainter.h>
#include <qdrawutil.h>
#include <qstringlist.h>
#include <qregexp.h>
......
......@@ -22,7 +22,8 @@
#define LISTBOXPIXMAP_H
#include <qlistbox.h>
#include <qpainter.h>
class QPainter;
class ListBoxPixmap : public QListBoxPixmap
{
......
......@@ -15,6 +15,7 @@
* *
***************************************************************************/
#include <kapplication.h>
#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <klocale.h>
......
......@@ -218,11 +218,6 @@ PlaylistItemList Playlist::selectedItems() const
return(list);
}
void Playlist::remove()
{
remove(selectedItems());
}
void Playlist::remove(const PlaylistItemList &items)
{
if(isVisible() && !items.isEmpty()) {
......@@ -234,9 +229,9 @@ void Playlist::remove(const PlaylistItemList &items)
QString message;
if(files.count() == 1)
message = i18n("Do you really want to delete this item?");
message = i18n("Do you really want to delete this item from your disk?");
else
message = i18n("Do you really want to delete these %1 items?").arg(QString::number(files.count()));
message = i18n("Do you really want to delete these %1 items from your disk?").arg(QString::number(files.count()));
if(KMessageBox::questionYesNoList(this, message, files) == KMessageBox::Yes) {
for(QPtrListIterator<PlaylistItem> it(items); it.current(); ++it) {
......@@ -257,18 +252,15 @@ PlaylistItem *Playlist::nextItem(PlaylistItem *current, bool random)
return(0);
PlaylistItem *i;
Playlist *list = static_cast<Playlist *>(current->listView());
if(random) {
PlaylistItemList items = list->items();
if(items.count() > 1) {
list->history.push(current);
if(count() > 1) {
history.push(current);
srand(time(0));
i = current;
while(i == current)
i = items.at(rand() % items.count());
i = items().at(rand() % count());
}
else
i = 0;
......@@ -284,10 +276,8 @@ PlaylistItem *Playlist::previousItem(PlaylistItem *current, bool random)
if(!current)
return(0);
Playlist *list = static_cast<Playlist *>(current->listView());
if(random && !list->history.isEmpty())
return(list->history.pop());
if(random && !history.isEmpty())
return(history.pop());
else
return(static_cast<PlaylistItem *>(current->itemAbove()));
}
......@@ -336,6 +326,11 @@ void Playlist::setPlaylistBoxItem(PlaylistBoxItem *item)
boxItem = item;
}
int Playlist::count() const
{
return(childCount());
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
......@@ -446,6 +441,7 @@ void Playlist::setup()
setSorting(1);
connect(this, SIGNAL(selectionChanged()), this, SLOT(emitSelected()));
connect(this, SIGNAL(doubleClicked(QListViewItem *)), this, SLOT(emitDoubleClicked(QListViewItem *)));
addColumn(QString::null);
setResizeMode(QListView::LastColumn);
......@@ -464,4 +460,9 @@ void Playlist::emitSelected()
emit(selectionChanged(selectedItems()));
}
void Playlist::emitDoubleClicked(QListViewItem *)
{
emit(doubleClicked());
}
#include "playlist.moc"
......@@ -73,7 +73,7 @@ public:
/**
* Remove the currently selected items from the playlist.
*/
void remove();
void removeSelectedItems() { remove(selectedItems()); };