source: psi/trunk/src/infodlg.cpp@ 9

Last change on this file since 9 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 12.4 KB
Line 
1/*
2 * infodlg.cpp - handle vcard
3 * Copyright (C) 2001, 2002 Justin Karneges
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include"infodlg.h"
22
23#include<qlayout.h>
24#include<qlabel.h>
25#include<qtabwidget.h>
26#include<qpushbutton.h>
27#include<qlineedit.h>
28#include<qmessagebox.h>
29#include<qtextedit.h>
30#include<qfiledialog.h>
31#include<qbuffer.h>
32#include"xmpp.h"
33#include"msgmle.h"
34#include"userlist.h"
35#include"xmpp_vcard.h"
36#include"xmpp_tasks.h"
37#include"psiaccount.h"
38#include"busywidget.h"
39#include"common.h"
40#include"vcardfactory.h"
41#include"iconwidget.h"
42
43
44using namespace XMPP;
45
46class InfoDlg::Private
47{
48public:
49 Private() {}
50
51 int type;
52 Jid jid;
53 VCard vcard;
54 PsiAccount *pa;
55 BusyWidget *busy;
56 bool te_edited;
57 int actionType;
58 JT_VCard *jt;
59 bool cacheVCard;
60 PsiTextView* te_status;
61 QByteArray photo;
62};
63
64InfoDlg::InfoDlg(int type, const Jid &j, const VCard &vcard, PsiAccount *pa, QWidget *parent, const char *name, bool cacheVCard)
65:InfoUI(parent, name, false, WDestructiveClose)
66{
67 d = new Private;
68 d->type = type;
69 d->jid = j;
70 d->vcard = vcard;
71 d->pa = pa;
72 d->te_edited = false;
73 d->jt = 0;
74 d->pa->dialogRegister(this, j);
75 d->cacheVCard = cacheVCard;
76 d->te_status = NULL;
77 d->busy = busy;
78
79 te_desc->setTextFormat(QTextEdit::PlainText);
80
81 setCaption(d->jid.full());
82#ifndef Q_WS_MAC
83 setIcon(IconsetFactory::icon("psi/vCard"));
84#endif
85
86 connect(pb_refresh, SIGNAL(clicked()), this, SLOT(doRefresh()));
87 connect(pb_refresh, SIGNAL(clicked()), this, SLOT(updateStatus()));
88 connect(te_desc, SIGNAL(textChanged()), this, SLOT(textChanged()));
89 connect(pb_open, SIGNAL(clicked()), this, SLOT(selectPhoto()));
90 connect(pb_clear, SIGNAL(clicked()), this, SLOT(clearPhoto()));
91
92 if(d->type == Self) {
93 connect(pb_submit, SIGNAL(clicked()), this, SLOT(doSubmit()));
94 }
95 else {
96 // Add a status tab
97 d->te_status = new PsiTextView(tabwidget);
98 d->te_status->setReadOnly(true);
99 d->te_status->setTextFormat(RichText);
100 tabwidget->addTab(d->te_status, tr("Status"));
101 updateStatus();
102
103 // Hide buttons
104 pb_submit->hide();
105 pb_open->hide();
106 pb_clear->hide();
107 ly_photo->setSpacing(0);
108 setReadOnly(true);
109 }
110
111 setData(d->vcard);
112}
113
114InfoDlg::~InfoDlg()
115{
116 d->pa->dialogUnregister(this);
117 delete d;
118}
119
120/*void InfoDlg::closeEvent(QCloseEvent *e)
121{
122 e->accept();
123 reject();
124}*/
125
126void InfoDlg::done(int r)
127{
128 // don't close if submitting
129 if(d->busy->isActive() && d->actionType == 1)
130 return;
131
132 if(d->type == Self && edited()) {
133 int n = QMessageBox::information(this, tr("Warning"), tr("You have not published your account information changes.\nAre you sure you want to discard them?"), tr("Close and discard"), tr("Don't close"));
134 if(n != 0)
135 return;
136 }
137
138 // cancel active transaction (refresh only)
139 if(d->busy->isActive() && d->actionType == 0) {
140 delete d->jt;
141 d->jt = 0;
142 }
143
144 QDialog::done(r);
145}
146
147void InfoDlg::jt_finished()
148{
149 d->busy->stop();
150 pb_refresh->setEnabled(true);
151 pb_submit->setEnabled(true);
152 pb_close->setEnabled(true);
153 fieldsEnable(true);
154
155 if(d->jt->success()) {
156 if(d->actionType == 0) {
157 d->vcard = d->jt->vcard();
158 setData(d->vcard);
159 }
160 else if(d->actionType == 1) {
161 d->vcard = d->jt->vcard();
162 if ( d->cacheVCard )
163 VCardFactory::setVCard(d->jid, d->vcard);
164 setData(d->vcard);
165 }
166
167 if(d->jid.compare(d->pa->jid(), false)) {
168 if (!d->vcard.nickName().isEmpty())
169 d->pa->setNick(d->vcard.nickName());
170 else
171 d->pa->setNick(d->pa->jid().user());
172 }
173
174 if(d->actionType == 1)
175 QMessageBox::information(this, tr("Success"), tr("Your account information has been published."));
176 }
177 else {
178 if(d->actionType == 0) {
179 if(d->type == Self)
180 QMessageBox::critical(this, tr("Error"), tr("Unable to retrieve your account information. Perhaps you haven't entered any yet."));
181 else
182 QMessageBox::critical(this, tr("Error"), tr("Unable to retrieve information about this contact.\nReason: %1").arg(d->jt->statusString()));
183 }
184 else {
185 QMessageBox::critical(this, tr("Error"), tr("Unable to publish your account information.\nReason: %1").arg(d->jt->statusString()));
186 }
187 }
188
189 d->jt = 0;
190}
191
192void InfoDlg::setData(const VCard &i)
193{
194 le_fullname->setText( i.fullName() );
195 le_nickname->setText( i.nickName() );
196 le_bday->setText( i.bdayStr() );
197
198 QString email;
199 if ( !i.emailList().isEmpty() )
200 email = i.emailList()[0].userid;
201 le_email->setText( email );
202
203 le_homepage->setText( i.url() );
204
205 QString phone;
206 if ( !i.phoneList().isEmpty() )
207 phone = i.phoneList()[0].number;
208 le_phone->setText( phone );
209
210 VCard::Address addr;
211 if ( !i.addressList().isEmpty() )
212 addr = i.addressList()[0];
213 le_street->setText( addr.street );
214 le_ext->setText( addr.extaddr );
215 le_city->setText( addr.locality );
216 le_state->setText( addr.region );
217 le_pcode->setText( addr.pcode );
218 le_country->setText( addr.country );
219
220 le_orgName->setText( i.org().name );
221
222 QString unit;
223 if ( !i.org().unit.isEmpty() )
224 unit = i.org().unit[0];
225 le_orgUnit->setText( unit );
226
227 le_title->setText( i.title() );
228 le_role->setText( i.role() );
229 te_desc->setText( i.desc() );
230
231 if ( !i.photo().isEmpty() ) {
232 //printf("There is a picture...\n");
233 d->photo = i.photo();
234 updatePhoto();
235 }
236 else
237 clearPhoto();
238
239 setEdited(false);
240}
241
242void InfoDlg::updatePhoto()
243{
244 int max_width = label_photo->width() - 20; // FIXME: Ugly magic number
245 int max_height = label_photo->height() - 20; // FIXME: Ugly magic number
246
247 QImage img(d->photo);
248 QImage img_scaled;
249 if (img.width() > max_width || img.height() > max_height) {
250 img_scaled = img.smoothScale(max_width, max_height,QImage::ScaleMin);
251 }
252 else {
253 img_scaled = img;
254 }
255 label_photo->setPixmap(QPixmap(img_scaled));
256}
257
258void InfoDlg::fieldsEnable(bool x)
259{
260 le_fullname->setEnabled(x);
261 le_nickname->setEnabled(x);
262 le_bday->setEnabled(x);
263 le_email->setEnabled(x);
264 le_homepage->setEnabled(x);
265 le_phone->setEnabled(x);
266 pb_open->setEnabled(x);
267 pb_clear->setEnabled(x);
268
269 le_street->setEnabled(x);
270 le_ext->setEnabled(x);
271 le_city->setEnabled(x);
272 le_state->setEnabled(x);
273 le_pcode->setEnabled(x);
274 le_country->setEnabled(x);
275
276 le_orgName->setEnabled(x);
277 le_orgUnit->setEnabled(x);
278 le_title->setEnabled(x);
279 le_role->setEnabled(x);
280 te_desc->setEnabled(x);
281
282 setEdited(false);
283}
284
285void InfoDlg::setEdited(bool x)
286{
287 le_fullname->setEdited(x);
288 le_nickname->setEdited(x);
289 le_bday->setEdited(x);
290 le_email->setEdited(x);
291 le_homepage->setEdited(x);
292 le_phone->setEdited(x);
293 le_street->setEdited(x);
294 le_ext->setEdited(x);
295 le_city->setEdited(x);
296 le_state->setEdited(x);
297 le_pcode->setEdited(x);
298 le_country->setEdited(x);
299 le_orgName->setEdited(x);
300 le_orgUnit->setEdited(x);
301 le_title->setEdited(x);
302 le_role->setEdited(x);
303
304 d->te_edited = x;
305}
306
307bool InfoDlg::edited()
308{
309 bool x = false;
310
311 if(le_fullname->edited()) x = true;
312 if(le_nickname->edited()) x = true;
313 if(le_bday->edited()) x = true;
314 if(le_email->edited()) x = true;
315 if(le_homepage->edited()) x = true;
316 if(le_phone->edited()) x = true;
317 if(le_street->edited()) x = true;
318 if(le_ext->edited()) x = true;
319 if(le_city->edited()) x = true;
320 if(le_state->edited()) x = true;
321 if(le_pcode->edited()) x = true;
322 if(le_country->edited()) x = true;
323 if(le_orgName->edited()) x = true;
324 if(le_orgUnit->edited()) x = true;
325 if(le_title->edited()) x = true;
326 if(le_role->edited()) x = true;
327 if(d->te_edited) x = true;
328
329 return x;
330}
331
332void InfoDlg::setReadOnly(bool x)
333{
334 le_fullname->setReadOnly(x);
335 le_nickname->setReadOnly(x);
336 le_bday->setReadOnly(x);
337 le_email->setReadOnly(x);
338 le_homepage->setReadOnly(x);
339 le_phone->setReadOnly(x);
340 le_street->setReadOnly(x);
341 le_ext->setReadOnly(x);
342 le_city->setReadOnly(x);
343 le_state->setReadOnly(x);
344 le_pcode->setReadOnly(x);
345 le_country->setReadOnly(x);
346 le_orgName->setReadOnly(x);
347 le_orgUnit->setReadOnly(x);
348 le_title->setReadOnly(x);
349 le_role->setReadOnly(x);
350 te_desc->setReadOnly(x);
351}
352
353void InfoDlg::doRefresh()
354{
355 if(!d->pa->checkConnected(this))
356 return;
357 if(!pb_refresh->isEnabled())
358 return;
359 if(d->busy->isActive())
360 return;
361
362 pb_submit->setEnabled(false);
363 pb_refresh->setEnabled(false);
364 fieldsEnable(false);
365
366 d->actionType = 0;
367 d->busy->start();
368
369 d->jt = VCardFactory::getVCard(d->jid, d->pa->client()->rootTask(), this, SLOT(jt_finished()), d->cacheVCard);
370}
371
372void InfoDlg::doSubmit()
373{
374 if(!d->pa->checkConnected(this))
375 return;
376 if(!pb_submit->isEnabled())
377 return;
378 if(d->busy->isActive())
379 return;
380
381 VCard submit_vcard = makeVCard();
382
383 pb_submit->setEnabled(false);
384 pb_refresh->setEnabled(false);
385 pb_close->setEnabled(false);
386 fieldsEnable(false);
387
388 d->actionType = 1;
389 d->busy->start();
390
391 d->jt = new JT_VCard(d->pa->client()->rootTask());
392 connect(d->jt, SIGNAL(finished()), SLOT(jt_finished()));
393 d->jt->set(submit_vcard);
394 d->jt->go(true);
395}
396
397VCard InfoDlg::makeVCard()
398{
399 VCard v;
400
401 v.setFullName( le_fullname->text() );
402 v.setNickName( le_nickname->text() );
403 v.setBdayStr( le_bday->text() );
404
405 if ( !le_email->text().isEmpty() ) {
406 VCard::Email email;
407 email.internet = true;
408 email.userid = le_email->text();
409
410 VCard::EmailList list;
411 list << email;
412 v.setEmailList( list );
413 }
414
415 v.setUrl( le_homepage->text() );
416
417 if ( !le_phone->text().isEmpty() ) {
418 VCard::Phone p;
419 p.home = true;
420 p.voice = true;
421 p.number = le_phone->text();
422
423 VCard::PhoneList list;
424 list << p;
425 v.setPhoneList( list );
426 }
427
428 if ( !d->photo.isEmpty() ) {
429 //printf("Adding a pixmap to the vCard...\n");
430 v.setPhoto( d->photo );
431 }
432
433 if ( !le_street->text().isEmpty() ||
434 !le_ext->text().isEmpty() ||
435 !le_city->text().isEmpty() ||
436 !le_state->text().isEmpty() ||
437 !le_pcode->text().isEmpty() ||
438 !le_country->text().isEmpty() )
439 {
440 VCard::Address addr;
441 addr.home = true;
442 addr.street = le_street->text();
443 addr.extaddr = le_ext->text();
444 addr.locality = le_city->text();
445 addr.region = le_state->text();
446 addr.pcode = le_pcode->text();
447 addr.country = le_country->text();
448
449 VCard::AddressList list;
450 list << addr;
451 v.setAddressList( list );
452 }
453
454 VCard::Org org;
455
456 org.name = le_orgName->text();
457
458 if ( !le_orgUnit->text().isEmpty() )
459 org.unit << le_orgUnit->text();
460
461 v.setOrg( org );
462
463 v.setTitle( le_title->text() );
464 v.setRole( le_role->text() );
465 v.setDesc( te_desc->text() );
466
467 return v;
468}
469
470void InfoDlg::textChanged()
471{
472 d->te_edited = true;
473}
474
475/*!
476 * Opens a file browser dialog, and if selected, calls the setPreviewPhoto with the consecuent path.
477 * \see setPreviewPhoto(const QString& path)
478*/
479void InfoDlg::selectPhoto()
480{
481 while(1) {
482 if(option.lastPath.isEmpty())
483 option.lastPath = QDir::homeDirPath();
484 QString str = QFileDialog::getOpenFileName(option.lastPath, tr("Images (*.png *.xpm *.jpg *.PNG *.XPM *.JPG)"), this, 0, tr("Choose a file"));
485 if(!str.isEmpty()) {
486 QFileInfo fi(str);
487 if(!fi.exists()) {
488 QMessageBox::information(this, tr("Error"), tr("The file specified does not exist."));
489 continue;
490 }
491 option.lastPath = fi.dirPath();
492 //printf(QDir::convertSeparators(fi.filePath()));
493
494 // put the image in the preview box
495 setPreviewPhoto(str);
496 }
497 break;
498 }
499
500}
501
502/*!
503 * Loads the image from the requested URL, and inserts the resized image into the preview box.
504 * \param path image file to load
505*/
506void InfoDlg::setPreviewPhoto(const QString& path)
507{
508 QFile photo_file(path);
509 if (!photo_file.open(IO_ReadOnly))
510 return;
511
512 QByteArray photo_data = photo_file.readAll();
513 QImage photo_image(photo_data);
514 if(!photo_image.isNull()) {
515 d->photo = photo_data;
516 updatePhoto();
517 d->te_edited = true;
518 }
519}
520
521/*!
522 * Clears the preview image box and marks the te_edited signal in the private.
523*/
524void InfoDlg::clearPhoto()
525{
526 // this will cause the pixmap disappear
527 label_photo->setText(tr("Picture not\navailable"));
528 d->photo = QByteArray();
529
530 // the picture changed, so notify there are some changes done
531 d->te_edited = true;
532}
533
534/*!
535 * Updates the status info of the contact
536 */
537void InfoDlg::updateStatus()
538{
539 if (!d->te_status)
540 return;
541
542 UserListItem *u = d->pa->find(d->jid);
543 if(u) {
544 d->te_status->setText(u->makeDesc());
545 }
546 else {
547 d->te_status->clear();
548 }
549}
Note: See TracBrowser for help on using the repository browser.