Logo Search packages:      
Sourcecode: kdegames version File versions

kchatbase.cpp

/*
    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., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
*/

#include "kchatbase.h"

#include <klineedit.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kconfig.h>
#include <kapplication.h>
#include <kdebug.h>

#include <qlayout.h>
#include <qcombobox.h>
#include <qpainter.h>

class KChatBaseTextPrivate
{
public:
      KChatBaseTextPrivate()
      {
            mNameFont = 0;
            mMessageFont = 0;
      }

      QString mName;
      QString mMessage;

      const QFont* mNameFont;
      const QFont* mMessageFont;
};


00050 KChatBaseText::KChatBaseText(const QString& name, const QString& message) : QListBoxText()
{
 init();
 setName(name);
 setMessage(message);
}

00057 KChatBaseText::KChatBaseText(const QString& message) : QListBoxText()
{
 init();
 setMessage(message);
}

00063 KChatBaseText::~KChatBaseText()
{ 
 delete d;
}

void KChatBaseText::init()
{
 d = new KChatBaseTextPrivate;
}

00073 void KChatBaseText::setName(const QString& n)
{
// d->mName = n;
 d->mName = QString("%1: ").arg(n);
 setText(QString("%1: %2").arg(name()).arg(message())); // esp. for sorting
}

00080 void KChatBaseText::setMessage(const QString& m)
{
 d->mMessage = m;
 setText(QString("%1: %2").arg(name()).arg(message())); // esp. for sorting
}

00086 const QString& KChatBaseText::name() const
{ return d->mName; }

00089 const QString& KChatBaseText::message() const
{ return d->mMessage; }

00092 QFont KChatBaseText::nameFont() const
{
 if (d->mNameFont) {
      return *d->mNameFont; 
 } else if (listBox()) {
      return listBox()->font();
 } else {
      return QFont();
 }
}

00103 QFont KChatBaseText::messageFont() const
{
 if (d->mMessageFont) {
      return *d->mMessageFont; 
 } else if (listBox()) {
      return listBox()->font();
 } else {
      return QFont();
 }
}

00114 void KChatBaseText::setNameFont(const QFont* f)
{ d->mNameFont = f; }

00117 void KChatBaseText::setMessageFont(const QFont* f)
{ d->mMessageFont = f; }

void KChatBaseText::paint(QPainter* painter)
{
 QFontMetrics fm = painter->fontMetrics();
 painter->setFont(nameFont());
 painter->drawText(3, fm.ascent() + fm.leading()/2, name());
 painter->setFont(messageFont());
 painter->drawText(3 + QFontMetrics(nameFont()).width(name()), fm.ascent() + fm.leading()/2, message());
}

int KChatBaseText::width(QListBox* lb) const
{
 int w = 0;
 if (lb) {
      w += 6;
      w += QFontMetrics(nameFont()).width(name());
      w += QFontMetrics(messageFont()).width(message());
 }
// int w = lb ? lb->fontMetrics().width( text() ) + 6 : 0; // QT orig
 return QMAX(w, QApplication::globalStrut().width());
}

int KChatBaseText::height(QListBox* lb) const
{
 int h = 0;
 if (lb) {
      h += 2;
      // AB: is lineSpacing still correct?
      if (QFontMetrics(nameFont()).lineSpacing() > QFontMetrics(messageFont()).lineSpacing()) { 
            h += QFontMetrics(nameFont()).lineSpacing();
      } else {
            h += QFontMetrics(messageFont()).lineSpacing();
      }
 }
// int h = lb ? lb->fontMetrics().lineSpacing() + 2 : 0; // QT orig
 return QMAX(h, QApplication::globalStrut().height());
}



class KChatBasePrivate
{
public:
      KChatBasePrivate() 
      { 
            mBox = 0;
            mEdit = 0;
            mCombo = 0;

            mAcceptMessage = true;
            mMaxItems = -1;
      }
      QListBox* mBox;
      KLineEdit* mEdit;
      QComboBox* mCombo;
      bool mAcceptMessage;
      int mMaxItems;

      QValueList<int> mIndex2Id;

      QFont mNameFont;
      QFont mMessageFont;
      QFont mSystemNameFont;
      QFont mSystemMessageFont;
};

00185 KChatBase::KChatBase(QWidget* parent, bool noComboBox) : QFrame(parent)
{
 init(noComboBox); 
}

00190 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);
 
 QVBoxLayout* l = new QVBoxLayout(this);

 d->mBox = new QListBox(this);
 connect(d->mBox, SIGNAL(rightButtonClicked(QListBoxItem*, const QPoint&)), 
            this, SIGNAL(rightButtonClicked(QListBoxItem*, const QPoint&)));
 l->addWidget(d->mBox);
 d->mBox->setVScrollBarMode(QScrollView::AlwaysOn);
 d->mBox->setHScrollBarMode(QScrollView::AlwaysOff);
 d->mBox->setFocusPolicy(QWidget::NoFocus);
// d->mBox->setSelectionMode(QListBox::NoSelection);
 d->mBox->setSelectionMode(QListBox::Single);

 l->addSpacing(5);

 QHBoxLayout* h = new QHBoxLayout(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, SIGNAL(returnPressed(const QString&)), this, SLOT(slotReturnPressed(const QString&)));
 h->addWidget(d->mEdit);

 if (!noComboBox) {
      d->mCombo = new QComboBox(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();
 }
}

00244 bool KChatBase::acceptMessage() const
{ return d->mAcceptMessage; }

00247 void KChatBase::setAcceptMessage(bool a)
{ d->mAcceptMessage = a; }

00250 bool KChatBase::addSendingEntry(const QString& 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);
}

00259 bool KChatBase::insertSendingEntry(const QString& 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;
}

00282 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];
}

00296 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);
}

00306 void KChatBase::changeSendingEntry(const QString& 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);
}

00316 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));
}
 
00325 int KChatBase::findIndex(int id) const
{
 return d->mIndex2Id.findIndex(id);
}

00330 int KChatBase::nextId() const
{
 int i = SendToAll + 1;
 while (d->mIndex2Id.findIndex(i) != -1) {
      i++;
 }
 return i;
}

00339 void KChatBase::addItem(const QListBoxItem* 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);
 }
}

00349 void KChatBase::addMessage(const QString& fromName, const QString& text)
{
//maybe "%1 says: %2" or so
 addItem(layoutMessage(fromName, text));
}

00355 void KChatBase::addSystemMessage(const QString& fromName, const QString& text)
{
 addItem(layoutSystemMessage(fromName, text));
}

00360 QListBoxItem* KChatBase::layoutMessage(const QString& fromName, const QString& text)
{
 //TODO: KChatBaseConfigure? - e.g. color
 QListBoxItem* message;
 if (text.startsWith("/me ")) {
      // replace "/me" by a nice star. leave one space after the star
      QPixmap pix;
      pix.load(locate("data", QString::fromLatin1("kdegames/pics/star.png")));
      
      //TODO KChatBasePixmap? Should change the font here!
      
      message = (QListBoxItem*)new QListBoxPixmap(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 = (QListBoxItem*)m;
 }
 return message;
}

00382 QListBoxItem* KChatBase::layoutSystemMessage(const QString& fromName, const QString& 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 (QListBoxItem*)m;
}

00393 void KChatBase::slotReturnPressed(const QString& 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, SIGNAL(returnPressed(const QString&)), comp, SLOT(addItem(const QString&)));
 d->mEdit->clear();
 returnPressed(text);
}

00407 QString KChatBase::comboBoxItem(const QString& name) const
{ // TODO: such a function for "send to all" and "send to my group"
 return i18n("Send to %1").arg(name);
}

00412 void KChatBase::slotClear()
{
 d->mBox->clear();
}

00417 void KChatBase::setCompletionMode(KGlobalSettings::Completion mode)
{ d->mEdit->setCompletionMode(mode); }

00420 void KChatBase::setNameFont(const QFont& font)
{
 d->mNameFont = font; 
 d->mBox->triggerUpdate(false);
}

00426 void KChatBase::setMessageFont(const QFont& font)
{
 d->mMessageFont = font; 
 d->mBox->triggerUpdate(false);
}

00432 void KChatBase::setBothFont(const QFont& font)
{
 setNameFont(font);
 setMessageFont(font);
}

00438 const QFont& KChatBase::nameFont() const
{ return d->mNameFont; }

00441 const QFont& KChatBase::messageFont() const
{ return d->mMessageFont; }

00444 void KChatBase::setSystemNameFont(const QFont& font)
{
 d->mSystemNameFont = font; 
 d->mBox->triggerUpdate(false);
}

00450 void KChatBase::setSystemMessageFont(const QFont& font)
{
 d->mSystemMessageFont = font; 
 d->mBox->triggerUpdate(false);
}

00456 void KChatBase::setSystemBothFont(const QFont& font)
{
 setSystemNameFont(font);
 setSystemMessageFont(font);
}

00462 const QFont& KChatBase::systemNameFont() const
{ return d->mSystemNameFont; }

00465 const QFont& KChatBase::systemMessageFont() const
{ return d->mSystemMessageFont; }

00468 void KChatBase::saveConfig(KConfig* conf)
{
 QString 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);
 }
}

00488 void KChatBase::readConfig(KConfig* conf)
{
 QString 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);
 }
}

00508 void KChatBase::clear()
{
 d->mBox->clear();
}

00513 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);
      }
 }
}

00526 int KChatBase::maxItems() const
{ return d->mMaxItems; }


#include "kchatbase.moc"

Generated by  Doxygen 1.6.0   Back to index