PageRenderTime 94ms CodeModel.GetById 30ms app.highlight 42ms RepoModel.GetById 19ms app.codeStats 0ms

/src/libtomahawk/jobview/JobStatusModel.cpp

http://github.com/tomahawk-player/tomahawk
C++ | 319 lines | 205 code | 69 blank | 45 comment | 22 complexity | 6251f8af6d01c579633a75b4f4c6d369 MD5 | raw file
  1/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2 *
  3 *   Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
  4 *   Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
  5 *
  6 *   Tomahawk is free software: you can redistribute it and/or modify
  7 *   it under the terms of the GNU General Public License as published by
  8 *   the Free Software Foundation, either version 3 of the License, or
  9 *   (at your option) any later version.
 10 *
 11 *   Tomahawk is distributed in the hope that it will be useful,
 12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 14 *   GNU General Public License for more details.
 15 *
 16 *   You should have received a copy of the GNU General Public License
 17 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 18 */
 19
 20#include "JobStatusModel.h"
 21
 22#include "JobStatusItem.h"
 23#include "utils/Logger.h"
 24
 25#include <QPixmap>
 26
 27
 28JobStatusSortModel::JobStatusSortModel( QObject* parent )
 29    : QSortFilterProxyModel( parent )
 30{
 31    setDynamicSortFilter( true );
 32}
 33
 34
 35JobStatusSortModel::~JobStatusSortModel()
 36{
 37}
 38
 39
 40void
 41JobStatusSortModel::setJobModel( JobStatusModel* model )
 42{
 43    setSourceModel( model );
 44
 45    m_sourceModel = model;
 46
 47    connect( m_sourceModel, SIGNAL( customDelegateJobInserted( int, JobStatusItem* ) ), this, SLOT( customDelegateJobInsertedSlot( int, JobStatusItem* ) ) );
 48    connect( m_sourceModel, SIGNAL( customDelegateJobRemoved( int ) ), this, SLOT( customDelegateJobRemovedSlot( int ) ) );
 49    connect( m_sourceModel, SIGNAL( refreshDelegates() ), this, SLOT( refreshDelegatesSlot() ) );
 50}
 51
 52
 53void
 54JobStatusSortModel::addJob( JobStatusItem* item )
 55{
 56    m_sourceModel->addJob( item );
 57}
 58
 59
 60void
 61JobStatusSortModel::customDelegateJobInsertedSlot( int row, JobStatusItem* item )
 62{
 63    emit customDelegateJobInserted( mapFromSource( m_sourceModel->index( row ) ).row(), item );
 64}
 65
 66
 67void
 68JobStatusSortModel::customDelegateJobRemovedSlot( int row )
 69{
 70    emit customDelegateJobRemoved( mapFromSource( m_sourceModel->index( row ) ).row() );
 71}
 72
 73
 74void
 75JobStatusSortModel::refreshDelegatesSlot()
 76{
 77    sort( 0 );
 78    emit refreshDelegates();
 79}
 80
 81
 82bool
 83JobStatusSortModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
 84{
 85    const int leftSort = left.data( JobStatusModel::SortRole ).toInt();
 86    const int rightSort = right.data( JobStatusModel::SortRole ).toInt();
 87
 88    if ( leftSort == rightSort )
 89        return left.data( JobStatusModel::AgeRole ).toUInt() > right.data( JobStatusModel::AgeRole ).toUInt();
 90
 91    return leftSort < rightSort;
 92}
 93
 94
 95
 96JobStatusModel::JobStatusModel( QObject* parent )
 97    : QAbstractListModel ( parent )
 98{
 99}
100
101
102JobStatusModel::~JobStatusModel()
103{
104    qDeleteAll( m_items );
105    m_collapseCount.clear();
106}
107
108
109void
110JobStatusModel::addJob( JobStatusItem* item )
111{
112//    tLog() << Q_FUNC_INFO << "current jobs of item type: " << m_jobTypeCount[ item->type() ] << ", current queue size of item type: " << m_jobQueue[ item->type() ].size();
113    if ( item->concurrentJobLimit() > 0 )
114    {
115        if ( m_jobTypeCount[ item->type() ] >= item->concurrentJobLimit() )
116        {
117            m_jobQueue[ item->type() ].enqueue( item );
118            return;
119        }
120        int currentJobCount = m_jobTypeCount[ item->type() ];
121        currentJobCount++;
122        m_jobTypeCount[ item->type() ] = currentJobCount;
123    }
124
125//    tLog() << Q_FUNC_INFO << "new current jobs of item type: " << m_jobTypeCount[ item->type() ];
126
127    connect( item, SIGNAL( statusChanged() ), SLOT( itemUpdated() ) );
128    connect( item, SIGNAL( finished() ), SLOT( itemFinished() ) );
129
130    if ( item->collapseItem() )
131    {
132        if ( m_collapseCount.contains( item->type() ) )
133        {
134            m_collapseCount[ item->type() ].append( item );
135//             qDebug() << "Adding item:" << item << "TO COLLAPSE ONLY";
136            return; // we're done, no new rows
137        }
138        else
139        {
140            m_collapseCount.insert( item->type(), QList< JobStatusItem* >() << item );
141        }
142
143    }
144//    tLog() << Q_FUNC_INFO << "Adding item:" << item;
145
146    int currentEndRow = m_items.count();
147    beginInsertRows( QModelIndex(), currentEndRow, currentEndRow );
148    m_items.append( item );
149    endInsertRows();
150
151    if ( item->hasCustomDelegate() )
152    {
153//        tLog() << Q_FUNC_INFO << "job has custom delegate";
154        emit customDelegateJobInserted( currentEndRow, item );
155    }
156
157    emit refreshDelegates();
158}
159
160
161Qt::ItemFlags
162JobStatusModel::flags( const QModelIndex& index ) const
163{
164    Q_UNUSED( index );
165    // Don't let the items be selectable
166    return Qt::ItemIsEnabled;
167}
168
169
170QVariant
171JobStatusModel::data( const QModelIndex& index, int role ) const
172{
173    if ( !hasIndex( index.row(), index.column(), index.parent() ) )
174        return QVariant();
175
176    JobStatusItem* item = m_items[ index.row() ];
177
178    switch ( role )
179    {
180        case Qt::DecorationRole:
181            return item->icon();
182
183        case Qt::ToolTipRole:
184
185        case Qt::DisplayRole:
186        {
187            if ( m_collapseCount.contains( item->type() ) )
188                return m_collapseCount[ item->type() ].last()->mainText();
189            else
190                return item->mainText();
191        }
192
193        case RightColumnRole:
194        {
195            if ( m_collapseCount.contains( item->type() ) )
196                return m_collapseCount[ item->type() ].count();
197            else
198                return item->rightColumnText();
199        }
200
201        case AllowMultiLineRole:
202            return item->allowMultiLine();
203
204        case JobDataRole:
205            return QVariant::fromValue< JobStatusItem* >( item );
206
207        case SortRole:
208            return item->weight();
209
210        case AgeRole:
211            return item->age();
212
213        default:
214            return QVariant();
215    }
216
217    return QVariant();
218}
219
220
221int
222JobStatusModel::rowCount( const QModelIndex& parent ) const
223{
224    Q_UNUSED( parent );
225    return m_items.count();
226}
227
228
229void
230JobStatusModel::itemFinished()
231{
232//    tLog( LOGVERBOSE ) << Q_FUNC_INFO;
233    JobStatusItem* item = qobject_cast< JobStatusItem* >( sender() );
234    Q_ASSERT( item );
235
236//     tDebug() << "Got item finished:" << item->type() << item->mainText() << item;
237    if ( !m_items.contains( item ) && !m_collapseCount.contains( item->type() ) )
238        return;
239
240//     foreach( JobStatusItem* item, m_items )
241//     {
242//         qDebug() << "ITEM #:" << item;
243//     }
244//     foreach( const QString& str, m_collapseCount.keys() )
245//     {
246//         tDebug() << "\t" << str;
247//         foreach( JobStatusItem* chain, m_collapseCount[ str ] )
248//             qDebug() << "\t\t" << chain;
249//     }
250    if ( m_collapseCount.contains( item->type() ) )
251    {
252        const int indexOf = m_items.indexOf( m_collapseCount[ item->type() ].first() );
253//         tDebug() << "index in main list of collapsed irst item:" << indexOf;
254        if ( m_collapseCount[ item->type() ].first() == item &&
255             m_items.contains( m_collapseCount[ item->type() ].first() ) && m_collapseCount[ item->type() ].size() > 1 )
256        {
257            // the placeholder we use that links m_items and m_collapsecount is done, so choose another one
258            m_items.replace( m_items.indexOf( m_collapseCount[ item->type() ].first() ), m_collapseCount[ item->type() ][ 1 ] );
259//             qDebug() << "Replaced" << m_collapseCount[ item->type() ].first() << "with:" << m_collapseCount[ item->type() ][ 1 ] << m_items;
260        }
261        m_collapseCount[ item->type() ].removeAll( item );
262//         tDebug() << "New collapse count list:" << m_collapseCount[ item->type() ];
263        if ( m_collapseCount[ item->type() ].isEmpty() )
264            m_collapseCount.remove( item->type() );
265        else
266        {
267            // One less to count, but item is still there
268            const QModelIndex idx = index( indexOf, 0, QModelIndex() );
269            emit dataChanged( idx, idx );
270            emit refreshDelegates();
271            return;
272        }
273    }
274
275    // Remove row completely
276    const int idx = m_items.indexOf( item );
277//     tDebug() << "Got index of item:" << idx;
278    Q_ASSERT( idx >= 0 );
279
280    beginRemoveRows( QModelIndex(), idx, idx );
281    m_items.removeAll( item );
282    endRemoveRows();
283
284    if ( item->customDelegate() )
285        emit customDelegateJobRemoved( idx );
286
287    emit refreshDelegates();
288
289//    tLog() << Q_FUNC_INFO << "current jobs of item type: " << m_jobTypeCount[ item->type() ] << ", current queue size of item type: " << m_jobQueue[ item->type() ].size();
290    if ( item->concurrentJobLimit() > 0 )
291    {
292        int currentJobs = m_jobTypeCount[ item->type() ];
293        currentJobs--;
294        m_jobTypeCount[ item->type() ] = currentJobs;
295
296        if ( !m_jobQueue[ item->type() ].isEmpty() )
297        {
298            JobStatusItem* nextItem = m_jobQueue[ item->type() ].dequeue();
299            QMetaObject::invokeMethod( this, "addJob", Qt::QueuedConnection, Q_ARG( JobStatusItem*, nextItem ) );
300        }
301    }
302
303    item->deleteLater();
304}
305
306
307void
308JobStatusModel::itemUpdated()
309{
310//    tLog( LOGVERBOSE ) << Q_FUNC_INFO;
311    JobStatusItem* item = qobject_cast< JobStatusItem* >( sender() );
312    Q_ASSERT( item );
313
314    if ( m_collapseCount.contains( item->type() ) )
315        item = m_collapseCount[ item->type() ].first();
316
317    const QModelIndex idx = index( m_items.indexOf( item ), 0, QModelIndex() );
318    emit dataChanged( idx, idx );
319}