/* Copyright 2003 Rikard Björklind, Mikael Gransell This file is part of dc-qt. dc-qt is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. dc-qt is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dc-qt; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "file_transfer_lv.h" #include "dc_file.h" #include "debugdlg.h" #include #include #include #include const int CANCEL = 0; const int FLIST = 1; file_transfer_lv::file_transfer_lv(int aType,QWidget* parent, const char *name) : QListView(parent, name) { timer = NULL; type = aType; setAllColumnsShowFocus(true); addColumn("Nick"); if(type==DOWNLOAD) addColumn("Status"); addColumn("Size"); addColumn("Percent"); addColumn("Speed"); addColumn("ETA"); addColumn("File"); if(type==DOWNLOAD) addColumn("Range"); menu = new QPopupMenu(this, "file_transfer_lv menu"); menu->insertItem("Cancel", CANCEL); menu->insertItem("Get User File List", FLIST); connect (menu, SIGNAL(activated(int)), SLOT(menu_clicked(int))); connect (this, SIGNAL(rightButtonClicked(QListViewItem*, const QPoint&, int)), SLOT(show_menu(QListViewItem*, const QPoint&, int))); last_clicked = 0; } /// Add a download void file_transfer_lv::add_transfer(int gdl, const QString &nick) { debugWin->print("Found! Adding...\n"); if(!timer) { timer = new QTimer(this); timer->start(1000); connect(timer, SIGNAL(timeout()), SLOT(update_all())); } if( !timer->isActive() ) timer->start(1000); file_transfer_lv_item *item = new file_transfer_lv_item(this, gdl, nick,QString::null,type); insertItem(item); transfers.push_back(item); } /// Add an upload. Uploads and downloads are treated differently thanks to dctc. void file_transfer_lv::add_transfer(int id,const QString &nick, const QString &filename) { file_transfer_lv_item *item = new file_transfer_lv_item(this,id,nick,filename,type); insertItem( item ); // Insert the item into the QListView transfers.push_back( item ); // Insert the item into our own list of transfers } /// Removes an upload, given the nick and file name. Stupid dctc won't let us know the id. void file_transfer_lv::removeTransfer(const QString &nick, const QString &fname) { list::iterator i = transfers.begin(); while(i!=transfers.end()) { if( (*i)->transfer_user() == nick && (*i)->transfer_file() == fname ) { takeItem(*i); transfers.erase(i); break; } i++; } } /// Updates transfer information about a download. /// This function handles all adding, updating of downloads. void file_transfer_lv::transfer_info(int gdl, const QString &fname, int totSize, int recSize, int recLast10, const QString &users, const QString &status ) { // First parse the users and statuses strings QStringList llusers = QStringList::split('|',users); QStringList llstatus = QStringList::split('|',status); unsigned int numFound = 0; list::iterator i = transfers.begin(); while(i!=transfers.end()) { if ((*i)->transfer_id() == gdl) { debugWin->print("processing transfer, gdl=" + QString::number(gdl) + "user=" +(*i)->transfer_user() + "\n"); // We've found a transfer. Check if it is in the llusers list and remove // it if not (multidownload source removed) if(llusers.contains((*i)->transfer_user())==0) { debugWin->print("llusers does not contain " + (*i)->transfer_user() + ", removing.\n"); // Move it to the history emit transferDone( (*i)->transfer_user(), (*i)->transfer_file() ); delete *i; i = transfers.erase(i); continue; } // Mark this download as active so that we dont remove it when the gdl-info list ends (*i)->SetActive(true); // If the filenames dont match, it is the first time we receive info about the DL. // A signal is emitted so that the transferdlg can remove it from the queue. if( fname != (*i)->transfer_file()) emit transferStart((*i)->transfer_user(), fname); // Now, the user of this entry should be in the users list. Find it. int index = llusers.findIndex( (*i)->transfer_user() ); // Extract the corresponding status string const QString stat = llstatus[index]; debugWin->print("stat=" + stat + "\n"); // Get some info from it /* tt is the status: 'W' for waiting, 'T' for trying and 'Rhhh[iii;jjj]' for running (hhh is the number of bytes downloaded in the range, iii is the download start position and jjj is the download end position (excluded).*/ int s; QString range; if( stat=="W" ) { delete *i; i = transfers.erase(i); continue; } if( stat=="T" ) s = STATUS_TRYING; if( stat[0]=='R') { s = STATUS_RUNNING; QString bajs = stat.section('[',1); range = bajs.section(';',0,0) + " - " + bajs.section(';',1,1); range.truncate( range.length()-1 ); } (*i)->update( fname, totSize, recSize, recLast10); (*i)->update( s, range ); (*i)->update_data(); numFound++; } i++; } // If we found less entrys than entrys in the llusers list, another multidownload source // has been added and we need to add it to the transfer list. debugWin->print("Checking if we should add this...\n"); if(numFound < llusers.count()) { int index=0; debugWin->print("Adding " + fname + "...\n"); for(QStringList::iterator iter = llusers.begin();iter!=llusers.end();iter++) { debugWin->print("Checking user " + *iter + "...\n"); // If this user is not in the list, add it bool found = false; list::iterator i = transfers.begin(); while(i!=transfers.end()) { if ((*i)->transfer_id() == gdl) if((*i)->transfer_user() == *iter) { found = true; break; } i++; } if(!found && llstatus[index]!="W") { add_transfer(gdl,*iter); } index++; } } } /// Updates transfer information about an upload void file_transfer_lv::transfer_info(int id, int totSize, int amountSent) { // Find the item list::iterator i = transfers.begin(); while( i!=transfers.end() && (*i)->transfer_id() !=id) i++; if( i == transfers.end() ) return; // This would mean a programming error (*i)->update( totSize, amountSent ); (*i)->update_data(); } // void file_transfer_lv::active_transfers( list &llGdlIds ) // { // for( list::iterator i = transfers.begin(); // i != transfers.end();) // { // bool contains = false; // for( list::iterator gi=llGdlIds.begin();gi!=llGdlIds.end();gi++) // if( (*gi) == (*i)->transfer_id()) contains = true; // // If the element is not in the current gdlId list, remove it // if( !contains ) // { // QString user = (*i)->transfer_user(); // QString fileName = (*i)->transfer_file(); // takeItem(*i); // transfers.erase(i); // i = transfers.begin(); // dont know if this is necessary // emit transferDone(user,fileName); // timer->stop(); // } // else i++; // to avoid advancement of the iterator when rewinding // } // } void file_transfer_lv::update_all() { emit update_dlist(); } void file_transfer_lv::menu_clicked(int i) { if (!last_clicked) return; if (i == CANCEL) { // Check if this is the only download with this GDL id. // list::iterator fi = transfers.begin(); // while(fi!=transfers.end()) // if( (*fi) != last_clicked && (*fi)->transfer_id() == last_clicked->transfer_id() ) // { // emit remove_source(last_clicked()->transfer_id(),last_clicked()->transfer_user(), emit cancel_transfer (last_clicked->transfer_id()); } if (i == FLIST) { emit get_flist(last_clicked->transfer_user()); } } void file_transfer_lv::show_menu(QListViewItem* i, const QPoint &p, int) { if(i) { menu->popup(p); last_clicked = (file_transfer_lv_item*)i; } } /// Removes downloads flagged as inactive (triggered by dctc_hub::gdlListEnd()) void file_transfer_lv::removeInactive() { /* for( list::iterator i = transfers.begin(); i != transfers.end();) { if( !(*i)->IsActive() ) { debugWin->print("Transfer " + (*i)->text(0) + " is inactive.\n"); emit transferDone( (*i)->transfer_user(), (*i)->transfer_file() ); delete *i; i = transfers.erase(i); } else { i++; } } for( list::iterator i = transfers.begin();i != transfers.end();i++) (*i)->SetActive(false); */ } file_transfer_lv_item *file_transfer_lv::findTransfer(const QString& file) { for( list::iterator i = transfers.begin();i != transfers.end();i++) { //debugWin->print("Comparing " + file + " and " + (*i)->transfer_file() + "\n"); if( (*i)->transfer_file() == file ) return *i; } return 0; } void file_transfer_lv::storeGDL(int gdlId, const QString& nick, const QString& remoteName, const QString& localName, int size) { llFiles.push_back( new file_transfer( gdlId, nick, localName, remoteName,size )); } file_transfer* file_transfer_lv::findTransferRequest(const QString& localFile) { for( list::iterator i = llFiles.begin(); i != llFiles.end(); i++ ) if((*i)->transfer_file() == localFile) return *i; return 0; }