Commit 7cbf5daf authored by Scott Wheeler's avatar Scott Wheeler

Yep. More general updates. The context menus on the CollectionListBox

actually do something now.

svn path=/trunk/kdemultimedia/juk/; revision=179471
parent de9543f4
......@@ -41,15 +41,15 @@ void CollectionList::initialize(QWidget *parent)
// public methods
////////////////////////////////////////////////////////////////////////////////
void CollectionList::append(const QString &item)
void CollectionList::add(const QString &item, bool sorted)
{
Playlist::append(item);
Playlist::add(item);
emit(collectionChanged());
}
void CollectionList::append(const QStringList &items)
void CollectionList::add(const QStringList &items, bool sorted)
{
Playlist::append(items);
Playlist::add(items);
emit(collectionChanged());
}
......@@ -58,7 +58,7 @@ CollectionListItem *CollectionList::lookup(const QString &file)
return(itemsDict.find(file));
}
PlaylistItem *CollectionList::createItem(const QFileInfo &file)
PlaylistItem *CollectionList::createItem(const QFileInfo &file, bool sorted)
{
PlaylistItem *item = new CollectionListItem(file);
}
......@@ -101,7 +101,7 @@ void CollectionList::contentsDropEvent(QDropEvent *e)
for(KURL::List::Iterator it = urls.begin(); it != urls.end(); it++)
files.append((*it).path());
append(files);
add(files);
}
}
}
......@@ -114,10 +114,10 @@ void CollectionList::contentsDragMoveEvent(QDragMoveEvent *e)
e->accept(false);
}
void CollectionList::appendImpl(const QString &item)
void CollectionList::addImpl(const QString &item)
{
if(!lookup(item))
Playlist::appendImpl(item);
Playlist::addImpl(item);
}
void CollectionList::addToDict(const QString &file, CollectionListItem *item)
......
......@@ -44,11 +44,13 @@ public:
static CollectionList *instance();
static void initialize(QWidget *parent);
virtual void append(const QString &item);
virtual void append(const QStringList &items);
virtual void add(const QString &item, bool sorted = true);
virtual void add(const QStringList &items, bool sorted = true);
CollectionListItem *lookup(const QString &file);
virtual PlaylistItem *createItem(const QFileInfo &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);
protected:
CollectionList(QWidget *parent = 0);
......@@ -57,7 +59,7 @@ protected:
virtual void contentsDropEvent(QDropEvent *e);
virtual void contentsDragMoveEvent(QDragMoveEvent *e);
virtual void appendImpl(const QString &item);
virtual void addImpl(const QString &item);
void addToDict(const QString &file, CollectionListItem *item);
void removeFromDict(const QString &file);
......
......@@ -55,7 +55,7 @@ void GenreList::load(const QString &file)
QString GenreList::name(int ID3v1)
{
if(hasIndex && ID3v1 >= 0 && ID3v1 < int(index.count()))
if(hasIndex && ID3v1 >= 0 && ID3v1 < int(index.size()))
return(index[ID3v1]);
else
return(QString::null);
......@@ -94,8 +94,8 @@ int GenreList::findIndex(const QString &item)
void GenreList::initializeIndex()
{
index.clear();
index.resize(count());
index.resize(size());
for(GenreList::Iterator it = begin(); it != end(); ++it)
if((*it).getID3v1() >= 0 && (*it).getID3v1() < int(index.count()))
if((*it).getID3v1() >= 0 && (*it).getID3v1() < int(index.size()))
index[(*it).getID3v1()] = QString(*it);
}
......@@ -33,8 +33,8 @@ JuK::JuK(QWidget *parent, const char *name) : KMainWindow(parent, name)
{
// Expect segfaults if you change this order.
setupActions();
setupLayout();
setupActions();
setupPlayer();
readConfig();
processArgs();
......@@ -67,6 +67,8 @@ void JuK::setupActions()
// view menu
showEditorAction = new KToggleAction(i18n("Show Tag Editor"), 0, actionCollection(), "showEditor");
connect(showEditorAction, SIGNAL(toggled(bool)), splitter, SLOT(setEditorVisible(bool)));
KStdAction::redisplay(splitter, SLOT(refresh()), actionCollection());
// play menu
playAction = new KAction(i18n("&Play"), "1rightarrow", 0, this, SLOT(playFile()), actionCollection(), "playFile");
......@@ -74,12 +76,16 @@ void JuK::setupActions()
stopAction = new KAction(i18n("&Stop"), "player_stop", 0, this, SLOT(stopFile()), actionCollection(), "stopFile");
// playlist menu
(void) new KAction(i18n("New Playlist..."), "filenew", 0, this, SLOT(createPlaylist()), actionCollection(), "createPlaylist");
(void) new KAction(i18n("New Playlist..."), "filenew", 0, splitter, SLOT(createPlaylist()), actionCollection(), "createPlaylist");
// just in the toolbar
sliderAction = new SliderAction(i18n("Track Position"), actionCollection(), "trackPositionAction");
createGUI();
// set the slider to the proper orientation and make it stay that way
sliderAction->updateOrientation();
connect(this, SIGNAL(dockWindowPositionChanged(QDockWindow *)), sliderAction, SLOT(updateOrientation(QDockWindow *)));
}
void JuK::setupLayout()
......@@ -89,11 +95,6 @@ void JuK::setupLayout()
splitter = new PlaylistSplitter(this, "playlistSplitter");
setCentralWidget(splitter);
connect(showEditorAction, SIGNAL(toggled(bool)), splitter, SLOT(setEditorVisible(bool)));
// set the slider to the proper orientation and make it stay that way
sliderAction->updateOrientation();
connect(this, SIGNAL(dockWindowPositionChanged(QDockWindow *)), sliderAction, SLOT(updateOrientation(QDockWindow *)));
// playlist item activation connection
connect(splitter, SIGNAL(playlistDoubleClicked(QListViewItem *)), this, SLOT(playItem(QListViewItem *)));
......@@ -108,7 +109,7 @@ void JuK::setupPlayer()
pauseAction->setEnabled(false);
stopAction->setEnabled(false);
playTimer=new QTimer(this);
playTimer = new QTimer(this);
connect(playTimer, SIGNAL(timeout()), this, SLOT(pollPlay()));
if(sliderAction && sliderAction->getTrackPositionSlider() && sliderAction->getVolumeSlider()) {
......@@ -192,7 +193,7 @@ void JuK::saveFile()
void JuK::remove()
{
QPtrList<PlaylistItem> items(splitter->playlistSelection());
PlaylistItemList items(splitter->playlistSelection());
PlaylistItem *item = items.first();
while(item) {
if(item == playingItem)
......@@ -205,7 +206,7 @@ void JuK::remove()
void JuK::quit()
{
delete(this);
kapp->quit();
}
////////////////////////////////////////////////////////////////////////////////
......@@ -214,7 +215,7 @@ void JuK::quit()
void JuK::cut()
{
QPtrList<PlaylistItem> items = splitter->playlistSelection();
PlaylistItemList items = splitter->playlistSelection();
PlaylistItem *item = items.first();
while(item) {
......@@ -247,7 +248,7 @@ void JuK::playFile()
}
}
else if(splitter) {
QPtrList<PlaylistItem> items = splitter->playlistSelection();
PlaylistItemList items = splitter->playlistSelection();
if(items.count() > 0)
playItem(items.at(0));
else
......@@ -276,21 +277,6 @@ void JuK::stopFile()
playingItem->setPixmap(0, 0);
}
////////////////////////////////////////////////////////////////////////////////
// playlist menu
////////////////////////////////////////////////////////////////////////////////
void JuK::createPlaylist()
{
if(splitter) {
bool ok;
QString name = QInputDialog::getText(i18n("New Playlist..."), i18n("Please enter a name for the new playlist:"),
QLineEdit::Normal, splitter->uniquePlaylistName(), &ok);
if(ok)
splitter->createPlaylist(name);
}
}
////////////////////////////////////////////////////////////////////////////////
// additional player slots
////////////////////////////////////////////////////////////////////////////////
......
......@@ -86,9 +86,6 @@ private slots:
void pauseFile();
void stopFile();
// playlist menu
void createPlaylist();
// additional player slots
void trackPositionSliderClick();
void trackPositionSliderRelease();
......
......@@ -11,8 +11,10 @@
<Separator/>
<Action name="file_quit"/>
</Menu>
<Menu name="view"><text>&amp;View</text>
<Menu name="view" noMerge="1"><text>&amp;View</text>
<Action name="showEditor"/>
<Separator/>
<Action name="view_redisplay"/>
</Menu>
<Menu name="player"><text>&amp;Player</text>
<Action name="playFile"/>
......
......@@ -47,32 +47,51 @@ Playlist::~Playlist()
}
void Playlist::append(const QString &item, bool sorted)
void Playlist::save()
{
kdDebug() << "Playlist::save() -- Not yet implemented!" << endl;
// needs an implementation to write to m3u files
}
void Playlist::saveAs()
{
kdDebug() << "Playlist::saveAs() -- Not yet implemented!" << endl;
// needs an implementation to write to m3u files
}
void Playlist::add(const QString &item, bool sorted)
{
collectionListChanged = false;
QApplication::setOverrideCursor(Qt::waitCursor);
appendImpl(item);
addImpl(item);
QApplication::restoreOverrideCursor();
if(collectionListChanged)
emit(collectionChanged());
}
void Playlist::append(const QStringList &items, bool sorted)
void Playlist::add(const QStringList &items, bool sorted)
{
collectionListChanged = false;
QApplication::setOverrideCursor(Qt::waitCursor);
for(QStringList::ConstIterator it = items.begin(); it != items.end(); ++it)
appendImpl(*it);
addImpl(*it);
QApplication::restoreOverrideCursor();
if(collectionListChanged)
emit(collectionChanged());
}
void Playlist::clearItems(const QPtrList<PlaylistItem> &items)
void Playlist::refresh()
{
PlaylistItemList list;
for(PlaylistItem *i = static_cast<PlaylistItem *>(firstChild()); i; i = static_cast<PlaylistItem *>(i->itemBelow()))
i->refreshFromDisk();
}
void Playlist::clearItems(const PlaylistItemList &items)
{
QPtrListIterator<PlaylistItem> it(items);
while(it.current()) {
......@@ -82,13 +101,31 @@ void Playlist::clearItems(const QPtrList<PlaylistItem> &items)
}
}
QPtrList<PlaylistItem> Playlist::selectedItems() const
QStringList Playlist::files() const
{
QPtrList<PlaylistItem> list;
for(PlaylistItem *i = static_cast<PlaylistItem *>(firstChild()); i != 0; i = static_cast<PlaylistItem *>(i->itemBelow())) {
QStringList list;
for(PlaylistItem *i = static_cast<PlaylistItem *>(firstChild()); i; i = static_cast<PlaylistItem *>(i->itemBelow()))
list.append(i->absFilePath());
return(list);
}
PlaylistItemList Playlist::items() const
{
PlaylistItemList list;
for(PlaylistItem *i = static_cast<PlaylistItem *>(firstChild()); i; i = static_cast<PlaylistItem *>(i->itemBelow()))
list.append(i);
return(list);
}
PlaylistItemList Playlist::selectedItems() const
{
PlaylistItemList list;
for(PlaylistItem *i = static_cast<PlaylistItem *>(firstChild()); i; i = static_cast<PlaylistItem *>(i->itemBelow()))
if(i->isSelected())
list.append(i);
}
return(list);
}
......@@ -97,16 +134,16 @@ void Playlist::remove()
remove(selectedItems());
}
void Playlist::remove(const QPtrList<PlaylistItem> &items)
void Playlist::remove(const PlaylistItemList &items)
{
if(isVisible() && !items.isEmpty()) {
QString message = i18n("Are you sure that you want to delete:\n");
for(QPtrListIterator<PlaylistItem> it(items); it.current() != 0; ++it)
for(QPtrListIterator<PlaylistItem> it(items); it.current(); ++it)
message.append(it.current()->fileName() + "\n");
if(KMessageBox::warningYesNo(this, message, i18n("Delete Files")) == KMessageBox::Yes) {
for(QPtrListIterator<PlaylistItem> it(items); it.current() != 0; ++it) {
for(QPtrListIterator<PlaylistItem> it(items); it.current(); ++it) {
if(QFile::remove(it.current()->filePath()))
delete(it.current());
else
......@@ -133,7 +170,7 @@ QStringList &Playlist::getAlbumList()
QDragObject *Playlist::dragObject()
{
QPtrList<PlaylistItem> items = selectedItems();
PlaylistItemList items = selectedItems();
KURL::List urls;
for(PlaylistItem *i = items.first(); i; i = items.next()) {
KURL url;
......@@ -159,7 +196,7 @@ void Playlist::contentsDropEvent(QDropEvent *e)
if(e->source() == this) {
QPtrList<QListViewItem> items = KListView::selectedItems();
for(QPtrListIterator<QListViewItem> it(items); it.current() != 0; ++it) {
for(QPtrListIterator<QListViewItem> it(items); it.current(); ++it) {
(*it)->moveItem(moveAfter);
moveAfter = *it;
}
......@@ -169,12 +206,12 @@ void Playlist::contentsDropEvent(QDropEvent *e)
if(KURLDrag::decode(e, urls) && !urls.isEmpty()) {
QStringList files;
QStringList fileList;
for(KURL::List::Iterator it = urls.begin(); it != urls.end(); it++)
files.append((*it).path());
fileList.append((*it).path());
append(files);
add(fileList);
}
}
}
......@@ -187,22 +224,26 @@ void Playlist::contentsDragMoveEvent(QDragMoveEvent *e)
e->accept(false);
}
PlaylistItem *Playlist::createItem(const QFileInfo &file)
PlaylistItem *Playlist::createItem(const QFileInfo &file, bool sorted)
{
CollectionListItem *item = CollectionList::instance()->lookup(file.absFilePath());
if(item)
return(new PlaylistItem(item, this));
else if(CollectionList::instance()) {
if(!item && CollectionList::instance()) {
item = new CollectionListItem(file);
collectionListChanged = true;
return(new PlaylistItem(item, this));
}
if(item) {
if(sorted && selectedItems().getFirst())
PlaylistItem *newItem = new PlaylistItem(item, this, selectedItems().getFirst());
else
PlaylistItem *newItem = new PlaylistItem(item, this);
}
else
return(0);
}
void Playlist::appendImpl(const QString &item, bool sorted)
void Playlist::addImpl(const QString &item, bool sorted)
{
processEvents();
QFileInfo file(QDir::cleanDirPath(item));
......@@ -212,13 +253,13 @@ void Playlist::appendImpl(const QString &item, bool sorted)
QStringList dirContents=dir.entryList();
for(QStringList::Iterator it = dirContents.begin(); it != dirContents.end(); ++it)
if(*it != "." && *it != "..")
appendImpl(file.filePath() + QDir::separator() + *it);
addImpl(file.filePath() + QDir::separator() + *it);
}
else {
QString extension = file.extension(false);
if(extensions.contains(extension) > 0 && (members.contains(file.absFilePath()) == 0 || allowDuplicates)) {
members.append(file.absFilePath());
(void) createItem(file);
(void) createItem(file, sorted);
}
}
}
......
......@@ -31,17 +31,26 @@ public:
Playlist(QWidget *parent = 0, const char *name = 0);
virtual ~Playlist();
/** Set sorted = false to append the items at the end of the list rather
virtual void save();
virtual void saveAs();
/** Set sorted = false to add the items at the end of the list rather
than adding them into the list in their sorted place. */
virtual void append(const QString &item, bool sorted = true);
virtual void append(const QStringList &items, bool sorted = true);
virtual void add(const QString &item, bool sorted = true);
virtual void add(const QStringList &items, bool sorted = true);
virtual void refresh();
virtual void clearItems(const QPtrList<PlaylistItem> &items);
virtual void clearItems(const PlaylistItemList &items);
QPtrList<PlaylistItem> selectedItems() const;
/** All of the files in the list. */
QStringList files() const;
/** All of the items in the list. */
PlaylistItemList items() const;
PlaylistItemList selectedItems() const;
void remove();
void remove(const QPtrList<PlaylistItem> &items);
void remove(const PlaylistItemList &items);
/** Allow duplicate files in the playlist. */
void setAllowDuplicates(bool allow);
......@@ -61,8 +70,8 @@ protected:
virtual void contentsDragMoveEvent(QDragMoveEvent *e);
/** This is being used as a mini-factory of sorts to make the construction
of PlaylistItems virtual. */
virtual PlaylistItem *createItem(const QFileInfo &file);
virtual void appendImpl(const QString &item, bool sorted = true);
virtual PlaylistItem *createItem(const QFileInfo &file, bool sorted = true);
virtual void addImpl(const QString &item, bool sorted = true);
private:
void setup();
......@@ -91,7 +100,7 @@ signals:
/** This is emitted when the playlist selection is changed. This is used
primarily to notify the TagEditor of the new data. */
void selectionChanged(const QPtrList<PlaylistItem> &selection);
void selectionChanged(const PlaylistItemList &selection);
};
#endif
......@@ -21,23 +21,39 @@
#include <kdebug.h>
#include <qdrawutil.h>
#include <qinputdialog.h>
#include "playlistbox.h"
#include "collectionlist.h"
#include "playlistsplitter.h"
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox public methods
////////////////////////////////////////////////////////////////////////////////
PlaylistBox::PlaylistBox(QWidget *parent, const char *name) : KListBox(parent, name)
PlaylistBox::PlaylistBox(PlaylistSplitter *parent, const char *name) : KListBox(parent, name)
{
splitter = parent;
collectionContextMenu = new KPopupMenu();
collectionContextMenu->insertItem(SmallIcon("editcopy"), i18n("Duplicate..."), this, SLOT(contextDuplicateItem()));
playlistContextMenu = new KPopupMenu();
playlistContextMenu->insertItem(SmallIcon("filesave"), i18n("Save"), this, SLOT(contextSave()));
playlistContextMenu->insertItem(SmallIcon("filesaveas"), i18n("Save As..."), this, SLOT(contextSaveAs()));
playlistContextMenu->insertItem(i18n("Rename..."), this, SLOT(contextRename()));
playlistContextMenu->insertItem(SmallIcon("editcopy"), i18n("Duplicate..."), this, SLOT(contextDuplicateItem()));
playlistContextMenu->insertItem(SmallIcon("editdelete"), i18n("Delete"), this, SLOT(contextDeleteItem()));
setAcceptDrops(true);
connect(this, SIGNAL(currentChanged(QListBoxItem *)), this, SLOT(currentItemChanged(QListBoxItem *)));
connect(this, SIGNAL(currentChanged(QListBoxItem *)),
this, SLOT(currentItemChanged(QListBoxItem *)));
}
PlaylistBox::~PlaylistBox()
{
delete(playlistContextMenu);
}
QStringList PlaylistBox::names() const
......@@ -46,7 +62,7 @@ QStringList PlaylistBox::names() const
}
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox protected methods
// PlaylistBox private methods
////////////////////////////////////////////////////////////////////////////////
void PlaylistBox::resizeEvent(QResizeEvent *e)
......@@ -73,7 +89,7 @@ void PlaylistBox::dropEvent(QDropEvent *e)
PlaylistBoxItem *i = static_cast<PlaylistBoxItem *>(itemAt(e->pos()));
if(i && i->playlist())
i->playlist()->append(files);
i->playlist()->add(files);
}
}
......@@ -84,26 +100,44 @@ void PlaylistBox::dragMoveEvent(QDragMoveEvent *e)
// selected playlist and is not the CollectionList, then accept the event.
//
// Otherwise, do not accept the event.
// At the moment this does not account for dragging from sources outside of
// JuK onto the CollectionList or to the selected PlaylistBoxItem. It makes
// sense to not allow this from the top widget of the QWidgetStack of
// playlists, however, it should allow dragging from other applications, i.e.
// Konq to these PlaylistBoxItems. This just involves checking the source
// in the logic below.
if(KURLDrag::canDecode(e) && itemAt(e->pos())) {
PlaylistBoxItem *i = static_cast<PlaylistBoxItem *>(itemAt(e->pos()));
if(i->playlist() && i->playlist() != CollectionList::instance())
if(selectedItem() && i != selectedItem())
e->accept(true);
// This is a semi-dirty hack to check if the items are coming from within
// JuK. If they are not coming from a Playlist (or subclass) then the
// dynamic_cast will fail and we can safely assume that the item is
// coming from outside of JuK.
if(dynamic_cast<Playlist *>(e->source())) {
if(i->playlist() && i->playlist() != CollectionList::instance())
if(selectedItem() && i != selectedItem())
e->accept(true);
else
e->accept(false);
else
e->accept(false);
else
e->accept(false);
}
else // the dropped items are coming from outside of JuK
e->accept(true);
}
else
e->accept(false);
}
void PlaylistBox::mousePressEvent(QMouseEvent *e)
{
if(e->button() == Qt::RightButton) {
QListBoxItem *i = itemAt(e->pos());
if(i)
drawContextMenu(i, e->globalPos());
e->accept();
}
else {
e->ignore();
QListBox::mousePressEvent(e);
}
}
void PlaylistBox::addName(const QString &name)
......@@ -122,18 +156,87 @@ void PlaylistBox::currentItemChanged(QListBoxItem *item)
emit(currentChanged(i));
}
void PlaylistBox::drawContextMenu(QListBoxItem *item, const QPoint &point)
{
PlaylistBoxItem *i = static_cast<PlaylistBoxItem *>(item);
contextMenuOn = i;
if(i)
if(i->playlist() == CollectionList::instance())
collectionContextMenu->popup(point);
else
playlistContextMenu->popup(point);
}
void PlaylistBox::contextSave()
{
if(contextMenuOn)
contextMenuOn->playlist()->save();
}
void PlaylistBox::contextSaveAs()
{
if(contextMenuOn)
contextMenuOn->playlist()->saveAs();
}
void PlaylistBox::contextRename()
{
if(contextMenuOn) {
bool ok;
QString name = QInputDialog::getText(i18n("Rename..."), i18n("Please enter a name for this playlist:"),
QLineEdit::Normal, contextMenuOn->text(), &ok);
if(ok) {
nameList.remove(contextMenuOn->text());
nameList.append(name);
contextMenuOn->setText(name);
updateItem(contextMenuOn);
}
}
}
void PlaylistBox::contextDuplicateItem()
{
if(contextMenuOn) {
bool ok;
// If this text is changed, please also change it in PlaylistSplitter::createPlaylist().
QString name = QInputDialog::getText(i18n("New Playlist..."), i18n("Please enter a name for the new playlist:"),
QLineEdit::Normal, splitter->uniquePlaylistName(contextMenuOn->text(), true), &ok);
if(ok) {
Playlist *p = splitter->createPlaylist(name);
p->add(contextMenuOn->playlist()->files());
}
}
}
void PlaylistBox::contextDeleteItem()
{
if(contextMenuOn) {
nameList.remove(contextMenuOn->text());
delete(contextMenuOn->playlist());
delete(contextMenuOn);
contextMenuOn = 0;
}
}
////////////////////////////////////////////////////////////////////////////////
// PlaylistBoxItem public methods
////////////////////////////////////////////////////////////////////////////////
PlaylistBoxItem::PlaylistBoxItem(PlaylistBox *listbox, const QPixmap &pix, const QString &text, Playlist *l) : ListBoxPixmap(listbox, pix, text)
PlaylistBoxItem::PlaylistBoxItem(PlaylistBox *listbox, const QPixmap &pix, const QString &text, Playlist *l)
: ListBoxPixmap(listbox, pix, text)
{
list = l;
setOrientation(Qt::Vertical);
listbox->addName(text);
}
PlaylistBoxItem::PlaylistBoxItem(PlaylistBox *listbox, const QString &text, Playlist *l) : ListBoxPixmap(listbox, SmallIcon("midi", 32), text)
PlaylistBoxItem::PlaylistBoxItem(PlaylistBox *listbox, const QString &text, Playlist *l)
: ListBoxPixmap(listbox, SmallIcon("midi", 32), text)
{
list = l;
setOrientation(Qt::Vertical);
......
......@@ -19,6 +19,7 @@
#define PLAYLISTBOX_H
#include <klistbox.h>
#include <kpopupmenu.h>