File indexing completed on 2024-04-14 14:32:06

0001 /***************************************************************************
0002                           cconnection.cpp  -  handles connections
0003     This file is a part of KMuddy distribution.
0004                              -------------------
0005     begin                : Po Jul 22 2002
0006     copyright            : (C) 2002 by Tomas Mecir
0007     email                : kmuddy@kmuddy.com
0008  ***************************************************************************/
0009 
0010 /***************************************************************************
0011  *                                                                         *
0012  *   This program is free software; you can redistribute it and/or modify  *
0013  *   it under the terms of the GNU General Public License as published by  *
0014  *   the Free Software Foundation; either version 2 of the License, or     *
0015  *   (at your option) any later version.                                   *
0016  *                                                                         *
0017  ***************************************************************************/
0018 
0019 #include "cconnection.h"
0020 
0021 #include <config-mxp.h>
0022 
0023 #include <kmessagebox.h>
0024 #include <KLocalizedString>
0025 
0026 #include <QDateTime>
0027 #include <QPushButton>
0028 #include <QTimer>
0029 
0030 #include "kmuddy.h"
0031 #include "ccmdprocessor.h"
0032 #include "clistmanager.h"
0033 #include "cprofilemanager.h"
0034 #include "cprofilesettings.h"
0035 #include "csessionmanager.h"
0036 #include "ctelnet.h"
0037 
0038 #include "caliaslist.h"
0039 #include "ctriggerlist.h"
0040 #include "cbuttonlist.h"
0041 #include "cgaugelist.h"
0042 #include "ctimerlist.h"
0043 #include "cshortcutlist.h"
0044 #include "cstatusvarlist.h"
0045 #include "cvariablelist.h"
0046 #include "cwindowlist.h"
0047 
0048 #include "ctranscript.h"
0049 
0050 #include <map>
0051 
0052 #include "dialogs/dlgprofilesettings.h"
0053 #include "dialogs/dlgwindows.h"
0054 
0055 #define AUTOSAVE_INTERVAL 5
0056 
0057 // TODO: lists will go to a separate class - cListManager
0058 
0059 /** this class holds private data of a cConnection object */
0060 struct cConnectionPrivate {
0061 
0062   bool profileConnection;
0063   QString profileName;
0064   QString quickServer;
0065   int quickPort;  // server/port for quick connections
0066 
0067   QString caption;
0068 
0069   QString commands;
0070   // waiting for commands - no immediate sending
0071   bool waitCommands;
0072 
0073   int commandNum;
0074 
0075   QTimer *connecting;
0076   QTimer *saver;
0077 
0078   dlgProfileSettings *sdlg;
0079 
0080   bool destroying;
0081 
0082   bool connclosed;
0083   bool canCT;
0084 
0085   bool connInProgress, qconnInProgress, sendNothing;
0086 
0087   //login sequence and its iterator
0088   QStringList loginSeq;
0089   QStringList::iterator seqIter;
0090 
0091   //lists with data
0092   cVariableList *variablelist;
0093   cWindowList *windowlist;
0094 };
0095 
0096 cConnection::cConnection (int sess) : cActionBase ("connection", sess)
0097 {
0098   d = new cConnectionPrivate;
0099   d->profileConnection = false;
0100   d->destroying = false;
0101   d->connecting = nullptr;
0102   d->connclosed = false;
0103   d->canCT = false;
0104   d->connInProgress = d->qconnInProgress = d->sendNothing = false;
0105   d->commands = QString();
0106   d->waitCommands = false;
0107   d->commandNum = 0;
0108 
0109   d->variablelist = nullptr;
0110   d->windowlist = nullptr;
0111 
0112   d->saver = new QTimer;
0113   connect (d->saver, &QTimer::timeout, this, &cConnection::saveSession);
0114 
0115   addEventHandler ("connected", 10, PT_NOTHING);
0116   addEventHandler ("save", 10, PT_NOTHING);
0117   addEventHandler ("disconnected", 500, PT_NOTHING);
0118   addEventHandler ("connection-failed", 100, PT_STRING);
0119   addEventHandler ("send-command", 50, PT_STRING);
0120   addEventHandler ("command-block", 50, PT_NOTHING);
0121   addEventHandler ("send-commands", 50, PT_NOTHING);
0122 }
0123 
0124 cConnection::~cConnection ()
0125 {
0126   d->destroying = true;
0127   disconnect ();  //maybe we aren't connected, but disconnect() can handle it
0128 
0129   removeEventHandler ("connected");
0130   removeEventHandler ("disconnected");
0131   removeEventHandler ("connection-failed");
0132   removeEventHandler ("send-command");
0133   removeEventHandler ("command-block");
0134   removeEventHandler ("send-commands");
0135 
0136   delete d->saver;
0137   delete d;
0138 }
0139 
0140 void cConnection::eventNothingHandler (QString event, int)
0141 {
0142   cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet", sess()));
0143   if (telnet == nullptr)
0144     return;
0145 
0146   if (event == "connected") {
0147     // TODO: better way of detecting quick/normal - other classes need it too
0148     // probably just some setting set upon creating objects (loader knows session type)
0149 
0150     setAttrib ("connected", 1);
0151     d->connclosed = false;
0152     d->canCT = false;
0153     d->commands = QString();
0154     updateMenus ();
0155     KMuddy::self()->enableConnectedOptions ();
0156 
0157     if (d->connInProgress) {
0158       // register the internal lists if needed
0159       registerLists ();
0160 
0161       // initialize the profile
0162       invokeEvent ("profile-init", sess(), d->profileName);
0163 
0164       // load the variable list and the window list
0165       // these two are not handled by the list manager
0166       // variable list must be loaded before the other lists are
0167       d->variablelist = new cVariableList (sess());
0168       d->windowlist = new cWindowList (sess());
0169 
0170       // load the profile
0171       invokeEvent ("profile-load", sess(), d->profileName);
0172 
0173       // profile is loaded, so we can fetch settings by session ID
0174       cProfileSettings *sett = cProfileManager::self()->settings (sess());
0175       // adjust everything based on the profile settings
0176       invokeEvent ("settings-changed", sess());
0177 
0178       QString login = sett->getString ("login");
0179       QString profile = cProfileManager::self()->visibleProfileName (d->profileName);
0180 
0181       // set some variables - $character, $session, $profile
0182       cVariableList *vl = dynamic_cast<cVariableList *>(object ("variables"));
0183       vl->set ("character", login);
0184       vl->set ("profile", d->profileName);
0185       vl->set ("session", profile);
0186 
0187       KMuddy::self()->enableAdvancedOptions ();
0188 
0189       //update caption
0190       d->caption = login.isEmpty() ? profile : (login + "@" + profile);
0191       cSessionManager::self()->setSessionName (sess(), d->caption);
0192 
0193       // Here be autologging
0194       if (settings()->getBool ("auto-adv-transcript"))
0195       {
0196         cTranscript *transcript = dynamic_cast<cTranscript *>(object ("transcript"));
0197         transcript->load();
0198         transcript->startAdvTranscript();
0199       }
0200 
0201       //everything's ready - schedule sending of login sequence if needed...
0202       if (!d->sendNothing)
0203       {
0204         // generate the login sequence
0205         d->loginSeq.clear();
0206         int seqn = sett->getInt ("on-connect-count");
0207         for (int i = 0; i < seqn; ++i)
0208           d->loginSeq << sett->getString ("on-connect-"+QString::number(i));
0209         
0210         d->seqIter = d->loginSeq.begin();
0211         if ((seqn > 1) || ((seqn == 1) && (d->loginSeq[0].length() > 0)))
0212         {
0213           d->connecting = new QTimer;
0214           connect (d->connecting, &QTimer::timeout, this, &cConnection::sendLoginAndPassword);
0215           telnet->waitingForData();
0216           d->connecting->start (400);
0217         }
0218       }
0219 
0220       //also schedule automatic saving of settings and objects
0221       d->saver->start (AUTOSAVE_INTERVAL * 60 * 1000);
0222     } else
0223     {
0224       KMuddy::self()->disableAdvancedOptions ();
0225 
0226   #ifdef HAVE_MXP
0227       //allow MXP auto-detection for quick connections
0228       telnet->setMXPAllowed (3);
0229   #endif
0230 
0231       //update application caption
0232       //update caption
0233       d->caption = d->quickServer + ":" + QString::number (d->quickPort);
0234       cSessionManager::self()->setSessionName (sess(), d->caption);
0235     }
0236 
0237     d->connInProgress = d->qconnInProgress = false;
0238   }
0239   else if (event == "disconnected") {
0240     disconnect ();
0241   }
0242   else if (event == "save") {
0243     save ();
0244   }
0245   else if (event == "command-block") {
0246     d->waitCommands = true;
0247   }
0248   else if (event == "send-commands") {
0249     sendCommands ();
0250   }
0251 }
0252 
0253 void cConnection::eventStringHandler (QString event, int, QString &par1, const QString &)
0254 {
0255   if (event == "send-command") {
0256     if (par1.isEmpty())
0257       addCommand (par1);  // allow empty commands to be sent
0258     else
0259       addCommands (par1.split ("\n"));
0260   }
0261   else if (event == "connection-failed") {
0262     invokeEvent ("message", sess(), i18n ("Network error: %1", par1));
0263     setConnectionClosed (true);
0264     updateMenus ();
0265   }
0266 }
0267 
0268 QString cConnection::actionStringHandler (QString action, int, QString &par1, const QString &)
0269 {
0270   if (action == "send-command") {
0271     addCommands (par1.split ("\n"));
0272   }
0273 
0274   return QString();
0275 }
0276 
0277 QString cConnection::actionNothingHandler (QString action, int)
0278 {
0279   if (action == "command-block") {
0280     d->waitCommands = true;
0281   }
0282   else if (action == "send-commands") {
0283     sendCommands ();
0284   }
0285 
0286   return QString();
0287 }
0288 
0289 QString cConnection::getCaption () {
0290   return d->caption;
0291 }
0292 
0293 void cConnection::setConnectionClosed (bool canCloseTab) {
0294   setAttrib ("connected", 0);
0295   d->connclosed = true;
0296   d->canCT = canCloseTab;
0297 }
0298 
0299 void cConnection::unsetConnectionClosed () {
0300   setAttrib ("connected", 1);
0301   d->connclosed = false;
0302   d->canCT = false;
0303 }
0304 
0305 bool cConnection::connectionClosed () {
0306   return d->connclosed;
0307 }
0308 
0309 void cConnection::showConnPrefsDialog ()
0310 {
0311   cProfileSettings *sett = settings ();
0312   if (!sett) return;    //not a profile-based connection - do nothing
0313   //so first we have to create the dialog...
0314   d->sdlg = new dlgProfileSettings (KMuddy::self());
0315 
0316   //then we connect() all its signals - this handles everything that the dialog offers...
0317   connect (d->sdlg, &dlgProfileSettings::accepted, this, &cConnection::getSettingsFromDialog);
0318   connect (d->sdlg->button (QDialogButtonBox::Apply), &QPushButton::clicked, this, &cConnection::getSettingsFromDialog);
0319 
0320   //next we fill in its data
0321   putSettingsToDialog ();
0322 
0323   //dialog is ready - show it!
0324   d->sdlg->exec ();
0325 
0326   //further action is handled via slots issued by buttons, so that we only
0327   //have to destroy the dialog...
0328   delete d->sdlg;
0329 }
0330 
0331 void cConnection::getSettingsFromDialog ()
0332 {
0333   cProfileSettings *sett = settings ();
0334   if (!sett) return;  // should never happen
0335 
0336   dlgProfileSettings *sdlg = d->sdlg;
0337 
0338   sett->setBool ("use-ansi", sdlg->useAnsi ());
0339   sett->setBool ("limit-repeater", sdlg->limitRepeater ());
0340   sett->setString ("encoding", sdlg->encoding ());
0341   sett->setBool ("startup-negotiate", sdlg->negotiateOnStartup ());
0342   sett->setBool ("lpmud-style", sdlg->LPMudStyle());
0343   sett->setBool ("prompt-label", sdlg->promptLabel());
0344   sett->setBool ("prompt-status", sdlg->statusPrompt());
0345   sett->setBool ("prompt-console", sdlg->consolePrompt());
0346   sett->setBool ("auto-adv-transcript", sdlg->autoAdvTranscript());
0347 
0348   for (int i = 0; i < 10; i++)
0349     sett->setString ("movement-command-"+QString::number(i), sdlg->movementCmd (i));
0350   sett->setString ("script-directory", sdlg->scriptDir ());
0351   sett->setString ("script-working-directory", sdlg->scriptWorkDir ());
0352   sett->setString ("transcript-directory", sdlg->transcriptDir ());
0353 
0354   QStringList sdirs = sdlg->soundDirList();
0355   sett->setInt ("sound-dir-count", sdirs.size());
0356   int idx = 0;
0357   QStringList::iterator it;
0358   for (it = sdirs.begin(); it != sdirs.end(); ++it)
0359     sett->setString ("sound-dir-" + QString::number (++idx), *it);
0360   sett->setBool ("use-msp", sdlg->useMSP());
0361   sett->setBool ("always-msp", sdlg->alwaysMSP());
0362   sett->setBool ("midline-msp", sdlg->midlineMSP());
0363 
0364 #ifdef HAVE_MXP
0365   sett->setInt ("use-mxp", sdlg->MXPAllowed());
0366   sett->setString ("mxp-variable-prefix", sdlg->variablePrefix ());
0367 #endif  //HAVE_MXP
0368 
0369   //inform everyone ...
0370   invokeEvent ("dialog-save", sess(), "profile-prefs");
0371   invokeEvent ("settings-changed", sess());
0372 
0373   sett->save ();
0374 }
0375 
0376 void cConnection::putSettingsToDialog ()
0377 {
0378   cProfileSettings *sett = settings ();
0379   if (!sett) return;  // should never happen
0380 
0381   dlgProfileSettings *sdlg = d->sdlg;
0382 
0383   sdlg->setUseAnsi (sett->getBool ("use-ansi"));
0384   sdlg->setLimitRepeater (sett->getBool ("limit-repeater"));
0385   sdlg->setEncoding (sett->getString ("encoding"));
0386   sdlg->setNegotiateOnStartup (sett->getBool ("startup-negotiate"));
0387   sdlg->setLPMudStyle (sett->getBool ("lpmud-style"));
0388   sdlg->setPromptLabel (sett->getBool ("prompt-label"));
0389   sdlg->setStatusPrompt (sett->getBool ("prompt-status"));
0390   sdlg->setConsolePrompt (sett->getBool ("prompt-console"));
0391   sdlg->setAutoAdvTranscript (sett->getBool ("auto-adv-transcript"));
0392 
0393   for (int i = 0; i < 10; i++)
0394     sdlg->setMovementCmd (i, sett->getString ("movement-command-"+QString::number(i)));
0395   sdlg->setScriptDir (sett->getString ("script-directory"));
0396   sdlg->setScriptWorkDir (sett->getString ("script-working-directory"));
0397   sdlg->setTranscriptDir (sett->getString ("transcript-directory"));
0398 
0399   QStringList sdirs;
0400   int cnt = sett->getInt ("sound-dir-count");
0401   for (int i = 1; i <= cnt; ++i)
0402     sdirs << sett->getString ("sound-dir-" + QString::number (i));
0403   sdlg->setSoundDirList (sdirs);
0404   sdlg->setUseMSP (sett->getBool ("use-msp"));
0405   sdlg->setAlwaysMSP (sett->getBool ("always-msp"));
0406   sdlg->setMidlineMSP (sett->getBool ("midline-msp"));
0407 
0408 #ifdef HAVE_MXP
0409   sdlg->setMXPAllowed (sett->getInt ("use-mxp"));
0410   sdlg->setVariablePrefix (sett->getString ("mxp-variable-prefix"));
0411 #endif  //HAVE_MXP
0412 
0413   invokeEvent ("dialog-create", sess(), "profile-prefs");
0414 }
0415 
0416 bool cConnection::handleDisconnect ()
0417 {
0418   if (!isConnected())
0419     return true;    //no longer connected
0420   //ask if he really wants to disconnect
0421   if (KMessageBox::questionTwoActionsCancel (KMuddy::self(),
0422         i18n("Do you want to close connection to %1?", d->caption),
0423         i18n("Disconnect"), KGuiItem(i18n("Close connection")), KGuiItem(i18n("Stay connected"))) == KMessageBox::PrimaryAction)
0424   {
0425     disconnect ();
0426     return true;
0427   }
0428   return false;
0429 }
0430 
0431 void cConnection::establishConnection (const QString &profileName, bool sendNothing)
0432 {
0433   cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet", sess()));
0434   if (!telnet)
0435     return;
0436   cProfileSettings *sett = cProfileManager::self()->settings (profileName);
0437   if (!sett) return;
0438 
0439   d->profileConnection = true;
0440   d->profileName = profileName;
0441   d->sendNothing = sendNothing;
0442 
0443   if (telnet->isConnected ())
0444     disconnect ();
0445 
0446   d->connInProgress = true;
0447   d->qconnInProgress = false;
0448   telnet->connectIt (sett->getString ("server"), sett->getInt ("port"), sett);
0449   // now we wait for event from telnet (standard connections only, offline ones
0450   // return immediately)
0451 }
0452 
0453 void cConnection::sendLoginAndPassword ()
0454 {
0455   //This function is used to send login sequence (usually login name and
0456   //password) to the MUD.
0457   //Problem: it's not very good at detecting login prompt - name can be sent
0458   //too early, causing password to be sent too early as well...
0459   //I can only hope that the server will handle that properly.
0460 
0461   cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet", sess()));
0462   if (!telnet)
0463     return;
0464   static int wasData = false; //have some data already arrived?
0465 
0466   cProfileSettings *sett = cProfileManager::self()->settings (sess());
0467   if (!sett) return;
0468 
0469   if (telnet->isConnected())
0470   {
0471     if (wasData)
0472     {
0473       if (telnet->newData() || (d->seqIter == d->loginSeq.begin()))
0474       //only send next command if something new has arrived (should be reply
0475       //to previous sent command). Also send it if it's the first command,
0476       //where the required data was received during previous call - used to
0477       //wait for intro screens and such).
0478       {
0479         //get next command from login sequence
0480         QString command = *d->seqIter;
0481         QString cmd = "", cmddisp = "";
0482 
0483         //expand $name and $password
0484         int len = command.length();
0485         QString varname = QString();
0486 
0487         bool expanded = false;
0488         bool invar = false;
0489         for (int i = 0; i < len; i++)
0490         {
0491           if (invar)
0492           {
0493             varname += command[i];
0494             if (varname == "$name")
0495             {
0496               varname = "";
0497               invar = false;
0498               cmd += sett->getString ("login");
0499               cmddisp += sett->getString ("login");
0500               expanded = true;
0501             }
0502             if (varname == "$password")
0503             {
0504               varname = "";
0505               invar = false;
0506               cmd += sett->getString ("password");
0507               cmddisp += i18n("(password is hidden)");
0508               expanded = true;
0509             }
0510           }
0511           else
0512             if (command[i].toLatin1() == '$')
0513             {
0514               invar = true;
0515               varname = "$";
0516             }
0517             else
0518             {
0519               cmd += command[i];
0520               cmddisp += command[i];
0521             }
0522         }
0523 
0524         //send resulting command and display notification
0525         //lines containing the name and password are sent as-is, others are sent to the
0526         //command processor - hence aliases/script names/... get expanded
0527         if (expanded)
0528         {
0529           if (!cmd.isEmpty()) {  // but don't send anything if we expanded to nothing - otherwise we send two empty lines if the user didn't specify name/password
0530             telnet->sendData(cmd);
0531             telnet->sendData("\n");
0532             invokeEvent ("command-sent", sess(), cmddisp);
0533           }
0534         }
0535         else
0536           // we have a command to send ...
0537           invokeEvent ("command", sess(), cmd);
0538 
0539         telnet->waitingForData();
0540 
0541         //advance to next command (that will be sent on next call)
0542         ++d->seqIter;
0543 
0544         //finish execution if there's nothing more to send
0545         if (d->seqIter == d->loginSeq.end())
0546         {
0547           d->connecting->stop ();
0548           //I have no idea why this is needed
0549           QObject::disconnect (d->connecting, &QTimer::timeout, this, &cConnection::sendLoginAndPassword);
0550           delete d->connecting;
0551           d->connecting = nullptr;
0552           wasData = false;
0553         }
0554       }
0555     }
0556     else
0557       if (telnet->newData())
0558       {
0559         telnet->waitingForData();
0560         wasData = true;
0561       }
0562   }
0563   else
0564   {
0565     d->connecting->stop ();
0566     //I have no idea why this is needed
0567     QObject::disconnect (d->connecting, &QTimer::timeout, this, &cConnection::sendLoginAndPassword);
0568     delete d->connecting;
0569     d->connecting = nullptr;
0570     wasData = false;
0571   }
0572 }
0573 
0574 void cConnection::establishQuickConnection (const QString &server, int port)
0575 {
0576   cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet", sess()));
0577   if (!telnet)
0578     return;
0579 
0580   if (telnet->isConnected ())
0581     disconnect ();
0582   d->profileConnection = false;
0583   d->quickServer = server;
0584   d->quickPort = port;
0585   d->connInProgress = false;
0586   d->qconnInProgress = true;
0587   telnet->connectIt (server, port);
0588 
0589   // now wait for event from telnet
0590 }
0591 
0592 bool cConnection::isConnected ()
0593 {
0594   cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet", sess()));
0595   if (!telnet)
0596     return false;
0597 
0598   return telnet->isConnected ();
0599 }
0600 
0601 void cConnection::disconnect ()
0602 {
0603   cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet", sess()));
0604   if (telnet == nullptr)
0605     return;
0606 
0607   if (d->connecting != nullptr)
0608   {
0609     d->connecting->stop ();
0610     delete d->connecting;
0611     d->connecting = nullptr;
0612   }
0613   d->saver->stop ();
0614   setAttrib ("connected", 0);
0615   if (cProfileManager::self()->settings (sess()))
0616     invokeEvent ("save", sess());
0617 
0618   //clear command queue, so that pending commands don't close the tab
0619   //immediately
0620   d->commands = QString();
0621 
0622   // adjust menus, but only if this session is the active one
0623   if ((!d->destroying) && (cActionManager::self()->activeSession() == sess()))
0624   {
0625     KMuddy::self()->disableConnectedOptions ();
0626     KMuddy::self()->disableAdvancedOptions ();
0627   }
0628 
0629   // this dontDelete thing is a work-around for the event priorities problem, should be removed after that's fixed
0630   static bool dontDelete = false;
0631   if (dontDelete) return;
0632   dontDelete = true;
0633 
0634   if (telnet->isConnected())
0635     telnet->disconnect ();
0636 
0637   dontDelete = false;
0638 
0639   // delete our held lists - must be after the disconnected event, as the variable list
0640   // may still be needed there
0641   delete d->variablelist;
0642   delete d->windowlist;
0643   d->variablelist = nullptr;
0644   d->windowlist = nullptr;
0645 }
0646 
0647 void cConnection::reconnect ()
0648 {
0649   //inform plug-ins
0650   invokeEvent ("reconnect", sess());
0651   d->commandNum = 0;
0652 
0653   //reconnect...
0654   if (d->profileConnection)
0655     establishConnection (d->profileName, d->sendNothing);
0656   else
0657     establishQuickConnection (d->quickServer, d->quickPort);
0658 }
0659 
0660 void cConnection::addCommands (const QStringList &commands)
0661 {
0662   QStringList::const_iterator it;
0663   for (it = commands.begin(); it != commands.end(); ++it)
0664     addCommand (*it);
0665 }
0666 
0667 void cConnection::addCommand (const QString &command)
0668 {
0669   QString cmd = command;
0670   invokeEvent ("new-command", sess(), cmd);
0671   if ((command != QString()) && (cmd == QString())) {
0672     // the handler has cleared the command - do not send it
0673     return;
0674   }
0675   d->commands += cmd;
0676   d->commands += "\r\n";
0677   if (!d->waitCommands)
0678     sendCommands ();
0679 
0680   // technically, this is wrong, because the command can still be in the queue,
0681   // but I believe it's sufficient
0682   d->commandNum++;
0683   invokeEvent ("command-sent", sess(), command);
0684 }
0685 
0686 void cConnection::sendCommands ()
0687 {
0688   // TODO: reimplent using the modern architecture
0689   cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet", sess()));
0690   if (telnet == nullptr)
0691     return;
0692   if (d->commands != QString())
0693     telnet->sendData (d->commands);
0694   d->commands = QString();
0695   d->waitCommands = false;
0696 }
0697 
0698 int cConnection::sentCommands ()
0699 {
0700   return d->commandNum;
0701 }
0702 
0703 void cConnection::handleWindowsDialog ()
0704 {
0705   cWindowList *wl = dynamic_cast<cWindowList *>(object ("windowlist"));
0706   if (!wl)
0707     return;
0708 
0709   dlgWindows *wdlg = new dlgWindows (wl, KMuddy::self());
0710 
0711   wdlg->exec ();
0712 
0713   delete wdlg;
0714 
0715   invokeEvent ("save", sess());
0716 }
0717 
0718 void cConnection::switchAliases (bool val)
0719 {
0720   cListManager *lm = cListManager::self();
0721   cAliasList *al = dynamic_cast<cAliasList *>(lm->getList (sess(), "aliases"));
0722   if (!al)
0723     return;
0724   al->setEnabled (val);
0725   invokeEvent ("message", sess(),
0726       val ? i18n ("Aliases are now enabled.") : i18n ("Aliases are now disabled."));
0727 }
0728 
0729 void cConnection::switchTriggers (bool val)
0730 {
0731   cListManager *lm = cListManager::self();
0732   cTriggerList *tl = dynamic_cast<cTriggerList *>(lm->getList (sess(), "triggers"));
0733   if (!tl)
0734     return;
0735   tl->setEnabled (val);
0736   invokeEvent ("message", sess(),
0737       val ? i18n ("Triggers are now enabled.") : i18n ("Triggers are now disabled."));
0738 }
0739 
0740 void cConnection::switchTimers (bool val)
0741 {
0742   cListManager *lm = cListManager::self();
0743   cTimerList *tl = dynamic_cast<cTimerList *>(lm->getList (sess(), "timers"));
0744   if (!tl)
0745     return;
0746   tl->setEnabled (val);
0747   invokeEvent ("message", sess(),
0748       val ? i18n ("Timers are now enabled.") : i18n ("Timers are now disabled."));
0749 }
0750 
0751 void cConnection::switchShortcuts (bool val)
0752 {
0753   cListManager *lm = cListManager::self();
0754   cShortcutList *sl = dynamic_cast<cShortcutList *>(lm->getList (sess(), "shortcuts"));
0755   if (!sl)
0756     return;
0757   sl->setEnabled (val);
0758   invokeEvent ("message", sess(),
0759       val ? i18n ("Macro keys are now enabled.") : i18n ("Macro keys are now disabled."));
0760 }
0761 
0762 void cConnection::updateMenus ()
0763 {
0764   // do nothing if this session is not active
0765   if (sess() != cSessionManager::self()->activeSession())
0766     return;
0767 
0768   // TODO: reimplent using the modern architecture
0769   cTelnet *telnet = dynamic_cast<cTelnet *>(object ("telnet", sess()));
0770   if (!telnet)
0771     return;
0772   if (telnet->isConnected())
0773   {
0774     KMuddy::self()->unsetClosedConn ();
0775     KMuddy::self()->enableConnectedOptions();
0776     if (settings())
0777       KMuddy::self()->enableAdvancedOptions();
0778     else
0779       KMuddy::self()->disableAdvancedOptions();
0780 
0781     if (settings())
0782     {
0783       cListManager *lm = cListManager::self();
0784       cList *al = lm->getList (sess(), "aliases");
0785       cList *tl = lm->getList (sess(), "triggers");
0786       cList *ml = lm->getList (sess(), "timers");
0787       cList *sl = lm->getList (sess(), "shortcuts");
0788       if (al) KMuddy::self()->setMenuAliasesEnabled (al->enabled ());
0789       if (tl) KMuddy::self()->setMenuTriggersEnabled (tl->enabled ());
0790       if (ml) KMuddy::self()->setMenuTimersEnabled (ml->enabled ());
0791       if (sl) KMuddy::self()->setMenuShortcutsEnabled (sl->enabled ());
0792     }
0793   }
0794   else
0795   {
0796     KMuddy::self()->disableConnectedOptions();
0797     if (d->connclosed)
0798       KMuddy::self()->setClosedConn (d->canCT);
0799     else
0800       KMuddy::self()->unsetClosedConn ();
0801   }
0802 }
0803 
0804 void cConnection::registerLists ()
0805 {
0806   static bool registered = false;
0807   if (registered) return;
0808   registered = true;
0809 
0810   cListManager *lm = cListManager::self();
0811  
0812   lm->registerType ("aliases", i18n ("Aliases"), cAliasList::newList);
0813   lm->registerType ("triggers", i18n ("Triggers"), cTriggerList::newList);
0814   lm->registerType ("buttons", i18n ("Buttons"), cButtonList::newList);
0815   lm->registerType ("timers", i18n ("Timers"), cTimerList::newList);
0816   lm->registerType ("macrokeys", i18n ("Macro Keys"), cShortcutList::newList);
0817   lm->registerType ("statusvars", i18n ("Status variables"), cStatusVarList::newList);
0818   lm->registerType ("gauges", i18n ("Gauges"), cGaugeList::newList);
0819   // lm->registerType ("windows", i18n ("Output Windows"), cWindowList::newList);
0820 }
0821 
0822 void cConnection::saveSession ()
0823 {
0824   invokeEvent ("save", sess());
0825 }
0826 
0827 void cConnection::save ()
0828 {
0829   if (d->variablelist)
0830     d->variablelist->save();
0831   if (d->windowlist)
0832     d->windowlist->save();
0833 }
0834 
0835 #include "moc_cconnection.cpp"