void JMessageReceiptFilter::filter(Jreen::Message &message) { Jreen::Receipt *receipt = message.payload<Jreen::Receipt>().data(); ChatUnit *unit = m_account->conferenceManager()->muc(message.from()); if (!unit) unit = m_account->roster()->contact(message.from(), true); qDebug() << Q_FUNC_INFO << unit << message.from(); if(message.containsPayload<Jreen::Error>()) return; if(receipt) { if(receipt->type() == Jreen::Receipt::Received) { QString id = receipt->id(); if(id.isEmpty()) id = message.id(); //for slowpoke client such as Miranda if(unit) qApp->postEvent(ChatLayer::get(unit), new qutim_sdk_0_3::MessageReceiptEvent(id.toUInt(), true)); } else { //TODO send this request only when message marked as read Jreen::Message request(Jreen::Message::Chat, message.from()); request.setThread(message.thread()); //for slowpoke clients request.setID(message.id()); //correct behaviour request.addExtension(new Jreen::Receipt(Jreen::Receipt::Received,message.id())); m_account->client()->send(request); } } Jreen::ChatState *state = message.payload<Jreen::ChatState>().data(); if(state) { if(unit) unit->setChatState(static_cast<qutim_sdk_0_3::ChatUnit::ChatState>(state->state())); } }
void AbstractChatWidget::setTitle(ChatSessionImpl *s) { ChatUnit *u = s->getUnit(); const bool customIcon = (m_attributes & UseCustomIcon); QIcon icon; if (customIcon) icon = Icon("view-choose"); QString title; if(s->unread().count()) title = tr("Chat with %1 (have %2 unread messages)").arg(u->title()).arg(s->unread().count()); else title = tr("Chat with %1").arg(u->title()); if (Conference *c = qobject_cast<Conference *>(u)) { if (customIcon) icon = Icon("meeting-attending"); //TODO title = tr("Conference %1 (%2)").arg(c->title(),c->id()); } else if (customIcon) { if (Buddy *b = qobject_cast<Buddy*>(u)) { if (b->avatar().isEmpty()) icon = Icon("view-choose"); else { QIcon overlay = b->status().icon(); icon = AvatarFilter::icon(b->avatar(), overlay); } } } window()->setWindowTitle(tr("%1 - qutIM").arg(title)); window()->setWindowIcon(icon); }
static inline ChatUnit *getUnitForSession(QObject *obj) { ChatUnit *unit = qobject_cast<ChatUnit*>(obj); if (ChatUnit *contact = unit->metaContact()) unit = contact; return unit ? unit->account()->getUnitForSession(unit) : 0; }
void JSoftwareDetection::handlePresence(const Jreen::Presence &presence) { QString jid = presence.from().full(); ChatUnit *unit = m_account->getUnit(jid, false); if (JContactResource *resource = qobject_cast<JContactResource *>(unit)) { if (!resource->features().isEmpty()) return; setClientInfo(resource, "", "unknown-client"); QString node; if (Jreen::Capabilities::Ptr caps = presence.payload<Jreen::Capabilities>()) { // qDebug() << "handle caps" << caps->node(); QString capsNode = caps->node(); if(capsNode == QLatin1String("http://www.android.com/gtalk/client/caps")) { QString software = "GTalk (Android)"; QString softwareVersion = caps->ver(); QString client = getClientDescription(software, softwareVersion, QString()); updateClientData(resource, client, software, softwareVersion, QString(), "gtalk-android"); return; } static const QRegExp regExp("^http://.*google.com/.*client/caps$"); Q_ASSERT(regExp.isValid()); if(regExp.exactMatch(capsNode)) { QString software = "GTalk"; if(capsNode.startsWith("http://mail.")) software += " (GMail)"; else if(capsNode.startsWith("http://talkgadget.")) software += " (Gadget)"; QString softwareVersion = caps->ver(); QString client = getClientDescription(software, softwareVersion, QString()); updateClientData(resource, client, software, softwareVersion, QString(), "gtalk"); return; } else { node = caps->node() + '#' + caps->ver(); unit->setProperty("node", node); SoftwareInfoHash::iterator it = m_hash.find(node); // qDebug() << "find from hash" << m_hash.count(); if (it != m_hash.end()) { SoftwareInfo &info = *it; resource->setFeatures(info.features); // qDebug() << info.name; if (!info.finished) { // qDebug() << "Send software version request"; requestSoftware(presence.from()); } else { updateClientData(resource, info.description, info.name, info.version, info.os, info.icon); } return; } } } setClientInfo(resource, "", "unknown-client"); Jreen::Disco::Item discoItem(presence.from(), node, QString()); Jreen::DiscoReply *reply = m_account->client()->disco()->requestInfo(discoItem); connect(reply, SIGNAL(finished()), SLOT(onInfoRequestFinished())); } }
ChatUnit* ChatUnit::metaContact() { ChatUnit *u = this; while (u) { if (qobject_cast<MetaContact*>(u)) return u; u = u->upperUnit(); } return 0; }
ChatUnit *ChatUnit::buddy() { ChatUnit *u = this; while (u) { if (qobject_cast<Buddy*>(u)) return u; u = u->upperUnit(); } return this; }
QString AbstractChatWidget::titleForSession(ChatSessionImpl *s) { ChatUnit *u = s->getUnit(); QString title; if(s->unread().count()) title = tr("Chat with %1 (have %2 unread messages)").arg(u->title()).arg(s->unread().count()); else title = tr("Chat with %1").arg(u->title()); if (Conference *c = qobject_cast<Conference *>(u)) title = tr("Conference %1 (%2)").arg(c->title(), c->id()); return title; }
void MetaContactMessageHandler::doHandle(Message &message, const MessageHandler::Handler &handler) { if (message.isIncoming() && !qobject_cast<MetaContactImpl*>(message.chatUnit())) { Q_ASSERT(message.chatUnit()); if (MetaContactImpl *contact = qobject_cast<MetaContactImpl*>(message.chatUnit()->metaContact())) { Contact *rawContact = 0; ChatUnit *u = message.chatUnit(); while (u) { if ((rawContact = qobject_cast<Contact*>(u))) break; u = u->upperUnit(); } if (rawContact && contact->getActiveContact() != rawContact) contact->setActiveContact(rawContact); } } handler(Accept, QString()); }
void OtrMessagePreHandler::encrypt(Message &message) { ChatUnit *unit = const_cast<ChatUnit*>(message.chatUnit()->getHistoryUnit()); if (!qobject_cast<Contact*>(unit)) return; TreeModelItem item = unit; OtrClosure *closure = OTRCrypt::instance()->ensureClosure(unit); QString encrypted = closure->getMessaging()->encryptMessage( unit->account()->id(), unit->id(), message.html(), item); if (encrypted != message.text()) { message.setProperty("__otr__text", message.text()); message.setProperty("__otr__html", message.html()); message.setText(unescape(encrypted)); message.setHtml(encrypted); } }
void OtrMessagePreHandler::decrypt(Message &message) { ChatUnit *unit = const_cast<ChatUnit*>(message.chatUnit()->getHistoryUnit()); if (!qobject_cast<Contact*>(unit)) return; TreeModelItem item = unit; if (OTRCrypt::instance()->isEnabledAccount(unit->account())) { OtrClosure *closure = OTRCrypt::instance()->ensureClosure(unit); QString decrypted = closure->getMessaging()->decryptMessage( unit->id(), unit->account()->id(), message.text(), item); if (message.text() != decrypted) { message.setText(unescape(decrypted)); message.setHtml(decrypted); message.setProperty("otrEncrypted", true); } } }
void NetworkManager::sendMessage(const qutim_sdk_0_3::Message &message) { MessageAction *action = new MessageAction(); ChatUnit *contact = const_cast<ChatUnit*>(message.chatUnit()->getHistoryUnit()); action->account = AccountId(contact->account()); action->contact = contact->id(); action->time = message.time(); action->text = message.text(); action->incoming = message.isIncoming(); if (message.property("otrEncrypted", false)) action->encryption << QLatin1String("otr"); if (message.property("pgpEncrypted", false) || (encryptedMessageIdInited && encryptedMessageId == message.id())) { action->encryption << QLatin1String("pgp"); } if (message.property("autoreply", false)) action->encryption << QLatin1String("autoreply"); m_actions << action; trySend(); }
const ChatUnit* ChatUnit::getHistoryUnit() const { ChatUnit *u = const_cast<ChatUnit *>(this); ChatUnit *buddy = 0; if (qobject_cast<Contact*>(u)) return u; else if (qobject_cast<Buddy*>(u)) buddy = u; ChatUnit *p; while ((p = u->upperUnit()) != 0) { if (qobject_cast<MetaContact*>(p)) { break; } else if (qobject_cast<Contact*>(p)) { buddy = p; break; } else if (qobject_cast<Conference*>(p)) { break; } else if (qobject_cast<Buddy*>(p) && !buddy) { buddy = p; } u = p; } return buddy ? buddy : u; }
void HistoryWindow::on_dateTreeWidget_currentItemChanged(QTreeWidgetItem *dayItem, QTreeWidgetItem *) { QTreeWidgetItem *monthItem = dayItem ? dayItem->parent() : nullptr; if (!dayItem || !monthItem) return; if (dayItem->data(0, Qt::UserRole).type() != QVariant::Date) return; if (monthItem->data(0, Qt::UserRole).type() != QVariant::Date) return; auto contactIndex = ui.fromComboBox->currentIndex(); auto contactInfo = ui.fromComboBox->itemData(contactIndex).value<History::ContactInfo>(); auto date = dayItem->data(0, Qt::UserRole).toDate(); QDateTime from(date, QTime(0, 0)); QDateTime to(date, QTime(23, 59, 59, 999)); int count = std::numeric_limits<int>::max(); history()->read(contactInfo, from, to, count).connect(this, [this, contactInfo, date] (const MessageList &messages) { int contactIndex = ui.fromComboBox->currentIndex(); auto currentContactInfo = ui.fromComboBox->itemData(contactIndex).value<History::ContactInfo>(); if (!(currentContactInfo == contactInfo)) return; QTextDocument *doc = ui.historyLog->document(); doc->setParent(0); ui.historyLog->setDocument(0); doc->clear(); QTextCursor cursor = QTextCursor(doc); QTextCharFormat defaultFont = cursor.charFormat(); QTextCharFormat serviceFont = cursor.charFormat(); serviceFont.setForeground(Qt::darkGreen); serviceFont.setFontWeight(QFont::Bold); QTextCharFormat incomingFont = cursor.charFormat(); incomingFont.setForeground(Qt::red); incomingFont.setFontWeight(QFont::Bold); QTextCharFormat outgoingFont = cursor.charFormat(); outgoingFont.setForeground(Qt::blue); outgoingFont.setFontWeight(QFont::Bold); const QString serviceMessageTitle = tr("Service message"); const QString resultString = QStringLiteral("<span style='background: #ffff00'>\\1</span>"); cursor.beginEditBlock(); Account *account = findAccount(contactInfo); ChatUnit *unit = findContact(contactInfo); QString accountNickname = account ? account->name() : contactInfo.account; QString fromNickname = unit ? unit->title() : contactInfo.contact; int in_count = 0; int out_count = 0; for (const Message &message : messages) { bool service = message.property("service", false); QDateTime time = message.time(); bool incoming = message.isIncoming(); QString historyMessage = message.html(); QString sender = message.property("senderName", incoming ? fromNickname : accountNickname); incoming ? in_count++ : out_count++; if (service) { cursor.setCharFormat(serviceFont); cursor.insertText(serviceMessageTitle); } else { cursor.setCharFormat(incoming ? incomingFont : outgoingFont); cursor.insertText(sender); } cursor.insertText(QStringLiteral(" (") % time.toString(QStringLiteral("dd.MM.yyyy hh:mm:ss")) % QStringLiteral(")")); cursor.setCharFormat(defaultFont); cursor.insertText(QStringLiteral("\n")); if (m_search_word.isEmpty()) { cursor.insertHtml(historyMessage); cursor.insertText(QStringLiteral("\n")); } else { cursor.insertHtml(historyMessage.replace(m_search, resultString)); cursor.insertText(QStringLiteral("\n")); } } cursor.endEditBlock(); doc->setParent(ui.historyLog); ui.historyLog->setDocument(doc); if (m_search_word.isEmpty()) ui.historyLog->moveCursor(QTextCursor::End); else ui.historyLog->find(m_search_word); ui.historyLog->verticalScrollBar()->setValue(ui.historyLog->verticalScrollBar()->maximum()); ui.label_in->setText(tr("In: %L1").arg(in_count)); ui.label_out->setText(tr("Out: %L1").arg(out_count)); ui.label_all->setText(tr("All: %L1").arg(in_count + out_count)); }); }
QString &WebKitMessageViewStyle::fillKeywordsForBaseTemplate(QString &inString, qutim_sdk_0_3::ChatSession *session) { Q_D(WebKitMessageViewStyle); ChatUnit *unit = session->unit(); Account *account = unit->account(); Protocol *protocol = account->protocol(); // FIXME: Should be session->title inString.replace(QLatin1String("%chatName%"), escapeString(unit->title())); inString.replace(QLatin1String("%sourceName%"), escapeString(account->name())); inString.replace(QLatin1String("%destinationName%"), escapeString(unit->id())); inString.replace(QLatin1String("%destinationDisplayName%"), escapeString(unit->title())); QString iconPath; inString.replace(QLatin1String("%incomingColor%"), WebKitColorsAdditions::representedColorForObject(unit->id(), validSenderColors())); inString.replace(QLatin1String("%outgoingColor%"), WebKitColorsAdditions::representedColorForObject(account->name(), validSenderColors())); iconPath = urlFromFilePath(unit->property("avatar").toString()); if (iconPath.isEmpty()) { ChatUnit *contact = unit->upperUnit(); while (contact && iconPath.isEmpty()) { iconPath = contact->property("avatar").toString(); contact = contact->upperUnit(); } } inString.replace(QLatin1String("%incomingIconPath%"), iconPath.isEmpty() ? QString::fromLatin1("incoming_icon.png") : iconPath); iconPath = urlFromFilePath(account->property("avatar").toString()); inString.replace(QLatin1String("%outgoingIconPath%"), iconPath.isEmpty() ? QString::fromLatin1("outgoing_icon.png") : iconPath); // FIXME: Implement protocol.iconPath and protocol.shortDescription QString serviceIconPath = QString(); //account.protocol.iconPath; QString serviceIconTag = QString::fromLatin1("<img class=\"serviceIcon\" src=\"%1\" alt=\"%2\" title=\"%2\">") .arg(serviceIconPath.isEmpty() ? QString::fromLatin1("outgoing_icon.png") : serviceIconPath, protocol->id() /*shortDescription*/ ); inString.replace(QLatin1String("%serviceIconImg%"), serviceIconTag); inString.replace(QLatin1String("%serviceIconPath%"), serviceIconPath); inString.replace(QLatin1String("%timeOpened%"), convertTimeDate(d->timeStampFormatter, session->dateOpened())); //Replaces %time{x}% with a timestamp formatted like x (using NSDateFormatter) const QStringMatcher matcher(QLatin1String("%timeOpened{")); const int matcherSize = matcher.pattern().size(); const QStringMatcher endMatcher(QLatin1String("}%")); const int endMatcherSize = endMatcher.pattern().size(); int range = 0; do { range = matcher.indexIn(inString, range); if (range != -1) { int endRange = endMatcher.indexIn(inString, range + matcherSize); if (endRange != -1) { QString timeFormat = inString.mid(range + matcherSize, endRange - range - matcherSize); QString time = convertTimeDate(timeFormat, session->dateOpened()); inString.replace(range, endRange + endMatcherSize - range, time); range = range + time.size(); } } } while (range != -1); inString.replace(QLatin1String("%dateOpened%"), session->dateOpened().toString(Qt::SystemLocaleLongDate)); //Background { QLatin1String bodyBackground("==bodyBackground=="); range = inString.indexOf(bodyBackground); if (range != -1) { //a backgroundImage tag is not required QString bodyTag; if (d->allowsCustomBackground && (!d->customBackgroundPath.isEmpty() || d->customBackgroundColor.isValid())) { if (!d->customBackgroundPath.isNull()) { if (d->customBackgroundPath.length() > 0) { switch (d->customBackgroundType) { case BackgroundNormal: bodyTag.append(QString::fromLatin1("background-image: url('%1'); background-repeat: no-repeat; background-attachment:fixed;").arg(d->customBackgroundPath)); break; case BackgroundCenter: bodyTag.append(QString::fromLatin1("background-image: url('%1'); background-position: center; background-repeat: no-repeat; background-attachment:fixed;").arg(d->customBackgroundPath)); break; case BackgroundTile: bodyTag.append(QString::fromLatin1("background-image: url('%1'); background-repeat: repeat;").arg(d->customBackgroundPath)); break; case BackgroundTileCenter: bodyTag.append(QString::fromLatin1("background-image: url('%1'); background-repeat: repeat; background-position: center;").arg(d->customBackgroundPath)); break; case BackgroundScale: bodyTag.append(QString::fromLatin1("background-image: url('%1'); -webkit-background-size: 100%% 100%%; background-size: 100%% 100%%; background-attachment: fixed;").arg(d->customBackgroundPath)); break; } } else { bodyTag.append(QLatin1String("background-image: none; ")); } } if (d->customBackgroundColor.isValid()) { qreal red, green, blue, alpha; d->customBackgroundColor.getRgbF(&red, &green, &blue, &alpha); bodyTag.append(QString::fromLatin1("background-color: rgba(%1, %2, %3, %4); ") .arg(QString::number(int(red * 255.0)), QString::number(int(green * 255.0)), QString::number(int(blue * 255.0)), QString::number(alpha, 'f'))); } } //Replace the body background tag inString.replace(range, qstrlen(bodyBackground.latin1()), bodyTag); } } inString.replace(QLatin1String("%variant%"), activeVariantPath()); return inString; }
void ChatEdit::send() { QString text = textEditToPlainText(); QString trimmed = text.trimmed(); if(!m_session || trimmed.isEmpty()) return; ChatUnit *unit = m_session->getCurrentUnit(); if (trimmed.startsWith(QLatin1Char('/')) && trimmed.size() > 1) { int index = trimmed.indexOf(QLatin1Char(' ')); QStringRef cmd = trimmed.midRef(1, (index == -1 ? trimmed.size() : index) - 1); const QMetaObject *meta = unit->metaObject(); for (int i = meta->propertyCount() - 1; i >= 0; --i) { QMetaProperty prop = meta->property(i); if (prop.isWritable() && QLatin1String(prop.name()) == cmd) { prop.write(unit, trimmed.mid(index + 1)); clear(); return; } } QByteArray signature = cmd.toString().toLatin1(); int methodIndex = meta->indexOfMethod(signature + "(QString)"); if (methodIndex != -1) { QMetaMethod method = meta->method(methodIndex); QString arg = trimmed.mid(index + 1); if (method.invoke(unit, Q_ARG(QString, arg))) { clear(); return; } } methodIndex = meta->indexOfMethod(signature + "(QVariant)"); if (methodIndex != -1) { QMetaMethod method = meta->method(methodIndex); QVariant arg = trimmed.mid(index + 1); if (method.invoke(unit, Q_ARG(QVariant, arg))) { clear(); return; } } methodIndex = meta->indexOfMethod(signature + "()"); if (methodIndex != -1) { QMetaMethod method = meta->method(methodIndex); if (method.invoke(unit)) { clear(); return; } } } Message message(text); message.setIncoming(false); message.setChatUnit(unit); message.setTime(QDateTime::currentDateTime()); qint64 result = m_session->appendMessage(message); if (MessageHandler::Error != -result) clear(); // if (!unit->sendMessage(message)) { // NotificationRequest request(Notification::System); // request.setObject(this); // request.setText(tr("Unable to send message to %1").arg(unit->title())); // request.send(); // } // else { // m_session->appendMessage(message); // clear(); // } }
void ChatEdit::send() { if (!isEnabled()) return; ChatEditLocker locker(this); QString text = textEditToPlainText(); QString trimmed = text.trimmed(); if(!m_session || trimmed.isEmpty()) return; ChatUnit *unit = m_session.data()->getCurrentUnit(); if (trimmed.startsWith(QLatin1Char('/')) && trimmed.size() > 1) { int index = trimmed.indexOf(QLatin1Char(' ')); QStringRef cmd = trimmed.midRef(1, (index == -1 ? trimmed.size() : index) - 1); const QMetaObject *meta = unit->metaObject(); for (int i = meta->propertyCount() - 1; i >= 0; --i) { QMetaProperty prop = meta->property(i); if (prop.isWritable() && QLatin1String(prop.name()) == cmd) { prop.write(unit, trimmed.mid(index + 1)); clear(); return; } } QByteArray signature = cmd.toString().toLatin1(); int methodIndex = meta->indexOfMethod(signature + "(QString)"); if (methodIndex != -1) { QMetaMethod method = meta->method(methodIndex); QString arg = trimmed.mid(index + 1); if (method.invoke(unit, Q_ARG(QString, arg))) { clear(); return; } } methodIndex = meta->indexOfMethod(signature + "(QVariant)"); if (methodIndex != -1) { QMetaMethod method = meta->method(methodIndex); QVariant arg = trimmed.mid(index + 1); if (method.invoke(unit, Q_ARG(QVariant, arg))) { clear(); return; } } methodIndex = meta->indexOfMethod(signature + "()"); if (methodIndex != -1) { QMetaMethod method = meta->method(methodIndex); if (method.invoke(unit)) { clear(); return; } } } Message message(text); message.setIncoming(false); message.setChatUnit(unit); message.setTime(QDateTime::currentDateTime()); MessageHandler::traceHandlers(); auto lockerPtr = QSharedPointer<ChatEditLocker>::create(std::move(locker)); QPointer<ChatEdit> edit(this); m_session->append(message, [edit, lockerPtr] (qint64 result, const Message &, const QString &) mutable { if (MessageHandler::Error != -result && edit) edit->clear(); lockerPtr.reset(); }); }