File indexing completed on 2023-11-26 04:55:35

0001 /*
0002  * This file is part of telepathy-accounts-kcm
0003  *
0004  * Copyright (C) 2011 David Edmundson <kde@davidedmundson.co.uk>
0005  * Copyright (C) 2012 Daniele E. Domenichelli <daniele.domenichelli@gmail.com>
0006  *
0007  * This library is free software; you can redistribute it and/or
0008  * modify it under the terms of the GNU Lesser General Public
0009  * License as published by the Free Software Foundation; either
0010  * version 2.1 of the License, or (at your option) any later version.
0011  *
0012  * This library is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  * Lesser General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU Lesser General Public
0018  * License along with this library; if not, write to the Free Software
0019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
0020  */
0021 
0022 #include "accounts-list-delegate.h"
0023 
0024 #include "edit-display-name-button.h"
0025 #include "change-icon-button.h"
0026 
0027 #include <KTp/presence.h>
0028 #include <KTp/Models/accounts-list-model.h>
0029 
0030 #include <KDE/KLocale>
0031 #include <KDE/KIconButton>
0032 #include <KDE/KMenu>
0033 #include <KDE/KAction>
0034 #include <KDE/KDebug>
0035 
0036 #include <QtGui/QApplication>
0037 #include <QtGui/QPainter>
0038 #include <QtGui/QCheckBox>
0039 #include <QtGui/QAbstractItemView>
0040 #include <QtGui/QSortFilterProxyModel>
0041 #include <QtGui/QLabel>
0042 #include <sys/stat.h>
0043 
0044 
0045 AccountsListDelegate::AccountsListDelegate(QAbstractItemView *itemView, QObject *parent)
0046     : KWidgetItemDelegate(itemView, parent)
0047 {
0048 }
0049 
0050 QSize AccountsListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
0051 {
0052     Q_UNUSED(index);
0053 
0054     int iconHeight = option.decorationSize.height() + (m_vpadding*2);  //icon height + padding either side
0055     int textHeight = option.fontMetrics.height()*2 + (m_vpadding*2) + 10; // text height * 2 + padding + some space between the lines
0056 
0057     return QSize(-1,qMax(iconHeight, textHeight)); //any width,the view should give us the whole thing.
0058 }
0059 
0060 QList<QWidget*> AccountsListDelegate::createItemWidgets() const
0061 {
0062     // Items created by this method and added to the list returned will be
0063     // deleted by KWidgetItemDelegate
0064 
0065     QCheckBox *checkbox = new QCheckBox();
0066     connect(checkbox, SIGNAL(clicked(bool)), SLOT(onCheckBoxToggled(bool)));
0067 
0068     ChangeIconButton *changeIconButton = new ChangeIconButton();
0069     changeIconButton->setFlat(true);
0070     changeIconButton->setToolTip(i18n("Change account icon"));
0071     changeIconButton->setWhatsThis(i18n("This button allows you to change the icon for your account.<br />"
0072                                   "This icon is just used locally on your computer, your contacts will not be able to see it."));
0073 
0074     QLabel *statusTextLabel = new QLabel();
0075     QLabel *statusIconLabel = new QLabel();
0076 
0077     EditDisplayNameButton *displayNameButton = new EditDisplayNameButton();
0078     displayNameButton->setFlat(true);
0079     displayNameButton->setToolTip(i18n("Change account display name"));
0080     displayNameButton->setWhatsThis(i18n("This button allows you to change the display name for your account.<br />"
0081                                          "The display name is an alias for your account and is just used locally "
0082                                          "on your computer, your contacts will not be able to see it."));
0083 
0084     QLabel *connectionErrorLabel = new QLabel();
0085 
0086     return QList<QWidget*>() << checkbox
0087                              << changeIconButton
0088                              << statusTextLabel
0089                              << statusIconLabel
0090                              << displayNameButton
0091                              << connectionErrorLabel;
0092 }
0093 
0094 
0095 void AccountsListDelegate::updateItemWidgets(const QList<QWidget *> widgets, const QStyleOptionViewItem &option, const QPersistentModelIndex &index) const
0096 {
0097     // draws:
0098     //                   AccountName
0099     // Checkbox | Icon |              | ConnectionIcon | ConnectionState
0100     //                   errorMessage
0101 
0102     if (!index.isValid()) {
0103         return;
0104     }
0105 
0106     Q_ASSERT(widgets.size() == 6);
0107 
0108     // Get the widgets
0109     QCheckBox* checkbox = qobject_cast<QCheckBox*>(widgets.at(0));
0110     ChangeIconButton* changeIconButton = qobject_cast<ChangeIconButton*>(widgets.at(1));
0111     QLabel *statusTextLabel = qobject_cast<QLabel*>(widgets.at(2));
0112     QLabel *statusIconLabel = qobject_cast<QLabel*>(widgets.at(3));
0113     EditDisplayNameButton *displayNameButton = qobject_cast<EditDisplayNameButton*>(widgets.at(4));
0114     QLabel *connectionErrorLabel = qobject_cast<QLabel*>(widgets.at(5));
0115 
0116     Q_ASSERT(checkbox);
0117     Q_ASSERT(changeIconButton);
0118     Q_ASSERT(statusTextLabel);
0119     Q_ASSERT(statusIconLabel);
0120     Q_ASSERT(displayNameButton);
0121     Q_ASSERT(connectionErrorLabel);
0122 
0123 
0124     bool isSelected(itemView()->selectionModel()->isSelected(index) && itemView()->hasFocus());
0125     bool isEnabled(index.data(KTp::AccountsListModel::EnabledRole).toBool());
0126     KIcon accountIcon(index.data(Qt::DecorationRole).value<QIcon>());
0127     KIcon statusIcon(index.data(KTp::AccountsListModel::ConnectionStateIconRole).value<QIcon>());
0128     QString statusText(index.data(KTp::AccountsListModel::ConnectionStateDisplayRole).toString());
0129     QString displayName(index.data(Qt::DisplayRole).toString());
0130     QString connectionError(index.data(KTp::AccountsListModel::ConnectionErrorMessageDisplayRole).toString());
0131     Tp::AccountPtr account(index.data(KTp::AccountsListModel::AccountRole).value<Tp::AccountPtr>());
0132 
0133     if (!account->isEnabled()) {
0134       connectionError = i18n("Click checkbox to enable");
0135     }
0136 
0137     QRect outerRect(0, 0, option.rect.width(), option.rect.height());
0138     QRect contentRect = outerRect.adjusted(m_hpadding,m_vpadding,-m_hpadding,-m_vpadding); //add some padding
0139 
0140 
0141     // checkbox
0142     if (isEnabled) {
0143         checkbox->setChecked(true);;
0144         checkbox->setToolTip(i18n("Disable account"));
0145     } else {
0146         checkbox->setChecked(false);
0147         checkbox->setToolTip(i18n("Enable account"));
0148     }
0149 
0150     int checkboxLeftMargin = contentRect.left();
0151     int checkboxTopMargin = (outerRect.height() - checkbox->height()) / 2;
0152     checkbox->move(checkboxLeftMargin, checkboxTopMargin);
0153 
0154 
0155     // changeIconButton
0156     changeIconButton->setIcon(accountIcon);
0157     changeIconButton->setAccount(account);
0158     // At the moment (KDE 4.8.1) decorationSize is not passed from KWidgetItemDelegate
0159     // through the QStyleOptionViewItem, therefore we leave default size unless
0160     // the user has a more recent version.
0161     if (option.decorationSize.width() > -1) {
0162         changeIconButton->setButtonIconSize(option.decorationSize.width());
0163     }
0164 
0165     int changeIconButtonLeftMargin = checkboxLeftMargin + checkbox->width();
0166     int changeIconButtonTopMargin = (outerRect.height() - changeIconButton->height()) / 2;
0167     changeIconButton->move(changeIconButtonLeftMargin, changeIconButtonTopMargin);
0168 
0169 
0170     // statusTextLabel
0171     QFont statusTextFont = option.font;
0172     QPalette statusTextLabelPalette = option.palette;
0173     if (isEnabled) {
0174         statusTextLabel->setEnabled(true);
0175         statusTextFont.setItalic(false);
0176     } else {
0177         statusTextLabel->setDisabled(true);
0178         statusTextFont.setItalic(true);
0179     }
0180     if (isSelected) {
0181         statusTextLabelPalette.setColor(QPalette::Text, statusTextLabelPalette.color(QPalette::Active, QPalette::HighlightedText));
0182     }
0183     statusTextLabel->setPalette(statusTextLabelPalette);
0184     statusTextLabel->setFont(statusTextFont);
0185     statusTextLabel->setText(statusText);
0186     statusTextLabel->setFixedSize(statusTextLabel->fontMetrics().boundingRect(statusText).width(),
0187                                   statusTextLabel->height());
0188     int statusTextLabelLeftMargin = contentRect.right() - statusTextLabel->width();
0189     int statusTextLabelTopMargin = (outerRect.height() - statusTextLabel->height()) / 2;
0190     statusTextLabel->move(statusTextLabelLeftMargin, statusTextLabelTopMargin);
0191 
0192 
0193     // statusIconLabel
0194     statusIconLabel->setPixmap(statusIcon.pixmap(KIconLoader::SizeSmall));
0195     statusIconLabel->setFixedSize(statusIconLabel->minimumSizeHint());
0196     int statusIconLabelLeftMargin = contentRect.right() - statusTextLabel->width() - statusIconLabel->width() - 6;
0197     int statusIconLabelTopMargin = (outerRect.height() - statusIconLabel->height()) / 2;
0198     statusIconLabel->move(statusIconLabelLeftMargin, statusIconLabelTopMargin);
0199 
0200 
0201     QRect innerRect = contentRect.adjusted(changeIconButton->geometry().right() - contentRect.left(),
0202                                            0,
0203                                            -statusTextLabel->width() - statusIconLabel->width() - 6,
0204                                            0); // rect containing account name and error message
0205 
0206 
0207     // displayNameButton
0208     QFont displayNameButtonFont = option.font;
0209     QPalette displayNameButtonPalette = option.palette;
0210     if (isEnabled) {
0211         displayNameButtonPalette.setColor(QPalette::WindowText, displayNameButtonPalette.color(QPalette::Active, QPalette::Text));
0212         displayNameButtonFont.setBold(true);
0213     } else {
0214         displayNameButtonFont.setItalic(true);
0215         // NOTE: Flat QPushButton use WindowText instead of ButtonText for button text color
0216         displayNameButtonPalette.setColor(QPalette::WindowText, displayNameButtonPalette.color(QPalette::Disabled, QPalette::Text));
0217     }
0218     if (isSelected) {
0219         // Account is selected
0220         displayNameButtonPalette.setColor(QPalette::WindowText, displayNameButtonPalette.color(QPalette::Active, QPalette::HighlightedText));
0221     }
0222     displayNameButton->setFont(displayNameButtonFont);
0223     displayNameButton->setPalette(displayNameButtonPalette);
0224 
0225     QString displayNameButtonText = displayNameButton->fontMetrics().elidedText(displayName,
0226                                                                                 Qt::ElideRight,
0227                                                                                 innerRect.width() - (m_hpadding*2));
0228     displayNameButton->setText(displayNameButtonText);
0229     displayNameButton->setFixedSize(displayNameButton->fontMetrics().boundingRect(displayNameButtonText).width() + (m_hpadding*2),
0230                                     displayNameButton->minimumSizeHint().height());
0231     displayNameButton->setAccount(account);
0232 
0233     int displayNameButtonLeftMargin = innerRect.left();
0234     int displayNameButtonTopMargin = innerRect.top();
0235     displayNameButton->move(displayNameButtonLeftMargin, displayNameButtonTopMargin);
0236 
0237 
0238     // connectionErrorLabel
0239     QFont connectionErrorLabelFont = option.font;
0240     QPalette connectionErrorLabelPalette = option.palette;
0241     if (isEnabled) {
0242         connectionErrorLabelPalette.setColor(QPalette::WindowText, connectionErrorLabelPalette.color(QPalette::Active, QPalette::Text));
0243     } else {
0244         connectionErrorLabelFont.setItalic(true);
0245         connectionErrorLabelPalette.setColor(QPalette::Text, connectionErrorLabelPalette.color(QPalette::Disabled, QPalette::Text));
0246     }
0247     if (isSelected) {
0248         // Account is selected
0249         connectionErrorLabelPalette.setColor(QPalette::Text, connectionErrorLabelPalette.color(QPalette::Active, QPalette::HighlightedText));
0250     }
0251     connectionErrorLabel->setFont(connectionErrorLabelFont);
0252     connectionErrorLabel->setPalette(connectionErrorLabelPalette);
0253 
0254     QString connectionErrorLabelText = connectionErrorLabel->fontMetrics().elidedText(connectionError,
0255                                                                                       Qt::ElideRight,
0256                                                                                       innerRect.width() - (m_hpadding*2));
0257     connectionErrorLabel->setText(connectionErrorLabelText);
0258     connectionErrorLabel->setFixedSize(connectionErrorLabel->fontMetrics().boundingRect(connectionErrorLabelText).width(),
0259                                        displayNameButton->height());
0260 
0261     int connectionErrorLabelLeftMargin = innerRect.left() + m_hpadding;
0262     int connectionErrorLabelTopMargin = contentRect.bottom() - displayNameButton->height();
0263     connectionErrorLabel->move(connectionErrorLabelLeftMargin, connectionErrorLabelTopMargin);
0264 }
0265 
0266 void AccountsListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
0267 {
0268     if (!index.isValid()) {
0269         return;
0270     }
0271 
0272     QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0);
0273 }
0274 
0275 
0276 void AccountsListDelegate::onCheckBoxToggled(bool checked)
0277 {
0278     QModelIndex index = focusedIndex();
0279     Q_EMIT itemChecked(index, checked);
0280 }