File indexing completed on 2024-05-12 04:59:20

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 "iwfiletreemodel.h"
0022 
0023 #include <KLocalizedString>
0024 #include <cmath>
0025 
0026 #include <interfaces/torrentfileinterface.h>
0027 #include <interfaces/torrentinterface.h>
0028 #include <util/functions.h>
0029 
0030 using namespace bt;
0031 
0032 namespace kt
0033 {
0034 
0035 IWFileTreeModel::IWFileTreeModel(bt::TorrentInterface *tc, QObject *parent)
0036     : TorrentFileTreeModel(tc, KEEP_FILES, parent)
0037 {
0038     mmfile = IsMultimediaFile(tc->getStats().output_path);
0039     preview = false;
0040     percentage = 0;
0041 
0042     if (root) {
0043         BitSet d = tc->downloadedChunksBitSet();
0044         d -= tc->onlySeedChunksBitSet();
0045         root->initPercentage(tc, d);
0046     }
0047 }
0048 
0049 IWFileTreeModel::~IWFileTreeModel()
0050 {
0051 }
0052 
0053 int IWFileTreeModel::columnCount(const QModelIndex & /*parent*/) const
0054 {
0055     return 5;
0056 }
0057 
0058 QVariant IWFileTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
0059 {
0060     if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
0061         return QVariant();
0062 
0063     if (section < 2)
0064         return TorrentFileTreeModel::headerData(section, orientation, role);
0065 
0066     switch (section) {
0067     case 2:
0068         return i18n("Priority");
0069     case 3:
0070         return i18n("Preview");
0071     // xgettext: no-c-format
0072     case 4:
0073         return i18nc("Percent of File Downloaded", "% Complete");
0074     default:
0075         return QVariant();
0076     }
0077 }
0078 
0079 static QString PriorityString(const bt::TorrentFileInterface *file)
0080 {
0081     switch (file->getPriority()) {
0082     case FIRST_PREVIEW_PRIORITY:
0083     case FIRST_PRIORITY:
0084         return i18nc("Download first", "First");
0085     case LAST_PREVIEW_PRIORITY:
0086     case LAST_PRIORITY:
0087         return i18nc("Download last", "Last");
0088     case ONLY_SEED_PRIORITY:
0089     case EXCLUDED:
0090         return QString();
0091     case NORMAL_PREVIEW_PRIORITY:
0092     default:
0093         return i18nc("Download normally(not as first or last)", "Normal");
0094     }
0095 }
0096 
0097 QVariant IWFileTreeModel::data(const QModelIndex &index, int role) const
0098 {
0099     Node *n = nullptr;
0100     if (index.column() < 2 && role != Qt::ForegroundRole)
0101         return TorrentFileTreeModel::data(index, role);
0102 
0103     if (!index.isValid() || !(n = (Node *)index.internalPointer()))
0104         return QVariant();
0105 
0106     if (role == Qt::ForegroundRole && index.column() == 2 && tc->getStats().multi_file_torrent && n->file)
0107         return QVariant();
0108 
0109     if (role == Qt::DisplayRole)
0110         return displayData(n, index);
0111     else if (role == Qt::UserRole)
0112         return sortData(n, index);
0113 
0114     return QVariant();
0115 }
0116 
0117 QVariant IWFileTreeModel::displayData(Node *n, const QModelIndex &index) const
0118 {
0119     if (tc->getStats().multi_file_torrent && n->file) {
0120         const bt::TorrentFileInterface *file = n->file;
0121         switch (index.column()) {
0122         case 2:
0123             return PriorityString(file);
0124         case 3:
0125             if (file->isMultimedia()) {
0126                 if (file->isPreviewAvailable())
0127                     return i18nc("preview available", "Available");
0128                 else
0129                     return i18nc("Preview pending", "Pending");
0130             } else
0131                 return i18nc("No preview available", "No");
0132         case 4:
0133             if (file->getPriority() == ONLY_SEED_PRIORITY || file->getPriority() == EXCLUDED)
0134                 return QVariant();
0135             else
0136                 return ki18n("%1 %").subs(n->percentage, 0, 'f', 2).toString();
0137         default:
0138             return QVariant();
0139         }
0140     } else if (!tc->getStats().multi_file_torrent) {
0141         switch (index.column()) {
0142         case 2:
0143             return QVariant();
0144         case 3:
0145             if (mmfile) {
0146                 if (tc->readyForPreview())
0147                     return i18nc("Preview available", "Available");
0148                 else
0149                     return i18nc("Preview pending", "Pending");
0150             } else
0151                 return i18nc("No preview available", "No");
0152         case 4:
0153             return ki18n("%1 %").subs(bt::Percentage(tc->getStats()), 0, 'f', 2).toString();
0154         default:
0155             return QVariant();
0156         }
0157     } else if (tc->getStats().multi_file_torrent && index.column() == 4) {
0158         return ki18n("%1 %").subs(n->percentage, 0, 'f', 2).toString();
0159     }
0160 
0161     return QVariant();
0162 }
0163 
0164 QVariant IWFileTreeModel::sortData(Node *n, const QModelIndex &index) const
0165 {
0166     if (tc->getStats().multi_file_torrent && n->file) {
0167         const bt::TorrentFileInterface *file = n->file;
0168         switch (index.column()) {
0169         case 2:
0170             return (int)file->getPriority();
0171         case 3:
0172             if (file->isMultimedia()) {
0173                 if (file->isPreviewAvailable())
0174                     return 3;
0175                 else
0176                     return 2;
0177             } else
0178                 return 1;
0179         case 4:
0180             return n->percentage;
0181         }
0182     } else if (!tc->getStats().multi_file_torrent) {
0183         switch (index.column()) {
0184         case 2:
0185             return QVariant();
0186         case 3:
0187             if (mmfile) {
0188                 if (tc->readyForPreview())
0189                     return 3;
0190                 else
0191                     return 2;
0192             } else
0193                 return 1;
0194         case 4:
0195             return bt::Percentage(tc->getStats());
0196         }
0197     } else if (tc->getStats().multi_file_torrent && index.column() == 4) {
0198         return n->percentage;
0199     }
0200 
0201     return QVariant();
0202 }
0203 
0204 bool IWFileTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
0205 {
0206     if (role == Qt::CheckStateRole)
0207         return TorrentFileTreeModel::setData(index, value, role);
0208 
0209     if (!index.isValid() || role != Qt::UserRole)
0210         return false;
0211 
0212     Node *n = static_cast<Node *>(index.internalPointer());
0213     if (!n)
0214         return false;
0215 
0216     if (!n->file) {
0217         for (int i = 0; i < n->children.count(); i++) {
0218             // recurse down the tree
0219             setData(index.model()->index(i, 0), value, role);
0220         }
0221     } else {
0222         bt::TorrentFileInterface *file = n->file;
0223         auto prio = (bt::Priority)value.toInt();
0224         Priority old = file->getPriority();
0225 
0226         if (prio != old) {
0227             file->setPriority(prio);
0228             dataChanged(createIndex(index.row(), 0), createIndex(index.row(), 4));
0229             QModelIndex parent = index.parent();
0230             if (parent.isValid())
0231                 dataChanged(parent, parent); // parent needs to be updated to
0232         }
0233     }
0234 
0235     return true;
0236 }
0237 
0238 void IWFileTreeModel::filePercentageChanged(bt::TorrentFileInterface *file, float percentage)
0239 {
0240     Q_UNUSED(percentage)
0241     update(index(0, 0, QModelIndex()), file, 4);
0242 }
0243 
0244 void IWFileTreeModel::filePreviewChanged(bt::TorrentFileInterface *file, bool preview)
0245 {
0246     Q_UNUSED(preview)
0247     update(index(0, 0, QModelIndex()), file, 3);
0248 }
0249 
0250 void IWFileTreeModel::update(const QModelIndex &idx, bt::TorrentFileInterface *file, int col)
0251 {
0252     Node *n = (Node *)idx.internalPointer();
0253     if (n->file && n->file == file) {
0254         QModelIndex i = createIndex(idx.row(), col, n);
0255         Q_EMIT dataChanged(i, i);
0256         if (col == 4) {
0257             // update percentages along the tree
0258             // this will go back up the tree and update the percentage of
0259             // all directories involved
0260             BitSet d = tc->downloadedChunksBitSet();
0261             d -= tc->onlySeedChunksBitSet();
0262             n->updatePercentage(d);
0263 
0264             // Q_EMIT necessary signals
0265             QModelIndex parent = idx.parent();
0266             while (parent.isValid()) {
0267                 Node *nd = (Node *)parent.internalPointer();
0268                 i = createIndex(parent.row(), 4, nd);
0269                 Q_EMIT dataChanged(i, i);
0270                 parent = parent.parent();
0271             }
0272         }
0273     } else {
0274         for (int i = 0; i < n->children.count(); i++) {
0275             // recurse down the tree
0276             update(idx.model()->index(i, 0), file, col);
0277         }
0278     }
0279 }
0280 
0281 void IWFileTreeModel::update()
0282 {
0283     if (!tc->getStats().multi_file_torrent) {
0284         bool changed = false;
0285         bool np = mmfile && tc->readyForPreview();
0286         if (preview != np) {
0287             preview = np;
0288             changed = true;
0289         }
0290 
0291         double perc = bt::Percentage(tc->getStats());
0292         if (fabs(perc - percentage) > 0.01) {
0293             percentage = perc;
0294             changed = true;
0295         }
0296 
0297         if (changed)
0298             dataChanged(createIndex(0, 2), createIndex(0, 4));
0299     }
0300 }
0301 }
0302 
0303 #include "moc_iwfiletreemodel.cpp"