/* This file is part of the KDE games library Copyright (C) 2001 Andreas Beckermann (b_mann@gmx.de) 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 #include #include #include #include #include #include #include #include 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: ").arg(n); setText(TQString("%1: %2").arg(name()).arg(message())); // esp. for sorting } void KChatBaseText::setMessage(const TQString& m) { d->mMessage = m; setText(TQString("%1: %2").arg(name()).arg(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 QMAX(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 QMAX(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 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(TQWidget::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 Qt 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="<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::fromLatin1("kdegames/pics/star.png"))); //TODO KChatBasePixmap? Should change the font here! message = (TQListBoxItem*)new TQListBoxPixmap(pix, i18n("%1 %2").arg(fromName).arg(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").arg(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").arg(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"