Ticket #157: userlistview_test2.cpp

File userlistview_test2.cpp, 10.8 KB (added by lbponey, 3 years ago)
Line 
1/* museeq - a Qt client to museekd
2 *
3 * Copyright (C) 2003-2004 Hyriand <hyriand@thegraveyard.org>
4 * Copyright 2008 little blue poney <lbponey@users.sourceforge.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include "userlistview.h"
22#include "userlistitem.h"
23#include "usermenu.h"
24#include "museeq.h"
25#include "images.h"
26#include "util.h"
27
28#include <QPixmap>
29#include <QDropEvent>
30#include <QList>
31#include <QUrl>
32#include <QPainter>
33#include <QApplication>
34#include <QDrag>
35#include <QMouseEvent>
36
37UserListView::UserListView(bool comments, QWidget * parent, const char * name)
38        : QTreeWidget(parent) {
39
40        mUsermenu = new Usermenu(this);
41
42    setAcceptDrops(true);
43        setDragEnabled(true);
44        setSelectionMode(QAbstractItemView::SingleSelection);
45        setColumnCount(4);
46
47        QStringList headers;
48        headers  << QString::null << tr("User") << tr("Speed") << tr("Files");
49        if(comments) {
50                headers << (tr("Comments"));
51        setColumnCount(5);
52        }
53        setHeaderLabels(headers);
54
55        setAlternatingRowColors(true);
56        setSortingEnabled(true);
57        sortItems(1, Qt::AscendingOrder);
58        QPixmap& p(IMG("online"));
59        setColumnWidth (0, p.width()+5);
60        setColumnWidth ( 1, 100 );
61        setColumnWidth ( 2, 100 );
62        setColumnWidth ( 3, 100 );
63        setAllColumnsShowFocus(true);
64        setRootIsDecorated(false);
65        setContextMenuPolicy(Qt::CustomContextMenu);
66        connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), SLOT(slotActivate(QTreeWidgetItem*, int)));
67        connect(this, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(slotActivate(QTreeWidgetItem*, int)));
68        connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(slotContextMenu(const QPoint&)));
69
70
71        connect(museeq, SIGNAL(sortingEnabled(bool)), this, SLOT(sorting(bool)));
72        connect(museeq, SIGNAL(userStatus(const QString&, uint)), SLOT(setStatus(const QString&, uint)));
73        connect(museeq, SIGNAL(doUpdateStatus(const QString&)), SLOT(updateStatus(const QString&)));
74        connect(museeq, SIGNAL(userData(const QString&, uint, uint)), SLOT(setData(const QString&, uint, uint)));
75}
76
77void UserListView::sorting(bool sort) {
78        setSortingEnabled(sort);
79        if (sort)
80                resizeColumnToContents(1);
81}
82UserListItem* UserListView::findItem(const QString& _u) {
83        QList<QTreeWidgetItem *> items = findItems(_u, Qt::MatchExactly, 1);
84        if (!items.isEmpty())
85        return dynamic_cast<UserListItem *>(items.at(0));
86    else
87        return NULL;
88}
89
90uint UserListView::status(const QString& _u) {
91        UserListItem* item = findItem(_u);
92        if(! item)
93                return 0;
94        return item->status();
95}
96
97uint UserListView::speed(const QString& _u) {
98        UserListItem* item = findItem(_u);
99        if(! item)
100                return 0;
101        return item->speed();
102}
103
104uint UserListView::files(const QString& _u) {
105        UserListItem* item = findItem(_u);
106        if(! item)
107                return 0;
108        return item->files();
109}
110
111QString UserListView::comments(const QString& _u) {
112        UserListItem* item = findItem(_u);
113        if(! item)
114                return QString::null;
115        return item->comments();
116}
117
118void UserListView::setStatus(const QString& _u, uint _s) {
119        qDebug() << _u << _s;
120        UserListItem *item = findItem(_u);
121        qDebug() << _u << " found" << !item;
122        if(! item)
123                return;
124        item->setStatus(_s);
125}
126
127void UserListView::updateStatus(const QString& _u) {
128        UserListItem* item = findItem(_u);
129        if(! item)
130                return;
131        item->updateUserStatus();
132}
133
134void UserListView::setData(const QString& _u, uint _s, uint _f) {
135        UserListItem *item = findItem(_u);
136        if(! item)
137                return;
138        item->setSpeed(_s);
139        item->setFiles(_f);
140}
141
142void UserListView::setComments(const QString& _u, const QString& _c) {
143        UserListItem *item = findItem(_u);
144        if(! item)
145                return;
146        item->setComments(_c);
147}
148
149void UserListView::add(const QString& _u, uint _st, uint _s, uint _f, const QString& _c) {
150        UserListItem *item = findItem(_u);
151        if(item) {
152                item->setAll(_st, _s, _f, _c);
153                return;
154        }
155        new UserListItem(this, _u, _st, _s, _f, _c);
156
157}
158
159void UserListView::add(const QString& _u, const QString& _c) {
160        UserListItem *item = findItem(_u);
161        if(item) {
162                item->setComments(_c);
163                return;
164        }
165        new UserListItem(this, _u, 0, 0, 0, _c);
166
167}
168
169void UserListView::remove(const QString& _u) {
170        UserListItem *item = findItem(_u);
171        if(! item) {
172                printf("warning, couldn't find user!\n");
173                return;
174        }
175        delete item;
176}
177
178void UserListView::slotActivate(QTreeWidgetItem* item, int column) {
179        slotActivate( item);
180}
181void UserListView::slotActivate(QTreeWidgetItem* item) {
182        UserListItem* _item = dynamic_cast<UserListItem*>(item);
183        if(! _item)
184                return;
185        emit activated(_item->user());
186        emit activated(_item->user(), _item->comments());
187}
188
189/**
190  * Search TreeWidget users column for users matching keypresses (only first letter)
191  */
192void UserListView::keyboardSearch(const QString& string) {
193    // Search for a user starting by this letter
194        QList<QTreeWidgetItem *> searchUsers = QTreeWidget::findItems(string, Qt::MatchStartsWith, 1);
195
196        // If we've already searched for this letter earlier, we should display next one
197        if (mLastSearch != string) {
198                mSearchPosition = 0;
199                mLastSearch = QString(string);
200        } else {
201                mSearchPosition += 1;
202        }
203
204    // Do nothing if we didn't find anything
205        if (searchUsers.isEmpty())
206        return;
207
208    // If we're on the last user having this letter, next one will be the first one
209    if (static_cast<int>(mSearchPosition) >= searchUsers.size())
210                mSearchPosition = 0;
211
212    // Get the found item
213        QTreeWidgetItem * item = 0;
214        item = searchUsers.at(mSearchPosition);
215
216        if (! item)
217                return;
218
219    // Select found item
220        setCurrentItem(item);
221}
222
223/**
224  * User have press mouse button in this widget
225  */
226void UserListView::mousePressEvent(QMouseEvent *event)
227{
228    event->accept();
229
230    if (event->button() == Qt::LeftButton)
231        mDragStartPosition = event->pos();
232
233    QTreeWidget::mousePressEvent(event);
234}
235
236/**
237  * User have moved his mouse in this widget
238  */
239void UserListView::mouseMoveEvent(QMouseEvent *event)
240{
241    event->accept();
242
243    // Should we start dragging?
244    if (!(event->buttons() & Qt::LeftButton))
245        return;
246    if ((event->pos() - mDragStartPosition).manhattanLength() < QApplication::startDragDistance())
247        return;
248
249    // Create drag object
250    QDrag *drag = new QDrag(this);
251    QMimeData *mimeData = new QMimeData;
252
253    QList<QUrl> urls;
254
255        QList<QTreeWidgetItem*> items = selectedItems();
256    QList<QTreeWidgetItem*>::const_iterator it = items.begin();
257        for(; it != items.end(); ++it) {
258            // slsk protocol: in QUrl, hostname is always lower case.
259            // So we put username as hostname for compatibility, and as username to have the correct case.
260            // Ex: slsk://MuSeEk@museek/path/to/a/file
261            // Code should first look at QUrl::userName() and if not present, try QUrl::host()
262            UserListItem * item = dynamic_cast<UserListItem*>(*it);
263            if (!item)
264            continue;
265            QUrl url("slsk://" + item->user());
266            url.setUserName(item->user());
267
268            // There may be spaces in username so url may not be valid. It will work, but QUrl::isValid() should not be used
269            urls.push_back(url);
270        }
271
272        if(urls.count() == 0)
273                return;
274
275        // Add the urls to the mimedata
276    mimeData->setUrls(urls);
277    // Add them too in text format if we want to paste it in a text area
278    QString textUrls;
279    QList<QUrl>::const_iterator uit;
280    for(uit = urls.begin(); uit != urls.end(); uit++)
281        textUrls += uit->toString() + "\n";
282    mimeData->setText(textUrls);
283
284    // And now set this mimedata into drag object
285    drag->setMimeData(mimeData);
286
287    // Make visible what we're dragging
288    if(items.count() < 6) {
289                QSize dest(0, 0);
290                for(it = items.begin(); it != items.end(); ++it) {
291            UserListItem * item = dynamic_cast<UserListItem*>(*it);
292            if (!item)
293                continue;
294
295                        QSize textSize = viewport()->fontMetrics().size(Qt::TextSingleLine, item->user());
296
297                        QPixmap icon = item->icon(0).pixmap(50, 50); // 50x50 is the maximum size, if image is smaller, the pixmap will be too
298                        QSize iconSize = icon.size();
299
300                        QSize lineSize = textSize.expandedTo(QSize(textSize.width() + iconSize.width() + 2, iconSize.height()));
301                        dest = dest.expandedTo(QSize(lineSize.width(), lineSize.height() + 2));
302                }
303
304                QSize s(dest.width() + 6, dest.height() * items.count() + 4);
305
306                QPixmap pix(s);
307                QPainter p(&pix);
308                p.setFont(viewport()->font());
309        p.setPen(viewport()->palette().color(QPalette::WindowText));
310
311                p.fillRect(QRect(QPoint(0, 0), s), viewport()->palette().color(QPalette::Background));
312                p.drawRect(QRect(QPoint(0, 0), s));
313
314                int y = 2;
315                for(it = items.begin(); it != items.end(); ++it) {
316            UserListItem * item = dynamic_cast<UserListItem*>(*it);
317            if (!item)
318                continue;
319
320                        const QPixmap icon = item->icon(0).pixmap(50, 50);
321                        p.drawPixmap(3, y + ((dest.height() - icon.height()) / 2), icon);
322                        QRect r(QPoint(5 + icon.width(), y),
323                                dest - QSize(icon.width() + 2, 0));
324                        p.drawText(r, Qt::AlignLeft |  Qt::AlignVCenter, item->user());
325                        y += dest.height();
326                }
327
328                p.end();
329
330        drag->setHotSpot(QPoint(20, 20));
331                drag->setPixmap(pix);
332    }
333        else {
334                QString x(QString(tr("%n user(s)", "", items.count())));
335                QSize s = viewport()->fontMetrics().size(Qt::TextSingleLine, x) + QSize(6, 4);
336
337                QPixmap pix(s);
338                QPainter p(&pix);
339                p.setFont(viewport()->font());
340        p.setPen(viewport()->palette().color(QPalette::WindowText));
341
342                p.fillRect(QRect(QPoint(0, 0), s), viewport()->palette().color(QPalette::Background));
343                p.drawRect(QRect(QPoint(0, 0), s));
344                p.drawText(QRect(QPoint(3, 3), s - QSize(3, 3)), Qt::AlignLeft | Qt::AlignVCenter, x);
345
346                p.end();
347
348        drag->setHotSpot(QPoint(20, 20));
349                drag->setPixmap(pix);
350        }
351
352    // Begin dragging
353    drag->exec();
354}
355
356void UserListView::dragMoveEvent(QDragMoveEvent* event)
357{
358    event->acceptProposedAction();
359}
360
361void UserListView::dragEnterEvent(QDragEnterEvent* event) {
362    event->acceptProposedAction();
363}
364
365void UserListView::dropEvent(QDropEvent* event) {
366    event->acceptProposedAction();
367
368    if (Util::hasSlskUrls(event) && acceptDrops())
369        emit dropSlsk(event->mimeData()->urls());
370}
371
372void UserListView::slotContextMenu(const QPoint& pos) {
373        QTreeWidgetItem * item = 0 ;
374        item = itemAt(pos) ;
375        if (! item ) {
376                return;
377        }
378        mUsermenu->exec(item->text(1), mapToGlobal(pos));
379}
380
381void UserListView::slotContextMenu(QTreeWidgetItem* item, const QPoint& pos, int) {
382    UserListItem * _item = dynamic_cast<UserListItem *>(item);
383        if(_item)
384        mUsermenu->exec(_item->user(), pos);
385}