22 #include <QGridLayout> 
   25 #include <QVBoxLayout> 
   26 #include <QFormLayout> 
   28 #include <TelepathyQt/Contact> 
   29 #include <TelepathyQt/PendingContactInfo> 
   30 #include <TelepathyQt/AvatarData> 
   31 #include <TelepathyQt/Presence> 
   32 #include <TelepathyQt/SharedPtr> 
   33 #include <TelepathyQt/ContactManager> 
   34 #include <TelepathyQt/Connection> 
   35 #include <TelepathyQt/Account> 
   36 #include <TelepathyQt/PendingContacts> 
   39 #include <KMessageWidget> 
   40 #include <KTitleWidget> 
   41 #include <KLocalizedString> 
   42 #include <KPushButton> 
   44 #include <KDateComboBox> 
   45 #include <KFileDialog> 
   46 #include <KImageFilePreview> 
   47 #include <KMessageBox> 
   62 static struct InfoRow {
 
   64     const QString fieldName;
 
   67     { 
FullName,         QLatin1String(
"fn"),            i18n(
"Full name:") },
 
   68     { 
Nickname,         QLatin1String(
"nickname"),      i18n(
"Nickname:") },
 
   69     { 
Email,            QLatin1String(
"email"),         i18n(
"Email:") },
 
   70     { 
Phone,            QLatin1String(
"tel"),           i18n(
"Phone:") },
 
   71     { 
Homepage,         QLatin1String(
"url"),           i18n(
"Homepage:") },
 
   72     { 
Birthday,         QLatin1String(
"bday"),          i18n(
"Birthday:") },
 
   73     { 
Organization,     QLatin1String(
"org"),           i18n(
"Organization:") }
 
   76 class ContactInfoDialog::Private
 
   81         infoDataChanged(false),
 
   87         changeAvatarButton(0),
 
   93     void onContactUpgraded(Tp::PendingOperation *op);
 
   94     void onContactInfoReceived(Tp::PendingOperation *op);
 
   95     void onChangeAvatarButtonClicked();
 
   96     void onClearAvatarButtonClicked();
 
   97     void onInfoDataChanged();
 
   99     void addInfoRow(
InfoRowIndex index, 
const QString &value);
 
  100     void addStateRow(
const QString &description, Tp::Contact::PresenceState state);
 
  102     Tp::AccountPtr account;
 
  106     bool infoDataChanged;
 
  108     QString newAvatarFile;
 
  110     QMap<InfoRowIndex,QWidget*> infoValueWidgets;
 
  112     KMessageWidget *messageWidget;
 
  113     QHBoxLayout *columnsLayout;
 
  114     QFormLayout *infoLayout;
 
  115     QFormLayout *stateLayout;
 
  116     KPushButton *changeAvatarButton;
 
  117     KPushButton *clearAvatarButton;
 
  124 void ContactInfoDialog::Private::onContactUpgraded(Tp::PendingOperation* op)
 
  127         messageWidget->setMessageType(KMessageWidget::Error);
 
  128         messageWidget->setText(op->errorMessage());
 
  129         messageWidget->setCloseButtonVisible(
false);
 
  130         messageWidget->setWordWrap(
true);
 
  131         messageWidget->animatedShow();
 
  135     Tp::PendingContacts *contacts = qobject_cast<Tp::PendingContacts*>(op);
 
  136     Q_ASSERT(contacts->contacts().count() == 1);
 
  138     contact = contacts->contacts().first();
 
  141     if (contacts->features().contains(Tp::Contact::FeatureAvatarData)) {
 
  142         QVBoxLayout *avatarLayout = 
new QVBoxLayout();
 
  143         avatarLayout->setSpacing(5);
 
  144         avatarLayout->setAlignment(Qt::AlignHCenter);
 
  145         columnsLayout->addLayout(avatarLayout);
 
  147         avatarLabel = 
new QLabel(q);
 
  148         avatarLabel->setMaximumSize(150, 150);
 
  149         avatarLayout->addWidget(avatarLabel, 0, Qt::AlignTop);
 
  152             changeAvatarButton = 
new KPushButton(i18n(
"Change Avatar"), q);
 
  153             connect(changeAvatarButton, SIGNAL(clicked(
bool)),
 
  154                     q, SLOT(onChangeAvatarButtonClicked()));
 
  155             avatarLayout->addWidget(changeAvatarButton);
 
  157             clearAvatarButton = 
new KPushButton(i18n(
"Clear Avatar"), q);
 
  158             connect(clearAvatarButton, SIGNAL(clicked(
bool)),
 
  159                     q, SLOT(onClearAvatarButtonClicked()));
 
  160             avatarLayout->addWidget(clearAvatarButton);
 
  162             avatarLayout->addStretch(1);
 
  165         QPixmap avatar(contact->avatarData().fileName);
 
  166         if (avatar.isNull()) {
 
  167             avatar = KIconLoader::global()->loadIcon(QLatin1String(
"im-user"), KIconLoader::Desktop, 128);
 
  168             if (clearAvatarButton) {
 
  169                 clearAvatarButton->setEnabled(
false);
 
  172         avatarLabel->setPixmap(avatar.scaled(avatarLabel->maximumSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
 
  176     if (contacts->features().contains(Tp::Contact::FeatureInfo)) {
 
  177         infoLayout = 
new QFormLayout();
 
  178         infoLayout->setSpacing(10);
 
  179         columnsLayout->addLayout(infoLayout);
 
  181         Tp::PendingContactInfo *op = contact->requestInfo();
 
  182         connect(op, SIGNAL(finished(Tp::PendingOperation*)),
 
  183                 q, SLOT(onContactInfoReceived(Tp::PendingOperation*)));
 
  187 void ContactInfoDialog::Private::onContactInfoReceived(Tp::PendingOperation* op)
 
  190         messageWidget->setMessageType(KMessageWidget::Error);
 
  191         messageWidget->setText(op->errorMessage());
 
  192         messageWidget->setCloseButtonVisible(
false);
 
  193         messageWidget->setWordWrap(
true);
 
  194         messageWidget->animatedShow();
 
  198     Tp::PendingContactInfo *ci = qobject_cast<Tp::PendingContactInfo*>(op);
 
  199     const Tp::ContactInfoFieldList fieldList = ci->infoFields().allFields();
 
  204         Q_FOREACH(
const Tp::ContactInfoField &field, fieldList) {
 
  205             if (field.fieldValue.count() == 0) {
 
  209             if (field.fieldName == 
InfoRows[index].fieldName) {
 
  210                 value = field.fieldValue.first();
 
  216         if (!editable && value.isEmpty()) {
 
  220         addInfoRow(index, value);
 
  224 void ContactInfoDialog::Private::onChangeAvatarButtonClicked()
 
  226     QPointer<KFileDialog> fileDialog = 
new KFileDialog(KUrl(), QString(), q);
 
  227     fileDialog->setOperationMode(KFileDialog::Opening);
 
  228     fileDialog->setPreviewWidget(
new KImageFilePreview(fileDialog));
 
  229     fileDialog->setMimeFilter(QStringList() << QLatin1String(
"image/*"));
 
  231     int c = fileDialog->exec();
 
  232     if (fileDialog && c) {
 
  233         newAvatarFile = fileDialog->selectedFile();
 
  235         QPixmap avatar(newAvatarFile);
 
  236         if (avatar.isNull()) {
 
  237             KMessageBox::error(q, i18n(
"Failed to load the new avatar image"));
 
  238             newAvatarFile.clear();
 
  242         avatarLabel->setPixmap(avatar.scaled(avatarLabel->maximumSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
 
  243         avatarChanged = 
true;
 
  244         clearAvatarButton->setEnabled(
true);
 
  250 void ContactInfoDialog::Private::onClearAvatarButtonClicked()
 
  253     avatar = KIconLoader::global()->loadIcon(QLatin1String(
"im-user"), KIconLoader::Desktop, 128);
 
  255     newAvatarFile.clear();
 
  256     avatarChanged = 
true;
 
  259 void ContactInfoDialog::Private::onInfoDataChanged()
 
  261     infoDataChanged = 
true;
 
  264 void ContactInfoDialog::Private::addInfoRow(
InfoRowIndex index, 
const QString &value)
 
  268     QLabel *descriptionLabel = 
new QLabel(row->title, q);
 
  269     QFont font = descriptionLabel->font();
 
  271     descriptionLabel->setFont(font);
 
  275             KDateComboBox *combo = 
new KDateComboBox(q);
 
  276             combo->setOptions(KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker);
 
  277             combo->setMinimumWidth(200);
 
  278             combo->setDate(QDate::fromString(value));
 
  279             connect(combo, SIGNAL(dateChanged(QDate)), q, SLOT(onInfoDataChanged()));
 
  281             infoValueWidgets.insert(index, combo);
 
  283             KLineEdit *edit = 
new KLineEdit(q);
 
  284             edit->setMinimumWidth(200);
 
  285             edit->setText(value);
 
  286             connect(edit, SIGNAL(textChanged(QString)), q, SLOT(onInfoDataChanged()));
 
  288             infoValueWidgets.insert(index, edit);
 
  291         QLabel *label = 
new QLabel(q);
 
  292         label->setOpenExternalLinks(
true);
 
  293         label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse);
 
  294         if (index == 
Email) {
 
  295             label->setText(QString::fromLatin1(
"<a href=\"mailto:%1\">%1</a>").arg(value));
 
  298             if (!value.startsWith(QLatin1String(
"http"), Qt::CaseInsensitive)) {
 
  299                 format = QLatin1String(
"<a href=\"http://%1\">%1</a>");
 
  301                 format = QLatin1String(
"<a href=\"%1\">%1</a>");
 
  303             label->setText(format.arg(value));
 
  305             label->setText(value);
 
  308         infoValueWidgets.insert(index, label);
 
  311     infoLayout->addRow(descriptionLabel, infoValueWidgets.value(index));
 
  314 void ContactInfoDialog::Private::addStateRow(
const QString& description, Tp::Contact::PresenceState state)
 
  316     QLabel *descriptionLabel = 
new QLabel(description, q);
 
  320         case Tp::Contact::PresenceStateYes:
 
  321             icon = KIcon(QLatin1String(
"task-complete"));
 
  323         case Tp::Contact::PresenceStateNo:
 
  324             icon = KIcon(QLatin1String(
"task-reject"));
 
  326         case Tp::Contact::PresenceStateAsk:
 
  328             icon = KIcon(QLatin1String(
"task-attempt"));
 
  332     QLabel *stateLabel = 
new QLabel(q);
 
  333     stateLabel->setPixmap(icon.pixmap(16));
 
  335     stateLayout->addRow(descriptionLabel, stateLabel);
 
  340     , d(new Private(this))
 
  342 #if 0   // Editing contacts is not yet supported in TpQt 
  344     d->editable = (contact == account->connection()->selfContact());
 
  347     d->account = account;
 
  348     d->contact = contact;
 
  352         setButtons(User1 | Close);
 
  353         setButtonGuiItem(User1, KGuiItem(i18n(
"Save"), QLatin1String(
"document-save")));
 
  358     setMaximumSize(sizeHint());
 
  360     QVBoxLayout *layout = 
new QVBoxLayout(mainWidget());
 
  361     layout->setSpacing(30);
 
  364     KTitleWidget *titleWidget = 
new KTitleWidget(
this);
 
  366     titleWidget->setPixmap(presence.icon().pixmap(32, 32), KTitleWidget::ImageLeft);
 
  367     titleWidget->setText(contact->alias());
 
  368     titleWidget->setComment(contact->id());
 
  369     layout->addWidget(titleWidget);
 
  372     d->messageWidget = 
new KMessageWidget(
this);
 
  373     d->messageWidget->setVisible(
false);
 
  374     layout->addWidget(d->messageWidget);
 
  377     d->columnsLayout = 
new QHBoxLayout();
 
  378     d->columnsLayout->setSpacing(30);
 
  379     layout->addLayout(d->columnsLayout);
 
  382     Tp::PendingContacts *op = contact->manager()->upgradeContacts(
 
  383             QList<Tp::ContactPtr>() << contact,
 
  384             Tp::Features() << Tp::Contact::FeatureAvatarData
 
  385                            << Tp::Contact::FeatureInfo);
 
  386     connect(op, SIGNAL(finished(Tp::PendingOperation*)), SLOT(onContactUpgraded(Tp::PendingOperation*)));
 
  390         d->stateLayout = 
new QFormLayout();
 
  391         d->stateLayout->setSpacing(10);
 
  392         layout->addLayout(d->stateLayout);
 
  393         d->addStateRow(i18n(
"Contact can see when you are online:"), contact->publishState());
 
  394         d->addStateRow(i18n(
"You can see when the contact is online:"), contact->subscriptionState());
 
  395         d->addStateRow(i18n(
"Contact is blocked:"), contact->isBlocked() ? Tp::Contact::PresenceStateYes : Tp::Contact::PresenceStateNo);
 
  406     if (button == User1) {
 
  407         if (d->avatarChanged) {
 
  409             if (!d->newAvatarFile.isEmpty()) {
 
  410                 QFile file(d->newAvatarFile);
 
  411                 file.open(QIODevice::ReadOnly);
 
  415                 avatar.avatarData = file.readAll();
 
  417                 avatar.MIMEType = KMimeType::findByNameAndContent(d->newAvatarFile, &file)->defaultMimeType();
 
  420             d->account->setAvatar(avatar);
 
  423         if (d->infoDataChanged) {
 
  424             Tp::ContactInfoFieldList fieldList;
 
  429                 Tp::ContactInfoField field;
 
  430                 field.fieldName = row->fieldName;
 
  433                     KDateComboBox *combo = qobject_cast<KDateComboBox*>(d->infoValueWidgets.value(index));
 
  434                     field.fieldValue << combo->date().toString();
 
  436                     KLineEdit *lineEdit = qobject_cast<KLineEdit*>(d->infoValueWidgets.value(index));
 
  437                     field.fieldValue << lineEdit->text();
 
  443 #if 0   // This method does not exist in TpQt (yet) 
  444             d->account->connection()->setContactInfo(fieldList);
 
  458 #include "contact-info-dialog.moc"