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();
}
示例#8
0
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();
	}
}
示例#9
0
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();
	}
}
示例#10
0
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;
}
示例#11
0
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();
	}
}