00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <qtextbrowser.h>
00012 #include <qlineedit.h>
00013 #include <qtabwidget.h>
00014 #include <qcombobox.h>
00015 #include <qmessagebox.h>
00016 #include <qfile.h>
00017 #include <qtextstream.h>
00018 #include <qdom.h>
00019 #include <qdir.h>
00020 #include <qlistbox.h>
00021 #include <qwidgetstack.h>
00022 #include <qregexp.h>
00023 #include <qprocess.h>
00024 #include <qradiobutton.h>
00025 #include <qstatusbar.h>
00026
00027 #include <dlfcn.h>
00028
00029 #include "qnet.h"
00030 #include "connectionbox.h"
00031 #include "ChatSession.h"
00032 #include "version.h"
00033 #include "domutil.h"
00034 #include "SessionsDialog.h"
00035 #include "mtpsettings.h"
00036 #include "mtpfilterssettings.h"
00037 #include "UrlSettings.h"
00038 #include "PrefixSettings.h"
00039 #include "fortunesettings.h"
00040 #include "appearancesettings.h"
00041 #include "remotecontrol.h"
00042 #include "page.h"
00043
00044 QMtp::QMtp(QWidget *parent, const char *name)
00045 : QMtp_base(parent, name), m_document() {
00046
00047
00048 delete statusBar();
00049
00050 connect(tabs,SIGNAL(currentChanged(QWidget*)),
00051 this, SLOT(slotCurrentPageChanged(QWidget*)));
00052
00053 if (!loadConfigFile()) {
00054 QString default_content("<qnet/>");
00055 m_document.setContent(default_content);
00056 }
00057 tabs->setTabPosition((QTabWidget::TabPosition)DomUtil::readIntEntry(m_document,"/appearance/tabs/position",QTabWidget::Top));
00058 fortune_page = 0;
00059 fproc = 0;
00060 if (DomUtil::readBoolEntry(m_document,"/remote/enabled",false))
00061 rctl = new RemoteControlServerInfo(this,DomUtil::readIntEntry(m_document,"/remote/port",5000),system_view);
00062
00063
00064 QStringList plugs = DomUtil::readListEntry(m_document,"/general/plugins","file");
00065 for(QStringList::Iterator it = plugs.begin(); it != plugs.end(); ++it)
00066 loadPlugin(*it);
00067
00068
00069 QStringList list = DomUtil::readListEntry(m_document,"/general/sessions","session");
00070 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it)
00071 if(DomUtil::readBoolEntry(m_document,"/sessions/" + *it + "/autoconnect",false))
00072 launchSession(*it);
00073 }
00074
00075
00076 QMtp::~QMtp() {
00077 saveConfigFile();
00078
00079
00080 for (QMap<QString,void*>::Iterator it = plugins_map.begin(); it != plugins_map.end(); ++it)
00081 dlclose(*it);
00082 }
00083
00084 void QMtp::slotConfigure() {
00085 MtpSettings settings(this);
00086 QDomDocument temporary_dom;
00087
00088 temporary_dom.setContent(m_document.toString());
00089
00090
00091 connect(settings.prop_list, SIGNAL(highlighted(int)),
00092 settings.stack, SLOT(raiseWidget(int)));
00093
00094
00095 {
00096 MtpFiltersSettings * filters_settings = new MtpFiltersSettings(settings.stack);
00097 settings.stack->addWidget(filters_settings,0);
00098 settings.prop_list->insertItem("Filters",0);
00099
00100 filters_settings->setDom(&temporary_dom);
00101 }
00102
00103
00104 UrlSettings * url_settings = new UrlSettings(settings.stack);
00105 settings.stack->addWidget(url_settings,1);
00106 settings.prop_list->insertItem("Url",1);
00107 {
00108 QStringList list = DomUtil::readListEntry(m_document,"/urls/available","type");
00109 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
00110 QString name = *it;
00111 QString motif = DomUtil::readEntry(m_document,"/urls/" + name + "/motif","");
00112 QString command = DomUtil::readEntry(m_document,"/urls/" + name + "/command","");
00113 UrlSettings::UrlItem mng(name,motif,command);
00114 url_settings->addUrlItem(mng);
00115 }
00116 }
00117
00118
00119 PrefixSettings * prefix_settings = new PrefixSettings(settings.stack);
00120 settings.stack->addWidget(prefix_settings,2);
00121 settings.prop_list->insertItem("Prefixes",2);
00122 {
00123 QStringList list = DomUtil::readListEntry(m_document,"/prefixes","item");
00124 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
00125 PrefixSettings::PrefixItem mng(*it);
00126 prefix_settings->addPrefixItem(mng);
00127 }
00128 }
00129
00130
00131 FortuneSettings * fortune_settings = new FortuneSettings(settings.stack);
00132 settings.stack->addWidget(fortune_settings,3);
00133 settings.prop_list->insertItem("Fortune",3);
00134 {
00135 QString args = DomUtil::readEntry(m_document,"/fortune");
00136 fortune_settings->fortune_edit->setText(args);
00137 }
00138
00139
00140 AppearanceSettings * appearance_settings = new AppearanceSettings(settings.stack);
00141 settings.stack->addWidget(appearance_settings,4);
00142 settings.prop_list->insertItem("Appearance",4);
00143 {
00144 int position = DomUtil::readIntEntry(m_document,"/appearance/tabs/position",QTabWidget::Top);
00145 appearance_settings->rbTop->setChecked(position==QTabWidget::Top);
00146 appearance_settings->rbBottom->setChecked(!appearance_settings->rbTop->isChecked());
00147 }
00148
00149 if (settings.exec() == QDialog::Accepted) {
00150
00151 m_document.setContent(temporary_dom.toString());
00152
00153 for(QValueList<ChatSession*>::Iterator it = sessions.begin(); it != sessions.end(); ++it) {
00154 (*it)->updateFilters();
00155 }
00156
00157
00158 {
00159 QStringList l;
00160 for (uint i=0; i< url_settings->urls_box->count(); i++)
00161 l << url_settings->urls_box->text(i);
00162 DomUtil::writeListEntry(m_document,"/urls/available","type",l);
00163
00164 for (uint i=0; i< url_settings->urls_box->count(); i++) {
00165 UrlSettings::UrlItem it = *(url_settings->map.find(url_settings->urls_box->text(i)));
00166 DomUtil::writeEntry(m_document,"/urls/" + it.name + "/motif",it.prefix);
00167 DomUtil::writeEntry(m_document,"/urls/" + it.name + "/command",it.command);
00168 }
00169 }
00170
00171
00172 {
00173 QStringList l;
00174 for (uint i=0; i< prefix_settings->prefix_box->count(); i++)
00175 l << prefix_settings->prefix_box->text(i);
00176 DomUtil::writeListEntry(m_document,"/prefixes","item",l);
00177 }
00178
00179
00180 {
00181 DomUtil::writeEntry(m_document,"/fortune",fortune_settings->fortune_edit->text());
00182 }
00183
00184
00185 {
00186 int position = appearance_settings->rbTop->isChecked()?QTabWidget::Top : QTabWidget::Bottom;
00187 DomUtil::writeIntEntry(m_document,"appearance/tabs/position",position);
00188 tabs->setTabPosition((QTabWidget::TabPosition)position);
00189 }
00190 saveConfigFile();
00191 }
00192 }
00193
00194 void QMtp::fileNew() {
00195 ConnectionBox box;
00196 QStringList list = DomUtil::readListEntry(m_document,"/general/sessions","session");
00197 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it)
00198 box.session_box->insertItem(*it);
00199 box.session_box->setFocus();
00200
00201 if(box.exec() && (box.session_box->currentText() != "")) {
00202 launchSession(box.session_box->currentText());
00203 }
00204 }
00205
00206 Page * QMtp::getNewPage(const QString& type,const QString& name,ChatSession * ref) {
00207 QMap<QString,void*>::Iterator it;
00208 if((it = plugins_map.find(type)) != plugins_map.end()) {
00209 create_t* create_plugin = (create_t*) dlsym(*it, "create");
00210 Page* page = create_plugin(tabs,name,ref);
00211 if (page->isSlave()) {
00212 tabs->addTab(page,name);
00213 tabs->showPage(page);
00214 }
00215 tab_map.insert(page,ref);
00216 connect(page, SIGNAL(textDisplayed(QWidget *)),
00217 this, SLOT(slotTextDisplayed(QWidget *)));
00218 return page;
00219 }
00220 system_view->append("No type \"" + type + "\" available\n");
00221 return 0;
00222 }
00223
00224 void QMtp::fileSessions() {
00225 SessionsDialog dlg;
00226
00227 QStringList list = DomUtil::readListEntry(m_document,"/general/sessions","session");
00228 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
00229 QString name = *it;
00230 QString host = DomUtil::readEntry(m_document,"/sessions/" + name + "/host","");
00231 QString port = DomUtil::readEntry(m_document,"/sessions/" + name + "/port","");
00232 QString login = DomUtil::readEntry(m_document,"/sessions/" + name + "/login","");
00233 QString password = DomUtil::readEntry(m_document,"/sessions/" + name + "/password","");
00234 bool autoconnect = DomUtil::readBoolEntry(m_document,"/sessions/" + name + "/autoconnect",false);
00235 SessionsDialog::SessionItem session(name,host,port,login,password,autoconnect);
00236 dlg.addSessionItem(session);
00237 }
00238
00239 if (dlg.exec()) {
00240 QStringList l;
00241 for (uint i=0; i< dlg.sessions_box->count(); i++)
00242 l << dlg.sessions_box->text(i);
00243 DomUtil::writeListEntry(m_document,"/general/sessions","session",l);
00244
00245 QDomElement child = DomUtil::elementByPath(m_document,"/sessions");
00246 if(!child.isNull()) child.parentNode().removeChild(child);
00247
00248 for (uint i=0; i< dlg.sessions_box->count(); i++) {
00249 SessionsDialog::SessionItem it = *(dlg.map.find(dlg.sessions_box->text(i)));
00250 DomUtil::writeEntry(m_document,"/sessions/" + it.name + "/host",it.host);
00251 DomUtil::writeEntry(m_document,"/sessions/" + it.name + "/port",it.port);
00252 DomUtil::writeEntry(m_document,"/sessions/" + it.name + "/login",it.login);
00253 DomUtil::writeEntry(m_document,"/sessions/" + it.name + "/password",it.password);
00254 DomUtil::writeBoolEntry(m_document,"/sessions/" + it.name + "/autoconnect",it.autoconnect);
00255 }
00256 }
00257 }
00258
00259 void QMtp::closeCurrentTab() {
00260 closeTab(tabs->currentPage());
00261 }
00262
00263 void QMtp::closeTab(QWidget *w) {
00264 if(w == fortune_page) {
00265 delete w;
00266 fortune_page = 0;
00267 return;
00268 }
00269 if(w != tab) {
00270 tabs->removePage(w);
00271 QMap<QWidget*,ChatSession*>::Iterator it;
00272 if ((it = tab_map.find(w)) != tab_map.end()) {
00273 (*it)->kill((Page*)w);
00274 } else
00275 sessions.remove((ChatSession*)w);
00276 delete w;
00277 }
00278 }
00279
00280 void QMtp::fileExit() {
00281 saveConfigFile();
00282 close();
00283 }
00284
00285 void QMtp::gotoNextTab() {
00286 tabs->setCurrentPage((tabs->currentPageIndex() + 1) % tabs->count());
00287 }
00288
00289 void QMtp::gotoPreviousTab() {
00290 tabs->setCurrentPage((tabs->currentPageIndex() + tabs->count() - 1) % tabs->count());
00291 }
00292
00293 void QMtp::helpAbout() {
00294 QMessageBox::about(this, "About QNet", CLIENT + QString("\nŠ 2002 - Sigma <Yann.Hodique@lifl.fr>"));
00295 }
00296
00297 bool QMtp::loadConfigFile() {
00298 QFile fin(QDir::homeDirPath() + "/.qnetrc");
00299 if (!fin.open(IO_ReadOnly)) {
00300 QMessageBox::critical(this,"Error","Could not read config file");
00301 return false;
00302 }
00303
00304 int errorLine, errorCol;
00305 QString errorMsg;
00306 if (!m_document.setContent(&fin, &errorMsg, &errorLine, &errorCol)) {
00307 QMessageBox::critical(this,"Error",QString("This is not a valid config file.\nXML error in line %1, column %2:\n%3").arg(errorLine).arg(errorCol).arg(errorMsg));
00308 fin.close();
00309 return false;
00310 }
00311 if (m_document.documentElement().nodeName() !="qnet") {
00312 QMessageBox::critical(this,"Error","This is not a valid config file.");
00313 fin.close();
00314 return false;
00315 }
00316
00317 fin.close();
00318
00319 return true;
00320 }
00321
00322 bool QMtp::saveConfigFile() {
00323 QFile fout(QDir::homeDirPath() + "/.qnetrc");
00324 if( !fout.open(IO_WriteOnly) ) {
00325 QMessageBox::critical(this,"Error","Could not write the config file.");
00326 return false;
00327 }
00328
00329 QTextStream stream(&fout);
00330 stream << m_document.toString();
00331 fout.close();
00332
00333 return true;
00334 }
00335
00336 void QMtp::slotTextDisplayed(QWidget* w) {
00337 QString current_label = tabs->label(tabs->indexOf(w));
00338 if ((tabs->currentPage() == w) || current_label.endsWith("*"))
00339 return;
00340 tabs->setTabLabel(w,current_label + "*");
00341 }
00342
00343 void QMtp::slotCurrentPageChanged(QWidget* w) {
00344 QString current_label = tabs->label(tabs->indexOf(w));
00345 if (current_label.endsWith("*"))
00346 tabs->setTabLabel(w,current_label.replace(QRegExp("\\*$"),""));
00347 }
00348
00349 void QMtp::slotDisplayFortune() {
00350 if (fproc)
00351 return;
00352 fproc = new QProcess(this);
00353 if (!(this->fortune_page)) {
00354 fortune_page = new QTextBrowser(tabs,"Fortune");
00355 fortune_page->setTextFormat(Qt::RichText);
00356
00357 fortune_page->setWrapPolicy(QTextBrowser::Anywhere);
00358
00359 tabs->addTab(fortune_page,"Fortune");
00360 tabs->showPage(fortune_page);
00361 }
00362
00363 QStringList list;
00364 QStringList list_args = QStringList::split(" ",DomUtil::readEntry(m_document,"/fortune"));
00365 list << "fortune";
00366
00367 for (QStringList::Iterator it = list_args.begin(); it != list_args.end(); ++it)
00368 list << (*it);
00369
00370 connect(fproc,SIGNAL(readyReadStdout()),
00371 this, SLOT(readFortune()));
00372 connect(fproc,SIGNAL(processExited()),
00373 this, SLOT(endFortune()));
00374 fproc->setArguments(list);
00375 fproc->start();
00376 }
00377
00378 void QMtp::readFortune() {
00379 QProcess *p = (QProcess*) sender();
00380 while (p->canReadLineStdout()) {
00381 QString msg(p->readLineStdout());
00382 fortune_page->append(msg);
00383 }
00384 }
00385
00386 void QMtp::endFortune() {
00387 fortune_page->append("<hr>");
00388 delete fproc;
00389 fproc = 0;
00390 }
00391
00392 void QMtp::loadPlugin(const QString& file_name) {
00393 system_view->append("Loading " + file_name);
00394
00395 void* plug = dlopen(file_name, RTLD_LAZY);
00396 if (!plug) {
00397 system_view->append(QString("Cannot load library: ") + dlerror() + "\n");
00398 return;
00399 }
00400
00401 create_t* create_plugin = (create_t*) dlsym(plug, "create");
00402 destroy_t* destroy_plugin = (destroy_t*) dlsym(plug, "destroy");
00403 name_t* name_plugin = (name_t*) dlsym(plug, "name");
00404 if (!create_plugin || !destroy_plugin || !name_plugin) {
00405 system_view->append(QString("Cannot load symbols: ") + dlerror() + "\n");
00406 return;
00407 }
00408
00409 plugins_map.insert(name_plugin(),plug);
00410 }
00411
00412 void QMtp::launchSession(const QString& name) {
00413 ChatSession * session = new ChatSession(name,this,tabs,0,&m_document);
00414
00415 sessions.push_back(session);
00416
00417 tabs->addTab(session,name);
00418 tabs->showPage(session);
00419
00420 connect(session, SIGNAL(textDisplayed(QWidget *)),
00421 this, SLOT(slotTextDisplayed(QWidget *)));
00422 }