Skip to content

Instantly share code, notes, and snippets.

@shadeslayer
Created May 11, 2011 16:28
Show Gist options
  • Select an option

  • Save shadeslayer/966812 to your computer and use it in GitHub Desktop.

Select an option

Save shadeslayer/966812 to your computer and use it in GitHub Desktop.
Temp
/*
* Tool button which controls account's presence
*
* Copyright (C) 2011 Martin Klapetek <martin dot klapetek at gmail dot com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "account-button.h"
#include <QtGui/QPainter>
#include <QtGui/QPixmap>
#include <QListWidget>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include<QtGui/QPushButton>
#include <KAction>
#include <KToggleAction>
#include <KIcon>
#include <KDialog>
#include <KComboBox>
#include <KConfig>
#include <KLineEdit>
#include <KGlobalSettings>
#include <KLocale>
#include <KMenu>
#include <KPixmapSequenceOverlayPainter>
#include <KPixmapSequence>
#include <KIconLoader>
#include <TelepathyQt4/Account>
#include <TelepathyQt4/PendingOperation>
AccountButton::AccountButton(const Tp::AccountPtr &account, QWidget* parent)
: QToolButton(parent), m_busyOverlay(0)
{
m_account = account;
m_busyOverlay = new KPixmapSequenceOverlayPainter(this);
m_busyOverlay->setWidget(this);
m_busyOverlay->setSequence(KPixmapSequence(QString("process-working")));
m_header = new KMenu(this);
m_header->setMinimumWidth(150);
QFont titleFont = KGlobalSettings::menuFont();
QFontMetrics *titleFontMetrics = new QFontMetrics(titleFont);
QString accountName = titleFontMetrics->elidedText(m_account->displayName(), Qt::ElideMiddle, m_header->width());
m_header->addTitle(KIcon(m_account->iconName()), accountName);
m_errorPixmap = KIconLoader::global()->loadIcon("dialog-error", KIconLoader::NoGroup, 16);
m_onlinePixmap = KIconLoader::global()->loadIcon("user-online", KIconLoader::NoGroup, 16);
m_awayPixmap = KIconLoader::global()->loadIcon("user-away", KIconLoader::NoGroup, 16);
m_awayExPixmap = KIconLoader::global()->loadIcon("user-away-extended", KIconLoader::NoGroup, 16);
m_busyPixmap = KIconLoader::global()->loadIcon("user-busy", KIconLoader::NoGroup, 16);
m_hiddenPixmap = KIconLoader::global()->loadIcon("user-invisible", KIconLoader::NoGroup, 16);
m_offlinePixmap = KIconLoader::global()->loadIcon("user-offline", KIconLoader::NoGroup, 16);
QString iconPath = account->iconName();
setIcon(KIcon(iconPath));
if (!account->isValid()) {
//we paint a warning symbol in the right-bottom corner
QPixmap pixmap = icon().pixmap(32, 32);
QPainter painter(&pixmap);
painter.drawPixmap(15, 15, 16, 16, m_errorPixmap);
setIcon(KIcon(pixmap));
}
setMaximumWidth(24);
setAutoRaise(true);
setPopupMode(QToolButton::InstantPopup);
setArrowType(Qt::NoArrow);
titleFont = KGlobalSettings::generalFont();
delete titleFontMetrics;
titleFontMetrics = new QFontMetrics(titleFont);
KAction *onlineAction = new KAction(KIcon("user-online"), i18nc("@action:inmenu This is an IM user status", "Available"), m_header);
KAction *busyAction = new KAction(KIcon("user-busy"), i18nc("@action:inmenu This is an IM user status", "Busy"), m_header);
KAction *offlineAction = new KAction(KIcon("user-offline"), i18nc("@action:inmenu This is an IM user status", "Offline"), m_header);
KAction *awayAction = new KAction(KIcon("user-away"), i18nc("@action:inmenu This is an IM user status", "Away"), m_header);
KAction *invisibleAction = new KAction(KIcon("user-invisible"), i18nc("@action:inmenu This is an IM user status", "Invisible"), m_header);
KAction *customAvailableAction = new KAction(KIcon("user-online"), i18nc("@action:inmenu This is an IM user status", "Custom Message"), m_header);
KAction *customBusyAction = new KAction(KIcon("user-busy"), i18nc("@action:inmenu This is an IM user status", "Custom Message"), m_header);
customAvailableAction->setCheckable(false);
customBusyAction->setCheckable(false);
//let's set the presences as data so we can easily just use the Tp::Presence when the action has been triggered
onlineAction->setData(qVariantFromValue(Tp::Presence::available()));
awayAction->setData(qVariantFromValue(Tp::Presence::away()));
// brbAction->setData(qVariantFromValue(Tp::Presence::brb()));
busyAction->setData(qVariantFromValue(Tp::Presence::busy()));
// dndAction->setData(qVariantFromValue(Tp::Presence::busy()));
// xaAction->setData(qVariantFromValue(Tp::Presence::xa()));
invisibleAction->setData(qVariantFromValue(Tp::Presence::hidden()));
offlineAction->setData(qVariantFromValue(Tp::Presence::offline()));
m_header->addAction(onlineAction);
m_header->addAction(customAvailableAction);
m_header->addSeparator();
m_header->addAction(busyAction);
m_header->addAction(awayAction);
m_header->addAction(customBusyAction);
m_header->addSeparator();
m_header->addAction(invisibleAction);
m_header->addAction(offlineAction);
addActions(m_header->actions());
this->setMenu(m_header);
//set the current status as checked and paint presence overlay
presenceChanged(m_account->currentPresence());
connect(this, SIGNAL(triggered(QAction*)),
this, SLOT(setAccountStatus(QAction*)));
connect(m_account.data(),SIGNAL(connectionStatusChanged(Tp::ConnectionStatus)),
this, SLOT(connectionChanged(Tp::ConnectionStatus)));
connect(m_account.data(), SIGNAL(currentPresenceChanged(Tp::Presence)),
this, SLOT(presenceChanged(Tp::Presence)));
connect(customAvailableAction, SIGNAL(triggered()),
this, SLOT(customStatusDialog(AccountButton::availableCustomStatusType)));
connect(customAvailableAction, SIGNAL(triggered()),
this, SLOT(customStatusDialog(AccountButton::busyCustomStatusType)));
updateToolTip();
}
QString AccountButton::accountId()
{
return m_account->uniqueIdentifier();
}
void AccountButton::setAccountStatus(QAction *action)
{
Tp::SimplePresence presence;
presence.type = qVariantValue<Tp::Presence>(action->data()).type();
presence.status = qVariantValue<Tp::Presence>(action->data()).status();
presence.statusMessage = m_customPresenceMessage;
Q_ASSERT(!m_account.isNull());
Tp::PendingOperation* presenceRequest = m_account->setRequestedPresence(presence);
connect(presenceRequest, SIGNAL(finished(Tp::PendingOperation*)),
this, SLOT(updateToolTip()));
}
void AccountButton::updateToolTip()
{
//check if the custom status message has been set
if (m_account->currentPresence().statusMessage().isEmpty()) {
setToolTip(QString("%1\n%2").arg(m_account->displayName())
.arg(presenceDisplayString(m_account->currentPresence())));
} else {
setToolTip(QString("%1\n%2\n%3").arg(m_account->displayName())
.arg(presenceDisplayString(m_account->currentPresence()))
.arg(m_account->currentPresence().statusMessage()));
}
}
void AccountButton::connectionChanged(const Tp::ConnectionStatus &status)
{
switch (status) {
case Tp::ConnectionStatusConnecting:
showBusyIndicator();
break;
case Tp::ConnectionStatusConnected:
case Tp::ConnectionStatusDisconnected:
hideBusyIndicator();
break;
default:
break;
}
}
void AccountButton::showBusyIndicator()
{
m_busyOverlay->start();
}
void AccountButton::hideBusyIndicator()
{
m_busyOverlay->stop();
}
void AccountButton::presenceChanged(const Tp::Presence &presence)
{
if (!presence.isValid()) {
return;
}
bool accountPresenceFound = false;
foreach (QAction *a, actions()) {
QFont presenceFont = KGlobalSettings::generalFont();
presenceFont.setItalic(true);
presenceFont.setBold(true);
if (presence.type() == qVariantValue<Tp::Presence>(a->data()).type()) {
a->setFont(presenceFont);
updateToolTip();
accountPresenceFound = true;
QPixmap pixmap = icon().pixmap(32, 32);
QPainter painter(&pixmap);
KIcon(a->icon()).paint(&painter, 15, 15, 16, 16);
setIcon(KIcon(pixmap));
break;
}
}
if (!accountPresenceFound) {
presenceChanged(Tp::Presence::offline());
}
}
/* since there is no easy way to get this string by Tp::Presence,
we need to loop through all the actions and return the right one.
This will also get us i18n strings for free. */
QString AccountButton::presenceDisplayString(const Tp::Presence &presence)
{
foreach (QAction *a, actions()) {
if (presence.status() == qVariantValue<Tp::Presence>(a->data()).status()) {
return a->text();
}
}
return QString();
}
void AccountButton::setCustomPresenceMessage(const QString& message)
{
m_customPresenceMessage = message;
Tp::SimplePresence presence;
presence.type = m_account->currentPresence().type();
presence.status = m_account->currentPresence().status();
presence.statusMessage = m_customPresenceMessage;
Q_ASSERT(!m_account.isNull());
Tp::PendingOperation* presenceRequest = m_account->setRequestedPresence(presence);
connect(presenceRequest, SIGNAL(finished(Tp::PendingOperation*)),
this, SLOT(updateToolTip()));
}
void AccountButton::customStatusDialog(AccountButton::customstatusType type)
{
KSharedConfigPtr config = KGlobal::config();
KConfigGroup configGroup(config, "Status");
QStringList statusList;
statusList = configGroup.readEntry(m_account->uniqueIdentifier(), QStringList());
KDialog *dialog = new KDialog(this);
dialog->setCaption(i18n("Custom Status"));
dialog->setButtons(KDialog::Close);
QVBoxLayout *vLayout = new QVBoxLayout(dialog);
QListWidget *listWidget = new QListWidget(dialog);
new QListWidgetItem(KIcon("user-online"), i18n("Foo"), listWidget );
KComboBox* statusMessage = new KComboBox(true, dialog);
if(type == busyCustomStatusType){
statusMessage->addItem(KIcon("user-busy"), QString("Set custom busy message"), qVariantFromValue(Tp::Presence::busy()));
}
else if(type == availableCustomStatusType){
statusMessage->addItem(KIcon("user-online"), QString("Set custom available message"),qVariantFromValue(Tp::Presence::available()));
}
statusMessage->setAutoCompletion(false);
statusMessage->show();
QPushButton *addStatus = new QPushButton(KIcon("list-add"), i18n("Add Status"), dialog);
// QPushButton *removeStatus = new QPushButton(dialog);
QHBoxLayout *hLayout = new QHBoxLayout(dialog);
hLayout->addWidget(statusMessage);
hLayout->addWidget(addStatus);
vLayout->addLayout(hLayout);
vLayout->addWidget(listWidget);
dialog->setLayout(vLayout);
dialog->show();
}
#include "account-button.moc"
/*
* Tool button which controls account's presence
*
* Copyright (C) 2011 Martin Klapetek <martin dot klapetek at gmail dot com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef TELEPATHY_ACCOUNTBUTTON_H
#define TELEPATHY_ACCOUNTBUTTON_H
#include <QToolButton>
#include <TelepathyQt4/Types>
#include <TelepathyQt4/Presence>
class QAction;
class KPixmapSequenceOverlayPainter;
class KMenu;
class AccountButton : public QToolButton
{
Q_OBJECT
public:
enum customstatusType{
availableCustomStatusType,
busyCustomStatusType
};
explicit AccountButton(const Tp::AccountPtr &account, QWidget *parent = 0);
///Returns the unique account ID
QString accountId();
///Returns the action (menu item) string for displaying elsewhere on the screen
QString presenceDisplayString(const Tp::Presence &presence);
public Q_SLOTS:
///Sets the account status contained in action (connects to triggered(QAction*) signal)
void setAccountStatus(QAction *action);
///Updates the tooltip with the latest selected status
void updateToolTip();
///Called when the connection status changes
void connectionChanged(const Tp::ConnectionStatus &status);
///Shows the animated busy icon over the button
void showBusyIndicator();
///Hides the animated busy icon over the button
void hideBusyIndicator();
///Called when the account presence changes
void presenceChanged(const Tp::Presence &presence);
///Sets the custom presence message
void setCustomPresenceMessage(const QString &message);
///Calls Dialog for setting custom message
void customStatusDialog(AccountButton::customstatusType type);
private:
///Holds the account it controls
Tp::AccountPtr m_account;
///Contains the custom presence string
QString m_customPresenceMessage;
///The busy icon which is painted when connecting
KPixmapSequenceOverlayPainter *m_busyOverlay;
KMenu *m_header;
QPixmap m_errorPixmap;
QPixmap m_onlinePixmap;
QPixmap m_awayPixmap;
QPixmap m_busyPixmap;
QPixmap m_awayExPixmap;
QPixmap m_hiddenPixmap;
QPixmap m_offlinePixmap;
};
#endif // TELEPATHY_ACCOUNTBUTTON_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment