diff options
Diffstat (limited to 'libtdegames/kchatbase.cpp')
-rw-r--r-- | libtdegames/kchatbase.cpp | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/libtdegames/kchatbase.cpp b/libtdegames/kchatbase.cpp new file mode 100644 index 00000000..14f74103 --- /dev/null +++ b/libtdegames/kchatbase.cpp @@ -0,0 +1,530 @@ +/* + This file is part of the KDE games library + Copyright (C) 2001 Andreas Beckermann ([email protected]) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kchatbase.h" + +#include <klineedit.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kconfig.h> +#include <kapplication.h> +#include <kdebug.h> + +#include <tqlayout.h> +#include <tqcombobox.h> +#include <tqpainter.h> + +class KChatBaseTextPrivate +{ +public: + KChatBaseTextPrivate() + { + mNameFont = 0; + mMessageFont = 0; + } + + TQString mName; + TQString mMessage; + + const TQFont* mNameFont; + const TQFont* mMessageFont; +}; + + +KChatBaseText::KChatBaseText(const TQString& name, const TQString& message) : TQListBoxText() +{ + init(); + setName(name); + setMessage(message); +} + +KChatBaseText::KChatBaseText(const TQString& message) : TQListBoxText() +{ + init(); + setMessage(message); +} + +KChatBaseText::~KChatBaseText() +{ + delete d; +} + +void KChatBaseText::init() +{ + d = new KChatBaseTextPrivate; +} + +void KChatBaseText::setName(const TQString& n) +{ +// d->mName = n; + d->mName = TQString("%1: ").tqarg(n); + setText(TQString("%1: %2").tqarg(name()).tqarg(message())); // esp. for sorting +} + +void KChatBaseText::setMessage(const TQString& m) +{ + d->mMessage = m; + setText(TQString("%1: %2").tqarg(name()).tqarg(message())); // esp. for sorting +} + +const TQString& KChatBaseText::name() const +{ return d->mName; } + +const TQString& KChatBaseText::message() const +{ return d->mMessage; } + +TQFont KChatBaseText::nameFont() const +{ + if (d->mNameFont) { + return *d->mNameFont; + } else if (listBox()) { + return listBox()->font(); + } else { + return TQFont(); + } +} + +TQFont KChatBaseText::messageFont() const +{ + if (d->mMessageFont) { + return *d->mMessageFont; + } else if (listBox()) { + return listBox()->font(); + } else { + return TQFont(); + } +} + +void KChatBaseText::setNameFont(const TQFont* f) +{ d->mNameFont = f; } + +void KChatBaseText::setMessageFont(const TQFont* f) +{ d->mMessageFont = f; } + +void KChatBaseText::paint(TQPainter* painter) +{ + TQFontMetrics fm = painter->fontMetrics(); + painter->setFont(nameFont()); + painter->drawText(3, fm.ascent() + fm.leading()/2, name()); + painter->setFont(messageFont()); + painter->drawText(3 + TQFontMetrics(nameFont()).width(name()), fm.ascent() + fm.leading()/2, message()); +} + +int KChatBaseText::width(TQListBox* lb) const +{ + int w = 0; + if (lb) { + w += 6; + w += TQFontMetrics(nameFont()).width(name()); + w += TQFontMetrics(messageFont()).width(message()); + } +// int w = lb ? lb->fontMetrics().width( text() ) + 6 : 0; // QT orig + return TQMAX(w, TQApplication::globalStrut().width()); +} + +int KChatBaseText::height(TQListBox* lb) const +{ + int h = 0; + if (lb) { + h += 2; + // AB: is lineSpacing still correct? + if (TQFontMetrics(nameFont()).lineSpacing() > TQFontMetrics(messageFont()).lineSpacing()) { + h += TQFontMetrics(nameFont()).lineSpacing(); + } else { + h += TQFontMetrics(messageFont()).lineSpacing(); + } + } +// int h = lb ? lb->fontMetrics().lineSpacing() + 2 : 0; // QT orig + return TQMAX(h, TQApplication::globalStrut().height()); +} + + + +class KChatBasePrivate +{ +public: + KChatBasePrivate() + { + mBox = 0; + mEdit = 0; + mCombo = 0; + + mAcceptMessage = true; + mMaxItems = -1; + } + TQListBox* mBox; + KLineEdit* mEdit; + TQComboBox* mCombo; + bool mAcceptMessage; + int mMaxItems; + + TQValueList<int> mIndex2Id; + + TQFont mNameFont; + TQFont mMessageFont; + TQFont mSystemNameFont; + TQFont mSystemMessageFont; +}; + +KChatBase::KChatBase(TQWidget* parent, bool noComboBox) : TQFrame(parent) +{ + init(noComboBox); +} + +KChatBase::~KChatBase() +{ +// kdDebug(11000) << "KChatBase: DESTRUCT (" << this << ")" << endl; + saveConfig(); + delete d; +} + +void KChatBase::init(bool noComboBox) +{ +// kdDebug(11000) << "KChatBase: INIT (" << this << ")" << endl; + + d = new KChatBasePrivate; + + setMinimumWidth(100); + setMinimumHeight(150); + + TQVBoxLayout* l = new TQVBoxLayout(this); + + d->mBox = new TQListBox(this); + connect(d->mBox, TQT_SIGNAL(rightButtonClicked(TQListBoxItem*, const TQPoint&)), + this, TQT_SIGNAL(rightButtonClicked(TQListBoxItem*, const TQPoint&))); + l->addWidget(d->mBox); + d->mBox->setVScrollBarMode(TQScrollView::AlwaysOn); + d->mBox->setHScrollBarMode(TQScrollView::AlwaysOff); + d->mBox->setFocusPolicy(TQ_NoFocus); +// d->mBox->setSelectionMode(TQListBox::NoSelection); + d->mBox->setSelectionMode(TQListBox::Single); + + l->addSpacing(5); + + TQHBoxLayout* h = new TQHBoxLayout(l); + d->mEdit = new KLineEdit(this); + d->mEdit->setHandleSignals(false); + d->mEdit->setTrapReturnKey(true); + d->mEdit->completionObject(); // add the completion object + d->mEdit->setCompletionMode(KGlobalSettings::CompletionNone); + connect(d->mEdit, TQT_SIGNAL(returnPressed(const TQString&)), this, TQT_SLOT(slotReturnPressed(const TQString&))); + h->addWidget(d->mEdit); + + if (!noComboBox) { + d->mCombo = new TQComboBox(this); + h->addWidget(d->mCombo); + addSendingEntry(i18n("Send to All Players"), SendToAll);//FIXME: where to put the id? + } + + d->mAcceptMessage = true; // by default + setMaxItems(-1); // unlimited + + if (kapp) { + // kapp might be NULL as well - in case we are in TQt designer. + readConfig(); + } +} + +bool KChatBase::acceptMessage() const +{ return d->mAcceptMessage; } + +void KChatBase::setAcceptMessage(bool a) +{ d->mAcceptMessage = a; } + +bool KChatBase::addSendingEntry(const TQString& text, int id) +{ +//FIXME: is ID used correctly? +// do we need ID at all? +// what the hell should be here? +// d->mCombo->insertItem(i18n("Send to All Players"), SendToAll); + return insertSendingEntry(text, id); +} + +bool KChatBase::insertSendingEntry(const TQString& text, int id, int index) +{ + if (!d->mCombo) { + kdWarning(11000) << "KChatBase: Cannot add an entry to the combo box" << endl; + return false; + } + if (d->mIndex2Id.findIndex(id) != -1) { + kdError(11000) << "KChatBase: Cannot add more than one entry with the same ID! " << endl; + kdError(11000) << "KChatBase: Text="<<text<<endl; + return false; + } + d->mCombo->insertItem(text, index); + if (index < 0) { + d->mIndex2Id.append(id); + } else { + d->mIndex2Id.insert(d->mIndex2Id.at(index), id); + } + if (d->mIndex2Id.count() != (uint)d->mCombo->count()) { + kdError(11000) << "KChatBase: internal ERROR - local IDs do not match combo box entries!" << endl; + } + return true; +} + +int KChatBase::sendingEntry() const +{ + if (!d->mCombo) { + kdWarning(11001) << "Cannot retrieve index from NULL combo box" << endl; + return -1; + } + int index = d->mCombo->currentItem(); + if (d->mIndex2Id.at(index) == d->mIndex2Id.end()) { + kdWarning(11000) << "could not find the selected sending entry!" << endl; + return -1; + } + return d->mIndex2Id[index]; +} + +void KChatBase::removeSendingEntry(int id) +{ + if (!d->mCombo) { + kdWarning(11000) << "KChatBase: Cannot remove an entry from the combo box" << endl; + return; + } + d->mCombo->removeItem(findIndex(id)); + d->mIndex2Id.remove(id); +} + +void KChatBase::changeSendingEntry(const TQString& text, int id) +{ + if (!d->mCombo) { + kdWarning(11000) << "KChatBase: Cannot change an entry in the combo box" << endl; + return; + } + int index = findIndex(id); + d->mCombo->changeItem(text, index); +} + +void KChatBase::setSendingEntry(int id) +{ + if (!d->mCombo) { + kdWarning(11000) << "KChatBase: Cannot set an entry in the combo box" << endl; + return; + } + d->mCombo->setCurrentItem(findIndex(id)); +} + +int KChatBase::findIndex(int id) const +{ + return d->mIndex2Id.findIndex(id); +} + +int KChatBase::nextId() const +{ + int i = SendToAll + 1; + while (d->mIndex2Id.findIndex(i) != -1) { + i++; + } + return i; +} + +void KChatBase::addItem(const TQListBoxItem* text) +{ + d->mBox->insertItem(text); + int index = d->mBox->count() -1; + d->mBox->setBottomItem(index);//FIXME: don't scroll to bottom if user scrolled down manually + if (maxItems() >= 0 && d->mBox->count() > (unsigned int)maxItems()) { + d->mBox->removeItem(0); + } +} + +void KChatBase::addMessage(const TQString& fromName, const TQString& text) +{ +//maybe "%1 says: %2" or so + addItem(layoutMessage(fromName, text)); +} + +void KChatBase::addSystemMessage(const TQString& fromName, const TQString& text) +{ + addItem(layoutSystemMessage(fromName, text)); +} + +TQListBoxItem* KChatBase::layoutMessage(const TQString& fromName, const TQString& text) +{ + //TODO: KChatBaseConfigure? - e.g. color + TQListBoxItem* message; + if (text.startsWith("/me ")) { + // replace "/me" by a nice star. leave one space after the star + TQPixmap pix; + pix.load(locate("data", TQString::tqfromLatin1("tdegames/pics/star.png"))); + + //TODO KChatBasePixmap? Should change the font here! + + message = (TQListBoxItem*)new TQListBoxPixmap(pix, i18n("%1 %2").tqarg(fromName).tqarg(text.mid(3))); + } else { + // the text is not edited in any way. just return an item + KChatBaseText* m = new KChatBaseText(fromName, text); + m->setNameFont(&d->mNameFont); + m->setMessageFont(&d->mMessageFont); + message = (TQListBoxItem*)m; + } + return message; +} + +TQListBoxItem* KChatBase::layoutSystemMessage(const TQString& fromName, const TQString& text) +{ + //TODO: KChatBaseConfigure? - e.g. color + + // no need to check for /me etc. + KChatBaseText* m = new KChatBaseText(i18n("--- %1").tqarg(fromName), text); + m->setNameFont(&d->mSystemNameFont); + m->setMessageFont(&d->mSystemMessageFont); + return (TQListBoxItem*)m; +} + +void KChatBase::slotReturnPressed(const TQString& text) +{ + if (text.length() <= 0) { + // no text entered - probably hit return by accident + return; + } else if (!acceptMessage()) { + return; + } + d->mEdit->completionObject()->addItem(text); +// connect(d->mEdit, TQT_SIGNAL(returnPressed(const TQString&)), comp, TQT_SLOT(addItem(const TQString&))); + d->mEdit->clear(); + returnPressed(text); +} + +TQString KChatBase::comboBoxItem(const TQString& name) const +{ // TODO: such a function for "send to all" and "send to my group" + return i18n("Send to %1").tqarg(name); +} + +void KChatBase::slotClear() +{ + d->mBox->clear(); +} + +void KChatBase::setCompletionMode(KGlobalSettings::Completion mode) +{ d->mEdit->setCompletionMode(mode); } + +void KChatBase::setNameFont(const TQFont& font) +{ + d->mNameFont = font; + d->mBox->triggerUpdate(false); +} + +void KChatBase::setMessageFont(const TQFont& font) +{ + d->mMessageFont = font; + d->mBox->triggerUpdate(false); +} + +void KChatBase::setBothFont(const TQFont& font) +{ + setNameFont(font); + setMessageFont(font); +} + +const TQFont& KChatBase::nameFont() const +{ return d->mNameFont; } + +const TQFont& KChatBase::messageFont() const +{ return d->mMessageFont; } + +void KChatBase::setSystemNameFont(const TQFont& font) +{ + d->mSystemNameFont = font; + d->mBox->triggerUpdate(false); +} + +void KChatBase::setSystemMessageFont(const TQFont& font) +{ + d->mSystemMessageFont = font; + d->mBox->triggerUpdate(false); +} + +void KChatBase::setSystemBothFont(const TQFont& font) +{ + setSystemNameFont(font); + setSystemMessageFont(font); +} + +const TQFont& KChatBase::systemNameFont() const +{ return d->mSystemNameFont; } + +const TQFont& KChatBase::systemMessageFont() const +{ return d->mSystemMessageFont; } + +void KChatBase::saveConfig(KConfig* conf) +{ + TQString oldGroup; + if (!conf) { + conf = kapp->config(); + oldGroup = conf->group(); + conf->setGroup("KChatBase"); + } + + conf->writeEntry("NameFont", nameFont()); + conf->writeEntry("MessageFont", messageFont()); + conf->writeEntry("SystemNameFont", systemNameFont()); + conf->writeEntry("SystemMessageFont", systemMessageFont()); + conf->writeEntry("MaxMessages", maxItems()); + + if (!oldGroup.isNull()) { + conf->setGroup(oldGroup); + } +} + +void KChatBase::readConfig(KConfig* conf) +{ + TQString oldGroup; + if (!conf) { + conf = kapp->config(); + oldGroup = conf->group(); + conf->setGroup("KChatBase"); + } + + setNameFont(conf->readFontEntry("NameFont")); + setMessageFont(conf->readFontEntry("MessageFont")); + setSystemNameFont(conf->readFontEntry("SystemNameFont")); + setSystemMessageFont(conf->readFontEntry("SystemMessageFont")); + setMaxItems(conf->readNumEntry("MaxMessages", -1)); + + if (!oldGroup.isNull()) { + conf->setGroup(oldGroup); + } +} + +void KChatBase::clear() +{ + d->mBox->clear(); +} + +void KChatBase::setMaxItems(int maxItems) +{ + d->mMaxItems = maxItems; + //TODO cut too many messages + if (maxItems == 0) { + clear(); + } else if (maxItems > 0) { + while (d->mBox->count() > (unsigned int)maxItems) { + d->mBox->removeItem(0); + } + } +} + +int KChatBase::maxItems() const +{ return d->mMaxItems; } + + +#include "kchatbase.moc" |