ircchatadapter.cpp
1 //------------------------------------------------------------------------------
2 // ircchatadapter.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2010 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "ircchatadapter.h"
24 
25 #include "irc/ircnetworkadapter.h"
26 #include "utf8splitter.h"
27 
28 IRCChatAdapter::IRCChatAdapter(IRCNetworkAdapter *pNetwork, const QString &recipient)
29 {
30  this->pNetwork = pNetwork;
31  this->recipientName = recipient;
32 }
33 
34 IRCChatAdapter::~IRCChatAdapter()
35 {
36  if (this->pNetwork != nullptr)
37  {
38  // Prevent the situation where this->pNetwork is
39  // NULLified while we still may need it.
40  IRCNetworkAdapter *pTmpNetwork = this->pNetwork;
41 
42  pTmpNetwork->detachChatWindow(this);
43  }
44 }
45 
46 void IRCChatAdapter::doSendMessage(const QString &message, IRCAdapterBase *pOrigin)
47 {
48  Q_UNUSED(pOrigin);
49  // If network is null and we can still send messages this might be a bug
50  // in the application.
51  if (pNetwork == nullptr)
52  {
53  emit error("This chat window is not attached to any network. This is probably a bug in Doomseeker.");
54  return;
55  }
56 
57  // Trim whitespaces to make sure the '/' character gets detected properly.
58  QString messageTrimmed = message.trimmed();
59 
60  if (messageTrimmed.startsWith("/"))
61  {
62  // This is a IRC comand. Send it as is to the network.
63  pNetwork->doSendMessage(messageTrimmed, this);
64  }
65  else
66  {
67  // This is a chat message. We need to process this before
68  // sending.
69  sendChatMessage(messageTrimmed);
70  }
71 }
72 
73 void IRCChatAdapter::emitChatMessage(const QString &sender, const QString &content)
74 {
75  emit message(QString("<%1>: %2").arg(sender, content));
76 }
77 
78 QString IRCChatAdapter::extractMessageLine(QStringList &words, int maxLength)
79 {
80  QByteArray sentence = "";
81  while (!words.isEmpty())
82  {
83  QByteArray word = words.takeFirst().toUtf8();
84 
85  // Remember to add the spacebar into the equation.
86  if (sentence.length() + word.length() + 1 > maxLength)
87  {
88  // If there is no valid way of splitting the sentence; if
89  // the word itself is longer than maxLength we have to split
90  // the word. Dash will be appended to the end of such word.
91  if (sentence.isEmpty())
92  {
93  // We need to split the word.
94  QList<QByteArray> splitWordTokens = Utf8Splitter().split(word, maxLength);
95 
96  sentence = splitWordTokens.takeFirst();
97  sentence += '-';
98 
99  QString wordRemainder = "";
100  for (const QByteArray &wordToken : splitWordTokens)
101  {
102  wordRemainder += QString::fromUtf8(wordToken.constData(), wordToken.size());
103  }
104  words.prepend(wordRemainder);
105  }
106  else
107  {
108  // Put the word back on the list, we'll come back to it
109  // in the next line of the message.
110  words.prepend(QString::fromUtf8(word.constData(), word.size()));
111  }
112 
113  break;
114  }
115 
116  sentence += word + " ";
117  }
118  return QString::fromUtf8(sentence.constData(), sentence.size()).trimmed();
119 }
120 
121 void IRCChatAdapter::sendChatMessage(const QString &message)
122 {
123  // Here we will split too long messages to make sure they don't
124  // exceed the 512 character limit as stated in RFC 1459.
125 
126  // NOTE: Messages are echoed back through IRCRequestParser
127 
128  QString ircCall = QString("/PRIVMSG %1 ").arg(recipientName);
129  int maxLength = IRCClient::SAFE_MESSAGE_LENGTH - ircCall.toUtf8().length();
130  QStringList wordLines = message.split("\n");
131 
132  for (QString line : wordLines)
133  {
134  QStringList words = line.split(" ");
135 
136  while (!words.isEmpty())
137  {
138  QString sentence = extractMessageLine(words, maxLength);
139  pNetwork->doSendMessage(ircCall + sentence, this);
140  }
141  }
142 }
143 
145 {
146  this->pNetwork = pNetwork;
147 }
148 
149 void IRCChatAdapter::setRecipient(const QString &name)
150 {
151  this->recipientName = name;
152  emit titleChange();
153 }
154 
155 QString IRCChatAdapter::title() const
156 {
157  return recipientName;
158 }