void Plugin::RequestLastMessages (QObject *entryObj, int num) { ICLEntry *entry = qobject_cast<ICLEntry*> (entryObj); if (!entry) { qWarning () << Q_FUNC_INFO << entryObj << "doesn't implement ICLEntry"; return; } if (entry->GetEntryType () != ICLEntry::ETChat) return; IAccount *account = qobject_cast<IAccount*> (entry->GetParentAccount ()); if (!account) { qWarning () << Q_FUNC_INFO << entry->GetParentAccount () << "doesn't implement IAccount"; return; } const QString& accId = account->GetAccountID (); const QString& entryId = entry->GetEntryID (); Core::Instance ()->GetChatLogs (accId, entryId, 0, num); RequestedLogs_ [accId] [entryId] = entryObj; }
void Core::Process (QObject *msgObj) { IMessage *msg = qobject_cast<IMessage*> (msgObj); if (msg->GetMessageType () != IMessage::MTChatMessage && msg->GetMessageType () != IMessage::MTMUCMessage) return; if (msg->GetBody ().isEmpty ()) return; if (msg->GetDirection () == IMessage::DOut && msg->GetMessageType () == IMessage::MTMUCMessage) return; ICLEntry *entry = qobject_cast<ICLEntry*> (msg->ParentCLEntry ()); if (!entry) { qWarning () << Q_FUNC_INFO << "message's other part doesn't implement ICLEntry" << msg->GetObject () << msg->OtherPart (); return; } if (DisabledIDs_.contains (entry->GetEntryID ())) return; IAccount *acc = qobject_cast<IAccount*> (entry->GetParentAccount ()); if (!acc) { qWarning () << Q_FUNC_INFO << "message's account doesn't implement IAccount" << entry->GetParentAccount (); return; } QVariantMap data; data ["EntryID"] = entry->GetEntryID (); data ["VisibleName"] = entry->GetEntryName (); data ["AccountID"] = acc->GetAccountID (); data ["DateTime"] = msg->GetDateTime (); data ["Direction"] = msg->GetDirection () == IMessage::DIn ? "IN" : "OUT"; data ["Body"] = msg->GetBody (); data ["OtherVariant"] = msg->GetOtherVariant (); data ["MessageType"] = static_cast<int> (msg->GetMessageType ()); QMetaObject::invokeMethod (StorageThread_->GetStorage (), "addMessage", Qt::QueuedConnection, Q_ARG (QVariantMap, data)); }
void Core::Process (QObject *msgObj) { IMessage *msg = qobject_cast<IMessage*> (msgObj); if (msg->GetMessageType () != IMessage::Type::ChatMessage && msg->GetMessageType () != IMessage::Type::MUCMessage) return; if (msg->GetBody ().isEmpty ()) return; if (msg->GetDirection () == IMessage::Direction::Out && msg->GetMessageType () == IMessage::Type::MUCMessage) return; const double secsDiff = msg->GetDateTime ().secsTo (QDateTime::currentDateTime ()); if (msg->GetMessageType () == IMessage::Type::MUCMessage && std::abs (secsDiff) >= 2) return; ICLEntry *entry = qobject_cast<ICLEntry*> (msg->ParentCLEntry ()); if (!entry) { qWarning () << Q_FUNC_INFO << "message's other part doesn't implement ICLEntry" << msg->GetQObject () << msg->OtherPart (); return; } if (DisabledIDs_.contains (entry->GetEntryID ())) return; const auto acc = entry->GetParentAccount (); QVariantMap data; data ["EntryID"] = entry->GetEntryID (); data ["AccountID"] = acc->GetAccountID (); data ["DateTime"] = msg->GetDateTime (); data ["Direction"] = msg->GetDirection () == IMessage::Direction::In ? "IN" : "OUT"; data ["Body"] = msg->GetBody (); data ["OtherVariant"] = msg->GetOtherVariant (); data ["Type"] = static_cast<int> (msg->GetMessageType ()); data ["EscapePolicy"] = msg->GetEscapePolicy () == IMessage::EscapePolicy::Escape ? "Esc" : "NEs"; if (const auto irtm = qobject_cast<IRichTextMessage*> (msgObj)) data ["RichBody"] = irtm->GetRichBody (); if (entry->GetEntryType () == ICLEntry::EntryType::PrivateChat) { const auto parent = entry->GetParentCLEntry (); data ["VisibleName"] = parent->GetEntryName () + "/" + entry->GetEntryName (); } else data ["VisibleName"] = entry->GetEntryName (); QMetaObject::invokeMethod (StorageThread_->GetStorage (), "addMessage", Qt::QueuedConnection, Q_ARG (QVariantMap, data)); }
bool CLModel::TryDropFile (const QMimeData* mime, const QModelIndex& parent) { if (parent.data (Core::CLREntryType).value<Core::CLEntryType> () != Core::CLETContact) return false; QObject *entryObj = parent.data (Core::CLREntryObject).value<QObject*> (); ICLEntry *entry = qobject_cast<ICLEntry*> (entryObj); if (entry->Variants ().isEmpty ()) return false; IAccount *acc = qobject_cast<IAccount*> (entry->GetParentAccount ()); ITransferManager *mgr = qobject_cast<ITransferManager*> (acc->GetTransferManager ()); if (!mgr) return false; const QList<QUrl>& urls = mime->urls (); if (urls.isEmpty ()) return false; QString text; if (urls.size () > 2) text = tr ("Are you sure you want to send %n files to %1?", 0, urls.size ()) .arg (entry->GetEntryName ()); else { QStringList list; Q_FOREACH (const QUrl& url, urls) list << QFileInfo (url.path ()).fileName (); text = tr ("Are you sure you want to send %1 to %2?") .arg ("<em>" + list.join (", ") + "</em>") .arg (entry->GetEntryName ()); } if (QMessageBox::question (0, "LeechCraft", text, QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return false; Q_FOREACH (const QUrl& url, urls) { const QString& path = url.toLocalFile (); if (!QFileInfo (path).exists ()) continue; QObject *job = mgr->SendFile (entry->GetEntryID (), entry->Variants ().first (), path); Core::Instance ().GetTransferJobManager()->HandleJob (job); } return true; }
void ContactListDelegate::DrawContact (QPainter *painter, QStyleOptionViewItemV4 option, const QModelIndex& index) const { QObject *entryObj = index.data (Core::CLREntryObject).value<QObject*> (); ICLEntry *entry = qobject_cast<ICLEntry*> (entryObj); const bool isMUC = entry->GetEntryType () == ICLEntry::ETMUC; QStyle *style = option.widget ? option.widget->style () : QApplication::style (); const QRect& r = option.rect; const int sHeight = r.height (); const int iconSize = sHeight - 2 * CPadding; const int clientIconSize = (iconSize > 16) ? 16 : iconSize; const QIcon& stateIcon = index.data (Qt::DecorationRole).value<QIcon> (); QString name = index.data (Qt::DisplayRole).value<QString> (); const QString status = entry->GetStatus ().StatusString_.replace ('\n', ' '); const QImage& avatarImg = ShowAvatars_ ? Core::Instance ().GetAvatar (entry, iconSize) : QImage (); const int unreadNum = index.data (Core::CLRUnreadMsgCount).toInt (); const QString& unreadStr = unreadNum ? QString (" %1 :: ").arg (unreadNum) : QString (); if (ShowStatuses_ && !status.isEmpty ()) name += " (" + status + ")"; const bool selected = option.state & QStyle::State_Selected; const QColor fgColor = selected ? option.palette.color (QPalette::HighlightedText) : option.palette.color (QPalette::Text); QFont unreadFont; int unreadSpace = 0; if (unreadNum) { unreadFont = option.font; unreadFont.setBold (true); unreadSpace = CPadding + QFontMetrics (unreadFont).width (unreadStr); } const int textShift = 2 * CPadding + iconSize + unreadSpace; const QStringList& vars = entry->Variants (); QList<QIcon> clientIcons; if (!isMUC && ShowClientIcons_) { const auto& iconsMap = Core::Instance ().GetClientIconForEntry (entry); for (int i = 0; i < std::min (vars.size (), 4); ++i) clientIcons << iconsMap [vars.at (i)]; clientIcons.erase (std::remove_if (clientIcons.begin (), clientIcons.end (), [] (const QIcon& icon) { return icon.isNull (); }), clientIcons.end ()); } if (entry->GetEntryType () == ICLEntry::ETPrivateChat) { const QByteArray& aff = index.data (Core::CLRAffiliation).toByteArray (); const QIcon& icon = Core::Instance ().GetAffIcon (aff); if (!icon.isNull ()) clientIcons.prepend (icon); } if (!vars.isEmpty ()) { const QMap<QString, QVariant>& addInfo = entry->GetClientInfo (vars.first ()); if (addInfo.contains ("user_activity")) { const QMap<QString, QVariant>& actInfo = addInfo ["user_activity"].toMap (); const QString& iconName = ActivityIconset_ + '/' + GetActivityIconName (actInfo ["general"].toString (), actInfo ["specific"].toString ()); QIcon icon = ActivityIconCache_ [iconName]; if (icon.isNull ()) icon = QIcon (Core::Instance () .GetResourceLoader (Core::RLTActivityIconLoader)-> GetIconPath (iconName)); if (!icon.isNull ()) { clientIcons.prepend (icon); ActivityIconCache_ [iconName] = icon; } } if (addInfo.contains ("user_mood")) { const QMap<QString, QVariant>& moodInfo = addInfo ["user_mood"].toMap (); QString iconName = moodInfo ["mood"].toString (); iconName [0] = iconName.at (0).toUpper (); iconName.prepend (MoodIconset_ + '/'); QIcon icon = MoodIconCache_ [iconName]; if (icon.isNull ()) icon = QIcon (Core::Instance () .GetResourceLoader (Core::RLTMoodIconLoader)-> GetIconPath (iconName)); if (!icon.isNull ()) { clientIcons.prepend (icon); MoodIconCache_ [iconName] = icon; } } if (addInfo.contains ("user_tune")) LoadSystemIcon ("/notification_roster_tune", clientIcons); ISupportGeolocation *geoloc = qobject_cast<ISupportGeolocation*> (entry->GetParentAccount ()); if (geoloc) { const GeolocationInfo_t& info = geoloc-> GetUserGeolocationInfo (entryObj, vars.value (0, QString ())); if (!info.isEmpty ()) LoadSystemIcon ("/geolocation", clientIcons); } } const int clientsIconsWidth = clientIcons.isEmpty () ? 0 : clientIcons.size () * (clientIconSize + CPadding); /* text for width is total width minus shift of the text from * the left (textShift) minus space for avatar (if present) with * paddings minus space for client icons and paddings between * them: there are N-1 paddings inbetween if there are N icons. */ const int textWidth = r.width () - textShift - (isMUC || !ShowAvatars_ ? 0 : (iconSize + 2 * CPadding)) - clientsIconsWidth; QPixmap pixmap (r.size ()); pixmap.fill (Qt::transparent); QPainter p (&pixmap); if (selected || (option.state & QStyle::State_MouseOver)) { QStyleOptionViewItemV4 bgOpt = option; bgOpt.rect.moveTopLeft (QPoint (0, 0)); style->drawPrimitive (QStyle::PE_PanelItemViewItem, &bgOpt, &p, option.widget); } p.setPen (fgColor); if (unreadNum) { p.setFont (unreadFont); p.drawText (textShift - unreadSpace, CPadding, textWidth, r.height () - 2 * CPadding, Qt::AlignVCenter | Qt::AlignLeft, unreadStr); } p.setFont (option.font); p.drawText (textShift, CPadding, textWidth, r.height () - 2 * CPadding, Qt::AlignVCenter | Qt::AlignLeft, option.fontMetrics.elidedText (name, Qt::ElideRight, textWidth)); const QPixmap& stateIconPx = stateIcon.pixmap (iconSize, iconSize); p.drawPixmap (QPoint (CPadding, (sHeight - stateIconPx.height ()) / 2), stateIconPx); if (!avatarImg.isNull ()) p.drawPixmap (QPoint (textShift + textWidth + clientsIconsWidth + CPadding, CPadding), QPixmap::fromImage (avatarImg)); int currentShift = textShift + textWidth + CPadding; Q_FOREACH (const QIcon& icon, clientIcons) { p.drawPixmap (QPoint (currentShift, (sHeight - stateIconPx.height ()) / 2), icon.pixmap (clientIconSize, clientIconSize)); currentShift += clientIconSize + CPadding; }
void ChatHistoryWidget::handleGotChatLogs (const QString& accountId, const QString& entryId, int, int, const QVariant& logsVar) { const QString& selectedEntry = Ui_.Contacts_->selectionModel ()-> currentIndex ().data (MRIDRole).toString (); if (accountId != Ui_.AccountBox_-> itemData (Ui_.AccountBox_->currentIndex ()).toString () || entryId != selectedEntry) return; Amount_ = 0; Ui_.HistView_->clear (); const auto& defFormat = Ui_.HistView_->currentCharFormat (); ICLEntry *entry = qobject_cast<ICLEntry*> (Core::Instance ()-> GetPluginProxy ()->GetEntry (entryId, accountId)); const QString& name = entry ? entry->GetEntryName () : EntryID2NameCache_.value (entryId, entryId); const QString& ourName = entry ? qobject_cast<IAccount*> (entry->GetParentAccount ())->GetOurNick () : QString (); QString preNick = Core::Instance ()->GetPluginProxy ()-> GetSettingsManager ()->property ("PreNickText").toString (); QString postNick = Core::Instance ()->GetPluginProxy ()-> GetSettingsManager ()->property ("PostNickText").toString (); preNick.replace ('<', "<"); postNick.replace ('<', "<"); const auto& bgColor = palette ().color (QPalette::Base); const auto& colors = Core::Instance ()-> GetPluginProxy ()->GenerateColors ("hash", bgColor); int scrollPos = -1; for (const auto& logVar : logsVar.toList ()) { const QVariantMap& map = logVar.toMap (); const bool isChat = map ["Type"] == "CHAT"; QString html = "[" + map ["Date"].toDateTime ().toString () + "] " + preNick; const QString& var = map ["Variant"].toString (); if (isChat) { QString remoteName; if (!entry && !var.isEmpty ()) remoteName += var; else if (entry && var.isEmpty ()) remoteName += name; else remoteName += name + '/' + var; if (!ourName.isEmpty ()) html += map ["Direction"] == "IN" ? remoteName : ourName; else { html += map ["Direction"] == "IN" ? QString::fromUtf8 ("← ") : QString::fromUtf8 ("→ "); html += remoteName; } } else { const QString& color = Core::Instance ()-> GetPluginProxy ()->GetNickColor (var, colors); html += "<font color=\"" + color + "\">" + var + "</font>"; } auto msgText = map ["Message"].toString (); msgText.replace ('<', "<"); Core::Instance ()->GetPluginProxy ()->FormatLinks (msgText); msgText.replace ('\n', "<br/>"); html += postNick + ' ' + msgText; const bool isSearchRes = SearchResultPosition_ == PerPageAmount_ - Amount_; if (isChat && !isSearchRes) { html.prepend (QString ("<font color=\"#") + (map ["Direction"] == "IN" ? "0000dd" : "dd0000") + "\">"); html += "</font>"; } else if (isSearchRes) { QTextCharFormat fmt = defFormat; scrollPos = Ui_.HistView_->document ()->characterCount (); html.prepend ("<font color='#FF7E00'>"); html += "</font>"; } ++Amount_; Ui_.HistView_->append (html); if (isSearchRes) Ui_.HistView_->setCurrentCharFormat (defFormat); } if (scrollPos >= 0) { QTextCursor cur (Ui_.HistView_->document ()); cur.setPosition (scrollPos); Ui_.HistView_->setTextCursor (cur); Ui_.HistView_->ensureCursorVisible (); } }