Commit 5d417225 authored by Scott Wheeler's avatar Scott Wheeler

Started cleaning up the ugly "view modes" situaion in PlaylistBox. It's

now been moved out to another group of classes, each of which encapsulates
a view mode.

At the present the tree view's code has been ripped out of the old structure
and not replaced in the new one.  This hopefully will follow tomorrow.

svn path=/trunk/kdemultimedia/juk/; revision=230058
parent 293407ec
......@@ -11,7 +11,7 @@ juk_SOURCES = directorylistbase.ui genrelisteditorbase.ui \
slideraction.cpp keydialog.cpp juk.cpp main.cpp tagguesser.cpp \
tagguesserconfigdlgwidget.ui tagguesserconfigdlg.cpp jukIface.skel \
playlistsearch.cpp searchwidget.cpp filerenamer.cpp dynamicplaylist.cpp \
searchplaylist.cpp musicbrainzquery.cpp mediafiles.cpp
searchplaylist.cpp musicbrainzquery.cpp mediafiles.cpp viewmode.cpp
tagguessertest_SOURCES = tagguessertest.cpp tagguesser.cpp
......
......@@ -30,7 +30,6 @@
#include "playlistbox.h"
#include "playlistsplitter.h"
#include "playlistsearch.h"
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox public methods
......@@ -39,7 +38,7 @@
PlaylistBox::PlaylistBox(PlaylistSplitter *parent, const char *name) : KListView(parent, name),
m_splitter(parent),
m_updatePlaylistStack(true),
m_viewMode(Compact),
m_viewModeIndex(0),
m_hasSelection(false)
{
readConfig();
......@@ -62,7 +61,7 @@ PlaylistBox::PlaylistBox(PlaylistSplitter *parent, const char *name) : KListView
if(!w)
return;
KActionCollection *actions = static_cast<KMainWindow *>(w)->actionCollection();
actions->action("file_new")->plug(m_contextMenu);
......@@ -77,10 +76,19 @@ PlaylistBox::PlaylistBox(PlaylistSplitter *parent, const char *name) : KListView
m_viewModeAction = new KSelectAction(actions, "viewModeMenu");
m_viewModeAction->setText(i18n("View Modes"));
QStringList modes;
modes << i18n("Default") << i18n("Compact") << i18n("Tree");
m_viewModeAction->setItems(modes);
m_viewModeAction->setCurrentItem(m_viewMode);
m_viewModes.append(new ViewMode(this));
m_viewModes.append(new CompactViewMode(this));
m_viewModes.append(new TreeViewMode(this));
m_viewModes.setAutoDelete(true);
QStringList modeNames;
for(ViewMode *view = m_viewModes.first(); view; view = m_viewModes.next())
modeNames.append(view->name());
m_viewModeAction->setItems(modeNames);
m_viewModeAction->setCurrentItem(m_viewModeIndex);
m_viewModeAction->plug(m_contextMenu);
connect(m_viewModeAction, SIGNAL(activated(int)), this, SLOT(slotSetViewMode(int)));
......@@ -132,8 +140,8 @@ PlaylistList PlaylistBox::playlists()
{
PlaylistList l;
for(QListViewItem *it = firstChild(); it; it = it->nextSibling()) {
Item *i = static_cast<Item *>(it);
for(QListViewItemIterator it(this); it.current(); ++it) {
Item *i = static_cast<Item *>(*it);
if(i->playlist() != CollectionList::instance())
l.append(i->playlist());
}
......@@ -161,22 +169,6 @@ void PlaylistBox::duplicate()
duplicate(static_cast<Item *>(currentItem()));
}
void PlaylistBox::initViewMode()
{
int iconSize = m_viewMode != Default ? 16 : 32;
for(QListViewItem *it = firstChild(); it; it = it->nextSibling()) {
Item *i = static_cast<Item *>(it);
i->setPixmap(0, SmallIcon(i->iconName(), iconSize));
for(QListViewItem *n = i->firstChild(); n; n = n->nextSibling())
n->setVisible(m_viewMode == Tree);
if(m_viewMode == Tree && i->childCount() == 0)
i->slotSetData();
}
setRootIsDecorated(m_viewMode == Tree);
setColumnWidthMode(0, (m_viewMode == Tree) ? Maximum : Manual);
}
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox public slots
////////////////////////////////////////////////////////////////////////////////
......@@ -201,7 +193,7 @@ void PlaylistBox::readConfig()
KConfig *config = kapp->config();
{
KConfigGroupSaver saver(config, "PlaylistBox");
m_viewMode = (ViewMode) config->readNumEntry("ViewMode", 0);
m_viewModeIndex = config->readNumEntry("ViewMode", 0);
}
}
......@@ -320,7 +312,6 @@ void PlaylistBox::decode(QMimeSource *s, Item *item)
files.append((*it).path());
m_splitter->slotAddToPlaylist(files, item->playlist());
item->rootItem()->slotSetData();
}
}
......@@ -363,9 +354,9 @@ QValueList<PlaylistBox::Item *> PlaylistBox::selectedItems()
{
QValueList<Item *> l;
for(QListViewItem *it = firstChild(); it; it = it->nextSibling()) {
if(isSelected(it))
l.append(static_cast<Item *>(it));
for(QListViewItemIterator it(this); it.current(); ++it) {
if(isSelected(*it))
l.append(static_cast<Item *>(*it));
}
return l;
......@@ -388,40 +379,13 @@ void PlaylistBox::slotPlaylistChanged()
m_hasSelection = !items.isEmpty();
if(!m_updatePlaylistStack)
return;
if(m_hasSelection) {
return;
QValueList<Playlist *> playlists;
for(QValueList<Item *>::iterator i = items.begin(); i != items.end(); ++i)
playlists.append((*i)->playlist());
QValueList<Playlist *> playlists;
for(QValueList<Item *>::iterator i = items.begin(); i != items.end(); ++i)
playlists.append((*i)->playlist());
emit signalCurrentChanged(playlists);
}
else {
for(QListViewItemIterator it(this); it.current(); ++it) {
if(isSelected(*it)) {
Item *i = static_cast<Item *>(*it);
PlaylistList playlists;
playlists.append(i->playlist());
if(i->childCount() > 0)
i->playlist()->setItemsVisible(i->playlist()->items(), true);
else {
ColumnList searchedColumns;
searchedColumns.append(i->category());
PlaylistSearch::Component component(i->text(), true, searchedColumns);
PlaylistSearch::ComponentList components;
components.append(component);
PlaylistSearch search(playlists, components);
Playlist::setItemsVisible(search.matchedItems(), true);
Playlist::setItemsVisible(search.unmatchedItems(), false);
}
emit signalCurrentChanged(playlists);
break;
}
}
}
emit signalCurrentChanged(playlists);
}
void PlaylistBox::slotDoubleClicked(QListViewItem *)
......@@ -434,12 +398,14 @@ void PlaylistBox::slotShowContextMenu(QListViewItem *, const QPoint &point, int)
m_contextMenu->popup(point);
}
void PlaylistBox::slotSetViewMode(int viewMode)
void PlaylistBox::slotSetViewMode(int index)
{
if(viewMode != m_viewMode) {
m_viewMode = ViewMode(viewMode);
initViewMode();
}
if(index == m_viewModeIndex)
return;
viewMode()->setShown(false);
m_viewModeIndex = index;
viewMode()->setShown(true);
}
////////////////////////////////////////////////////////////////////////////////
......@@ -448,23 +414,13 @@ void PlaylistBox::slotSetViewMode(int viewMode)
PlaylistBox::Item::Item(PlaylistBox *listBox, const char *icon, const QString &text, Playlist *l)
: QObject(listBox), KListViewItem(listBox, text),
m_list(l), m_text(text), m_iconName(icon), m_category(-1)
m_list(l), m_text(text), m_iconName(icon)
{
int iconSize = listBox->viewMode() != PlaylistBox::Default ? 16 : 32;
int iconSize = listBox->viewModeIndex() == 0 ? 32 : 16;
setPixmap(0, SmallIcon(icon, iconSize));
listBox->addName(text);
connect(l, SIGNAL(signalNameChanged(const QString &)), this, SLOT(slotSetName(const QString &)));
connect(l, SIGNAL(signalDataChanged()), this, SLOT(slotTriggerSetData()));
connect(l, SIGNAL(signalNumberOfItemsChanged(Playlist *)), this, SLOT(slotTriggerSetData()));
connect(l, SIGNAL(signalFilesDropped(const QStringList &, Playlist *)), this, SLOT(slotSetData()));
}
PlaylistBox::Item::Item(Item *parent, const char *icon, const QString &text, int category, Playlist *l)
: QObject(parent), KListViewItem(parent, text),
m_list(l), m_text(text), m_iconName(icon), m_category(category)
{
setPixmap(0, SmallIcon(icon, 16));
}
PlaylistBox::Item::~Item()
......@@ -474,10 +430,9 @@ PlaylistBox::Item::~Item()
int PlaylistBox::Item::compare(QListViewItem *i, int col, bool) const
{
if(playlist() == CollectionList::instance() && category() == -1)
if(playlist() == CollectionList::instance())
return -1;
else if(static_cast<Item *>(i)->playlist() == CollectionList::instance() &&
static_cast<Item *>(i)->category() == -1)
else if(static_cast<Item *>(i)->playlist() == CollectionList::instance())
return 1;
return text(col).lower().localeAwareCompare(i->text(col).lower());
......@@ -485,83 +440,8 @@ int PlaylistBox::Item::compare(QListViewItem *i, int col, bool) const
void PlaylistBox::Item::paintCell(QPainter *painter, const QColorGroup &colorGroup, int column, int width, int align)
{
if(width < pixmap(column)->width())
return;
QFontMetrics fm = painter->fontMetrics();
QString line = m_text;
switch(static_cast<PlaylistBox *>(listView())->viewMode()) {
case Tree:
KListViewItem::setText(column, line);
KListViewItem::paintCell(painter, colorGroup, column, width, align);
break;
case Compact:
{
int baseWidth = pixmap(column)->width() + listView()->itemMargin() * 4;
if(baseWidth + fm.width(line) > width) {
int ellipsisLength = fm.width("...");
if(width > baseWidth + ellipsisLength) {
while(baseWidth + fm.width(line) + ellipsisLength > width)
line.truncate(line.length() - 1);
line = line.append("...");
}
else
line = "...";
}
KListViewItem::setText(column, line);
KListViewItem::paintCell(painter, colorGroup, column, width, align);
break;
}
default:
{
QStringList lines;
while(!line.isEmpty()) {
int textLength = line.length();
while(textLength > 0 &&
fm.width(line.mid(0, textLength).stripWhiteSpace()) + listView()->itemMargin() * 2 > 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);
}
int y = listView()->itemMargin();
const QPixmap *pm = pixmap(column);
int height = 3 * listView()->itemMargin() + pm->height() +
(fm.height() - fm.descent()) * lines.count();
if(isSelected()) {
painter->fillRect(0, 0, width, height, colorGroup.brush(QColorGroup::Highlight));
painter->setPen(colorGroup.highlightedText());
}
else
painter->eraseRect(0, 0, width, height);
if (!pm->isNull()) {
int x = (width - pm->width()) / 2;
x = QMAX(x, listView()->itemMargin());
painter->drawPixmap(x, y, *pm);
}
y += pm->height() + fm.height() - fm.descent();
for(QStringList::Iterator it = lines.begin(); it != lines.end(); ++it) {
int x = (width - fm.width(*it)) / 2;
x = QMAX(x, listView()->itemMargin());
painter->drawText(x, y, *it);
y += fm.height() - fm.descent();
}
setHeight(height);
break;
}
}
PlaylistBox *playlistBox = static_cast<PlaylistBox *>(listView());
playlistBox->viewMode()->paintCell(this, painter, colorGroup, column, width, align);
}
void PlaylistBox::Item::setText(int column, const QString &text)
......@@ -570,14 +450,6 @@ void PlaylistBox::Item::setText(int column, const QString &text)
KListViewItem::setText(column, text);
}
PlaylistBox::Item *PlaylistBox::Item::rootItem()
{
Item *i = this;
while(i->category() != -1)
i = static_cast<Item *>(i->KListViewItem::parent());
return i;
}
////////////////////////////////////////////////////////////////////////////////
// PlaylistBox::Item protected slots
////////////////////////////////////////////////////////////////////////////////
......@@ -592,80 +464,4 @@ void PlaylistBox::Item::slotSetName(const QString &name)
}
}
void PlaylistBox::Item::slotTriggerSetData()
{
// Trigger setting data in tree view later, to ensure deleteLater is done
QTimer::singleShot(1, this, SLOT(slotSetData()));
}
void PlaylistBox::Item::slotSetData()
{
static const char *categoryText[] =
{I18N_NOOP("Artist"), I18N_NOOP("Album"), I18N_NOOP("Genre"), I18N_NOOP("Year")};
static const int categoryIndex[] =
{PlaylistItem::ArtistColumn, PlaylistItem::AlbumColumn,
PlaylistItem::GenreColumn, PlaylistItem::YearColumn};
static const int categoryCount = sizeof(categoryText)/sizeof(categoryText[0]);
PlaylistBox *listBox = static_cast<PlaylistBox *>(listView());
if(listBox->viewMode() != Tree && childCount() == 0)
return;
// Fetch item data and put in categories
PlaylistItemList items = m_list->items();
SortedStringList categories[categoryCount];
for(PlaylistItemList::iterator item = items.begin(); item != items.end(); ++item) {
Tag *tag = (*item)->tag();
categories[0].insert(tag->artist());
categories[1].insert(tag->album());
categories[2].insert(tag->genre());
categories[3].insert(tag->yearString());
}
// Delete items that no longer exist, and remove existing items from categories
listBox->setUpdatesEnabled(false);
if(childCount() > 0) {
for(QListViewItem *i = firstChild(); i; ) {
Item *categoryItem = static_cast<Item *>(i);
i = i->nextSibling();
int category = categoryItem->category();
for(QListViewItem *n = categoryItem->firstChild(); n; ) {
Item *currentItem = static_cast<Item *>(n);
n = n->nextSibling();
if(categories[category].contains(currentItem->text()))
categories[category].remove(currentItem->text());
else
delete currentItem;
}
}
}
// Find or create category items, and then add new items remaining in categories
for(int category = 0; category < categoryCount; category++) {
QStringList categoryList = categories[category].values();
Item *categoryItem = 0;
QListViewItem *item;
for(item = firstChild(); item; item = item->nextSibling()) {
Item *currentItem = static_cast<Item *>(item);
if(currentItem->category() == category) {
categoryItem = currentItem;
break;
}
}
if(!item)
categoryItem = new Item(this, iconName(), i18n(categoryText[category]), category, m_list);
for(QStringList::iterator text = categoryList.begin(); text != categoryList.end(); ++text)
if(!(*text).isEmpty())
new Item(categoryItem, "cdimage", *text, categoryIndex[category], m_list);
if(categoryItem->childCount() < 2) {
delete categoryItem;
categoryItem = 0;
}
}
listBox->setUpdatesEnabled(true);
listBox->triggerUpdate();
}
#include "playlistbox.moc"
......@@ -25,6 +25,7 @@
#include <qmap.h>
#include "playlist.h"
#include "viewmode.h"
class PlaylistItem;
class PlaylistSplitter;
......@@ -42,8 +43,6 @@ class PlaylistBox : public KListView
Q_OBJECT
public:
enum ViewMode { Default = 0, Compact = 1, Tree = 2 };
PlaylistBox(PlaylistSplitter *parent = 0, const char *name = 0);
virtual ~PlaylistBox();
......@@ -60,10 +59,10 @@ public:
void duplicate();
void deleteItem();
bool hasSelection() const { return m_hasSelection; }
bool hasSelection() const { return m_hasSelection; }
void initViewMode();
ViewMode viewMode() const { return m_viewMode; }
ViewMode *viewMode() { return m_viewModes.at(m_viewModeIndex); }
int viewModeIndex() const { return m_viewModeIndex; }
class Item;
friend class Item;
......@@ -109,7 +108,7 @@ private slots:
void slotPlaylistChanged();
void slotDoubleClicked(QListViewItem *);
void slotShowContextMenu(QListViewItem *, const QPoint &point, int);
void slotSetViewMode(int viewMode);
void slotSetViewMode(int index);
private:
PlaylistSplitter *m_splitter;
......@@ -117,7 +116,8 @@ private:
KPopupMenu *m_contextMenu;
bool m_updatePlaylistStack;
QPtrDict<Item> m_playlistDict;
ViewMode m_viewMode;
int m_viewModeIndex;
QPtrList<ViewMode> m_viewModes;
KSelectAction *m_viewModeAction;
bool m_hasSelection;
};
......@@ -127,6 +127,8 @@ private:
class PlaylistBox::Item : public QObject, public KListViewItem
{
friend class PlaylistBox;
friend class ViewMode;
friend class CompactViewMode;
Q_OBJECT
......@@ -139,31 +141,25 @@ public:
protected:
Item(PlaylistBox *listBox, const char *icon, const QString &text, Playlist *l = 0);
Item(Item *parent, const char *icon, const QString &text, int category, Playlist *l = 0);
Playlist *playlist() const { return m_list; }
PlaylistBox *listView() const { return static_cast<PlaylistBox *>(KListViewItem::listView()); }
const char *iconName() const { return m_iconName; }
QString text() const { return m_text; }
int category() const { return m_category; }
virtual int compare(QListViewItem *i, int col, bool) const;
virtual void paintCell(QPainter *p, const QColorGroup &colorGroup, int column, int width, int align);
virtual void setText(int column, const QString &text);
virtual Item *rootItem();
virtual QString text(int column) const { return KListViewItem::text(column); }
protected slots:
void slotSetName(const QString &name);
void slotTriggerSetData();
void slotSetData();
private:
Playlist *m_list;
QString m_text;
const char *m_iconName;
int m_category;
};
#endif
......@@ -54,7 +54,6 @@ PlaylistSplitter::PlaylistSplitter(QWidget *parent, bool restore, const char *na
readConfig();
m_editor->slotUpdateCollection();
m_playlistBox->initViewMode();
}
PlaylistSplitter::~PlaylistSplitter()
......@@ -675,7 +674,6 @@ void PlaylistSplitter::slotCreatePlaylist(const PlaylistItemList &items)
return;
playlist->createItems(items);
m_playlistBox->initViewMode();
}
void PlaylistSplitter::slotShowSearchResults()
......
/***************************************************************************
viewmode.cpp
-------------------
begin : Sat Jun 7 2003
copyright : (C) 2003 by Scott Wheeler,
email : 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 as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <kiconloader.h>
#include <qpixmap.h>
#include <qpainter.h>
#include "viewmode.h"
#include "playlistbox.h"
////////////////////////////////////////////////////////////////////////////////
// ViewMode
////////////////////////////////////////////////////////////////////////////////
ViewMode::ViewMode(PlaylistBox *b) :
m_playlistBox(b),
m_visible(false)
{
}
ViewMode::~ViewMode()
{
}
void ViewMode::paintCell(QListViewItem *i,
QPainter *painter,
const QColorGroup &colorGroup,
int column, int width, int align)
{
Q_UNUSED(align);
if(width < i->pixmap(column)->width())
return;
PlaylistBox::Item *item = static_cast<PlaylistBox::Item *>(i);
QFontMetrics fm = painter->fontMetrics();
QString line = item->text();
QStringList lines;
while(!line.isEmpty()) {
int textLength = line.length();
while(textLength > 0 &&
fm.width(line.mid(0, textLength).stripWhiteSpace()) + item->listView()->itemMargin() * 2 > 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);
}
int y = item->listView()->itemMargin();
const QPixmap *pm = item->pixmap(column);
int height = 3 * item->listView()->itemMargin() + pm->height() +
(fm.height() - fm.descent()) * lines.count();
if(item->isSelected()) {
painter->fillRect(0, 0, width, height, colorGroup.brush(QColorGroup::Highlight));
painter->setPen(colorGroup.highlightedText());
}
else
painter->eraseRect(0, 0, width, height);
if (!pm->isNull()) {
int x = (width - pm->width()) / 2;
x = QMAX(x, item->listView()->itemMargin());
painter->drawPixmap(x, y, *pm);
}
y += pm->height() + fm.height() - fm.descent();
for(QStringList::Iterator it = lines.begin(); it != lines.end(); ++it) {
int x = (width - fm.width(*it)) / 2;
x = QMAX(x, item->listView()->itemMargin());
painter->drawText(x, y, *it);
y += fm.height() - fm.descent();
}
item->setHeight(height);
}
void ViewMode::setShown(bool shown)
{
m_visible = shown;
if(shown)
updateIcons(32);
}
void ViewMode::updateIcons(int size)
{
for(QListViewItemIterator it(m_playlistBox); it.current(); ++it) {
PlaylistBox::Item *i = static_cast<PlaylistBox::Item *>(*it);
i->setPixmap(0, SmallIcon(i->iconName(), size));
}
}
///////////////////////////////////////////////////////////////////////////////
// CompactViewMode
////////////////////////////////////////////////////////////////////////////////
CompactViewMode::CompactViewMode(PlaylistBox *b) : ViewMode(b)
{
}
CompactViewMode::~CompactViewMode()
{
}
void CompactViewMode::paintCell(QListViewItem *i,
</