Exemple #1
0
	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;
	}
Exemple #2
0
	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));
	}
Exemple #3
0
	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));
	}
Exemple #4
0
	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 ('<', "&lt;");
		postNick.replace ('<', "&lt;");

		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 ('<', "&lt;");
			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 ();
		}
	}