File indexing completed on 2023-11-26 04:55:35
0001 /* 0002 * Button representing user's Avatar 0003 * 0004 * Copyright (C) 2011 Martin Klapetek <martin.klapetek@gmail.com> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Lesser General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2.1 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Lesser General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Lesser General Public 0017 * License along with this library; if not, write to the Free Software 0018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0019 */ 0020 0021 #include "avatar-button.h" 0022 0023 #include <QtGui/QWidgetAction> 0024 #include <QDataStream> 0025 0026 #include <KFileDialog> 0027 #include <KMenu> 0028 #include <KLocalizedString> 0029 #include <KMessageBox> 0030 #include <KImageFilePreview> 0031 0032 #include <TelepathyQt/Account> 0033 0034 #include <KDE/KDebug> 0035 #include <KGlobalSettings> 0036 #include <KPixmapRegionSelectorDialog> 0037 #include <KPixmapRegionSelectorWidget> 0038 0039 // It has been decided by a fair dice roll that 128px is a reasonable avatar 0040 // size limit in case the server (or Telepathy backend) does not provide 0041 // such information 0042 #define AVATAR_MIN_SIZE 64 0043 #define AVATAR_MAX_SIZE 128 0044 0045 AvatarButton::AvatarButton(QWidget *parent) 0046 : QToolButton(parent) 0047 { 0048 KMenu *menu = new KMenu(this); 0049 0050 setPopupMode(QToolButton::InstantPopup); 0051 0052 setIconSize(QSize(64,64)); 0053 0054 menu->addAction(KIcon(QLatin1String("document-open-folder")), i18n("Load from file..."), this, SLOT(onLoadAvatarFromFile())); 0055 menu->addAction(KIcon(QLatin1String("edit-clear")), i18n("Clear Avatar"), this, SLOT(onClearAvatar())); 0056 0057 setMenu(menu); 0058 } 0059 0060 AvatarButton::~AvatarButton() 0061 { 0062 0063 } 0064 0065 void AvatarButton::setAvatar(const Tp::Avatar &avatar) 0066 { 0067 m_avatar = avatar; 0068 0069 if (! avatar.avatarData.isNull()) { 0070 KIcon avatarIcon; 0071 QPixmap avatarPixmap = QPixmap::fromImage(QImage::fromData(avatar.avatarData)); 0072 //scale oversized avatars to fit, but don't stretch smaller avatars 0073 avatarIcon.addPixmap(avatarPixmap.scaled(iconSize().boundedTo(avatarPixmap.size()), Qt::KeepAspectRatio, Qt::SmoothTransformation)); 0074 setIcon(avatarIcon); 0075 } else { 0076 setIcon(KIcon(QLatin1String("im-user"))); 0077 } 0078 } 0079 0080 Tp::Avatar AvatarButton::avatar() const 0081 { 0082 return m_avatar; 0083 } 0084 0085 void AvatarButton::setAccount(const Tp::AccountPtr& account) 0086 { 0087 m_account = account; 0088 } 0089 0090 void AvatarButton::onLoadAvatarFromFile() 0091 { 0092 QStringList mimeTypes; 0093 if (m_account) { 0094 mimeTypes = m_account->avatarRequirements().supportedMimeTypes(); 0095 } 0096 if (mimeTypes.isEmpty()) { 0097 mimeTypes << QLatin1String("image/jpeg") 0098 << QLatin1String("image/png") 0099 << QLatin1String("imgae/gif"); 0100 } 0101 0102 QPointer<KFileDialog> dialog = new KFileDialog(KUrl::fromPath(KGlobalSettings::picturesPath()), 0103 mimeTypes.join(QLatin1String(" ")), this); 0104 dialog->setOperationMode(KFileDialog::Opening); 0105 dialog->setPreviewWidget(new KImageFilePreview(dialog)); 0106 dialog->setCaption(i18n("Please choose your avatar")); 0107 0108 KUrl fileUrl; 0109 if (dialog->exec()) { 0110 if (!dialog) { 0111 return; 0112 } 0113 0114 fileUrl = dialog->selectedUrl(); 0115 } 0116 0117 delete dialog; 0118 0119 if (fileUrl.isEmpty()) { 0120 return; 0121 } 0122 0123 const QPixmap pixmap(fileUrl.toLocalFile()); 0124 0125 const Tp::AvatarSpec spec = m_account->avatarRequirements(); 0126 0127 const int maxWidth = spec.maximumWidth() > 0 ? spec.maximumWidth() : AVATAR_MAX_SIZE; 0128 const int maxHeight = spec.maximumHeight() > 0 ? spec.maximumHeight() : AVATAR_MAX_SIZE; 0129 const int minWidth = spec.minimumWidth() > 0 ? spec.minimumWidth() : AVATAR_MIN_SIZE; 0130 const int minHeight = spec.minimumHeight() > 0 ? spec.minimumHeight() : AVATAR_MIN_SIZE; 0131 0132 QPixmap finalPixmap; 0133 if (pixmap.width() > spec.maximumWidth() || pixmap.height() > spec.maximumHeight()) { 0134 finalPixmap = cropPixmap(pixmap, maxWidth, maxHeight, minWidth, minHeight); 0135 } else { 0136 finalPixmap = pixmap; 0137 0138 if (pixmap.width() < minWidth) { 0139 finalPixmap = finalPixmap.scaledToWidth(minWidth, Qt::SmoothTransformation); 0140 } 0141 0142 if (pixmap.height() < minHeight) { 0143 finalPixmap = finalPixmap.scaledToHeight(minHeight, Qt::SmoothTransformation); 0144 } 0145 } 0146 0147 if (finalPixmap.isNull()) { 0148 return; 0149 } 0150 0151 Tp::Avatar avatar; 0152 avatar.MIMEType = QLatin1String("image/png"); 0153 QDataStream stream(&avatar.avatarData, QIODevice::WriteOnly); 0154 if (!finalPixmap.save(stream.device(), "PNG")) { 0155 KMessageBox::error(this, i18n("Failed to load avatar.")); 0156 return; 0157 } 0158 0159 setAvatar(avatar); 0160 Q_EMIT avatarChanged(); 0161 } 0162 0163 QPixmap AvatarButton::cropPixmap(const QPixmap &pixmap, int maxWidth, int maxHeight, 0164 int minWidth, int minHeight) const 0165 { 0166 //if there's no image we don't need to select a region 0167 if (pixmap.isNull()) { 0168 return pixmap; 0169 } 0170 0171 QPointer<KPixmapRegionSelectorDialog> regionDlg = new KPixmapRegionSelectorDialog(); 0172 KPixmapRegionSelectorWidget *widget = regionDlg->pixmapRegionSelectorWidget(); 0173 widget->setPixmap(pixmap); 0174 widget->setSelectionAspectRatio(maxWidth, maxHeight); 0175 0176 if (regionDlg->exec()) { 0177 if (!regionDlg) { 0178 return QPixmap(); 0179 } 0180 0181 delete regionDlg; 0182 0183 QImage selectedImage = widget->selectedImage(); 0184 if (selectedImage.width() > maxWidth || selectedImage.height() > maxHeight) { 0185 return QPixmap::fromImage(selectedImage.scaled(maxWidth, maxHeight, Qt::KeepAspectRatio)); 0186 } else if (selectedImage.width() < minWidth || selectedImage.height() < minHeight) { 0187 return QPixmap::fromImage(selectedImage.scaled(minWidth, minHeight, Qt::KeepAspectRatio)); 0188 } else { 0189 return QPixmap::fromImage(widget->selectedImage()); 0190 } 0191 } 0192 0193 delete regionDlg; 0194 0195 return QPixmap(); 0196 } 0197 0198 void AvatarButton::onClearAvatar() 0199 { 0200 setAvatar(Tp::Avatar()); 0201 Q_EMIT avatarChanged(); 0202 }