aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorManjeet Dahiya <manjeetdahiya@gmail.com>2010-09-08 09:23:18 +0000
committerManjeet Dahiya <manjeetdahiya@gmail.com>2010-09-08 09:23:18 +0000
commitda88f5f0bb5e73bc69bf7ed3962691622b1ae4f9 (patch)
treec3686f7649785a2bfcc2c637a1588acdb8a721e8 /examples
parent3431f5a37174b7eb8490672686db68df2b48e35f (diff)
downloadqxmpp-da88f5f0bb5e73bc69bf7ed3962691622b1ae4f9.tar.gz
add Gui Client example
Diffstat (limited to 'examples')
-rw-r--r--examples/GuiClient/GuiClient.pro51
-rw-r--r--examples/GuiClient/avatarWidget.cpp41
-rw-r--r--examples/GuiClient/avatarWidget.h14
-rw-r--r--examples/GuiClient/chatDialog.cpp130
-rw-r--r--examples/GuiClient/chatDialog.h56
-rw-r--r--examples/GuiClient/chatDialog.ui82
-rw-r--r--examples/GuiClient/chatGraphicsScene.cpp61
-rw-r--r--examples/GuiClient/chatGraphicsScene.h25
-rw-r--r--examples/GuiClient/chatGraphicsView.cpp43
-rw-r--r--examples/GuiClient/chatGraphicsView.h20
-rw-r--r--examples/GuiClient/customLabel.cpp84
-rw-r--r--examples/GuiClient/customLabel.h36
-rw-r--r--examples/GuiClient/customListView.cpp69
-rw-r--r--examples/GuiClient/customListView.h34
-rw-r--r--examples/GuiClient/customPushButton.cpp72
-rw-r--r--examples/GuiClient/customPushButton.h17
-rw-r--r--examples/GuiClient/customToolButton.cpp51
-rw-r--r--examples/GuiClient/customToolButton.h14
-rw-r--r--examples/GuiClient/main.cpp20
-rw-r--r--examples/GuiClient/mainDialog.cpp409
-rw-r--r--examples/GuiClient/mainDialog.h69
-rw-r--r--examples/GuiClient/mainDialog.ui352
-rw-r--r--examples/GuiClient/messageGraphicsItem.cpp287
-rw-r--r--examples/GuiClient/messageGraphicsItem.h63
-rw-r--r--examples/GuiClient/resource/Thumbs.dbbin0 -> 18432 bytes
-rw-r--r--examples/GuiClient/resource/ajax-loader.gifbin0 -> 3208 bytes
-rw-r--r--examples/GuiClient/resource/avatar.pngbin0 -> 961 bytes
-rw-r--r--examples/GuiClient/resource/downArrow.pngbin0 -> 205 bytes
-rw-r--r--examples/GuiClient/resource/gray.pngbin0 -> 341 bytes
-rw-r--r--examples/GuiClient/resource/green.pngbin0 -> 382 bytes
-rw-r--r--examples/GuiClient/resource/icon.xcfbin0 -> 2452 bytes
-rw-r--r--examples/GuiClient/resource/orange.pngbin0 -> 345 bytes
-rw-r--r--examples/GuiClient/resource/red.pngbin0 -> 359 bytes
-rw-r--r--examples/GuiClient/resource/redred.pngbin0 -> 578 bytes
-rw-r--r--examples/GuiClient/resource/searchIcon.pngbin0 -> 731 bytes
-rw-r--r--examples/GuiClient/resources.qrc12
-rw-r--r--examples/GuiClient/rosterItem.cpp107
-rw-r--r--examples/GuiClient/rosterItem.h144
-rw-r--r--examples/GuiClient/rosterItemModel.cpp82
-rw-r--r--examples/GuiClient/rosterItemModel.h25
-rw-r--r--examples/GuiClient/rosterItemSortFilterProxyModel.cpp41
-rw-r--r--examples/GuiClient/rosterItemSortFilterProxyModel.h13
-rw-r--r--examples/GuiClient/searchLineEdit.cpp53
-rw-r--r--examples/GuiClient/searchLineEdit.h58
-rw-r--r--examples/GuiClient/statusTextWidget.cpp144
-rw-r--r--examples/GuiClient/statusTextWidget.h111
-rw-r--r--examples/GuiClient/statusWidget.cpp130
-rw-r--r--examples/GuiClient/statusWidget.h29
-rw-r--r--examples/GuiClient/statusWidget.ui213
-rw-r--r--examples/GuiClient/utils.cpp120
-rw-r--r--examples/GuiClient/utils.h21
-rw-r--r--examples/GuiClient/vCardManager.cpp176
-rw-r--r--examples/GuiClient/vCardManager.h50
53 files changed, 3629 insertions, 0 deletions
diff --git a/examples/GuiClient/GuiClient.pro b/examples/GuiClient/GuiClient.pro
new file mode 100644
index 00000000..ba06c3c7
--- /dev/null
+++ b/examples/GuiClient/GuiClient.pro
@@ -0,0 +1,51 @@
+include(../examples.pri)
+
+TARGET = GuiClient
+TEMPLATE = app
+
+SOURCES += main.cpp \
+ messageGraphicsItem.cpp \
+ chatGraphicsScene.cpp \
+ chatGraphicsView.cpp \
+ chatDialog.cpp \
+ mainDialog.cpp \
+ rosterItemModel.cpp \
+ rosterItem.cpp \
+ rosterItemSortFilterProxyModel.cpp \
+ utils.cpp \
+ customListView.cpp \
+ searchLineEdit.cpp \
+ statusWidget.cpp \
+ customPushButton.cpp \
+ customLabel.cpp \
+ avatarWidget.cpp \
+ statusTextWidget.cpp \
+ customToolButton.cpp \
+ vCardManager.cpp
+HEADERS += messageGraphicsItem.h \
+ chatGraphicsScene.h \
+ chatGraphicsView.h \
+ chatDialog.h \
+ mainDialog.h \
+ rosterItemModel.h \
+ rosterItem.h \
+ rosterItemSortFilterProxyModel.h \
+ utils.h \
+ customListView.h \
+ searchLineEdit.h \
+ statusWidget.h \
+ customPushButton.h \
+ customLabel.h \
+ avatarWidget.h \
+ statusTextWidget.h \
+ customToolButton.h \
+ vCardManager.h
+
+FORMS += mainDialog.ui \
+ chatDialog.ui \
+ statusWidget.ui
+
+QT += network \
+ xml
+
+RESOURCES += resources.qrc
diff --git a/examples/GuiClient/avatarWidget.cpp b/examples/GuiClient/avatarWidget.cpp
new file mode 100644
index 00000000..535e1d63
--- /dev/null
+++ b/examples/GuiClient/avatarWidget.cpp
@@ -0,0 +1,41 @@
+#include "avatarWidget.h"
+#include <QtGui/QPainter>
+
+avatarWidget::avatarWidget(QWidget* parent)
+ : QPushButton(parent)
+{
+}
+
+void avatarWidget::paintEvent(QPaintEvent* event)
+{
+ Q_UNUSED(event);
+ QPainter painter(this);
+
+ QRect r = rect();
+
+ QPixmap pixmap = icon().pixmap(sizeHint(), QIcon::Normal, QIcon::On);
+ if(pixmap.isNull())
+ pixmap = QPixmap(":/icons/resource/avatar.png");
+ QRect pixRect(0, 0, 32, 32);
+ pixRect.moveCenter(r.center());
+ painter.drawPixmap(pixRect, pixmap);
+
+ if(underMouse() && !isDown())
+ {
+ painter.drawRect(pixRect.adjusted(0, 0, -1, -1));
+ QColor col(Qt::white);
+ col.setAlpha(80);
+ painter.fillRect(pixRect.adjusted(0, 0, -1, -1), col);
+ }
+ if(isDown())
+ {
+ QColor col(Qt::white);
+ col.setAlpha(50);
+ painter.drawRect(pixRect.adjusted(1, 1, -2, -2));
+ }
+}
+
+QSize avatarWidget::sizeHint() const
+{
+ return QSize(32, 32);
+}
diff --git a/examples/GuiClient/avatarWidget.h b/examples/GuiClient/avatarWidget.h
new file mode 100644
index 00000000..1b81d41e
--- /dev/null
+++ b/examples/GuiClient/avatarWidget.h
@@ -0,0 +1,14 @@
+#ifndef AVATARWIDGET_H
+#define AVATARWIDGET_H
+
+#include <QPushButton>
+
+class avatarWidget : public QPushButton
+{
+public:
+ avatarWidget(QWidget* parent = 0);
+ void paintEvent(QPaintEvent* event);
+ QSize sizeHint() const;
+};
+
+#endif // AVATARWIDGET_H
diff --git a/examples/GuiClient/chatDialog.cpp b/examples/GuiClient/chatDialog.cpp
new file mode 100644
index 00000000..b37d51b2
--- /dev/null
+++ b/examples/GuiClient/chatDialog.cpp
@@ -0,0 +1,130 @@
+#include "chatDialog.h"
+#include "ui_chatDialog.h"
+
+#include "chatGraphicsView.h"
+#include "chatGraphicsScene.h"
+#include "QXmppClient.h"
+#include <QPainter>
+#include <QPushButton>
+
+chatDialog::chatDialog(QWidget *parent): QDialog(parent, Qt::Window),
+ ui(new Ui::chatDialogClass), m_scene(0), m_view(0), m_client(0), m_pushButtonSend(0)
+{
+ ui->setupUi(this);
+ m_view = new chatGraphicsView(this);
+ m_scene = new chatGraphicsScene(this);
+ m_view->setChatGraphicsScene(m_scene);
+ m_pushButtonSend = new QPushButton("Send", this);
+// m_pushButtonSend->setFixedHeight();
+// m_pushButtonSend->setFixedWidth();
+ QRect rect = ui->lineEdit->geometry();
+ rect.setLeft(rect.right());
+ rect.setWidth(60);
+ m_pushButtonSend->setGeometry(rect);
+ ui->lineEdit->setFocus();
+ ui->verticalLayout->insertWidget(0, m_view);
+ bool check = connect(m_pushButtonSend, SIGNAL(clicked(bool)), SLOT(sendMessage()));
+ Q_ASSERT(check);
+ updateSendButtonGeomerty();
+}
+
+void chatDialog::show()
+{
+ QDialog::show();
+}
+
+QString chatDialog::getBareJid() const
+{
+ return m_bareJid;
+}
+
+QString chatDialog::getDisplayName() const
+{
+ return m_displayName;
+}
+
+void chatDialog::setBareJid(const QString& str)
+{
+ m_bareJid = str;
+}
+
+void chatDialog::setDisplayName(const QString& str)
+{
+ m_displayName = str;
+ setWindowTitle(QString("Chat with %1").arg(m_displayName));
+
+ QFont font;
+ font.setBold(true);
+ QFontMetrics fontMetrics(font);
+ QRect rect = fontMetrics.boundingRect(m_displayName);
+ int width = rect.width();
+
+ if(m_scene)
+ m_scene->setBoxStartLength(width);
+// ui->horizontalSpacer_2->changeSize(width+20, 10);
+ ui->lineEdit->setFixedWidth(350 - width - 25);
+ updateSendButtonGeomerty();
+}
+
+void chatDialog::setQXmppClient(QXmppClient* client)
+{
+ m_client = client;
+}
+
+void chatDialog::sendMessage()
+{
+ if(m_client)
+ m_client->sendMessage(getBareJid(), ui->lineEdit->text());
+
+ m_view->addMessage("Me", ui->lineEdit->text());
+ ui->lineEdit->clear();
+}
+
+void chatDialog::messageReceived(const QString& msg)
+{
+ m_view->addMessage(getDisplayName(), msg);
+}
+
+void chatDialog::keyPressEvent(QKeyEvent* event1)
+{
+ ui->lineEdit->setFocus();
+ ui->lineEdit->event(event1);
+
+ if(event1->key() == Qt::Key_Return)
+ {
+ m_pushButtonSend->click();
+ }
+ else if(event1->key() == Qt::Key_Escape)
+ {
+ hide();
+ }
+}
+
+void chatDialog::paintEvent(QPaintEvent* event)
+{
+ QDialog::paintEvent(event);
+ QPainter p(this);
+ p.setPen(Qt::gray);
+ p.drawRect(rect().adjusted(5, 5, -6, -6));
+}
+
+void chatDialog::resizeEvent(QResizeEvent *)
+{
+ updateSendButtonGeomerty();
+}
+
+void chatDialog::moveEvent(QMoveEvent *)
+{
+ updateSendButtonGeomerty();
+}
+
+void chatDialog::updateSendButtonGeomerty()
+{
+ QRect rect = ui->lineEdit->geometry();
+ rect.setLeft(rect.right() + 6);
+ rect.setWidth(60);
+ QRect rect2 = rect;
+ rect2.setHeight(25);
+ rect2.moveCenter(rect.center());
+ m_pushButtonSend->setGeometry(rect2);
+}
diff --git a/examples/GuiClient/chatDialog.h b/examples/GuiClient/chatDialog.h
new file mode 100644
index 00000000..9840ac49
--- /dev/null
+++ b/examples/GuiClient/chatDialog.h
@@ -0,0 +1,56 @@
+#ifndef CHATDIALOG_H
+#define CHATDIALOG_H
+
+#include <QDialog>
+#include <QKeyEvent>
+
+namespace Ui
+{
+ class chatDialogClass;
+}
+
+class chatGraphicsView;
+class chatGraphicsScene;
+class QXmppClient;
+class QPushButton;
+
+class chatDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ chatDialog(QWidget *parent = 0);
+ void show();
+
+ QString getBareJid() const;
+ QString getDisplayName() const;
+ void setBareJid(const QString&);
+ void setDisplayName(const QString&);
+ void setQXmppClient(QXmppClient* client);
+ void messageReceived(const QString& msg);
+
+private slots:
+ void sendMessage();
+
+protected:
+ void keyPressEvent(QKeyEvent*);
+ void paintEvent(QPaintEvent* event);
+ virtual void resizeEvent(QResizeEvent*);
+ virtual void moveEvent(QMoveEvent*);
+
+private:
+ void updateSendButtonGeomerty();
+
+ Ui::chatDialogClass *ui;
+ chatGraphicsView* m_view;
+ chatGraphicsScene* m_scene;
+ QPushButton* m_pushButtonSend;
+
+ // holds a reference to the the connected client
+ QXmppClient* m_client;
+
+ QString m_bareJid;
+ QString m_displayName;
+};
+
+#endif // CHATDIALOG_H
diff --git a/examples/GuiClient/chatDialog.ui b/examples/GuiClient/chatDialog.ui
new file mode 100644
index 00000000..0bca14fa
--- /dev/null
+++ b/examples/GuiClient/chatDialog.ui
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>chatDialogClass</class>
+ <widget class="QDialog" name="chatDialogClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>445</width>
+ <height>291</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>445</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <property name="styleSheet">
+ <string>alternate-background-color: rgb(255, 255, 255);</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>6</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QWidget" name="widget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string>background-color: rgb(255, 255, 255);</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEdit">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>50</height>
+ </size>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QWidget" name="widget_2" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="styleSheet">
+ <string>background-color: rgb(255, 255, 255);</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/GuiClient/chatGraphicsScene.cpp b/examples/GuiClient/chatGraphicsScene.cpp
new file mode 100644
index 00000000..415b8c53
--- /dev/null
+++ b/examples/GuiClient/chatGraphicsScene.cpp
@@ -0,0 +1,61 @@
+#include "chatGraphicsScene.h"
+#include "messageGraphicsItem.h"
+#include "chatGraphicsView.h"
+
+chatGraphicsScene::chatGraphicsScene(QObject* parent) : QGraphicsScene(parent),
+ m_verticalPosForNewMessage(0), m_verticalSpacing(5)
+{
+}
+
+void chatGraphicsScene::addMessage(const QString& user, const QString& message)
+{
+ messageGraphicsItem* item = new messageGraphicsItem();
+ m_items.append(item);
+ item->setName(user);
+ item->setBoxStartLength(m_boxStartLength);
+ item->setText(message);
+ item->setViewWidth(350);
+// item->setViewWidth(views().at(0)->size().width());
+ item->setPos(0, m_verticalPosForNewMessage);
+ int height = item->boundingRect().height();
+ m_verticalPosForNewMessage = m_verticalPosForNewMessage + height + m_verticalSpacing;
+ addItem(item);
+
+ QRectF rect = sceneRect();
+ rect.setHeight(m_verticalPosForNewMessage);
+ setSceneRect(rect);
+}
+
+void chatGraphicsScene::setWidthResize(int newWidth, int oldWidth)
+{
+// verticalReposition();
+}
+
+void chatGraphicsScene::verticalReposition()
+{
+ m_verticalPosForNewMessage = 0;
+
+ messageGraphicsItem* item = 0;
+ for(int i = 0; i < m_items.size(); ++i)
+ {
+ item = m_items.at(i);
+ item->setViewWidth(views().at(0)->size().width());
+ item->setPos(0, m_verticalPosForNewMessage);
+ int height = item->boundingRect().height();
+ m_verticalPosForNewMessage = m_verticalPosForNewMessage + height + m_verticalSpacing;
+ }
+
+ QRectF rect = sceneRect();
+ if(item)
+ {
+ rect.setHeight(m_verticalPosForNewMessage);
+ rect.setWidth(item->getMaxWidth() + item->getBoxStartLength() - 4);
+ setSceneRect(rect);
+ }
+}
+
+void chatGraphicsScene::setBoxStartLength(int length)
+{
+ m_boxStartLength = length;
+}
+
diff --git a/examples/GuiClient/chatGraphicsScene.h b/examples/GuiClient/chatGraphicsScene.h
new file mode 100644
index 00000000..d9f46b94
--- /dev/null
+++ b/examples/GuiClient/chatGraphicsScene.h
@@ -0,0 +1,25 @@
+#ifndef CHATGRAPHICSSCENE_H
+#define CHATGRAPHICSSCENE_H
+
+#include <QGraphicsScene>
+#include <QList>
+
+class messageGraphicsItem;
+
+class chatGraphicsScene : public QGraphicsScene
+{
+public:
+ chatGraphicsScene(QObject* parent = 0);
+ void addMessage(const QString& user, const QString& message);
+ void setWidthResize(int newWidth, int oldWidth);
+ void verticalReposition();
+ void setBoxStartLength(int length);
+
+private:
+ int m_verticalPosForNewMessage;
+ int m_verticalSpacing;
+ int m_boxStartLength;
+ QList <messageGraphicsItem*> m_items;
+};
+
+#endif // CHATGRAPHICSSCENE_H
diff --git a/examples/GuiClient/chatGraphicsView.cpp b/examples/GuiClient/chatGraphicsView.cpp
new file mode 100644
index 00000000..786cc24f
--- /dev/null
+++ b/examples/GuiClient/chatGraphicsView.cpp
@@ -0,0 +1,43 @@
+#include "chatGraphicsView.h"
+#include "chatGraphicsScene.h"
+#include <QResizeEvent>
+
+chatGraphicsView::chatGraphicsView(QWidget* parent) : QGraphicsView(parent)
+{
+ setAlignment(Qt::AlignHCenter|Qt::AlignTop);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setFrameStyle(QFrame::NoFrame);
+}
+
+void chatGraphicsView::setChatGraphicsScene(chatGraphicsScene* scene)
+{
+ m_scene = scene;
+ setScene(m_scene);
+}
+
+void chatGraphicsView::addMessage(const QString& user, const QString& message)
+{
+ if(m_scene)
+ m_scene->addMessage(user, message);
+
+ QRectF rect = scene()->sceneRect();
+ rect.adjust(-4, -4, 4, 4);
+ setSceneRect(rect);
+
+ rect = sceneRect();
+ rect.setTop(sceneRect().height() - 20);
+ rect.setWidth(20);
+ ensureVisible(rect, 50, 50);
+}
+
+void chatGraphicsView::resizeEvent(QResizeEvent *event)
+{
+// pass this to scene
+ m_scene->setWidthResize(event->size().width(), event->oldSize().width());
+ QGraphicsView::resizeEvent(event);
+
+ QRectF rect = scene()->sceneRect();
+ rect.adjust(-4, -4, 4, 4);
+ setSceneRect(rect);
+}
diff --git a/examples/GuiClient/chatGraphicsView.h b/examples/GuiClient/chatGraphicsView.h
new file mode 100644
index 00000000..be7fa653
--- /dev/null
+++ b/examples/GuiClient/chatGraphicsView.h
@@ -0,0 +1,20 @@
+#ifndef CHATGRAPHICSVIEW_H
+#define CHATGRAPHICSVIEW_H
+
+#include <QGraphicsView>
+class chatGraphicsScene;
+
+class chatGraphicsView : public QGraphicsView
+{
+public:
+ chatGraphicsView(QWidget* parent = 0);
+ void setChatGraphicsScene(chatGraphicsScene* scene);
+ void addMessage(const QString& user, const QString& message);
+
+private:
+ void resizeEvent(QResizeEvent *event);
+
+ chatGraphicsScene* m_scene;
+};
+
+#endif // CHATGRAPHICSVIEW_H
diff --git a/examples/GuiClient/customLabel.cpp b/examples/GuiClient/customLabel.cpp
new file mode 100644
index 00000000..9e527cbb
--- /dev/null
+++ b/examples/GuiClient/customLabel.cpp
@@ -0,0 +1,84 @@
+#include "customLabel.h"
+#include <QFontMetrics>
+
+customLabel::customLabel(QWidget* parent):QLabel(parent), m_timer(this),
+ m_option(None)
+{
+ m_timer.setSingleShot(false);
+
+ bool check = connect(&m_timer, SIGNAL(timeout()), SLOT(timeout()));
+ Q_ASSERT(check);
+}
+
+void customLabel::setCustomText(const QString& text, customLabel::Option op,
+ int countDown)
+{
+ m_text = text;
+ m_option = op;
+ m_countDown = countDown;
+ switch(op)
+ {
+ case None:
+ m_timer.stop();
+ m_postfix = "";
+ break;
+ case WithProgressEllipsis:
+// m_timer.start(400);
+ m_postfix = "";
+ break;
+ case CountDown:
+ m_timer.start(1000);
+ m_postfix = "";
+ break;
+ default:
+ m_timer.stop();
+ m_postfix = "";
+ break;
+ }
+
+ if(m_option == CountDown)
+ setText(m_text.arg(m_countDown) + m_postfix);
+ else
+ setText(m_text + m_postfix);
+
+ updateGeometry();
+}
+
+void customLabel::timeout()
+{
+ switch(m_option)
+ {
+ case None:
+ break;
+ case WithProgressEllipsis:
+ if(m_postfix == "")
+ m_postfix = ".";
+ else if(m_postfix == ".")
+ m_postfix = "..";
+ else if(m_postfix == "..")
+ m_postfix = "...";
+ else if(m_postfix == "...")
+ m_postfix = "";
+ break;
+ case CountDown:
+ if(m_countDown == 0)
+ m_timer.stop();
+ --m_countDown;
+ break;
+ default:
+ break;
+ }
+
+ if(m_option == CountDown)
+ setText(m_text.arg(m_countDown) + m_postfix);
+ else
+ setText(m_text + m_postfix);
+ updateGeometry();
+}
+
+//QSize customLabel::sizeHint() const
+//{
+// QFont font;
+// QFontMetrics fm(font);
+// return QSize(fm.width(m_text) + 15, 20);
+//}
diff --git a/examples/GuiClient/customLabel.h b/examples/GuiClient/customLabel.h
new file mode 100644
index 00000000..d163d693
--- /dev/null
+++ b/examples/GuiClient/customLabel.h
@@ -0,0 +1,36 @@
+#ifndef CUSTOMLABEL_H
+#define CUSTOMLABEL_H
+
+#include <QLabel>
+#include <QTimer>
+
+class customLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ enum Option
+ {
+ None = 0,
+ WithProgressEllipsis,
+ CountDown
+ };
+ customLabel(QWidget* parent = 0);
+
+ void setCustomText(const QString& text, customLabel::Option op = None,
+ int countDown = 0);
+
+// QSize sizeHint() const;
+
+private slots:
+ void timeout();
+
+private:
+ QTimer m_timer;
+ customLabel::Option m_option;
+ QString m_text;
+ QString m_postfix;
+ int m_countDown;
+};
+
+#endif // CUSTOMLABEL_H
diff --git a/examples/GuiClient/customListView.cpp b/examples/GuiClient/customListView.cpp
new file mode 100644
index 00000000..9a2bab98
--- /dev/null
+++ b/examples/GuiClient/customListView.cpp
@@ -0,0 +1,69 @@
+#include "customListView.h"
+#include "rosterItem.h"
+#include <QApplication>
+#include <QMenu>
+#include <QKeyEvent>
+
+customListView::customListView(QWidget* parent):QListView(parent), m_chat("Chat", this), m_profile("View Profile", this)
+{
+ bool check = connect(this, SIGNAL(pressed(const QModelIndex&)), this,
+ SLOT(mousePressed(const QModelIndex&)));
+ Q_ASSERT(check);
+ check = connect(this, SIGNAL(doubleClicked(const QModelIndex&)), this,
+ SLOT(doubleClicked(const QModelIndex&)));
+ Q_ASSERT(check);
+ check = connect(this, SIGNAL(clicked(const QModelIndex&)), this,
+ SLOT(clicked(const QModelIndex&)));
+ Q_ASSERT(check);
+ check = connect(&m_chat, SIGNAL(triggered()), this,
+ SLOT(showChatDialog_helper()));
+ Q_ASSERT(check);
+}
+
+bool customListView::event(QEvent* e)
+{
+ return QListView::event(e);
+}
+
+void customListView::mousePressed(const QModelIndex& index)
+{
+ if(QApplication::mouseButtons() == Qt::RightButton)
+ {
+ QString bareJid = index.data().toString();
+ QMenu menu(this);
+ menu.addAction(&m_chat);
+ menu.setDefaultAction(&m_chat);
+ menu.addAction(&m_profile);
+ menu.exec(QCursor::pos());
+ }
+}
+
+void customListView::doubleClicked(const QModelIndex& index)
+{
+ m_chat.trigger();
+}
+
+void customListView::clicked(const QModelIndex& index)
+{
+}
+
+void customListView::showChatDialog_helper()
+{
+ QString bareJid;
+ if(selectedIndexes().size() > 0)
+ {
+ bareJid = selectedIndexes().at(0).data(rosterItem::BareJid).toString();
+
+ if(!bareJid.isEmpty())
+ emit showChatDialog(bareJid);
+ }
+}
+
+void customListView::keyPressEvent(QKeyEvent* event1)
+{
+ if(event1->key() == Qt::Key_Return)
+ {
+ showChatDialog_helper();
+ }
+ QListView::keyPressEvent(event1);
+}
diff --git a/examples/GuiClient/customListView.h b/examples/GuiClient/customListView.h
new file mode 100644
index 00000000..21898980
--- /dev/null
+++ b/examples/GuiClient/customListView.h
@@ -0,0 +1,34 @@
+#ifndef CUSTOMLISTVIEW_H
+#define CUSTOMLISTVIEW_H
+
+#include <QListView>
+#include <QAction>
+
+class customListView : public QListView
+{
+ Q_OBJECT
+
+public:
+ customListView(QWidget* parent = 0);
+ bool event(QEvent* e);
+
+public slots:
+ void mousePressed(const QModelIndex& index);
+ void doubleClicked(const QModelIndex& index);
+ void clicked(const QModelIndex& index);
+
+private slots:
+ void showChatDialog_helper();
+
+protected:
+ void keyPressEvent(QKeyEvent*);
+
+signals:
+ void showChatDialog(const QString& bareJid);
+
+private:
+ QAction m_chat;
+ QAction m_profile;
+};
+
+#endif // CUSTOMLISTVIEW_H
diff --git a/examples/GuiClient/customPushButton.cpp b/examples/GuiClient/customPushButton.cpp
new file mode 100644
index 00000000..f0693dc1
--- /dev/null
+++ b/examples/GuiClient/customPushButton.cpp
@@ -0,0 +1,72 @@
+#include "customPushButton.h"
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOptionFrameV2>
+#include <QFontMetrics>
+
+customPushButton::customPushButton(QWidget* parent)
+ : QPushButton(parent)
+{
+ setMinimumSize(QSize(20, 18));
+}
+
+void customPushButton::paintEvent(QPaintEvent* event)
+{
+ Q_UNUSED(event);
+ QPainter painter(this);
+// painter.setRenderHint(QPainter::Antialiasing);
+
+ QFont font;
+ painter.setFont(font);
+ QStyleOptionButton panel;
+ initStyleOption(&panel);
+ QRect r = style()->subElementRect(QStyle::SE_PushButtonFocusRect, &panel, this);
+ painter.setPen(Qt::gray);
+
+ QRect rectSize(0, 0, sizeHint().width(), sizeHint().height());
+ rectSize.moveCenter(r.center());
+ r = rectSize;
+ r.adjust(0, 0, -1, -1);
+ if(underMouse() && !isDown())
+ {
+ QRectF rr = r;
+ painter.drawRoundedRect(r, 3, 3);
+ QColor col(Qt::white);
+ col.setAlpha(80);
+ rr.adjust(1, 1, -1, -1);
+ painter.fillRect(rr, col);
+ }
+ if(isDown())
+ {
+ QRectF rr = r;
+// rr.adjust(1, 1, -1, -1);
+ painter.drawRoundedRect(rr, 3, 3);
+ QColor col(Qt::white);
+ col.setAlpha(80);
+ rr.adjust(1, 1, -1, -1);
+ painter.fillRect(rr, col);
+ }
+ painter.setPen(Qt::black);
+ painter.setBrush(Qt::black);
+ r.moveLeft(r.left() + 3);
+ font.setBold(true);
+ painter.setFont(font);
+ painter.drawText(r, Qt::AlignVCenter|Qt::TextSingleLine, text());
+
+ QImage image(":/icons/resource/downArrow.png");
+ QRect rectDelta(0, 0, 7, 4);
+ rectDelta.moveRight(r.right() - 4);
+ rectDelta.moveCenter(QPoint(rectDelta.center().x(), r.center().y()));
+ painter.drawImage(rectDelta, image);
+}
+
+QSize customPushButton::sizeHint() const
+{
+ QFont font;
+ font.setBold(true);
+ QFontMetrics fm(font);
+ int width = fm.width(text());
+ if(width <= (160 - 8 - 9))
+ return QSize(width+8+9, 18);
+ else
+ return QSize(160, 18);
+}
diff --git a/examples/GuiClient/customPushButton.h b/examples/GuiClient/customPushButton.h
new file mode 100644
index 00000000..196a2cfa
--- /dev/null
+++ b/examples/GuiClient/customPushButton.h
@@ -0,0 +1,17 @@
+#ifndef CUSTOMPUSHBUTTON_H
+#define CUSTOMPUSHBUTTON_H
+
+#include <QPushButton>
+#include <QPainter>
+
+class customPushButton : public QPushButton
+{
+ Q_OBJECT
+
+public:
+ customPushButton(QWidget* parent = 0);
+ void paintEvent(QPaintEvent* event);
+ QSize sizeHint() const;
+};
+
+#endif // CUSTOMPUSHBUTTON_H
diff --git a/examples/GuiClient/customToolButton.cpp b/examples/GuiClient/customToolButton.cpp
new file mode 100644
index 00000000..ba92b923
--- /dev/null
+++ b/examples/GuiClient/customToolButton.cpp
@@ -0,0 +1,51 @@
+#include "customToolButton.h"
+#include <QPainter>
+#include <QStyle>
+#include <QStyleOptionToolButton>
+
+customToolButton::customToolButton(QWidget* parent) : QToolButton(parent)
+{
+ setMinimumSize(QSize(20, 18));
+}
+
+void customToolButton::paintEvent(QPaintEvent* event)
+{
+ Q_UNUSED(event);
+ QPainter painter(this);
+ QStyleOptionToolButton panel;
+ initStyleOption(&panel);
+ style()->drawPrimitive(QStyle::PE_PanelButtonTool, &panel, &painter, this);
+ QRect r = rect();
+ QFont font;
+ painter.setFont(font);
+ painter.setPen(Qt::gray);
+
+ QRect rectSize(0, 0, sizeHint().width(), sizeHint().height());
+ rectSize.moveCenter(r.center());
+ r = rectSize;
+ r.adjust(0, 0, -1, -1);
+ painter.setPen(Qt::black);
+ painter.setBrush(Qt::black);
+ r.moveLeft(r.left() + 3);
+ font.setBold(true);
+ painter.setFont(font);
+ painter.drawText(r, Qt::AlignVCenter|Qt::TextSingleLine, text());
+
+ QImage image(":/icons/resource/downArrow.png");
+ QRect rectDelta(0, 0, 7, 4);
+ rectDelta.moveRight(r.right() - 4);
+ rectDelta.moveCenter(QPoint(rectDelta.center().x(), r.center().y()));
+ painter.drawImage(rectDelta, image);
+}
+
+QSize customToolButton::sizeHint() const
+{
+ QFont font;
+ font.setBold(true);
+ QFontMetrics fm(font);
+ int width = fm.width(text());
+ if(width <= (160 - 8 - 9))
+ return QSize(width+8+9, 18);
+ else
+ return QSize(160, 18);
+}
diff --git a/examples/GuiClient/customToolButton.h b/examples/GuiClient/customToolButton.h
new file mode 100644
index 00000000..c9e7048b
--- /dev/null
+++ b/examples/GuiClient/customToolButton.h
@@ -0,0 +1,14 @@
+#ifndef CUSTOMTOOLBUTTON_H
+#define CUSTOMTOOLBUTTON_H
+
+#include <QToolButton>
+
+class customToolButton : public QToolButton
+{
+public:
+ customToolButton(QWidget* parent = 0);
+ void paintEvent(QPaintEvent* event);
+ QSize sizeHint() const;
+};
+
+#endif // CUSTOMTOOLBUTTON_H
diff --git a/examples/GuiClient/main.cpp b/examples/GuiClient/main.cpp
new file mode 100644
index 00000000..23730e9c
--- /dev/null
+++ b/examples/GuiClient/main.cpp
@@ -0,0 +1,20 @@
+#include <QtGui/QApplication>
+#include <QDir>
+#include "chatDialog.h"
+#include "chatGraphicsView.h"
+#include "chatGraphicsScene.h"
+#include "mainDialog.h"
+#include "statusTextWidget.h"
+#include "utils.h"
+
+int main(int argc, char *argv[])
+{
+ QDir dir;
+ if(!dir.exists(getSettingsDir()))
+ dir.mkpath(getSettingsDir());
+
+ QApplication a(argc, argv);
+ mainDialog cw;
+ cw.show();
+ return a.exec();
+}
diff --git a/examples/GuiClient/mainDialog.cpp b/examples/GuiClient/mainDialog.cpp
new file mode 100644
index 00000000..be062a5f
--- /dev/null
+++ b/examples/GuiClient/mainDialog.cpp
@@ -0,0 +1,409 @@
+#include "mainDialog.h"
+#include "ui_mainDialog.h"
+#include "QXmppRoster.h"
+#include "QXmppPresence.h"
+#include "QXmppMessage.h"
+#include "QXmppUtils.h"
+#include "utils.h"
+#include "QXmppReconnectionManager.h"
+#include "QXmppVCardManager.h"
+#include "QXmppLogger.h"
+#include "QXmppVCard.h"
+
+#include <QMovie>
+
+mainDialog::mainDialog(QWidget *parent): QDialog(parent, Qt::Window),
+ ui(new Ui::mainDialogClass), m_rosterItemModel(this),
+ m_rosterItemSortFilterModel(this), m_vCardManager(&m_xmppClient)
+{
+ ui->setupUi(this);
+ ui->pushButton_cancel->setDisabled(true);
+ ui->label_throbber->setMovie(new QMovie(":/icons/resource/ajax-loader.gif"));
+ ui->label_throbber->movie()->start();
+ showSignInPage();
+
+ bool check = connect(&m_xmppClient.rosterManager(),
+ SIGNAL(rosterReceived()),
+ this, SLOT(rosterReceived()));
+
+ check = connect(&m_xmppClient.rosterManager(),
+ SIGNAL(rosterChanged(const QString&)),
+ this, SLOT(rosterChanged(const QString&)));
+ Q_ASSERT(check);
+
+ QXmppLogger::getLogger()->setLoggingType(QXmppLogger::FileLogging);
+
+
+ check = connect(&m_xmppClient.rosterManager(),
+ SIGNAL(presenceChanged(const QString&, const QString&)),
+ this, SLOT(presenceChanged(const QString&, const QString&)));
+ Q_ASSERT(check);
+
+ check = connect(ui->pushButton_view, SIGNAL(clicked()), this, SLOT(sort()));
+ Q_ASSERT(check);
+
+ check = connect(ui->lineEdit_filter, SIGNAL(textChanged(const QString&)),
+ this, SLOT(filterChanged(const QString&)));
+ Q_ASSERT(check);
+
+ check = connect(ui->listView, SIGNAL(showChatDialog(const QString&)),
+ this, SLOT(showChatDialog(const QString&)));
+ Q_ASSERT(check);
+
+ check = connect(&m_xmppClient, SIGNAL(messageReceived(const QXmppMessage&)),
+ SLOT(messageReceived(const QXmppMessage&)));
+ Q_ASSERT(check);
+
+ check = connect(ui->pushButton_signIn, SIGNAL(clicked(bool)), SLOT(signIn()));
+ Q_ASSERT(check);
+
+ check = connect(ui->pushButton_cancel, SIGNAL(clicked(bool)),
+ SLOT(cancelSignIn()));
+ Q_ASSERT(check);
+
+ m_rosterItemSortFilterModel.setSourceModel(&m_rosterItemModel);
+ ui->listView->setModel(&m_rosterItemSortFilterModel);
+ sort();
+
+ ItemDelegate *delegate = new ItemDelegate();
+ ui->listView->setItemDelegate(delegate);
+ ui->listView->setFocus();
+ ui->verticalLayout_3->insertWidget(0, &m_statusWidget);
+
+ check = connect(&m_statusWidget, SIGNAL(statusTextChanged(const QString&)),
+ SLOT(statusTextChanged(const QString&)));
+ Q_ASSERT(check);
+ check = connect(&m_statusWidget, SIGNAL(presenceTypeChanged(QXmppPresence::Type)),
+ SLOT(presenceTypeChanged(QXmppPresence::Type)));
+ Q_ASSERT(check);
+ check = connect(&m_statusWidget,
+ SIGNAL(presenceStatusTypeChanged(QXmppPresence::Status::Type)),
+ SLOT(presenceStatusTypeChanged(QXmppPresence::Status::Type)));
+ Q_ASSERT(check);
+ check = connect(&m_statusWidget,
+ SIGNAL(avatarChanged(const QImage&)),
+ SLOT(avatarChanged(const QImage&)));
+ Q_ASSERT(check);
+
+ check = connect(&m_xmppClient, SIGNAL(connected()), SLOT(updateStatusWidget()));
+ Q_ASSERT(check);
+
+ check = connect(&m_xmppClient, SIGNAL(connected()), SLOT(showRosterPage()));
+ Q_ASSERT(check);
+
+ check = connect(m_xmppClient.reconnectionManager(),
+ SIGNAL(reconnectingIn(int)),
+ SLOT(showSignInPageForAutoReconnection(int)));
+ Q_ASSERT(check);
+
+ check = connect(m_xmppClient.reconnectionManager(),
+ SIGNAL(reconnectingNow()),
+ SLOT(showSignInPageForAutoReconnectionNow()));
+ Q_ASSERT(check);
+
+ check = connect(&m_xmppClient.vCardManager(),
+ SIGNAL(vCardReceived(const QXmppVCard&)), &m_vCardManager,
+ SLOT(vCardReceived(const QXmppVCard&)));
+ Q_ASSERT(check);
+
+ check = connect(&m_vCardManager,
+ SIGNAL(vCardReadyToUse(const QString&)),
+ SLOT(updateVCard(const QString&)));
+ Q_ASSERT(check);
+}
+
+void mainDialog::rosterChanged(const QString& bareJid)
+{
+ m_rosterItemModel.updateRosterEntry(bareJid, m_xmppClient.rosterManager().
+ getRosterEntry(bareJid));
+
+ bool check = m_vCardManager.isVCardAvailable(bareJid);
+ if(check)
+ {
+ m_rosterItemModel.updateAvatar(bareJid,
+ m_vCardManager.getVCard(bareJid).image);
+ }
+ else
+ {
+ m_vCardManager.requestVCard(bareJid);
+ }
+}
+
+void mainDialog::rosterReceived()
+{
+ QStringList list = m_xmppClient.rosterManager().getRosterBareJids();
+ QString bareJid;
+ foreach(bareJid, list)
+ rosterChanged(bareJid);
+}
+
+void mainDialog::presenceChanged(const QString& bareJid, const QString& resource)
+{
+ if(bareJid == m_xmppClient.configuration().getJidBare())
+ return;
+
+ if(!m_rosterItemModel.getRosterItemFromBareJid(bareJid))
+ return;
+
+ QMap<QString, QXmppPresence> presences = m_xmppClient.rosterManager().
+ getAllPresencesForBareJid(bareJid);
+ m_rosterItemModel.updatePresence(bareJid, presences);
+
+// QXmppPresence::Type presenceType = presences.begin().value().getType();
+
+// if(!m_vCardManager.isVCardAvailable(bareJid) &&
+// presenceType == QXmppPresence::Available)
+// {
+// m_rosterItemModel.updateAvatar(bareJid,
+// m_vCardManager.getVCard(bareJid).image);
+// }
+}
+
+void mainDialog::sort()
+{
+ m_rosterItemSortFilterModel.sort(0);
+}
+
+void mainDialog::filterChanged(const QString& filter)
+{
+ m_rosterItemSortFilterModel.setFilterRegExp(filter);
+ ui->listView->selectionModel()->select(ui->listView->model()->index(0, 0),
+ QItemSelectionModel::ClearAndSelect);
+}
+
+void mainDialog::keyPressEvent(QKeyEvent* event1)
+{
+ if(ui->stackedWidget->currentIndex() == 1) // sign in page
+ {
+ QDialog::keyPressEvent(event1);
+ return;
+ }
+
+ if(event1->matches(QKeySequence::Find) ||(
+ event1->key() <= Qt::Key_9 && event1->key() >= Qt::Key_1) ||
+ (event1->key() <= Qt::Key_Z && event1->key() >= Qt::Key_At) ||
+ event1->key() == Qt::Key_Backspace)
+ {
+ ui->lineEdit_filter->setFocus();
+ ui->lineEdit_filter->event(event1);
+ }
+ else if(event1->key() == Qt::Key_Escape)
+ {
+ ui->lineEdit_filter->clear();
+ ui->listView->setFocus();
+ }
+ else if(event1->key() == Qt::Key_Up ||
+ event1->key() == Qt::Key_Down ||
+ event1->key() == Qt::Key_PageUp ||
+ event1->key() == Qt::Key_PageDown)
+ {
+ ui->listView->setFocus();
+ ui->listView->event(event1);
+ }
+ else if(event1->key() == Qt::Key_Return && ui->listView->hasFocus())
+ {
+ ui->listView->event(event1);
+ }
+}
+
+chatDialog* mainDialog::getChatDialog(const QString& bareJid)
+{
+ if(!m_chatDlgsList.contains(bareJid))
+ {
+ m_chatDlgsList[bareJid] = new chatDialog();
+ m_chatDlgsList[bareJid]->setBareJid(bareJid);
+
+ if(!m_rosterItemModel.getRosterItemFromBareJid(bareJid))
+ return 0;
+
+ if(!m_rosterItemModel.getRosterItemFromBareJid(bareJid)->
+ getName().isEmpty())
+ m_chatDlgsList[bareJid]->setDisplayName(m_rosterItemModel.
+ getRosterItemFromBareJid(bareJid)->getName());
+ else
+ m_chatDlgsList[bareJid]->setDisplayName(bareJid.split(QChar('@')).at(0));
+
+ m_chatDlgsList[bareJid]->setQXmppClient(&m_xmppClient);
+ }
+
+ return m_chatDlgsList[bareJid];
+}
+
+void mainDialog::showChatDialog(const QString& bareJid)
+{
+ getChatDialog(bareJid)->show();
+}
+
+void mainDialog::messageReceived(const QXmppMessage& msg)
+{
+ QString from = msg.getFrom();
+ getChatDialog(jidToBareJid(from))->show();
+ getChatDialog(jidToBareJid(from))->messageReceived(msg.getBody());
+}
+
+void mainDialog::statusTextChanged(const QString& status)
+{
+ QXmppPresence presence = m_xmppClient.clientPresence();
+ presence.status().setStatusText(status);
+ m_xmppClient.setClientPresence(presence);
+}
+
+void mainDialog::presenceTypeChanged(QXmppPresence::Type presenceType)
+{
+ if(presenceType == QXmppPresence::Unavailable)
+ {
+ m_xmppClient.disconnect();
+ showSignInPageAfterUserDisconnection();
+ }
+ else
+ {
+ m_xmppClient.setClientPresence(presenceType);
+ }
+ m_statusWidget.setStatusText(
+ presenceToStatusText(m_xmppClient.clientPresence()));
+}
+
+void mainDialog::presenceStatusTypeChanged(QXmppPresence::Status::Type statusType)
+{
+ QXmppPresence presence = m_xmppClient.clientPresence();
+ if(statusType == QXmppPresence::Status::Offline)
+ presence.setType(QXmppPresence::Unavailable);
+ else
+ presence.setType(QXmppPresence::Available);
+ presence.status().setType(statusType);
+ m_xmppClient.setClientPresence(presence);
+}
+
+void mainDialog::avatarChanged(const QImage& image)
+{
+ QXmppVCard vcard;
+ vcard.setType(QXmppIq::Set);
+ vcard.setPhoto(image);
+ m_xmppClient.sendPacket(vcard);
+ m_statusWidget.setAvatar(image);
+}
+
+void mainDialog::updateStatusWidget()
+{
+ // fetch selfVCard
+ m_xmppClient.vCardManager().requestVCard();
+
+ m_statusWidget.setDisplayName(m_xmppClient.configuration().getJidBare());
+ m_statusWidget.setStatusText(presenceToStatusText(m_xmppClient.clientPresence()));
+ m_statusWidget.setPresenceAndStatusType(m_xmppClient.clientPresence().getType(),
+ m_xmppClient.clientPresence().getStatus().getType());
+}
+
+void mainDialog::signIn()
+{
+ ui->label_throbber->show();
+ ui->pushButton_signIn->setDisabled(true);
+ ui->pushButton_cancel->setDisabled(false);
+ ui->lineEdit_userName->setDisabled(true);
+ ui->lineEdit_password->setDisabled(true);
+ ui->checkBox->setDisabled(true);
+ showLoginStatusWithProgress("Connecting");
+
+ QString bareJid = ui->lineEdit_userName->text();
+ QString passwd = ui->lineEdit_password->text();
+
+ m_xmppClient.configuration().setJid(bareJid);
+ m_xmppClient.configuration().setPasswd(passwd);
+
+ m_vCardManager.loadAllFromCache();
+ m_rosterItemModel.clear();
+ startConnection();
+}
+
+void mainDialog::cancelSignIn()
+{
+ ui->label_throbber->hide();
+ m_xmppClient.reconnectionManager()->cancelReconnection();
+ m_xmppClient.disconnect();
+ showSignInPage();
+ showLoginStatus("Sign in cancelled");
+}
+
+void mainDialog::showSignInPage()
+{
+ ui->label_throbber->hide();
+ ui->pushButton_signIn->setDisabled(false);
+ ui->pushButton_cancel->setDisabled(true);
+ ui->lineEdit_userName->setDisabled(false);
+ ui->lineEdit_password->setDisabled(false);
+ ui->checkBox->setDisabled(false);
+ ui->stackedWidget->setCurrentIndex(1);
+}
+
+void mainDialog::showSignInPageAfterUserDisconnection()
+{
+ ui->label_throbber->hide();
+ showLoginStatus("Disconnected");
+ showSignInPage();
+}
+
+void mainDialog::showSignInPageForAutoReconnection(int i)
+{
+ ui->label_throbber->hide();
+ ui->pushButton_signIn->setDisabled(true);
+ ui->pushButton_cancel->setDisabled(false);
+ ui->lineEdit_userName->setDisabled(true);
+ ui->lineEdit_password->setDisabled(true);
+ ui->checkBox->setDisabled(true);
+ showLoginStatusWithCounter(QString("Reconnecting in %1 sec..."), i);
+ ui->stackedWidget->setCurrentIndex(1);
+}
+
+void mainDialog::showSignInPageForAutoReconnectionNow()
+{
+ ui->label_throbber->show();
+ ui->pushButton_signIn->setDisabled(true);
+ ui->pushButton_cancel->setDisabled(false);
+ ui->lineEdit_userName->setDisabled(true);
+ ui->lineEdit_password->setDisabled(true);
+ ui->checkBox->setDisabled(true);
+ showLoginStatusWithProgress(QString("Connecting"));
+ ui->stackedWidget->setCurrentIndex(1);
+}
+
+void mainDialog::showRosterPage()
+{
+ ui->stackedWidget->setCurrentIndex(0);
+}
+
+void mainDialog::startConnection()
+{
+// m_xmppClient.setClientPresence(QXmppPresence());
+ m_xmppClient.connectToServer(m_xmppClient.configuration());
+}
+
+void mainDialog::showLoginStatus(const QString& msg)
+{
+ ui->label_status->setCustomText(msg, customLabel::None);
+}
+
+void mainDialog::showLoginStatusWithProgress(const QString& msg)
+{
+ ui->label_status->setCustomText(msg, customLabel::WithProgressEllipsis);
+}
+
+void mainDialog::showLoginStatusWithCounter(const QString& msg, int time)
+{
+ ui->label_status->setCustomText(msg, customLabel::CountDown, time);
+}
+
+void mainDialog::updateVCard(const QString& bareJid)
+{
+ if(bareJid != m_xmppClient.configuration().getJidBare())
+ m_rosterItemModel.updateAvatar(bareJid,
+ m_vCardManager.getVCard(bareJid).image);
+ else
+ {
+ if(m_vCardManager.getSelfFullName().isEmpty())
+ m_statusWidget.setDisplayName(m_xmppClient.configuration().getJidBare());
+ else
+ m_statusWidget.setDisplayName(m_vCardManager.getSelfFullName());
+
+ m_statusWidget.setAvatar(m_vCardManager.getVCard(bareJid).image);
+ }
+}
diff --git a/examples/GuiClient/mainDialog.h b/examples/GuiClient/mainDialog.h
new file mode 100644
index 00000000..58adf789
--- /dev/null
+++ b/examples/GuiClient/mainDialog.h
@@ -0,0 +1,69 @@
+#ifndef MAINDIALOG_H
+#define MAINDIALOG_H
+
+#include <QDialog>
+#include "QXmppClient.h"
+#include "rosterItemModel.h"
+#include "rosterItemSortFilterProxyModel.h"
+#include <QKeyEvent>
+#include <QMap>
+#include "statusWidget.h"
+#include "chatDialog.h"
+#include "vCardManager.h"
+
+namespace Ui
+{
+ class mainDialogClass;
+}
+
+class mainDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ mainDialog(QWidget *parent = 0);
+
+protected:
+ void keyPressEvent(QKeyEvent*);
+
+private slots:
+ void rosterChanged(const QString& bareJid);
+ void rosterReceived();
+ void presenceChanged(const QString&, const QString&);
+ void sort();
+ void filterChanged(const QString& filter);
+ void showChatDialog(const QString& bareJid);
+ void messageReceived(const QXmppMessage& msg);
+ void statusTextChanged(const QString&);
+ void presenceTypeChanged(QXmppPresence::Type);
+ void presenceStatusTypeChanged(QXmppPresence::Status::Type);
+ void signIn();
+ void cancelSignIn();
+ void showSignInPage();
+ void showSignInPageAfterUserDisconnection();
+ void showSignInPageForAutoReconnection(int);
+ void showSignInPageForAutoReconnectionNow();
+ void showRosterPage();
+ void startConnection();
+ void updateStatusWidget();
+ void showLoginStatusWithProgress(const QString& msg);
+ void showLoginStatus(const QString& msg);
+ void showLoginStatusWithCounter(const QString& msg, int time);
+ void updateVCard(const QString& bareJid);
+ void avatarChanged(const QImage&);
+
+private:
+ chatDialog* getChatDialog(const QString& bareJid);
+
+ Ui::mainDialogClass* ui;
+ QXmppClient m_xmppClient;
+ rosterItemModel m_rosterItemModel;
+ rosterItemSortFilterProxyModel m_rosterItemSortFilterModel;
+ statusWidget m_statusWidget;
+ vCardManager m_vCardManager;
+
+ // map of bare jids and respective chatdlg
+ QMap<QString, chatDialog*> m_chatDlgsList;
+};
+
+#endif // MAINDIALOG_H
diff --git a/examples/GuiClient/mainDialog.ui b/examples/GuiClient/mainDialog.ui
new file mode 100644
index 00000000..fbf203b8
--- /dev/null
+++ b/examples/GuiClient/mainDialog.ui
@@ -0,0 +1,352 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>mainDialogClass</class>
+ <widget class="QDialog" name="mainDialogClass">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>263</width>
+ <height>487</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>QXmpp</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="margin">
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QStackedWidget" name="stackedWidget">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="page">
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>4</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="searchLineEdit" name="lineEdit_filter">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="customListView" name="listView">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="verticalScrollMode">
+ <enum>QAbstractItemView::ScrollPerPixel</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QPushButton" name="pushButton_2">
+ <property name="text">
+ <string>+</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton_view">
+ <property name="text">
+ <string>View</string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton_4">
+ <property name="text">
+ <string>Settings</string>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="page_2">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="leftMargin">
+ <number>20</number>
+ </property>
+ <property name="rightMargin">
+ <number>20</number>
+ </property>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Username:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEdit_userName">
+ <property name="text">
+ <string>qxmpp.test1@gmail.com</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineEdit_password">
+ <property name="text">
+ <string>qxmpp123</string>
+ </property>
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkBox">
+ <property name="text">
+ <string>Remember password</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton_signIn">
+ <property name="text">
+ <string>Sign in</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pushButton_cancel">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="customLabel" name="label_status">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_throbber">
+ <property name="text">
+ <string>movie</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>35</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>70</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>customListView</class>
+ <extends>QListView</extends>
+ <header>customListView.h</header>
+ </customwidget>
+ <customwidget>
+ <class>searchLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>searchLineEdit.h</header>
+ </customwidget>
+ <customwidget>
+ <class>customLabel</class>
+ <extends>QLabel</extends>
+ <header>customLabel.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/GuiClient/messageGraphicsItem.cpp b/examples/GuiClient/messageGraphicsItem.cpp
new file mode 100644
index 00000000..79b912b2
--- /dev/null
+++ b/examples/GuiClient/messageGraphicsItem.cpp
@@ -0,0 +1,287 @@
+#include "messageGraphicsItem.h"
+#include <QPainter>
+#include <QTextDocument>
+#include <QFontMetrics>
+#include <QGraphicsScene>
+#include <QGraphicsView>
+#include <QTime>
+
+QLinearGradient getGradient(const QColor &col, const QRectF &rect)
+{
+ QLinearGradient g(rect.topLeft(), rect.bottomLeft());
+
+ qreal hue = col.hueF();
+ qreal value = col.valueF();
+ qreal saturation = col.saturationF();
+
+ QColor c = col;
+ c.setHsvF(hue, 0.42 * saturation, 0.98 * value);
+ g.setColorAt(0, c);
+ c.setHsvF(hue, 0.58 * saturation, 0.95 * value);
+ g.setColorAt(0.25, c);
+ c.setHsvF(hue, 0.70 * saturation, 0.93 * value);
+ g.setColorAt(0.5, c);
+
+ c.setHsvF(hue, 0.95 * saturation, 0.9 * value);
+ g.setColorAt(0.501, c);
+ c.setHsvF(hue * 0.95, 0.95 * saturation, 0.95 * value);
+ g.setColorAt(0.75, c);
+ c.setHsvF(hue * 0.90, 0.95 * saturation, 1 * value);
+ g.setColorAt(1.0, c);
+
+ return g;
+}
+
+QLinearGradient darken(const QLinearGradient &gradient)
+{
+ QGradientStops stops = gradient.stops();
+ for (int i = 0; i < stops.size(); ++i) {
+ QColor color = stops.at(i).second;
+ stops[i].second = color.darker(160);
+ }
+
+ QLinearGradient g = gradient;
+ g.setStops(stops);
+ return g;
+}
+
+void drawPath(QPainter *p, const QPainterPath &path,
+ const QColor &col, const QString &name, int textWidth,
+ bool dark = false)
+{
+ const QRectF pathRect = path.boundingRect();
+
+ const QLinearGradient baseGradient = getGradient(col, pathRect);
+ const QLinearGradient darkGradient = darken(baseGradient);
+
+ p->save();
+
+ // p->setOpacity(0.25);
+
+ //glow
+// if (dark)
+// p->strokePath(path, QPen(darkGradient, 6));
+// else
+// p->strokePath(path, QPen(baseGradient, 6));
+
+ p->setOpacity(1.0);
+
+ //fill
+ if (dark)
+ p->fillPath(path, darkGradient);
+ else
+ p->fillPath(path, baseGradient);
+
+ QLinearGradient g(pathRect.topLeft(), pathRect.topRight());
+ g.setCoordinateMode(QGradient::ObjectBoundingMode);
+
+ p->setOpacity(0.2);
+ p->fillPath(path, g);
+
+ p->setOpacity(0.5);
+
+ // highlight
+// if (dark)
+// p->strokePath(path, QPen(col.lighter(160).darker(160), 2));
+// else
+// p->strokePath(path, QPen(col.lighter(160), 2));
+
+ p->setOpacity(1.0);
+
+ p->restore();
+}
+
+messageGraphicsItem::messageGraphicsItem(QGraphicsItem * parent):QGraphicsPathItem(parent),
+ m_spikeWidth(9),
+ m_spikeHeight(6),
+ m_cornerRadius(10),
+ m_textSpacing(4), m_color(Qt::yellow)
+{
+ setPath(createPath());
+// setFlags(QGraphicsItem::ItemIsMovable);
+
+ QFont font;
+ QFontMetrics fm(font);
+ m_timeStampWidth = fm.width(getTime()) + 4;
+}
+
+void messageGraphicsItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+ painter->setRenderHint(QPainter::Antialiasing);
+ drawPath(painter, path(), m_color, getText(), getTextWidth());
+
+ int spike_x = m_spikeWidth;
+ int spike_y = m_spikeHeight;
+ int corner = m_cornerRadius;
+ int length = m_width - spike_x;
+ int offset = spike_x;
+ QFont font;
+ font.setBold(true);
+ QTextDocument textDoc(getText());
+ QTextOption textOp;
+ textOp.setWrapMode(QTextOption::WrapAnywhere);
+ textOp.setAlignment(Qt::AlignLeft);
+ textDoc.setDefaultTextOption(textOp);
+ textDoc.setTextWidth(getTextWidth());
+ textDoc.setDefaultFont(font);
+
+ painter->setPen(Qt::white);
+ painter->setFont(font);
+ int height = (int) textDoc.size().height();
+ painter->drawText(m_spikeWidth + m_cornerRadius, 4, getTextWidth(), height,
+ Qt::AlignLeft|Qt::TextWrapAnywhere, getText());
+
+// painter->setPen(Qt::gray);
+ painter->setPen(Qt::black);
+
+// font.setBold(false);
+ painter->setFont(font);
+ painter->drawText(-m_boxStartLength, 0, m_boxStartLength, m_height,
+ Qt::AlignRight|Qt::AlignBottom, getName());
+
+ font.setBold(false);
+ painter->setPen(Qt::gray);
+ painter->setFont(font);
+
+ int timeWidth;
+ if(m_timeStampWidth > m_boxStartLength)
+ timeWidth = m_timeStampWidth;
+ else
+ timeWidth = m_boxStartLength;
+
+ painter->drawText(getMaxWidth() + 6, 0, timeWidth - 6, m_height,
+ Qt::AlignBottom|Qt::AlignLeft, getTime());
+}
+
+void messageGraphicsItem::setText(const QString& text)
+{
+ m_text = text;
+ calculateWidth();
+ setPath(createPath());
+}
+
+void messageGraphicsItem::setMaxWidth(int width)
+{
+ m_maxWidth = width;
+ setPath(createPath());
+}
+
+void messageGraphicsItem::setViewWidth(int width)
+{
+ //25 for scrollbar
+ setMaxWidth(width - getBoxStartLength() - 25);
+}
+
+int messageGraphicsItem::getMaxWidth() const
+{
+ return m_maxWidth;
+}
+
+void messageGraphicsItem::setAlignment(Alignment align)
+{
+ m_alignment = align;
+ setPath(createPath());
+}
+
+QPainterPath messageGraphicsItem::createPath()
+{
+ calculateWidth();
+ int spike_x = m_spikeWidth;
+ int spike_y = m_spikeHeight;
+ int corner = m_cornerRadius;
+ int length = m_width - spike_x;
+ int offset = spike_x;
+
+ QPainterPath messageBoxPath;
+ messageBoxPath.moveTo(0 + offset, m_height - corner);
+ QRectF rect(offset - 2*spike_x, m_height - corner - spike_y, 2*spike_x, 2*spike_y);
+ messageBoxPath.arcMoveTo(rect, -90.0);
+ messageBoxPath.arcTo(rect, 270, 90.0);
+ messageBoxPath.lineTo(0 + offset, corner);
+ messageBoxPath.arcTo(0 + offset, 0, 2*corner, 2*corner, 180, -90.0);
+ messageBoxPath.lineTo(length - corner, 0);
+ messageBoxPath.arcTo(length + offset - corner*2, 0, 2*corner, 2*corner, 90, -90.0);
+ messageBoxPath.lineTo(length + offset, m_height - corner);
+ messageBoxPath.arcTo(length + offset - corner*2, m_height - 2*corner, 2*corner, 2*corner, 0, -90.0);
+ messageBoxPath.lineTo(offset + corner, m_height);
+ messageBoxPath.arcTo(offset, m_height - 2*corner, 2*corner, 2*corner, 270, -45.0);
+ messageBoxPath.closeSubpath();
+
+ return messageBoxPath;
+}
+
+QString messageGraphicsItem::getText() const
+{
+ return m_text;
+}
+
+int messageGraphicsItem::getTextWidth() const
+{
+ return getMaxWidth() - m_spikeWidth - m_cornerRadius*2;
+}
+
+void messageGraphicsItem::calculateWidth()
+{
+ QFont font;
+ font.setBold(true);
+ QTextDocument textDoc(m_text);
+ textDoc.setDefaultFont(font);
+ int idealWidth = (int)textDoc.size().width();
+ textDoc.setTextWidth(getTextWidth());
+ m_height = (int)textDoc.size().height();
+
+ if(idealWidth < getTextWidth())
+ {
+ m_width = idealWidth + m_spikeWidth + m_cornerRadius;
+ }
+ else
+ m_width = getMaxWidth();
+}
+
+void messageGraphicsItem::setName(const QString& name)
+{
+ m_name = name;
+ if(name != "Me")
+ m_color = QColor(0, 210, 250);
+ else
+ m_color = QColor(250, 188, 239);
+}
+
+QString messageGraphicsItem::getName() const
+{
+ return m_name;
+}
+
+QString messageGraphicsItem::getTime() const
+{
+ return QTime::currentTime().toString("hh:mm");
+}
+
+void messageGraphicsItem::setBoxStartLength(int length)
+{
+ m_boxStartLength = length;
+}
+
+int messageGraphicsItem::getBoxStartLength() const
+{
+ return m_boxStartLength;
+}
+
+void messageGraphicsItem::setColor(const QColor& color)
+{
+ m_color = color;
+}
+
+QRectF messageGraphicsItem::boundingRect() const
+{
+ QRectF rect = QGraphicsPathItem::boundingRect();
+ rect.setLeft(-getBoxStartLength());
+
+ int timeWidth;
+ if(m_timeStampWidth > m_boxStartLength)
+ timeWidth = m_timeStampWidth;
+ else
+ timeWidth = m_boxStartLength;
+ rect.setRight(getMaxWidth() + timeWidth);
+ return rect;
+}
diff --git a/examples/GuiClient/messageGraphicsItem.h b/examples/GuiClient/messageGraphicsItem.h
new file mode 100644
index 00000000..7aafa2a7
--- /dev/null
+++ b/examples/GuiClient/messageGraphicsItem.h
@@ -0,0 +1,63 @@
+#ifndef MESSAGEGRAPHICSITEM_H
+#define MESSAGEGRAPHICSITEM_H
+
+#include <QGraphicsPathItem>
+
+class messageGraphicsItem : public QGraphicsPathItem
+{
+public:
+ enum Alignment
+ {
+ LEFT = 0,
+ RIGHT
+ };
+
+ messageGraphicsItem(QGraphicsItem * parent = 0);
+ void setText(const QString& text);
+ void setName(const QString& name);
+ QString getName() const;
+ QString getText() const;
+
+ void setMaxWidth(int width);
+ int getMaxWidth() const;
+ void setViewWidth(int viewWidth);
+
+ void setAlignment(Alignment align);
+
+ void setBoxStartLength(int length);
+ int getBoxStartLength() const;
+
+ void setColor(const QColor&);
+
+ virtual QRectF boundingRect() const;
+
+private:
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+ QPainterPath createPath();
+ int getTextWidth() const;
+ void calculateWidth();
+ QString getTime() const;
+
+ // max width of bubble including the spike
+ int m_maxWidth;
+
+ // actual width
+ int m_width;
+
+ // height of bubble
+ int m_height;
+ int m_spikeWidth;
+ int m_spikeHeight;
+ int m_cornerRadius;
+ int m_textSpacing;
+ int m_boxStartLength;
+ int m_timeStampWidth;
+ QColor m_color;
+
+ QString m_text;
+ QString m_name;
+ int m_length;
+ Alignment m_alignment;
+};
+
+#endif // MESSAGEGRAPHICSITEM_H
diff --git a/examples/GuiClient/resource/Thumbs.db b/examples/GuiClient/resource/Thumbs.db
new file mode 100644
index 00000000..ddb376bc
--- /dev/null
+++ b/examples/GuiClient/resource/Thumbs.db
Binary files differ
diff --git a/examples/GuiClient/resource/ajax-loader.gif b/examples/GuiClient/resource/ajax-loader.gif
new file mode 100644
index 00000000..3288d103
--- /dev/null
+++ b/examples/GuiClient/resource/ajax-loader.gif
Binary files differ
diff --git a/examples/GuiClient/resource/avatar.png b/examples/GuiClient/resource/avatar.png
new file mode 100644
index 00000000..1a8111c7
--- /dev/null
+++ b/examples/GuiClient/resource/avatar.png
Binary files differ
diff --git a/examples/GuiClient/resource/downArrow.png b/examples/GuiClient/resource/downArrow.png
new file mode 100644
index 00000000..365684bd
--- /dev/null
+++ b/examples/GuiClient/resource/downArrow.png
Binary files differ
diff --git a/examples/GuiClient/resource/gray.png b/examples/GuiClient/resource/gray.png
new file mode 100644
index 00000000..152d8e18
--- /dev/null
+++ b/examples/GuiClient/resource/gray.png
Binary files differ
diff --git a/examples/GuiClient/resource/green.png b/examples/GuiClient/resource/green.png
new file mode 100644
index 00000000..aed27a33
--- /dev/null
+++ b/examples/GuiClient/resource/green.png
Binary files differ
diff --git a/examples/GuiClient/resource/icon.xcf b/examples/GuiClient/resource/icon.xcf
new file mode 100644
index 00000000..8a56c227
--- /dev/null
+++ b/examples/GuiClient/resource/icon.xcf
Binary files differ
diff --git a/examples/GuiClient/resource/orange.png b/examples/GuiClient/resource/orange.png
new file mode 100644
index 00000000..9f6611c7
--- /dev/null
+++ b/examples/GuiClient/resource/orange.png
Binary files differ
diff --git a/examples/GuiClient/resource/red.png b/examples/GuiClient/resource/red.png
new file mode 100644
index 00000000..9f356080
--- /dev/null
+++ b/examples/GuiClient/resource/red.png
Binary files differ
diff --git a/examples/GuiClient/resource/redred.png b/examples/GuiClient/resource/redred.png
new file mode 100644
index 00000000..3cf1bc72
--- /dev/null
+++ b/examples/GuiClient/resource/redred.png
Binary files differ
diff --git a/examples/GuiClient/resource/searchIcon.png b/examples/GuiClient/resource/searchIcon.png
new file mode 100644
index 00000000..d8c1e9bd
--- /dev/null
+++ b/examples/GuiClient/resource/searchIcon.png
Binary files differ
diff --git a/examples/GuiClient/resources.qrc b/examples/GuiClient/resources.qrc
new file mode 100644
index 00000000..082e59d0
--- /dev/null
+++ b/examples/GuiClient/resources.qrc
@@ -0,0 +1,12 @@
+<RCC>
+ <qresource prefix="/icons" >
+ <file>resource/green.png</file>
+ <file>resource/orange.png</file>
+ <file>resource/red.png</file>
+ <file>resource/gray.png</file>
+ <file>resource/avatar.png</file>
+ <file>resource/searchIcon.png</file>
+ <file>resource/downArrow.png</file>
+ <file>resource/ajax-loader.gif</file>
+ </qresource>
+</RCC>
diff --git a/examples/GuiClient/rosterItem.cpp b/examples/GuiClient/rosterItem.cpp
new file mode 100644
index 00000000..4075f4fb
--- /dev/null
+++ b/examples/GuiClient/rosterItem.cpp
@@ -0,0 +1,107 @@
+#include "rosterItem.h"
+#include <QImage>
+
+rosterItem::rosterItem(const QString& bareJid) //: QStandardItem(bareJid)
+{
+ setStatusType(QXmppPresence::Status::Offline);
+ setStatusText("Offline");
+}
+
+void rosterItem::setName(const QString& name)
+{
+ setText(name);
+}
+
+QString rosterItem::getName()
+{
+ return text();
+}
+
+void rosterItem::setBareJid(const QString& bareJid)
+{
+ setData(bareJid, rosterItem::BareJid);
+}
+
+void rosterItem::setStatusText(const QString& text)
+{
+ setData(text, rosterItem::StatusText);
+}
+
+QString rosterItem::getBareJid()
+{
+ return data(rosterItem::BareJid).toString();
+}
+
+QString rosterItem::getStatusText()
+{
+ return data(rosterItem::StatusText).toString();
+}
+
+void rosterItem::setStatusType(QXmppPresence::Status::Type type)
+{
+ setData(static_cast<int>(type), StatusType);
+ QString icon;
+ switch(type)
+ {
+ case QXmppPresence::Status::Online:
+ case QXmppPresence::Status::Chat:
+ icon = "green";
+ break;
+ case QXmppPresence::Status::Away:
+ case QXmppPresence::Status::XA:
+ icon = "orange";
+ break;
+ case QXmppPresence::Status::DND:
+ icon = "red";
+ break;
+ case QXmppPresence::Status::Invisible:
+ case QXmppPresence::Status::Offline:
+ icon = "gray";
+ break;
+ }
+ if(!icon.isEmpty())
+ setIcon(QIcon(":/icons/resource/"+icon+".png"));
+}
+
+QXmppPresence::Status::Type rosterItem::getStatusType()
+{
+ return static_cast<QXmppPresence::Status::Type>(data(StatusType).toInt());
+}
+
+void rosterItem::setPresenceType(QXmppPresence::Type type)
+{
+ setData(static_cast<int>(type), PresenceType);
+ QString icon;
+ switch(type)
+ {
+ case QXmppPresence::Available:
+ break;
+ case QXmppPresence::Unavailable:
+ icon = "gray";
+ break;
+ case QXmppPresence::Error:
+ case QXmppPresence::Subscribe:
+ case QXmppPresence::Subscribed:
+ case QXmppPresence::Unsubscribe:
+ case QXmppPresence::Unsubscribed:
+ case QXmppPresence::Probe:
+ break;
+ }
+ if(!icon.isEmpty())
+ setIcon(QIcon(":/icons/resource/"+icon+".png"));
+}
+
+QXmppPresence::Type rosterItem::getPresenceType()
+{
+ return static_cast<QXmppPresence::Type>(data(PresenceType).toInt());
+}
+
+void rosterItem::setAvatar(const QImage& image)
+{
+ setData(QVariant(image), rosterItem::Avatar);
+}
+
+QImage rosterItem::getAvatar()
+{
+ return qvariant_cast<QImage>(data(rosterItem::Avatar));
+}
diff --git a/examples/GuiClient/rosterItem.h b/examples/GuiClient/rosterItem.h
new file mode 100644
index 00000000..94e2d0bc
--- /dev/null
+++ b/examples/GuiClient/rosterItem.h
@@ -0,0 +1,144 @@
+#ifndef ROSTERITEM_H
+#define ROSTERITEM_H
+
+#include <QStandardItem>
+#include <QItemDelegate>
+#include <QPainter>
+#include "QXmppPresence.h"
+
+class rosterItem : public QStandardItem
+{
+
+public:
+ enum userRoles
+ {
+ StatusText = Qt::UserRole + 2,
+ StatusType,
+ PresenceType,
+ BareJid,
+ Avatar
+ };
+
+ rosterItem(const QString& bareJid);
+
+ void setName(const QString& name);
+ QString getName();
+ void setBareJid(const QString& bareJid);
+ void setStatusText(const QString& text);
+ void setStatusType(QXmppPresence::Status::Type type);
+ void setPresenceType(QXmppPresence::Type type);
+ void setAvatar(const QImage& image);
+ QImage getAvatar();
+ QString getBareJid();
+ QString getStatusText();
+ QXmppPresence::Status::Type getStatusType();
+ QXmppPresence::Type getPresenceType();
+};
+
+class ItemDelegate : public QItemDelegate
+{
+public:
+ ItemDelegate()
+ {
+ }
+
+ QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const
+ {
+ return QSize(44, 36);
+ }
+
+ void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
+ {
+ painter->save();
+ painter->setRenderHint(QPainter::TextAntialiasing);
+ QVariant value = index.data(Qt::DecorationRole);
+
+ QColor selectedBg(60, 140, 222);
+ QColor alternateBg(239, 245, 254);
+ QColor selectedText(Qt::white);
+
+ QColor nameTextColor(Qt::black);
+ QColor statusTextColor(Qt::darkGray);
+
+ QPixmap pixmap;
+ if(value.type() == QVariant::Icon)
+ {
+ QIcon icon = qvariant_cast<QIcon>(value);
+ pixmap = icon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On);
+ }
+
+ QPen penDivision;
+// if(index.row() % 2)
+// painter->fillRect(option.rect, alternateBg);
+
+ if (option.state & QStyle::State_Selected)
+ {
+ painter->fillRect(option.rect, selectedBg);
+// painter->fillRect(option.rect, option.palette.highlight());
+// penDivision.setColor(option.palette.highlight().color());
+ penDivision.setColor(selectedBg);
+ nameTextColor = selectedText;
+ statusTextColor = selectedText;
+ }
+ else
+ {
+ penDivision.setColor(QColor(244, 244, 244));
+ }
+
+ QRect rect = option.rect;
+ rect.setWidth(pixmap.width());
+ rect.setHeight(pixmap.height());
+ rect.moveTop(rect.y() + (option.rect.height() - pixmap.height())/2);
+ rect.moveLeft(rect.left() + 2);
+ painter->drawPixmap(rect, pixmap);
+
+ rect = option.rect;
+ rect.setLeft(rect.x() + pixmap.width() + 8);
+ rect.moveTop(rect.y() + 3);
+ QFont font;
+ painter->setFont(font);
+ painter->setPen(nameTextColor);
+ if(!index.data(Qt::DisplayRole).toString().isEmpty())
+ painter->drawText(rect, index.data(Qt::DisplayRole).toString());
+ else
+ painter->drawText(rect, index.data(rosterItem::BareJid).toString());
+
+ painter->setPen(statusTextColor);
+ rect.setTop(rect.y() + rect.height()/2);
+ rect.moveTop(rect.y() - 3);
+ painter->drawText(rect, index.data(rosterItem::StatusText).toString());
+
+ penDivision.setWidth(0);
+ painter->setPen(penDivision);
+
+ rect = option.rect;
+ QPoint left = rect.bottomLeft();
+ left.setX(left.x() + 4);
+ QPoint right = rect.bottomRight();
+ right.setX(right.x() - 4);
+ painter->drawLine(left, right);
+
+ QImage image;
+ value = index.data(rosterItem::Avatar);
+ if(value.type() == QVariant::Image)
+ {
+ image = qvariant_cast<QImage>(value);
+ }
+
+ pixmap = QPixmap(":/icons/resource/avatar.png");
+ rect = option.rect;
+ rect.setWidth(pixmap.width());
+ rect.setHeight(pixmap.height());
+ rect.moveTop(rect.y() + (option.rect.height() - pixmap.height())/2);
+ rect.moveLeft(option.rect.x() + option.rect.width() - pixmap.width() - 2);
+
+ if(image.isNull())
+ painter->drawPixmap(rect, pixmap);
+ else
+ painter->drawImage(rect, image);
+
+ painter->restore();
+ }
+};
+
+#endif // ROSTERITEM_H
diff --git a/examples/GuiClient/rosterItemModel.cpp b/examples/GuiClient/rosterItemModel.cpp
new file mode 100644
index 00000000..2b59dbbd
--- /dev/null
+++ b/examples/GuiClient/rosterItemModel.cpp
@@ -0,0 +1,82 @@
+#include "rosterItemModel.h"
+
+rosterItemModel::rosterItemModel(QObject* parent) : QStandardItemModel(parent)
+{
+// addRosterItemIfDontExist("jkhjkhkhkhk");
+// addRosterItemIfDontExist("uuuu");
+// addRosterItemIfDontExist("kkkkkkk");
+// addRosterItemIfDontExist("jjjjjjjj");
+}
+
+rosterItem* rosterItemModel::getRosterItemFromBareJid(const QString& bareJid)
+{
+ if(m_jidRosterItemMap.contains(bareJid))
+ return m_jidRosterItemMap[bareJid];
+ else
+ return 0;
+}
+
+void rosterItemModel::addRosterItemIfDontExist(const QString& bareJid)
+{
+ if(!m_jidRosterItemMap.contains(bareJid))
+ {
+ rosterItem* item = new rosterItem(bareJid);
+ m_jidRosterItemMap[bareJid] = item;
+ appendRow(item);
+ item->setStatusText("Offline");
+ item->setBareJid(bareJid);
+ }
+}
+
+void rosterItemModel::updatePresence(const QString& bareJid, const QMap<QString, QXmppPresence>& presences)
+{
+ addRosterItemIfDontExist(bareJid);
+
+ if(presences.count() > 0)
+ {
+ QString statusText = presences.begin().value().getStatus().getStatusText();
+ QXmppPresence::Status::Type statusType = presences.begin().value().getStatus().getType();
+ QXmppPresence::Type presenceType = presences.begin().value().getType();
+
+ if(statusText.isEmpty())
+ {
+ if(presenceType == QXmppPresence::Available)
+ statusText = "Available";
+ else if(presenceType == QXmppPresence::Unavailable)
+ statusText = "Offline";
+ }
+ getRosterItemFromBareJid(bareJid)->setStatusText(statusText);
+ getRosterItemFromBareJid(bareJid)->setStatusType(statusType);
+ getRosterItemFromBareJid(bareJid)->setPresenceType(presenceType);
+ }
+}
+
+void rosterItemModel::updateRosterEntry(const QString& bareJid, const QXmppRosterIq::Item& rosterEntry)
+{
+ addRosterItemIfDontExist(bareJid);
+
+ QString name = rosterEntry.getName();
+ if(name.isEmpty())
+ {
+ name = bareJid;
+ }
+
+ if(getRosterItemFromBareJid(bareJid))
+ getRosterItemFromBareJid(bareJid)->setName(name);
+}
+
+void rosterItemModel::updateAvatar(const QString& bareJid, const QImage& image)
+{
+ addRosterItemIfDontExist(bareJid);
+
+ if(image.isNull())
+ return;
+
+ getRosterItemFromBareJid(bareJid)->setAvatar(image);
+}
+
+void rosterItemModel::clear()
+{
+ QStandardItemModel::clear();
+ m_jidRosterItemMap.clear();
+}
diff --git a/examples/GuiClient/rosterItemModel.h b/examples/GuiClient/rosterItemModel.h
new file mode 100644
index 00000000..e4a57fb5
--- /dev/null
+++ b/examples/GuiClient/rosterItemModel.h
@@ -0,0 +1,25 @@
+#ifndef ROSTERITEMMODEL_H
+#define ROSTERITEMMODEL_H
+
+#include <QStandardItemModel>
+#include "rosterItem.h"
+#include "QXmppRoster.h"
+#include "QXmppPresence.h"
+
+class rosterItemModel : public QStandardItemModel
+{
+public:
+ rosterItemModel(QObject* parent);
+ rosterItem* getRosterItemFromBareJid(const QString& bareJid);
+
+ void updatePresence(const QString& bareJid, const QMap<QString, QXmppPresence>& presences);
+ void updateRosterEntry(const QString& bareJid, const QXmppRosterIq::Item& rosterEntry);
+ void updateAvatar(const QString& bareJid, const QImage& image);
+
+ void clear();
+private:
+ QMap<QString, rosterItem*> m_jidRosterItemMap;
+ void addRosterItemIfDontExist(const QString& bareJid);
+};
+
+#endif // ROSTERITEMMODEL_H
diff --git a/examples/GuiClient/rosterItemSortFilterProxyModel.cpp b/examples/GuiClient/rosterItemSortFilterProxyModel.cpp
new file mode 100644
index 00000000..555a0364
--- /dev/null
+++ b/examples/GuiClient/rosterItemSortFilterProxyModel.cpp
@@ -0,0 +1,41 @@
+#include "rosterItemSortFilterProxyModel.h"
+#include "rosterItem.h"
+#include "utils.h"
+
+rosterItemSortFilterProxyModel::rosterItemSortFilterProxyModel(QObject* parent):
+ QSortFilterProxyModel(parent)
+{
+ setDynamicSortFilter(true);
+ setFilterRole(Qt::DisplayRole);
+ setFilterCaseSensitivity(Qt::CaseInsensitive);
+}
+
+bool rosterItemSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
+{
+ int leftPresenceType = sourceModel()->data(left, rosterItem::PresenceType).toInt();
+ int leftStatusType = sourceModel()->data(left, rosterItem::StatusType).toInt();
+ int rightPresenceType = sourceModel()->data(right, rosterItem::PresenceType).toInt();
+ int rightStatusType = sourceModel()->data(right, rosterItem::StatusType).toInt();
+
+ if(leftPresenceType == rightPresenceType)
+ {
+ if(leftStatusType == rightStatusType)
+ {
+ // based on display text
+ int compare = left.data().toString().compare(right.data().toString(), Qt::CaseInsensitive);
+ if(compare < 0)
+ return true;
+ else
+ return false;
+ }
+ else
+ {
+ return comparisonWeightsPresenceStatusType(static_cast<QXmppPresence::Status::Type>(leftStatusType)) <
+ comparisonWeightsPresenceStatusType(static_cast<QXmppPresence::Status::Type>(rightStatusType));
+ }
+ }
+ else
+ return comparisonWeightsPresenceType(static_cast<QXmppPresence::Type>(leftPresenceType)) <
+ comparisonWeightsPresenceType(static_cast<QXmppPresence::Type>(rightPresenceType));
+}
+
diff --git a/examples/GuiClient/rosterItemSortFilterProxyModel.h b/examples/GuiClient/rosterItemSortFilterProxyModel.h
new file mode 100644
index 00000000..9df4195c
--- /dev/null
+++ b/examples/GuiClient/rosterItemSortFilterProxyModel.h
@@ -0,0 +1,13 @@
+#ifndef ROSTERITEMSORTFILTERPROXYMODEL_H
+#define ROSTERITEMSORTFILTERPROXYMODEL_H
+
+#include <QSortFilterProxyModel>
+
+class rosterItemSortFilterProxyModel : public QSortFilterProxyModel
+{
+public:
+ rosterItemSortFilterProxyModel(QObject* parent = 0);
+ bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
+};
+
+#endif // ROSTERITEMSORTFILTERPROXYMODEL_H
diff --git a/examples/GuiClient/searchLineEdit.cpp b/examples/GuiClient/searchLineEdit.cpp
new file mode 100644
index 00000000..6584ab06
--- /dev/null
+++ b/examples/GuiClient/searchLineEdit.cpp
@@ -0,0 +1,53 @@
+#include "searchLineEdit.h"
+
+searchLineEdit::searchLineEdit(QWidget* parent):QLineEdit(parent)
+{
+ setMinimumSize(QSize(20, 24));
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ setStyleSheet(":enabled { padding-right: 20px; padding-left: 20px }");
+ clearButton = new ClearButton(this);
+ clearButton->setVisible(true);
+
+ clearButton->setCursor(Qt::ArrowCursor);
+ clearButton->setToolTip("Clear");
+ connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
+}
+
+void searchLineEdit::paintEvent(QPaintEvent *e) {
+ QLineEdit::paintEvent(e);
+ QPainter painter(this);
+
+ QImage image(":/icons/resource/searchIcon.png");
+
+ QRectF target(image.rect());
+ target.moveCenter(QPointF(target.center().x()+2, target.center().y()+3));
+ painter.drawImage(target, image, image.rect());
+
+ if (text().length() == 0 && (!hasFocus()) )
+ {
+ painter.setPen(Qt::gray);
+ QRect r = rect();
+ painter.drawText(24, r.height()/2+4, "Search Contacts");
+ }
+
+ if(text().isEmpty())
+ clearButton->setVisible(false);
+ else
+ clearButton->setVisible(true);
+}
+
+void searchLineEdit::resizeEvent(QResizeEvent*)
+{
+ clearButton->setParent(this);
+ clearButton->setGeometry(QRect(width()-23,
+ 0,
+ 24, 24));
+}
+
+void searchLineEdit::moveEvent(QMoveEvent*)
+{
+ clearButton->setParent(this);
+ clearButton->setGeometry(QRect(width()-23, 1,
+ 24, 24));
+}
diff --git a/examples/GuiClient/searchLineEdit.h b/examples/GuiClient/searchLineEdit.h
new file mode 100644
index 00000000..330bbd3b
--- /dev/null
+++ b/examples/GuiClient/searchLineEdit.h
@@ -0,0 +1,58 @@
+#ifndef SEARCHLINEEDIT_H
+#define SEARCHLINEEDIT_H
+
+#include <QPushButton>
+#include <QLineEdit>
+#include <QPainter>
+
+class ClearButton : public QPushButton
+{
+ Q_OBJECT
+
+public:
+ ClearButton(QWidget *w)
+ : QPushButton(w)
+ {
+ setMinimumSize(24, 24);
+ setFixedSize(24, 24);
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ }
+ void paintEvent(QPaintEvent *event)
+ {
+ Q_UNUSED(event);
+ QPainter painter(this);
+ int height = parentWidget()->geometry().height();
+ int width = height; //parentWidget()->geometry().width();
+
+ painter.setRenderHint(QPainter::Antialiasing, true);
+ painter.setPen(Qt::white);
+
+ float penwidth = isDown() ? 1.2 :
+ underMouse() ? 1.6 : 1.2;
+ painter.setBrush(Qt::red);
+ //painter.drawEllipse(4, 4, width - 8, height - 8);
+ QPen pen;
+ pen.setWidthF(penwidth);
+ pen.setColor(Qt::black);
+ painter.setPen(pen);
+ int border = 7;
+ painter.drawLine(border, border, width - border, height - border);
+ painter.drawLine(border, height - border, width - border, border);
+ }
+};
+
+class searchLineEdit : public QLineEdit
+{
+public:
+ searchLineEdit(QWidget* parent = 0);
+
+protected:
+ virtual void paintEvent(QPaintEvent* e);
+ virtual void resizeEvent(QResizeEvent*);
+ virtual void moveEvent(QMoveEvent*);
+
+private:
+ QPushButton *clearButton;
+};
+
+#endif // SEARCHLINEEDIT_H
diff --git a/examples/GuiClient/statusTextWidget.cpp b/examples/GuiClient/statusTextWidget.cpp
new file mode 100644
index 00000000..c268dd3f
--- /dev/null
+++ b/examples/GuiClient/statusTextWidget.cpp
@@ -0,0 +1,144 @@
+#include "statusTextWidget.h"
+#include <QHBoxLayout>
+#include <QMenu>
+
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOptionFrameV2>
+
+QSize statusLineEdit::sizeHint() const
+{
+ QFont font;
+ QFontMetrics fm(font);
+ int width = fm.width(text());
+ if(width <= (160 - 8))
+ return QSize(width+8, 18);
+ else
+ return QSize(160, 18);
+}
+
+void statusLineEditButton::paintEvent(QPaintEvent* event)
+{
+ Q_UNUSED(event);
+ QPainter painter(this);
+
+ QStyleOptionButton panel;
+ initStyleOption(&panel);
+ QRect r = style()->subElementRect(QStyle::SE_PushButtonFocusRect, &panel, this);
+
+ QImage image(":/icons/resource/downArrow.png");
+ QRect rectDelta(0, 0, 7, 4);
+ rectDelta.moveCenter(r.center());
+ painter.drawImage(rectDelta, image);
+}
+
+void statusLineEdit::focusInEvent(QFocusEvent* event)
+{
+ QLineEdit::focusInEvent(event);
+ QLineEdit::selectAll();
+}
+
+void statusLineEdit::mousePressEvent(QMouseEvent* event)
+{
+ QLineEdit::mousePressEvent(event);
+ QLineEdit::selectAll();
+}
+
+statusTextWidget::statusTextWidget(QWidget* parent) : QWidget(parent),
+ m_statusLineEdit(0), m_statusButton(0), m_clearStatusTextHistory("Clear Status Message", this)
+{
+ m_statusLineEdit = new statusLineEdit(this);
+ QHBoxLayout* layout = new QHBoxLayout;
+ layout->addWidget(m_statusLineEdit);
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ m_statusButton = new statusLineEditButton(this);
+ layout->addWidget(m_statusButton);
+ setLayout(layout);
+
+ bool check = connect(m_statusButton, SIGNAL(clicked(bool)), SLOT(showMenu()));
+ Q_ASSERT(check);
+ check = connect(m_statusLineEdit, SIGNAL(textChanged(const QString&)), SLOT(textChanged()));
+ Q_ASSERT(check);
+ check = connect(m_statusLineEdit, SIGNAL(editingFinished()), SLOT(statusTextChanged_helper()));
+ Q_ASSERT(check);
+ check = connect(&m_clearStatusTextHistory, SIGNAL(triggered()), SLOT(clearStatusTextHistory()));
+ Q_ASSERT(check);
+}
+
+void statusTextWidget::showMenu()
+{
+ QMenu menu(this);
+
+ int size = m_statusTextActionList.size();
+ for(int i = 0; i < size; ++i)
+ {
+ menu.addAction(m_statusTextActionList.at(size - 1 - i));
+ }
+
+ menu.addSeparator();
+ menu.addAction(&m_clearStatusTextHistory);
+ m_clearStatusTextHistory.setDisabled(size == 0);
+ menu.exec(m_statusLineEdit->mapToGlobal(QPoint(0, m_statusLineEdit->height())));
+}
+
+void statusTextWidget::textChanged()
+{
+ m_statusLineEdit->updateGeometry();
+}
+
+void statusTextWidget::statusTextChanged_helper()
+{
+ addStatusTextToList(m_statusLineEdit->text());
+ emit statusTextChanged(m_statusLineEdit->text());
+ parentWidget()->setFocus();
+}
+
+void statusTextWidget::setStatusText(const QString& statusText)
+{
+ m_statusLineEdit->setText(statusText);
+}
+
+void statusTextWidget::addStatusTextToList(const QString& status)
+{
+ for(int i = 0; i < m_statusTextActionList.size(); ++i)
+ {
+ if(m_statusTextActionList.at(i)->data().toString() == status)
+ {
+ QAction* action = m_statusTextActionList.takeAt(i);
+ m_statusTextActionList.append(action);
+ return;
+ }
+ }
+
+ QAction* action = new QAction(status, this);
+ action->setData(status);
+ bool check = connect(action, SIGNAL(triggered()), SLOT(statusTextChanged_menuClick()));
+ Q_ASSERT(check);
+ m_statusTextActionList.append(action);
+}
+
+void statusTextWidget::statusTextChanged_menuClick()
+{
+ QAction* action = qobject_cast<QAction*>(sender());
+ if(action)
+ {
+ int i = 0;
+ while(i < m_statusTextActionList.size() && action != m_statusTextActionList.at(i))
+ {
+ ++i;
+ }
+
+ if(action == m_statusTextActionList.at(i))
+ {
+ m_statusTextActionList.removeAt(i);
+ m_statusTextActionList.append(action);
+ }
+ m_statusLineEdit->setText(action->data().toString());
+ emit statusTextChanged(action->data().toString());
+ }
+}
+
+void statusTextWidget::clearStatusTextHistory()
+{
+ emit statusTextChanged("");
+}
diff --git a/examples/GuiClient/statusTextWidget.h b/examples/GuiClient/statusTextWidget.h
new file mode 100644
index 00000000..1d91e143
--- /dev/null
+++ b/examples/GuiClient/statusTextWidget.h
@@ -0,0 +1,111 @@
+#ifndef STATUSTEXTWIDGET_H
+#define STATUSTEXTWIDGET_H
+
+#include <QWidget>
+#include <QAction>
+#include <QLineEdit>
+#include <QPainter>
+#include <QPushButton>
+#include <QStyleOptionFrameV2>
+#include <QFontMetrics>
+
+
+class statusLineEditButton : public QPushButton
+{
+ Q_OBJECT
+
+public:
+ statusLineEditButton(QWidget* parent = 0): QPushButton(parent)
+ {
+ setCursor(Qt::PointingHandCursor);
+ }
+ void paintEvent(QPaintEvent* event);
+ QSize sizeHint() const
+ {
+ return QSize(14, 14);
+ }
+};
+
+class statusLineEdit : public QLineEdit
+{
+public:
+ statusLineEdit(QWidget* parent = 0) : QLineEdit(parent)
+ {
+ setAttribute(Qt::WA_Hover, true);
+ setText("Available");
+ setMinimumSize(QSize(20, 18));
+ }
+ void focusInEvent(QFocusEvent* event);
+ void mousePressEvent(QMouseEvent* event);
+
+ void paintEvent(QPaintEvent* event)
+ {
+ if(hasFocus())
+ {
+ QLineEdit::paintEvent(event);
+ }
+ else
+ {
+ QPainter p(this);
+ QRect r = rect();
+ QPalette pal = palette();
+
+ QStyleOptionFrameV2 panel;
+ initStyleOption(&panel);
+ r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
+ r.adjust(-1, -1, 0, 0);
+ r.setLeft(r.left() + 4);
+ p.setPen(Qt::darkGray);
+ p.drawText(r, Qt::AlignVCenter, text());
+ }
+
+ if(underMouse() && !hasFocus())
+ {
+ QPainter p(this);
+ QRect r = rect();
+ QPalette pal = palette();
+
+ QStyleOptionFrameV2 panel;
+ initStyleOption(&panel);
+ r = style()->subElementRect(QStyle::SE_LineEditContents, &panel, this);
+ r.adjust(-1, -1, 0, 0);
+ p.setPen(Qt::gray);
+ p.drawRect(r);
+ r.setLeft(r.left() + 4);
+ p.setPen(Qt::darkGray);
+ p.drawText(r, Qt::AlignVCenter, text());
+ }
+ }
+ QSize sizeHint() const;
+};
+
+class statusTextWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ statusTextWidget(QWidget* parent = 0);
+ void setStatusText(const QString& statusText);
+
+public slots:
+ void showMenu();
+ void textChanged();
+
+private slots:
+ void statusTextChanged_helper();
+ void statusTextChanged_menuClick();
+ void clearStatusTextHistory();
+
+signals:
+ void statusTextChanged(const QString&);
+
+private:
+ void addStatusTextToList(const QString& status);
+ statusLineEdit* m_statusLineEdit;
+ statusLineEditButton* m_statusButton;
+
+ QList<QAction*> m_statusTextActionList;
+ QAction m_clearStatusTextHistory;
+};
+
+#endif // STATUSTEXTWIDGET_H
diff --git a/examples/GuiClient/statusWidget.cpp b/examples/GuiClient/statusWidget.cpp
new file mode 100644
index 00000000..0ad1ead6
--- /dev/null
+++ b/examples/GuiClient/statusWidget.cpp
@@ -0,0 +1,130 @@
+#include "statusWidget.h"
+#include <QMenu>
+#include <QFileDialog>
+#include <QMessageBox>
+
+statusWidget::statusWidget(QWidget* parent)
+{
+ setupUi(this);
+ QMenu* menu = new QMenu(this);
+ menu->addAction(actionAvailable);
+ menu->addAction(actionBusy);
+ menu->addAction(actionAway);
+// menu->addAction(actionInvisible);
+ menu->addSeparator();
+ menu->addAction(actionSign_out);
+ toolButton_userName->setMenu(menu);
+
+ bool check = connect(statusTextWidgetObject, SIGNAL(statusTextChanged(const QString&)), SIGNAL(statusTextChanged(const QString&)));
+ Q_ASSERT(check);
+
+ check = connect(actionAvailable, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
+ Q_ASSERT(check);
+ check = connect(actionBusy, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
+ Q_ASSERT(check);
+ check = connect(actionAway, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
+ Q_ASSERT(check);
+ check = connect(actionInvisible, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
+ Q_ASSERT(check);
+ check = connect(actionSign_out, SIGNAL(triggered()), SLOT(presenceMenuTriggered()));
+ Q_ASSERT(check);
+
+ check = connect(pushButton_avatar, SIGNAL(clicked()), SLOT(avatarSelection()));
+ Q_ASSERT(check);
+}
+
+void statusWidget::setStatusText(const QString& statusText)
+{
+ statusTextWidgetObject->setStatusText(statusText);
+}
+
+void statusWidget::presenceMenuTriggered()
+{
+ QString icon = "green";
+ QAction* action = qobject_cast<QAction*>(sender());
+ if(action == actionAvailable)
+ {
+ emit presenceTypeChanged(QXmppPresence::Available);
+ icon = "green";
+ }
+ else if(action == actionBusy)
+ {
+ emit presenceStatusTypeChanged(QXmppPresence::Status::DND);
+ icon = "red";
+ }
+ else if(action == actionAway)
+ {
+ emit presenceStatusTypeChanged(QXmppPresence::Status::Away);
+ icon = "orange";
+ }
+ else if(action == actionInvisible)
+ {
+ emit presenceStatusTypeChanged(QXmppPresence::Status::Invisible);
+ icon = "gray";
+ }
+ else if(action == actionSign_out)
+ {
+ emit presenceTypeChanged(QXmppPresence::Unavailable);
+ icon = "gray";
+ }
+ label->setPixmap(QPixmap(":/icons/resource/"+icon+".png"));
+}
+
+void statusWidget::setPresenceAndStatusType(QXmppPresence::Type presenceType,
+ QXmppPresence::Status::Type statusType)
+{
+ if(presenceType == QXmppPresence::Available)
+ {
+ QString icon = "green";
+ switch(statusType)
+ {
+ case QXmppPresence::Status::Online:
+ case QXmppPresence::Status::Chat:
+ icon = "green";
+ break;
+ case QXmppPresence::Status::Away:
+ case QXmppPresence::Status::XA:
+ icon = "orange";
+ break;
+ case QXmppPresence::Status::DND:
+ icon = "red";
+ break;
+ case QXmppPresence::Status::Invisible:
+ case QXmppPresence::Status::Offline:
+ icon = "gray";
+ break;
+ }
+ label->setPixmap(QPixmap(":/icons/resource/"+icon+".png"));
+ }
+ else if(presenceType == QXmppPresence::Unavailable)
+ {
+ label->setPixmap(QPixmap(":/icons/resource/gray.png"));
+ }
+}
+
+void statusWidget::avatarSelection()
+{
+ QString file = QFileDialog::getOpenFileName(this, "Select your avatar");
+ if(file.isEmpty())
+ return;
+
+ QImage image;
+ if(image.load(file))
+ {
+ QImage scaled = image.scaled(QSize(96, 96), Qt::KeepAspectRatio,
+ Qt::SmoothTransformation);
+ emit avatarChanged(scaled);
+ }
+ else
+ QMessageBox::information(this, "Avatar selection", "Invalid image file");
+}
+
+void statusWidget::setDisplayName(const QString& name)
+{
+ toolButton_userName->setText(name);
+}
+
+void statusWidget::setAvatar(const QImage& image)
+{
+ pushButton_avatar->setIcon(QIcon(QPixmap::fromImage(image)));
+}
diff --git a/examples/GuiClient/statusWidget.h b/examples/GuiClient/statusWidget.h
new file mode 100644
index 00000000..17609342
--- /dev/null
+++ b/examples/GuiClient/statusWidget.h
@@ -0,0 +1,29 @@
+#ifndef STATUSWIDGET_H
+#define STATUSWIDGET_H
+#include "ui_statusWidget.h"
+#include "QXmppPresence.h"
+
+class statusWidget : public QWidget, public Ui::statusWidgetClass
+{
+ Q_OBJECT
+
+public:
+ statusWidget(QWidget* parent = 0);
+ void setDisplayName(const QString& name);
+ void setStatusText(const QString& statusText);
+ void setPresenceAndStatusType(QXmppPresence::Type presenceType,
+ QXmppPresence::Status::Type statusType);
+ void setAvatar(const QImage&);
+
+private slots:
+ void presenceMenuTriggered();
+ void avatarSelection();
+
+signals:
+ void statusTextChanged(const QString&);
+ void presenceTypeChanged(QXmppPresence::Type);
+ void presenceStatusTypeChanged(QXmppPresence::Status::Type);
+ void avatarChanged(const QImage&);
+};
+
+#endif // STATUSWIDGET_H
diff --git a/examples/GuiClient/statusWidget.ui b/examples/GuiClient/statusWidget.ui
new file mode 100644
index 00000000..758fa63b
--- /dev/null
+++ b/examples/GuiClient/statusWidget.ui
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>statusWidgetClass</class>
+ <widget class="QWidget" name="statusWidgetClass">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>251</width>
+ <height>40</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>4</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>4</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="pixmap">
+ <pixmap resource="resources.qrc">:/icons/resource/green.png</pixmap>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="customToolButton" name="toolButton_userName">
+ <property name="text">
+ <string>toolbutton</string>
+ </property>
+ <property name="popupMode">
+ <enum>QToolButton::InstantPopup</enum>
+ </property>
+ <property name="toolButtonStyle">
+ <enum>Qt::ToolButtonTextBesideIcon</enum>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ <property name="arrowType">
+ <enum>Qt::DownArrow</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="statusTextWidget" name="statusTextWidgetObject" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="avatarWidget" name="pushButton_avatar">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/icons/resource/avatar.png</normaloff>:/icons/resource/avatar.png</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ <action name="actionBusy">
+ <property name="icon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/icons/resource/red.png</normaloff>:/icons/resource/red.png</iconset>
+ </property>
+ <property name="text">
+ <string>Busy</string>
+ </property>
+ </action>
+ <action name="actionAvailable">
+ <property name="icon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/icons/resource/green.png</normaloff>:/icons/resource/green.png</iconset>
+ </property>
+ <property name="text">
+ <string>Available</string>
+ </property>
+ </action>
+ <action name="actionInvisible">
+ <property name="icon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/icons/resource/gray.png</normaloff>:/icons/resource/gray.png</iconset>
+ </property>
+ <property name="text">
+ <string>Invisible</string>
+ </property>
+ </action>
+ <action name="actionSign_out">
+ <property name="icon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/icons/resource/gray.png</normaloff>:/icons/resource/gray.png</iconset>
+ </property>
+ <property name="text">
+ <string>Sign out</string>
+ </property>
+ </action>
+ <action name="actionAway">
+ <property name="icon">
+ <iconset resource="resources.qrc">
+ <normaloff>:/icons/resource/orange.png</normaloff>:/icons/resource/orange.png</iconset>
+ </property>
+ <property name="text">
+ <string>Away</string>
+ </property>
+ </action>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>avatarWidget</class>
+ <extends>QPushButton</extends>
+ <header>avatarWidget.h</header>
+ </customwidget>
+ <customwidget>
+ <class>statusTextWidget</class>
+ <extends>QWidget</extends>
+ <header>statusTextWidget.h</header>
+ <container>1</container>
+ </customwidget>
+ <customwidget>
+ <class>customToolButton</class>
+ <extends>QToolButton</extends>
+ <header>customToolButton.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="resources.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/examples/GuiClient/utils.cpp b/examples/GuiClient/utils.cpp
new file mode 100644
index 00000000..0d19830e
--- /dev/null
+++ b/examples/GuiClient/utils.cpp
@@ -0,0 +1,120 @@
+#include "utils.h"
+#include <QDir>
+#include <QDesktopServices>
+
+int comparisonWeightsPresenceStatusType(QXmppPresence::Status::Type statusType)
+{
+ switch(statusType)
+ {
+ case QXmppPresence::Status::Online:
+ case QXmppPresence::Status::Chat:
+ return 0;
+ case QXmppPresence::Status::DND:
+ return 1;
+ case QXmppPresence::Status::Away:
+ case QXmppPresence::Status::XA:
+ return 2;
+ case QXmppPresence::Status::Offline:
+ case QXmppPresence::Status::Invisible:
+ return 3;
+ }
+}
+
+int comparisonWeightsPresenceType(QXmppPresence::Type type)
+{
+ switch(type)
+ {
+ case QXmppPresence::Available:
+ return 0;
+ case QXmppPresence::Unavailable:
+ return 1;
+ case QXmppPresence::Error:
+ case QXmppPresence::Subscribe:
+ case QXmppPresence::Subscribed:
+ case QXmppPresence::Unsubscribe:
+ case QXmppPresence::Unsubscribed:
+ case QXmppPresence::Probe:
+ return 3;
+ }
+}
+
+QString presenceToStatusText(const QXmppPresence& presence)
+{
+ QString statusText = presence.getStatus().getStatusText();
+ if(statusText.isEmpty())
+ {
+ if(presence.getType() == QXmppPresence::Available)
+ {
+ switch(presence.getStatus().getType())
+ {
+ case QXmppPresence::Status::Invisible:
+ case QXmppPresence::Status::Offline:
+ statusText = "Offline";
+ break;
+ case QXmppPresence::Status::Online:
+ case QXmppPresence::Status::Chat:
+ statusText = "Available";
+ break;
+ case QXmppPresence::Status::Away:
+ case QXmppPresence::Status::XA:
+ statusText = "Idle";
+ break;
+ case QXmppPresence::Status::DND:
+ statusText = "Busy";
+ break;
+ }
+ }
+ else
+ statusText = "Offline";
+ }
+
+ return statusText;
+}
+
+QString getSettingsDir()
+{
+ return "appCache/";
+}
+
+QString getImageHash(const QByteArray& image)
+{
+ if(image.isEmpty())
+ return "";
+ else
+ return QString(QCryptographicHash::hash(image,
+ QCryptographicHash::Sha1).toHex());
+}
+
+QImage getImageFromByteArray(const QByteArray& image)
+{
+ QBuffer buffer;
+ buffer.setData(image);
+ buffer.open(QIODevice::ReadOnly);
+ QImageReader imageReader(&buffer);
+ return imageReader.read();
+}
+
+QString getImageType1(const QByteArray& image)
+{
+ QBuffer buffer;
+ buffer.setData(image);
+ buffer.open(QIODevice::ReadOnly);
+ QString format = QImageReader::imageFormat(&buffer);
+
+ if(format.toUpper() == "PNG")
+ return "image/png";
+ else if(format.toUpper() == "MNG")
+ return "video/x-mng";
+ else if(format.toUpper() == "GIF")
+ return "image/gif";
+ else if(format.toUpper() == "BMP")
+ return "image/bmp";
+ else if(format.toUpper() == "XPM")
+ return "image/x-xpm";
+ else if(format.toUpper() == "SVG")
+ return "image/svg+xml";
+ else if(format.toUpper() == "JPEG")
+ return "image/jpeg";
+
+ return "image/unknown";
+}
diff --git a/examples/GuiClient/utils.h b/examples/GuiClient/utils.h
new file mode 100644
index 00000000..5708c9f0
--- /dev/null
+++ b/examples/GuiClient/utils.h
@@ -0,0 +1,21 @@
+#ifndef CLIENTUTILS_H
+#define CLIENTUTILS_H
+
+#include "QXmppPresence.h"
+
+#include <QCryptographicHash>
+#include <QBuffer>
+#include <QImageReader>
+
+int comparisonWeightsPresenceStatusType(QXmppPresence::Status::Type);
+int comparisonWeightsPresenceType(QXmppPresence::Type);
+
+QString presenceToStatusText(const QXmppPresence& presence);
+
+QString getSettingsDir();
+
+QString getImageHash(const QByteArray& image);
+QImage getImageFromByteArray(const QByteArray& image);
+QString getImageType1(const QByteArray& image);
+
+#endif // CLIENTUTILS_H
diff --git a/examples/GuiClient/vCardManager.cpp b/examples/GuiClient/vCardManager.cpp
new file mode 100644
index 00000000..41af045c
--- /dev/null
+++ b/examples/GuiClient/vCardManager.cpp
@@ -0,0 +1,176 @@
+#include "vCardManager.h"
+#include "QXmppClient.h"
+#include "QXmppUtils.h"
+#include "utils.h"
+#include "QXmppVCardManager.h"
+#include <QFile>
+#include <QDomDocument>
+#include <QTextStream>
+#include <QCoreApplication>
+
+vCardManager::vCardManager(QXmppClient* client) : QObject(client),
+ m_client(client)
+{
+}
+
+void vCardManager::vCardReceived(const QXmppVCard& vcard)
+{
+ QString from = vcard.getFrom();
+ if(from.isEmpty() && m_client)
+ {
+ from = m_client->configuration().getJidBare();
+ m_selfFullName = vcard.fullName();
+ }
+
+// m_mapBareJidVcard[from] = vcard;
+
+ if(m_mapBareJidVCard[from].imageHash == getImageHash(vcard.photo()))
+ {
+ emit vCardReadyToUse(from);
+ return;
+ }
+
+ if(!m_mapBareJidVCard[from].imageHash.isEmpty())
+ {
+ QString fileName = getSettingsDir() + m_mapBareJidVCard[from].imageHash;
+ QFile file1(fileName + "_original.png");
+ QFile file2(fileName + "_scaled.png");
+ file1.remove();
+ file2.remove();
+ }
+
+ m_mapBareJidVCard[from].imageHash = getImageHash(vcard.photo());
+
+ QImage image = getImageFromByteArray(vcard.photo());
+ m_mapBareJidVCard[from].imageOriginal = image;
+
+ if(!image.isNull())
+ m_mapBareJidVCard[from].image = image.scaledToWidth(32);
+
+ QString fileName = getSettingsDir() + m_mapBareJidVCard[from].imageHash;
+ m_mapBareJidVCard[from].imageOriginal.save(fileName + "_original.png", "PNG");
+ m_mapBareJidVCard[from].image.save(fileName + "_scaled.png", "PNG");
+
+ saveToCache(from);
+
+ emit vCardReadyToUse(from);
+}
+
+bool vCardManager::isVCardAvailable(const QString& bareJid)
+{
+ return m_mapBareJidVCard.contains(bareJid);
+}
+
+void vCardManager::requestVCard(const QString& bareJid)
+{
+ if(m_client)
+ m_client->vCardManager().requestVCard(bareJid);
+}
+
+vCardManager::vCard& vCardManager::getVCard(const QString& bareJid)
+{
+ return m_mapBareJidVCard[bareJid];
+}
+
+void vCardManager::saveToCache(const QString& bareJid)
+{
+ QString fileBareJidImageMap = getSettingsDir() + m_client->configuration().getJidBare() + "_jidimage";
+ QFile file(fileBareJidImageMap);
+
+ if(!file.open(QIODevice::ReadWrite))
+ return;
+
+ QTextStream out(&file);
+ QMap<QString, vCardManager::vCard>::const_iterator i = m_mapBareJidVCard.constBegin();
+ while(i != m_mapBareJidVCard.constEnd())
+ {
+ out << i.key() << "\n" << i.value().imageHash << "\n";
+ ++i;
+ }
+ file.close();
+
+// if(!m_mapBareJidVCard.contains(bareJid))
+// return;
+// QString fileName = getSettingsDir() + m_mapBareJidVCard[bareJid].imageHash;
+// m_mapBareJidVCard[bareJid].imageOriginal.save(fileName + "_original.png", "PNG");
+// m_mapBareJidVCard[bareJid].image.save(fileName + "_scaled.png", "PNG");
+//
+// QString fileBareJidImageMap = getSettingsDir() + m_client->configuration().getJidBare() + "_jidimage.xml";
+//
+// if(m_domJidImage.documentElement().isNull())
+// {
+// QDomElement root = m_domJidImage.createElement("jidimage");
+// m_domJidImage.appendChild(root);
+// }
+//
+// QFile file(fileBareJidImageMap);
+// if(!file.open(QIODevice::ReadWrite))
+// return;
+//
+// if(m_domJidImage.documentElement().firstChildElement(bareJid).isNull())
+// {
+// QDomElement tag = m_domJidImage.createElement(bareJid);
+// m_domJidImage.documentElement().appendChild(tag);
+// QDomText t = m_domJidImage.createTextNode(m_mapBareJidVCard[bareJid].imageHash);
+// tag.appendChild(t);
+// }
+// else
+// {
+// m_domJidImage.documentElement().firstChildElement(bareJid).firstChild().setNodeValue(m_mapBareJidVCard[bareJid].imageHash);
+// }
+//
+// QTextStream out(&file);
+// m_domJidImage.save(out, 4);
+// file.close();
+}
+
+void vCardManager::loadAllFromCache()
+{
+ QString fileBareJidImageMap = getSettingsDir() + m_client->configuration().getJidBare() + "_jidimage";
+ QFile file(fileBareJidImageMap);
+ if(!file.open(QIODevice::ReadOnly))
+ return;
+
+ QString bareJid, imageHash;
+ while(!file.atEnd())
+ {
+ bareJid = file.readLine();
+ bareJid = bareJid.trimmed();
+ imageHash = file.readLine();
+ imageHash = imageHash.trimmed();
+ m_mapBareJidVCard[bareJid].imageHash = imageHash;
+ m_mapBareJidVCard[bareJid].image.load(
+ getSettingsDir() + m_mapBareJidVCard[bareJid].imageHash + "_scaled.png");
+ m_mapBareJidVCard[bareJid].imageOriginal.load(
+ getSettingsDir() + m_mapBareJidVCard[bareJid].imageHash + "_original.png");
+ QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ }
+ file.close();
+
+// QString fileBareJidImageMap = getSettingsDir() + m_client->configuration().getJidBare() + "_jidimage.xml";
+// QDomDocument doc(m_client->configuration().getJidBare() + "_jidimage");
+// QFile file(fileBareJidImageMap);
+//
+// if(!file.open(QIODevice::ReadOnly))
+// return;
+//
+// QString error;
+// if(m_domJidImage.setContent(&file, false, &error))
+// {
+// QDomElement nodeRecv = doc.documentElement().firstChildElement();
+// while(!nodeRecv.isNull())
+// {
+// m_mapBareJidVCard[nodeRecv.tagName()].imageHash = nodeRecv.text();
+// bool check = m_mapBareJidVCard[nodeRecv.tagName()].image.load(
+// getSettingsDir() + m_mapBareJidVCard[nodeRecv.tagName()].imageHash + "_scaled.png");
+// m_mapBareJidVCard[nodeRecv.tagName()].imageOriginal.load(
+// getSettingsDir() + m_mapBareJidVCard[nodeRecv.tagName()].imageHash + "_original.png");
+// nodeRecv = nodeRecv.nextSiblingElement();
+// }
+// }
+}
+
+QString vCardManager::getSelfFullName()
+{
+ return m_selfFullName;
+}
diff --git a/examples/GuiClient/vCardManager.h b/examples/GuiClient/vCardManager.h
new file mode 100644
index 00000000..55758362
--- /dev/null
+++ b/examples/GuiClient/vCardManager.h
@@ -0,0 +1,50 @@
+#ifndef VCARDMANAGER_H
+#define VCARDMANAGER_H
+
+#include <QObject>
+#include <QMap>
+#include <QImage>
+#include "QXmppVCard.h"
+
+// use sqlite
+
+class QXmppClient;
+
+class vCardManager : public QObject
+{
+ Q_OBJECT
+
+public:
+ class vCard
+ {
+ public:
+ QString imageHash;
+ QImage image;
+ QImage imageOriginal;
+ };
+
+ vCardManager(QXmppClient* client);
+ void requestVCard(const QString& bareJid);
+// bool isVCardReceived(const QString& bareJid);
+ bool isVCardAvailable(const QString& bareJid);
+
+ vCardManager::vCard& getVCard(const QString& bareJid);
+ void loadAllFromCache();
+ void saveToCache(const QString& bareJid);
+ QString getSelfFullName();
+
+signals:
+ void vCardReadyToUse(const QString& bareJid);
+
+public slots:
+ void vCardReceived(const QXmppVCard&);
+
+private:
+ QString m_selfFullName;
+ QXmppClient* m_client;
+
+// QMap<QString, QXmppVCard> m_mapBareJidVcard;
+ QMap<QString, vCardManager::vCard> m_mapBareJidVCard;
+};
+
+#endif // VCARDMANAGER_H