1#ifndef LIBKOPETE_UI_AVATARSELECTORWIDGET_CPP
2#define LIBKOPETE_UI_AVATARSELECTORWIDGET_CPP
3/*
4 avatarselectorwidget.cpp - Widget to manage and select user avatar
5
6 Copyright (c) 2007 by Michaƫl Larouche <larouche@kde.org>
7 Copyright (c) 2007 Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net>
8
9 Kopete (c) 2002-2007 by the Kopete developers <kopete-devel@kde.org>
10
11 *************************************************************************
12 * *
13 * This library is free software; you can redistribute it and/or *
14 * modify it under the terms of the GNU Lesser General Public *
15 * License as published by the Free Software Foundation; either *
16 * version 2 of the License, or (at your option) any later version. *
17 * *
18 *************************************************************************
19*/
20#include "avatarselectorwidget.h"
21#include "avatarwebcamdialog.h"
22
23// Qt includes
24#include <QListWidget>
25#include <QListWidgetItem>
26#include <QIcon>
27#include <QPainter>
28
29// KDE includes
30#include <kdebug.h>
31#include <klocale.h>
32#include <kurl.h>
33#include <kfiledialog.h>
34#include <kpixmapregionselectordialog.h>
35
36#include "ui_avatarselectorwidget.h"
37#ifndef VIDEOSUPPORT_DISABLED
38#include "avdevice/videodevicepool.h"
39
40using namespace Kopete::AV;
41#endif
42
43namespace Kopete
44{
45namespace UI
46{
47
48class AvatarSelectorWidgetItem : public QListWidgetItem
49{
50public:
51 AvatarSelectorWidgetItem(QListWidget *parent)
52 : QListWidgetItem(parent, QListWidgetItem::UserType)
53 {}
54
55 void setAvatarEntry(Kopete::AvatarManager::AvatarEntry entry)
56 {
57 m_entry = entry;
58
59 QSize s(96,96);
60
61 if (listWidget())
62 s = listWidget()->iconSize();
63
64 QPixmap pix;
65 if (entry.path.isEmpty())
66 {
67 // draw a fake image telling there is no avatar
68 pix = QPixmap(s);
69 QPainter p(&pix);
70 p.fillRect(pix.rect(), Qt::white);
71 p.drawText(pix.rect(), Qt::TextWordWrap | Qt::AlignCenter, i18n("No Avatar"));
72 }
73 else
74 {
75 pix = QPixmap(entry.path).scaled(s);
76 }
77
78 // draw a border around the avatar
79 QPainter p(&pix);
80 p.setBrush(Qt::NoBrush);
81 p.drawRect(0,0,pix.width()-1,pix.height()-1);
82
83 setIcon(pix);
84 }
85
86 Kopete::AvatarManager::AvatarEntry avatarEntry() const
87 {
88 return m_entry;
89 }
90
91private:
92 Kopete::AvatarManager::AvatarEntry m_entry;
93};
94
95class AvatarSelectorWidget::Private
96{
97public:
98 Private()
99 : selectedItem(0), noAvatarItem(0)
100 {}
101
102 Ui::AvatarSelectorWidget mainWidget;
103 QListWidgetItem *selectedItem;
104 QString currentAvatar;
105 AvatarSelectorWidgetItem * noAvatarItem;
106 AvatarSelectorWidgetItem * addItem(Kopete::AvatarManager::AvatarEntry entry);
107};
108
109AvatarSelectorWidget::AvatarSelectorWidget(QWidget *parent)
110 : QWidget(parent), d(new Private)
111{
112 d->mainWidget.setupUi(this);
113
114 // use icons on buttons
115 d->mainWidget.buttonAddAvatar->setIcon( KIcon("list-add") );
116 d->mainWidget.buttonRemoveAvatar->setIcon( KIcon("edit-delete") );
117 d->mainWidget.buttonFromWebcam->setIcon( KIcon("camera-web") );
118
119#ifndef VIDEOSUPPORT_DISABLED
120 VideoDevicePool* devicePool = VideoDevicePool::self();
121 if( devicePool->size() == 0 ){
122 d->mainWidget.buttonFromWebcam->hide();
123 }
124#else
125 //If windows, just hide it
126 d->mainWidget.buttonFromWebcam->hide();
127#endif
128
129 // Connect signals/slots
130 connect(d->mainWidget.buttonAddAvatar, SIGNAL(clicked()), this, SLOT(buttonAddAvatarClicked()));
131 connect(d->mainWidget.buttonRemoveAvatar, SIGNAL(clicked()), this, SLOT(buttonRemoveAvatarClicked()));
132 connect(d->mainWidget.buttonFromWebcam, SIGNAL(clicked()), this, SLOT(buttonFromWebcamClicked()));
133 connect(d->mainWidget.listUserAvatar, SIGNAL(itemClicked(QListWidgetItem*)),
134 this, SLOT(listSelectionChanged(QListWidgetItem*)));
135 connect(Kopete::AvatarManager::self(), SIGNAL(avatarAdded(Kopete::AvatarManager::AvatarEntry)),
136 this, SLOT(avatarAdded(Kopete::AvatarManager::AvatarEntry)));
137 connect(Kopete::AvatarManager::self(), SIGNAL(avatarRemoved(Kopete::AvatarManager::AvatarEntry)),
138 this, SLOT(avatarRemoved(Kopete::AvatarManager::AvatarEntry)));
139
140 // Add a "No Avatar" option
141 Kopete::AvatarManager::AvatarEntry empty;
142 empty.name = i18n("No Avatar");
143 empty.contact = 0;
144 empty.category = Kopete::AvatarManager::User;
145 d->noAvatarItem = d->addItem(empty);
146
147 // List avatars of User category
148 Kopete::AvatarQueryJob *queryJob = new Kopete::AvatarQueryJob(this);
149 connect(queryJob, SIGNAL(result(KJob*)), this, SLOT(queryJobFinished(KJob*)));
150 queryJob->setQueryFilter( Kopete::AvatarManager::User );
151
152 queryJob->start();
153}
154
155AvatarSelectorWidget::~AvatarSelectorWidget()
156{
157 delete d;
158}
159
160Kopete::AvatarManager::AvatarEntry AvatarSelectorWidget::selectedEntry() const
161{
162 Kopete::AvatarManager::AvatarEntry result;
163
164 if( d->selectedItem )
165 {
166 result = static_cast<AvatarSelectorWidgetItem*>(d->selectedItem)->avatarEntry();
167 }
168
169 return result;
170}
171
172void AvatarSelectorWidget::setCurrentAvatar(const QString &path)
173{
174 d->currentAvatar = path;
175
176 //try to find the avatar in the list
177 QList<QListWidgetItem*> itemList = d->mainWidget.listUserAvatar->findItems("", Qt::MatchContains);
178 QList<QListWidgetItem*>::iterator it = itemList.begin();
179
180 while (it != itemList.end())
181 {
182 AvatarSelectorWidgetItem *item = static_cast<AvatarSelectorWidgetItem*>(*it);
183 if (item->avatarEntry().path == path)
184 {
185 item->setSelected(true);
186 listSelectionChanged( item );
187 return;
188 }
189 ++it;
190 }
191
192}
193
194void AvatarSelectorWidget::buttonAddAvatarClicked()
195{
196 KUrl imageUrl = KFileDialog::getImageOpenUrl( KUrl(), this );
197 if( !imageUrl.isEmpty() )
198 {
199 // TODO: Download image
200 if( !imageUrl.isLocalFile() )
201 return;
202
203 QPixmap pixmap( imageUrl.toLocalFile() );
204 if ( pixmap.isNull() )
205 return;
206 QString imageName = imageUrl.fileName();
207 cropAndSaveAvatar(pixmap,imageName);
208 }
209}
210
211void AvatarSelectorWidget::buttonRemoveAvatarClicked()
212{
213 // if no item was selected, just exit
214 if ( !d->mainWidget.listUserAvatar->selectedItems().count() )
215 return;
216
217 AvatarSelectorWidgetItem *selectedItem = dynamic_cast<AvatarSelectorWidgetItem*>( d->mainWidget.listUserAvatar->selectedItems().first() );
218 if( selectedItem )
219 {
220 if ( selectedItem != d->noAvatarItem )
221 {
222 if( !Kopete::AvatarManager::self()->remove( selectedItem->avatarEntry() ) )
223 {
224 kDebug(14010) << "Removing of avatar failed for unknown reason.";
225 }
226 }
227 }
228}
229
230void AvatarSelectorWidget::cropAndSaveAvatar(QPixmap& pixmap, const QString& imageName){
231 // Crop the image
232 QImage avatar = KPixmapRegionSelectorDialog::getSelectedImage( pixmap, 96, 96, this );
233
234 Kopete::AvatarManager::AvatarEntry newEntry;
235 // Remove extension from filename
236 const int extIndex = imageName.lastIndexOf('.');
237 newEntry.name = ( extIndex > 0 ) ? imageName.left( extIndex ) : imageName;
238 newEntry.image = avatar;
239 newEntry.category = Kopete::AvatarManager::User;
240
241 Kopete::AvatarManager::AvatarEntry addedEntry = Kopete::AvatarManager::self()->add( newEntry );
242 if( addedEntry.path.isEmpty() )
243 {
244 //TODO add a real error message
245 //d->mainWidget.labelErrorMessage->setText( i18n("Kopete cannot add this new avatar because it could not save the avatar image in user directory.") );
246 return;
247 }
248
249 // select the added entry and show the user tab
250 QList<QListWidgetItem *> foundItems = d->mainWidget.listUserAvatar->findItems( addedEntry.name, Qt::MatchContains );
251 if( !foundItems.isEmpty() )
252 {
253 AvatarSelectorWidgetItem *item = dynamic_cast<AvatarSelectorWidgetItem*>( foundItems.first() );
254 if ( !item )
255 return;
256 item->setSelected( true );
257 }
258}
259
260void AvatarSelectorWidget::buttonFromWebcamClicked()
261{
262 Kopete::UI::AvatarWebcamDialog *dialog = new Kopete::UI::AvatarWebcamDialog();
263 int result = dialog->exec();
264 if(result == KDialog::Accepted){
265 QString avatarName("Webcam");
266 int increment = 1;
267 kDebug(14010) << "Trying with: " << avatarName;
268 while((Kopete::AvatarManager::self()->exists(avatarName))) {
269 avatarName = "Webcam_"+QString::number(increment);
270 ++increment;
271 kDebug(14010) << "Trying with: " << avatarName;
272 }
273 cropAndSaveAvatar(dialog->getLastPixmap(),avatarName);
274 }
275 dialog->close();
276 delete dialog;
277}
278
279void AvatarSelectorWidget::queryJobFinished(KJob *job)
280{
281 Kopete::AvatarQueryJob *queryJob = static_cast<Kopete::AvatarQueryJob*>(job);
282 if( !queryJob->error() )
283 {
284 QList<Kopete::AvatarManager::AvatarEntry> avatarList = queryJob->avatarList();
285 foreach(const Kopete::AvatarManager::AvatarEntry &entry, avatarList)
286 {
287 d->addItem(entry);
288 }
289 }
290 else
291 {
292 //TODO add a real error message
293 //d->mainWidget.labelErrorMessage->setText( queryJob->errorText() );
294 }
295}
296
297void AvatarSelectorWidget::avatarAdded(Kopete::AvatarManager::AvatarEntry newEntry)
298{
299 d->addItem(newEntry);
300 setCurrentAvatar(newEntry.path);
301}
302
303void AvatarSelectorWidget::avatarRemoved(Kopete::AvatarManager::AvatarEntry entryRemoved)
304{
305 // Same here, avatar can be only removed from listUserAvatar
306 foreach(QListWidgetItem *item, d->mainWidget.listUserAvatar->findItems("",Qt::MatchContains))
307 {
308 // checks if this is the right item
309 AvatarSelectorWidgetItem *avatar = dynamic_cast<AvatarSelectorWidgetItem*>(item);
310 if (!avatar || avatar->avatarEntry().name != entryRemoved.name)
311 continue;
312
313 kDebug(14010) << "Removing " << entryRemoved.name << " from list.";
314
315 int deletedRow = d->mainWidget.listUserAvatar->row( item );
316 QListWidgetItem *removedItem = d->mainWidget.listUserAvatar->takeItem( deletedRow );
317 delete removedItem;
318
319 int newRow = --deletedRow;
320 if( newRow < 0 )
321 newRow = 0;
322
323 // Select the previous avatar in the list, thus selecting a new avatar
324 // and deselecting the avatar being removed.
325 d->mainWidget.listUserAvatar->setCurrentRow( newRow );
326 // Force update
327 listSelectionChanged( d->mainWidget.listUserAvatar->item(newRow) );
328 }
329}
330
331void AvatarSelectorWidget::listSelectionChanged(QListWidgetItem *item)
332{
333 d->mainWidget.buttonRemoveAvatar->setEnabled( item != d->noAvatarItem );
334 d->selectedItem = item;
335}
336
337AvatarSelectorWidgetItem * AvatarSelectorWidget::Private::addItem(Kopete::AvatarManager::AvatarEntry entry)
338{
339 kDebug(14010) << "Entry(" << entry.name << "): " << entry.category;
340
341 // only use User avatars
342 if( !(entry.category & Kopete::AvatarManager::User) )
343 return 0;
344
345 AvatarSelectorWidgetItem *item = new AvatarSelectorWidgetItem(mainWidget.listUserAvatar);
346 item->setAvatarEntry(entry);
347 if (entry.path == currentAvatar)
348 item->setSelected(true);
349 return item;
350}
351
352} // Namespace Kopete::UI
353
354} // Namespace Kopete
355
356#include "avatarselectorwidget.moc"
357#endif // LIBKOPETE_UI/AVATARSELECTORWIDGET_CPP
358