Example #1
0
ContactListModelSelection::ContactListModelSelection(QList<ContactListItemProxy*> items)
	: QMimeData()
	, mimeData_(0)
{
	QDomDocument doc;
	QDomElement root = doc.createElement("items");
	root.setAttribute("version", "2.0");
	doc.appendChild(root);

	// TODO: maybe also embed a random instance-specific token to
	// prevent drag'n'drop with other running Psi instances?

	QStringList jids;

	foreach(ContactListItemProxy* itemProxy, items) {
		Q_ASSERT(itemProxy);

		PsiContact* contact = 0;
		ContactListNestedGroup* group = 0;
		ContactListAccountGroup* account = 0;
		if ((contact = dynamic_cast<PsiContact*>(itemProxy->item()))) {
			QDomElement tag = textTag(&doc, "contact", contact->jid().full());
			tag.setAttribute("account", contact->account()->id());
			tag.setAttribute("group", itemProxy->parent() ? itemProxy->parent()->fullName() : "");
			root.appendChild(tag);

			jids << contact->jid().full();
		}
		else if ((account = dynamic_cast<ContactListAccountGroup*>(itemProxy->item()))) {
			QDomElement tag = doc.createElement("account");
			tag.setAttribute("id", account->account()->id());
			root.appendChild(tag);

			jids << account->displayName();
		}
		else if ((group = dynamic_cast<ContactListNestedGroup*>(itemProxy->item()))) {
			// if group->fullName() consists only of whitespace when we'll try
			// to read it back we'll get an empty string, so we're using CDATA
			// QDomElement tag = textTag(&doc, "group", group->fullName());
			QDomElement tag = doc.createElement("group");
			QDomText text = doc.createCDATASection(TextUtil::escape(group->fullName()));
			tag.appendChild(text);

			root.appendChild(tag);

			jids << group->fullName();
		}
		else {
			qWarning("ContactListModelSelection::ContactListModelSelection(): Unable to serialize %d, unsupported type", itemProxy->item()->type());
		}
	}
Example #2
0
bool ContactListModel::setData(const QModelIndex &index, const QVariant &data, int role)
{
    if (!index.isValid())
        return false;

    ContactListItem *item = toItem(index);
    if (!item)
        return false;
    PsiContact *contact = item->isContact() ? item->contact() : nullptr;

    if (role == ActivateRole) {
        if (!contact)
            return false;

        contact->activate();
        return true;
    }
    else if (role == Qt::EditRole) {
        QString name = data.toString();
        if (contact) {
            item->setName(name);
            emit dataChanged(index, index);
        }
        else if (item->isGroup() && !name.isEmpty()) {
            QString oldName = item->name();
            QList<PsiContact*> contacts;
            for (int i = 0; i < item->childCount(); ++i) {
                if (item->child(i)->isContact())
                contacts << item->child(i)->contact();
            }

            for (PsiContact *contact: contacts) {
                QStringList groups = contact->groups();
                groups.removeOne(oldName);
                groups << name;
                contact->setGroups(groups);
            }

        }

        return true;
    }
    else if (role == ExpandedRole) {
        if (!item->isContact()) {
            item->setExpanded(data.toBool());
        }
    }

    return true;
}
Example #3
0
/**
 * TODO
 */
bool PsiContactListModel::setData(const QModelIndex& index, const QVariant& data, int role)
{
	if (role == ActivateRole) {
		if (!index.isValid())
			return false;

		ContactListItem* item = static_cast<ContactListItem*>(index.internalPointer());
		PsiContact* contact = dynamic_cast<PsiContact*>(item);
		if (!contact)
			return false;

		contact->activate();
		return true;
	}
	else if (role == Qt::EditRole) {
		ContactListItem* item = static_cast<ContactListItem*>(index.internalPointer());
		PsiContactGroup* group   = 0;
		PsiContact*      contact = 0;
		QString name = data.toString();
		if ((contact = dynamic_cast<PsiContact*>(item))) {
			if (name.isEmpty()) {
				QMessageBox::information(0, tr("Error"), tr("You can't set a blank name."));
				return false;
			}
			else {
				contact->setName(name);
			}
		}
		else if ((group = dynamic_cast<PsiContactGroup*>(item))) {
			if (name.isEmpty()) {
				QMessageBox::information(0, tr("Error"), tr("You can't set a blank group name."));
				return false;
			}
			else {
				// make sure we don't have it already
				if (group->account()->groupList().contains(name)) {
					QMessageBox::information(0, tr("Error"), tr("You already have a group with that name."));
					return false;
				}

				group->setName(name);
			}
		}
		emit dataChanged(index, index);
		return true;
	}

	return ContactListModel::setData(index, data, role);
}
Example #4
0
void ContactListModel::Private::contactUpdated()
{
    PsiContact *contact = qobject_cast<PsiContact*>(sender());
    Q_ASSERT(monitoredContacts.contains(contact));
    if (!monitoredContacts.contains(contact))
        return;

    // Check for groups changing
    // Maybe very difficult and should be simplified?
    QList<ContactListItem*> groupItems;
    for (const QPersistentModelIndex &index: monitoredContacts.values(contact)) {
        ContactListItem *item = q->toItem(index);
        ContactListItem *parent = item->parent();
        if (parent && parent->isGroup()) {
            groupItems << parent;
        }
    }

    Operation operation = Operation::UpdateContact;
    ContactListItem::SpecialGroupType specialGroupType = specialGroupFor(contact);
    if (specialGroupType == ContactListItem::SpecialGroupType::NoneSpecialGroupType) {
        QStringList groups1;
        for (ContactListItem *item: groupItems) {
            groups1 << item->name();
        }
        groups1.sort();
        QStringList groups2 = contact->groups();
        groups2.sort();
        if (groups1 != groups2) {
            operation = Operation::ContactGroupsChanged;
        }
    }
    else if (groupItems.size() > 1 || (!groupItems.isEmpty() && groupItems.first()->specialGroupType() != specialGroupType)) {
        operation = Operation::ContactGroupsChanged;
    }

    addOperation(contact, operation);
}
bool YaPopupNotification::notify(int id, PsiEvent* event, int soundType)
{
	Q_ASSERT(event);

#ifndef YAPSI_ACTIVEX_SERVER
	// FIXME: should use PsiAccount::Private::noPopup()
	if (!event->account() || event->account()->status().type() != XMPP::Status::Online)
		return false;
#endif

	if (event->type() == PsiEvent::Message || event->type() == PsiEvent::Mood) {
		ChatDlg* chatDlg = event->account()->findChatDialog(event->from());
		if (!chatDlg)
			chatDlg = event->account()->findChatDialog(event->jid());

		if (chatDlg && chatDlg->isActiveTab())
			return false;
	}

	if (event->type() == PsiEvent::Message) {
#ifndef YAPSI_ACTIVEX_SERVER
		if (!PsiOptions::instance()->getOption("options.ya.popups.message.enable").toBool()) {
			return false;
		}
#endif
	}

	if (event->type() == PsiEvent::Mood) {
		MoodEvent* moodEvent = static_cast<MoodEvent*>(event);
		if (!event->account()->psi()->yaToasterCentral()->showToaster(YaToasterCentral::MoodChange, event->from(), moodEvent->mood())) {
			// qWarning("YaToasterCentral blocked mood change: %s %s", qPrintable(contact->jid().full()), qPrintable(mood));
			return false;
		}

		// qWarning("%s Changed mood to: %s", qPrintable(contact->jid().full()), qPrintable(mood));

#ifndef YAPSI_ACTIVEX_SERVER
		if (!PsiOptions::instance()->getOption("options.ya.popups.moods.enable").toBool()) {
			return false;
		}
#endif

#if defined(Q_WS_MAC) && defined(HAVE_GROWL)
		PsiContact* contact = event->account()->findContact(event->from());
		if (contact) {
			QString contactName = Ya::contactName(contact->name(), contact->jid().bare());
			PsiGrowlNotifier::instance()->moodChanged(event->account(), contact->jid(), contactName, moodEvent->mood());
		}
		return true;
#endif
	}

#ifdef YAPSI_ACTIVEX_SERVER
	if (event->account()->psi()->yaOnline()) {
		event->account()->psi()->yaOnline()->notify(id, event, soundType);
		return true;
	}
#endif

#if defined(Q_WS_MAC) && defined(HAVE_GROWL)
	// nasty-nasty YaToster steals focus on Mac OS X
	return true;
#endif

	YaPopupNotification* notification = new YaPopupNotification(id, event);
	int height = notification->sizeHint().height();
	notification->setMinimumSize(QSize(16, height));
	YaToster* toster = new YaToster(notification);
	toster->setStayForever(Ya::isSubscriptionRequest(event));
	toster->setTimes(1000, 5000, 500);
	toster->setSize(QSize(280, height));
	toster->start();
	return true;
}
Example #6
0
bool ContactListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
	QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
	if (!index.isValid())
		return false;

	ContactListItemProxy* itemProxy = static_cast<ContactListItemProxy*>(index.internalPointer());
	ContactListItem* item = itemProxy ? itemProxy->item() : 0;
	if (!item) {
		Q_ASSERT(false);
		return false;
	}

	if (item->editing()) {
		return true;
	}

	switch (ContactListModel::indexType(index)) {
	case ContactListModel::ContactType: {
		PsiContact* psiContact = dynamic_cast<PsiContact*>(item);

		if (psiContact->isHidden()) {
			return false;
		}

		if (psiContact->isSelf()) {
			return showSelf();
		}
		else if (psiContact->isAgent()) {
			return showTransports();
		}

		if (!showOffline()) {
			return psiContact->isOnline();
		}
		else {
			return true;
		}
	}
	case ContactListModel::GroupType:
		{
			ContactListGroup::SpecialType specialGroupType = static_cast<ContactListGroup::SpecialType>(index.data(ContactListModel::SpecialGroupTypeRole).toInt());
			if (specialGroupType != ContactListGroup::SpecialType_None) {
				if (specialGroupType == ContactListGroup::SpecialType_Transports)
					return showTransports();
			}

			if (!showOffline()) {
				ContactListGroup* group = dynamic_cast<ContactListGroup*>(item);
				return group->haveOnlineContacts();
			}
			else {
				return true;
			}
		}
	case ContactListModel::AccountType:
		return true;
	case ContactListModel::InvalidType:
		return true;
	default:
		Q_ASSERT(false);
	}

	return true;
}
void ContactListUtil::removeContact(PsiContact* contact, QMimeData* _selection, ContactListDragModel* model, QWidget* widget, QObject* obj)
{
	Q_ASSERT(model);
	QModelIndexList indexes = model ? model->indexesFor(contact, _selection) : QModelIndexList();
	if (model && !indexes.isEmpty()) {
		QMimeData* selection = model->mimeData(indexes);
		QString selectionData = confirmationData(contact, _selection, model);

		// WARNING: selection could also contain groups. and when there are groups,
		// all groups' contacts are marked for deletion too
		QList<PsiContact*> contactsLost = model->contactsLostByRemove(selection);
		bool removeConfirmed = contactsLost.isEmpty();
		bool confirmWithoutPrompt = false;

		if (!removeConfirmed) {
			QStringList contactNames = contactNamesFor(contactsLost);

			QString destructiveActionName;
			QString msg;
			bool doPrompt = true;

			// don't prompt when removing single muc or not-in-list contacts
			if(contactsLost.count() == 1 && (contactsLost[0]->isPrivate() || !contactsLost[0]->inList())) {
				doPrompt = false;
			}

			if (!contactNames.isEmpty()) {
				msg = tr("This will permanently remove<br>"
						 "%1"
						 "<br>from your contact list."
                         ).arg(contactNames.join(", ").replace("\\40","@"));
			}

#ifdef YAPSI
			QString complimentaryActionName;
			const char* complimentaryActionSlot = 0;

			ContactListModelSelection contactListSelection(selection);
			if (contactNames.count() > 1 || contactListSelection.groups().count()) {
				QStringList tmp;
				QStringList tmpContactNames = contactNames;
				while (!tmpContactNames.isEmpty()) {
					if (tmp.count() >= 10)
						break;

					tmp << QString("%1. %2").arg(tmp.count() + 1).arg(tmpContactNames.takeFirst());
				}

				QString andNContacts;
				if (!tmpContactNames.isEmpty()) {
					andNContacts = tr("and %n contacts ", 0,
									  tmpContactNames.count());
				}

				if (contactListSelection.groups().count() > 1) {
					msg = tr("This will permanently remove:<br>"
							 "%1"
							 "<br>%2and %n groups from your contact list.",
							 0,
							 contactListSelection.groups().count()
							).arg(tmp.join("<br>"))
							 .arg(andNContacts);
				}
				else if (contactListSelection.groups().count() == 1) {
					msg = tr("This will permanently remove:<br>"
							 "%1"
							 "<br>%2and \"%3\" group from your contact list."
							).arg(tmp.join("<br>"))
							 .arg(andNContacts)
							 .arg(contactListSelection.groups().first().fullName);
				}
				else {
					msg = tr("This will permanently remove:<br>"
							 "%1"
							 "<br>%2from your contact list."
							).arg(tmp.join("<br>"))
							 .arg(andNContacts);
				}
			}

			if (indexes.count() == 1 && model->indexType(indexes.first()) == ContactListModel::GroupType) {
				if (YaContactListContactsModel::virtualUnremovableGroups().contains(contactListSelection.groups().first().fullName)) {
					msg = tr("This is a system group and can't be removed. "
							 "Permanently remove all its contacts from your contact list?");
					destructiveActionName = tr("Clear Group");
				}
				else {
					msg = tr("This will permanently remove<br>"
							 "%1"
							 "<br>group and all its contacts from your contact list.").arg(TextUtil::escape(indexes.first().data().toString()));
				}
			}
			else if (indexes.count() == 1 && model->indexType(indexes.first()) == ContactListModel::ContactType) {
				Q_ASSERT(contactListSelection.contacts().count() == 1);
				ContactListModelSelection::Contact c = contactListSelection.contacts().first();

				PsiAccount* account = contactList()->getAccount(c.account);
				PsiContact* psiContact = account ? account->findContact(c.jid) : 0;
				QStringList contactGroupsLostByRemove;
				if (psiContact) {
					contactGroupsLostByRemove = model->contactGroupsLostByRemove(psiContact, selection);
				}

				if (psiContact && !psiContact->inList() && psiContact->blockAvailable()) {
					msg = tr("This will permanently remove %1 from your contact list. "
							 "You could block it in order to avoid further messages.")
                            .arg(contactNames.join(", ").replace("\\40","@"));
					destructiveActionName = tr("Delete");
					complimentaryActionName = tr("Block");
					complimentaryActionSlot = "blockContactConfirmation";
				}
				else if (psiContact && psiContact->groups().count() > 1 && contactGroupsLostByRemove.count() == 1) {
					// TODO: needs to be translated
					msg = tr("This will remove %1 from \"%2\" group. "
							 "You could also remove it from all groups.")
						  .arg(contactNames.join(", "))
						  .arg(contactGroupsLostByRemove.first());
					destructiveActionName = tr("Delete");
					complimentaryActionName = tr("Delete From All Groups");
					// TODO: needs to be implemented
					complimentaryActionSlot = "removeContactFullyConfirmation";
				}
			}
#endif

			if (!msg.isEmpty()) {
				if (doPrompt) {
#ifdef YAPSI
					if (complimentaryActionSlot) {
						RemoveConfirmationMessageBoxManager::instance()->
							removeConfirmation(selectionData,
											   obj, "removeContactConfirmation",
											   obj, complimentaryActionSlot,
											   tr("Deleting contacts"),
											   msg,
											   widget,
											   destructiveActionName,
											   complimentaryActionName);
					}
#else
					if (false) {
					}
#endif
					else {
						RemoveConfirmationMessageBoxManager::instance()->
							removeConfirmation(selectionData,
											   obj, "removeContactConfirmation",
											   tr("Deleting contacts"),
											   msg,
											   widget,
											   destructiveActionName);
					}

					removeConfirmed = false;
				}
				else {
					confirmWithoutPrompt = true;
				}
			}
		}

		QMetaObject::invokeMethod(obj, "removeContactConfirmation", Qt::DirectConnection,
								  QGenericReturnArgument(),
								  Q_ARG(QString, selectionData), Q_ARG(bool, removeConfirmed));

		if(confirmWithoutPrompt) {
			QMetaObject::invokeMethod(obj, "removeContactConfirmation", Qt::QueuedConnection,
								  QGenericReturnArgument(),
								  Q_ARG(QString, selectionData), Q_ARG(bool, true));
		}

		delete selection;
	}