/* * This file Copyright (C) Mnemosyne LLC * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * $Id$ */ #include #include #include "filters.h" #include "hig.h" #include "prefs.h" #include "torrent.h" #include "torrent-filter.h" #include "torrent-model.h" #include "utils.h" TorrentFilter :: TorrentFilter( Prefs& prefs ): myPrefs( prefs ) { // listen for changes to the preferences to know when to refilter / resort connect( &myPrefs, SIGNAL(changed(int)), this, SLOT(refreshPref(int))); setDynamicSortFilter( true ); // initialize our state from the current prefs QList initKeys; initKeys << Prefs :: SORT_MODE << Prefs :: FILTER_MODE << Prefs :: FILTER_TRACKERS << Prefs :: FILTER_TEXT; foreach( int key, initKeys ) refreshPref( key ); } TorrentFilter :: ~TorrentFilter( ) { } void TorrentFilter :: refreshPref( int key ) { switch( key ) { case Prefs :: FILTER_TEXT: case Prefs :: FILTER_MODE: case Prefs :: FILTER_TRACKERS: invalidateFilter( ); /* force a re-sort */ sort( 0, !myPrefs.getBool(Prefs::SORT_REVERSED) ? Qt::AscendingOrder : Qt::DescendingOrder ); case Prefs :: SORT_MODE: case Prefs :: SORT_REVERSED: sort( 0, myPrefs.getBool(Prefs::SORT_REVERSED) ? Qt::AscendingOrder : Qt::DescendingOrder ); invalidate( ); break; } } /*** **** ***/ namespace { template int compare( const T a, const T b ) { if( a < b ) return -1; if( b < a ) return 1; return 0; } } bool TorrentFilter :: lessThan( const QModelIndex& left, const QModelIndex& right ) const { int val = 0; const Torrent * a = sourceModel()->data( left, TorrentModel::TorrentRole ).value(); const Torrent * b = sourceModel()->data( right, TorrentModel::TorrentRole ).value(); switch( myPrefs.get(Prefs::SORT_MODE).mode() ) { case SortMode :: SORT_BY_QUEUE: if( !val ) val = -compare( a->queuePosition(), b->queuePosition() ); break; case SortMode :: SORT_BY_SIZE: if( !val ) val = compare( a->sizeWhenDone(), b->sizeWhenDone() ); break; case SortMode :: SORT_BY_AGE: val = compare( a->dateAdded().toTime_t(), b->dateAdded().toTime_t() ); break; case SortMode :: SORT_BY_ID: if( !val ) val = compare( a->id(), b->id() ); break; case SortMode :: SORT_BY_ACTIVITY: if( !val ) val = compare( a->downloadSpeed() + a->uploadSpeed(), b->downloadSpeed() + b->uploadSpeed() ); if( !val ) val = compare( a->peersWeAreUploadingTo() + a->webseedsWeAreDownloadingFrom(), b->peersWeAreUploadingTo() + b->webseedsWeAreDownloadingFrom()); // fall through case SortMode :: SORT_BY_STATE: if( !val ) val = -compare( a->isPaused(), b->isPaused() ); if( !val ) val = compare( a->getActivity(), b->getActivity() ); if( !val ) val = -compare( a->queuePosition(), b->queuePosition() ); if( !val ) val = compare( a->hasError(), b->hasError() ); // fall through case SortMode :: SORT_BY_PROGRESS: if( !val ) val = compare( a->percentComplete(), b->percentComplete() ); if( !val ) val = a->compareSeedRatio( *b ); if( !val ) val = -compare( a->queuePosition(), b->queuePosition() ); case SortMode :: SORT_BY_RATIO: if( !val ) val = a->compareRatio( *b ); break; case SortMode :: SORT_BY_ETA: if( !val ) val = a->compareETA( *b ); break; default: break; } if( val == 0 ) val = -a->name().compare( b->name(), Qt::CaseInsensitive ); if( val == 0 ) val = compare( a->hashString(), b->hashString() ); return val < 0; } /*** **** ***/ bool TorrentFilter :: trackerFilterAcceptsTorrent( const Torrent * tor, const QString& tracker ) const { return tracker.isEmpty() || tor->hasTrackerSubstring( tracker ); } bool TorrentFilter :: activityFilterAcceptsTorrent( const Torrent * tor, const FilterMode& m ) const { bool accepts; switch( m.mode( ) ) { case FilterMode::SHOW_ACTIVE: accepts = tor->peersWeAreUploadingTo( ) > 0 || tor->peersWeAreDownloadingFrom( ) > 0 || tor->isVerifying( ); break; case FilterMode::SHOW_DOWNLOADING: accepts = tor->isDownloading( ) || tor->isWaitingToDownload( ); break; case FilterMode::SHOW_SEEDING: accepts = tor->isSeeding( ) || tor->isWaitingToSeed( ); break; case FilterMode::SHOW_PAUSED: accepts = tor->isPaused( ); break; case FilterMode::SHOW_FINISHED: accepts = tor->isFinished( ); break; case FilterMode::SHOW_VERIFYING: accepts = tor->isVerifying( ) || tor->isWaitingToVerify( ); break; case FilterMode::SHOW_ERROR: accepts = tor->hasError( ); break; default: // FilterMode::SHOW_ALL accepts = true; break; } return accepts; } bool TorrentFilter :: filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const { QModelIndex childIndex = sourceModel()->index( sourceRow, 0, sourceParent ); const Torrent * tor = childIndex.model()->data( childIndex, TorrentModel::TorrentRole ).value(); bool accepts = true; if( accepts ) { const FilterMode m = myPrefs.get(Prefs::FILTER_MODE); accepts = activityFilterAcceptsTorrent( tor, m ); } if( accepts ) { const QString trackers = myPrefs.getString(Prefs::FILTER_TRACKERS); accepts = trackerFilterAcceptsTorrent( tor, trackers ); } if( accepts ) { const QString text = myPrefs.getString( Prefs::FILTER_TEXT ); if( !text.isEmpty( ) ) accepts = tor->name().contains( text, Qt::CaseInsensitive ); } return accepts; } int TorrentFilter :: hiddenRowCount( ) const { return sourceModel()->rowCount( ) - rowCount( ); } void TorrentFilter :: countTorrentsPerMode (int * setmeCounts) const { std::fill_n (setmeCounts, FilterMode::NUM_MODES, 0); for (int row(0); ; ++row) { QModelIndex index (sourceModel()->index(row, 0)); if (!index.isValid()) break; const Torrent * tor (index.data( TorrentModel::TorrentRole ).value()); for (int mode(0); mode