From c90c389a8a8d9d8661e9772ec4144c5cf2039f23 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegames@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kbackgammon/engines/fibs/kbgfibschat.cpp | 828 +++++++++++++++++++++++++++++++ 1 file changed, 828 insertions(+) create mode 100644 kbackgammon/engines/fibs/kbgfibschat.cpp (limited to 'kbackgammon/engines/fibs/kbgfibschat.cpp') diff --git a/kbackgammon/engines/fibs/kbgfibschat.cpp b/kbackgammon/engines/fibs/kbgfibschat.cpp new file mode 100644 index 00000000..45ba2bb7 --- /dev/null +++ b/kbackgammon/engines/fibs/kbgfibschat.cpp @@ -0,0 +1,828 @@ + +/* Yo Emacs, this -*- C++ -*- + + Copyright (C) 1999-2001 Jens Hoefkens + jens@hoefkens.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + $Id$ + +*/ + + +#include "kbgfibschat.h" +#include "kbgfibschat.moc" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clip.h" +#include "version.h" + + +/* + * Private utility class that might become more generally useful in + * the future. Basically, it implements rich text QListBox items. + */ +class KLBT : public QListBoxText +{ + +public: + + /* + * Constructor + */ + KLBT(QWidget *parent, const QString &text = QString::null, const QString &player = QString::null) + : QListBoxText(text) + { + w = parent; + n = new QString(player); + t = new QSimpleRichText(text, w->font()); + + // FIXME: this is not yet perfect + t->setWidth(w->width()-20); + } + + /* + * Destructor + */ + virtual ~KLBT() + { + delete t; + delete n; + } + + /* + * Overloaded required members returning height + */ + virtual int height(const QListBox *) const + { + return (1+t->height()); + } + + /* + * Overloaded required members returning width + */ + virtual int width(const QListBox *) const + { + return t->width(); + } + + /* + * The context menu needs the name of the player. It's easier + * than extracting it from the text. + */ + QString player() const + { + return *n; + } + +protected: + + /* + * Required overloaded member to paint the text on the painter p. + */ + virtual void paint(QPainter *p) + { + t->draw(p, 1, 1, QRegion(p->viewport()), w->colorGroup()); + } + +private: + + QSimpleRichText *t; + QWidget *w; + QString *n; + +}; + + +class KBgChatPrivate +{ +public: + + /* + * Name of the users + */ + QString mName[2]; + + /* + * Hold and assemble info text + */ + QString mText; + + /* + * Numbers of the private action list. + */ + enum Privact {Inquire, InviteD, Invite1, Invite2, Invite3, Invite4, + Invite5, Invite6, Invite7, InviteR, InviteU, Silent, + Talk, Gag, Ungag, Cleargag, Copy, Clear, Close, MaxAction}; + + /* + * Available actions + */ + KAction *mAct[MaxAction]; + + /* + * Context menu and invitation menu + */ + QPopupMenu *mChat, *mInvt; + + /* + * list of users we do not want to hear shouting + */ + QStringList mGag; + + /* + * Listbox needed by the setup dialog + */ + QListBox *mLb; + + /* + * Internal ID to name mapping + */ + QDict *mName2ID; + +}; + + +// == constructor, destructor ================================================== + +/* + * Constructor of the chat window. + */ +KBgChat::KBgChat(QWidget *parent, const char *name) + : KChat(parent, false) +{ + d = new KBgChatPrivate(); + KActionCollection* actions = new KActionCollection(this); + + d->mName[0] = QString::null; + d->mChat = 0; + d->mInvt = new QPopupMenu(); + + setAutoAddMessages(false); // we get an echo from FIBS + setFromNickname(i18n("%1 user").arg(PROG_NAME)); + + if (!addSendingEntry(i18n("Kibitz to watchers and players"), CLIP_YOU_KIBITZ)) + kdDebug(10500) << "adding kibitz" << endl; + if (!addSendingEntry(i18n("Whisper to watchers only"), CLIP_YOU_WHISPER)) + kdDebug(10500) << "adding whisper" << endl; + + connect(this, SIGNAL(rightButtonClicked(QListBoxItem *, const QPoint &)), + this, SLOT(contextMenu(QListBoxItem *, const QPoint &))); + connect(this, SIGNAL(signalSendMessage(int, const QString &)), + this, SLOT(handleCommand(int, const QString &))); + + d->mName2ID = new QDict(17, true); + d->mName2ID->setAutoDelete(true); + + /* + * some eye candy :) + */ + setIcon(kapp->miniIcon()); + setCaption(i18n("Chat Window")); + + QWhatsThis::add(this, i18n("This is the chat window.\n\n" + "The text in this window is colored depending on whether " + "it is directed at you personally, shouted to the general " + "FIBS population, has been said by you, or is of general " + "interest. If you select the name of a player, the context " + "contains entries specifically geared towards that player.")); + /* + * Define set of available actions + */ + d->mAct[KBgChatPrivate::Inquire] = new KAction(i18n("Info On"), + QIconSet(kapp->iconLoader()->loadIcon( + "help.xpm", KIcon::Small)), + 0, this, SLOT(slotInquire()), actions); + d->mAct[KBgChatPrivate::Talk] = new KAction(i18n("Talk To"), + QIconSet(kapp->iconLoader()->loadIcon( + PROG_NAME "-chat.png", KIcon::Small)), + 0, this, SLOT(slotTalk()), actions); + + d->mAct[KBgChatPrivate::InviteD] = new KAction(i18n("Use Dialog"), 0, this, + SLOT(slotInviteD()), actions); + d->mAct[KBgChatPrivate::Invite1] = new KAction(i18n("1 Point Match"), 0, this, + SLOT(slotInvite1()), actions); + d->mAct[KBgChatPrivate::Invite2] = new KAction(i18n("2 Point Match"), 0, this, + SLOT(slotInvite2()), actions); + d->mAct[KBgChatPrivate::Invite3] = new KAction(i18n("3 Point Match"), 0, this, + SLOT(slotInvite3()), actions); + d->mAct[KBgChatPrivate::Invite4] = new KAction(i18n("4 Point Match"), 0, this, + SLOT(slotInvite4()), actions); + d->mAct[KBgChatPrivate::Invite5] = new KAction(i18n("5 Point Match"), 0, this, + SLOT(slotInvite5()), actions); + d->mAct[KBgChatPrivate::Invite6] = new KAction(i18n("6 Point Match"), 0, this, + SLOT(slotInvite6()), actions); + d->mAct[KBgChatPrivate::Invite7] = new KAction(i18n("7 Point Match"), 0, this, + SLOT(slotInvite7()), actions); + d->mAct[KBgChatPrivate::InviteU] = new KAction(i18n("Unlimited"), 0, this, + SLOT(slotInviteU()), actions); + d->mAct[KBgChatPrivate::InviteR] = new KAction(i18n("Resume"), 0, this, + SLOT(slotInviteR()), actions); + + d->mAct[KBgChatPrivate::InviteD]->plug(d->mInvt); + + d->mInvt->insertSeparator(); + + d->mAct[KBgChatPrivate::Invite1]->plug(d->mInvt); + d->mAct[KBgChatPrivate::Invite2]->plug(d->mInvt); + d->mAct[KBgChatPrivate::Invite3]->plug(d->mInvt); + d->mAct[KBgChatPrivate::Invite4]->plug(d->mInvt); + d->mAct[KBgChatPrivate::Invite5]->plug(d->mInvt); + d->mAct[KBgChatPrivate::Invite6]->plug(d->mInvt); + d->mAct[KBgChatPrivate::Invite7]->plug(d->mInvt); + + d->mInvt->insertSeparator(); + + d->mAct[KBgChatPrivate::InviteU]->plug(d->mInvt); + d->mAct[KBgChatPrivate::InviteR]->plug(d->mInvt); + + d->mAct[KBgChatPrivate::Gag] = new KAction(i18n("Gag"), 0, this, SLOT(slotGag()), actions); + d->mAct[KBgChatPrivate::Ungag] = new KAction(i18n("Ungag"), 0, this, SLOT(slotUngag()), actions); + d->mAct[KBgChatPrivate::Cleargag] = new KAction(i18n("Clear Gag List"), 0, this, SLOT(slotCleargag()), actions); + d->mAct[KBgChatPrivate::Copy] = KStdAction::copy(this, SLOT(slotCopy()), actions); + d->mAct[KBgChatPrivate::Clear] = new KAction(i18n("Clear"), 0, this, SLOT(slotClear()), actions); + d->mAct[KBgChatPrivate::Close] = KStdAction::close(this, SLOT(hide()), actions); + d->mAct[KBgChatPrivate::Silent] = new KToggleAction(i18n("Silent"), 0, this, SLOT(slotSilent()), actions); +} + + +/* + * Destructor + */ +KBgChat::~KBgChat() +{ + delete d->mName2ID; + delete d->mChat; // save to delete NULL pointers + delete d->mInvt; + delete d; +} + + +// == configuration handling =================================================== + +/* + * Restore the previously stored settings + */ +void KBgChat::readConfig() +{ + KConfig* config = kapp->config(); + config->setGroup("chat window"); + + QPoint pos(10, 10); + + pos = config->readPointEntry("ori", &pos); + setGeometry(pos.x(), pos.y(), config->readNumEntry("wdt",460), config->readNumEntry("hgt",200)); + + config->readBoolEntry("vis", false) ? show() : hide(); + + ((KToggleAction *)d->mAct[KBgChatPrivate::Silent])->setChecked(config->readBoolEntry("sil", false)); + + d->mGag = config->readListEntry("gag"); +} + +/* + * Save the current settings to disk + */ +void KBgChat::saveConfig() +{ + KConfig* config = kapp->config(); + config->setGroup("chat window"); + + config->writeEntry("ori", pos()); + config->writeEntry("hgt", height()); + config->writeEntry("wdt", width()); + config->writeEntry("vis", isVisible()); + + config->writeEntry("sil", ((KToggleAction *)d->mAct[KBgChatPrivate::Silent])->isChecked()); + + config->writeEntry("gag", d->mGag); +} + + +/* + * Setup dialog page of the player list - allow the user to select the + * columns to show + * + * FIXME: need to be able to set font here KChatBase::setBothFont(const QFont& font) + */ +void KBgChat::getSetupPages(KTabCtl *nb, int space) +{ + /* + * Main Widget + * =========== + */ + QWidget *w = new QWidget(nb); + QGridLayout *gl = new QGridLayout(w, 2, 1, space); + + d->mLb = new QListBox(w); + d->mLb->setMultiSelection(true); + + d->mLb->insertStringList(d->mGag); + + QLabel *info = new QLabel(w); + info->setText(i18n("Select users to be removed from the gag list.")); + + QWhatsThis::add(w, i18n("Select all the users you want " + "to remove from the gag list " + "and then click OK. Afterwards " + "you will again hear what they shout.")); + + gl->addWidget(d->mLb, 0, 0); + gl->addWidget(info, 1, 0); + + /* + * put in the page + * =============== + */ + gl->activate(); + w->adjustSize(); + w->setMinimumSize(w->size()); + nb->addTab(w, i18n("&Gag List")); +} + +/* + * Remove all the selected entries from the gag list + */ +void KBgChat::setupOk() +{ + for (uint i = 0; i < d->mLb->count(); ++i) { + if (d->mLb->isSelected(i)) + d->mGag.remove(d->mLb->text(i)); + } + d->mLb->clear(); + d->mLb->insertStringList(d->mGag); +} + +/* + * Don't do anything + */ +void KBgChat::setupCancel() +{ + // empty +} + +/* + * By default, all players stay in the gag list + */ +void KBgChat::setupDefault() +{ + d->mLb->clearSelection(); +} + + +// == various slots and functions ============================================== + +/* + * Overloaded member to create a QListBoxItem for the chat window. + */ +QListBoxItem* KBgChat::layoutMessage(const QString& fromName, const QString& text) +{ + QListBoxText* message = new KLBT(this, text, fromName); + return message; +} + +/* + * Catch hide events, so the engine's menu can be update. + */ +void KBgChat::showEvent(QShowEvent *e) +{ + QFrame::showEvent(e); + emit windowVisible(true); +} + +/* + * Catch hide events, so the engine's menu can be update. + */ +void KBgChat::hideEvent(QHideEvent *e) +{ + emit windowVisible(false); + QFrame::hideEvent(e); +} + +/* + * At the beginning of a game, add the name to the list and switch to + * kibitz mode. + */ +void KBgChat::startGame(const QString &name) +{ + int *id = d->mName2ID->find(d->mName[1] = name); + if (!id) { + id = new int(nextId()); + d->mName2ID->insert(name, id); + addSendingEntry(i18n("Talk to %1").arg(name), *id); + } + setSendingEntry(CLIP_YOU_KIBITZ); +} + +/* + * At the end of a game, we switch to talk mode. + */ +void KBgChat::endGame() +{ + int *id = d->mName2ID->find(d->mName[1]); + if (id) + setSendingEntry(*id); + else + setSendingEntry(SendToAll); +} + +/* + * Set the chat window ready to talk to name + */ +void KBgChat::fibsTalk(const QString &name) +{ + int *id = d->mName2ID->find(name); + if (!id) { + id = new int(nextId()); + d->mName2ID->insert(name, id); + addSendingEntry(i18n("Talk to %1").arg(name), *id); + } + setSendingEntry(*id); +} + +/* + * Remove the player from the combo box when he/she logs out. + */ +void KBgChat::deletePlayer(const QString &name) +{ + int *id = d->mName2ID->find(name); + if (id) { + removeSendingEntry(*id); + d->mName2ID->remove(name); + } +} + +/* + * Take action when the user presses return in the line edit control. + */ +void KBgChat::handleCommand(int id, const QString& msg) +{ + int realID = sendingEntry(); + + switch (realID) { + case SendToAll: + emit fibsCommand("shout " + msg); + break; + case CLIP_YOU_KIBITZ: + emit fibsCommand("kibitz " + msg); + break; + case CLIP_YOU_WHISPER: + emit fibsCommand("whisper " + msg); + break; + default: + QDictIterator it(*d->mName2ID); + while (it.current()) { + if (*it.current() == realID) { + emit fibsCommand("tell " + it.currentKey() + " " + msg); + return; + } + ++it; + } + kdDebug(10500) << "unrecognized ID in KBgChat::handleCommand" << endl; + } +} + + +// == handle strings from the server =========================================== + +/* + * A message from the server that should be handled by us. If necessary, + * we replace the CLIP number by a string and put the line into the window. + * + * This function emits the string in rich text format with the signal + * personalMessage - again: the string contains rich text! + */ +void KBgChat::handleData(const QString &msg) +{ + QString clip = msg.left(msg.find(' ')), user, cMsg = msg; + QDateTime date; + + bool flag = false; + int cmd = clip.toInt(&flag); + + if (flag) { + cMsg.replace(0, cMsg.find(' ')+1, ""); + + user = cMsg.left(cMsg.find(' ')); + + switch (cmd) { + case CLIP_SAYS: + if (!d->mGag.contains(user)) { + cMsg = i18n("%1 tells you: %2").arg(user).arg(cMsg.replace(QRegExp("^" + user), "")); + cMsg = "" + cMsg + ""; + emit personalMessage(cMsg); + } else + cMsg = ""; + break; + + case CLIP_SHOUTS: + if ((!((KToggleAction *)d->mAct[KBgChatPrivate::Silent])->isChecked()) && (!d->mGag.contains(user))) { + cMsg = i18n("%1 shouts: %2").arg(user).arg(cMsg.replace(QRegExp("^" + user), "")); + cMsg = "" + cMsg + ""; + } else + cMsg = ""; + break; + + case CLIP_WHISPERS: + if (!d->mGag.contains(user)) { + cMsg = i18n("%1 whispers: %2").arg(user).arg(cMsg.replace(QRegExp("^" + user), "")); + cMsg = "" + cMsg + ""; + emit personalMessage(cMsg); + } else + cMsg = ""; + break; + + case CLIP_KIBITZES: + if (!d->mGag.contains(user)) { + cMsg = i18n("%1 kibitzes: %2").arg(user).arg(cMsg.replace(QRegExp("^" + user), "")); + cMsg = "" + cMsg + ""; + emit personalMessage(cMsg); + } else + cMsg = ""; + break; + + case CLIP_YOU_SAY: + cMsg = i18n("You tell %1: %2").arg(user).arg(cMsg.replace(QRegExp("^" + user), "")); + cMsg = "" + cMsg + ""; + emit personalMessage(cMsg); + user = QString::null; + break; + + case CLIP_YOU_SHOUT: + cMsg = i18n("You shout: %1").arg(cMsg); + cMsg = "" + cMsg + ""; + emit personalMessage(cMsg); + user = QString::null; + break; + + case CLIP_YOU_WHISPER: + cMsg = i18n("You whisper: %1").arg(cMsg); + cMsg = "" + cMsg + ""; + emit personalMessage(cMsg); + user = QString::null; + break; + + case CLIP_YOU_KIBITZ: + cMsg = i18n("You kibitz: %1").arg(cMsg); + cMsg = "" + cMsg + ""; + emit personalMessage(cMsg); + user = QString::null; + break; + + case CLIP_MESSAGE: + user = cMsg.left(cMsg.find(' ')+1); + cMsg.remove(0, cMsg.find(' ')+1); + date.setTime_t(cMsg.left(cMsg.find(' ')+1).toUInt()); + cMsg.remove(0, cMsg.find(' ')); + cMsg = i18n("User %1 left a message at %2: %3").arg(user).arg(date.toString()).arg(cMsg); + cMsg = "" + cMsg + ""; + emit personalMessage(cMsg); + user = QString::null; + break; + + case CLIP_MESSAGE_DELIVERED: + cMsg = i18n("Your message for %1 has been delivered.").arg(user); + cMsg = QString("") + cMsg + ""; + emit personalMessage(cMsg); + user = QString::null; + break; + + case CLIP_MESSAGE_SAVED: + cMsg = i18n("Your message for %1 has been saved.").arg(user); + cMsg = QString("") + cMsg + ""; + emit personalMessage(cMsg); + user = QString::null; + break; + + default: // ignore the message + return; + } + + } else { + + /* + * Special treatment for non-CLIP messages + */ + if (cMsg.contains(QRegExp("^You say to yourself: "))) { + cMsg.replace(QRegExp("^You say to yourself: "), + i18n("You say to yourself: ")); + } else { + kdDebug(user.isNull(), 10500) << "KBgChat::handleData unhandled message: " + << cMsg.latin1() << endl; + return; + } + } + + if (!cMsg.isEmpty()) + addMessage(user, cMsg); +} + + +// == context menu and related slots =========================================== + +/* + * RMB opens a context menu. + */ +void KBgChat::contextMenu(QListBoxItem *i, const QPoint &p) +{ + /* + * Even if i is non-null, user might still be QString::null + */ + d->mName[0] = (i == 0) ? QString::null : ((KLBT *)i)->player(); + d->mText = (i == 0) ? QString::null : ((KLBT *)i)->text(); + + /* + * Get a new context menu every time. Safe to delete the 0 + * pointer. + */ + delete d->mChat; d->mChat = new QPopupMenu(); + + /* + * Fill the context menu with actions + */ + if (!d->mName[0].isNull()) { + + d->mAct[KBgChatPrivate::Talk]->setText(i18n("Talk to %1").arg(d->mName[0])); + d->mAct[KBgChatPrivate::Talk]->plug(d->mChat); + + d->mAct[KBgChatPrivate::Inquire]->setText(i18n("Info on %1").arg(d->mName[0])); + d->mAct[KBgChatPrivate::Inquire]->plug(d->mChat); + + // invite menu is always the same + d->mChat->insertItem(i18n("Invite %1").arg(d->mName[0]), d->mInvt); + + d->mChat->insertSeparator(); + + if (d->mGag.contains(d->mName[0]) <= 0) { + d->mAct[KBgChatPrivate::Gag]->setText(i18n("Gag %1").arg(d->mName[0])); + d->mAct[KBgChatPrivate::Gag]->plug(d->mChat); + } else { + d->mAct[KBgChatPrivate::Ungag]->setText(i18n("Ungag %1").arg(d->mName[0])); + d->mAct[KBgChatPrivate::Ungag]->plug(d->mChat); + } + } + if (d->mGag.count() > 0) + d->mAct[KBgChatPrivate::Cleargag]->plug(d->mChat); + + if ((d->mGag.count() > 0) || (!d->mName[0].isNull())) + d->mChat->insertSeparator(); + + d->mAct[KBgChatPrivate::Silent]->plug(d->mChat); + + d->mChat->insertSeparator(); + + d->mAct[KBgChatPrivate::Copy ]->plug(d->mChat); + d->mAct[KBgChatPrivate::Clear]->plug(d->mChat); + d->mAct[KBgChatPrivate::Close]->plug(d->mChat); + + d->mChat->popup(p); +} + +/* + * Clear the gag list + */ +void KBgChat::slotCleargag() +{ + d->mGag.clear(); + + QString msg(""); + msg += i18n("The gag list is now empty."); + msg += ""; + + addMessage(QString::null, msg); +} + +/* + * Gag the selected user + */ +void KBgChat::slotGag() +{ + d->mGag.append(d->mName[0]); + + QString msg(""); + msg += i18n("You won't hear what %1 says and shouts.").arg(d->mName[0]); + msg += ""; + + addMessage(QString::null, msg); +} + +/* + * Simple interface to the actual talk slot + */ +void KBgChat::slotTalk() +{ + fibsTalk(d->mName[0]); +} + +/* + * Remove selected user from gag list + */ +void KBgChat::slotUngag() +{ + d->mGag.remove(d->mName[0]); + + QString msg(""); + msg += i18n("You will again hear what %1 says and shouts.").arg(d->mName[0]); + msg += ""; + + addMessage(QString::null, msg); +} + +/* + * Get information on selected user + */ +void KBgChat::slotInquire() +{ + kdDebug(d->mName[0].isNull(), 10500) << "KBgChat::slotInquire: user == null" << endl; + emit fibsCommand("whois " + d->mName[0]); +} + +/* + * Block all shouts from the chat window + */ +void KBgChat::slotSilent() +{ + QString msg; + if (((KToggleAction *)d->mAct[KBgChatPrivate::Silent])->isChecked()) + msg = "" + i18n("You will not hear what people shout.") + ""; + else + msg = "" + i18n("You will hear what people shout.") + ""; + addMessage(QString::null, msg); +} + +/* + * Copy the selected line to the clipboard. Strip the additional HTML + * from the text before copying. + */ +void KBgChat::slotCopy() +{ + d->mText.replace(QRegExp(""), ""); + d->mText.replace(QRegExp(""), ""); + d->mText.replace(QRegExp(""), ""); + d->mText.replace(QRegExp("^.*\">"), ""); + + kapp->clipboard()->setText(d->mText); +} + +/* + * Invite the selected player. + */ +void KBgChat::slotInviteD() +{ + kdDebug(d->mName[0].isNull(), 10500) << "KBgChat::slotInvite: user == null" << endl; + emit fibsRequestInvitation(d->mName[0]); +} +void KBgChat::slotInvite1() { emit fibsCommand("invite " + d->mName[0] + " 1"); } +void KBgChat::slotInvite2() { emit fibsCommand("invite " + d->mName[0] + " 2"); } +void KBgChat::slotInvite3() { emit fibsCommand("invite " + d->mName[0] + " 3"); } +void KBgChat::slotInvite4() { emit fibsCommand("invite " + d->mName[0] + " 4"); } +void KBgChat::slotInvite5() { emit fibsCommand("invite " + d->mName[0] + " 5"); } +void KBgChat::slotInvite6() { emit fibsCommand("invite " + d->mName[0] + " 6"); } +void KBgChat::slotInvite7() { emit fibsCommand("invite " + d->mName[0] + " 7"); } + +void KBgChat::slotInviteU() { emit fibsCommand("invite " + d->mName[0] + " unlimited"); } +void KBgChat::slotInviteR() { emit fibsCommand("invite " + d->mName[0]); } + + +// EOF -- cgit v1.2.1