Source

VPlayer / resultsmodel.py

# -*- coding: utf-8 -*-

import copy
import pickle

from PyQt4 import QtCore, QtGui
from track import Track

from vplayer.logger import log
from vplayer.tagreader import TagReader
from vplayer.fileloader import read_files

class ResultsModel(QtCore.QAbstractItemModel):

    def __init__(self):
        QtCore.QAbstractItemModel.__init__(self)
        self.tracks = []
        self.owner = None

    def set_owner(self, obj):
        self.owner = obj

    def track_updated(self, track):
        #print self.tracks
        #idx = -1
        #for x in range(len(self.tracks)):
            #if self.tracks[x] is track:
                #idx = x
                #break
        #print idx
        #if idx == -1:
            #return
        try:
            idx = self.tracks.index(track)
        except: return
        index = self.index(idx, 0, QtCore.QModelIndex())
        self.emit(QtCore.SIGNAL('dataChanged ( const QModelIndex, const QModelIndex )'), index, index)

    def data(self, index, role):
        if role == QtCore.Qt.SizeHintRole:
            return QtCore.QVariant(QtCore.QSize(0,20))

        if role == QtCore.Qt.FontRole:
            if self.tracks[index.row()].playing:
                font = QtGui.QFont()
                font.setBold(True)
                return QtCore.QVariant(font)

        if role == QtCore.Qt.ForegroundRole:
            if self.tracks[index.row()].is_bad():
                color = QtGui.QColor(170, 170, 170)
                return QtCore.QVariant(color)

        if role == QtCore.Qt.DecorationRole:
            if self.tracks[index.row()].is_playing() and index.column() == 0:
                pic = QtGui.QPixmap()
                if self.tracks[index.row()].is_paused():
                    pic.load(':/icons/images/nowpaused.png')
                else:
                    pic.load(':/icons/images/nowplaying.png')
                return QtCore.QVariant(pic.scaled(18, 18,
                  QtCore.Qt.IgnoreAspectRatio, QtCore.Qt.SmoothTransformation))

        if role == QtCore.Qt.DisplayRole:
            track = self.tracks[index.row()]
            if index.column() == 0:
                return QtCore.QVariant(track.artist)
            if index.column() == 1:
                return QtCore.QVariant(track.album)
            if index.column() == 2:
                return QtCore.QVariant(track.title)
            if index.column() == 3:
                return QtCore.QVariant(str(track.length))
            if index.column() == 4:
                if track.got_size:
                    return QtCore.QVariant(str(track.bitrate))
                else:
                    return QtCore.QVariant(self.tr('Resolving...'))
        return QtCore.QVariant()

    def headerData(self, section, orientation, role):
        if role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()

        headers = [self.tr('Artist'), self.tr('Album'), self.tr('Title'),
                   self.tr('Length'), self.tr('Bitrate')]
        if orientation == QtCore.Qt.Horizontal:
            return QtCore.QVariant(headers[section])
        if orientation == QtCore.Qt.Vertical:
            return QtCore.QVariant()

    def index(self, row, column, parent = QtCore.QModelIndex()):
        if row>len(self.tracks)-1:
            return QtCore.QModelIndex()
        track = self.tracks[row]
        item = ''
        if column == 0:
            item = track.artist
        if column == 1:
            item = track.album
        if column == 2:
            item = track.title
        if column == 3:
            item = str(track.length)
        if column == 4:
            item = str(track.bitrate)
        idx = self.createIndex(row, column, item)
        if column == 0:
            track.set_index1(idx)
        if column == 4:
            track.set_index2(idx)
        return idx

    def parent(self, index):
        return QtCore.QModelIndex()

    def rowCount(self, parent = QtCore.QModelIndex()):
        if parent.isValid():
            return 0
        return len(self.tracks)

    def columnCount(self, parent = QtCore.QModelIndex()):
        return 5

    def update(self):
        self.reset()
        #self.tracks = self.mdata
        #self.reset()

    def update_notused(self):
        self.tracks = []
        for track in self.mdata:
            ok = True
            if self.unique_only:
                while track in self.tracks:
                    t = self.tracks[self.tracks.index(track)]
                    if t.length < track.length:
                        self.tracks.remove(t)
                    else:
                        if ok: ok = False
                        break
            if self.artist:
                if track.artist.upper() != self.artist.upper():
                    if ok: ok = False
            if self.title:
                if track.title.upper() != self.title.upper():
                    if ok: ok = False
            if self.filterw:
                text = track.title.upper() + track.artist.upper()
                if self.filterw.upper() not in text:
                    if ok: ok = False
            if ok:
                self.tracks.append(track)
        if self.sorting:
            self.sort(self.sorting[0], self.sorting[1])

    def set_data(self, data):
        "Use this method to set model content"
        for track in self.tracks:
            track.prepare_to_die()
        self.tracks = copy.copy(data)
        for track in self.tracks:
            track.set_parent(self)
        self.reset()

    def add_data(self, data):
        "Use this method to add content to model"
        if hasattr(data, '__iter__'):
            self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(),
                                 self.rowCount()+len(data))
            newdata = copy.copy(data)
            for track in newdata:
                track.set_parent(self)
            self.tracks += newdata
        else:
            self.beginInsertRows(QtCore.QModelIndex(), self.rowCount(),
                                 self.rowCount())
            track = copy.copy(data)
            track.set_parent(self)
            self.tracks.append(tack)
        self.endInsertRows()
        self.reset()

    def item_updated(self, idx1, idx2):
        self.emit(QtCore.SIGNAL('dataChanged ( const QModelIndex &, const QModelIndex &)'),
                                idx1, idx2)

    def clear(self):
        for track in self.tracks:
            track.prepare_to_die()
        self.tracks = []
        self.reset()

    def get_url(self, index):
        return self.tracks[index.row()].url

    def get_track(self, index):
        if isinstance(index, int):
            return self.tracks[index]
        else:
            return self.tracks[index.row()]

#    def removeRow(self, row, parent):
#        del self.tracks[row]

    def removeRows(self, row, count, parent):
        log.debug('removeRows called! %d %d' % (row, count))
        self.beginRemoveRows(parent, row, row + count - 1)
        while count:
            self.tracks[row].prepare_to_die()
            del self.tracks[row]
            count -= 1
        self.endRemoveRows()
        return True

    def insertRow(self, row, parent):
        self.tracks.insert(row, None)

    def mimeTypes(self):
        types = QtCore.QStringList()
        types << "application/x-tracks"
        types << "text/uri-list"
        return types

    def mimeData(self, indexes):
        mimeData = QtCore.QMimeData()
        rows = []
        tracks = []
        for index in indexes:
            if index.row() not in rows:
                rows.append(index.row())
                track = copy.copy(self.tracks[index.row()])
                #track.set_playing(False)
                #track.set_paused(False)
                #track.set_parent(None)
                track.free()
                tracks.append(track)
        data = pickle.dumps(tracks)
        mimeData.setData("application/x-tracks", data)
        return mimeData

    def dropMimeData(self, data, action, row, column, parent):
        if action == QtCore.Qt.IgnoreAction:
            return True

        if data.hasFormat("application/x-tracks"):
            if column > 2:
                return False

            beginRow = int()
            if row != -1:
                beginRow = row
            elif parent.isValid():
                beginRow = parent.row()
            else:
                beginRow = self.rowCount(QtCore.QModelIndex())

            encoded_data = data.data("application/x-tracks");
            newitems = pickle.loads(encoded_data)
            rows = len(newitems)
            self.beginInsertRows(QtCore.QModelIndex(), beginRow, beginRow + rows-1)
            for track in newitems:
                self.insertRow(beginRow, QtCore.QModelIndex())
                track.set_parent(self)
                self.tracks[beginRow] = track
                beginRow += 1
            self.endInsertRows()
        elif data.hasFormat('text/uri-list'):
            if column > 2:
                return False

            beginRow = int()
            if row != -1:
                beginRow = row
            elif parent.isValid():
                beginRow = parent.row()
            else:
                beginRow = self.rowCount(QtCore.QModelIndex())

            files = []
            for url in data.urls():
                filename = url.toLocalFile()
                if filename:
                    files.append(filename)
            self.add_data(read_files(files))
            #encoded_data = data.data("text/uri-list")
            #names = []
            #for name in unicode(encoded_data).split('\r\n'):
                #if not name.startswith('file://'): continue
                #bytes = QtCore.QByteArray()
                #bytes.append(name[7:])
                #names.append(unicode(QtCore.QUrl.fromPercentEncoding(bytes)))
            #if names:
                #self.add_data(read_files(names))
        return True

    def supportedDragActions(self):
        if self.owner.role == 'search':
            return QtCore.Qt.MoveAction#QtCore.Qt.CopyAction
        if self.owner.role == 'playlist':
            return QtCore.Qt.MoveAction
            #return QtCore.QAbstractItemModel.supportedDragActions(self) | QtCore.Qt.MoveAction

    def flags(self, index):
        defaultFlags = QtCore.QAbstractItemModel.flags(self, index)

        if index.isValid():
            #return defaultFlags^QtCore.Qt.ItemIsDropEnabled
            #return ~QtCore.Qt.ItemIsDropEnabled | defaultFlags
            return QtCore.Qt.ItemIsDragEnabled | defaultFlags | QtCore.Qt.ItemIsDropEnabled
        else:
            #return defaultFlags
            return QtCore.Qt.ItemIsDropEnabled | defaultFlags

    def supportedDropActions(self):
        #if self.owner.role == 'search':
        #    return QtCore.Qt.IgnoreAction
        #else:
        return QtCore.Qt.MoveAction #| QtCore.Qt.CopyAction
        #
        #else:
        #    return QtCore.Qt.MoveAction

#    def setData(self, index, value, role):
#        return True