1/* 2 * This file Copyright (C) Mnemosyne LLC 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 6 * as published by the Free Software Foundation. 7 * 8 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html 9 * 10 * $Id: torrent-filter.cc 12653 2011-08-08 16:58:29Z jordan $ 11 */ 12 13#include <iostream> 14 15#include "filters.h" 16#include "hig.h" 17#include "prefs.h" 18#include "torrent.h" 19#include "torrent-filter.h" 20#include "torrent-model.h" 21#include "utils.h" 22 23TorrentFilter :: TorrentFilter( Prefs& prefs ): 24 myPrefs( prefs ) 25{ 26 // listen for changes to the preferences to know when to refilter / resort 27 connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(refreshPref(int))); 28 29 setDynamicSortFilter( true ); 30 31 // initialize our state from the current prefs 32 QList<int> initKeys; 33 initKeys << Prefs :: SORT_MODE 34 << Prefs :: FILTER_MODE 35 << Prefs :: FILTER_TRACKERS 36 << Prefs :: FILTER_TEXT; 37 foreach( int key, initKeys ) 38 refreshPref( key ); 39} 40 41TorrentFilter :: ~TorrentFilter( ) 42{ 43} 44 45void 46TorrentFilter :: refreshPref( int key ) 47{ 48 switch( key ) 49 { 50 case Prefs :: FILTER_TEXT: 51 case Prefs :: FILTER_MODE: 52 case Prefs :: FILTER_TRACKERS: 53 invalidateFilter( ); 54 /* force a re-sort */ 55 sort( 0, !myPrefs.getBool(Prefs::SORT_REVERSED) ? Qt::AscendingOrder : Qt::DescendingOrder ); 56 57 case Prefs :: SORT_MODE: 58 case Prefs :: SORT_REVERSED: 59 sort( 0, myPrefs.getBool(Prefs::SORT_REVERSED) ? Qt::AscendingOrder : Qt::DescendingOrder ); 60 invalidate( ); 61 break; 62 } 63} 64 65/*** 66**** 67***/ 68 69namespace 70{ 71 template <typename T> int compare( const T a, const T b ) 72 { 73 if( a < b ) return -1; 74 if( b < a ) return 1; 75 return 0; 76 } 77} 78 79bool 80TorrentFilter :: lessThan( const QModelIndex& left, const QModelIndex& right ) const 81{ 82 int val = 0; 83 const Torrent * a = sourceModel()->data( left, TorrentModel::TorrentRole ).value<const Torrent*>(); 84 const Torrent * b = sourceModel()->data( right, TorrentModel::TorrentRole ).value<const Torrent*>(); 85 86 switch( myPrefs.get<SortMode>(Prefs::SORT_MODE).mode() ) 87 { 88 case SortMode :: SORT_BY_QUEUE: 89 if( !val ) val = -compare( a->queuePosition(), b->queuePosition() ); 90 break; 91 case SortMode :: SORT_BY_SIZE: 92 if( !val ) val = compare( a->sizeWhenDone(), b->sizeWhenDone() ); 93 break; 94 case SortMode :: SORT_BY_AGE: 95 val = compare( a->dateAdded().toTime_t(), b->dateAdded().toTime_t() ); 96 break; 97 case SortMode :: SORT_BY_ID: 98 if( !val ) val = compare( a->id(), b->id() ); 99 break; 100 case SortMode :: SORT_BY_ACTIVITY: 101 if( !val ) val = compare( a->downloadSpeed() + a->uploadSpeed(), b->downloadSpeed() + b->uploadSpeed() ); 102 if( !val ) val = compare( a->uploadedEver(), b->uploadedEver() ); 103 // fall through 104 case SortMode :: SORT_BY_STATE: 105 if( !val ) val = compare( a->hasError(), b->hasError() ); 106 if( !val ) val = compare( a->getActivity(), b->getActivity() ); 107 if( !val ) val = -compare( a->queuePosition(), b->queuePosition() ); 108 // fall through 109 case SortMode :: SORT_BY_PROGRESS: 110 if( !val ) val = compare( a->percentComplete(), b->percentComplete() ); 111 if( !val ) val = a->compareSeedRatio( *b ); 112 if( !val ) val = -compare( a->queuePosition(), b->queuePosition() ); 113 case SortMode :: SORT_BY_RATIO: 114 if( !val ) val = a->compareRatio( *b ); 115 break; 116 case SortMode :: SORT_BY_ETA: 117 if( !val ) val = a->compareETA( *b ); 118 break; 119 default: 120 break; 121 } 122 if( val == 0 ) 123 val = -a->name().compare( b->name(), Qt::CaseInsensitive ); 124 if( val == 0 ) 125 val = compare( a->hashString(), b->hashString() ); 126 return val < 0; 127} 128 129 130/*** 131**** 132***/ 133 134bool 135TorrentFilter :: trackerFilterAcceptsTorrent( const Torrent * tor, const QString& tracker ) const 136{ 137 return tracker.isEmpty() || tor->hasTrackerSubstring( tracker ); 138} 139 140bool 141TorrentFilter :: activityFilterAcceptsTorrent( const Torrent * tor, const FilterMode& m ) const 142{ 143 bool accepts; 144 145 switch( m.mode( ) ) 146 { 147 case FilterMode::SHOW_ACTIVE: 148 accepts = tor->peersWeAreUploadingTo( ) > 0 || tor->peersWeAreDownloadingFrom( ) > 0 || tor->isVerifying( ); 149 break; 150 case FilterMode::SHOW_DOWNLOADING: 151 accepts = tor->isDownloading( ) || tor->isWaitingToDownload( ); 152 break; 153 case FilterMode::SHOW_SEEDING: 154 accepts = tor->isSeeding( ) || tor->isWaitingToSeed( ); 155 break; 156 case FilterMode::SHOW_PAUSED: 157 accepts = tor->isPaused( ); 158 break; 159 case FilterMode::SHOW_FINISHED: 160 accepts = tor->isFinished( ); 161 break; 162 case FilterMode::SHOW_VERIFYING: 163 accepts = tor->isVerifying( ) || tor->isWaitingToVerify( ); 164 break; 165 case FilterMode::SHOW_ERROR: 166 accepts = tor->hasError( ); 167 break; 168 default: // FilterMode::SHOW_ALL 169 accepts = true; 170 break; 171 } 172 173 return accepts; 174} 175 176bool 177TorrentFilter :: filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const 178{ 179 QModelIndex childIndex = sourceModel()->index( sourceRow, 0, sourceParent ); 180 const Torrent * tor = childIndex.model()->data( childIndex, TorrentModel::TorrentRole ).value<const Torrent*>(); 181 bool accepts = true; 182 183 if( accepts ) { 184 const FilterMode m = myPrefs.get<FilterMode>(Prefs::FILTER_MODE); 185 accepts = activityFilterAcceptsTorrent( tor, m ); 186 } 187 188 if( accepts ) { 189 const QString trackers = myPrefs.getString(Prefs::FILTER_TRACKERS); 190 accepts = trackerFilterAcceptsTorrent( tor, trackers ); 191 } 192 193 if( accepts ) { 194 const QString text = myPrefs.getString( Prefs::FILTER_TEXT ); 195 if( !text.isEmpty( ) ) 196 accepts = tor->name().contains( text, Qt::CaseInsensitive ); 197 } 198 199 return accepts; 200} 201 202int 203TorrentFilter :: hiddenRowCount( ) const 204{ 205 return sourceModel()->rowCount( ) - rowCount( ); 206} 207 208int 209TorrentFilter :: count( const FilterMode& mode ) const 210{ 211 int count = 0; 212 213 for( int row=0; ; ++row ) { 214 QModelIndex index = sourceModel()->index( row, 0 ); 215 if( !index.isValid( ) ) 216 break; 217 const Torrent * tor = index.data( TorrentModel::TorrentRole ).value<const Torrent*>(); 218 if( activityFilterAcceptsTorrent( tor, mode ) ) 219 ++count; 220 } 221 222 return count; 223} 224