File indexing completed on 2024-05-12 04:06:09

0001 /*
0002     This file is part of the KDE games library
0003     SPDX-FileCopyrightText: 2001 Andreas Beckermann <b_mann@gmx.de>
0004     SPDX-FileCopyrightText: 2007 Gael de Chalendar (aka Kleag) <kleag@free.fr>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #include "kchatbase.h"
0010 #include "kchatbase_p.h"
0011 
0012 // own
0013 #include "kchatbaseitemdelegate.h"
0014 #include "kchatbasemodel.h"
0015 #include <kdegamesprivate_kgame_logging.h>
0016 #include <kdegamesprivate_logging.h>
0017 // KF
0018 #include <KConfig>
0019 #include <KLineEdit>
0020 #include <KLocalizedString>
0021 // Qt
0022 #include <QComboBox>
0023 #include <QHBoxLayout>
0024 #include <QList>
0025 #include <QListView>
0026 #include <QVBoxLayout>
0027 
0028 KChatBasePrivate::KChatBasePrivate(KChatBaseModel *model, KChatBaseItemDelegate *delegate, QWidget *parent)
0029 {
0030     if (!model) {
0031         model = new KChatBaseModel(parent);
0032     }
0033     if (!delegate) {
0034         delegate = new KChatBaseItemDelegate(parent);
0035     }
0036 
0037     mModel = model;
0038     mDelegate = delegate;
0039 }
0040 
0041 void KChatBase::setModel(KChatBaseModel *m)
0042 {
0043     Q_D(KChatBase);
0044 
0045     // delete d->mModel;
0046     d->mModel = m;
0047 }
0048 
0049 KChatBaseModel *KChatBase::model()
0050 {
0051     Q_D(KChatBase);
0052 
0053     return d->mModel;
0054 }
0055 
0056 KChatBase::KChatBase(QWidget *parent, KChatBaseModel *model, KChatBaseItemDelegate *delegate, bool noComboBox)
0057     : KChatBase(*new KChatBasePrivate(model, delegate, parent), parent, noComboBox)
0058 {
0059 }
0060 
0061 KChatBase::KChatBase(KChatBasePrivate &dd, QWidget *parent, bool noComboBox)
0062     : QFrame(parent)
0063     , d(&dd)
0064 {
0065     setMinimumWidth(100);
0066     setMinimumHeight(150);
0067 
0068     QVBoxLayout *l = new QVBoxLayout(this);
0069 
0070     d->mBox = new QListView();
0071     d->mBox->setModel(d->mModel);
0072     d->mBox->setItemDelegate(d->mDelegate);
0073     l->addWidget(d->mBox);
0074 
0075     connect(d->mModel, &QAbstractItemModel::rowsInserted, d->mBox, &QAbstractItemView::scrollToBottom);
0076 
0077     connect(d->mBox, &QListView::customContextMenuRequested, this, &KChatBase::customMenuHandler);
0078 
0079     d->mBox->setContextMenuPolicy(Qt::CustomContextMenu);
0080     d->mBox->setFocusPolicy(Qt::NoFocus);
0081     d->mBox->setSelectionMode(QAbstractItemView::SingleSelection);
0082 
0083     l->addSpacing(5);
0084 
0085     QHBoxLayout *h = new QHBoxLayout;
0086     l->addLayout(h);
0087     d->mEdit = new KLineEdit(this);
0088     d->mEdit->setHandleSignals(false);
0089     d->mEdit->setTrapReturnKey(true);
0090     d->mEdit->completionObject(); // add the completion object
0091     d->mEdit->setCompletionMode(KCompletion::CompletionNone);
0092     connect(d->mEdit, &KLineEdit::returnKeyPressed, this, &KChatBase::slotReturnPressed);
0093     h->addWidget(d->mEdit);
0094 
0095     if (!noComboBox) {
0096         d->mCombo = new QComboBox(this);
0097         h->addWidget(d->mCombo);
0098         addSendingEntry(i18n("Send to All Players"), SendToAll); // FIXME: where to put the id?
0099     }
0100 
0101     d->mAcceptMessage = true; // by default
0102     setMaxItems(-1); // unlimited
0103 
0104     readConfig();
0105 }
0106 
0107 QModelIndex KChatBase::indexAt(QPoint pos) const
0108 {
0109     Q_D(const KChatBase);
0110 
0111     return d->mBox->indexAt(pos);
0112 }
0113 
0114 void KChatBase::customMenuHandler(QPoint pos)
0115 {
0116     qCDebug(KDEGAMESPRIVATE_LOG) << "custom menu has been requested at position=" << pos << ". Implement handler at subclass if you need it.";
0117 }
0118 
0119 KChatBase::~KChatBase()
0120 {
0121     // qCDebug(KDEGAMESPRIVATE_LOG) << "KChatBase: DESTRUCT (" << this << ")";
0122     saveConfig();
0123 }
0124 
0125 bool KChatBase::acceptMessage() const
0126 {
0127     Q_D(const KChatBase);
0128 
0129     return d->mAcceptMessage;
0130 }
0131 
0132 void KChatBase::setAcceptMessage(bool a)
0133 {
0134     Q_D(KChatBase);
0135 
0136     d->mAcceptMessage = a;
0137 }
0138 
0139 bool KChatBase::addSendingEntry(const QString &text, int id)
0140 {
0141     // FIXME: is ID used correctly?
0142     // do we need ID at all?
0143     // what the hell should be here?
0144     // d->mCombo->insertItem(i18n("Send to All Players"), SendToAll);
0145     return insertSendingEntry(text, id);
0146 }
0147 
0148 bool KChatBase::insertSendingEntry(const QString &text, int id, int index)
0149 {
0150     Q_D(KChatBase);
0151 
0152     if (!d->mCombo) {
0153         qCWarning(KDEGAMESPRIVATE_LOG) << "KChatBase: Cannot add an entry to the combo box";
0154         return false;
0155     }
0156     if (d->mIndex2Id.indexOf(id) != -1) {
0157         qCCritical(KDEGAMESPRIVATE_LOG) << "KChatBase: Cannot add more than one entry with the same ID! ";
0158         qCCritical(KDEGAMESPRIVATE_LOG) << "KChatBase: Text=" << text;
0159         return false;
0160     }
0161     d->mCombo->insertItem(index, text);
0162     if (index < 0) {
0163         d->mIndex2Id.prepend(id);
0164     } else {
0165         d->mIndex2Id.insert(d->mIndex2Id.at(index), id);
0166     }
0167     if (d->mIndex2Id.count() != d->mCombo->count()) {
0168         qCCritical(KDEGAMESPRIVATE_LOG) << "KChatBase: internal ERROR - local IDs do not match combo box entries!";
0169     }
0170     return true;
0171 }
0172 
0173 int KChatBase::sendingEntry() const
0174 {
0175     Q_D(const KChatBase);
0176 
0177     if (!d->mCombo) {
0178         qCWarning(KDEGAMESPRIVATE_KGAME_LOG) << "Cannot retrieve index from NULL combo box";
0179         return -1;
0180     }
0181     const int index = d->mCombo->currentIndex();
0182     if (index >= 0 && index < d->mIndex2Id.size())
0183         return d->mIndex2Id[index];
0184 
0185     qCWarning(KDEGAMESPRIVATE_LOG) << "could not find the selected sending entry!";
0186     return -1;
0187 }
0188 
0189 void KChatBase::removeSendingEntry(int id)
0190 {
0191     Q_D(KChatBase);
0192 
0193     if (!d->mCombo) {
0194         qCWarning(KDEGAMESPRIVATE_LOG) << "KChatBase: Cannot remove an entry from the combo box";
0195         return;
0196     }
0197     int idx = findIndex(id);
0198     // Guard, passing -1 will crash qcombobox
0199     if (idx >= 0)
0200         d->mCombo->removeItem(idx);
0201     d->mIndex2Id.removeAll(id);
0202 }
0203 
0204 void KChatBase::changeSendingEntry(const QString &text, int id)
0205 {
0206     Q_D(KChatBase);
0207 
0208     if (!d->mCombo) {
0209         qCWarning(KDEGAMESPRIVATE_LOG) << "KChatBase: Cannot change an entry in the combo box";
0210         return;
0211     }
0212     int index = findIndex(id);
0213     d->mCombo->setItemText(index, text);
0214 }
0215 
0216 void KChatBase::setSendingEntry(int id)
0217 {
0218     Q_D(KChatBase);
0219 
0220     if (!d->mCombo) {
0221         qCWarning(KDEGAMESPRIVATE_LOG) << "KChatBase: Cannot set an entry in the combo box";
0222         return;
0223     }
0224     d->mCombo->setCurrentIndex(findIndex(id));
0225 }
0226 
0227 int KChatBase::findIndex(int id) const
0228 {
0229     Q_D(const KChatBase);
0230 
0231     return d->mIndex2Id.indexOf(id);
0232 }
0233 
0234 int KChatBase::nextId() const
0235 {
0236     Q_D(const KChatBase);
0237 
0238     int i = SendToAll + 1;
0239     while (d->mIndex2Id.indexOf(i) != -1) {
0240         i++;
0241     }
0242     return i;
0243 }
0244 
0245 void KChatBase::slotReturnPressed(const QString &text)
0246 {
0247     Q_D(KChatBase);
0248 
0249     if (text.length() <= 0) {
0250         // no text entered - probably hit return by accident
0251         return;
0252     } else if (!acceptMessage()) {
0253         return;
0254     }
0255     d->mEdit->completionObject()->addItem(text);
0256     d->mEdit->clear();
0257     returnPressed(text);
0258 }
0259 
0260 QString KChatBase::comboBoxItem(const QString &name) const
0261 { // TODO: such a function for "send to all" and "send to my group"
0262     return i18n("Send to %1", name);
0263 }
0264 
0265 void KChatBase::slotClear()
0266 {
0267     clear();
0268 }
0269 
0270 void KChatBase::setCompletionMode(KCompletion::CompletionMode mode)
0271 {
0272     Q_D(KChatBase);
0273 
0274     d->mEdit->setCompletionMode(mode);
0275 }
0276 
0277 void KChatBase::saveConfig(KConfig *conf)
0278 {
0279     Q_D(KChatBase);
0280 
0281     if (conf == nullptr) {
0282         return;
0283     }
0284     d->mModel->saveConfig(conf);
0285 }
0286 
0287 void KChatBase::readConfig(KConfig *conf)
0288 {
0289     Q_D(KChatBase);
0290 
0291     if (conf == nullptr) {
0292         return;
0293     }
0294     d->mModel->readConfig(conf);
0295 }
0296 
0297 void KChatBase::clear()
0298 {
0299     Q_D(KChatBase);
0300 
0301     d->mModel->removeRows(0, d->mModel->rowCount());
0302 }
0303 
0304 void KChatBase::setMaxItems(int maxItems)
0305 {
0306     Q_D(KChatBase);
0307 
0308     d->mModel->setMaxItems(maxItems);
0309     // TODO cut too many messages
0310     if (maxItems == 0) {
0311         clear();
0312     } else if (maxItems > 0) {
0313         while (d->mModel->rowCount() > (int)maxItems) {
0314             d->mModel->removeRow(0);
0315         }
0316     }
0317 }
0318 
0319 int KChatBase::maxItems() const
0320 {
0321     Q_D(const KChatBase);
0322 
0323     return d->mModel->maxItems();
0324 }
0325 
0326 QFont KChatBase::nameFont() const
0327 {
0328     Q_D(const KChatBase);
0329 
0330     return d->mModel->nameFont();
0331 }
0332 
0333 QFont KChatBase::messageFont() const
0334 {
0335     Q_D(const KChatBase);
0336 
0337     return d->mModel->messageFont();
0338 }
0339 
0340 QFont KChatBase::systemNameFont() const
0341 {
0342     Q_D(const KChatBase);
0343 
0344     return d->mModel->systemNameFont();
0345 }
0346 
0347 QFont KChatBase::systemMessageFont() const
0348 {
0349     Q_D(const KChatBase);
0350 
0351     return d->mModel->systemMessageFont();
0352 }
0353 
0354 void KChatBase::setNameFont(const QFont &font)
0355 {
0356     Q_D(KChatBase);
0357 
0358     d->mModel->setNameFont(font);
0359 }
0360 
0361 void KChatBase::setMessageFont(const QFont &font)
0362 {
0363     Q_D(KChatBase);
0364 
0365     d->mModel->setMessageFont(font);
0366 }
0367 
0368 void KChatBase::setBothFont(const QFont &font)
0369 {
0370     Q_D(KChatBase);
0371 
0372     d->mModel->setBothFont(font);
0373 }
0374 
0375 void KChatBase::setSystemNameFont(const QFont &font)
0376 {
0377     Q_D(KChatBase);
0378 
0379     d->mModel->setSystemNameFont(font);
0380 }
0381 
0382 void KChatBase::setSystemMessageFont(const QFont &font)
0383 {
0384     Q_D(KChatBase);
0385 
0386     d->mModel->setSystemMessageFont(font);
0387 }
0388 
0389 void KChatBase::setSystemBothFont(const QFont &font)
0390 {
0391     Q_D(KChatBase);
0392 
0393     d->mModel->setSystemBothFont(font);
0394 }
0395 
0396 void KChatBase::addMessage(const QString &fromName, const QString &text)
0397 {
0398     Q_D(KChatBase);
0399 
0400     d->mModel->addMessage(fromName, text);
0401 }
0402 
0403 void KChatBase::addSystemMessage(const QString &fromName, const QString &text)
0404 {
0405     Q_D(KChatBase);
0406 
0407     d->mModel->addSystemMessage(fromName, text);
0408 }
0409 
0410 #include "moc_kchatbase.cpp"