00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kchatbase.h"
00021
00022 #include <klineedit.h>
00023 #include <klocale.h>
00024 #include <kstandarddirs.h>
00025 #include <kconfig.h>
00026 #include <kapplication.h>
00027 #include <kdebug.h>
00028
00029 #include <qlayout.h>
00030 #include <qcombobox.h>
00031 #include <qpainter.h>
00032
00033 class KChatBaseTextPrivate
00034 {
00035 public:
00036 KChatBaseTextPrivate()
00037 {
00038 mNameFont = 0;
00039 mMessageFont = 0;
00040 }
00041
00042 QString mName;
00043 QString mMessage;
00044
00045 const QFont* mNameFont;
00046 const QFont* mMessageFont;
00047 };
00048
00049
00050 KChatBaseText::KChatBaseText(const QString& name, const QString& message) : QListBoxText()
00051 {
00052 init();
00053 setName(name);
00054 setMessage(message);
00055 }
00056
00057 KChatBaseText::KChatBaseText(const QString& message) : QListBoxText()
00058 {
00059 init();
00060 setMessage(message);
00061 }
00062
00063 KChatBaseText::~KChatBaseText()
00064 {
00065 delete d;
00066 }
00067
00068 void KChatBaseText::init()
00069 {
00070 d = new KChatBaseTextPrivate;
00071 }
00072
00073 void KChatBaseText::setName(const QString& n)
00074 {
00075
00076 d->mName = QString("%1: ").arg(n);
00077 setText(QString("%1: %2").arg(name()).arg(message()));
00078 }
00079
00080 void KChatBaseText::setMessage(const QString& m)
00081 {
00082 d->mMessage = m;
00083 setText(QString("%1: %2").arg(name()).arg(message()));
00084 }
00085
00086 const QString& KChatBaseText::name() const
00087 { return d->mName; }
00088
00089 const QString& KChatBaseText::message() const
00090 { return d->mMessage; }
00091
00092 QFont KChatBaseText::nameFont() const
00093 {
00094 if (d->mNameFont) {
00095 return *d->mNameFont;
00096 } else if (listBox()) {
00097 return listBox()->font();
00098 } else {
00099 return QFont();
00100 }
00101 }
00102
00103 QFont KChatBaseText::messageFont() const
00104 {
00105 if (d->mMessageFont) {
00106 return *d->mMessageFont;
00107 } else if (listBox()) {
00108 return listBox()->font();
00109 } else {
00110 return QFont();
00111 }
00112 }
00113
00114 void KChatBaseText::setNameFont(const QFont* f)
00115 { d->mNameFont = f; }
00116
00117 void KChatBaseText::setMessageFont(const QFont* f)
00118 { d->mMessageFont = f; }
00119
00120 void KChatBaseText::paint(QPainter* painter)
00121 {
00122 QFontMetrics fm = painter->fontMetrics();
00123 painter->setFont(nameFont());
00124 painter->drawText(3, fm.ascent() + fm.leading()/2, name());
00125 painter->setFont(messageFont());
00126 painter->drawText(3 + QFontMetrics(nameFont()).width(name()), fm.ascent() + fm.leading()/2, message());
00127 }
00128
00129 int KChatBaseText::width(QListBox* lb) const
00130 {
00131 int w = 0;
00132 if (lb) {
00133 w += 6;
00134 w += QFontMetrics(nameFont()).width(name());
00135 w += QFontMetrics(messageFont()).width(message());
00136 }
00137
00138 return QMAX(w, QApplication::globalStrut().width());
00139 }
00140
00141 int KChatBaseText::height(QListBox* lb) const
00142 {
00143 int h = 0;
00144 if (lb) {
00145 h += 2;
00146
00147 if (QFontMetrics(nameFont()).lineSpacing() > QFontMetrics(messageFont()).lineSpacing()) {
00148 h += QFontMetrics(nameFont()).lineSpacing();
00149 } else {
00150 h += QFontMetrics(messageFont()).lineSpacing();
00151 }
00152 }
00153
00154 return QMAX(h, QApplication::globalStrut().height());
00155 }
00156
00157
00158
00159 class KChatBasePrivate
00160 {
00161 public:
00162 KChatBasePrivate()
00163 {
00164 mBox = 0;
00165 mEdit = 0;
00166 mCombo = 0;
00167
00168 mAcceptMessage = true;
00169 mMaxItems = -1;
00170 }
00171 QListBox* mBox;
00172 KLineEdit* mEdit;
00173 QComboBox* mCombo;
00174 bool mAcceptMessage;
00175 int mMaxItems;
00176
00177 QValueList<int> mIndex2Id;
00178
00179 QFont mNameFont;
00180 QFont mMessageFont;
00181 QFont mSystemNameFont;
00182 QFont mSystemMessageFont;
00183 };
00184
00185 KChatBase::KChatBase(QWidget* parent, bool noComboBox) : QFrame(parent)
00186 {
00187 init(noComboBox);
00188 }
00189
00190 KChatBase::~KChatBase()
00191 {
00192
00193 saveConfig();
00194 delete d;
00195 }
00196
00197 void KChatBase::init(bool noComboBox)
00198 {
00199
00200
00201 d = new KChatBasePrivate;
00202
00203 setMinimumWidth(100);
00204 setMinimumHeight(150);
00205
00206 QVBoxLayout* l = new QVBoxLayout(this);
00207
00208 d->mBox = new QListBox(this);
00209 connect(d->mBox, SIGNAL(rightButtonClicked(QListBoxItem*, const QPoint&)),
00210 this, SIGNAL(rightButtonClicked(QListBoxItem*, const QPoint&)));
00211 l->addWidget(d->mBox);
00212 d->mBox->setVScrollBarMode(QScrollView::AlwaysOn);
00213 d->mBox->setHScrollBarMode(QScrollView::AlwaysOff);
00214 d->mBox->setFocusPolicy(QWidget::NoFocus);
00215
00216 d->mBox->setSelectionMode(QListBox::Single);
00217
00218 l->addSpacing(5);
00219
00220 QHBoxLayout* h = new QHBoxLayout(l);
00221 d->mEdit = new KLineEdit(this);
00222 d->mEdit->setHandleSignals(false);
00223 d->mEdit->setTrapReturnKey(true);
00224 d->mEdit->completionObject();
00225 d->mEdit->setCompletionMode(KGlobalSettings::CompletionNone);
00226 connect(d->mEdit, SIGNAL(returnPressed(const QString&)), this, SLOT(slotReturnPressed(const QString&)));
00227 h->addWidget(d->mEdit);
00228
00229 if (!noComboBox) {
00230 d->mCombo = new QComboBox(this);
00231 h->addWidget(d->mCombo);
00232 addSendingEntry(i18n("Send to All Players"), SendToAll);
00233 }
00234
00235 d->mAcceptMessage = true;
00236 setMaxItems(-1);
00237
00238 if (kapp) {
00239
00240 readConfig();
00241 }
00242 }
00243
00244 bool KChatBase::acceptMessage() const
00245 { return d->mAcceptMessage; }
00246
00247 void KChatBase::setAcceptMessage(bool a)
00248 { d->mAcceptMessage = a; }
00249
00250 bool KChatBase::addSendingEntry(const QString& text, int id)
00251 {
00252
00253
00254
00255
00256 return insertSendingEntry(text, id);
00257 }
00258
00259 bool KChatBase::insertSendingEntry(const QString& text, int id, int index)
00260 {
00261 if (!d->mCombo) {
00262 kdWarning(11000) << "KChatBase: Cannot add an entry to the combo box" << endl;
00263 return false;
00264 }
00265 if (d->mIndex2Id.findIndex(id) != -1) {
00266 kdError(11000) << "KChatBase: Cannot add more than one entry with the same ID! " << endl;
00267 kdError(11000) << "KChatBase: Text="<<text<<endl;
00268 return false;
00269 }
00270 d->mCombo->insertItem(text, index);
00271 if (index < 0) {
00272 d->mIndex2Id.append(id);
00273 } else {
00274 d->mIndex2Id.insert(d->mIndex2Id.at(index), id);
00275 }
00276 if (d->mIndex2Id.count() != (uint)d->mCombo->count()) {
00277 kdError(11000) << "KChatBase: internal ERROR - local IDs do not match combo box entries!" << endl;
00278 }
00279 return true;
00280 }
00281
00282 int KChatBase::sendingEntry() const
00283 {
00284 if (!d->mCombo) {
00285 kdWarning(11001) << "Cannot retrieve index from NULL combo box" << endl;
00286 return -1;
00287 }
00288 int index = d->mCombo->currentItem();
00289 if (d->mIndex2Id.at(index) == d->mIndex2Id.end()) {
00290 kdWarning(11000) << "could not find the selected sending entry!" << endl;
00291 return -1;
00292 }
00293 return d->mIndex2Id[index];
00294 }
00295
00296 void KChatBase::removeSendingEntry(int id)
00297 {
00298 if (!d->mCombo) {
00299 kdWarning(11000) << "KChatBase: Cannot remove an entry from the combo box" << endl;
00300 return;
00301 }
00302 d->mCombo->removeItem(findIndex(id));
00303 d->mIndex2Id.remove(id);
00304 }
00305
00306 void KChatBase::changeSendingEntry(const QString& text, int id)
00307 {
00308 if (!d->mCombo) {
00309 kdWarning(11000) << "KChatBase: Cannot change an entry in the combo box" << endl;
00310 return;
00311 }
00312 int index = findIndex(id);
00313 d->mCombo->changeItem(text, index);
00314 }
00315
00316 void KChatBase::setSendingEntry(int id)
00317 {
00318 if (!d->mCombo) {
00319 kdWarning(11000) << "KChatBase: Cannot set an entry in the combo box" << endl;
00320 return;
00321 }
00322 d->mCombo->setCurrentItem(findIndex(id));
00323 }
00324
00325 int KChatBase::findIndex(int id) const
00326 {
00327 return d->mIndex2Id.findIndex(id);
00328 }
00329
00330 int KChatBase::nextId() const
00331 {
00332 int i = SendToAll + 1;
00333 while (d->mIndex2Id.findIndex(i) != -1) {
00334 i++;
00335 }
00336 return i;
00337 }
00338
00339 void KChatBase::addItem(const QListBoxItem* text)
00340 {
00341 d->mBox->insertItem(text);
00342 int index = d->mBox->count() -1;
00343 d->mBox->setBottomItem(index);
00344 if (maxItems() >= 0 && d->mBox->count() > (unsigned int)maxItems()) {
00345 d->mBox->removeItem(0);
00346 }
00347 }
00348
00349 void KChatBase::addMessage(const QString& fromName, const QString& text)
00350 {
00351
00352 addItem(layoutMessage(fromName, text));
00353 }
00354
00355 void KChatBase::addSystemMessage(const QString& fromName, const QString& text)
00356 {
00357 addItem(layoutSystemMessage(fromName, text));
00358 }
00359
00360 QListBoxItem* KChatBase::layoutMessage(const QString& fromName, const QString& text)
00361 {
00362
00363 QListBoxItem* message;
00364 if (text.startsWith("/me ")) {
00365
00366 QPixmap pix;
00367 pix.load(locate("data", QString::fromLatin1("kdegames/pics/star.png")));
00368
00369
00370
00371 message = (QListBoxItem*)new QListBoxPixmap(pix, i18n("%1 %2").arg(fromName).arg(text.mid(3)));
00372 } else {
00373
00374 KChatBaseText* m = new KChatBaseText(fromName, text);
00375 m->setNameFont(&d->mNameFont);
00376 m->setMessageFont(&d->mMessageFont);
00377 message = (QListBoxItem*)m;
00378 }
00379 return message;
00380 }
00381
00382 QListBoxItem* KChatBase::layoutSystemMessage(const QString& fromName, const QString& text)
00383 {
00384
00385
00386
00387 KChatBaseText* m = new KChatBaseText(i18n("--- %1").arg(fromName), text);
00388 m->setNameFont(&d->mSystemNameFont);
00389 m->setMessageFont(&d->mSystemMessageFont);
00390 return (QListBoxItem*)m;
00391 }
00392
00393 void KChatBase::slotReturnPressed(const QString& text)
00394 {
00395 if (text.length() <= 0) {
00396
00397 return;
00398 } else if (!acceptMessage()) {
00399 return;
00400 }
00401 d->mEdit->completionObject()->addItem(text);
00402
00403 d->mEdit->clear();
00404 returnPressed(text);
00405 }
00406
00407 QString KChatBase::comboBoxItem(const QString& name) const
00408 {
00409 return i18n("Send to %1").arg(name);
00410 }
00411
00412 void KChatBase::slotClear()
00413 {
00414 d->mBox->clear();
00415 }
00416
00417 void KChatBase::setCompletionMode(KGlobalSettings::Completion mode)
00418 { d->mEdit->setCompletionMode(mode); }
00419
00420 void KChatBase::setNameFont(const QFont& font)
00421 {
00422 d->mNameFont = font;
00423 d->mBox->triggerUpdate(false);
00424 }
00425
00426 void KChatBase::setMessageFont(const QFont& font)
00427 {
00428 d->mMessageFont = font;
00429 d->mBox->triggerUpdate(false);
00430 }
00431
00432 void KChatBase::setBothFont(const QFont& font)
00433 {
00434 setNameFont(font);
00435 setMessageFont(font);
00436 }
00437
00438 const QFont& KChatBase::nameFont() const
00439 { return d->mNameFont; }
00440
00441 const QFont& KChatBase::messageFont() const
00442 { return d->mMessageFont; }
00443
00444 void KChatBase::setSystemNameFont(const QFont& font)
00445 {
00446 d->mSystemNameFont = font;
00447 d->mBox->triggerUpdate(false);
00448 }
00449
00450 void KChatBase::setSystemMessageFont(const QFont& font)
00451 {
00452 d->mSystemMessageFont = font;
00453 d->mBox->triggerUpdate(false);
00454 }
00455
00456 void KChatBase::setSystemBothFont(const QFont& font)
00457 {
00458 setSystemNameFont(font);
00459 setSystemMessageFont(font);
00460 }
00461
00462 const QFont& KChatBase::systemNameFont() const
00463 { return d->mSystemNameFont; }
00464
00465 const QFont& KChatBase::systemMessageFont() const
00466 { return d->mSystemMessageFont; }
00467
00468 void KChatBase::saveConfig(KConfig* conf)
00469 {
00470 QString oldGroup;
00471 if (!conf) {
00472 conf = kapp->config();
00473 oldGroup = conf->group();
00474 conf->setGroup("KChatBase");
00475 }
00476
00477 conf->writeEntry("NameFont", nameFont());
00478 conf->writeEntry("MessageFont", messageFont());
00479 conf->writeEntry("SystemNameFont", systemNameFont());
00480 conf->writeEntry("SystemMessageFont", systemMessageFont());
00481 conf->writeEntry("MaxMessages", maxItems());
00482
00483 if (!oldGroup.isNull()) {
00484 conf->setGroup(oldGroup);
00485 }
00486 }
00487
00488 void KChatBase::readConfig(KConfig* conf)
00489 {
00490 QString oldGroup;
00491 if (!conf) {
00492 conf = kapp->config();
00493 oldGroup = conf->group();
00494 conf->setGroup("KChatBase");
00495 }
00496
00497 setNameFont(conf->readFontEntry("NameFont"));
00498 setMessageFont(conf->readFontEntry("MessageFont"));
00499 setSystemNameFont(conf->readFontEntry("SystemNameFont"));
00500 setSystemMessageFont(conf->readFontEntry("SystemMessageFont"));
00501 setMaxItems(conf->readNumEntry("MaxMessages", -1));
00502
00503 if (!oldGroup.isNull()) {
00504 conf->setGroup(oldGroup);
00505 }
00506 }
00507
00508 void KChatBase::clear()
00509 {
00510 d->mBox->clear();
00511 }
00512
00513 void KChatBase::setMaxItems(int maxItems)
00514 {
00515 d->mMaxItems = maxItems;
00516
00517 if (maxItems == 0) {
00518 clear();
00519 } else if (maxItems > 0) {
00520 while (d->mBox->count() > (unsigned int)maxItems) {
00521 d->mBox->removeItem(0);
00522 }
00523 }
00524 }
00525
00526 int KChatBase::maxItems() const
00527 { return d->mMaxItems; }
00528
00529
00530 #include "kchatbase.moc"