QSize
QTorrentItemDelegat::sizeHint(const QStyleOptionViewItem& option, const Torrent& tor) const
{
	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);
	QString nameStr;
	int queuePosition = tor.GetQueuePosition();

	if (queuePosition > -1)
	{
		nameStr = QString("#%1 %2").arg(QString::number(queuePosition + 1), tor.GetName());
	}
	else
	{
		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);
}
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);
}
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 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();
	}
}