void TransferListView::update(const NTransfer& transfer) {
    TransferListItem* file = findTransfer(transfer.user, transfer.filename);
    if (!file ) {
        file = new TransferListItem(findParent(transfer.user), transfer.user, transfer.filename);
        museeq->flush(); // Needed to avoid transfers being added times when update() is called twice.
    }

    file->update(transfer);
}
QList<QPair<QString, QString> > Transfers::findByStates(TransferListView* l, QList<uint> states) {
	QList<QPair<QString, QString> > items;
	QTreeWidgetItemIterator it(mPoppedUpload ? mUploads : mDownloads, QTreeWidgetItemIterator::Selectable);
	for(; *it; ++it) {
		TransferListItem* item = dynamic_cast<TransferListItem*>(*it);
		if(item && states.contains(item->state()))
			items += QPair<QString, QString>(item->user(), item->path());
	}
	return items;
}
TransferListItem* TransferListView::findTransfer(const QString& _u, const QString& _p) {
    QTreeWidgetItemIterator it(this);
    while (*it) {
        TransferListItem * item = dynamic_cast<TransferListItem *>(*it);
        if (item && (item->user().compare(_u) == 0) && (item->path().compare(_p) == 0))
            return item;
        it++;
    }

    return NULL;
}
void TransferListView::updateParentsStats() {
    if(mGroupMode == None)
        return;

    int topit = 0;

    for(; topit < topLevelItemCount(); topit++) {
        TransferListItem * top = dynamic_cast<TransferListItem *>(topLevelItem(topit));
        if (top)
            top->updateStats();
    }
}
void TransferListView::setGroupMode(GroupMode mode) {
    if(mode == mGroupMode)
        return;

    mGroupMode = mode;

    if(mGroupMode == None) {
        QList<QTreeWidgetItem *> items;
        QList<QTreeWidgetItem *> subitems;
        QList<QTreeWidgetItem *>::iterator sitx;
        items = invisibleRootItem()->takeChildren ();
        QList<QTreeWidgetItem *>::iterator itx = items.begin();
        for(; itx != items.end(); ++itx) {
            if ( ! ( *itx)->text(1).isNull())
                invisibleRootItem()->addChild(*itx);
            else {
                subitems = (*itx)->takeChildren();
                sitx = subitems.begin();
                for(; sitx != subitems.end(); ++sitx)
                    invisibleRootItem()->addChild(*sitx);
            }
        }

        setRootIsDecorated(false);
    }
    else {
        QList<QTreeWidgetItem *> items;

        items = invisibleRootItem()->takeChildren ();

        QList<QTreeWidgetItem *>::iterator itx = items.begin();
        for(; itx != items.end(); ++itx) {
            if ( (*itx)->text(1).isNull())
                invisibleRootItem()->addChild(*itx);
        }
        itx = items.begin();
        for(; itx != items.end(); ++itx) {
            if (! (*itx)->text(1).isNull()) {
                TransferListItem *itxx = dynamic_cast<TransferListItem *>(*itx);
                if (itxx)
                    findParent(itxx->user())->addChild(*itx);
            }
        }

        updateParentsStats();

        setRootIsDecorated(true);
    }
}
void Transfers::retrySelected() {
	QList<QPair<QString, QPair<QString, qint64> > > items;
	QTreeWidgetItemIterator it(mPoppedUpload ? mUploads : mDownloads, QTreeWidgetItemIterator::Selected | QTreeWidgetItemIterator::NotHidden);
	for(; *it; ++it) {
		TransferListItem* item = dynamic_cast<TransferListItem*>(*it);
		if (item)
            items += QPair<QString, QPair<QString, qint64> >(item->user(), QPair<QString, qint64>(item->path(), item->size()));
	}

	QList<QPair<QString, QPair<QString, qint64> > >::iterator sit = items.begin();
	for(; sit != items.end(); ++sit) {
		if(mPoppedUpload)
			museeq->uploadFile((*sit).first, (*sit).second.first);
		else
			museeq->downloadFile((*sit).first, (*sit).second.first, (*sit).second.second);
	}
}
TransferListItem* TransferListView::findParent(const QString& user) {
    if (mGroupMode == None)
        return static_cast<TransferListItem *>(invisibleRootItem());

    TransferListItem * parent = 0;
    QList<QTreeWidgetItem *> Groups = TransferListView::findItems(user, Qt::MatchExactly, 0);
    QList<QTreeWidgetItem *>::iterator transfers_it = Groups.begin();
    for(; transfers_it != Groups.end();  ++transfers_it) {
        TransferListItem * trans = dynamic_cast<TransferListItem *>(*transfers_it);
        if (trans && trans->path().isNull()) {
            parent = trans;
        }
    }

    if (! parent)
        parent = new TransferListItem(this, user, QString::null);

    addTopLevelItem(parent);
    return parent;

}
void Transfers::setupUsers() {
	mUsersMenu->clear();

	QStringList users;
	QTreeWidgetItemIterator it(mPoppedUpload ? mUploads : mDownloads, QTreeWidgetItemIterator::Selected );
	for(; *it; ++it) {
		TransferListItem* item = dynamic_cast<TransferListItem*>(*it);
		if(item && !users.contains(item->user()))
		{
			users << item->user();
		}
	}

    int numusers = users.size();
    mTransferMenu->removeAction(mUsersMenu->menuAction());
    delete mUsersMenu;
    if (numusers <= 0) {
        mUsersMenu = mTransferMenu->addMenu(tr("Users"));
        return;
    }
    else if (numusers == 1) {
        mUsersMenu = new Usermenu(mTransferMenu);
        dynamic_cast<Usermenu*>(mUsersMenu)->setup(users.first());
        QAction * usermenu = mTransferMenu->addMenu(mUsersMenu);
        usermenu->setText(tr("User '%1'").arg(users.first()));
    }
    else {
        QStringListIterator usersIt(users);
        mUsersMenu = mTransferMenu->addMenu(tr("Users"));
        while (usersIt.hasNext()) {
            QString username = usersIt.next();
            Usermenu *m = new Usermenu(mUsersMenu);
            m->setup(username);
            QAction * usermenu = mUsersMenu->addMenu(static_cast<QMenu*>(m));
            usermenu->setText(username);
        }
    }
}
QList<QPair<QString, QString> > Transfers::findSelected(TransferListView* l) {
	QList<QPair<QString, QString> > items;
	QTreeWidgetItemIterator it(mPoppedUpload ? mUploads : mDownloads, QTreeWidgetItemIterator::Selected | QTreeWidgetItemIterator::NotHidden);
	for(; *it; ++it) {
		TransferListItem* item = dynamic_cast<TransferListItem*>(*it);
		if (!item)
            continue;

		if (!item->path().isEmpty())
            items += QPair<QString, QString>(item->user(), item->path());
        else {
            // We would like to delete a group of transfers
            int numChildren = item->childCount();
            for(int childId = 0; childId < numChildren; childId++) {
                TransferListItem* child = dynamic_cast<TransferListItem*>(item->child(childId));
                if (child)
                    items += QPair<QString, QString>(child->user(), child->path());
            }
        }
	}
	return items;
}
void TransferListView::remove(const QString& _u, const QString& _p) {
    TransferListItem* item = findTransfer(_u, _p);
    if (! item )
        return;

    if(item->user() == _u && (mGroupMode != None || item->path() == _p)) {
        if(mGroupMode == None) {
            museeq->output("delete item");
            delete item;
        } else {
            delete item;
            TransferListItem* parent = findParent(_u);
            if(parent->childCount() == 0)
                delete parent;
            else
                parent->updateStats();
        }
        return;
    }

}
/**
  * User have moved his mouse in this widget
  */
void TransferListView::mouseMoveEvent(QMouseEvent *event)
{
    event->accept();

    // Should we start dragging?
    if (!dragEnabled()) {
        // We change selection: don't stop dragging and restore extendedselection
        setSelection(QRect(mDragStartPosition, event->pos()), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
        return;
    }
    if (!(event->buttons() & Qt::LeftButton))
        return;
    if ((event->pos() - mDragStartPosition).manhattanLength() < QApplication::startDragDistance())
        return;

    // Create drag object
    QDrag *drag = new QDrag(this);
    QMimeData *mimeData = new QMimeData;

    QList<QUrl> urls;
    QStringList users;

    QList<QTreeWidgetItem*> items = selectedItems();
    QList<QTreeWidgetItem*>::const_iterator it = items.begin();
    for(; it != items.end(); ++it) {
        TransferListItem * item = dynamic_cast<TransferListItem*>(*it);
        if (!item)
            continue;

        if(users.indexOf(item->user()) == -1)
            users << item->user();

        // slsk protocol: in QUrl, hostname is always lower case.
        // So we put username as hostname for compatibility, and as username to have the correct case.
        // Ex: slsk://MuSeEk@museek/path/to/a/file
        // Code should first look at QUrl::userName() and if not present, try QUrl::host()
        QUrl url("slsk://" + item->user());
        url.setUserName(item->user());

        // There may be spaces in username so url may not be valid. It will work, but QUrl::isValid() should not be used
        urls.push_back(url);
    }

    if(urls.count() == 0)
        return;

    // Add the urls to the mimedata
    mimeData->setUrls(urls);
    // Add them too in text format if we want to paste it in a text area
    QString textUrls;
    QList<QUrl>::const_iterator uit;
    for(uit = urls.begin(); uit != urls.end(); uit++)
        textUrls += uit->toString() + "\n";
    mimeData->setText(textUrls);

    // And now set this mimedata into drag object
    drag->setMimeData(mimeData);

    QString x(tr("%n transfer(s)", "", items.count()) + tr(" (%n user(s))", "", users.count()));
    QSize s = viewport()->fontMetrics().size(Qt::TextSingleLine, x) + QSize(6, 4);

    QPixmap pix(s);
    QPainter p(&pix);
    p.setFont(viewport()->font());
    p.setPen(viewport()->palette().color(QPalette::WindowText));

    p.fillRect(QRect(QPoint(0, 0), s), viewport()->palette().color(QPalette::Background));
    p.drawRect(QRect(QPoint(0, 0), s));
    p.drawText(QRect(QPoint(3, 3), s - QSize(3, 3)), Qt::AlignLeft | Qt::AlignVCenter, x);

    p.end();

    drag->setHotSpot(QPoint(20, 20));
    drag->setPixmap(pix);

    // Begin dragging
    drag->exec();
}