Logo Search packages:      
Sourcecode: qmpdclient version File versions  Download package

playlistmodel.cpp

/*
 * QMPDClient - An MPD client written in Qt 4.
 * Copyright (C) 2005-2008 HÃ¥vard Tautra Knutsen <havtknut@tihlde.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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "playlistmodel.h"
#include "aafilter.h"
#include "macroexpander.h"
#include "mpd.h"
#include "mpdcache.h"
#include <QApplication>
#include <QFont>
#include <QMimeData>

PlaylistModel::PlaylistModel(QObject *p) : MPDSongModel(p, 0),
            m_topDrop(false) {
      setObjectName("playlistmodel");
      m_pattern = "%b - %t";
}

void PlaylistModel::setPattern(const QString &p) {
      m_pattern = p;
      reset();
}

QString PlaylistModel::pattern() const {
      return m_pattern;
}

void PlaylistModel::setTopDrop(bool t) {
      m_topDrop = t;
}

QVariant PlaylistModel::data(const QModelIndex &index, int role) const {
      if (!index.isValid() || index.row() < 0 || index.row() > m_visible.size())
            return QVariant();

      MPDSong s = m_visible.at(index.row());
      if (s.isNull())
            return QVariant();


      if (role == Qt::DisplayRole) {
            if (m_queue.contains(s))
                  return QString("[%1] %2. %3|%4").arg(m_queue.indexOf(s)).arg(s.pos() + 1).arg(expandMacros(s, m_pattern)).arg(s.time());
            else
                  return QString("%1. %2|%3").arg(s.pos() + 1).arg(expandMacros(s, m_pattern)).arg(s.time());
      } else if (role == Qt::FontRole && s == m_playingSong) {
            QFont font = QApplication::font();
            font.setBold(true);
            return font;
      } else if (role == Qt::ToolTipRole) {
            return QString("%1 - %2").arg(s.artist(), s.title());
      }
      return QVariant();
}

int PlaylistModel::columnCount(const QModelIndex &) const {
      return 1;
}

MPDSongList PlaylistModel::unSelectedSongs(const QModelIndexList &selectedIndexes) const {
      MPDSongList selected = songs(selectedIndexes);
      MPDSongList ret;
      foreach(MPDSong song, m_visible) {
            if (selected.contains(song))
                  continue;
            ret << song;
      }
      return ret;
}

MPDSong PlaylistModel::lastSong() const {
      if (m_visible.isEmpty())
            return MPDSong();
      return m_visible.last();
}

void PlaylistModel::setPlaying(const MPDSong &song) {
      if (!song.isNull() && m_playingSong == song)
            return;
      QModelIndex oldidx = indexOfSong(m_playingSong);
      m_playingSong = song;
      QModelIndex idx = index(indexOfSong(m_playingSong).row(), 0);
      emit dataChanged(oldidx, idx);
}

MPDSong PlaylistModel::playingSong() const {
      return m_playingSong;
}

QModelIndex PlaylistModel::indexOfSong(const MPDSong &s) const {
      const int pos = m_visible.indexOf(s);
      if (pos > -1)
            return index(pos, 0);
      return QModelIndex();
}

void PlaylistModel::setFilter(const QString &a) {
      m_filter = QRegExp(a, Qt::CaseInsensitive);
      filter();
}

void PlaylistModel::filter() {
      if (m_filter.isEmpty()) {
            m_visible = m_all;
            reset();
            return;
      }

      m_visible.clear();
      for (QListIterator<MPDSong> it(m_all); it.hasNext();) {
            MPDSong s = it.next();
            if ((m_pattern.contains("%n") && s.track().contains(m_filter))
                    || (m_pattern.contains("%t") && s.title().contains(m_filter))
                    || (m_pattern.contains("%b") && s.artist().contains(m_filter))
                    || (m_pattern.contains("%a") && s.album().contains(m_filter))
                    || (m_pattern.contains("%g") && s.genre().contains(m_filter))
                    || (m_pattern.contains("%c") && s.composer().contains(m_filter))
                    || (m_pattern.contains("%d") && s.date().contains(m_filter))
                    || (m_pattern.contains("%f") && s.filename().contains(m_filter))
                    || (m_pattern.contains("%u") && s.url().contains(m_filter))
                    || s.time().contains(m_filter))
                  m_visible << s;
      }
      reset();
}

/*
 * DND
 */
MPDSongList PlaylistModel::decodeSongs(const QMimeData *m, QString format) const {
      Q_ASSERT(m);
      if (format == "qmpdclient/aa") {
            QByteArray encodedData = m->data(format);
            QDataStream stream(&encodedData, QIODevice::ReadOnly);
            AAFilter aa;
            while (!stream.atEnd()) {
                  stream >> aa;
            }
            return MPDCache::instance()->songsByAA(aa);
      }
      MPDSongList res;
      QByteArray encodedData = m->data(format);
      QDataStream stream(&encodedData, QIODevice::ReadOnly);
      while (!stream.atEnd()) {
            MPDSong s;
            stream >> s;
            res << s;
      }
      return res;
}

bool PlaylistModel::dropMimeData(const QMimeData *data, Qt::DropAction, int row, int, const QModelIndex &index) {
      Q_ASSERT(data);
      QString format;
      foreach(QString m, mimeTypes()) {
            if (data->hasFormat(m)) {
                  format = m;
                  break;
            }
      }
      if (format.isEmpty())
            return false;

      int dropPos;
      if (row != -1)
            dropPos = row;
      else if (index.isValid())
            dropPos = index.row();
      else
            dropPos = -1;

      MPDSongList songs = decodeSongs(data, format);
      if (format == "qmpdclient/move") {
            // drop pos special for moves
            if (dropPos == -1)
                  dropPos = lastSong().pos();

            if (!songs.isEmpty() && songs.first().pos() > dropPos)
                  ++dropPos;// ++ when moving songs upwards

            MPD::instance()->moveSongs(songs, dropPos);
      } else {
            if (m_topDrop) // Add to top.
                  dropPos = 0;
            else if (dropPos != -1) // ++ when adding, but not when adding to end
                  ++dropPos;
            MPD::instance()->addSongs(songs, true, dropPos);
      }
      return true;
}

QStringList PlaylistModel::mimeTypes() const {
      return QStringList() << "qmpdclient/song" << "qmpdclient/move" << "qmpdclient/aa";
}

QMimeData *PlaylistModel::mimeData(const QModelIndexList &indexes) const {
      if (m_dragDisabled)
            return 0;

      QByteArray encodedData;
      QDataStream stream(&encodedData, QIODevice::WriteOnly);
      foreach(MPDSong song, songs(indexes)) {
            stream << song;
      }

      QMimeData *mimeData = new QMimeData;
      mimeData->setData("qmpdclient/move", encodedData);
      return mimeData;
}

/*
 * Playlist queue
 */
void PlaylistModel::toggleQueue(const QModelIndexList &s) {
      foreach(QModelIndex i, s) {
            MPDSong song = m_visible.at(i.row());
            if(m_queue.contains(song)) {
                  m_queue.removeAll(song);
                  dataChanged(i, i);
            } else {
                  m_queue.append(song);
            }
      }
      foreach(MPDSong song, m_queue) {
            QModelIndex i = indexOfSong(song);
            dataChanged(i, i);
      }
}

void PlaylistModel::advanceQueue() {
      if (!m_queue.isEmpty())
            setPlaying(m_queue.takeFirst());
}

QList<MPDSong> PlaylistModel::queue() const {
      return m_queue;
}

Generated by  Doxygen 1.6.0   Back to index