Mercurial > octave-nkf
changeset 13678:117ae3cb156e
Shifted IRCWidget.
author | Jacob Dawid <jacob.dawid@googlemail.com> |
---|---|
date | Sun, 25 Sep 2011 21:12:47 +0200 |
parents | f27573828e92 |
children | e272af3f252d |
files | gui/octave-gui.pro gui/src/HistoryDockWidget.cpp gui/src/HistoryDockWidget.h gui/src/IRCWidget.cpp gui/src/IRCWidget.h gui/src/VariablesDockWidget.cpp gui/src/VariablesDockWidget.h gui/src/qirc/IRCWidget.cpp gui/src/qirc/IRCWidget.h |
diffstat | 9 files changed, 575 insertions(+), 591 deletions(-) [+] |
line wrap: on
line diff
--- a/gui/octave-gui.pro Sun Sep 25 18:29:24 2011 +0200 +++ b/gui/octave-gui.pro Sun Sep 25 21:12:47 2011 +0200 @@ -65,7 +65,7 @@ src/FileEditorMdiSubWindow.cpp \ src/BrowserWidget.cpp \ src/ImageViewerMdiSubWindow.cpp \ - src/IRCWidget.cpp \ + src/qirc/IRCWidget.cpp \ src/SettingsDialog.cpp \ src/OctaveGUI.cpp \ src/ResourceManager.cpp \ @@ -92,7 +92,7 @@ src/FileEditorMdiSubWindow.h \ src/BrowserWidget.h \ src/ImageViewerMdiSubWindow.h \ - src/IRCWidget.h \ + src/qirc/IRCWidget.h \ src/SettingsDialog.h \ src/ResourceManager.h \ src/CommandLineParser.h \
--- a/gui/src/HistoryDockWidget.cpp Sun Sep 25 18:29:24 2011 +0200 +++ b/gui/src/HistoryDockWidget.cpp Sun Sep 25 21:12:47 2011 +0200 @@ -63,12 +63,6 @@ } void -HistoryDockWidget::noticeSettings () -{ - -} - -void HistoryDockWidget::handleDoubleClick (QModelIndex modelIndex) { emit commandDoubleClicked (modelIndex.data().toString());
--- a/gui/src/HistoryDockWidget.h Sun Sep 25 18:29:24 2011 +0200 +++ b/gui/src/HistoryDockWidget.h Sun Sep 25 21:12:47 2011 +0200 @@ -32,8 +32,6 @@ void updateHistory (QStringList history); public slots: - /** Tells the widget to notice settings that are probably new. */ - void noticeSettings (); void handleVisibilityChanged (bool visible); signals:
--- a/gui/src/IRCWidget.cpp Sun Sep 25 18:29:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,448 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "ResourceManager.h" -#include "IRCWidget.h" -#include <QMessageBox> -#include <QHBoxLayout> -#include <QVBoxLayout> -#include <QLabel> -#include <QSettings> -#include <QInputDialog> -#include <QKeyEvent> -#include <QScrollBar> -#include <QApplication> -#include "IRCClientImpl.h" - -ChatMessageTextEdit::ChatMessageTextEdit (QWidget *parent) - : QPlainTextEdit (parent), m_completer (0) -{ - setMaximumHeight (50); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); -} - -ChatMessageTextEdit::~ChatMessageTextEdit () -{ -} - -void -ChatMessageTextEdit::setCompleter (QCompleter *completer) -{ - if (m_completer) - QObject::disconnect (m_completer, 0, this, 0); - - m_completer = completer; - - if (!m_completer) - return; - - m_completer->setWidget (this); - m_completer->setCompletionMode (QCompleter::PopupCompletion); - m_completer->setCaseSensitivity (Qt::CaseInsensitive); - QObject::connect (m_completer, SIGNAL (activated (QString)), - this, SLOT (insertCompletion (QString))); -} - -QCompleter * -ChatMessageTextEdit::completer () const -{ - return m_completer; -} - -void -ChatMessageTextEdit::insertCompletion(const QString& completion) -{ - - if (m_completer->widget() != this) - return; - QTextCursor tc = textCursor(); - int extra = completion.length() - m_completer->completionPrefix().length(); - tc.movePosition(QTextCursor::Left); - tc.movePosition(QTextCursor::EndOfWord); - tc.insertText(completion.right(extra)); - setTextCursor(tc); -} - -QString -ChatMessageTextEdit::textUnderCursor () const -{ - QTextCursor tc = textCursor (); - tc.select (QTextCursor::WordUnderCursor); - return tc.selectedText (); -} - -void -ChatMessageTextEdit::focusInEvent (QFocusEvent *e) -{ - if (m_completer) - m_completer->setWidget (this); - QPlainTextEdit::focusInEvent (e); -} - -void -ChatMessageTextEdit::keyPressEvent (QKeyEvent *keyPressEvent) -{ - if (m_completer) { - switch (keyPressEvent->key ()) { - case Qt::Key_Enter: - case Qt::Key_Return: - if (! (keyPressEvent->modifiers () & Qt::ShiftModifier)) - { - emit sendMessage (document ()->toPlainText ()); - document ()->setPlainText (""); - } - else - { - QPlainTextEdit::keyPressEvent (keyPressEvent); - } - break; - case Qt::Key_Escape: - case Qt::Key_Tab: - case Qt::Key_Backtab: - keyPressEvent->ignore (); - return; - default: - QPlainTextEdit::keyPressEvent(keyPressEvent); - break; - } - - QString completionPrefix = textUnderCursor (); - if (completionPrefix != m_completer->completionPrefix ()) - { - m_completer->setCompletionPrefix(completionPrefix); - } - - if (completionPrefix.length() > 2) - { - m_completer->popup ()->setCurrentIndex (m_completer->completionModel ()->index (0, 0)); - m_completer->complete (); - } - else - { - m_completer->popup ()->hide (); - } - } -} - -IRCWidget::IRCWidget (QWidget * parent): -QWidget (parent) -{ - QSettings *settings = ResourceManager::instance ()->settings (); - bool connectOnStartup = settings->value ("connectOnStartup").toBool (); - m_autoIdentification = settings->value ("autoIdentification").toBool (); - m_nickServPassword = settings->value ("nickServPassword").toString (); - - m_initialNick = settings->value ("IRCNick").toString (); - - if (m_initialNick.isEmpty ()) - m_initialNick = "OctaveGUI-User"; - - QVBoxLayout *layout = new QVBoxLayout (); - - m_chatWindow = new QTextEdit (this); - m_chatWindow->setReadOnly (true); - m_chatWindow->setEnabled (false); - QWidget *bottomWidget = new QWidget (this); - - layout->addWidget (m_chatWindow); - layout->addWidget (bottomWidget); - layout->setMargin (0); - setLayout (layout); - - QHBoxLayout *bottomLayout = new QHBoxLayout (); - m_nickButton = new QPushButton (bottomWidget); - m_nickButton->setStatusTip (tr ((char *) "Click here to change your nick.")); - m_nickButton->setText (m_initialNick); - m_chatMessageTextEdit = new ChatMessageTextEdit (bottomWidget); - m_chatMessageTextEdit->setStatusTip (tr ((char *) "Enter your message here.")); - - bottomLayout->addWidget (m_nickButton); - bottomLayout->addWidget (new QLabel (":", this)); - bottomLayout->addWidget (m_chatMessageTextEdit); - bottomLayout->setMargin (0); - bottomWidget->setLayout (bottomLayout); - - m_nickButton->setEnabled (false); - m_chatMessageTextEdit->setEnabled (false); - - //setFocusProxy (m_chatMessageTextEdit); - m_nickButton->setFocusProxy (m_chatMessageTextEdit); - - QFont font; - font.setFamily ("Courier"); - font.setPointSize (11); - m_chatWindow->setFont (font); - m_ircClientInterface = new IRCClientImpl (this); - m_octaveChannel = m_ircClientInterface->ircChannelProxy ("#octave"); - - connect (m_ircClientInterface, SIGNAL (connected (QString)), - this, SLOT (handleConnected (QString))); - connect (m_ircClientInterface, SIGNAL(loggedIn(QString)), - this, SLOT (joinOctaveChannel (QString))); - connect (m_ircClientInterface, SIGNAL (error (QString)), - this, SLOT (showErrorMessage (QString))); - connect (m_ircClientInterface, SIGNAL (debugMessage (QString)), - this, SLOT (showStatusMessage (QString))); - connect (m_ircClientInterface, SIGNAL (message (QString, QString, QString)), - this, SLOT (showMessage (QString, QString, QString ))); - connect (m_ircClientInterface, SIGNAL (nicknameChanged (QString,QString)), - this, SLOT (handleNickChange (QString,QString))); - connect (m_ircClientInterface, SIGNAL (notification (QString,QString)), - this, SLOT (showNotification (QString,QString))); - connect (m_ircClientInterface, SIGNAL (loggedIn (QString)), - this, SLOT (handleLoggedIn(QString))); - connect (m_ircClientInterface, SIGNAL (userNicknameChanged (QString)), - this, SLOT (handleUserNicknameChanged (QString))); - - connect (m_nickButton, SIGNAL (clicked ()), this, SLOT (showChangeUserNickPopup ())); - connect (m_chatMessageTextEdit, SIGNAL (sendMessage (QString)), - this, SLOT (sendMessage (QString))); - - m_chatMessageTextEdit->setCompleter - (new QCompleter (m_ircClientInterface->ircChannelProxy ("#octave")->userListModel (), this)); - m_chatWindow->setDocument (m_octaveChannel->conversationModel ()); - - if (connectOnStartup) - connectToServer (); -} - -void -IRCWidget::connectToServer () -{ - showStatusMessage ("Looking up irc.freenode.net."); - QHostInfo hostInfo = QHostInfo::fromName ("irc.freenode.net"); - QList<QHostAddress> hostAddresses = hostInfo.addresses(); - if (hostAddresses.isEmpty ()) - { - showStatusMessage ("Failed to lookup irc.freenode.net."); - } - else - { - showStatusMessage (QString ("Attempting to connect to %1.") - .arg (hostAddresses.at (0).toString ())); - m_ircClientInterface->connectToHost(hostAddresses.at (0), 6667, m_initialNick); - } -} - -void -IRCWidget::showStatusMessage (const QString& message) -{ - m_chatWindow->append (QString ("<i>%1</i>").arg (message)); -} - -void -IRCWidget::showErrorMessage (const QString& message) -{ - m_chatWindow->append (QString ("<i>Error: %1</i>").arg (message)); -} - -void -IRCWidget::handleConnected (const QString &host) -{ - showStatusMessage (QString ("Connected to server %1.").arg (host)); -} - -void -IRCWidget::joinOctaveChannel (const QString& nick) -{ - Q_UNUSED (nick); - showStatusMessage (QString ("Joining channel #octave.")); - m_octaveChannel->sendJoinRequest (); -} - -void -IRCWidget::showMessage (const QString& channel, const QString& sender, const QString& message) -{ - Q_UNUSED (channel); - - // TODO: This doesn't work properly! - // Every message makes it emit unreadMessage (true), - // though it should inly be emitted when this window - // does not have focus, ie. is not the active window. - if (!(hasFocus() - || m_chatMessageTextEdit->hasFocus () - || m_nickButton->hasFocus () - || m_chatWindow->hasFocus () )) - { - emit unreadMessages (true); - } - - QString output; - QString htmlMessage = message; - htmlMessage.replace ("<", "<"); - htmlMessage.replace (">", ">"); - htmlMessage.replace ("\n", "<br>"); - if (message.contains (m_ircClientInterface->nickname ())) - { - output = - QString ("<font color=\"#990000\"><b>%1:</b> %2</font>").arg (sender). - arg (htmlMessage); - - QApplication::alert (this); - } - else - { - output = - QString ("<b>%1:</b> %2").arg (sender). - arg (htmlMessage); - } - m_chatWindow->append (output); - scrollToBottom (); -} - -void -IRCWidget::showNotification (const QString& sender, const QString& message) -{ - Q_UNUSED (sender); - m_chatWindow->append (QString ("<font color=\"#007700\">%1</font>").arg (message)); - scrollToBottom (); -} - -void -IRCWidget::showChangeUserNickPopup () -{ - bool ok; - QString newNick = - QInputDialog::getText (this, QString ("Nickname"), - QString ("Type in your nickname:"), - QLineEdit::Normal, m_ircClientInterface->nickname (), &ok); - if (ok) - { - m_ircClientInterface->sendNicknameChangeRequest (newNick); - } -} - -void -IRCWidget::sendMessage (QString message) -{ - // Do not send empty messages. - if (message.isEmpty ()) - return; - - // Remove trailing spaces. - while (message.at (0).isSpace ()) - message.remove (0, 1); - if (message.startsWith ("/")) - { - QStringList line = - message.split (QRegExp ("\\s+"), QString::SkipEmptyParts); - if (line.at (0) == "/join") - { - IRCChannelProxyInterface *ircChannel = m_ircClientInterface->ircChannelProxy (line.at (1)); - ircChannel->sendJoinRequest (); - } - else if (line.at (0) == "/nick") - { - m_ircClientInterface->sendNicknameChangeRequest (line.at (1)); - } - else if (line.at (0) == "/msg") - { - QString recipient = line.at (1); - // Since we splitted the message before, we have to glue it together again. - QString pmsg = ""; - for (int i = 2; i < line.length (); i++) - { - pmsg += line.at (i); - pmsg += " "; - } - m_ircClientInterface->sendPrivateMessage(recipient, pmsg); - } - } - else - { - m_octaveChannel->sendMessage (message); - message.replace ("<", "<"); - message.replace (">", ">"); - message.replace ("\n", "<br>"); - m_chatWindow->append (QString ("<b>%1:</b> %2"). - arg (m_ircClientInterface->nickname ()).arg (message)); - } - - scrollToBottom (); -} - -void -IRCWidget::maybeIdentifyOnNickServ () -{ - if (m_autoIdentification) - { - m_ircClientInterface->sendPrivateMessage("NickServ", QString ("identify %1"). - arg (m_nickServPassword)); - } -} - -void -IRCWidget::scrollToBottom () -{ - if (m_chatWindow->verticalScrollBar ()) - { - m_chatWindow->verticalScrollBar ()->setValue (m_chatWindow->verticalScrollBar ()->maximum ()); - } -} - -void -IRCWidget::focusInEvent (QFocusEvent *focusEvent) -{ - Q_UNUSED (focusEvent); - emit unreadMessages (false); - QWidget::focusInEvent (focusEvent); - - m_chatMessageTextEdit->setFocus (); -} - -void -IRCWidget::handleLoggedIn (const QString &nick) -{ - m_chatWindow-> - append (QString - ("<i><font color=\"#00AA00\"><b>Successfully logged in as %1.</b></font></i>"). - arg (nick)); - m_nickButton->setEnabled (true); - m_chatMessageTextEdit->setEnabled (true); - m_chatWindow->setEnabled (true); - m_chatMessageTextEdit->setFocus (); -} - -void -IRCWidget::handleNickChange (const QString &oldNick, const QString &newNick) -{ - m_chatWindow->append (QString ("%1 is now known as %2.").arg (oldNick).arg (newNick)); - scrollToBottom (); -} - -void -IRCWidget::handleUserJoined (const QString &nick, const QString &channel) -{ - m_chatWindow->append (QString ("<i>%1 has joined %2.</i>").arg (nick).arg (channel)); - scrollToBottom (); -} - -void -IRCWidget::handleUserQuit (const QString &nick, const QString &reason) -{ - m_chatWindow->append (QString ("<i>%1 has quit.(%2).</i>").arg (nick).arg (reason)); - scrollToBottom (); -} - -void -IRCWidget::handleUserNicknameChanged (const QString &nick) -{ - m_nickButton->setText (nick); - QSettings *settings = ResourceManager::instance ()->settings (); - settings->setValue ("IRCNick", nick); - maybeIdentifyOnNickServ (); -}
--- a/gui/src/IRCWidget.h Sun Sep 25 18:29:24 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* OctaveGUI - A graphical user interface for Octave - * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef IRCWIDGET_H -#define IRCWIDGET_H - -#include <QWidget> -#include <QPlainTextEdit> -#include <QPushButton> -#include <QLineEdit> -#include <QCompleter> -#include "IRCClientInterface.h" - -class ChatMessageTextEdit : public QPlainTextEdit -{ - Q_OBJECT -public: - explicit ChatMessageTextEdit(QWidget *parent = 0); - ~ChatMessageTextEdit(); - - void setCompleter(QCompleter *m_completer); - QCompleter *completer() const; - -signals: - void sendMessage (const QString& message); - -protected: - void keyPressEvent(QKeyEvent *e); - void focusInEvent(QFocusEvent *e); - -private slots: - void insertCompletion(const QString &completion); - -private: - QString textUnderCursor() const; - -private: - QCompleter *m_completer; -}; - -class IRCWidget : public QWidget -{ -Q_OBJECT public: - explicit IRCWidget (QWidget * parent); - void connectToServer (); - -public slots: - void showStatusMessage (const QString&); - void showErrorMessage (const QString&); - void showMessage (const QString& channel, const QString& sender, const QString& message); - void showNotification (const QString& sender, const QString& message); - - void handleConnected (const QString& host); - void joinOctaveChannel (const QString& nick); - - void handleLoggedIn (const QString& nick); - void handleNickChange (const QString& oldNick, const QString& newNick); - void handleUserJoined (const QString& nick, const QString& channel); - void handleUserQuit (const QString& nick, const QString& reason); - void handleUserNicknameChanged (const QString& nick); - - void showChangeUserNickPopup (); - void sendMessage (QString); - - void maybeIdentifyOnNickServ (); - void scrollToBottom (); - -signals: - void unreadMessages (bool yes); - -protected: - void focusInEvent (QFocusEvent *focusEvent); - -private: - IRCClientInterface *m_ircClientInterface; - IRCChannelProxyInterface *m_octaveChannel; - QTextEdit *m_chatWindow; - QPushButton *m_nickButton; - ChatMessageTextEdit *m_chatMessageTextEdit; - - QString m_initialNick; - bool m_autoIdentification; - QString m_nickServPassword; - QString m_settingsFile; -}; - -#endif // IRCWIDGET_H
--- a/gui/src/VariablesDockWidget.cpp Sun Sep 25 18:29:24 2011 +0200 +++ b/gui/src/VariablesDockWidget.cpp Sun Sep 25 21:12:47 2011 +0200 @@ -157,26 +157,26 @@ // will contain the appropriate QTreeWidgetItem* pointing at it. for (int i = 0; i < childCount; i++) { - child = topLevelItem->child (i); - if (child->data (0, 0).toString () == - QString (symbolRecord.name ().c_str ())) - { - alreadyExists = true; - break; - } + child = topLevelItem->child (i); + if (child->data (0, 0).toString () == + QString (symbolRecord.name ().c_str ())) + { + alreadyExists = true; + break; + } } // If it already exists, just update it. if (alreadyExists) { - updateTreeEntry (child, symbolRecord); + updateTreeEntry (child, symbolRecord); } else { - // It does not exist, so create a new one and set the right values. - child = new QTreeWidgetItem (); - updateTreeEntry (child, symbolRecord); - topLevelItem->addChild (child); + // It does not exist, so create a new one and set the right values. + child = new QTreeWidgetItem (); + updateTreeEntry (child, symbolRecord); + topLevelItem->addChild (child); } } @@ -186,30 +186,24 @@ bool existsInVariableList = false; QTreeWidgetItem *child = topLevelItem->child (i); foreach (SymbolRecord symbolRecord, symbolTable) - { - if (QString (symbolRecord.name ().c_str ()) == - child->data (0, 0).toString ()) - { - existsInVariableList = true; - } - } + { + if (QString (symbolRecord.name ().c_str ()) == + child->data (0, 0).toString ()) + { + existsInVariableList = true; + } + } if (!existsInVariableList) - { - topLevelItem->removeChild (child); - delete child; - i--; - } + { + topLevelItem->removeChild (child); + delete child; + i--; + } } } void -VariablesDockWidget::noticeSettings () -{ - -} - -void VariablesDockWidget::fetchSymbolTable () { QList < SymbolRecord > symbolTable = OctaveLink::instance ()->copyCurrentSymbolTable ();
--- a/gui/src/VariablesDockWidget.h Sun Sep 25 18:29:24 2011 +0200 +++ b/gui/src/VariablesDockWidget.h Sun Sep 25 21:12:47 2011 +0200 @@ -31,8 +31,6 @@ void setVariablesList (QList < SymbolRecord > symbolTable); public slots: - /** Tells the widget to notice settings that are probably new. */ - void noticeSettings (); void fetchSymbolTable (); void handleVisibilityChanged (bool visible); signals:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/qirc/IRCWidget.cpp Sun Sep 25 21:12:47 2011 +0200 @@ -0,0 +1,448 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ResourceManager.h" +#include "IRCWidget.h" +#include <QMessageBox> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QLabel> +#include <QSettings> +#include <QInputDialog> +#include <QKeyEvent> +#include <QScrollBar> +#include <QApplication> +#include "IRCClientImpl.h" + +ChatMessageTextEdit::ChatMessageTextEdit (QWidget *parent) + : QPlainTextEdit (parent), m_completer (0) +{ + setMaximumHeight (50); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); +} + +ChatMessageTextEdit::~ChatMessageTextEdit () +{ +} + +void +ChatMessageTextEdit::setCompleter (QCompleter *completer) +{ + if (m_completer) + QObject::disconnect (m_completer, 0, this, 0); + + m_completer = completer; + + if (!m_completer) + return; + + m_completer->setWidget (this); + m_completer->setCompletionMode (QCompleter::PopupCompletion); + m_completer->setCaseSensitivity (Qt::CaseInsensitive); + QObject::connect (m_completer, SIGNAL (activated (QString)), + this, SLOT (insertCompletion (QString))); +} + +QCompleter * +ChatMessageTextEdit::completer () const +{ + return m_completer; +} + +void +ChatMessageTextEdit::insertCompletion(const QString& completion) +{ + + if (m_completer->widget() != this) + return; + QTextCursor tc = textCursor(); + int extra = completion.length() - m_completer->completionPrefix().length(); + tc.movePosition(QTextCursor::Left); + tc.movePosition(QTextCursor::EndOfWord); + tc.insertText(completion.right(extra)); + setTextCursor(tc); +} + +QString +ChatMessageTextEdit::textUnderCursor () const +{ + QTextCursor tc = textCursor (); + tc.select (QTextCursor::WordUnderCursor); + return tc.selectedText (); +} + +void +ChatMessageTextEdit::focusInEvent (QFocusEvent *e) +{ + if (m_completer) + m_completer->setWidget (this); + QPlainTextEdit::focusInEvent (e); +} + +void +ChatMessageTextEdit::keyPressEvent (QKeyEvent *keyPressEvent) +{ + if (m_completer) { + switch (keyPressEvent->key ()) { + case Qt::Key_Enter: + case Qt::Key_Return: + if (! (keyPressEvent->modifiers () & Qt::ShiftModifier)) + { + emit sendMessage (document ()->toPlainText ()); + document ()->setPlainText (""); + } + else + { + QPlainTextEdit::keyPressEvent (keyPressEvent); + } + break; + case Qt::Key_Escape: + case Qt::Key_Tab: + case Qt::Key_Backtab: + keyPressEvent->ignore (); + return; + default: + QPlainTextEdit::keyPressEvent(keyPressEvent); + break; + } + + QString completionPrefix = textUnderCursor (); + if (completionPrefix != m_completer->completionPrefix ()) + { + m_completer->setCompletionPrefix(completionPrefix); + } + + if (completionPrefix.length() > 2) + { + m_completer->popup ()->setCurrentIndex (m_completer->completionModel ()->index (0, 0)); + m_completer->complete (); + } + else + { + m_completer->popup ()->hide (); + } + } +} + +IRCWidget::IRCWidget (QWidget * parent): +QWidget (parent) +{ + QSettings *settings = ResourceManager::instance ()->settings (); + bool connectOnStartup = settings->value ("connectOnStartup").toBool (); + m_autoIdentification = settings->value ("autoIdentification").toBool (); + m_nickServPassword = settings->value ("nickServPassword").toString (); + + m_initialNick = settings->value ("IRCNick").toString (); + + if (m_initialNick.isEmpty ()) + m_initialNick = "OctaveGUI-User"; + + QVBoxLayout *layout = new QVBoxLayout (); + + m_chatWindow = new QTextEdit (this); + m_chatWindow->setReadOnly (true); + m_chatWindow->setEnabled (false); + QWidget *bottomWidget = new QWidget (this); + + layout->addWidget (m_chatWindow); + layout->addWidget (bottomWidget); + layout->setMargin (0); + setLayout (layout); + + QHBoxLayout *bottomLayout = new QHBoxLayout (); + m_nickButton = new QPushButton (bottomWidget); + m_nickButton->setStatusTip (tr ((char *) "Click here to change your nick.")); + m_nickButton->setText (m_initialNick); + m_chatMessageTextEdit = new ChatMessageTextEdit (bottomWidget); + m_chatMessageTextEdit->setStatusTip (tr ((char *) "Enter your message here.")); + + bottomLayout->addWidget (m_nickButton); + bottomLayout->addWidget (new QLabel (":", this)); + bottomLayout->addWidget (m_chatMessageTextEdit); + bottomLayout->setMargin (0); + bottomWidget->setLayout (bottomLayout); + + m_nickButton->setEnabled (false); + m_chatMessageTextEdit->setEnabled (false); + + //setFocusProxy (m_chatMessageTextEdit); + m_nickButton->setFocusProxy (m_chatMessageTextEdit); + + QFont font; + font.setFamily ("Courier"); + font.setPointSize (11); + m_chatWindow->setFont (font); + m_ircClientInterface = new IRCClientImpl (this); + m_octaveChannel = m_ircClientInterface->ircChannelProxy ("#octave"); + + connect (m_ircClientInterface, SIGNAL (connected (QString)), + this, SLOT (handleConnected (QString))); + connect (m_ircClientInterface, SIGNAL(loggedIn(QString)), + this, SLOT (joinOctaveChannel (QString))); + connect (m_ircClientInterface, SIGNAL (error (QString)), + this, SLOT (showErrorMessage (QString))); + connect (m_ircClientInterface, SIGNAL (debugMessage (QString)), + this, SLOT (showStatusMessage (QString))); + connect (m_ircClientInterface, SIGNAL (message (QString, QString, QString)), + this, SLOT (showMessage (QString, QString, QString ))); + connect (m_ircClientInterface, SIGNAL (nicknameChanged (QString,QString)), + this, SLOT (handleNickChange (QString,QString))); + connect (m_ircClientInterface, SIGNAL (notification (QString,QString)), + this, SLOT (showNotification (QString,QString))); + connect (m_ircClientInterface, SIGNAL (loggedIn (QString)), + this, SLOT (handleLoggedIn(QString))); + connect (m_ircClientInterface, SIGNAL (userNicknameChanged (QString)), + this, SLOT (handleUserNicknameChanged (QString))); + + connect (m_nickButton, SIGNAL (clicked ()), this, SLOT (showChangeUserNickPopup ())); + connect (m_chatMessageTextEdit, SIGNAL (sendMessage (QString)), + this, SLOT (sendMessage (QString))); + + m_chatMessageTextEdit->setCompleter + (new QCompleter (m_ircClientInterface->ircChannelProxy ("#octave")->userListModel (), this)); + m_chatWindow->setDocument (m_octaveChannel->conversationModel ()); + + if (connectOnStartup) + connectToServer (); +} + +void +IRCWidget::connectToServer () +{ + showStatusMessage ("Looking up irc.freenode.net."); + QHostInfo hostInfo = QHostInfo::fromName ("irc.freenode.net"); + QList<QHostAddress> hostAddresses = hostInfo.addresses(); + if (hostAddresses.isEmpty ()) + { + showStatusMessage ("Failed to lookup irc.freenode.net."); + } + else + { + showStatusMessage (QString ("Attempting to connect to %1.") + .arg (hostAddresses.at (0).toString ())); + m_ircClientInterface->connectToHost(hostAddresses.at (0), 6667, m_initialNick); + } +} + +void +IRCWidget::showStatusMessage (const QString& message) +{ + m_chatWindow->append (QString ("<i>%1</i>").arg (message)); +} + +void +IRCWidget::showErrorMessage (const QString& message) +{ + m_chatWindow->append (QString ("<i>Error: %1</i>").arg (message)); +} + +void +IRCWidget::handleConnected (const QString &host) +{ + showStatusMessage (QString ("Connected to server %1.").arg (host)); +} + +void +IRCWidget::joinOctaveChannel (const QString& nick) +{ + Q_UNUSED (nick); + showStatusMessage (QString ("Joining channel #octave.")); + m_octaveChannel->sendJoinRequest (); +} + +void +IRCWidget::showMessage (const QString& channel, const QString& sender, const QString& message) +{ + Q_UNUSED (channel); + + // TODO: This doesn't work properly! + // Every message makes it emit unreadMessage (true), + // though it should inly be emitted when this window + // does not have focus, ie. is not the active window. + if (!(hasFocus() + || m_chatMessageTextEdit->hasFocus () + || m_nickButton->hasFocus () + || m_chatWindow->hasFocus () )) + { + emit unreadMessages (true); + } + + QString output; + QString htmlMessage = message; + htmlMessage.replace ("<", "<"); + htmlMessage.replace (">", ">"); + htmlMessage.replace ("\n", "<br>"); + if (message.contains (m_ircClientInterface->nickname ())) + { + output = + QString ("<font color=\"#990000\"><b>%1:</b> %2</font>").arg (sender). + arg (htmlMessage); + + QApplication::alert (this); + } + else + { + output = + QString ("<b>%1:</b> %2").arg (sender). + arg (htmlMessage); + } + m_chatWindow->append (output); + scrollToBottom (); +} + +void +IRCWidget::showNotification (const QString& sender, const QString& message) +{ + Q_UNUSED (sender); + m_chatWindow->append (QString ("<font color=\"#007700\">%1</font>").arg (message)); + scrollToBottom (); +} + +void +IRCWidget::showChangeUserNickPopup () +{ + bool ok; + QString newNick = + QInputDialog::getText (this, QString ("Nickname"), + QString ("Type in your nickname:"), + QLineEdit::Normal, m_ircClientInterface->nickname (), &ok); + if (ok) + { + m_ircClientInterface->sendNicknameChangeRequest (newNick); + } +} + +void +IRCWidget::sendMessage (QString message) +{ + // Do not send empty messages. + if (message.isEmpty ()) + return; + + // Remove trailing spaces. + while (message.at (0).isSpace ()) + message.remove (0, 1); + if (message.startsWith ("/")) + { + QStringList line = + message.split (QRegExp ("\\s+"), QString::SkipEmptyParts); + if (line.at (0) == "/join") + { + IRCChannelProxyInterface *ircChannel = m_ircClientInterface->ircChannelProxy (line.at (1)); + ircChannel->sendJoinRequest (); + } + else if (line.at (0) == "/nick") + { + m_ircClientInterface->sendNicknameChangeRequest (line.at (1)); + } + else if (line.at (0) == "/msg") + { + QString recipient = line.at (1); + // Since we splitted the message before, we have to glue it together again. + QString pmsg = ""; + for (int i = 2; i < line.length (); i++) + { + pmsg += line.at (i); + pmsg += " "; + } + m_ircClientInterface->sendPrivateMessage(recipient, pmsg); + } + } + else + { + m_octaveChannel->sendMessage (message); + message.replace ("<", "<"); + message.replace (">", ">"); + message.replace ("\n", "<br>"); + m_chatWindow->append (QString ("<b>%1:</b> %2"). + arg (m_ircClientInterface->nickname ()).arg (message)); + } + + scrollToBottom (); +} + +void +IRCWidget::maybeIdentifyOnNickServ () +{ + if (m_autoIdentification) + { + m_ircClientInterface->sendPrivateMessage("NickServ", QString ("identify %1"). + arg (m_nickServPassword)); + } +} + +void +IRCWidget::scrollToBottom () +{ + if (m_chatWindow->verticalScrollBar ()) + { + m_chatWindow->verticalScrollBar ()->setValue (m_chatWindow->verticalScrollBar ()->maximum ()); + } +} + +void +IRCWidget::focusInEvent (QFocusEvent *focusEvent) +{ + Q_UNUSED (focusEvent); + emit unreadMessages (false); + QWidget::focusInEvent (focusEvent); + + m_chatMessageTextEdit->setFocus (); +} + +void +IRCWidget::handleLoggedIn (const QString &nick) +{ + m_chatWindow-> + append (QString + ("<i><font color=\"#00AA00\"><b>Successfully logged in as %1.</b></font></i>"). + arg (nick)); + m_nickButton->setEnabled (true); + m_chatMessageTextEdit->setEnabled (true); + m_chatWindow->setEnabled (true); + m_chatMessageTextEdit->setFocus (); +} + +void +IRCWidget::handleNickChange (const QString &oldNick, const QString &newNick) +{ + m_chatWindow->append (QString ("%1 is now known as %2.").arg (oldNick).arg (newNick)); + scrollToBottom (); +} + +void +IRCWidget::handleUserJoined (const QString &nick, const QString &channel) +{ + m_chatWindow->append (QString ("<i>%1 has joined %2.</i>").arg (nick).arg (channel)); + scrollToBottom (); +} + +void +IRCWidget::handleUserQuit (const QString &nick, const QString &reason) +{ + m_chatWindow->append (QString ("<i>%1 has quit.(%2).</i>").arg (nick).arg (reason)); + scrollToBottom (); +} + +void +IRCWidget::handleUserNicknameChanged (const QString &nick) +{ + m_nickButton->setText (nick); + QSettings *settings = ResourceManager::instance ()->settings (); + settings->setValue ("IRCNick", nick); + maybeIdentifyOnNickServ (); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gui/src/qirc/IRCWidget.h Sun Sep 25 21:12:47 2011 +0200 @@ -0,0 +1,101 @@ +/* OctaveGUI - A graphical user interface for Octave + * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef IRCWIDGET_H +#define IRCWIDGET_H + +#include <QWidget> +#include <QPlainTextEdit> +#include <QPushButton> +#include <QLineEdit> +#include <QCompleter> +#include "IRCClientInterface.h" + +class ChatMessageTextEdit : public QPlainTextEdit +{ + Q_OBJECT +public: + explicit ChatMessageTextEdit(QWidget *parent = 0); + ~ChatMessageTextEdit(); + + void setCompleter(QCompleter *m_completer); + QCompleter *completer() const; + +signals: + void sendMessage (const QString& message); + +protected: + void keyPressEvent(QKeyEvent *e); + void focusInEvent(QFocusEvent *e); + +private slots: + void insertCompletion(const QString &completion); + +private: + QString textUnderCursor() const; + +private: + QCompleter *m_completer; +}; + +class IRCWidget : public QWidget +{ +Q_OBJECT public: + explicit IRCWidget (QWidget * parent); + void connectToServer (); + +public slots: + void showStatusMessage (const QString&); + void showErrorMessage (const QString&); + void showMessage (const QString& channel, const QString& sender, const QString& message); + void showNotification (const QString& sender, const QString& message); + + void handleConnected (const QString& host); + void joinOctaveChannel (const QString& nick); + + void handleLoggedIn (const QString& nick); + void handleNickChange (const QString& oldNick, const QString& newNick); + void handleUserJoined (const QString& nick, const QString& channel); + void handleUserQuit (const QString& nick, const QString& reason); + void handleUserNicknameChanged (const QString& nick); + + void showChangeUserNickPopup (); + void sendMessage (QString); + + void maybeIdentifyOnNickServ (); + void scrollToBottom (); + +signals: + void unreadMessages (bool yes); + +protected: + void focusInEvent (QFocusEvent *focusEvent); + +private: + IRCClientInterface *m_ircClientInterface; + IRCChannelProxyInterface *m_octaveChannel; + QTextEdit *m_chatWindow; + QPushButton *m_nickButton; + ChatMessageTextEdit *m_chatMessageTextEdit; + + QString m_initialNick; + bool m_autoIdentification; + QString m_nickServPassword; + QString m_settingsFile; +}; + +#endif // IRCWIDGET_H