00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <QHeaderView>
00023 #include <QItemSelectionModel>
00024 #include <klocale.h>
00025 #include <kiconloader.h>
00026 #include <kglobal.h>
00027 #include <kmenu.h>
00028 #include <krun.h>
00029 #include <kmessagebox.h>
00030 #include <kmimetype.h>
00031 #include <ksharedconfig.h>
00032 #include <kconfiggroup.h>
00033 #include <kfiledialog.h>
00034 #include <util/bitset.h>
00035 #include <util/error.h>
00036 #include <util/functions.h>
00037 #include <interfaces/torrentinterface.h>
00038 #include <interfaces/torrentfileinterface.h>
00039 #include <qfileinfo.h>
00040 #include <util/log.h>
00041 #include "fileview.h"
00042 #include "iwfiletreemodel.h"
00043 #include "iwfilelistmodel.h"
00044
00045 using namespace bt;
00046
00047 namespace kt
00048 {
00049
00050 FileView::FileView(QWidget *parent) : QTreeView(parent),curr_tc(0),model(0)
00051 {
00052 setContextMenuPolicy(Qt::CustomContextMenu);
00053 setRootIsDecorated(false);
00054 setSortingEnabled(true);
00055 setAlternatingRowColors(true);
00056 setSelectionMode(QAbstractItemView::ExtendedSelection);
00057 setSelectionBehavior(QAbstractItemView::SelectRows);
00058
00059 context_menu = new KMenu(this);
00060 open_action = context_menu->addAction(KIcon("document-open"),i18n("Open"),this,SLOT(open()));
00061 context_menu->addSeparator();
00062 download_first_action = context_menu->addAction(i18n("Download first"),this,SLOT(downloadFirst()));
00063 download_normal_action = context_menu->addAction(i18n("Download normally"),this,SLOT(downloadNormal()));
00064 download_last_action = context_menu->addAction(i18n("Download last"),this,SLOT(downloadLast()));
00065 context_menu->addSeparator();
00066 dnd_action = context_menu->addAction(i18n("Do Not Download"),this,SLOT(doNotDownload()));
00067 delete_action = context_menu->addAction(i18n("Delete File(s)"),this,SLOT(deleteFiles()));
00068 context_menu->addSeparator();
00069 move_files_action = context_menu->addAction(i18n("Move File"),this,SLOT(moveFiles()));
00070
00071 connect(this,SIGNAL(customContextMenuRequested(const QPoint & )),
00072 this,SLOT(showContextMenu(const QPoint& )));
00073 connect(this,SIGNAL(itemDoubleClicked(const QModelIndex & )),
00074 this,SLOT(onDoubleClicked(const QModelIndex & )));
00075
00076 setEnabled(false);
00077 show_list_of_files = false;
00078 }
00079
00080
00081 FileView::~FileView()
00082 {}
00083
00084 void FileView::changeTC(bt::TorrentInterface* tc,KSharedConfigPtr cfg)
00085 {
00086 if (tc == curr_tc)
00087 return;
00088
00089 if (model)
00090 {
00091 saveState(cfg);
00092 if (curr_tc)
00093 expanded_state_map[curr_tc] = model->saveExpandedState(this);
00094 }
00095 setModel(0);
00096 delete model;
00097 model = 0;
00098 curr_tc = tc;
00099 setEnabled(tc != 0);
00100 if (tc)
00101 {
00102 connect(tc,SIGNAL(missingFilesMarkedDND( bt::TorrentInterface* )),
00103 this,SLOT(onMissingFileMarkedDND(bt::TorrentInterface*)));
00104
00105 if (show_list_of_files)
00106 model = new IWFileListModel(tc,this);
00107 else
00108 model = new IWFileTreeModel(tc,this);
00109
00110 setModel(model);
00111 setRootIsDecorated(tc->getStats().multi_file_torrent);
00112 loadState(cfg);
00113 QMap<bt::TorrentInterface*,QByteArray>::iterator i = expanded_state_map.find(tc);
00114 if (i != expanded_state_map.end())
00115 model->loadExpandedState(this,i.value());
00116 else
00117 expandAll();
00118 }
00119 else
00120 {
00121 setModel(0);
00122 model = 0;
00123 }
00124 }
00125
00126 void FileView::onMissingFileMarkedDND(bt::TorrentInterface* tc)
00127 {
00128 if (curr_tc == tc)
00129 model->missingFilesMarkedDND();
00130 }
00131
00132 void FileView::showContextMenu(const QPoint & p)
00133 {
00134 const TorrentStats & s = curr_tc->getStats();
00135
00136 QModelIndexList sel = selectionModel()->selectedRows();
00137 if (sel.count() == 0)
00138 return;
00139
00140 if (sel.count() > 1)
00141 {
00142 download_first_action->setEnabled(true);
00143 download_normal_action->setEnabled(true);
00144 download_last_action->setEnabled(true);
00145 open_action->setEnabled(false);
00146 dnd_action->setEnabled(true);
00147 delete_action->setEnabled(true);
00148 context_menu->popup(mapToGlobal(p));
00149 move_files_action->setEnabled(true);
00150 return;
00151 }
00152
00153 QModelIndex item = sel.front();
00154 bt::TorrentFileInterface* file = model->indexToFile(item);
00155
00156 download_first_action->setEnabled(false);
00157 download_last_action->setEnabled(false);
00158 download_normal_action->setEnabled(false);
00159 dnd_action->setEnabled(false);
00160 delete_action->setEnabled(false);
00161
00162 if (!s.multi_file_torrent)
00163 {
00164 open_action->setEnabled(true);
00165 move_files_action->setEnabled(true);
00166 preview_path = curr_tc->getStats().output_path;
00167 }
00168 else if (file)
00169 {
00170 move_files_action->setEnabled(true);
00171 if (!file->isNull())
00172 {
00173 open_action->setEnabled(true);
00174 preview_path = file->getPathOnDisk();
00175
00176 download_first_action->setEnabled(file->getPriority() != FIRST_PRIORITY);
00177 download_normal_action->setEnabled(file->getPriority() != NORMAL_PRIORITY);
00178 download_last_action->setEnabled(file->getPriority() != LAST_PRIORITY);
00179 dnd_action->setEnabled(file->getPriority() != ONLY_SEED_PRIORITY);
00180 delete_action->setEnabled(file->getPriority() != EXCLUDED);
00181 }
00182 else
00183 {
00184 open_action->setEnabled(false);
00185 }
00186 }
00187 else
00188 {
00189 move_files_action->setEnabled(false);
00190 download_first_action->setEnabled(true);
00191 download_normal_action->setEnabled(true);
00192 download_last_action->setEnabled(true);
00193 dnd_action->setEnabled(true);
00194 delete_action->setEnabled(true);
00195 open_action->setEnabled(true);
00196 preview_path = curr_tc->getDataDir() + model->dirPath(item);
00197 }
00198
00199 context_menu->popup(mapToGlobal(p));
00200 }
00201
00202 void FileView::open()
00203 {
00204 new KRun(KUrl(preview_path), 0, true, true);
00205 }
00206
00207 void FileView::changePriority(bt::Priority newpriority)
00208 {
00209 model->changePriority(selectionModel()->selectedRows(2),newpriority);
00210 }
00211
00212
00213 void FileView::downloadFirst()
00214 {
00215 changePriority(FIRST_PRIORITY);
00216 }
00217
00218 void FileView::downloadLast()
00219 {
00220 changePriority(LAST_PRIORITY);
00221 }
00222
00223 void FileView::downloadNormal()
00224 {
00225 changePriority(NORMAL_PRIORITY);
00226 }
00227
00228 void FileView::doNotDownload()
00229 {
00230 changePriority(ONLY_SEED_PRIORITY);
00231 }
00232
00233 void FileView::deleteFiles()
00234 {
00235 QModelIndexList sel = selectionModel()->selectedRows();
00236 Uint32 n = sel.count();
00237 if (n == 1)
00238 {
00239 if (!model->indexToFile(sel.front()))
00240 n++;
00241 }
00242
00243 QString msg = n > 1 ? i18n("You will lose all data in this file, are you sure you want to do this ?") :
00244 i18n("You will lose all data in these files, are you sure you want to do this ?");
00245
00246 if (KMessageBox::warningYesNo(0,msg) == KMessageBox::Yes)
00247 changePriority(EXCLUDED);
00248 }
00249
00250 void FileView::moveFiles()
00251 {
00252 if (curr_tc->getStats().multi_file_torrent)
00253 {
00254 QModelIndexList sel = selectionModel()->selectedRows();
00255 QMap<bt::TorrentFileInterface*,QString> moves;
00256
00257 QString dir = KFileDialog::getExistingDirectory(KUrl("kfiledialog:///openTorrent"),
00258 this,i18n("Select a directory to move the data to."));
00259 if (dir.isNull())
00260 return;
00261
00262 foreach (QModelIndex idx,sel)
00263 {
00264 bt::TorrentFileInterface* tfi = model->indexToFile(idx);
00265 if (!tfi)
00266 continue;
00267
00268 moves.insert(tfi,dir);
00269 }
00270
00271 if (moves.count() > 0)
00272 {
00273 curr_tc->moveTorrentFiles(moves);
00274 }
00275 }
00276 else
00277 {
00278 QString dir = KFileDialog::getExistingDirectory(KUrl("kfiledialog:///openTorrent"),
00279 this,i18n("Select a directory to move the data to."));
00280 if (dir.isNull())
00281 return;
00282
00283 curr_tc->changeOutputDir(dir,bt::TorrentInterface::MOVE_FILES);
00284 }
00285 }
00286
00287 void FileView::onDoubleClicked(const QModelIndex & index)
00288 {
00289 if (!curr_tc)
00290 return;
00291
00292 const TorrentStats & s = curr_tc->getStats();
00293
00294 if (s.multi_file_torrent)
00295 {
00296 bt::TorrentFileInterface* file = model->indexToFile(index);
00297 if (!file)
00298 {
00299
00300 new KRun(KUrl(curr_tc->getDataDir() + model->dirPath(index)), 0, true, true);
00301 }
00302 else
00303 {
00304
00305 new KRun(KUrl(file->getPathOnDisk()), 0, true, true);
00306 }
00307 }
00308 else
00309 {
00310 new KRun(KUrl(curr_tc->getStats().output_path), 0, true, true);
00311 }
00312 }
00313
00314 void FileView::saveState(KSharedConfigPtr cfg)
00315 {
00316 if (!model)
00317 return;
00318
00319 KConfigGroup g = cfg->group("FileView");
00320 QByteArray s = header()->saveState();
00321 g.writeEntry("state",s.toBase64());
00322 }
00323
00324 void FileView::loadState(KSharedConfigPtr cfg)
00325 {
00326 KConfigGroup g = cfg->group("FileView");
00327 QByteArray s = QByteArray::fromBase64(g.readEntry("state",QByteArray()));
00328 if (!s.isNull())
00329 header()->restoreState(s);
00330 }
00331
00332 void FileView::update()
00333 {
00334 if (model)
00335 model->update();
00336 }
00337
00338 void FileView::onTorrentRemoved(bt::TorrentInterface* tc)
00339 {
00340 expanded_state_map.remove(tc);
00341 }
00342
00343 void FileView::setShowListOfFiles(bool on,KSharedConfigPtr cfg)
00344 {
00345 if (show_list_of_files == on)
00346 return;
00347
00348 show_list_of_files = on;
00349 if (!model || !curr_tc)
00350 return;
00351
00352 saveState(cfg);
00353 expanded_state_map[curr_tc] = model->saveExpandedState(this);
00354
00355 setModel(0);
00356 delete model;
00357 model = 0;
00358
00359 if (show_list_of_files)
00360 model = new IWFileListModel(curr_tc,this);
00361 else
00362 model = new IWFileTreeModel(curr_tc,this);
00363
00364 setModel(model);
00365 setRootIsDecorated(curr_tc->getStats().multi_file_torrent);
00366 loadState(cfg);
00367 QMap<bt::TorrentInterface*,QByteArray>::iterator i = expanded_state_map.find(curr_tc);
00368 if (i != expanded_state_map.end())
00369 model->loadExpandedState(this,i.value());
00370 else
00371 expandAll();
00372 }
00373 }
00374
00375 #include "fileview.moc"