Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ChatSession.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2002 by Yann Hodique                                    *
00003  *   Yann.Hodique@lifl.fr                                                  *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "ChatSession.h"
00012 #include "telnetmanager.h"
00013 #include <qstring.h>
00014 #include <qstringlist.h>
00015 #include <qregexp.h>
00016 #include <qstylesheet.h>
00017 #include <qaction.h>
00018 #include <qkeysequence.h>
00019 #include <qprocess.h>
00020 #include "mtpbrowser.h"
00021 #include <qlineedit.h>
00022 #include <qlistbox.h>
00023 #include <iostream>
00024 #include "mtpfilterssettings.h"
00025 #include "qnet.h"
00026 #include "domutil.h"
00027 #include "MtpFilter.h"
00028 #include "MtpContext.h"
00029 #include <qmessagebox.h>
00030 #include <qtextedit.h>
00031 #include <qapplication.h>
00032 #include "page.h"
00033 #include <qglobal.h>
00034 
00035 ChatSession::ChatSession(const QString& session_name, QMtp * mtp, QWidget *parent, const char *name, QDomDocument * dom)
00036         : ChatPage(parent, name) {
00037 
00038     host = DomUtil::readEntry(*dom,"/sessions/" + session_name + "/host","");
00039     port = DomUtil::readEntry(*dom,"/sessions/" + session_name + "/port","");
00040     this->mtp = mtp;
00041     this->m_dom = dom;
00042     this->session_name = session_name;
00043 
00044 /*    mng = new TelnetManager(this);
00045     mng->setArgs(host,port);
00046     mng->setLogin(DomUtil::readEntry(*dom,"/sessions/" + session_name + "/login",""));
00047     mng->setPassword(DomUtil::readEntry(*dom,"/sessions/" + session_name + "/password",""));
00048     mng->start();*/
00049     
00050     createTelnetManager();
00051 
00052     displayStderr("Connecting to " + host + ":" + port);
00053 
00054     chat_view->setTextFormat(Qt::RichText);
00055 
00056     chat_view->setWrapPolicy(QTextBrowser::Anywhere);
00057     chat_view->setLinkUnderline(true);
00058 
00059     item = new QStyleSheetItem(chat_view->styleSheet(),"mypre");
00060     item->setWhiteSpaceMode(QStyleSheetItem::WhiteSpacePre);
00061 
00062 
00063     login_set = false;
00064     enable_stdout = true;
00065     receiving_who = false;
00066     position = 0;
00067 
00068     history_up = new QAction(chat_edit,"up");
00069     history_up->setAccel(QKeySequence(SHIFT + Key_Up));
00070     history_down = new QAction(chat_edit,"down");
00071     history_down->setAccel(QKeySequence(SHIFT + Key_Down));
00072     new_line = new QAction(chat_edit,"new");
00073     new_line->setAccel(QKeySequence(CTRL + Key_Return));
00074     complete = new QAction(chat_edit,"complete");
00075     complete->setAccel(QKeySequence(Key_Tab));
00076     reconnect = new QAction(this,"reconnect");
00077     reconnect->setAccel(QKeySequence(CTRL + Key_R));
00078 
00079     connect(history_up, SIGNAL(activated()),
00080             this, SLOT(slotHistoryUp()));
00081     connect(history_down, SIGNAL(activated()),
00082             this, SLOT(slotHistoryDown()));
00083     connect(new_line, SIGNAL(activated()),
00084             this, SLOT(slotNewLine()));
00085     connect(complete, SIGNAL(activated()),
00086             this, SLOT(slotComplete()));
00087     connect(reconnect, SIGNAL(activated()),
00088             this, SLOT(slotReconnect()));
00089 
00090     connect(mng, SIGNAL(processExited()),
00091             this, SLOT(closeSession()));
00092 
00093     connect(chat_view,SIGNAL(linkClicked(const QString &)),
00094             this, SLOT(slotLinkClicked(const QString &)));
00095 
00096     connect(chat_edit, SIGNAL(returnPressed()),
00097             this, SLOT(returnPressed()));
00098 
00099     chat_edit->setFocus();
00100     chat_edit->setWordWrap(QTextEdit::NoWrap);
00101     chat_edit->setTextFormat(Qt::PlainText);
00102 
00103     doc_source = chat_view->source();
00104     history_iterator = 0;
00105 
00106     //proc = new QProcess(this);
00107     m_filter = new MtpFilter(dom,context());
00108 //    context() = new MtpContext();
00109 
00110 }
00111 
00112 
00113 ChatSession::~ChatSession() {
00114     //delete mng;
00115     delete m_filter;
00116     for (std::vector<Page*>::iterator it = brothers.begin(); it != brothers.end(); ++it)
00117         delete (*it);
00118 }
00119 
00120 void ChatSession::displayStderr(const QString& msg) {
00121     mtp->system_view->append("["+ host + ":" + port + "]" + msg);
00122 }
00123 
00124 void ChatSession::displayStdout(const QString& msg) {
00125 
00126     emit outputMessage(msg);
00127     QString m(msg);
00128     
00129     if (m.startsWith("<Mtp> Welcome")) {
00130         this->login = m.replace(QRegExp("<Mtp> Welcome, "),"").replace(QRegExp("\\..*"),"");
00131         displayStderr("Setting user name to " + this->login + ".");
00132 
00133         context()->setVar("login",caseUnsensitive(this->login));
00134         context()->setVar("Login",this->login);
00135   context()->setVar("channel","Hall");
00136 
00137         QString new_m("<Mtp> Welcome, " + login + ".");
00138 
00139         escape(&new_m);
00140         new_m = m_filter->filterOut(new_m);
00141 #if (QT_VERSION < 305)
00142         new_m += "<br>";
00143 #endif
00144 
00145         chat_view->append(new_m);
00146 
00147         position += new_m.length();
00148         login_set = true;
00149         mng->writeStdin(QString("set client ") + CLIENT);
00150         getInfo();
00151     } else if(filter(&m)) {
00152         escape(&m);
00153         m = m_filter->filterOut(m);
00154 
00155 
00156         QStringList list = QStringList::split("\n",m);
00157         for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
00158             QString mm = *it;
00159 #if (QT_VERSION < 305)
00160             mm += "<br>";
00161 #endif
00162 
00163             QRegExp rx("^:(\\w+\\?" "?):(\\w+):(.*)");
00164             if (rx.exactMatch(mm)) {
00165                 QString m(rx.cap(3));
00166 #if (QT_VERSION < 305)
00167                 m += "<br>";
00168 #endif
00169 
00170                 bool ok(!(rx.cap(1).endsWith("?")));
00171                 QString abbrev = ok ? rx.cap(1) : rx.cap(1).left(rx.cap(1).length()-1);
00172 
00173                 for (std::vector<Page*>::iterator it = brothers.begin(); it != brothers.end(); ++it)
00174                     if ((*it)->name() == rx.cap(2)) {
00175 
00176                         (*it)->append(m);
00177 
00178                         ok = false;
00179                     }
00180                 if (ok) {
00181 
00182         Page * edit = mtp->getNewPage(abbrev,rx.cap(2),this);
00183         if(edit) {
00184       brothers.push_back(edit);
00185       edit->append(m);
00186         }
00187         else
00188       displayStderr("Don't know what to do with : " + mm);
00189                 }
00190             } else {
00191                 chat_view->append(mm);
00192 
00193                 emit textDisplayed(this);
00194             }
00195         }
00196     }
00197 }
00198 
00199 const QString & ChatSession::sessionName() const {
00200     return session_name;
00201 }
00202 
00203 void ChatSession::kill(Page * ref) {
00204     for (std::vector<Page*>::iterator it = brothers.begin(); it != brothers.end(); ++it)
00205         if ((*it) == ref) {
00206             brothers.erase(it);
00207             return;
00208         }
00209 }
00210 
00211 void ChatSession::returnPressed() {
00212 
00213 
00214     // delete this $#!@? "\n" we've just inserted
00215     chat_edit->doKeyboardAction(QTextEdit::ActionBackspace);
00216 
00217     // put in history if and ONLY if password is already set...
00218     if (login_set && (chat_edit->text() != history[0]))
00219         history.push_front(chat_edit->text());
00220 
00221     QString m(chat_edit->text());
00222     send(m);
00223     chat_edit->clear();
00224 
00225     // history returns to start
00226     history_iterator = 0;
00227 
00228 }
00229 
00230 void ChatSession::send(const QString & m) {
00231     QString msg(m);
00232 
00233     QString prefix = "";
00234     // Compute the prefix
00235     QStringList l = DomUtil::readListEntry(*m_dom,"/prefixes","item");
00236     for (QStringList::Iterator it = l.begin(); it != l.end(); ++it) {
00237         QRegExp re("^(" + (*it).replace(QRegExp("%l"),"[^ ]*") + ") .*");
00238         if (re.exactMatch(msg)) {
00239             prefix = re.cap(1) + " ";
00240             break;
00241         }
00242     }
00243 
00244     // Delete prefix in string
00245     msg = msg.right(msg.length() - prefix.length());
00246 
00247     // split the input into atomic pieces
00248     QStringList list = QStringList::split("\n",msg);
00249     for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
00250 
00251         // For looooong messages
00252         QString m = *it;
00253         unsigned int limit = CHAT_BUFFER_LENGTH - prefix.length();
00254         while (m.length() > limit) {
00255             mng->writeStdin(prefix + m.left(limit));
00256             m = msg.right(m.length() - limit);
00257         }
00258         QString to_send(prefix + m);
00259         mng->writeStdin(m_filter->filterIn(to_send));
00260     }
00261 
00262 
00263 }
00264 
00265 void ChatSession::closeSession() {
00266     QMessageBox::information(this,"Connection lost","Lost connection with host " + host);
00267 }
00268 
00269 void ChatSession::slotLinkClicked(const QString & link) {
00270 
00271     QStringList list = DomUtil::readListEntry(*m_dom,"/urls/available","type");
00272     for(QStringList::Iterator it = list.begin(); it != list.end(); ++it)
00273         if(link.startsWith(*it))
00274             executeShellCommand(DomUtil::readEntry(*m_dom,QString("/urls/" + *it + "/command")).replace(QRegExp("%l"),link));
00275 }
00276 
00277 void ChatSession::slotHistoryUp() {
00278 
00279     if (history_iterator == 0)
00280         history_iterator=history.begin();
00281     else if (history_iterator != (--history.end()))
00282         history_iterator++;
00283     chat_edit->setText(*history_iterator);
00284 }
00285 
00286 void ChatSession::slotHistoryDown() {
00287     if( history_iterator == 0)
00288         return;
00289     if (history_iterator != history.begin()) {
00290         history_iterator--;
00291         chat_edit->setText(*history_iterator);
00292     } else {
00293         chat_edit->clear();
00294         history_iterator = 0;
00295     }
00296 }
00297 
00298 void ChatSession::slotNewLine() {
00299     chat_edit->doKeyboardAction(QTextEdit::ActionReturn);
00300 }
00301 
00302 void ChatSession::slotComplete() {
00303     int para, index;
00304     //    chat_edit->doKeyboardAction(QTextEdit::ActionBackspace);
00305     chat_edit->getCursorPosition(&para,&index);
00306     QString parag = chat_edit->text(para);
00307     QString pref;
00308 
00309     if (!parag.at(index-1).isLetterOrNumber())
00310         return;
00311 
00312     while (parag.at(--index).isLetterOrNumber()) {
00313         pref = parag.at(index) + pref;
00314         chat_edit->doKeyboardAction(QTextEdit::ActionBackspace);
00315     }
00316     for(uint i=0; i<users_box->count(); i++)
00317         //if (users_box->text(i).startsWith(pref)) {
00318         if (!(users_box->text(i).find(pref,0,false))) {
00319             if (users_box->text(i) == pref) {
00320                 uint position = (i+1)%(users_box->count());
00321                 chat_edit->insertAt(users_box->text(position),para,++index);
00322                 chat_edit->setCursorPosition(para,index+users_box->text(position).length());
00323             } else {
00324                 chat_edit->insertAt(users_box->text(i),para,++index);
00325                 chat_edit->setCursorPosition(para,index+users_box->text(i).length());
00326             }
00327             return;
00328         }
00329     chat_edit->insertAt(pref,para,++index);
00330     chat_edit->setCursorPosition(para,index+pref.length());
00331 }
00332 
00333 void ChatSession::slotReconnect() {
00334     delete mng;
00335     createTelnetManager();
00336 }
00337 
00338 void ChatSession::escape(QString * msg) {
00339 
00340     *msg = msg->replace(QRegExp("<"),"&lt ").replace(QRegExp(">"),"&gt ");
00341 
00342 
00343 }
00344 
00345 bool ChatSession::filter(QString * msg) {
00346     if (msg->startsWith("\a")) {
00347         *msg = msg->replace(QRegExp("^\a"),"");
00348     }
00349 
00350     QRegExp beep("^[0-9: ]*<Mtp> ([^ ]*) beeps you");
00351     if (beep.exactMatch(*msg))
00352         QApplication::beep();
00353 
00354     QRegExp user_out("^[0-9: ]*<Mtp> ([^ ]*) (leaves|disconnects|is kicked out).*");
00355     if (user_out.exactMatch(*msg))
00356         removeUser(user_out.cap(1));
00357 
00358     QRegExp user_kick("^[0-9: ]*<Mtp> You kick ([^ ]*) out.*");
00359     if (user_kick.exactMatch(*msg))
00360         removeUser(user_kick.cap(1));
00361 
00362     QRegExp user_in("^[0-9: ]*<Mtp> ([^ ]*) (comes in !).*");
00363     if (user_in.exactMatch(*msg))
00364         addUser(user_in.cap(1));
00365 
00366 
00367 
00368     if (msg->startsWith(" Login")) {
00369 
00370         if (who_demanded) {
00371             receiving_who = true;
00372             displayStderr("Getting informations about connected users");
00373             who_demanded = false;
00374             enable_stdout = false;
00375         }
00376         return enable_stdout;
00377     }
00378 
00379     if (msg->startsWith("-----")) {
00380         if(receiving_who)
00381             users_box->clear();
00382         return (enable_stdout);
00383     }
00384 
00385     if (msg->startsWith("<Mtp> There ")) {
00386         bool tmp = this->enable_stdout;
00387         this->enable_stdout = true;
00388         this->receiving_who = false;
00389         users_box->sort();
00390         return tmp;
00391     }
00392 
00393     if (receiving_who) {
00394         QString login(*msg);
00395         this->users_box->insertItem(login.replace(QRegExp(" .*"),""));
00396         return enable_stdout;
00397     }
00398 
00399     //    if (msg->startsWith("<Mtp> Password:"))
00400     //        chat_edit->setEchoMode(QLineEdit::Password);
00401 
00402     return true;
00403 }
00404 
00405 void ChatSession::getInfo() {
00406     who_demanded = true;
00407     mng->writeStdin("who all");
00408 }
00409 
00410 QString ChatSession::caseUnsensitive(const QString& msg) {
00411     QString up = msg.upper();
00412     QString low = msg.lower();
00413     QString res("");
00414     for (unsigned int i = 0; i<msg.length(); i++)
00415         res += "[" + up.at(i) + low.at(i) + "]";
00416     return res;
00417 }
00418 
00419 void ChatSession::addUser(const QString& name) {
00420     users_box->insertItem(name);
00421     users_box->sort();
00422 }
00423 
00424 void ChatSession::removeUser(const QString& name) {
00425     QListBoxItem * item = users_box->findItem(name,Qt::ExactMatch);
00426     delete item;
00427 }
00428 
00429 void ChatSession::executeShellCommand(const QString& com) {
00430     //    if (!proc->isRunning()) {
00431     proc = new QProcess(this);
00432     QStringList list = QStringList::split(" ",com);
00433     proc->setArguments(list);
00434     proc->start();
00435     connect(proc, SIGNAL(processExited()),
00436             this, SLOT(deleteProcess()));
00437     //    }
00438 }
00439 
00440 void ChatSession::setDomDocument(QDomDocument * dom) {
00441     m_dom = dom;
00442 }
00443 
00444 void ChatSession::deleteProcess() {
00445     delete sender();
00446 }
00447 
00448 void ChatSession::createTelnetManager()
00449 {
00450     mng = new TelnetManager(this);
00451     mng->setArgs(host,port);
00452     mng->setLogin(DomUtil::readEntry(*m_dom,"/sessions/" + session_name + "/login",""));
00453     mng->setPassword(DomUtil::readEntry(*m_dom,"/sessions/" + session_name + "/password",""));
00454     mng->start();
00455 }
00456 
00457 QMtp* ChatSession::topLevel() const {
00458     return mtp;
00459 }
00460 
00461 void ChatSession::updateFilters() {
00462     MtpFilter* f = m_filter;
00463     MtpFilter* g = new MtpFilter(m_dom,context());
00464     m_filter = g;
00465     f->setObsolete();
00466     delete f;
00467 }

Generated on Sat May 10 15:09:26 2003 for qnet by doxygen1.3