summaryrefslogtreecommitdiffstats
path: root/src/libcommuni/examples/client
diff options
context:
space:
mode:
authorMarkus Mittendrein <git@maxmitti.tk>2015-09-09 19:00:56 +0200
committerMarkus Mittendrein <git@maxmitti.tk>2015-09-09 19:02:23 +0200
commit8a6d4b06f2291c363f3dea17837ed20893852453 (patch)
treec091375499e35eaa1810586454e0834c06e6c9b2 /src/libcommuni/examples/client
parentf554a27046f203e56a07baaf214d90834942e3f5 (diff)
downloadmanager-8a6d4b06f2291c363f3dea17837ed20893852453.tar.gz
manager-8a6d4b06f2291c363f3dea17837ed20893852453.zip
Cleanup repo with some directories
Diffstat (limited to 'src/libcommuni/examples/client')
-rw-r--r--src/libcommuni/examples/client/client.pro16
-rw-r--r--src/libcommuni/examples/client/ircclient.cpp321
-rw-r--r--src/libcommuni/examples/client/ircclient.h78
-rw-r--r--src/libcommuni/examples/client/ircmessageformatter.cpp113
-rw-r--r--src/libcommuni/examples/client/ircmessageformatter.h31
-rw-r--r--src/libcommuni/examples/client/main.cpp20
6 files changed, 579 insertions, 0 deletions
diff --git a/src/libcommuni/examples/client/client.pro b/src/libcommuni/examples/client/client.pro
new file mode 100644
index 0000000..5e91b12
--- /dev/null
+++ b/src/libcommuni/examples/client/client.pro
@@ -0,0 +1,16 @@
+######################################################################
+# Communi
+######################################################################
+
+TEMPLATE = app
+TARGET = client
+DEPENDPATH += .
+INCLUDEPATH += .
+QT = core network gui
+greaterThan(QT_MAJOR_VERSION, 4):QT += widgets
+
+# Input
+HEADERS += ircclient.h ircmessageformatter.h
+SOURCES += ircclient.cpp ircmessageformatter.cpp main.cpp
+
+include(../examples.pri)
diff --git a/src/libcommuni/examples/client/ircclient.cpp b/src/libcommuni/examples/client/ircclient.cpp
new file mode 100644
index 0000000..c33043b
--- /dev/null
+++ b/src/libcommuni/examples/client/ircclient.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2008-2014 The Communi Project
+ *
+ * This example is free, and not covered by the BSD license. There is no
+ * restriction applied to their modification, redistribution, using and so on.
+ * You can study them, modify them, use them in your own program - either
+ * completely or partially.
+ */
+
+#include "ircclient.h"
+#include "ircmessageformatter.h"
+
+#include <QTextDocument>
+#include <QTextCursor>
+#include <QVBoxLayout>
+#include <QScrollBar>
+#include <QLineEdit>
+#include <QShortcut>
+#include <QListView>
+#include <QTextEdit>
+#include <QTime>
+
+#include <Irc>
+#include <IrcUser>
+#include <IrcBuffer>
+#include <IrcCommand>
+#include <IrcMessage>
+#include <IrcUserModel>
+#include <IrcCompleter>
+#include <IrcConnection>
+#include <IrcBufferModel>
+#include <IrcCommandParser>
+
+static const char* CHANNEL = "#communi";
+static const char* SERVER = "irc.freenode.net";
+
+IrcClient::IrcClient(QWidget* parent) : QSplitter(parent)
+{
+ createParser();
+ createConnection();
+ createCompleter();
+ createUserList();
+ createLayout();
+ createBufferList();
+
+ // queue a command to automatically join the channel when connected
+ connection->sendCommand(IrcCommand::createJoin(CHANNEL));
+ connection->open();
+
+ textEdit->append(IrcMessageFormatter::formatMessage(tr("! Welcome to the Communi %1 example client.").arg(IRC_VERSION_STR)));
+ textEdit->append(IrcMessageFormatter::formatMessage(tr("! This example connects %1 and joins %2.").arg(SERVER, CHANNEL)));
+ textEdit->append(IrcMessageFormatter::formatMessage(tr("! PS. Available commands: JOIN, ME, NICK, PART")));
+}
+
+IrcClient::~IrcClient()
+{
+ if (connection->isActive()) {
+ connection->quit(connection->realName());
+ connection->close();
+ }
+}
+
+void IrcClient::onConnected()
+{
+ textEdit->append(IrcMessageFormatter::formatMessage("! Connected to %1.").arg(SERVER));
+ textEdit->append(IrcMessageFormatter::formatMessage("! Joining %1...").arg(CHANNEL));
+}
+
+void IrcClient::onConnecting()
+{
+ textEdit->append(IrcMessageFormatter::formatMessage("! Connecting %1...").arg(SERVER));
+}
+
+void IrcClient::onDisconnected()
+{
+ textEdit->append(IrcMessageFormatter::formatMessage("! Disconnected from %1.").arg(SERVER));
+}
+
+void IrcClient::onTextEdited()
+{
+ // clear the possible error indication
+ lineEdit->setStyleSheet(QString());
+}
+
+void IrcClient::onTextEntered()
+{
+ QString input = lineEdit->text();
+ IrcCommand* command = parser->parse(input);
+ if (command) {
+ connection->sendCommand(command);
+
+ // echo own messages (servers do not send our own messages back)
+ if (command->type() == IrcCommand::Message || command->type() == IrcCommand::CtcpAction) {
+ IrcMessage* msg = command->toMessage(connection->nickName(), connection);
+ receiveMessage(msg);
+ delete msg;
+ }
+
+ lineEdit->clear();
+ } else if (input.length() > 1) {
+ QString error;
+ QString command = lineEdit->text().mid(1).split(" ", QString::SkipEmptyParts).value(0).toUpper();
+ if (parser->commands().contains(command))
+ error = tr("[ERROR] Syntax: %1").arg(parser->syntax(command).replace("<", "&lt;").replace(">", "&gt;"));
+ else
+ error = tr("[ERROR] Unknown command: %1").arg(command);
+ textEdit->append(IrcMessageFormatter::formatMessage(error));
+ lineEdit->setStyleSheet("background: salmon");
+ }
+}
+
+void IrcClient::onCompletion()
+{
+ completer->complete(lineEdit->text(), lineEdit->cursorPosition());
+}
+
+void IrcClient::onCompleted(const QString& text, int cursor)
+{
+ lineEdit->setText(text);
+ lineEdit->setCursorPosition(cursor);
+}
+
+void IrcClient::onBufferAdded(IrcBuffer* buffer)
+{
+ // joined a buffer - start listening to buffer specific messages
+ connect(buffer, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(receiveMessage(IrcMessage*)));
+
+ // create a document for storing the buffer specific messages
+ QTextDocument* document = new QTextDocument(buffer);
+ documents.insert(buffer, document);
+
+ // create a sorted model for buffer users
+ IrcUserModel* userModel = new IrcUserModel(buffer);
+ userModel->setSortMethod(Irc::SortByTitle);
+ userModels.insert(buffer, userModel);
+
+ // activate the new buffer
+ int idx = bufferModel->buffers().indexOf(buffer);
+ if (idx != -1)
+ bufferList->setCurrentIndex(bufferModel->index(idx));
+}
+
+void IrcClient::onBufferRemoved(IrcBuffer* buffer)
+{
+ // the buffer specific models and documents are no longer needed
+ delete userModels.take(buffer);
+ delete documents.take(buffer);
+}
+
+void IrcClient::onBufferActivated(const QModelIndex& index)
+{
+ IrcBuffer* buffer = index.data(Irc::BufferRole).value<IrcBuffer*>();
+
+ // document, user list and nick completion for the current buffer
+ textEdit->setDocument(documents.value(buffer));
+ textEdit->verticalScrollBar()->triggerAction(QScrollBar::SliderToMaximum);
+ userList->setModel(userModels.value(buffer));
+ completer->setBuffer(buffer);
+
+ // keep the command parser aware of the context
+ if (buffer)
+ parser->setTarget(buffer->title());
+}
+
+void IrcClient::onUserActivated(const QModelIndex& index)
+{
+ IrcUser* user = index.data(Irc::UserRole).value<IrcUser*>();
+
+ if (user) {
+ IrcBuffer* buffer = bufferModel->add(user->name());
+
+ // activate the new query
+ int idx = bufferModel->buffers().indexOf(buffer);
+ if (idx != -1)
+ bufferList->setCurrentIndex(bufferModel->index(idx));
+ }
+}
+
+static void appendHtml(QTextDocument* document, const QString& html)
+{
+ QTextCursor cursor(document);
+ cursor.beginEditBlock();
+ cursor.movePosition(QTextCursor::End);
+ if (!document->isEmpty())
+ cursor.insertBlock();
+ cursor.insertHtml(html);
+ cursor.endEditBlock();
+}
+
+void IrcClient::receiveMessage(IrcMessage* message)
+{
+ IrcBuffer* buffer = qobject_cast<IrcBuffer*>(sender());
+ if (!buffer)
+ buffer = bufferList->currentIndex().data(Irc::BufferRole).value<IrcBuffer*>();
+
+ QTextDocument* document = documents.value(buffer);
+ if (document) {
+ QString html = IrcMessageFormatter::formatMessage(message);
+ if (!html.isEmpty()) {
+ if (document == textEdit->document())
+ textEdit->append(html);
+ else
+ appendHtml(document, html);
+ }
+ }
+}
+
+void IrcClient::createLayout()
+{
+ setWindowTitle(tr("Communi %1 example client").arg(IRC_VERSION_STR));
+
+ // a read-only text editor for showing the messages
+ textEdit = new QTextEdit(this);
+ textEdit->setReadOnly(true);
+
+ // a line editor for entering commands
+ lineEdit = new QLineEdit(this);
+ lineEdit->setAttribute(Qt::WA_MacShowFocusRect, false);
+ textEdit->setFocusProxy(lineEdit);
+ connect(lineEdit, SIGNAL(returnPressed()), this, SLOT(onTextEntered()));
+ connect(lineEdit, SIGNAL(textEdited(QString)), this, SLOT(onTextEdited()));
+
+ // the rest is just setting up the UI layout...
+ QSplitter* splitter = new QSplitter(this);
+ splitter->setHandleWidth(1);
+ splitter->addWidget(textEdit);
+ splitter->addWidget(userList);
+ splitter->setStretchFactor(0, 5);
+ splitter->setStretchFactor(1, 1);
+
+ QWidget* container = new QWidget(this);
+ QVBoxLayout* layout = new QVBoxLayout(container);
+ layout->setSpacing(0);
+ layout->setMargin(0);
+ layout->addWidget(splitter);
+ layout->addWidget(lineEdit);
+
+ addWidget(container);
+
+ setHandleWidth(1);
+}
+
+void IrcClient::createCompleter()
+{
+ // nick name completion
+ completer = new IrcCompleter(this);
+ completer->setParser(parser);
+ connect(completer, SIGNAL(completed(QString,int)), this, SLOT(onCompleted(QString,int)));
+
+ QShortcut* shortcut = new QShortcut(Qt::Key_Tab, this);
+ connect(shortcut, SIGNAL(activated()), this, SLOT(onCompletion()));
+}
+
+void IrcClient::createParser()
+{
+ // create a command parser and teach it some commands. notice also
+ // that we must keep the command parser aware of the context in
+ // createUi() and onBufferActivated()
+
+ parser = new IrcCommandParser(this);
+ parser->setTolerant(true);
+ parser->setTriggers(QStringList("/"));
+ parser->addCommand(IrcCommand::Join, "JOIN <#channel> (<key>)");
+ parser->addCommand(IrcCommand::CtcpAction, "ME [target] <message...>");
+ parser->addCommand(IrcCommand::Mode, "MODE (<channel/user>) (<mode>) (<arg>)");
+ parser->addCommand(IrcCommand::Nick, "NICK <nick>");
+ parser->addCommand(IrcCommand::Part, "PART (<#channel>) (<message...>)");
+}
+
+void IrcClient::createUserList()
+{
+ // a list of channel users
+ userList = new QListView(this);
+ userList->setFocusPolicy(Qt::NoFocus);
+
+ // open a private query when double clicking a user
+ connect(userList, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(onUserActivated(QModelIndex)));
+}
+
+void IrcClient::createBufferList()
+{
+ bufferModel = new IrcBufferModel(connection);
+ connect(bufferModel, SIGNAL(added(IrcBuffer*)), this, SLOT(onBufferAdded(IrcBuffer*)));
+ connect(bufferModel, SIGNAL(removed(IrcBuffer*)), this, SLOT(onBufferRemoved(IrcBuffer*)));
+
+ bufferList = new QListView(this);
+ bufferList->setFocusPolicy(Qt::NoFocus);
+ bufferList->setModel(bufferModel);
+
+ // keep the command parser aware of the context
+ connect(bufferModel, SIGNAL(channelsChanged(QStringList)), parser, SLOT(setChannels(QStringList)));
+
+ // keep track of the current buffer, see also onBufferActivated()
+ connect(bufferList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(onBufferActivated(QModelIndex)));
+
+ // create a server buffer for non-targeted messages...
+ IrcBuffer* serverBuffer = bufferModel->add(connection->host());
+
+ // ...and connect it to IrcBufferModel::messageIgnored()
+ connect(bufferModel, SIGNAL(messageIgnored(IrcMessage*)), serverBuffer, SLOT(receiveMessage(IrcMessage*)));
+
+ insertWidget(0, bufferList);
+
+ setStretchFactor(0, 1);
+ setStretchFactor(1, 3);
+}
+
+void IrcClient::createConnection()
+{
+ connection = new IrcConnection(this);
+ connect(connection, SIGNAL(connected()), this, SLOT(onConnected()));
+ connect(connection, SIGNAL(connecting()), this, SLOT(onConnecting()));
+ connect(connection, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
+
+ qsrand(QTime::currentTime().msec());
+
+ connection->setHost(SERVER);
+ connection->setUserName("communi");
+ connection->setNickName(tr("Client%1").arg(qrand() % 9999));
+ connection->setRealName(tr("Communi %1 example client").arg(IRC_VERSION_STR));
+}
diff --git a/src/libcommuni/examples/client/ircclient.h b/src/libcommuni/examples/client/ircclient.h
new file mode 100644
index 0000000..9d6ee3c
--- /dev/null
+++ b/src/libcommuni/examples/client/ircclient.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2008-2014 The Communi Project
+ *
+ * This example is free, and not covered by the BSD license. There is no
+ * restriction applied to their modification, redistribution, using and so on.
+ * You can study them, modify them, use them in your own program - either
+ * completely or partially.
+ */
+
+#ifndef IRCCLIENT_H
+#define IRCCLIENT_H
+
+#include <QSplitter>
+#include <QHash>
+
+class IrcBuffer;
+class IrcMessage;
+class IrcUserModel;
+class IrcCompleter;
+class IrcConnection;
+class IrcBufferModel;
+class IrcCommandParser;
+
+QT_FORWARD_DECLARE_CLASS(QLineEdit)
+QT_FORWARD_DECLARE_CLASS(QListView)
+QT_FORWARD_DECLARE_CLASS(QTextEdit)
+QT_FORWARD_DECLARE_CLASS(QModelIndex)
+QT_FORWARD_DECLARE_CLASS(QTextDocument)
+
+class IrcClient : public QSplitter
+{
+ Q_OBJECT
+
+public:
+ IrcClient(QWidget* parent = 0);
+ ~IrcClient();
+
+private slots:
+ void onConnected();
+ void onConnecting();
+ void onDisconnected();
+
+ void onTextEdited();
+ void onTextEntered();
+
+ void onCompletion();
+ void onCompleted(const QString& text, int cursor);
+
+ void onBufferAdded(IrcBuffer* buffer);
+ void onBufferRemoved(IrcBuffer* buffer);
+
+ void onBufferActivated(const QModelIndex& index);
+ void onUserActivated(const QModelIndex& index);
+
+ void receiveMessage(IrcMessage* message);
+
+private:
+ void createLayout();
+ void createCompleter();
+ void createParser();
+ void createUserList();
+ void createBufferList();
+ void createConnection();
+
+ QLineEdit* lineEdit;
+ QTextEdit* textEdit;
+ QListView* userList;
+ QListView* bufferList;
+
+ IrcCompleter* completer;
+ IrcCommandParser* parser;
+ IrcConnection* connection;
+ IrcBufferModel* bufferModel;
+ QHash<IrcBuffer*, IrcUserModel*> userModels;
+ QHash<IrcBuffer*, QTextDocument*> documents;
+};
+
+#endif // IRCCLIENT_H
diff --git a/src/libcommuni/examples/client/ircmessageformatter.cpp b/src/libcommuni/examples/client/ircmessageformatter.cpp
new file mode 100644
index 0000000..6537664
--- /dev/null
+++ b/src/libcommuni/examples/client/ircmessageformatter.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2008-2014 The Communi Project
+ *
+ * This example is free, and not covered by the BSD license. There is no
+ * restriction applied to their modification, redistribution, using and so on.
+ * You can study them, modify them, use them in your own program - either
+ * completely or partially.
+ */
+
+#include "ircmessageformatter.h"
+
+#include <IrcTextFormat>
+#include <IrcConnection>
+#include <QTime>
+#include <Irc>
+
+QString IrcMessageFormatter::formatMessage(IrcMessage* message)
+{
+ QString formatted;
+ switch (message->type()) {
+ case IrcMessage::Join:
+ formatted = formatJoinMessage(static_cast<IrcJoinMessage*>(message));
+ break;
+ case IrcMessage::Mode:
+ formatted = formatModeMessage(static_cast<IrcModeMessage*>(message));
+ break;
+ case IrcMessage::Names:
+ formatted = formatNamesMessage(static_cast<IrcNamesMessage*>(message));
+ break;
+ case IrcMessage::Nick:
+ formatted = formatNickMessage(static_cast<IrcNickMessage*>(message));
+ break;
+ case IrcMessage::Part:
+ formatted = formatPartMessage(static_cast<IrcPartMessage*>(message));
+ break;
+ case IrcMessage::Private:
+ formatted = formatPrivateMessage(static_cast<IrcPrivateMessage*>(message));
+ break;
+ case IrcMessage::Quit:
+ formatted = formatQuitMessage(static_cast<IrcQuitMessage*>(message));
+ break;
+ default:
+ break;
+ }
+ return formatMessage(formatted);
+}
+
+QString IrcMessageFormatter::formatMessage(const QString& message)
+{
+ if (!message.isEmpty()) {
+ QString formatted = QObject::tr("[%1] %2").arg(QTime::currentTime().toString(), message);
+ if (message.startsWith("!"))
+ formatted = QObject::tr("<font color='gray'>%1</font>").arg(formatted);
+ else if (message.startsWith("*"))
+ formatted = QObject::tr("<font color='maroon'>%1</font>").arg(formatted);
+ else if (message.startsWith("["))
+ formatted = QObject::tr("<font color='indianred'>%1</font>").arg(formatted);
+ return formatted;
+ }
+ return QString();
+}
+
+QString IrcMessageFormatter::formatJoinMessage(IrcJoinMessage* message)
+{
+ if (message->flags() & IrcMessage::Own)
+ return QObject::tr("! You have joined %1 as %2").arg(message->channel(), message->nick());
+ else
+ return QObject::tr("! %1 has joined %2").arg(message->nick(), message->channel());
+}
+
+QString IrcMessageFormatter::formatModeMessage(IrcModeMessage* message)
+{
+ QString args = message->arguments().join(" ");
+ if (message->isReply())
+ return QObject::tr("! %1 mode is %2 %3").arg(message->target(), message->mode(), args);
+ else
+ return QObject::tr("! %1 sets mode %2 %3 %4").arg(message->nick(), message->target(), message->mode(), args);
+}
+
+QString IrcMessageFormatter::formatNamesMessage(IrcNamesMessage* message)
+{
+ return QObject::tr("! %1 has %2 users").arg(message->channel()).arg(message->names().count());
+}
+
+QString IrcMessageFormatter::formatNickMessage(IrcNickMessage* message)
+{
+ return QObject::tr("! %1 has changed nick to %2").arg(message->oldNick(), message->newNick());
+}
+
+QString IrcMessageFormatter::formatPartMessage(IrcPartMessage* message)
+{
+ if (message->reason().isEmpty())
+ return QObject::tr("! %1 has left %2").arg(message->nick(), message->channel());
+ else
+ return QObject::tr("! %1 has left %2 (%3)").arg(message->nick(), message->channel(), message->reason());
+}
+
+QString IrcMessageFormatter::formatPrivateMessage(IrcPrivateMessage* message)
+{
+ const QString content = IrcTextFormat().toHtml(message->content());
+ if (message->isAction())
+ return QObject::tr("* %1 %2").arg(message->nick(), content);
+ else
+ return QObject::tr("&lt;%1&gt; %2").arg(message->nick(),content);
+}
+
+QString IrcMessageFormatter::formatQuitMessage(IrcQuitMessage* message)
+{
+ if (message->reason().isEmpty())
+ return QObject::tr("! %1 has quit").arg(message->nick());
+ else
+ return QObject::tr("! %1 has quit (%2)").arg(message->nick(), message->reason());
+}
diff --git a/src/libcommuni/examples/client/ircmessageformatter.h b/src/libcommuni/examples/client/ircmessageformatter.h
new file mode 100644
index 0000000..f91be50
--- /dev/null
+++ b/src/libcommuni/examples/client/ircmessageformatter.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008-2014 The Communi Project
+ *
+ * This example is free, and not covered by the BSD license. There is no
+ * restriction applied to their modification, redistribution, using and so on.
+ * You can study them, modify them, use them in your own program - either
+ * completely or partially.
+ */
+
+#ifndef IRCMESSAGEFORMATTER_H
+#define IRCMESSAGEFORMATTER_H
+
+#include <IrcMessage>
+
+class IrcMessageFormatter
+{
+public:
+ static QString formatMessage(IrcMessage* message);
+ static QString formatMessage(const QString& message);
+
+private:
+ static QString formatJoinMessage(IrcJoinMessage* message);
+ static QString formatModeMessage(IrcModeMessage* message);
+ static QString formatNamesMessage(IrcNamesMessage* message);
+ static QString formatNickMessage(IrcNickMessage* message);
+ static QString formatPartMessage(IrcPartMessage* message);
+ static QString formatPrivateMessage(IrcPrivateMessage* message);
+ static QString formatQuitMessage(IrcQuitMessage* message);
+};
+
+#endif // IRCMESSAGEFORMATTER_H
diff --git a/src/libcommuni/examples/client/main.cpp b/src/libcommuni/examples/client/main.cpp
new file mode 100644
index 0000000..951ee91
--- /dev/null
+++ b/src/libcommuni/examples/client/main.cpp
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2008-2014 The Communi Project
+ *
+ * This example is free, and not covered by the BSD license. There is no
+ * restriction applied to their modification, redistribution, using and so on.
+ * You can study them, modify them, use them in your own program - either
+ * completely or partially.
+ */
+
+#include <QApplication>
+#include "ircclient.h"
+
+int main(int argc, char* argv[])
+{
+ QApplication app(argc, argv);
+ IrcClient client;
+ client.resize(800, 480);
+ client.show();
+ return app.exec();
+}