Commit 6b4b559b authored by Scott Wheeler's avatar Scott Wheeler

Uhh. Fixed stuff. Added features.

svn path=/trunk/kdemultimedia/juk/; revision=179977
parent 7cbf5daf
This diff is collapsed.
......@@ -20,6 +20,7 @@
#include <kdebug.h>
#include "collectionlist.h"
#include "playlistsplitter.h"
////////////////////////////////////////////////////////////////////////////////
// static methods
......@@ -41,16 +42,14 @@ void CollectionList::initialize(QWidget *parent)
// public methods
////////////////////////////////////////////////////////////////////////////////
void CollectionList::add(const QString &item, bool sorted)
QStringList CollectionList::artists() const
{
Playlist::add(item);
emit(collectionChanged());
return(artistList);
}
void CollectionList::add(const QStringList &items, bool sorted)
QStringList CollectionList::albums() const
{
Playlist::add(items);
emit(collectionChanged());
return(albumList);
}
CollectionListItem *CollectionList::lookup(const QString &file)
......@@ -58,21 +57,12 @@ CollectionListItem *CollectionList::lookup(const QString &file)
return(itemsDict.find(file));
}
PlaylistItem *CollectionList::createItem(const QFileInfo &file, bool sorted)
PlaylistItem *CollectionList::createItem(const QFileInfo &file)
{
PlaylistItem *item = new CollectionListItem(file);
}
////////////////////////////////////////////////////////////////////////////////
// public slots
////////////////////////////////////////////////////////////////////////////////
if(itemsDict.find(file.absFilePath()))
return(0);
void CollectionListItem::refresh()
{
refreshImpl();
// This is connected to refreshImpl() for all of the items children.
emit(refreshed());
return(new CollectionListItem(file));
}
////////////////////////////////////////////////////////////////////////////////
......@@ -101,7 +91,8 @@ void CollectionList::contentsDropEvent(QDropEvent *e)
for(KURL::List::Iterator it = urls.begin(); it != urls.end(); it++)
files.append((*it).path());
add(files);
if(PlaylistSplitter::instance())
PlaylistSplitter::instance()->add(files, this);
}
}
}
......@@ -114,12 +105,6 @@ void CollectionList::contentsDragMoveEvent(QDragMoveEvent *e)
e->accept(false);
}
void CollectionList::addImpl(const QString &item)
{
if(!lookup(item))
Playlist::addImpl(item);
}
void CollectionList::addToDict(const QString &file, CollectionListItem *item)
{
itemsDict.replace(file, item);
......@@ -130,6 +115,18 @@ void CollectionList::removeFromDict(const QString &file)
itemsDict.remove(file);
}
void CollectionList::addArtist(const QString &artist)
{
if(artistList.contains(artist) == 0)
artistList.append(artist);
}
void CollectionList::addAlbum(const QString &album)
{
if(albumList.contains(album) == 0)
albumList.append(album);
}
////////////////////////////////////////////////////////////////////////////////
// CollectionListItem public methods
////////////////////////////////////////////////////////////////////////////////
......@@ -161,4 +158,20 @@ void CollectionListItem::addChildItem(PlaylistItem *child)
connect(this, SIGNAL(refreshed()), child, SLOT(refreshImpl()));
}
////////////////////////////////////////////////////////////////////////////////
// CollectionListItem public slots
////////////////////////////////////////////////////////////////////////////////
void CollectionListItem::refresh()
{
refreshImpl();
if(CollectionList::instance()) {
CollectionList::instance()->addArtist(text(ArtistColumn));
CollectionList::instance()->addAlbum(text(AlbumColumn));
}
// This is connected to refreshImpl() for all of the items children.
emit(refreshed());
}
#include "collectionlist.moc"
......@@ -44,13 +44,11 @@ public:
static CollectionList *instance();
static void initialize(QWidget *parent);
virtual void add(const QString &item, bool sorted = true);
virtual void add(const QStringList &items, bool sorted = true);
QStringList artists() const;
QStringList albums() const;
CollectionListItem *lookup(const QString &file);
/** The sorted parameter here is actually ignored. All items inserted into
the collection will be sorted. */
virtual PlaylistItem *createItem(const QFileInfo &file, bool sorted = true);
virtual PlaylistItem *createItem(const QFileInfo &file);
protected:
CollectionList(QWidget *parent = 0);
......@@ -59,23 +57,36 @@ protected:
virtual void contentsDropEvent(QDropEvent *e);
virtual void contentsDragMoveEvent(QDragMoveEvent *e);
virtual void addImpl(const QString &item);
// These methods are used by CollectionListItem, which is a friend class.
void addToDict(const QString &file, CollectionListItem *item);
void removeFromDict(const QString &file);
/** This checks to see if the artist given is in the artist list maintained
by the collection list (for use in autocompletion and the TagEditor
combo boxes), and if it is not, it adds it to the list. */
void addArtist(const QString &artist);
/** This is similar to addArtist(), but is for album names. */
void addAlbum(const QString &album);
private:
static CollectionList *list;
QDict<CollectionListItem> itemsDict;
QStringList artistList;
QStringList albumList;
};
class CollectionListItem : public PlaylistItem
{
friend class Playlist;
friend class CollectionList;
friend class PlaylistItem;
Q_OBJECT
public:
CollectionListItem(const QFileInfo &file);
virtual ~CollectionListItem();
protected:
CollectionListItem(const QFileInfo &file);
void addChildItem(PlaylistItem *child);
public slots:
......
......@@ -16,7 +16,6 @@
***************************************************************************/
#include <klocale.h>
#include <kfiledialog.h>
#include <kiconloader.h>
#include <kcmdlineargs.h>
#include <kdebug.h>
......@@ -24,6 +23,9 @@
#include <qinputdialog.h>
#include "juk.h"
#include "playlist.h"
#include "playlistsplitter.h"
#include "collectionlist.h"
////////////////////////////////////////////////////////////////////////////////
// public members
......@@ -50,20 +52,35 @@ JuK::~JuK()
// private members
////////////////////////////////////////////////////////////////////////////////
void JuK::setupLayout()
{
// automagically save and restore settings
setAutoSaveSettings();
PlaylistSplitter::initialize(this);
splitter = PlaylistSplitter::instance();
setCentralWidget(splitter);
// playlist item activation connection
connect(splitter, SIGNAL(playlistDoubleClicked(QListViewItem *)), this, SLOT(playItem(QListViewItem *)));
splitter->setFocus();
}
void JuK::setupActions()
{
// file menu
KStdAction::open(this, SLOT(openFile()), actionCollection());
(void) new KAction(i18n("Open &Directory..."), "fileopen", 0, this, SLOT(openDirectory()), actionCollection(), "openDirectory");
KStdAction::save(this, SLOT(saveFile()), actionCollection());
(void) new KAction(i18n("Delete"), "edittrash", 0, this, SLOT(remove()), actionCollection(), "remove");
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");
KStdAction::quit(this, SLOT(quit()), actionCollection());
// edit menu
KStdAction::cut(this, SLOT(cut()), actionCollection());
KStdAction::copy(this, SLOT(copy()), actionCollection());
KStdAction::paste(this, SLOT(paste()), actionCollection());
KStdAction::selectAll(this, SLOT(selectAll()), actionCollection());
KStdAction::selectAll(splitter, SLOT(selectAll()), actionCollection());
// view menu
showEditorAction = new KToggleAction(i18n("Show Tag Editor"), 0, actionCollection(), "showEditor");
......@@ -71,12 +88,26 @@ void JuK::setupActions()
KStdAction::redisplay(splitter, SLOT(refresh()), actionCollection());
// play menu
randomPlayAction = new KToggleAction(i18n("Random Play"), 0, actionCollection(), "randomPlay");
playAction = new KAction(i18n("&Play"), "1rightarrow", 0, this, SLOT(playFile()), actionCollection(), "playFile");
pauseAction = new KAction(i18n("P&ause"), "player_pause", 0, this, SLOT(pauseFile()), actionCollection(), "pauseFile");
stopAction = new KAction(i18n("&Stop"), "player_stop", 0, this, SLOT(stopFile()), actionCollection(), "stopFile");
// playlist menu
(void) new KAction(i18n("New Playlist..."), "filenew", 0, splitter, SLOT(createPlaylist()), actionCollection(), "createPlaylist");
new KAction(i18n("New..."), "filenew", 0, splitter, SLOT(createPlaylist()), actionCollection(), "createPlaylist");
new KAction(i18n("Open..."), "fileopen", 0, splitter, SLOT(openPlaylist()), actionCollection(), "openPlaylist");
savePlaylistAction = new KAction(i18n("Save"), "filesave", 0, splitter, SLOT(savePlaylist()), actionCollection(), "savePlaylist");
saveAsPlaylistAction = new KAction(i18n("Save As..."), "filesaveas", 0, splitter, SLOT(saveAsPlaylist()),
actionCollection(), "saveAsPlaylist");
renamePlaylistAction = new KAction(i18n("Rename..."), 0, splitter, SLOT(renamePlaylist()),
actionCollection(), "renamePlaylist");
new KAction(i18n("Duplicate..."), "editcopy", 0, splitter, SLOT(duplicatePlaylist()), actionCollection(), "duplicatePlaylist");
deleteItemPlaylistAction = new KAction(i18n("Delete"), "editdelete", 0, splitter, SLOT(deleteItemPlaylist()), actionCollection(), "deleteItemPlaylist");
playlistChanged(0);
connect(splitter, SIGNAL(playlistChanged(Playlist *)), this, SLOT(playlistChanged(Playlist *)));
// just in the toolbar
sliderAction = new SliderAction(i18n("Track Position"), actionCollection(), "trackPositionAction");
......@@ -88,20 +119,6 @@ void JuK::setupActions()
connect(this, SIGNAL(dockWindowPositionChanged(QDockWindow *)), sliderAction, SLOT(updateOrientation(QDockWindow *)));
}
void JuK::setupLayout()
{
// automagically save and restore settings
setAutoSaveSettings();
splitter = new PlaylistSplitter(this, "playlistSplitter");
setCentralWidget(splitter);
// playlist item activation connection
connect(splitter, SIGNAL(playlistDoubleClicked(QListViewItem *)), this, SLOT(playItem(QListViewItem *)));
splitter->setFocus();
}
void JuK::setupPlayer()
{
trackPositionDragging = false;
......@@ -142,6 +159,10 @@ void JuK::readConfig()
int volume = config->readNumEntry("Volume", sliderAction->getVolumeSlider()->maxValue());
sliderAction->getVolumeSlider()->setValue(volume);
}
if(randomPlayAction) {
bool randomPlay = config->readBoolEntry("RandomPlay", false);
randomPlayAction->setChecked(randomPlay);
}
}
{ // view Settings
KConfigGroupSaver saver(config, "View");
......@@ -158,6 +179,8 @@ void JuK::saveConfig()
KConfigGroupSaver saver(config, "Player");
if(sliderAction && sliderAction->getVolumeSlider())
config->writeEntry("Volume", sliderAction->getVolumeSlider()->value());
if(randomPlayAction)
config->writeEntry("RandomPlay", randomPlayAction->isChecked());
}
{ // view settings
KConfigGroupSaver saver(config, "View");
......@@ -165,31 +188,29 @@ void JuK::saveConfig()
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// private slot definitions
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// private action slot implementations - file menu
////////////////////////////////////////////////////////////////////////////////
void JuK::openFile()
{
QStringList files = KFileDialog::getOpenFileNames(QString::null, "*.mp3|MPEG Audio (*.mp3)");
splitter->open(files);
}
void JuK::openDirectory()
void JuK::playlistChanged(Playlist *list)
{
splitter->open(KFileDialog::getExistingDirectory());
if(!list || list == CollectionList::instance()) {
savePlaylistAction->setEnabled(false);
saveAsPlaylistAction->setEnabled(false);
renamePlaylistAction->setEnabled(false);
deleteItemPlaylistAction->setEnabled(false);
}
else {
savePlaylistAction->setEnabled(true);
saveAsPlaylistAction->setEnabled(true);
renamePlaylistAction->setEnabled(true);
deleteItemPlaylistAction->setEnabled(true);
}
}
void JuK::saveFile()
{
splitter->save();
}
////////////////////////////////////////////////////////////////////////////////
// private action slot implementations - file menu
////////////////////////////////////////////////////////////////////////////////
void JuK::remove()
{
......@@ -227,11 +248,6 @@ void JuK::cut()
splitter->clearSelectedItems();
}
void JuK::selectAll(bool select)
{
splitter->selectAll(select);
}
////////////////////////////////////////////////////////////////////////////////
// player menu
////////////////////////////////////////////////////////////////////////////////
......@@ -283,12 +299,12 @@ void JuK::stopFile()
void JuK::trackPositionSliderClick()
{
trackPositionDragging=true;
trackPositionDragging = true;
}
void JuK::trackPositionSliderRelease()
{
trackPositionDragging=false;
trackPositionDragging = false;
player.seekPosition(sliderAction->getTrackPositionSlider()->value());
}
......@@ -305,20 +321,21 @@ void JuK::pollPlay()
playTimer->stop();
if(player.paused())
pauseFile();
else {
if(playingItem && dynamic_cast<PlaylistItem *>(playingItem->itemBelow())) {
playingItem->setPixmap(0, 0);
playingItem = dynamic_cast<PlaylistItem *>(playingItem->itemBelow());
sliderAction->getTrackPositionSlider()->setValue(0);
player.play(playingItem->absFilePath(), player.getVolume());
if(player.playing()) {
playTimer->start(pollInterval);
playingItem->setPixmap(0, QPixmap(UserIcon("playing")));
}
}
else
stopFile();
}
else if(playingItem) {
PlaylistItem *next = Playlist::nextItem(playingItem, randomPlayAction->isChecked());
if(next) {
playingItem->setPixmap(0, 0);
playingItem = next;
sliderAction->getTrackPositionSlider()->setValue(0);
player.play(playingItem->absFilePath(), player.getVolume());
if(player.playing()) {
playTimer->start(pollInterval);
playingItem->setPixmap(0, QPixmap(UserIcon("playing")));
}
}
}
else
stopFile();
}
else if(!trackPositionDragging)
sliderAction->getTrackPositionSlider()->setValue(player.position());
......@@ -326,7 +343,7 @@ void JuK::pollPlay()
if(player.playing() && float(player.totalTime() - player.currentTime()) < pollInterval * 2)
playTimer->changeInterval(50);
noSeek=false;
noSeek = false;
}
void JuK::setVolume(int volume)
......@@ -366,14 +383,4 @@ void JuK::playItem(PlaylistItem *item)
}
}
void JuK::playTaggerItem(QListViewItem *item)
{
}
void JuK::playTaggerItem(PlaylistItem *item)
{
}
#include "juk.moc"
......@@ -28,10 +28,15 @@
#include <kmainwindow.h>
#include <qtimer.h>
#include <qlistview.h>
#include "slideraction.h"
#include "player.h"
#include "playlistsplitter.h"
class Playlist;
class PlaylistSplitter;
class PlaylistItem;
class JuK : public KMainWindow
{
......@@ -42,8 +47,8 @@ public:
private:
// private methods
void setupActions();
void setupLayout();
void setupActions();
void setupPlayer();
void processArgs();
void readConfig();
......@@ -55,10 +60,16 @@ private:
// actions
KToggleAction *showEditorAction;
SliderAction *sliderAction;
KToggleAction *randomPlayAction;
KAction *playAction;
KAction *pauseAction;
KAction *stopAction;
KAction *savePlaylistAction;
KAction *saveAsPlaylistAction;
KAction *renamePlaylistAction;
KAction *deleteItemPlaylistAction;
QTimer *playTimer;
Player player;
PlaylistItem *playingItem;
......@@ -68,10 +79,9 @@ private:
const static int pollInterval = 800;
private slots:
void playlistChanged(Playlist *list);
// file menu
void openFile();
void openDirectory();
void saveFile();
void remove();
void quit();
......@@ -79,7 +89,6 @@ private slots:
void cut();
void copy() {};
void paste() {};
void selectAll(bool select = true);
// player menu
void playFile();
......@@ -94,8 +103,6 @@ private slots:
void setVolume(int volume);
void playItem(QListViewItem *item);
void playItem(PlaylistItem *item);
void playTaggerItem(QListViewItem *item);
void playTaggerItem(PlaylistItem *item);
};
#endif
......@@ -17,12 +17,20 @@
<Action name="view_redisplay"/>
</Menu>
<Menu name="player"><text>&amp;Player</text>
<Action name="randomPlay"/>
<Separator/>
<Action name="playFile"/>
<Action name="pauseFile"/>
<Action name="stopFile"/>
</Menu>
<Menu name="playlist"><text>Play&amp;list</text>
<Action name="createPlaylist"/>
<Action name="openPlaylist"/>
<Action name="savePlaylist"/>
<Action name="saveAsPlaylist"/>
<Action name="renamePlaylist"/>
<Action name="duplicatePlaylist"/>
<Action name="deleteItemPlaylist"/>
</Menu>
</MenuBar>
......
......@@ -18,7 +18,11 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <kdebug.h>
#include <qdrawutil.h>
#include <qstringlist.h>
#include <qregexp.h>
#include "listboxpixmap.h"
......@@ -27,9 +31,11 @@ class ListBoxPixmap::ListBoxPixmapPrivate
public:
ListBoxPixmapPrivate() {
orientation = Qt::Horizontal;
lineCount = 1;
}
Qt::Orientation orientation;
int lineCount;
};
ListBoxPixmap::ListBoxPixmap(QListBox *listbox, const QPixmap &pixmap)
......@@ -76,7 +82,7 @@ ListBoxPixmap::~ListBoxPixmap()
int ListBoxPixmap::width(const QListBox *listbox) const
{
if(d->orientation == Qt::Horizontal)
QListBoxPixmap::width(listbox);
return QListBoxPixmap::width(listbox);
return listbox->viewport()->width();
}
......@@ -84,9 +90,9 @@ int ListBoxPixmap::width(const QListBox *listbox) const
int ListBoxPixmap::height(const QListBox *listbox) const
{
if(d->orientation == Qt::Horizontal)
QListBoxPixmap::height(listbox);
return QListBoxPixmap::height(listbox);
int min = listbox->fontMetrics().lineSpacing() + pixmap()->height() + 6;
int min = listbox->fontMetrics().lineSpacing() * d->lineCount + pixmap()->height() + 6;
return min;
}
......@@ -103,11 +109,10 @@ void ListBoxPixmap::setOrientation(Qt::Orientation o)
void ListBoxPixmap::paint(QPainter *painter)
{
// Ripped out of Kaplan, which Danimo said was just ripped out of something
// else.
if(d->orientation == Qt::Horizontal) {
QListBoxPixmap::paint(painter);
// If we're using the default orientation, use the default paint method.
if( d->orientation == Qt::Horizontal ) {
QListBoxPixmap::paint( painter );
return;
}
......@@ -119,7 +124,7 @@ void ListBoxPixmap::paint(QPainter *painter)
const QPixmap *pm = pixmap();
if ( !pm->isNull() ) {
int x = (w - pm->width()) / 2;
int x = ( w - pm->width() ) / 2;
x = QMAX( x, margin );
painter->drawPixmap( x, y, *pm );
}
......@@ -127,9 +132,38 @@ void ListBoxPixmap::paint(QPainter *painter)
if ( !text().isEmpty() ) {
QFontMetrics fm = painter->fontMetrics();
y += pm->height() + fm.height() - fm.descent();
int x = (w - fm.width( text() )) / 2;
x = QMAX( x, margin );
painter->drawText( x, y, text() );
QStringList lines;
QString line = text();
while( !line.isEmpty() ) {
int textLength = line.length();
while( textLength > 0 &&
fm.width( line.mid( 0, textLength ).stripWhiteSpace() ) + margin * 2 > w &&
fm.width( line.mid( 0, textLength ).stripWhiteSpace() ) + margin * 2 > pm->width() ) {
int i = line.findRev( QRegExp( "\\W" ), textLength - 1 );
if( i > 0 )
textLength = i;
else
textLength--;
}
lines.append( line.mid( 0, textLength ).stripWhiteSpace() );
line = line.mid( textLength );
}
if( d->lineCount != lines.count() ) {
d->lineCount = lines.count();
listBox()->triggerUpdate( true );
}
for( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it ) {
int x = (w - fm.width( *it )) / 2;
x = QMAX( x, margin );
painter->drawText( x, y, *it );
y += fm.height() - fm.descent();
}
}
// draw sunken
if ( isCurrent() || isSelected() ) {
......
This diff is collapsed.
......@@ -28,8 +28,12 @@
#include <qapplication.h>
#include <qptrlist.h>
#include <stdlib.h>
#include <time.h>
#include "playlist.h"
#include "collectionlist.h"
#include "playlistsplitter.h"
////////////////////////////////////////////////////////////////////////////////
// public members
......@@ -38,8 +42,29 @@
Playlist::Playlist(QWidget *parent, const char *name) : KListView(parent, name)
{
setup();
setAcceptDrops(true);
allowDuplicates = false;
}
Playlist::Playlist(const QFileInfo &playlistFile, QWidget *parent, const char *name) : KListView(parent, name)
{
setup();
QFile file(playlistFile.absFilePath());
file.open(IO_ReadOnly);
QTextStream stream(&file);
while(!stream.atEnd()) {
QString itemName = (stream.readLine()).stripWhiteSpace();
QFileInfo item(itemName);
if(item.isRelative())
item.setFile(QDir::cleanDirPath(playlistFile.dirPath(true) + "/" + itemName));
if(item.exists() && item.isFile() && item.isReadable())
createItem(item);
}
file.close();
}
Playlist::~Playlist()
......@@ -59,31 +84,6 @@ void Playlist::saveAs()
// needs an implementation to write to m3u files
}
void Playlist::add(const QString &item, bool sorted)
{
collectionListChanged = false;
QApplication::setOverrideCursor(Qt::waitCursor);
addImpl(item);
QApplication::restoreOverrideCursor();
if(collectionListChanged)
emit(collectionChanged());
}
void Playlist::add(const QStringList &items, bool sorted)
{
collectionListChanged = false;