Beispiel #1
0
	void GlooxAccount::JoinRoom (const QString& jid, const QString& nick)
	{
		if (!ClientConnection_)
		{
			qWarning () << Q_FUNC_INFO
					<< "null ClientConnection";
			return;
		}

		const auto existingObj = ClientConnection_->GetCLEntry (jid, {});
		const auto existing = qobject_cast<ICLEntry*> (existingObj);
		if (existing && existing->GetEntryType () != ICLEntry::ETMUC)
		{
			const auto res = QMessageBox::question (nullptr,
					"LeechCraft",
					tr ("Cannot join something that's already added to the roster. "
						"Do you want to remove %1 from roster and retry?")
						.arg ("<em>" + jid + "</em>"),
					QMessageBox::Yes | QMessageBox::No);
			if (res != QMessageBox::Yes)
				return;

			RemoveEntry (existingObj);
			ExistingEntry2JoinConflict_ [existingObj] = qMakePair (jid, nick);
			return;
		}

		RoomCLEntry *entry = ClientConnection_->JoinRoom (jid, nick);
		if (!entry)
			return;

		emit gotCLItems ({ entry });
	}
Beispiel #2
0
	void EntryBase::SetVCard (const QXmppVCardIq& vcard, bool initial)
	{
#if QXMPP_VERSION >= 0x000801
		if (vcard == VCardIq_)
			return;
#endif

		VCardIq_ = vcard;
		VCardPhotoHash_ = VCardIq_.photo ().isEmpty () ?
				QByteArray () :
				QCryptographicHash::hash (VCardIq_.photo (), QCryptographicHash::Sha1);

		if (!vcard.photo ().isEmpty ())
		{
			SetAvatar (vcard.photo ());
			Core::Instance ().GetAvatarsStorage ()->StoreAvatar (Avatar_, VCardPhotoHash_.toHex ());
		}

		if (VCardDialog_)
			VCardDialog_->UpdateInfo (vcard);

		if (!initial &&
				GetEntryType () == ICLEntry::EntryType::Chat)
			Core::Instance ().ScheduleSaveRoster (10000);

		emit vcardUpdated ();
	}
Beispiel #3
0
	void EntryBase::handleCommands ()
	{
		QString jid = GetJID ();
		if (GetEntryType () != ETPrivateChat)
		{
			QStringList commandable;
			Q_FOREACH (const QString& var, Variant2VerString_.keys ())
			{
				const QStringList& caps = Account_->GetClientConnection ()->
						GetCapsManager ()->GetRawCaps (Variant2VerString_ [var]);
				if (caps.isEmpty () ||
					caps.contains (AdHocCommandManager::GetAdHocFeature ()))
					commandable << var;
			}

			if (commandable.isEmpty ())
				return;
			else if (commandable.size () == 1)
				jid += '/' + commandable.first ();
			else
			{
				bool ok = true;
				const QString& var = QInputDialog::getItem (0,
						tr ("Select resource"),
						tr ("Select resource for which to fetch the commands"),
						commandable,
						0,
						false,
						&ok);
				if (!ok || var.isEmpty ())
					return;

				jid += '/' + var;
			}
		}
Beispiel #4
0
	MUCInviteDialog::MUCInviteDialog (IAccount *acc, ListType type, QWidget *parent)
	: QDialog (parent)
	, ManualMode_ (false)
	{
		Ui_.setupUi (this);
		Ui_.Invitee_->setInsertPolicy (QComboBox::NoInsert);

		ICLEntry::EntryType requestedType = ICLEntry::EntryType::Chat;
		switch (type)
		{
		case ListType::ListEntries:
			break;
		case ListType::ListMucs:
			requestedType = ICLEntry::EntryType::MUC;
			Ui_.InviteeLabel_->setText ("Conferences:");
			break;
		}

		for (auto entryObj : acc->GetCLEntries ())
		{
			const auto entry = qobject_cast<ICLEntry*> (entryObj);
			if (!entry ||
					entry->GetEntryType () != requestedType)
				continue;

			const QString& id = entry->GetHumanReadableID ();
			Ui_.Invitee_->addItem (QString ("%1 (%2)")
						.arg (entry->GetEntryName ())
						.arg (id),
					id);
		}
	}
Beispiel #5
0
	void EntryBase::SetClientInfo (const QString& variant,
			const QString& node, const QByteArray& ver)
	{
		QString type = XooxUtil::GetClientIDName (node);
		if (type.isEmpty ())
		{
			if (!node.isEmpty ())
				qWarning () << Q_FUNC_INFO
						<< "unknown client type for"
						<< node;
			type = "unknown";
		}
		Variant2ClientInfo_ [variant] ["client_type"] = type;

		QString name = XooxUtil::GetClientHRName (node);
		if (name.isEmpty ())
		{
			if (!node.isEmpty ())
				qWarning () << Q_FUNC_INFO
						<< "unknown client name for"
						<< node;
			name = "Unknown";
		}
		Variant2ClientInfo_ [variant] ["client_name"] = name;
		Variant2ClientInfo_ [variant] ["raw_client_name"] = name;

		Variant2VerString_ [variant] = ver;

		QString reqJid = GetJID ();
		QString reqVar = "";
		if (GetEntryType () == ETChat)
		{
			reqJid = variant.isEmpty () ?
					reqJid :
					reqJid + '/' + variant;
			reqVar = variant;
		}

		auto capsManager = Account_->GetClientConnection ()->GetCapsManager ();
		const auto& storedIds = capsManager->GetIdentities (ver);

		if (!storedIds.isEmpty ())
			SetDiscoIdentities (reqVar, storedIds);
		else
		{
			qDebug () << "requesting ids for" << reqJid << reqVar;
			QPointer<EntryBase> pThis (this);
			QPointer<CapsManager> pCM (capsManager);
			Account_->GetClientConnection ()->RequestInfo (reqJid,
				[ver, reqVar, pThis, pCM] (const QXmppDiscoveryIq& iq)
				{
					if (!ver.isEmpty () && pCM)
						pCM->SetIdentities (ver, iq.identities ());
					if (pThis)
						pThis->SetDiscoIdentities (reqVar, iq.identities ());
				});
		}
	}
	void Xep0313ModelManager::PerformWithEntries (const QList<QObject*>& items,
			const std::function<void (ICLEntry*)>& f)
	{
		for (auto itemObj : items)
		{
			auto entry = qobject_cast<ICLEntry*> (itemObj);
			if (entry->GetEntryType () == ICLEntry::ETMUC)
				continue;

			f (entry);
		}
	}
Beispiel #7
0
bool PlanEntryModel::operator ==(PlanEntryModel &tem)
{
	bool b = true;
	if(compareTo(&tem) != 0)b = false;
	else if(tem.getTaskID() != getTaskID())b = false;
	else if(tem.getTaskStart() != getTaskStart())b = false;
	else if(tem.getTaskStop() != getTaskStop())b = false;
	else if(tem.getPercentComplete() != getPercentComplete())b = false;
	else if(_tcscmp(tem.GetOwner(), GetOwner()) != 0)b = false;
	else if(_tcscmp(tem.getTaskName(), getTaskName()) != 0)b = false;
	else if(_tcscmp(tem.getAnnotation(), getAnnotation()) != 0)b = false;
	else if(GetEntryType() != tem.GetEntryType())b = false;
	return b;
}
Beispiel #8
0
	void EntryBase::handleCommands ()
	{
		auto jid = GetJID ();
		if (GetEntryType () != EntryType::PrivateChat)
		{
			QStringList commandable;
			const auto capsMgr = Account_->GetClientConnection ()->GetCapsManager ();
			for (const auto& pair : Util::Stlize (Variant2VerString_))
			{
				const auto& caps = capsMgr->GetRawCaps (pair.second);
				if (caps.isEmpty () ||
						caps.contains (AdHocCommandManager::GetAdHocFeature ()))
					commandable << pair.first;
			}

			if (commandable.isEmpty ())
				return;
			else if (commandable.size () == 1)
			{
				const auto& var = commandable.first ();
				if (!var.isEmpty ())
					jid += '/' + var;
			}
			else
			{
				bool ok = true;
				const auto& var = QInputDialog::getItem (0,
						tr ("Select resource"),
						tr ("Select resource for which to fetch the commands"),
						commandable,
						0,
						false,
						&ok);
				if (!ok || var.isEmpty ())
					return;

				jid += '/' + var;
			}
		}

		const auto dia = new ExecuteCommandDialog (jid, Account_);
		dia->show ();
	}
Beispiel #9
0
	void MainWidget::showAllUsersList ()
	{
		QList<QObject*> entries;
		int accCount = 0;
		for (auto acc : Core::Instance ().GetAccounts ())
		{
			if (!acc->IsShownInRoster ())
				continue;

			++accCount;
			const auto& accEntries = acc->GetCLEntries ();
			std::copy_if (accEntries.begin (), accEntries.end (), std::back_inserter (entries),
					[] (QObject *entryObj) -> bool
					{
						auto entry = qobject_cast<ICLEntry*> (entryObj);
						return entry->GetEntryType () != ICLEntry::EntryType::PrivateChat;
					});
		}

		UsersListWidget w (entries,
				[accCount] (ICLEntry *entry) -> QString
				{
					QString text = entry->GetEntryName ();
					if (text != entry->GetHumanReadableID ())
						text += " (" + entry->GetHumanReadableID () + ")";

					if (accCount <= 1)
						return text;

					auto acc = entry->GetParentAccount ();
					return text + " [" + acc->GetAccountName () + "]";
				},
				this);
		if (w.exec () != QDialog::Accepted)
			return;

		if (auto entry = w.GetActivatedParticipant ())
			Core::Instance ().GetChatTabsManager ()->
					OpenChat (qobject_cast<ICLEntry*> (entry), true);
	}
	void PasteServiceBase::FeedURL (const QString& pasteUrl)
	{
		if (!Entry_)
		{
			QApplication::clipboard ()->setText (pasteUrl, QClipboard::Clipboard);
			QApplication::clipboard ()->setText (pasteUrl, QClipboard::Selection);

			const Entity& e = Util::MakeNotification (tr ("Text pasted"),
					tr ("Your text has been pasted: %1. The URL has "
						"been copied to the clipboard."),
					PInfo_);
			Proxy_->GetEntityManager ()->HandleEntity (e);

			return;
		}

		auto entry = qobject_cast<ICLEntry*> (Entry_);
		if (!entry)
		{
			qWarning () << Q_FUNC_INFO
					<< "unable to cast"
					<< Entry_
					<< "to ICLEntry";
			return;
		}

		auto type = entry->GetEntryType () == ICLEntry::EntryType::MUC ?
				IMessage::Type::MUCMessage :
				IMessage::Type::ChatMessage;
		const auto msg = entry->CreateMessage (type, QString (), pasteUrl);
		if (!msg)
		{
			qWarning () << Q_FUNC_INFO
					<< "unable to create message for"
					<< entry->GetEntryID ();
			return;
		}
		msg->Send ();
	}
Beispiel #11
0
	void EntryBase::handleTimeReceived (const QXmppEntityTimeIq& iq)
	{
		const auto& from = iq.from ();
		if (!from.startsWith (GetJID ()))
			return;

		const auto& thatTime = iq.utc ();
		if (!thatTime.isValid ())
			return;

		QString bare;
		QString variant;
		ClientConnection::Split (from, &bare, &variant);

		if (variant.isEmpty () || GetEntryType () == EntryType::PrivateChat)
			variant = "";

		const auto secsDiff = QDateTime::currentDateTimeUtc ().secsTo (thatTime);
		Variant2SecsDiff_ [variant] = { static_cast<int> (secsDiff), iq.tzo () };

		emit entryGenerallyChanged ();

		emit entityTimeUpdated ();
	}
	void Plugin::checkDates ()
	{
		if (!XmlSettingsManager::Instance ().property ("NotifyEnabled").toBool ())
			return;

		const auto& ranges = XmlSettingsManager::Instance ()
				.property ("NotificationDays").toString ().split (',', QString::SkipEmptyParts);

		QList<int> allowedDays;
		Q_FOREACH (const auto& range, ranges)
		{
			if (!range.contains ('-'))
			{
				bool ok = false;
				const int day = range.toInt (&ok);
				if (ok)
					allowedDays << day;
				continue;
			}

			const auto& ends = range.split ('-', QString::SkipEmptyParts);
			if (ends.size () != 2)
				continue;

			bool bOk = false, eOk = false;
			const int begin = ends.at (0).toInt (&bOk);
			const int end = ends.at (1).toInt (&eOk);
			if (!bOk || !eOk)
				continue;

			for (int i = begin; i <= end; ++i)
				allowedDays << i;
		}

		const auto& today = QDate::currentDate ();

		auto accs = AzothProxy_->GetAllAccounts ();
		Q_FOREACH (auto accObj, AzothProxy_->GetAllAccounts ())
		{
			auto acc = qobject_cast<IAccount*> (accObj);
			auto extSelf = qobject_cast<IExtSelfInfoAccount*> (accObj);
			Q_FOREACH (auto entryObj, acc->GetCLEntries ())
			{
				auto entry = qobject_cast<ICLEntry*> (entryObj);
				if (!entry || entry->GetEntryType () != ICLEntry::ETChat)
					continue;

				if (extSelf && extSelf->GetSelfContact () == entryObj)
					continue;

				auto meta = qobject_cast<IMetaInfoEntry*> (entryObj);
				if (!meta)
					continue;

				auto dt = meta->GetMetaInfo (IMetaInfoEntry::DataField::BirthDate).toDate ();
				if (!dt.isValid ())
					continue;

				dt.setDate (today.year (), dt.month (), dt.day ());
				if (!dt.isValid ())
					continue;

				int days = today.daysTo (dt);
				if (days < 0)
				{
					dt.setDate (today.year () + 1, dt.month (), dt.day ());
					if (!dt.isValid ())
						continue;
					days = today.daysTo (dt);
				}

				if (allowedDays.contains (days))
					NotifyBirthday (entry, days);
			}
		}
	}
Beispiel #13
0
	void EntryBase::SetStatus (const EntryStatus& status, const QString& variant, const QXmppPresence& presence)
	{
		const bool existed = CurrentStatus_.contains (variant);
		const bool wasOffline = existed ?
				CurrentStatus_ [variant].State_ == SOffline :
				false;

		if (existed &&
				status == CurrentStatus_ [variant] &&
				presence.priority () == Variant2ClientInfo_.value (variant).value ("priority"))
			return;

		CurrentStatus_ [variant] = status;

		const QStringList& vars = Variants ();
		if ((!existed || wasOffline) && !vars.isEmpty ())
		{
			const QString& highest = vars.first ();
			if (Location_.contains (QString ()))
				Location_ [highest] = Location_.take (QString ());
			if (Variant2ClientInfo_.contains (QString ()))
			{
				const auto& info = Variant2ClientInfo_ [QString ()];
				QStringList toCopy;
				toCopy << "user_tune" << "user_mood" << "user_activity";
				Q_FOREACH (const QString& key, toCopy)
					if (info.contains (key))
						Variant2ClientInfo_ [highest] [key] = info [key];
			}
		}

		if ((!existed || wasOffline) &&
				status.State_ != SOffline)
		{
			auto conn = Account_->GetClientConnection ();
			if (conn->GetInfoReqPolicyManager ()->IsRequestAllowed (InfoRequest::Version, this) &&
					!variant.isEmpty ())
				conn->FetchVersion (GetJID () + '/' + variant);
		}

		if (status.State_ != SOffline)
		{
			if (const int p = presence.priority ())
				Variant2ClientInfo_ [variant] ["priority"] = p;
		}
		else
		{
			Variant2Version_.remove (variant);
			Variant2ClientInfo_.remove (variant);
		}

		emit statusChanged (status, variant);

		if (!existed ||
				(existed && status.State_ == SOffline) ||
				wasOffline)
			emit availableVariantsChanged (vars);

		GlooxMessage *message = 0;
		if (GetEntryType () == ETPrivateChat)
			message = new GlooxMessage (IMessage::MTStatusMessage,
					IMessage::DIn,
					qobject_cast<RoomCLEntry*> (GetParentCLEntry ())->
							GetRoomHandler ()->GetRoomJID (),
					GetEntryName (),
					Account_->GetClientConnection ().get ());
		else
			message = new GlooxMessage (IMessage::MTStatusMessage,
				IMessage::DIn,
				GetJID (),
				variant,
				Account_->GetClientConnection ().get ());
		message->SetMessageSubType (IMessage::MSTParticipantStatusChange);

		GlooxProtocol *proto = qobject_cast<GlooxProtocol*> (Account_->GetParentProtocol ());
		IProxyObject *proxy = qobject_cast<IProxyObject*> (proto->GetProxyObject ());
		const QString& state = proxy->StateToString (status.State_);

		const QString& nick = GetEntryName () + '/' + variant;
		message->setProperty ("Azoth/Nick", nick);
		message->setProperty ("Azoth/TargetState", state);
		message->setProperty ("Azoth/StatusText", status.StatusString_);

		QString msg = tr ("%1 is now %2 (%3)")
				.arg (nick)
				.arg (state)
				.arg (status.StatusString_);
		message->SetBody (msg);
		HandleMessage (message);
	}
	void ContactDropFilter::HandleContactsDropped (const QMimeData *data)
	{
		const auto thisEntry = GetEntry<ICLEntry> (EntryId_);
		const bool isMuc = thisEntry->GetEntryType () == ICLEntry::EntryType::MUC;

		auto entries = DndUtil::DecodeEntryObjs (data);
		entries.erase (std::remove_if (entries.begin (), entries.end (),
					[thisEntry] (QObject *entryObj)
					{
						return !CanEntryBeInvited (thisEntry,
								qobject_cast<ICLEntry*> (entryObj));
					}),
				entries.end ());

		if (entries.isEmpty ())
			return;

		QString text;
		if (entries.size () > 1)
			text = isMuc ?
					tr ("Enter reason to invite %n contact(s) to %1:", 0, entries.size ())
						.arg (thisEntry->GetEntryName ()) :
					tr ("Enter reason to invite %1 to %n conference(s):", 0, entries.size ())
						.arg (thisEntry->GetEntryName ());
		else
		{
			const auto muc = isMuc ?
					thisEntry :
					qobject_cast<ICLEntry*> (entries.first ());
			const auto entry = isMuc ?
					qobject_cast<ICLEntry*> (entries.first ()) :
					thisEntry;
			text = tr ("Enter reason to invite %1 to %2:")
					.arg (entry->GetEntryName ())
					.arg (muc->GetEntryName ());
		}

		bool ok = false;
		auto reason = QInputDialog::getText (nullptr,
				tr ("Invite to a MUC"),
				text,
				QLineEdit::Normal,
				{},
				&ok);
		if (!ok)
			return;

		if (isMuc)
		{
			const auto muc = qobject_cast<IMUCEntry*> (thisEntry->GetQObject ());

			for (const auto& entry : entries)
				muc->InviteToMUC (qobject_cast<ICLEntry*> (entry)->GetHumanReadableID (), reason);
		}
		else
		{
			const auto thisId = thisEntry->GetHumanReadableID ();

			for (const auto& mucEntryObj : entries)
			{
				const auto muc = qobject_cast<IMUCEntry*> (mucEntryObj);
				muc->InviteToMUC (thisId, reason);
			}
		}
	}
Beispiel #15
0
	void EntryBase::SetStatus (const EntryStatus& status, const QString& variant, const QXmppPresence& presence)
	{
		const bool existed = CurrentStatus_.contains (variant);
		const bool wasOffline = existed ?
				CurrentStatus_ [variant].State_ == SOffline :
				false;

		if (existed &&
				status == CurrentStatus_ [variant] &&
				presence.priority () == Variant2ClientInfo_.value (variant).value ("priority"))
			return;

		CurrentStatus_ [variant] = status;

		const QStringList& vars = Variants ();
		if ((!existed || wasOffline) && !vars.isEmpty ())
		{
			const QString& highest = vars.first ();
			if (Location_.contains ({}))
				Location_ [highest] = Location_.take ({});
			if (Variant2Audio_.contains ({}))
				Variant2Audio_ [highest] = Variant2Audio_.take ({});
			if (Variant2Mood_.contains ({}))
				Variant2Mood_ [highest] = Variant2Mood_.take ({});
			if (Variant2Activity_.contains ({}))
				Variant2Activity_ [highest] = Variant2Activity_.take ({});
		}

		if ((!existed || wasOffline) &&
				status.State_ != SOffline)
		{
			auto conn = Account_->GetClientConnection ();
			if (conn->GetInfoReqPolicyManager ()->IsRequestAllowed (InfoRequest::Version, this))
			{
				if (!variant.isEmpty ())
					conn->FetchVersion (GetJID () + '/' + variant);
				else
					conn->FetchVersion (GetJID ());
			}
		}

		if (status.State_ != SOffline)
		{
			if (const int p = presence.priority ())
				Variant2ClientInfo_ [variant] ["priority"] = p;
		}
		else
		{
			Variant2Version_.remove (variant);
			Variant2ClientInfo_.remove (variant);
			Variant2VerString_.remove (variant);
			Variant2Identities_.remove (variant);

			Variant2Audio_.remove (variant);
			Variant2Mood_.remove (variant);
			Variant2Activity_.remove (variant);

			Variant2SecsDiff_.remove (variant);
		}

		emit statusChanged (status, variant);

		if (!existed ||
				status.State_ == SOffline ||
				wasOffline)
			emit availableVariantsChanged (vars);

		GlooxMessage *message = 0;
		if (GetEntryType () == EntryType::PrivateChat)
			message = new GlooxMessage (IMessage::Type::StatusMessage,
					IMessage::Direction::In,
					qobject_cast<RoomCLEntry*> (GetParentCLEntryObject ())->
							GetRoomHandler ()->GetRoomJID (),
					GetEntryName (),
					Account_->GetClientConnection ().get ());
		else
			message = new GlooxMessage (IMessage::Type::StatusMessage,
				IMessage::Direction::In,
				GetJID (),
				variant,
				Account_->GetClientConnection ().get ());
		message->SetMessageSubType (IMessage::SubType::ParticipantStatusChange);

		const auto proxy = Account_->GetParentProtocol ()->GetProxyObject ();
		const auto& state = proxy->StateToString (status.State_);

		const auto& nick = GetEntryName () + '/' + variant;
		message->setProperty ("Azoth/Nick", nick);
		message->setProperty ("Azoth/TargetState", state);
		message->setProperty ("Azoth/StatusText", status.StatusString_);

		const auto& msg = tr ("%1 is now %2 (%3)")
				.arg (nick)
				.arg (state)
				.arg (status.StatusString_);
		message->SetBody (msg);
		HandleMessage (message);
	}