Пример #1
0
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()));
	}
}
Пример #2
0
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);
}
Пример #3
0
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;
}
Пример #4
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()));
	}
}
Пример #5
0
ChatUnit* ChatUnit::metaContact()
{
	ChatUnit *u = this;
	while (u) {
		if (qobject_cast<MetaContact*>(u))
			return u;
		u = u->upperUnit();
	}
	return 0;
}
Пример #6
0
ChatUnit *ChatUnit::buddy()
{
	ChatUnit *u = this;
	while (u) {
		if (qobject_cast<Buddy*>(u))
			return u;
		u = u->upperUnit();
	}
	return this;
}
Пример #7
0
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;
}
Пример #8
0
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());
}
Пример #9
0
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);
	}
}
Пример #10
0
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);
		}
	}
}
Пример #11
0
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();
}
Пример #12
0
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;
}
Пример #13
0
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));
	});
}
Пример #14
0
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;
}
Пример #15
0
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();
//	}
}
Пример #16
0
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();
	});
}