QString QTorrentItemDelegat::GetStatusString(const Torrent& tor) const { QString upSpeed(tor.GetUploadSpeed()); QString downSpeed(tor.GetDwonloadSpeed()); QString status(tor.GetStatusString()); bool hasError(tor.hasError()); if(hasError) { return tor.GetErrorMessage(); } if(tor.isPaused()) { return tr("STR_PAUSED"); } if(tor.isDownloading()) { return QString("%1: %2 %3 - %4 %5").arg(status).arg(QChar(0x2193)).arg(downSpeed).arg(QChar(0x2191)).arg(upSpeed); } if(tor.isSeeding()) { if(!upSpeed.isEmpty()) { return QString("%2 %3 - %1").arg(status).arg(QChar(0x2191)).arg(upSpeed); } } return status; }
QSize QTorrentItemDelegat::sizeHint(const QStyleOptionViewItem& option, const Torrent& tor) const { try { const QStyle* style(QApplication::style()); const int iconSize(style->pixelMetric(QStyle::PM_MessageBoxIconSize)); QFont nameFont(option.font); nameFont.setWeight(QFont::Bold); const QFontMetrics nameFM(nameFont); const QString nameStr(tor.GetName()); int nameWidth = nameFM.width(nameStr); QFont statusFont(option.font); statusFont.setPointSize(int (option.font.pointSize() * 0.9)); const QFontMetrics statusFM(statusFont); const QString statusStr(GetStatusString(tor)); int statusWidth = statusFM.width(statusStr); QFont progressFont(statusFont); const QFontMetrics progressFM(progressFont); const QString progressStr(GetProgressString(tor)); const int progressWidth = progressFM.width(progressStr); const QSize m(margin(*style)); int width = m.width() + iconSize + std::max(nameWidth, statusWidth + progressWidth); int height = m.height() * 3 + nameFM.lineSpacing() + 2 * GUI_PAD + progressFM.lineSpacing(); return QSize(width, height); } catch(...) { qDebug() << "exception in size hint"; } return QSize(0, 0); }
QString QTorrentItemDelegat::GetProgressString(const Torrent& tor) const { if(tor.isDownloading()) { return tr("%1 STR_DOWNLOADED %2 STR_FROM %3").arg(tor.GetProgresString()).arg(tor.GetTotalDownloaded()).arg(tor.GetTotalSize()); } if(tor.isSeeding()) { return tr("%1 - %3 STR_UPLOADED %2").arg(tor.GetProgresString()).arg(tor.GetTotalUploaded()).arg(tor.GetTotalSize()); } return tor.GetProgresString(); }
ChunkManager::Private::Private(ChunkManager* p, Torrent& tor, const QString & tmpdir, const QString & datadir, bool custom_output_name, CacheFactory* fac) : p(p),chunks(tor.getNumChunks()),todo(tor.getNumChunks()) { during_load = false; todo.setAll(true); if (!fac) { if (tor.isMultiFile()) cache = new MultiFileCache(tor,tmpdir,datadir,custom_output_name); else cache = new SingleFileCache(tor,tmpdir,datadir); } else cache = fac->create(tor,tmpdir,datadir); cache->loadFileMap(); index_file = tmpdir + "index"; file_info_file = tmpdir + "file_info"; file_priority_file = tmpdir + "file_priority"; Uint64 tsize = tor.getTotalSize(); // total size Uint64 csize = tor.getChunkSize(); // chunk size Uint64 lsize = tsize - (csize * (tor.getNumChunks() - 1)); // size of last chunk for (Uint32 i = 0;i < tor.getNumChunks();i++) { if (i + 1 < tor.getNumChunks()) chunks[i] = new Chunk(i,csize,cache); else chunks[i] = new Chunk(i,lsize,cache); } chunks_left = 0; recalc_chunks_left = true; }
void Reconstructor::reconstructSession(Session *s) { // We get one monolithic file from a session. If we have the torrent file // we can break it up, otherwise the user will have to do it manually, as we // don't have that information. File file; Torrent *torrent = NULL; // Hold the torrent for this session if we have it ip_piece_map_t pieces = s->getPieces(); std::map<std::string, Peer> peers = s->getPeers(); std::map<std::string, Peer>::iterator it; std::vector<unsigned int>::iterator uit; char hash_string[42]; unsigned char temp_hash[20]; // std::cout.rdbuf((*(this->ohandle)).rdbuf()); // Output statistics // Make it easier to differentiate between different sessions in output std::cout << "****************************************" << std::endl; std::cout << "Processing a new BitTorrent session" << std::endl; std::cout << "SHA-1 Info Hash: " << std::endl << "\t"; const char *h = s->getHash().data(); for (int i = 0; i < 20; i++) printf("%x", (unsigned char)h[i]); std::cout << std::endl; // Build up our file from the session pieces ip_piece_map_t::iterator m, me; std::vector<Piece*>::iterator p, pe; for (m = pieces.begin(), me = pieces.end(); m != me; ++m) { for (p = m->second.begin(), pe = m->second.end(); p != pe; ++p) { if (not (*p)->isValid()) { assert(0 && "Should never have an invalid piece here"); } file.addPiece(*p); } } std::cout << "Peers: " << std::endl; //output ip:port for each peer for (it = peers.begin(); it != peers.end(); it++) { //Only print out active peers if (it->second.active) { std::cout << "\t" << it->second.ip << ":" << it->second.port << std::endl; } } //output upload statistics(if any) for (uit = s->getUploadedIndices().begin(); uit != s->getUploadedIndices().end(); uit++) { std::cout << "Uploaded part of piece index " << *uit << std::endl; } std::vector<Torrent*>::iterator i, ie; for (i = this->m_torrents.begin(), ie = this->m_torrents.end(); i != ie; ++i) { // if ((*i)->info_hash() == s->getHash().data()) { if (compare_sha1s((const unsigned char *)(*i)->info_hash().data(), (const unsigned char *)s->getHash().data())) { torrent = *i; } } file.reconstructFile(torrent); if (torrent == NULL) { // We still want to output, just no verification. Refactor this ASAP // Name the file after its checksum const unsigned char *data = (const unsigned char*) file.contents().data(); SHA1(data, file.contents().length(), temp_hash); //FIXME This is disgusting snprintf(hash_string, 42, "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x", (unsigned char)temp_hash[0], (unsigned char)temp_hash[1], (unsigned char)temp_hash[2], (unsigned char)temp_hash[3], (unsigned char)temp_hash[4], (unsigned char)temp_hash[5], (unsigned char)temp_hash[6], (unsigned char)temp_hash[7], (unsigned char)temp_hash[8], (unsigned char)temp_hash[9], (unsigned char)temp_hash[10], (unsigned char)temp_hash[11], (unsigned char)temp_hash[12], (unsigned char)temp_hash[13], (unsigned char)temp_hash[14], (unsigned char)temp_hash[15], (unsigned char)temp_hash[16], (unsigned char)temp_hash[17], (unsigned char)temp_hash[18], (unsigned char)temp_hash[19]); file.name(hash_string); std::cout << "Output filename: " << hash_string << std::endl; // We get file. How are you gentlemen? Output me to your base. std::cout << "Reconstructed file size: " << file.writeFile(0, std::string::npos) << " bytes." << std::endl; return; } // Break up files here unsigned int file_offset = 0; std::vector<unsigned int> v = torrent->file_lengths(); for (unsigned int i=0; i < v.size(); ++i) { std::string curr_file = file.contents().substr(file_offset, v.at(i)); // Name the file after its checksum const unsigned char *data = (const unsigned char*) curr_file.data(); SHA1(data, curr_file.length(), temp_hash); //FIXME This is disgusting snprintf(hash_string, 42, "%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x", (unsigned char)temp_hash[0], (unsigned char)temp_hash[1], (unsigned char)temp_hash[2], (unsigned char)temp_hash[3], (unsigned char)temp_hash[4], (unsigned char)temp_hash[5], (unsigned char)temp_hash[6], (unsigned char)temp_hash[7], (unsigned char)temp_hash[8], (unsigned char)temp_hash[9], (unsigned char)temp_hash[10], (unsigned char)temp_hash[11], (unsigned char)temp_hash[12], (unsigned char)temp_hash[13], (unsigned char)temp_hash[14], (unsigned char)temp_hash[15], (unsigned char)temp_hash[16], (unsigned char)temp_hash[17], (unsigned char)temp_hash[18], (unsigned char)temp_hash[19]); file.name(hash_string); std::cout << "Output filename: " << hash_string << std::endl; // We get file. How are you gentlemen? Output me to your base. std::cout << "Reconstructed file size: " << file.writeFile(file_offset, v.at(i)) << " bytes." << std::endl; file_offset += v.at(i); } }
bool TorrentSortModel::lessThan(const QModelIndex & left, const QModelIndex & right) const { Torrent leftItem = static_cast<TorrentModel *>(sourceModel())->torrent(left.row()); Torrent rightItem = static_cast<TorrentModel *>(sourceModel())->torrent(right.row()); if (left.column() == right.column()) { int column = left.column(); switch (column) { case TorrentModel::Name: return leftItem.name().toLower() < rightItem.name().toLower(); case TorrentModel::State: return leftItem.state() < rightItem.state(); case TorrentModel::Size: return leftItem.size() < rightItem.size(); case TorrentModel::Seeders: return leftItem.seedsConnected() < rightItem.seedsConnected(); case TorrentModel::Leechers: return leftItem.leechsConnected() < rightItem.leechsConnected(); case TorrentModel::DownloadRate: return leftItem.downloadRate() < rightItem.downloadRate(); case TorrentModel::Downloaded: return leftItem.downloaded() < rightItem.downloaded(); case TorrentModel::UploadRate: return leftItem.uploadRate() < rightItem.uploadRate(); case TorrentModel::Uploaded: return leftItem.uploaded() < rightItem.uploaded(); case TorrentModel::Ratio: return leftItem.ratio() < rightItem.ratio(); case TorrentModel::Priority: return leftItem.priority() < rightItem.priority(); default: return false; } } else { return false; } }
void QTorrentItemDelegat::drawTorrent(QPainter* painter, const QStyleOptionViewItem& option, const Torrent& tor, const QModelIndex& index) const { QStyleOptionViewItemV4 opt = option; initStyleOption(&opt, index); QStyle* style; if(opt.widget != NULL) { style = opt.widget->style(); } else { style = QApplication::style(); } const int iconSize(style->pixelMetric(QStyle::PM_LargeIconSize)); QFont nameFont(option.font); nameFont.setWeight(QFont::Bold); const QFontMetrics nameFM(nameFont); const QIcon mimeIcon(tor.GetMimeTypeIcon()); QString nameStr(tor.GetName()); QSize nameSize(nameFM.size(0, nameStr)); QFont statusFont(option.font); statusFont.setPointSize(int (option.font.pointSize() * 0.9)); const QFontMetrics statusFM(statusFont); QString statusStr(GetStatusString(tor)); int statusWidth = statusFM.width(statusStr); QFont progressFont(statusFont); const QFontMetrics progressFM(progressFont); QString progressStr(GetProgressString(tor)); bool isPaused(tor.isPaused()); painter->save(); painter->setRenderHint(QPainter::Antialiasing); style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget); /* if (option.state & QStyle::State_Selected) { QPalette::ColorGroup cg = option.state & QStyle::State_Enabled ? QPalette::Active : QPalette::Disabled; if (cg == QPalette::Normal && !(option.state & QStyle::State_Active)) cg = QPalette::Inactive; painter->fillRect(option.rect, opt.backgroundBrush); }*/ //style->drawControl(QStyle::CE_ItemViewItem,&option,painter); QIcon::Mode im; if(isPaused || !(option.state & QStyle::State_Enabled)) { im = QIcon::Disabled; } else if(option.state & QStyle::State_Selected) { im = QIcon::Selected; } else { im = QIcon::Normal; } QIcon::State qs; if(isPaused) { qs = QIcon::Off; } else { qs = QIcon::On; } QPalette::ColorGroup cg = QPalette::Normal; if(isPaused || !(option.state & QStyle::State_Enabled)) { cg = QPalette::Disabled; } if(cg == QPalette::Normal && !(option.state & QStyle::State_Active)) { cg = QPalette::Inactive; } QPalette::ColorRole cr; if(option.state & QStyle::State_Selected) { cr = QPalette::HighlightedText; } cr = QPalette::Text; // layout const QSize m(margin(*style)); QRect fillArea(option.rect); fillArea.adjust(m.width(), m.height(), -m.width(), -m.height()); QRect iconArea(fillArea.x(), fillArea.y() + (fillArea.height() - iconSize) / 2, iconSize, iconSize); QRect nameArea(iconArea.x() + iconArea.width() + GUI_PAD, fillArea.y(), fillArea.width() - GUI_PAD - iconArea.width(), nameSize.height()); if (nameArea.width() + nameArea.x() > opt.rect.width()) { nameArea.setWidth(opt.rect.width() - nameArea.x()); } QRect barArea(nameArea.x(), nameArea.y() + statusFM.lineSpacing() + GUI_PAD / 2, nameArea.width(), BAR_HEIGHT); QRect progArea(nameArea.x(), barArea.y() + barArea.height() + GUI_PAD / 2, barArea.width() - statusWidth, nameArea.height()); QRect statusArea(progArea.x() + progArea.width(), progArea.y(), statusWidth, progArea.height()); if(tor.hasError()) { painter->setPen(QColor("red")); } else { painter->setPen(opt.palette.color(cg, cr)); } mimeIcon.paint(painter, iconArea, Qt::AlignCenter, im, qs); painter->setFont(nameFont); nameStr = nameFM.elidedText(nameStr, Qt::ElideRight, nameArea.width()); style->drawItemText(painter, nameArea, Qt::AlignLeft, opt.palette, option.state & QStyle::State_Enabled, nameStr); painter->setFont(statusFont); statusStr = statusFM.elidedText(statusStr, Qt::ElideRight, statusArea.width()); style->drawItemText(painter, statusArea, Qt::AlignRight, opt.palette, option.state & QStyle::State_Enabled, statusStr); painter->setFont(progressFont); progressStr = statusFM.elidedText(progressStr, Qt::ElideRight, progArea.width()); style->drawItemText(painter, progArea, Qt::AlignLeft, opt.palette, option.state & QStyle::State_Enabled, progressStr); int progressPercentage = tor.GetProgress(); myProgressBarStyle->resize(barArea.size()); myProgressBarStyle->setValue(progressPercentage); //painter->translate(barArea.topLeft()); //myProgressBarStyle->render(painter); QStyleOptionProgressBarV2 pbStyleOpt; myProgressBarStyle->initilizeStyleOption(&pbStyleOpt); pbStyleOpt.rect = barArea; /*myProgressBarStyle->rect = barArea; if ( tor.isDownloading() ) { myProgressBarStyle->palette.setBrush( QPalette::Highlight, blueBrush ); myProgressBarStyle->palette.setColor( QPalette::Base, blueBack ); myProgressBarStyle->palette.setColor( QPalette::Background, blueBack ); } else if ( tor.isSeeding() ) { myProgressBarStyle->palette.setBrush( QPalette::Highlight, greenBrush ); myProgressBarStyle->palette.setColor( QPalette::Base, greenBack ); myProgressBarStyle->palette.setColor( QPalette::Background, greenBack ); } myProgressBarStyle->state = progressBarState; setProgressBarPercentDone( option, tor ); */ style->drawControl(QStyle::CE_ProgressBar, &pbStyleOpt, painter, myProgressBarStyle); painter->restore(); }
void TorrentSession::update() { std::deque<lt::alert*> alerts; mSessionHandle->pop_alerts(&alerts); for (const lt::alert *alert : alerts) { // Set the handle if a torrent was added. Torrent *t = nullptr; if (alert->type() == lt::torrent_added_alert::alert_type || alert->type() == lt::add_torrent_alert::alert_type) { const lt::torrent_alert *a = static_cast<const lt::torrent_alert*>(alert); t = mTorrentMap[a->handle.info_hash()].get(); assert(t); t->mHandle.reset(new lt::torrent_handle(a->handle)); } // Update info hash in map if it changed if (alert->type() == lt::torrent_update_alert::alert_type) { const lt::torrent_update_alert *a = static_cast<const lt::torrent_update_alert*>(alert); auto &newPos = mTorrentMap[a->new_ih]; auto it = mTorrentMap.find(a->old_ih); assert(newPos == nullptr); assert(it != mTorrentMap.end()); newPos = std::move(it->second); mTorrentMap.erase(it); } // Check whether it is an torrent alert and set `t`. if (t == nullptr) { const lt::torrent_alert *ta = dynamic_cast<const lt::torrent_alert*>(alert); if (ta) { t = mTorrentMap[ta->handle.info_hash()].get(); assert(t); } } // Fire the alert signal. this->alert(*alert, t); // Do private handling switch (alert->type()) { case lt::add_torrent_alert::alert_type: { const lt::add_torrent_alert *a = static_cast<const lt::add_torrent_alert*>(alert); assert(t); if (a->error) { t->addFailed(a->error); t->removed(); // TODO should I call this signal ? int ret = mTorrentMap.erase(a->params.ti ? a->params.ti->info_hash() : a->params.info_hash); assert(ret); } else { t->mAdded = true; t->added(); if (t->mDeleting) { mSessionHandle->remove_torrent(*t->mHandle, lt::session::delete_files); } else if (t->mRemoving) { mSessionHandle->remove_torrent(*t->mHandle); } } break; } case lt::torrent_removed_alert::alert_type: { const lt::torrent_removed_alert *a = static_cast<const lt::torrent_removed_alert*>(alert); assert(t); assert(t->mHandle->info_hash() == a->info_hash); t->removed(); int ret = mTorrentMap.erase(a->info_hash); assert(ret); break; } case lt::torrent_deleted_alert::alert_type: { const lt::torrent_deleted_alert *a = static_cast<const lt::torrent_deleted_alert*>(alert); assert(t); assert(t->mHandle->info_hash() == a->info_hash); t->deleted(); break; } case lt::torrent_delete_failed_alert::alert_type: { const lt::torrent_delete_failed_alert *a = static_cast<const lt::torrent_delete_failed_alert*>(alert); assert(t); assert(t->mHandle->info_hash() == a->info_hash); t->deleteFailed(a->error); break; } case lt::metadata_received_alert::alert_type: { const lt::metadata_received_alert *a = static_cast<const lt::metadata_received_alert*>(alert); assert(t); assert(*t->mHandle == a->handle); t->mMetadata.reset(new TorrentInfo(*t->mHandle->torrent_file())); t->metadataReceived(); break; } case lt::metadata_failed_alert::alert_type: { const lt::metadata_failed_alert *a = static_cast<const lt::metadata_failed_alert*>(alert); assert(t); assert(*t->mHandle == a->handle); t->metadataFailed(a->error); break; } case lt::state_update_alert::alert_type: { const lt::state_update_alert *a = static_cast<const lt::state_update_alert*>(alert); mNoUpdateCounter = 0; for (const lt::torrent_status &nts : a->status) { Torrent *t = mTorrentMap[nts.info_hash].get(); assert(t); assert(nts.info_hash == nts.handle.info_hash()); assert(*t->mHandle == nts.handle); t->mStatus->loadFromLibtorrent(nts); t->statusUpdated(); } mStatus->loadFromLibtorrent(mSessionHandle->status()); statusUpdated(); break; } } delete alert; } // get torrent states every 10 updates if (++mNoUpdateCounter == 10) { mSessionHandle->post_torrent_updates(); } }
void TorrentManager::SaveSession() { if (!m_bIsSaveSessionInitiated) { m_bIsSaveSessionInitiated = true; writeSettings(); num_outstanding_resume_data = 0; std::vector<torrent_status> temp; m_pTorrentSession->pause(); m_pTorrentSession->get_torrent_status(&temp, &yes, 0xffffffff); for (std::vector<torrent_status>::iterator i = temp.begin(); i != temp.end(); ++i) { torrent_status& st = *i; if (!st.handle.is_valid()) { continue; } if (!st.has_metadata) { continue; } /*if (!st.handle.need_save_resume_data()) { continue; }*/ st.handle.save_resume_data(); ++num_outstanding_resume_data; } QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); while (num_outstanding_resume_data > 0) { QVector<alert*> alerts; getPendingAlerts(alerts); for (QVector<alert*>::iterator i = alerts.begin() , end(alerts.end()); i != end; ++i) { boost::scoped_ptr<alert> a(*i); if (alert_cast<save_resume_data_failed_alert>(a.get())) { --num_outstanding_resume_data; continue; } save_resume_data_alert const* rd = alert_cast<save_resume_data_alert>(*i); if (!rd) { continue; } --num_outstanding_resume_data; if (!rd->resume_data) { continue; } torrent_handle h = rd->handle; std::vector<char> out; entry& e = *rd->resume_data; QString info_hash = QString::fromStdString(to_hex(h.info_hash().to_string())); Torrent* torrent = m_pTorrentStorrage->getTorrent(info_hash); if (torrent != NULL) { e["torrent_group"] = torrent->GetGroup().toUtf8().data(); e["torrent_name"] = #if LIBTORRENT_VERSION_NUM >= 10000 h.status(torrent_handle::query_name).name; #else h.name(); #endif bool isSeeding = torrent->isSeeding(); e["is_previous_seed"] = isSeeding ? 1 : 0; } bencode(back_inserter(out), e); if (save_file((StaticHelpers::CombinePathes(dataDir, "BtSessionData", info_hash + ".resume").toStdString()), out) < 0) { qDebug() << "save_file failed"; } } } { entry session_state; m_pTorrentSession->save_state(session_state); std::vector<char> out; bencode(back_inserter(out), session_state); QString path = StaticHelpers::CombinePathes(dataDir, "BtSessionData", "actual.state"); save_file(path.toStdString(), out); } m_pTorrentSession->abort(); } }
bool TorrentManager::AddTorrent(QString& path, QString& save_path, error_code& ec, QString name, QMap<QString, quint8> filePriorities, QString group, AddTorrentFlags flags) { boost::intrusive_ptr<torrent_info> t; t = new torrent_info(path.toUtf8().data(), ec); if (ec != 0) { return false; } add_torrent_params p; QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); QString infoHash = QString::fromStdString(to_hex(t->info_hash().to_string())); std::string resumeFileName = StaticHelpers::CombinePathes(dataDir, "BtSessionData", infoHash + ".resume").toStdString(); std::vector<char> buf; bool isPreviousSeed = false; if (load_file(resumeFileName.c_str(), buf, ec) == 0) { #if LIBTORRENT_VERSION_NUM >= 10000 p.resume_data = buf; #else p.resume_data = &buf; #endif entry e = bdecode(buf.begin(), buf.end()); if (entry* i = e.find_key("torrent_name")) { std::string stdName = i->string(); name = QString::fromUtf8(stdName.c_str()); } if (entry* i = e.find_key("torrent_group")) { std::string string = i->string(); group = QString::fromUtf8(string.c_str()); } if (entry* i = e.find_key("save_path")) { save_path = QString::fromUtf8(i->string().c_str()); } if (entry* i = e.find_key("is_previous_seed")) { isPreviousSeed = (i->integer() == 1); } } if (!filePriorities.isEmpty()) { std::vector<uint8_t> filepriorities; file_storage storrage = t->files(); int filesCount = storrage.num_files(); for (int i = 0; i < filesCount; i++) { file_entry file = storrage.at(i); QString filePath = QDir::toNativeSeparators(file.path.c_str()); if (filePriorities.contains(filePath)) { filepriorities.push_back(filePriorities[filePath]); } else { filepriorities.push_back(1); } } #if LIBTORRENT_VERSION_NUM >= 10000 p.file_priorities = filepriorities; #else p.file_priorities = &filepriorities; #endif } if (!name.isEmpty()) { p.name = name.toUtf8().data(); file_storage fs = t->files(); fs.set_name(p.name); t->remap_files(fs); } p.ti = t; p.save_path = std::string(save_path.toUtf8().data()); p.storage_mode = storage_mode_t(m_pTorrentSessionSettings->valueInt("Torrent", "file_allocation_mode", storage_mode_sparse)); p.flags = add_torrent_params::flag_duplicate_is_error | add_torrent_params::flag_update_subscribe; if (flags.testFlag(PAUSED_MODE)) { p.flags |= add_torrent_params::flag_paused; } if (flags.testFlag(SEED_MODE)) { p.flags |= add_torrent_params::flag_seed_mode; } if (flags.testFlag(SUPER_SEED_MODE)) { p.flags |= add_torrent_params::flag_super_seeding; } #if LIBTORRENT_VERSION_NUM >= 10000 if (flags.testFlag(SEQUENTIAL_MODE)) { p.flags |= add_torrent_params::flag_sequential_download; } #else p.flags |= add_torrent_params::flag_paused; #endif p.userdata = static_cast<void*>(strdup(path.toLatin1().data())); torrent_handle h = m_pTorrentSession->add_torrent(p, ec); if (ec || !h.is_valid()) { // QMessageBox::warning(0,"Error",ec.message().c_str()); return false; } #if LIBTORRENT_VERSION_NUM < 10000 if (flags.testFlag(SEQUENTIAL_MODE)) { h.set_sequential_download(true); } h.resume(); #endif Torrent* current = new Torrent(h.status(), group); current->setIsPrevioslySeeded(isPreviousSeed); m_pTorrentStorrage->append(current); emit AddTorrentGui(current); h.set_max_connections(max_connections_per_torrent); QFile::copy(path, StaticHelpers::CombinePathes(dataDir, "BtSessionData", infoHash + ".torrent")); return true; }
void TorrentManager::handle_alert(alert* a) { QString dataDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation); TORRENT_TRY { switch (a->type()) { case tracker_reply_alert::alert_type: { tracker_reply_alert* p = alert_cast<tracker_reply_alert>(a); Torrent* pTorrent = m_pTorrentStorrage->getTorrent(QString::fromStdString(to_hex(p->handle.info_hash().to_string()))); if (pTorrent != NULL) { pTorrent->SetTrackerPeersCnt(QString::fromStdString(p->url), p->num_peers); } break; } case file_error_alert::alert_type: { file_error_alert* p = alert_cast<file_error_alert>(a); QString message = StaticHelpers::translateLibTorrentError(p->error); message.append(QString::fromUtf8(p->message().c_str())); emit Notify(NotificationSystem::DISK_ERROR, message, QVariant()); break; } case torrent_finished_alert::alert_type: { torrent_finished_alert* p = alert_cast<torrent_finished_alert>(a); p->handle.set_max_connections(max_connections_per_torrent / 2); torrent_handle h = p->handle; QString infoHash = QString::fromStdString(to_hex(h.info_hash().to_string())); Torrent* pTorrent = m_pTorrentStorrage->getTorrent(infoHash); if (pTorrent != NULL) { if (pTorrent->isSquential()) { pTorrent->seqensialDownload(); } if (!pTorrent->isPrevioslySeeded()) { emit Notify(NotificationSystem::TORRENT_COMPLETED, tr("TORRENT_COMPLETED %1").arg(pTorrent->GetName()), StaticHelpers::CombinePathes(pTorrent->GetSavePath(), pTorrent->GetName())); } } h.save_resume_data(); break; } case save_resume_data_failed_alert::alert_type: { save_resume_data_failed_alert* p = alert_cast<save_resume_data_failed_alert>(a); p->handle.save_resume_data(); break; } case save_resume_data_alert::alert_type: { save_resume_data_alert* p = alert_cast<save_resume_data_alert>(a); torrent_handle h = p->handle; if (p->resume_data) { std::vector<char> out; entry e = *p->resume_data; QString info_hash = QString::fromStdString(to_hex(h.info_hash().to_string())); Torrent* torrent = m_pTorrentStorrage->getTorrent(info_hash); if (torrent != NULL) { bool isSeed = torrent->isSeeding(); e["torrent_group"] = torrent->GetGroup().toUtf8().data(); e["torrent_name"] = #if LIBTORRENT_VERSION_NUM >= 10000 h.status(torrent_handle::query_name).name; #else h.name(); #endif e["is_previous_seed"] = isSeed ? 1 : 0; torrent->setIsPrevioslySeeded(isSeed); } bencode(back_inserter(out), e); save_file(StaticHelpers::CombinePathes(dataDir, "BtSessionData", info_hash + ".resume").toStdString(), out); if (m_bIsSaveSessionInitiated) { num_outstanding_resume_data--; } } break; } case tracker_error_alert::alert_type: { tracker_error_alert* p = alert_cast<tracker_error_alert>(a); QString message = StaticHelpers::translateLibTorrentError(p->error); message.append(QString::fromLocal8Bit(p->message().c_str())); emit Notify(NotificationSystem::TRACKER_ERROR, message, QVariant()); break; } case storage_moved_alert::alert_type: { storage_moved_alert* p = alert_cast<storage_moved_alert>(a); torrent_handle h = p->handle; if (h.is_valid()) { h.save_resume_data(); } QString infoHash = QString::fromStdString(to_hex(h.info_hash().to_string())); Torrent* pTorrent = m_pTorrentStorrage->getTorrent(infoHash); if (pTorrent != NULL) { emit Notify(NotificationSystem::TORRENT_INFO, tr("MOVE_STORRAGE_COMPLETED_TO:\n%1 %2").arg(pTorrent->GetName(), pTorrent->GetSavePath()), pTorrent->GetSavePath()); pTorrent->CompliteMoveStorrage(); } break; } case fastresume_rejected_alert::alert_type: { fastresume_rejected_alert* p = alert_cast<fastresume_rejected_alert>(a); torrent_handle h = p->handle; h.auto_managed(false); h.pause(); emit Notify(NotificationSystem::TORRENT_ERROR, StaticHelpers::translateLibTorrentError(p->error), QVariant()); break; } case metadata_received_alert::alert_type: { metadata_received_alert* p = alert_cast<metadata_received_alert>(a); torrent_handle h = p->handle; if (h.is_valid()) { try { #if LIBTORRENT_VERSION_NUM >= 10000 boost::intrusive_ptr<torrent_info const> ti = h.torrent_file(); if (ti != NULL) { create_torrent ct(*ti.get()); QString info_hash = QString::fromStdString(to_hex(ti->info_hash().to_string())); #else const torrent_info ti = h.get_torrent_info(); { create_torrent ct(ti); QString info_hash = QString::fromStdString(to_hex(ti.info_hash().to_string())); #endif std::ofstream out(StaticHelpers::CombinePathes(dataDir, "BtSessionData", info_hash + ".torrent").toStdString(), std::ios_base::binary); bencode(std::ostream_iterator<char>(out), ct.generate()); } } catch (...) { qCritical() << "Exception in metadata_received_alert"; } } break; } case portmap_alert::alert_type: { portmap_alert* alert = alert_cast<portmap_alert>(a); emit Notify(NotificationSystem::SYSTEM_ERROR, QString::fromUtf8(alert->message().c_str()), QVariant()); } case state_update_alert::alert_type: { state_update_alert* p = alert_cast<state_update_alert>(a); for (int i = 0; i < p->status.size(); i++) { torrent_status status = p->status[i]; QString infoHash = QString::fromStdString(to_hex(status.info_hash.to_string())); Torrent* torrent = m_pTorrentStorrage->getTorrent(infoHash); if (torrent != NULL) { torrent->UpdateStatus(status); } } break; } case performance_alert::alert_type: /*{ performance_alert* p=alert_cast<performance_alert>(a); session_settings settings = ses->settings(); switch (p->warning_code) { case performance_alert::outstanding_disk_buffer_limit_reached: { settings.max_queued_disk_bytes+=settings.max_queued_disk_bytes/4; break; } case performance_alert::outstanding_request_limit_reached: { settings.max_out_request_queue+=settings.max_out_request_queue/4; break; } case performance_alert::upload_limit_too_low: { settings.upload_rate_limit+=settings.upload_rate_limit*5/100; break; } case performance_alert::download_limit_too_low: { settings.download_rate_limit+=settings.download_rate_limit*5/100; break; } case performance_alert::send_buffer_watermark_too_low: { settings.send_buffer_watermark+=settings.send_buffer_watermark/4; break; } case performance_alert::too_many_optimistic_unchoke_slots: { settings.unchoke_slots_limit+= settings.unchoke_slots_limit/4; break; } case performance_alert::too_high_disk_queue_limit: { if (settings.max_queued_disk_bytes-settings.max_queued_disk_bytes/4 < 16*KbInt) { settings.max_queued_disk_bytes=settings.max_queued_disk_bytes-settings.max_queued_disk_bytes/4; } else { settings.cache_size+=32; } break; } } ses->set_settings(settings); }*/ case add_torrent_alert::alert_type: case listen_succeeded_alert::alert_type: case state_changed_alert::alert_type: case torrent_added_alert::alert_type: case torrent_checked_alert::alert_type: case torrent_resumed_alert::alert_type: case torrent_paused_alert::alert_type: case torrent_removed_alert::alert_type: case cache_flushed_alert::alert_type: case torrent_deleted_alert::alert_type: case external_ip_alert::alert_type: case udp_error_alert::alert_type: case dht_reply_alert::alert_type: case tracker_announce_alert::alert_type: break; default: { QString information = QString::fromUtf8(a->message().c_str()); if ((a->category() & alert::error_notification) == alert::error_notification) { emit Notify(NotificationSystem::ERRORS, information, QVariant()); } else { emit Notify(NotificationSystem::TORRENT_INFO, information, QVariant()); } break; } } } TORRENT_CATCH(std::exception & e) { qCritical() << "exception in handle_alert" << e.what(); } }