13501
|
1 /* Quint - A graphical user interface for Octave |
|
2 * Copyright (C) 2011 Jacob Dawid |
|
3 * jacob.dawid@googlemail.com |
|
4 * |
|
5 * This program is free software: you can redistribute it and/or modify |
|
6 * it under the terms of the GNU General Public License as published by |
|
7 * the Free Software Foundation, either version 3 of the License, or |
|
8 * (at your option) any later version. |
|
9 * |
|
10 * This program 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 |
|
13 * GNU General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License |
|
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
17 */ |
|
18 |
|
19 #include "IRCWidget.h" |
|
20 #include <QMessageBox> |
|
21 #include <QHBoxLayout> |
|
22 #include <QVBoxLayout> |
|
23 #include <QLabel> |
|
24 #include <QSettings> |
|
25 #include <QInputDialog> |
|
26 |
|
27 IRCWidget::IRCWidget(QWidget *parent, QString settingsFile) : |
|
28 QWidget(parent) |
|
29 { |
|
30 m_settingsFile = settingsFile; |
|
31 m_alternatingColor = false; |
|
32 QSettings settings(m_settingsFile, QSettings::IniFormat); |
|
33 bool connectOnStartup = settings.value("connectOnStartup").toBool(); |
|
34 m_autoIdentification = settings.value("autoIdentification").toBool(); |
|
35 m_nickServPassword = settings.value("nickServPassword").toString(); |
|
36 |
|
37 m_initialNick = settings.value("IRCNick").toString(); |
|
38 |
|
39 if(m_initialNick.isEmpty()) |
|
40 m_initialNick = "OctaveGUI-User"; |
|
41 |
|
42 QVBoxLayout *layout = new QVBoxLayout(); |
|
43 |
|
44 m_chatWindow = new QTextEdit(this); |
|
45 m_chatWindow->setReadOnly(true); |
|
46 m_chatWindow->setEnabled(false); |
|
47 QWidget* bottomWidget = new QWidget(this); |
|
48 |
|
49 layout->addWidget(m_chatWindow); |
|
50 layout->addWidget(bottomWidget); |
|
51 setLayout(layout); |
|
52 |
|
53 QHBoxLayout *bottomLayout = new QHBoxLayout(); |
|
54 m_nickButton = new QPushButton(bottomWidget); |
|
55 m_nickButton->setStatusTip(tr((char*)"Click here to change your nick.")); |
|
56 m_nickButton->setText(m_initialNick); |
|
57 m_inputLine = new QLineEdit(bottomWidget); |
|
58 m_inputLine->setStatusTip(tr((char*)"Enter your message here.")); |
|
59 bottomLayout->addWidget(m_nickButton); |
|
60 bottomLayout->addWidget(new QLabel(":", this)); |
|
61 bottomLayout->addWidget(m_inputLine); |
|
62 bottomLayout->setMargin(0); |
|
63 bottomWidget->setLayout(bottomLayout); |
|
64 m_nickButton->setEnabled(false); |
|
65 m_inputLine->setEnabled(false); |
|
66 |
|
67 m_chatWindow->setFocusProxy(m_inputLine); |
|
68 m_nickButton->setFocusProxy(m_inputLine); |
|
69 |
|
70 QFont font; |
|
71 font.setFamily("Courier"); |
|
72 font.setPointSize(11); |
|
73 m_chatWindow->setFont(font); |
|
74 m_ircClient = new IRCClient(); |
|
75 |
|
76 connect(m_nickButton, SIGNAL(clicked()), this, SLOT(nickPopup())); |
|
77 connect(m_inputLine, SIGNAL(returnPressed()), this, SLOT(sendInputLine())); |
|
78 |
|
79 connect(m_ircClient, SIGNAL(nickInUseChanged()), this, SLOT(handleNickInUseChanged())); |
|
80 connect(m_ircClient, SIGNAL(connectionStatus(const char*)), this, SLOT(showStatusMessage(const char*))); |
|
81 connect(m_ircClient, SIGNAL(error(const char*)), this, SLOT(showStatusMessage(const char*))); |
|
82 connect(m_ircClient, SIGNAL(completedLogin(const char*)), this, SLOT(loginSuccessful(const char*))); |
|
83 connect(m_ircClient, SIGNAL(completedLogin(const char*)), this, SLOT(joinOctaveChannel(const char*))); |
|
84 connect(m_ircClient, SIGNAL(topic(const char*,const char*,const char*)), this, SLOT(showTopic(const char*,const char*,const char*))); |
|
85 connect(m_ircClient, SIGNAL(join(const char*,const char*)), this, SLOT(showJoin(const char*, const char*))); |
|
86 connect(m_ircClient, SIGNAL(quit(const char*,const char*)), this, SLOT(showQuit(const char*,const char*))); |
|
87 connect(m_ircClient, SIGNAL(privateMessage(const char*,const char*,const char*)), this, SLOT(showPrivateMessage(const char*,const char*,const char*))); |
|
88 connect(m_ircClient, SIGNAL(notice(const char*,const char*,const char*)), this, SLOT(showNotice(const char*,const char*,const char*))); |
|
89 connect(m_ircClient, SIGNAL(nick(const char*,const char*)), this, SLOT(showNickChange(const char*, const char*))); |
|
90 connect(m_ircClient, SIGNAL(replyCode(IRCEvent*)), this, SLOT(handleReplyCode(IRCEvent*))); |
|
91 |
|
92 if(connectOnStartup) |
|
93 connectToServer(); |
|
94 } |
|
95 |
|
96 void IRCWidget::connectToServer() { |
|
97 m_ircClient->connectToServer("irc.freenode.net", 6667, |
|
98 m_initialNick.toStdString().c_str(), |
|
99 m_initialNick.toStdString().c_str(), |
|
100 "Unknown", "Unknown", 0, 0); |
|
101 } |
|
102 |
|
103 void IRCWidget::showStatusMessage(const char *message) { |
|
104 m_chatWindow->append(QString("<i>%1</i>").arg(message)); |
|
105 } |
|
106 |
|
107 void IRCWidget::joinOctaveChannel(const char*) { |
|
108 m_ircClient->joinChannel("#octave"); |
|
109 } |
|
110 |
|
111 void IRCWidget::loginSuccessful(const char *nick) { |
|
112 m_chatWindow->append(QString("<i><font color=\"#00AA00\"><b>Successfully logged in as %1.</b></font></i>").arg(nick)); |
|
113 m_nickButton->setEnabled(true); |
|
114 m_inputLine->setEnabled(true); |
|
115 m_chatWindow->setEnabled(true); |
|
116 m_inputLine->setFocus(); |
|
117 |
|
118 if(m_autoIdentification) |
|
119 m_ircClient->sendCommand(2, COMMAND_PRIVMSG, |
|
120 "NickServ", |
|
121 QString("identify %1").arg(m_nickServPassword).toStdString().c_str()); |
|
122 } |
|
123 |
|
124 void IRCWidget::showPrivateMessage(const char *nick, const char *destination, const char *message) { |
|
125 Q_UNUSED(destination); |
|
126 QString msg(message); |
|
127 if(msg.contains(m_ircClient->nickInUse())) { |
|
128 msg = QString("<font color=\"#990000\"><b>%1:</b> %2</font>").arg(nick).arg(msg); |
|
129 } else { |
|
130 msg = QString("<font color=\"%3\"><b>%1:</b> %2</font>").arg(nick).arg(msg).arg(getAlternatingColor()); |
|
131 } |
|
132 m_chatWindow->append(msg); |
|
133 } |
|
134 |
|
135 void IRCWidget::showNotice(const char *nick, const char *destination, const char *message) { |
|
136 Q_UNUSED(nick); |
|
137 Q_UNUSED(destination); |
|
138 m_chatWindow->append(QString("<font color=\"#007700\">%1</font>").arg(message)); |
|
139 } |
|
140 |
|
141 void IRCWidget::showTopic(const char *nick, const char *channel, const char *message) { |
|
142 m_chatWindow->append(QString("Topic for %2 was set by %1: %3").arg(nick).arg(channel).arg(message)); |
|
143 } |
|
144 |
|
145 void IRCWidget::showNickChange(const char *oldNick, const char *newNick) { |
|
146 m_chatWindow->append(QString("%1 is now known as %2.").arg(oldNick).arg(newNick)); |
|
147 m_nickList.removeAll(QString(oldNick)); |
|
148 m_nickList.append(QString(newNick)); |
|
149 } |
|
150 |
|
151 void IRCWidget::nickPopup() { |
|
152 bool ok; |
|
153 QString newNick = QInputDialog::getText(this, QString("Nickname"), QString("Type in your nickname:"), |
|
154 QLineEdit::Normal, m_ircClient->nickInUse(), &ok); |
|
155 if(ok) { |
|
156 m_ircClient->sendNickChange(newNick); |
|
157 } |
|
158 } |
|
159 |
|
160 void IRCWidget::showJoin(const char *nick, const char *channel) { |
|
161 m_chatWindow->append(QString("<i>%1 has joined %2.</i>").arg(nick).arg(channel)); |
|
162 } |
|
163 |
|
164 void IRCWidget::showQuit(const char *nick, const char *reason) { |
|
165 m_chatWindow->append(QString("<i>%1 has quit.(%2).</i>").arg(nick).arg(reason)); |
|
166 } |
|
167 |
|
168 void IRCWidget::sendMessage(QString message) { |
|
169 // Do not send empty messages. |
|
170 if(message.isEmpty()) |
|
171 return; |
|
172 |
|
173 // Remove trailing spaces. |
|
174 while(message.at(0).isSpace()) message.remove(0, 1); |
|
175 if(message.startsWith("/")) { |
|
176 QStringList line = message.split(QRegExp("\\s+"), QString::SkipEmptyParts); |
|
177 if(line.at(0) == "/join") { |
|
178 m_ircClient->joinChannel(line.at(1)); |
|
179 } else if(line.at(0) == "/nick") { |
|
180 m_ircClient->sendNickChange(line.at(1)); |
|
181 } else if(line.at(0) == "/msg") { |
|
182 QString recipient = line.at(1); |
|
183 // Since we splitted the message before, we have to glue it together again. |
|
184 QString pmsg = ""; |
|
185 for(int i=2; i < line.length(); i++) { |
|
186 pmsg += line.at(i); |
|
187 pmsg += " "; |
|
188 } |
|
189 m_ircClient->sendCommand(2, COMMAND_PRIVMSG, |
|
190 recipient.toStdString().c_str(), |
|
191 pmsg.toStdString().c_str()); |
|
192 } |
|
193 } else { |
|
194 m_ircClient->sendPublicMessage(message); |
|
195 m_chatWindow->append(QString("<b>%1:</b> %2").arg(m_ircClient->nickInUse()).arg(message)); |
|
196 } |
|
197 } |
|
198 |
|
199 void IRCWidget::sendInputLine() { |
|
200 sendMessage(m_inputLine->text()); |
|
201 m_inputLine->setText(""); |
|
202 } |
|
203 |
|
204 void IRCWidget::handleNickInUseChanged() { |
|
205 m_nickButton->setText(m_ircClient->nickInUse()); |
|
206 QSettings settings(m_settingsFile, QSettings::IniFormat); |
|
207 settings.setValue("IRCNick", m_ircClient->nickInUse()); |
|
208 } |
|
209 |
|
210 void IRCWidget::handleReplyCode(IRCEvent *event) { |
|
211 QSettings settings(m_settingsFile, QSettings::IniFormat); |
|
212 |
|
213 switch(event->getNumeric()) { |
|
214 case RPL_MOTDSTART: |
|
215 case RPL_MOTD: |
|
216 case ERR_NOMOTD: |
|
217 case RPL_ENDOFMOTD: |
|
218 if(settings.value("showMessageOfTheDay").toBool()) |
|
219 m_chatWindow->append(QString("<font color=\"#777777\">%1</font>").arg(event->getParam(1))); |
|
220 break; |
|
221 case RPL_NOTOPIC: |
|
222 case RPL_TOPIC: |
|
223 if(settings.value("showTopic").toBool()) |
|
224 m_chatWindow->append(QString("<font color=\"#000088\"><b>%1</b></font>").arg(event->getParam(2))); |
|
225 break; |
|
226 case RPL_NAMREPLY: |
|
227 m_chatWindow->append(QString("<font color=\"#000088\">Users online: %1</font>").arg(event->getParam(3))); |
|
228 m_nickList = event->getParam(3).split(QRegExp("\\s+"), QString::SkipEmptyParts); |
|
229 updateNickCompleter(); |
|
230 break; |
|
231 case ERR_NICKNAMEINUSE: |
|
232 case ERR_NICKCOLLISION: |
|
233 m_chatWindow->append(QString("<font color=\"#AA0000\">Nickname in use.</font>")); |
|
234 break; |
|
235 }; |
|
236 } |
|
237 |
|
238 |
|
239 void IRCWidget::updateNickCompleter() { |
|
240 QCompleter *completer = new QCompleter(m_nickList, this); |
|
241 completer->setCompletionMode(QCompleter::InlineCompletion); |
|
242 m_inputLine->setCompleter(completer); |
|
243 } |