File indexing completed on 2024-05-05 04:59:12
0001 /*************************************************************************** 0002 * Copyright (C) 2007 by Joris Guisson and Ivan Vasic * 0003 * joris.guisson@gmail.com * 0004 * ivasic@gmail.com * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify * 0007 * it under the terms of the GNU General Public License as published by * 0008 * the Free Software Foundation; either version 2 of the License, or * 0009 * (at your option) any later version. * 0010 * * 0011 * This program is distributed in the hope that it will be useful, * 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0014 * GNU General Public License for more details. * 0015 * * 0016 * You should have received a copy of the GNU General Public License * 0017 * along with this program; if not, write to the * 0018 * Free Software Foundation, Inc., * 0019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 0020 ***************************************************************************/ 0021 #include "chunkdownloadmodel.h" 0022 0023 #include <interfaces/torrentfileinterface.h> 0024 #include <interfaces/torrentinterface.h> 0025 #include <util/functions.h> 0026 0027 #include <KLocalizedString> 0028 0029 using namespace bt; 0030 0031 namespace kt 0032 { 0033 0034 ChunkDownloadModel::Item::Item(ChunkDownloadInterface *cd, const QString &files) 0035 : cd(cd) 0036 , files(files) 0037 { 0038 cd->getStats(stats); 0039 } 0040 0041 bool ChunkDownloadModel::Item::changed(int col, bool &modified) const 0042 { 0043 ChunkDownloadInterface::Stats s; 0044 cd->getStats(s); 0045 bool ret = false; 0046 switch (col) { 0047 case 1: 0048 ret = s.pieces_downloaded != stats.pieces_downloaded; 0049 break; 0050 case 2: 0051 ret = s.current_peer_id != stats.current_peer_id; 0052 break; 0053 case 3: 0054 ret = s.download_speed != stats.download_speed; 0055 break; 0056 default: 0057 break; 0058 } 0059 0060 modified = s.pieces_downloaded != stats.pieces_downloaded || s.download_speed != stats.download_speed || s.current_peer_id != stats.current_peer_id; 0061 0062 stats = s; 0063 return ret; 0064 } 0065 0066 QVariant ChunkDownloadModel::Item::data(int col) const 0067 { 0068 switch (col) { 0069 case 0: 0070 return stats.chunk_index; 0071 case 1: 0072 return QString("%1 / %2").arg(stats.pieces_downloaded).arg(stats.total_pieces); 0073 case 2: 0074 return stats.current_peer_id; 0075 case 3: 0076 return BytesPerSecToString(stats.download_speed); 0077 case 4: 0078 return files; 0079 } 0080 return QVariant(); 0081 } 0082 0083 bool ChunkDownloadModel::Item::lessThan(int col, const Item *other) const 0084 { 0085 switch (col) { 0086 case 0: 0087 return stats.chunk_index < other->stats.chunk_index; 0088 case 1: 0089 return stats.pieces_downloaded < other->stats.pieces_downloaded; 0090 case 2: 0091 return stats.current_peer_id < other->stats.current_peer_id; 0092 case 3: 0093 return stats.download_speed < other->stats.download_speed; 0094 case 4: 0095 return files < other->files; 0096 } 0097 return false; 0098 } 0099 0100 ///////////////////////////////////////////////////////////// 0101 0102 ChunkDownloadModel::ChunkDownloadModel(QObject *parent) 0103 : QAbstractTableModel(parent) 0104 , tc(nullptr) 0105 { 0106 sort_column = 0; 0107 sort_order = Qt::AscendingOrder; 0108 } 0109 0110 ChunkDownloadModel::~ChunkDownloadModel() 0111 { 0112 qDeleteAll(items); 0113 } 0114 0115 void ChunkDownloadModel::downloadAdded(bt::ChunkDownloadInterface *cd) 0116 { 0117 if (!tc) 0118 return; 0119 0120 bt::ChunkDownloadInterface::Stats stats; 0121 cd->getStats(stats); 0122 QString files; 0123 int n = 0; 0124 if (tc->getStats().multi_file_torrent) { 0125 for (Uint32 i = 0; i < tc->getNumFiles(); ++i) { 0126 const bt::TorrentFileInterface &tf = tc->getTorrentFile(i); 0127 if (stats.chunk_index >= tf.getFirstChunk() && stats.chunk_index <= tf.getLastChunk()) { 0128 if (n > 0) 0129 files += '\n'; 0130 0131 files += tf.getPath(); 0132 n++; 0133 } else if (stats.chunk_index < tf.getFirstChunk()) 0134 break; 0135 } 0136 } 0137 0138 Item *nitem = new Item(cd, files); 0139 items.append(nitem); 0140 insertRow(items.count() - 1); 0141 sort(sort_column, sort_order); 0142 } 0143 0144 void ChunkDownloadModel::downloadRemoved(bt::ChunkDownloadInterface *cd) 0145 { 0146 int idx = 0; 0147 for (QList<Item *>::iterator i = items.begin(); i != items.end(); i++) { 0148 const Item *item = *i; 0149 if (item->cd == cd) { 0150 items.erase(i); 0151 delete item; 0152 removeRow(idx); 0153 break; 0154 } 0155 idx++; 0156 } 0157 } 0158 0159 void ChunkDownloadModel::changeTC(bt::TorrentInterface *tc) 0160 { 0161 beginResetModel(); 0162 qDeleteAll(items); 0163 items.clear(); 0164 this->tc = tc; 0165 endResetModel(); 0166 } 0167 0168 void ChunkDownloadModel::clear() 0169 { 0170 beginResetModel(); 0171 qDeleteAll(items); 0172 items.clear(); 0173 endResetModel(); 0174 } 0175 0176 void ChunkDownloadModel::update() 0177 { 0178 bool resort = false; 0179 Uint32 idx = 0; 0180 foreach (Item *i, items) { 0181 bool modified = false; 0182 if (i->changed(sort_column, modified)) 0183 resort = true; 0184 0185 if (modified && !resort) 0186 Q_EMIT dataChanged(index(idx, 1), index(idx, 3)); 0187 idx++; 0188 } 0189 0190 if (resort) 0191 sort(sort_column, sort_order); 0192 } 0193 0194 int ChunkDownloadModel::rowCount(const QModelIndex &parent) const 0195 { 0196 if (parent.isValid()) 0197 return 0; 0198 else 0199 return items.count(); 0200 } 0201 0202 int ChunkDownloadModel::columnCount(const QModelIndex &parent) const 0203 { 0204 if (parent.isValid()) 0205 return 0; 0206 else 0207 return 5; 0208 } 0209 0210 QVariant ChunkDownloadModel::headerData(int section, Qt::Orientation orientation, int role) const 0211 { 0212 if (orientation != Qt::Horizontal) 0213 return QVariant(); 0214 0215 if (role == Qt::DisplayRole) { 0216 switch (section) { 0217 case 0: 0218 return i18n("Chunk"); 0219 case 1: 0220 return i18n("Progress"); 0221 case 2: 0222 return i18n("Peer"); 0223 case 3: 0224 return i18n("Down Speed"); 0225 case 4: 0226 return i18n("Files"); 0227 default: 0228 return QVariant(); 0229 } 0230 } else if (role == Qt::ToolTipRole) { 0231 switch (section) { 0232 case 0: 0233 return i18n("Number of the chunk"); 0234 case 1: 0235 return i18n("Download progress of the chunk"); 0236 case 2: 0237 return i18n("Which peer we are downloading it from"); 0238 case 3: 0239 return i18n("Download speed of the chunk"); 0240 case 4: 0241 return i18n("Which files the chunk is located in"); 0242 default: 0243 return QVariant(); 0244 } 0245 } 0246 0247 return QVariant(); 0248 } 0249 0250 QModelIndex ChunkDownloadModel::index(int row, int column, const QModelIndex &parent) const 0251 { 0252 if (!hasIndex(row, column, parent) || parent.isValid()) 0253 return QModelIndex(); 0254 else 0255 return createIndex(row, column, items[row]); 0256 } 0257 0258 QVariant ChunkDownloadModel::data(const QModelIndex &index, int role) const 0259 { 0260 if (!index.isValid() || index.row() >= items.count() || index.row() < 0) 0261 return QVariant(); 0262 0263 if (role == Qt::DisplayRole) 0264 return items[index.row()]->data(index.column()); 0265 0266 return QVariant(); 0267 } 0268 0269 bool ChunkDownloadModel::removeRows(int row, int count, const QModelIndex & /*parent*/) 0270 { 0271 beginRemoveRows(QModelIndex(), row, row + count - 1); 0272 endRemoveRows(); 0273 return true; 0274 } 0275 0276 bool ChunkDownloadModel::insertRows(int row, int count, const QModelIndex & /*parent*/) 0277 { 0278 beginInsertRows(QModelIndex(), row, row + count - 1); 0279 endInsertRows(); 0280 return true; 0281 } 0282 0283 class ChunkDownloadModelItemCmp 0284 { 0285 public: 0286 ChunkDownloadModelItemCmp(int col, Qt::SortOrder order) 0287 : col(col) 0288 , order(order) 0289 { 0290 } 0291 0292 bool operator()(ChunkDownloadModel::Item *a, ChunkDownloadModel::Item *b) 0293 { 0294 if (order == Qt::AscendingOrder) 0295 return a->lessThan(col, b); 0296 else 0297 return !a->lessThan(col, b); 0298 } 0299 0300 int col; 0301 Qt::SortOrder order; 0302 }; 0303 0304 void ChunkDownloadModel::sort(int col, Qt::SortOrder order) 0305 { 0306 sort_column = col; 0307 sort_order = order; 0308 Q_EMIT layoutAboutToBeChanged(); 0309 std::stable_sort(items.begin(), items.end(), ChunkDownloadModelItemCmp(col, order)); 0310 Q_EMIT layoutChanged(); 0311 } 0312 } 0313 0314 #include "moc_chunkdownloadmodel.cpp"