<commit_before>/*  This file is part of the KDE project
    Copyright (C) 2005 Michal Vaner <michal.vaner@kdemail.net>
    Copyright (C) 2008-2009 Pali Rohár <pali.rohar@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/
#include "skypeprotocol.h"
#include "skypeeditaccount.h"
#include "skypeaccount.h"
#include "skypeaddcontact.h"
#include "skypecontact.h"

#include <kopeteonlinestatusmanager.h>
#include <kgenericfactory.h>
#include <qstring.h>
#include <qstringlist.h>
#include <kdebug.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kshortcut.h>
#include <kopetecontactlist.h>
#include <kopetemetacontact.h>

K_PLUGIN_FACTORY( SkypeProtocolFactory, registerPlugin<SkypeProtocol>(); )
K_EXPORT_PLUGIN( SkypeProtocolFactory( "kopete_skype" ) )

SkypeProtocol *SkypeProtocol::s_protocol = 0L;

class SkypeProtocolPrivate {
	private:
	public:
		///The "call contact" action
		KAction *callContactAction;
		///Pointer to the account
		SkypeAccount *account;
		///Constructor
		SkypeProtocolPrivate() {
			account = 0L;//no account yet
			callContactAction = 0L;
		}
};

SkypeProtocol::SkypeProtocol(QObject *parent, const QList<QVariant>&) :
	Kopete::Protocol(SkypeProtocolFactory::componentData(), parent),//create the parent
	Offline(Kopete::OnlineStatus::Offline, 0, this, 1, QStringList("skype_contact_offline"), i18n("Offline"), i18n("Offline"), Kopete::OnlineStatusManager::Offline),//and online statuses
	Online(Kopete::OnlineStatus::Online, 1, this, 2, QStringList("skype_contact_online"), i18n("Online"), i18n("Online"), Kopete::OnlineStatusManager::Online),
	SkypeMe(Kopete::OnlineStatus::Online, 0, this, 3, QStringList("skype_contact_skypeme"), i18n("Skype Me"), i18n("Skype Me"), Kopete::OnlineStatusManager::FreeForChat),
	Away(Kopete::OnlineStatus::Away, 2, this, 4, QStringList("skype_contact_away"), i18n("Away"), i18n("Away"), Kopete::OnlineStatusManager::Away),
	NotAvailable(Kopete::OnlineStatus::Away, 1, this, 5, QStringList("skype_contact_not_available"), i18n("Not Available"), i18n("Not Available"), Kopete::OnlineStatusManager::Away),
	DoNotDisturb(Kopete::OnlineStatus::Away, 0, this, 6, QStringList("skype_contact_dnd"), i18n("Do Not Disturb"), i18n("Do Not Disturb"), Kopete::OnlineStatusManager::Busy),
	Invisible(Kopete::OnlineStatus::Invisible, 0, this, 7, QStringList("skype_contact_invisible"), i18n("Invisible"), i18n("Invisible"), Kopete::OnlineStatusManager::Invisible),
	Connecting(Kopete::OnlineStatus::Connecting, 0, this, 8, QStringList("skype_connecting"), i18n("Connecting")),
	NotInList(Kopete::OnlineStatus::Offline, 0, this, 9, QStringList("skype_contact_unknown"), i18n("Not in Skype list")),
	NoAuth(Kopete::OnlineStatus::Offline, 0, this, 10, QStringList("skype_contact_unknown"), i18n("Not authorized")),
	Phone(Kopete::OnlineStatus::Online, 0, this, 11, QStringList("skype_contact_skypeout"), i18n("SkypeOut contact")),
	/** Contact property templates */
	propFullName(Kopete::Global::Properties::self()->fullName()),
	propPrivatePhone(Kopete::Global::Properties::self()->privatePhone()),
	propPrivateMobilePhone(Kopete::Global::Properties::self()->privateMobilePhone()),
	propWorkPhone(Kopete::Global::Properties::self()->workPhone()),
	propLastSeen(Kopete::Global::Properties::self()->lastSeen())

{
	kDebug(SKYPE_DEBUG_GLOBAL);
	//create the d pointer
	d = new SkypeProtocolPrivate();
	//add address book field
	addAddressBookField("messaging/skype", Kopete::Plugin::MakeIndexField);

	setXMLFile("skypeui.rc");

	d->callContactAction = new KAction( this );
	d->callContactAction->setIcon( (KIcon("skype_call") ) );
	d->callContactAction->setText( i18n ("Call") );
	connect(d->callContactAction, SIGNAL(triggered(bool)), SLOT(callContacts()));

	actionCollection()->addAction("callSkypeContact", d->callContactAction);

	updateCallActionStatus();
	connect(Kopete::ContactList::self(), SIGNAL(metaContactSelected(bool)), this, SLOT(updateCallActionStatus()));

	s_protocol = this;
}

SkypeProtocol::~SkypeProtocol() {
	kDebug(SKYPE_DEBUG_GLOBAL);
	//release the memory
	delete d;
}

Kopete::Account *SkypeProtocol::createNewAccount(const QString & accountID) {
	kDebug(SKYPE_DEBUG_GLOBAL);
	//just create one
	return new SkypeAccount(this, accountID);
}

AddContactPage *SkypeProtocol::createAddContactWidget(QWidget *parent, Kopete::Account *account) {
	kDebug(SKYPE_DEBUG_GLOBAL);
	return new SkypeAddContact(this, parent, (SkypeAccount *)account, 0L);
}

KopeteEditAccountWidget *SkypeProtocol::createEditAccountWidget(Kopete::Account *account, QWidget *parent) {
	kDebug(SKYPE_DEBUG_GLOBAL);
	return new skypeEditAccount(this, account, parent);//create the widget and return it
}

void SkypeProtocol::registerAccount(SkypeAccount *account) {
	kDebug(SKYPE_DEBUG_GLOBAL);

	d->account = account;
}

void SkypeProtocol::unregisterAccount() {
	kDebug(SKYPE_DEBUG_GLOBAL);

	d->account = 0L;//forget everything about the account
}

bool SkypeProtocol::hasAccount() const {
	kDebug(SKYPE_DEBUG_GLOBAL);

	return (d->account);
}

Kopete::Contact *SkypeProtocol::deserializeContact(Kopete::MetaContact *metaContact, const QMap<QString, QString> &serializedData, const QMap<QString, QString> &) {
	kDebug(SKYPE_DEBUG_GLOBAL) << "Name: " << serializedData["contactId"].toLower();

	QString contactID = serializedData["contactId"].toLower();//get the contact ID
	QString accountId = serializedData["accountId"];

	if (!d->account) {
		kDebug(SKYPE_DEBUG_GLOBAL) << "Account does not exists, skiping contact creation";//write error for debugging
		return 0L;//create nothing
	}

	if (d->account->contact(contactID)) {
		kDebug(SKYPE_DEBUG_GLOBAL) << "Contact" << contactID << "exists in contact list, skipping contact creation";
		return 0L;
	}

	return new SkypeContact(d->account, contactID, metaContact);//create the contact
}

void SkypeProtocol::updateCallActionStatus() {
	kDebug(SKYPE_DEBUG_GLOBAL);

	bool enab = false;

	if ((Kopete::ContactList::self()->selectedMetaContacts().count() != 1) && ((!d->account) || (!d->account->ableMultiCall()))) {
		d->callContactAction->setEnabled(false);
		return;
	}

	//Run trough all selected contacts and find if there is any skype contact
	const QList<Kopete::MetaContact*> &selected = Kopete::ContactList::self()->selectedMetaContacts();
	for (QList<Kopete::MetaContact*>::const_iterator met = selected.begin(); met != selected.end(); ++met) {
		const QList<Kopete::Contact*> &metaCont = (*met)->contacts();
		for (QList<Kopete::Contact*>::const_iterator con = metaCont.begin(); con != metaCont.end(); ++con) {
			if ((*con)->protocol() == this) {//This is skype contact, ask it if it can be called
				SkypeContact *thisCont = static_cast<SkypeContact *> (*con);
				if (thisCont->canCall()) {
					enab = true;
					goto OUTSIDE;
				}
			}
		}
	}
	OUTSIDE:
	d->callContactAction->setEnabled(enab);
}

void SkypeProtocol::callContacts() {
	kDebug(SKYPE_DEBUG_GLOBAL);

	QString list;

	const QList<Kopete::MetaContact*> &selected = Kopete::ContactList::self()->selectedMetaContacts();
	for (QList<Kopete::MetaContact*>::const_iterator met = selected.begin(); met != selected.end(); ++met) {
		const QList<Kopete::Contact*> &metaCont = (*met)->contacts();
		for (QList<Kopete::Contact*>::const_iterator con = metaCont.begin(); con != metaCont.end(); ++con) {
			if ((*con)->protocol() == this) {//This is skype contact, ask it if it can be called
				SkypeContact *thisCont = static_cast<SkypeContact *> (*con);
				if (thisCont->canCall()) {
					if (!list.isEmpty())
						list += ", ";
					list += thisCont->contactId();
				}
			}
		}
	}

	if (!list.isEmpty()) {
		d->account->makeCall(list);
	}
}

SkypeProtocol *SkypeProtocol::protocol()
{
	return s_protocol;
}

#include "skypeprotocol.moc"
<commit_msg>Make all SkypeOut contacts still offline<commit_after>/*  This file is part of the KDE project
    Copyright (C) 2005 Michal Vaner <michal.vaner@kdemail.net>
    Copyright (C) 2008-2009 Pali Rohár <pali.rohar@gmail.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License version 2 as published by the Free Software Foundation.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/
#include "skypeprotocol.h"
#include "skypeeditaccount.h"
#include "skypeaccount.h"
#include "skypeaddcontact.h"
#include "skypecontact.h"

#include <kopeteonlinestatusmanager.h>
#include <kgenericfactory.h>
#include <qstring.h>
#include <qstringlist.h>
#include <kdebug.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kshortcut.h>
#include <kopetecontactlist.h>
#include <kopetemetacontact.h>

K_PLUGIN_FACTORY( SkypeProtocolFactory, registerPlugin<SkypeProtocol>(); )
K_EXPORT_PLUGIN( SkypeProtocolFactory( "kopete_skype" ) )

SkypeProtocol *SkypeProtocol::s_protocol = 0L;

class SkypeProtocolPrivate {
	private:
	public:
		///The "call contact" action
		KAction *callContactAction;
		///Pointer to the account
		SkypeAccount *account;
		///Constructor
		SkypeProtocolPrivate() {
			account = 0L;//no account yet
			callContactAction = 0L;
		}
};

SkypeProtocol::SkypeProtocol(QObject *parent, const QList<QVariant>&) :
	Kopete::Protocol(SkypeProtocolFactory::componentData(), parent),//create the parent
	Offline(Kopete::OnlineStatus::Offline, 0, this, 1, QStringList("skype_contact_offline"), i18n("Offline"), i18n("Offline"), Kopete::OnlineStatusManager::Offline),//and online statuses
	Online(Kopete::OnlineStatus::Online, 1, this, 2, QStringList("skype_contact_online"), i18n("Online"), i18n("Online"), Kopete::OnlineStatusManager::Online),
	SkypeMe(Kopete::OnlineStatus::Online, 0, this, 3, QStringList("skype_contact_skypeme"), i18n("Skype Me"), i18n("Skype Me"), Kopete::OnlineStatusManager::FreeForChat),
	Away(Kopete::OnlineStatus::Away, 2, this, 4, QStringList("skype_contact_away"), i18n("Away"), i18n("Away"), Kopete::OnlineStatusManager::Away),
	NotAvailable(Kopete::OnlineStatus::Away, 1, this, 5, QStringList("skype_contact_not_available"), i18n("Not Available"), i18n("Not Available"), Kopete::OnlineStatusManager::Away),
	DoNotDisturb(Kopete::OnlineStatus::Away, 0, this, 6, QStringList("skype_contact_dnd"), i18n("Do Not Disturb"), i18n("Do Not Disturb"), Kopete::OnlineStatusManager::Busy),
	Invisible(Kopete::OnlineStatus::Invisible, 0, this, 7, QStringList("skype_contact_invisible"), i18n("Invisible"), i18n("Invisible"), Kopete::OnlineStatusManager::Invisible),
	Connecting(Kopete::OnlineStatus::Connecting, 0, this, 8, QStringList("skype_connecting"), i18n("Connecting")),
	NotInList(Kopete::OnlineStatus::Offline, 0, this, 9, QStringList("skype_contact_unknown"), i18n("Not in Skype list")),
	NoAuth(Kopete::OnlineStatus::Offline, 0, this, 10, QStringList("skype_contact_unknown"), i18n("Not authorized")),
	Phone(Kopete::OnlineStatus::Offline, 0, this, 11, QStringList("skype_contact_skypeout"), i18n("SkypeOut contact")), //Skype Out contact permanently offline TODO: add option for changing
	/** Contact property templates */
	propFullName(Kopete::Global::Properties::self()->fullName()),
	propPrivatePhone(Kopete::Global::Properties::self()->privatePhone()),
	propPrivateMobilePhone(Kopete::Global::Properties::self()->privateMobilePhone()),
	propWorkPhone(Kopete::Global::Properties::self()->workPhone()),
	propLastSeen(Kopete::Global::Properties::self()->lastSeen())

{
	kDebug(SKYPE_DEBUG_GLOBAL);
	//create the d pointer
	d = new SkypeProtocolPrivate();
	//add address book field
	addAddressBookField("messaging/skype", Kopete::Plugin::MakeIndexField);

	setXMLFile("skypeui.rc");

	d->callContactAction = new KAction( this );
	d->callContactAction->setIcon( (KIcon("skype_call") ) );
	d->callContactAction->setText( i18n ("Call") );
	connect(d->callContactAction, SIGNAL(triggered(bool)), SLOT(callContacts()));

	actionCollection()->addAction("callSkypeContact", d->callContactAction);

	updateCallActionStatus();
	connect(Kopete::ContactList::self(), SIGNAL(metaContactSelected(bool)), this, SLOT(updateCallActionStatus()));

	s_protocol = this;
}

SkypeProtocol::~SkypeProtocol() {
	kDebug(SKYPE_DEBUG_GLOBAL);
	//release the memory
	delete d;
}

Kopete::Account *SkypeProtocol::createNewAccount(const QString & accountID) {
	kDebug(SKYPE_DEBUG_GLOBAL);
	//just create one
	return new SkypeAccount(this, accountID);
}

AddContactPage *SkypeProtocol::createAddContactWidget(QWidget *parent, Kopete::Account *account) {
	kDebug(SKYPE_DEBUG_GLOBAL);
	return new SkypeAddContact(this, parent, (SkypeAccount *)account, 0L);
}

KopeteEditAccountWidget *SkypeProtocol::createEditAccountWidget(Kopete::Account *account, QWidget *parent) {
	kDebug(SKYPE_DEBUG_GLOBAL);
	return new skypeEditAccount(this, account, parent);//create the widget and return it
}

void SkypeProtocol::registerAccount(SkypeAccount *account) {
	kDebug(SKYPE_DEBUG_GLOBAL);

	d->account = account;
}

void SkypeProtocol::unregisterAccount() {
	kDebug(SKYPE_DEBUG_GLOBAL);

	d->account = 0L;//forget everything about the account
}

bool SkypeProtocol::hasAccount() const {
	kDebug(SKYPE_DEBUG_GLOBAL);

	return (d->account);
}

Kopete::Contact *SkypeProtocol::deserializeContact(Kopete::MetaContact *metaContact, const QMap<QString, QString> &serializedData, const QMap<QString, QString> &) {
	kDebug(SKYPE_DEBUG_GLOBAL) << "Name: " << serializedData["contactId"].toLower();

	QString contactID = serializedData["contactId"].toLower();//get the contact ID
	QString accountId = serializedData["accountId"];

	if (!d->account) {
		kDebug(SKYPE_DEBUG_GLOBAL) << "Account does not exists, skiping contact creation";//write error for debugging
		return 0L;//create nothing
	}

	if (d->account->contact(contactID)) {
		kDebug(SKYPE_DEBUG_GLOBAL) << "Contact" << contactID << "exists in contact list, skipping contact creation";
		return 0L;
	}

	return new SkypeContact(d->account, contactID, metaContact);//create the contact
}

void SkypeProtocol::updateCallActionStatus() {
	kDebug(SKYPE_DEBUG_GLOBAL);

	bool enab = false;

	if ((Kopete::ContactList::self()->selectedMetaContacts().count() != 1) && ((!d->account) || (!d->account->ableMultiCall()))) {
		d->callContactAction->setEnabled(false);
		return;
	}

	//Run trough all selected contacts and find if there is any skype contact
	const QList<Kopete::MetaContact*> &selected = Kopete::ContactList::self()->selectedMetaContacts();
	for (QList<Kopete::MetaContact*>::const_iterator met = selected.begin(); met != selected.end(); ++met) {
		const QList<Kopete::Contact*> &metaCont = (*met)->contacts();
		for (QList<Kopete::Contact*>::const_iterator con = metaCont.begin(); con != metaCont.end(); ++con) {
			if ((*con)->protocol() == this) {//This is skype contact, ask it if it can be called
				SkypeContact *thisCont = static_cast<SkypeContact *> (*con);
				if (thisCont->canCall()) {
					enab = true;
					goto OUTSIDE;
				}
			}
		}
	}
	OUTSIDE:
	d->callContactAction->setEnabled(enab);
}

void SkypeProtocol::callContacts() {
	kDebug(SKYPE_DEBUG_GLOBAL);

	QString list;

	const QList<Kopete::MetaContact*> &selected = Kopete::ContactList::self()->selectedMetaContacts();
	for (QList<Kopete::MetaContact*>::const_iterator met = selected.begin(); met != selected.end(); ++met) {
		const QList<Kopete::Contact*> &metaCont = (*met)->contacts();
		for (QList<Kopete::Contact*>::const_iterator con = metaCont.begin(); con != metaCont.end(); ++con) {
			if ((*con)->protocol() == this) {//This is skype contact, ask it if it can be called
				SkypeContact *thisCont = static_cast<SkypeContact *> (*con);
				if (thisCont->canCall()) {
					if (!list.isEmpty())
						list += ", ";
					list += thisCont->contactId();
				}
			}
		}
	}

	if (!list.isEmpty()) {
		d->account->makeCall(list);
	}
}

SkypeProtocol *SkypeProtocol::protocol()
{
	return s_protocol;
}

#include "skypeprotocol.moc"
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qcontactmaemo5backend_p.h"

#include <QSharedData>

#include "qcontactmaemo5debug_p.h"

DEFINE_GLOBAL_DEBUG_VAR

QContactManagerEngine* ContactMaemo5Factory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error)
{
    Q_UNUSED(parameters);
    Q_UNUSED(error);

    initDebugLogger();
    return new QContactMaemo5Engine(); //FIXME Wonderfull memory leak :D
}

QString ContactMaemo5Factory::managerName() const
{
    return QString("maemo5");
}

Q_EXPORT_PLUGIN2(qtcontacts_maemo5, ContactMaemo5Factory);

/*!
  \class QContactMaemo5Engine
  \brief The QContactMaemo5Engine class provides an implementation of
  QContactManagerEngine whose functions always return an error.

  The Maemo5 engine.
 */

/*! Constructs a new invalid contacts backend. */
QContactMaemo5Engine::QContactMaemo5Engine() : d(new QContactMaemo5EngineData)
{
  QContactABook *abook = d->m_abook;
  connect(abook, SIGNAL(contactsAdded(const QList<QContactLocalId>&)), SIGNAL(contactsAdded(const QList<QContactLocalId>&)));
  connect(abook, SIGNAL(contactsChanged(const QList<QContactLocalId>&)), SIGNAL(contactsChanged(const QList<QContactLocalId>&)));
  connect(abook, SIGNAL(contactsRemoved(const QList<QContactLocalId>&)), SIGNAL(contactsRemoved(const QList<QContactLocalId>&)));
}

/*! \reimp */
QContactMaemo5Engine& QContactMaemo5Engine::operator=(const QContactMaemo5Engine& other)
{
    d = other.d;
    return *this;
}

/*! \reimp */
QString QContactMaemo5Engine::managerName() const
{
    return QString(QLatin1String("maemo5"));
}

/* Synthesise the display label of a contact */
QString QContactMaemo5Engine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error* error) const
{
  Q_UNUSED(error)
  QString label = QContactManagerEngine::synthesizedDisplayLabel(contact, error);

  if (label.isEmpty()) {
    QContactNickname n = contact.detail(QContactNickname::DefinitionName);
    label = n.nickname();
  }

  if (label.isEmpty())
    label = "No name";

  return label;
}

bool QContactMaemo5Engine::validateContact(const QContact& contact, QContactManager::Error* error) const
{
    return QContactManagerEngine::validateContact(contact, error);
}

bool QContactMaemo5Engine::validateDefinition(const QContactDetailDefinition& definition, QContactManager::Error* error) const
{
    QContactDetailDefinition existing = detailDefinition(definition.name(), QContactType::TypeContact, error);
    if (existing == definition) {
        *error = QContactManager::NoError;
        return true;
    }

    *error = QContactManager::NotSupportedError; // XXX TODO: mutable definitions?
    return false;
}

QContactLocalId QContactMaemo5Engine::selfContactId(QContactManager::Error* error) const
{
  Q_CHECK_PTR(d->m_abook);

  return d->m_abook->selfContactId(error);
}

QList<QContactLocalId> QContactMaemo5Engine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
{
  Q_CHECK_PTR(d->m_abook);

  //return QContactManagerEngine::contactIds(filter, sortOrders, error);
  return d->m_abook->contactIds(filter, sortOrders, error);
}

QList<QContact> QContactMaemo5Engine::contacts(const QContactFilter & filter, const QList<QContactSortOrder> & sortOrders, const QContactFetchHint & fetchHint,
			  QContactManager::Error* error ) const
{
  Q_UNUSED(fetchHint); // no optimisations currently, ignore the fetchhint.
  Q_CHECK_PTR(d->m_abook);
  QList<QContact> rtn;

  QList<QContactLocalId> ids = contactIds(filter, sortOrders,error);
  foreach (QContactLocalId id, ids)
    rtn << contact(id, QContactFetchHint(), error);
  return rtn;
}

QContact QContactMaemo5Engine::contact(const QContactLocalId& contactId, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
{
  Q_UNUSED(fetchHint); //TODO
  Q_CHECK_PTR(d->m_abook);

  QContact *contact = d->m_abook->getQContact(contactId, error);
  QContact rtn(*contact);
  delete contact;
  setContactDisplayLabel(&rtn, synthesizedDisplayLabel(rtn, error));
  return rtn;
}

bool QContactMaemo5Engine::saveContacts(QList<QContact>* contacts, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
{
    *error = QContactManager::NoError;
    QContactManager::Error tempError = QContactManager::NoError;
    QContact curr;
    for (int i = 0; i < contacts->size(); i++) {
        curr = contacts->at(i);
        if (!saveContact(&curr, &tempError)) {
            errorMap->insert(i, tempError);
            *error = tempError;
        } else {
            contacts->replace(i, curr);
        }
    }

    return (*error == QContactManager::NoError);
}

bool QContactMaemo5Engine::removeContacts(const QList<QContactLocalId>& ids, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
{
    *error = QContactManager::NoError;
    QContactManager::Error tempError = QContactManager::NoError;
    QContact curr;
    for (int i = 0; i < ids.size(); i++) {
        if (!removeContact(ids.at(i), &tempError)) {
            errorMap->insert(i, tempError);
            *error = tempError;
        }
    }

    return (*error == QContactManager::NoError);
}

bool QContactMaemo5Engine::saveContact(QContact* contact, QContactManager::Error* error)
{
  Q_CHECK_PTR(d->m_abook);

  if (!contact) {
    *error = QContactManager::BadArgumentError;
    return false;
  }

  // synthesize the display label for the contact
  setContactDisplayLabel(contact, synthesizedDisplayLabel(*contact, error));

  // ensure that the contact's details conform to their definitions
  if (!validateContact(*contact, error)) {
    QCM5_DEBUG << "Validate Contact failed";
    return false;
  }

  bool retn = d->m_abook->saveContact(contact, error);
  QContactId cId = contact->id();
  cId.setManagerUri(managerUri());
  contact->setId(cId);
  return retn;
}

#if 0
QList<QContactManager::Error> QContactMaemo5Engine::removeContacts(QList<QContactLocalId>* contactIds, QContactManager::Error* error)
{
  bool ok = true;

  if (contactIds->isEmpty())
    return false;

  QContactLocalId id;
  foreach(id, contactIds){
      if (!removeContact(id, error))
	ok = false;
  }

  return ok;
}
#endif

bool QContactMaemo5Engine::removeContact(const QContactLocalId& contactId, QContactManager::Error* error)
{
  Q_CHECK_PTR(d->m_abook);
  return d->m_abook->removeContact(contactId, error);
}

QMap<QString, QContactDetailDefinition> QContactMaemo5Engine::detailDefinitions(const QString& contactType, QContactManager::Error* error) const
{

    QMap<QString, QMap<QString, QContactDetailDefinition> > defns = QContactManagerEngine::schemaDefinitions();

    QMap<QString, QContactDetailFieldDefinition> fields;

    QContactDetailFieldDefinition gsfd; //Generic string field definition
    gsfd.setDataType(QVariant::String);

    // QContactAddress
    fields = defns[contactType][QContactAddress::DefinitionName].fields();
    //fields.remove(QContactAddress::FieldSubTypes);
    fields.insert("Estension", gsfd);
    fields.insert(QContactDetail::FieldDetailUri, gsfd);
    defns[contactType][QContactAddress::DefinitionName].setFields(fields);

    // QContactAnniversary
    defns[contactType].remove(QContactAnniversary::DefinitionName);

    // QContactAvatar
    // TODO setUnique(true);
    // QContactBirthday
    // QContactDisplayLabel

    // QContactEmailAddress
    fields = defns[contactType][QContactEmailAddress::DefinitionName].fields();
    fields.insert(QContactDetail::FieldDetailUri, gsfd);
    defns[contactType][QContactEmailAddress::DefinitionName].setFields(fields);

    // QContactFamily
    // QContactGender
    // QContactGeoLocation
    defns[contactType].remove(QContactGeoLocation::DefinitionName);

    // QContactGuid
    // QContactName
    fields = defns[contactType][QContactName::DefinitionName].fields();
    fields.remove(QContactName::FieldCustomLabel);
    fields.remove(QContactName::FieldPrefix);
    fields.remove(QContactName::FieldSuffix);
    defns[contactType][QContactName::DefinitionName].setFields(fields);

    // QContactNickname
    // QContactNote
    // QContactOnlineAccount
    fields = defns[contactType][QContactOnlineAccount::DefinitionName].fields();
    fields.remove(QContactOnlineAccount::FieldAccountUri);
    fields.remove(QContactOnlineAccount::FieldSubTypes);
    fields.insert("AccountPath", gsfd);
    defns[contactType][QContactOnlineAccount::DefinitionName].setFields(fields);

    // QContactOrganization
    fields = defns[contactType][QContactOrganization::DefinitionName].fields();
    fields.remove(QContactOrganization::FieldAssistantName);
    fields.remove(QContactOrganization::FieldDepartment);
    fields.remove(QContactOrganization::FieldLocation);
    fields.remove(QContactOrganization::FieldLogoUrl);
    fields.remove(QContactOrganization::FieldName);
    fields.remove(QContactOrganization::FieldRole);
    defns[contactType][QContactOrganization::DefinitionName].setFields(fields);

    // QContactPhoneNumber
    fields = defns[contactType][QContactPhoneNumber::DefinitionName].fields();
    fields.insert(QContactDetail::FieldDetailUri, gsfd);
    defns[contactType][QContactPhoneNumber::DefinitionName].setFields(fields);

    // QContactSyncTarget
    defns[contactType].remove(QContactSyncTarget::DefinitionName);

    // QContactTimestamp
    // QContactType
    // QContactUrl
    fields = defns[contactType][QContactUrl::DefinitionName].fields();
    fields.remove(QContactUrl::FieldSubType);
    defns[contactType][QContactUrl::DefinitionName].setFields(fields);

    //Still unmanaged: GlobalPresence, Presence, Ringtone, Tag

    QCM5_DEBUG << "Contact type" << contactType << "Keys" <<  defns.keys();

    *error = QContactManager::NoError;
    return defns[contactType];
}

QContactDetailDefinition QContactMaemo5Engine::detailDefinition(const QString& definitionName, const QString& contactType, QContactManager::Error* error) const
{
    return QContactManagerEngine::detailDefinition(definitionName, contactType, error);
}

bool QContactMaemo5Engine::hasFeature(QContactManager::ManagerFeature feature, const QString& contactType) const {
  Q_UNUSED(contactType);
  if (feature == QContactManager::Anonymous)
    return true;

  return false;
}

bool QContactMaemo5Engine::isFilterSupported(const QContactFilter& filter) const {
  switch (filter.type()) {
    case QContactFilter::InvalidFilter:
    case QContactFilter::DefaultFilter:
    case QContactFilter::LocalIdFilter:
    case QContactFilter::ContactDetailFilter:
    case QContactFilter::ActionFilter:
    case QContactFilter::IntersectionFilter:
    case QContactFilter::UnionFilter:
      return true;
    default:
      return false;
  }
}

QList<QVariant::Type> QContactMaemo5Engine::supportedDataTypes() const {
  QList<QVariant::Type> st;
  st.append(QVariant::String);
  st.append(QVariant::Int);
  st.append(QVariant::UInt);
  st.append(QVariant::Double);
  st.append(QVariant::Date);
  st.append(QVariant::DateTime);

  return st;
}
<commit_msg>Remove old QContactMaemo5Engine::removeContacts code (cherry picked from commit 93a9f0b8a86ec2a7c154bb48edabe18716e463e2)<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qcontactmaemo5backend_p.h"

#include <QSharedData>

#include "qcontactmaemo5debug_p.h"

DEFINE_GLOBAL_DEBUG_VAR

QContactManagerEngine* ContactMaemo5Factory::engine(const QMap<QString, QString>& parameters, QContactManager::Error* error)
{
    Q_UNUSED(parameters);
    Q_UNUSED(error);

    initDebugLogger();
    return new QContactMaemo5Engine(); //FIXME Wonderfull memory leak :D
}

QString ContactMaemo5Factory::managerName() const
{
    return QString("maemo5");
}

Q_EXPORT_PLUGIN2(qtcontacts_maemo5, ContactMaemo5Factory);

/*!
  \class QContactMaemo5Engine
  \brief The QContactMaemo5Engine class provides an implementation of
  QContactManagerEngine whose functions always return an error.

  The Maemo5 engine.
 */

/*! Constructs a new invalid contacts backend. */
QContactMaemo5Engine::QContactMaemo5Engine() : d(new QContactMaemo5EngineData)
{
  QContactABook *abook = d->m_abook;
  connect(abook, SIGNAL(contactsAdded(const QList<QContactLocalId>&)), SIGNAL(contactsAdded(const QList<QContactLocalId>&)));
  connect(abook, SIGNAL(contactsChanged(const QList<QContactLocalId>&)), SIGNAL(contactsChanged(const QList<QContactLocalId>&)));
  connect(abook, SIGNAL(contactsRemoved(const QList<QContactLocalId>&)), SIGNAL(contactsRemoved(const QList<QContactLocalId>&)));
}

/*! \reimp */
QContactMaemo5Engine& QContactMaemo5Engine::operator=(const QContactMaemo5Engine& other)
{
    d = other.d;
    return *this;
}

/*! \reimp */
QString QContactMaemo5Engine::managerName() const
{
    return QString(QLatin1String("maemo5"));
}

/* Synthesise the display label of a contact */
QString QContactMaemo5Engine::synthesizedDisplayLabel(const QContact& contact, QContactManager::Error* error) const
{
  Q_UNUSED(error)
  QString label = QContactManagerEngine::synthesizedDisplayLabel(contact, error);

  if (label.isEmpty()) {
    QContactNickname n = contact.detail(QContactNickname::DefinitionName);
    label = n.nickname();
  }

  if (label.isEmpty())
    label = "No name";

  return label;
}

bool QContactMaemo5Engine::validateContact(const QContact& contact, QContactManager::Error* error) const
{
    return QContactManagerEngine::validateContact(contact, error);
}

bool QContactMaemo5Engine::validateDefinition(const QContactDetailDefinition& definition, QContactManager::Error* error) const
{
    QContactDetailDefinition existing = detailDefinition(definition.name(), QContactType::TypeContact, error);
    if (existing == definition) {
        *error = QContactManager::NoError;
        return true;
    }

    *error = QContactManager::NotSupportedError; // XXX TODO: mutable definitions?
    return false;
}

QContactLocalId QContactMaemo5Engine::selfContactId(QContactManager::Error* error) const
{
  Q_CHECK_PTR(d->m_abook);

  return d->m_abook->selfContactId(error);
}

QList<QContactLocalId> QContactMaemo5Engine::contactIds(const QContactFilter& filter, const QList<QContactSortOrder>& sortOrders, QContactManager::Error* error) const
{
  Q_CHECK_PTR(d->m_abook);

  //return QContactManagerEngine::contactIds(filter, sortOrders, error);
  return d->m_abook->contactIds(filter, sortOrders, error);
}

QList<QContact> QContactMaemo5Engine::contacts(const QContactFilter & filter, const QList<QContactSortOrder> & sortOrders, const QContactFetchHint & fetchHint,
			  QContactManager::Error* error ) const
{
  Q_UNUSED(fetchHint); // no optimisations currently, ignore the fetchhint.
  Q_CHECK_PTR(d->m_abook);
  QList<QContact> rtn;

  QList<QContactLocalId> ids = contactIds(filter, sortOrders,error);
  foreach (QContactLocalId id, ids)
    rtn << contact(id, QContactFetchHint(), error);
  return rtn;
}

QContact QContactMaemo5Engine::contact(const QContactLocalId& contactId, const QContactFetchHint& fetchHint, QContactManager::Error* error) const
{
  Q_UNUSED(fetchHint); //TODO
  Q_CHECK_PTR(d->m_abook);

  QContact *contact = d->m_abook->getQContact(contactId, error);
  QContact rtn(*contact);
  delete contact;
  setContactDisplayLabel(&rtn, synthesizedDisplayLabel(rtn, error));
  return rtn;
}

bool QContactMaemo5Engine::saveContacts(QList<QContact>* contacts, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
{
    *error = QContactManager::NoError;
    QContactManager::Error tempError = QContactManager::NoError;
    QContact curr;
    for (int i = 0; i < contacts->size(); i++) {
        curr = contacts->at(i);
        if (!saveContact(&curr, &tempError)) {
            errorMap->insert(i, tempError);
            *error = tempError;
        } else {
            contacts->replace(i, curr);
        }
    }

    return (*error == QContactManager::NoError);
}

bool QContactMaemo5Engine::removeContacts(const QList<QContactLocalId>& ids, QMap<int, QContactManager::Error>* errorMap, QContactManager::Error* error)
{
    *error = QContactManager::NoError;
    QContactManager::Error tempError = QContactManager::NoError;
    QContact curr;
    for (int i = 0; i < ids.size(); i++) {
        if (!removeContact(ids.at(i), &tempError)) {
            errorMap->insert(i, tempError);
            *error = tempError;
        }
    }

    return (*error == QContactManager::NoError);
}

bool QContactMaemo5Engine::saveContact(QContact* contact, QContactManager::Error* error)
{
  Q_CHECK_PTR(d->m_abook);

  if (!contact) {
    *error = QContactManager::BadArgumentError;
    return false;
  }

  // synthesize the display label for the contact
  setContactDisplayLabel(contact, synthesizedDisplayLabel(*contact, error));

  // ensure that the contact's details conform to their definitions
  if (!validateContact(*contact, error)) {
    QCM5_DEBUG << "Validate Contact failed";
    return false;
  }

  bool retn = d->m_abook->saveContact(contact, error);
  QContactId cId = contact->id();
  cId.setManagerUri(managerUri());
  contact->setId(cId);
  return retn;
}

bool QContactMaemo5Engine::removeContact(const QContactLocalId& contactId, QContactManager::Error* error)
{
  Q_CHECK_PTR(d->m_abook);
  return d->m_abook->removeContact(contactId, error);
}

QMap<QString, QContactDetailDefinition> QContactMaemo5Engine::detailDefinitions(const QString& contactType, QContactManager::Error* error) const
{

    QMap<QString, QMap<QString, QContactDetailDefinition> > defns = QContactManagerEngine::schemaDefinitions();

    QMap<QString, QContactDetailFieldDefinition> fields;

    QContactDetailFieldDefinition gsfd; //Generic string field definition
    gsfd.setDataType(QVariant::String);

    // QContactAddress
    fields = defns[contactType][QContactAddress::DefinitionName].fields();
    //fields.remove(QContactAddress::FieldSubTypes);
    fields.insert("Estension", gsfd);
    fields.insert(QContactDetail::FieldDetailUri, gsfd);
    defns[contactType][QContactAddress::DefinitionName].setFields(fields);

    // QContactAnniversary
    defns[contactType].remove(QContactAnniversary::DefinitionName);

    // QContactAvatar
    // TODO setUnique(true);
    // QContactBirthday
    // QContactDisplayLabel

    // QContactEmailAddress
    fields = defns[contactType][QContactEmailAddress::DefinitionName].fields();
    fields.insert(QContactDetail::FieldDetailUri, gsfd);
    defns[contactType][QContactEmailAddress::DefinitionName].setFields(fields);

    // QContactFamily
    // QContactGender
    // QContactGeoLocation
    defns[contactType].remove(QContactGeoLocation::DefinitionName);

    // QContactGuid
    // QContactName
    fields = defns[contactType][QContactName::DefinitionName].fields();
    fields.remove(QContactName::FieldCustomLabel);
    fields.remove(QContactName::FieldPrefix);
    fields.remove(QContactName::FieldSuffix);
    defns[contactType][QContactName::DefinitionName].setFields(fields);

    // QContactNickname
    // QContactNote
    // QContactOnlineAccount
    fields = defns[contactType][QContactOnlineAccount::DefinitionName].fields();
    fields.remove(QContactOnlineAccount::FieldAccountUri);
    fields.remove(QContactOnlineAccount::FieldSubTypes);
    fields.insert("AccountPath", gsfd);
    defns[contactType][QContactOnlineAccount::DefinitionName].setFields(fields);

    // QContactOrganization
    fields = defns[contactType][QContactOrganization::DefinitionName].fields();
    fields.remove(QContactOrganization::FieldAssistantName);
    fields.remove(QContactOrganization::FieldDepartment);
    fields.remove(QContactOrganization::FieldLocation);
    fields.remove(QContactOrganization::FieldLogoUrl);
    fields.remove(QContactOrganization::FieldName);
    fields.remove(QContactOrganization::FieldRole);
    defns[contactType][QContactOrganization::DefinitionName].setFields(fields);

    // QContactPhoneNumber
    fields = defns[contactType][QContactPhoneNumber::DefinitionName].fields();
    fields.insert(QContactDetail::FieldDetailUri, gsfd);
    defns[contactType][QContactPhoneNumber::DefinitionName].setFields(fields);

    // QContactSyncTarget
    defns[contactType].remove(QContactSyncTarget::DefinitionName);

    // QContactTimestamp
    // QContactType
    // QContactUrl
    fields = defns[contactType][QContactUrl::DefinitionName].fields();
    fields.remove(QContactUrl::FieldSubType);
    defns[contactType][QContactUrl::DefinitionName].setFields(fields);

    //Still unmanaged: GlobalPresence, Presence, Ringtone, Tag

    QCM5_DEBUG << "Contact type" << contactType << "Keys" <<  defns.keys();

    *error = QContactManager::NoError;
    return defns[contactType];
}

QContactDetailDefinition QContactMaemo5Engine::detailDefinition(const QString& definitionName, const QString& contactType, QContactManager::Error* error) const
{
    return QContactManagerEngine::detailDefinition(definitionName, contactType, error);
}

bool QContactMaemo5Engine::hasFeature(QContactManager::ManagerFeature feature, const QString& contactType) const {
  Q_UNUSED(contactType);
  if (feature == QContactManager::Anonymous)
    return true;

  return false;
}

bool QContactMaemo5Engine::isFilterSupported(const QContactFilter& filter) const {
  switch (filter.type()) {
    case QContactFilter::InvalidFilter:
    case QContactFilter::DefaultFilter:
    case QContactFilter::LocalIdFilter:
    case QContactFilter::ContactDetailFilter:
    case QContactFilter::ActionFilter:
    case QContactFilter::IntersectionFilter:
    case QContactFilter::UnionFilter:
      return true;
    default:
      return false;
  }
}

QList<QVariant::Type> QContactMaemo5Engine::supportedDataTypes() const {
  QList<QVariant::Type> st;
  st.append(QVariant::String);
  st.append(QVariant::Int);
  st.append(QVariant::UInt);
  st.append(QVariant::Double);
  st.append(QVariant::Date);
  st.append(QVariant::DateTime);

  return st;
}
<|endoftext|>


<commit_before>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

//libAccounts
#include <Accounts/Provider>
#include <Accounts/Account>
#include <Accounts/ServiceType>
#include <Accounts/Manager>

//Meegotouch
#include <MLayout>
#include <MLinearLayoutPolicy>
#include <MContentItem>
#include <MLocale>
#include <MAction>
#include <MLabel>
#include <MGridLayoutPolicy>
#include <MSeparator>
#include <MImageWidget>
#include <MButton>

//Qt
#include <QDebug>

//Accounts-Ui
#include "account-setup-finished-page-priv.h"
#include "accountsmanagersingleton.h"
#include "last-page-actions.h"
#include "provider-plugin-process.h"
#include "account-setup-finished-widget.h"

namespace AccountsUI {

void AccountSetupFinishedPagePrivate::actionButtonClicked()
{
    QString serviceName = sender()->property("serviceName").toString();
    qDebug() << "Invoking service" << serviceName;
    LastPageActions::executeService(serviceName);
    ProviderPluginProcess::instance()->quit();
}

AccountSetupFinishedPage::AccountSetupFinishedPage(AbstractAccountSetupContext *context)
        : MApplicationPage(),
          d_ptr(new AccountSetupFinishedPagePrivate())
{
    Q_D(AccountSetupFinishedPage);
    d->q_ptr = this;
    d->account = context->account();
    d->serviceType = context->serviceType();
    setObjectName("wgAccountSetupFinishedPage");
    setStyleName("AccountsUiPage");
}

AccountSetupFinishedPage::~AccountSetupFinishedPage()
{
    delete d_ptr;
}

void AccountSetupFinishedPage::createContent()
{
    Q_D(AccountSetupFinishedPage);

    setComponentsDisplayMode(EscapeButton, MApplicationPageModel::Hide);

    MWidget *centralWidget = new MWidget();
    MLayout *layout = new MLayout(centralWidget);
    MLinearLayoutPolicy *layoutPolicy = new MLinearLayoutPolicy(layout, Qt::Vertical);
    layoutPolicy->setSpacing(0);

    QString providerName(d->account->providerName());
    // xml file that describes the ui elements for the provider
    Accounts::Provider *provider = AccountsManager::instance()->provider(providerName);
    if (provider) {
        QDomElement root = provider->domDocument().documentElement();
        QDomElement providerIcon = root.firstChildElement("icon");
        QString providerIconId = providerIcon.text();

        MContentItem *providerItem = new MContentItem(MContentItem::IconAndSingleTextLabel, this);
        providerItem->setStyleName("SetupFinishedProviderName");
        providerItem->setImageID(providerIconId);
        providerItem->setTitle(provider->displayName());
        layoutPolicy->addItem(providerItem);
    }

    MSeparator *separatorTop = new MSeparator(this);
    separatorTop->setOrientation(Qt::Horizontal);
    separatorTop->setStyleName("CommonItemDividerInverted");

    layoutPolicy->addItem(separatorTop);

    AccountSetupFinishedWidget *widget = new AccountSetupFinishedWidget(providerName, this);
    layoutPolicy->addItem(widget);

    //% "Add more account"
    MButton *addMoreAccountButton = new MButton(qtTrId("qtn_acc_add_more_accounts"));
    connect (addMoreAccountButton, SIGNAL(clicked()), ProviderPluginProcess::instance(), SLOT(quit()));
    MLayout *buttonsLayout = new MLayout();
    MLinearLayoutPolicy *portraitPolicy = new MLinearLayoutPolicy(buttonsLayout, Qt::Vertical);
    MLinearLayoutPolicy *landscapePolicy = new MLinearLayoutPolicy(buttonsLayout, Qt::Horizontal);

    portraitPolicy->addStretch();
    portraitPolicy->setSpacing(20);
    landscapePolicy->addStretch();
    landscapePolicy->setSpacing(20);

    const LastPageActions &lastPageActions =
        ProviderPluginProcess::instance()->lastPageActions();
    const LastPageActions::ServiceActionList actions =
        lastPageActions.serviceActions();
    foreach (LastPageActions::ServiceAction action, actions) {
        MButton *button = new MButton(qtTrId("qtn_comm_go_to_x").
                                      arg(action.title()));
        button->setProperty("serviceName", action.serviceName());
        connect(button, SIGNAL(clicked()), d, SLOT(actionButtonClicked()));

        landscapePolicy->addItem(button, Qt::AlignRight);
        portraitPolicy->addItem(button, Qt::AlignCenter);
    }

    portraitPolicy->addItem(addMoreAccountButton, Qt::AlignCenter);
    landscapePolicy->addItem(addMoreAccountButton, Qt::AlignCenter);

    portraitPolicy->addStretch();
    landscapePolicy->addStretch();

    buttonsLayout->setLandscapePolicy(landscapePolicy);
    buttonsLayout->setPortraitPolicy(portraitPolicy);
    layoutPolicy->addStretch();
    layoutPolicy->addItem(buttonsLayout);

    setCentralWidget(centralWidget);

}

void AccountSetupFinishedPage::goToApplication()
{
    /* this slot is deprecated */
}

}
<commit_msg>Fixing: 229894 - Logical string qtn_mail_other_mailbox displayed in Account Setup Complete view<commit_after>/*
 * This file is part of accounts-ui
 *
 * Copyright (C) 2009-2010 Nokia Corporation.
 *
 * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */

//libAccounts
#include <Accounts/Provider>
#include <Accounts/Account>
#include <Accounts/ServiceType>
#include <Accounts/Manager>

//Meegotouch
#include <MLayout>
#include <MLinearLayoutPolicy>
#include <MContentItem>
#include <MLocale>
#include <MAction>
#include <MLabel>
#include <MGridLayoutPolicy>
#include <MSeparator>
#include <MImageWidget>
#include <MButton>

//Qt
#include <QDebug>

//Accounts-Ui
#include "account-setup-finished-page-priv.h"
#include "accountsmanagersingleton.h"
#include "last-page-actions.h"
#include "provider-plugin-process.h"
#include "account-setup-finished-widget.h"

namespace AccountsUI {

void AccountSetupFinishedPagePrivate::actionButtonClicked()
{
    QString serviceName = sender()->property("serviceName").toString();
    qDebug() << "Invoking service" << serviceName;
    LastPageActions::executeService(serviceName);
    ProviderPluginProcess::instance()->quit();
}

AccountSetupFinishedPage::AccountSetupFinishedPage(AbstractAccountSetupContext *context)
        : MApplicationPage(),
          d_ptr(new AccountSetupFinishedPagePrivate())
{
    Q_D(AccountSetupFinishedPage);
    d->q_ptr = this;
    d->account = context->account();
    d->serviceType = context->serviceType();
    setObjectName("wgAccountSetupFinishedPage");
    setStyleName("AccountsUiPage");
}

AccountSetupFinishedPage::~AccountSetupFinishedPage()
{
    delete d_ptr;
}

void AccountSetupFinishedPage::createContent()
{
    Q_D(AccountSetupFinishedPage);

    setComponentsDisplayMode(EscapeButton, MApplicationPageModel::Hide);

    MWidget *centralWidget = new MWidget();
    MLayout *layout = new MLayout(centralWidget);
    MLinearLayoutPolicy *layoutPolicy = new MLinearLayoutPolicy(layout, Qt::Vertical);
    layoutPolicy->setSpacing(0);

    QString providerName(d->account->providerName());
    // xml file that describes the ui elements for the provider
    Accounts::Provider *provider = AccountsManager::instance()->provider(providerName);
    if (provider) {
        QDomElement root = provider->domDocument().documentElement();
        QDomElement providerIcon = root.firstChildElement("icon");
        QString catalog = provider->trCatalog();
        MLocale locale;
        if (!catalog.isEmpty() && !locale.isInstalledTrCatalog(catalog)) {
            locale.installTrCatalog(catalog);
            MLocale::setDefault(locale);
        }
        QString providerIconId = providerIcon.text();

        MContentItem *providerItem = new MContentItem(MContentItem::IconAndSingleTextLabel, this);
        providerItem->setStyleName("SetupFinishedProviderName");
        providerItem->setImageID(providerIconId);
        providerItem->setTitle(qtTrId(provider->displayName().toLatin1()));

        layoutPolicy->addItem(providerItem);
    }

    MSeparator *separatorTop = new MSeparator(this);
    separatorTop->setOrientation(Qt::Horizontal);
    separatorTop->setStyleName("CommonItemDividerInverted");

    layoutPolicy->addItem(separatorTop);

    AccountSetupFinishedWidget *widget = new AccountSetupFinishedWidget(providerName, this);
    layoutPolicy->addItem(widget);

    //% "Add more account"
    MButton *addMoreAccountButton = new MButton(qtTrId("qtn_acc_add_more_accounts"));
    connect (addMoreAccountButton, SIGNAL(clicked()), ProviderPluginProcess::instance(), SLOT(quit()));
    MLayout *buttonsLayout = new MLayout();
    MLinearLayoutPolicy *portraitPolicy = new MLinearLayoutPolicy(buttonsLayout, Qt::Vertical);
    MLinearLayoutPolicy *landscapePolicy = new MLinearLayoutPolicy(buttonsLayout, Qt::Horizontal);

    portraitPolicy->addStretch();
    portraitPolicy->setSpacing(20);
    landscapePolicy->addStretch();
    landscapePolicy->setSpacing(20);

    const LastPageActions &lastPageActions =
        ProviderPluginProcess::instance()->lastPageActions();
    const LastPageActions::ServiceActionList actions =
        lastPageActions.serviceActions();
    foreach (LastPageActions::ServiceAction action, actions) {
        MButton *button = new MButton(qtTrId("qtn_comm_go_to_x").
                                      arg(action.title()));
        button->setProperty("serviceName", action.serviceName());
        connect(button, SIGNAL(clicked()), d, SLOT(actionButtonClicked()));

        landscapePolicy->addItem(button, Qt::AlignRight);
        portraitPolicy->addItem(button, Qt::AlignCenter);
    }

    portraitPolicy->addItem(addMoreAccountButton, Qt::AlignCenter);
    landscapePolicy->addItem(addMoreAccountButton, Qt::AlignCenter);

    portraitPolicy->addStretch();
    landscapePolicy->addStretch();

    buttonsLayout->setLandscapePolicy(landscapePolicy);
    buttonsLayout->setPortraitPolicy(portraitPolicy);
    layoutPolicy->addStretch();
    layoutPolicy->addItem(buttonsLayout);

    setCentralWidget(centralWidget);

}

void AccountSetupFinishedPage::goToApplication()
{
    /* this slot is deprecated */
}

}
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
   A very superficial test to verify that basic STL is working
   This is useful when we mess with / replace STL implementations

**/

#include <os>
#include <cassert>

#define GSL_THROW_ON_CONTRACT_VIOLATION
#include <gsl.h>
#include <lest.hpp>

int clock_gettime(clockid_t clk_id, struct timespec *tp){
(void*)clk_id;
(void*)tp;
return 0;
};

#define MYINFO(X,...) INFO("Test GSL",X,##__VA_ARGS__)

static int divcount_ = 0;

const lest::test test_basic_gsl[] = {
  {

    SCENARIO ("Basic Expects / Ensures behave as expected") {

      GIVEN ("A simple division function, requiring positive integers") {

        class Math {
        public:
          static int div (int x, int y) {
            Expects( y > 0 );

            int prevcount_ = divcount_;

            auto result = x / y;
            divcount_++;

            Ensures(result == x / y);
            Ensures(divcount_ > 0);
            Ensures(divcount_ == prevcount_ + 1);

            return result;

          }
        };

        WHEN ("y is zero") {
          int y = 0;

          THEN ("Division by y throws") {
            EXPECT_THROWS( Math::div(100, y) );
          }

        }

        WHEN ("y is positive") {
          int y = 4;

          THEN ("Division by y doesn't throw") {
            EXPECT_NO_THROW( Math::div(100, y) );
          }

          AND_THEN("Division gives the correct result"){
            EXPECT( Math::div(100,y) == 100 / y );
          }
        }

        WHEN ("y is negative"){
          int y = -90;

          THEN ("Divsion by y throws") {}
          EXPECT_THROWS( Math::div(100, y) );

          AND_THEN("Division should have succeeded twice"){
            EXPECT(divcount_ == 2);
          }
        }
      }
    }
  },

  {
    SCENARIO("We can use span to replace pointer-and-size interfaces") {

      GIVEN ("A (member) function with a span parameter") {

        class Mem {
        public:
          static unsigned int count(gsl::span<char> chars){

            int i = 0;
            for ( auto c : chars ) {
              printf("%c ", c);
              i++;
            }

            printf("\n");
            return i;
          }

        };

        WHEN ("We pass a raw pointer") {
          char* name = (char*)"Bjarne Stroustrup";

          THEN("if we lie to the about our size, span can't save us from overflow / underflow") {
            EXPECT( Mem::count({name, 100}) != std::string(name).size());
            EXPECT( Mem::count({name, 10}) != std::string(name).size());
          }

          AND_THEN("If callee keeps track of the size, it will still work"){
            EXPECT( Mem::count({name, 17}) == std::string(name).size());
          }
        }

        WHEN ("We use std::array") {
          std::array<char,30> my_array {'G','S','L',' ','l','o', 'o', 'k', 's', ' ', 'n', 'i', 'c', 'e'};
          THEN("we're perfectly safe"){
            EXPECT( Mem::count(my_array) == my_array.size() );
          }
        }

        WHEN ("We use normal array") {
          char str2 [] = {49, 50, 51, 52, 53};

          THEN ("Span helps us avoid decay to pointer") {
            EXPECT( Mem::count(str2) == sizeof(str2));
          }
        }
      }
    }
  }
};

void Service::start()
{

  // Lest takes command line params
  char* argv[2] = {(char*)"test", (char*)"-p"};

  auto failed = lest::run(test_basic_gsl, 2, argv);

  assert(not failed);

  MYINFO("SUCCESS");

}
<commit_msg>Updated GSL-test to verify bounds checking on span<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
   A very superficial test to verify that basic STL is working
   This is useful when we mess with / replace STL implementations

**/

#include <os>
#include <cassert>

#define GSL_THROW_ON_CONTRACT_VIOLATION
#include <gsl.h>
#include <lest.hpp>

int clock_gettime(clockid_t clk_id, struct timespec *tp){
(void*)clk_id;
(void*)tp;
return 0;
};

#define MYINFO(X,...) INFO("Test GSL",X,##__VA_ARGS__)

static int divcount_ = 0;

const lest::test test_basic_gsl[] = {
  {

    SCENARIO ("Basic Expects / Ensures behave as expected") {

      GIVEN ("A simple division function, requiring positive integers") {

        class Math {
        public:
          static int div (int x, int y) {
            Expects( y > 0 );

            int prevcount_ = divcount_;

            auto result = x / y;
            divcount_++;

            Ensures(result == x / y);
            Ensures(divcount_ > 0);
            Ensures(divcount_ == prevcount_ + 1);

            return result;

          }
        };

        WHEN ("y is zero") {
          int y = 0;

          THEN ("Division by y throws") {
            EXPECT_THROWS( Math::div(100, y) );
          }

        }

        WHEN ("y is positive") {
          int y = 4;

          THEN ("Division by y doesn't throw") {
            EXPECT_NO_THROW( Math::div(100, y) );
          }

          AND_THEN("Division gives the correct result"){
            EXPECT( Math::div(100,y) == 100 / y );
          }
        }

        WHEN ("y is negative"){
          int y = -90;

          THEN ("Divsion by y throws") {}
          EXPECT_THROWS( Math::div(100, y) );

          AND_THEN("Division should have succeeded twice"){
            EXPECT(divcount_ == 2);
          }
        }
      }
    }
  },

  {
    SCENARIO("We can use span to replace pointer-and-size interfaces") {

      GIVEN ("A (member) function with a span parameter") {

        class Mem {
        public:
          static unsigned int count(gsl::span<char> chars){

            int i = 0;
            for ( auto c : chars ) {
              printf("%c ", c);
              i++;
            }

            printf("\n");
            return i;
          }

        };

        WHEN ("We pass a raw pointer") {
          char* name = (char*)"Bjarne Stroustrup";

          THEN("if we lie to the about our size, span can't save us from overflow / underflow") {
            EXPECT( Mem::count({name, 100}) != std::string(name).size());
            EXPECT( Mem::count({name, 10}) != std::string(name).size());
          }

          AND_THEN("If caller keeps track of the size, it will still work"){
            EXPECT( Mem::count({name, 17}) == std::string(name).size());
          }

        }

        WHEN ("We use std::array") {
          std::array<char,30> my_array {'G','S','L',' ','l','o', 'o', 'k', 's', ' ', 'n', 'i', 'c', 'e'};
          THEN("we're perfectly safe"){
            EXPECT( Mem::count(my_array) == my_array.size() );
          }
        }

        WHEN ("We use normal array") {
          char str2 [] = {49, 50, 51, 52, 53};

          THEN ("Span helps us avoid decay to pointer") {
            EXPECT( Mem::count(str2) == sizeof(str2));
          }
        }
      }

      GIVEN ("A (Bad) span-interface that doesn't do any bounds checking") {

        class Bad {
        public:
          static unsigned char eighth(gsl::span<char> chars){
            return chars[8];
          }
        };

        WHEN ("we pass in sufficient data") {
          char* character = (char*) "Bjarne \"Yoda\" Stroustrup leas the Jedi council with wisdom";
          THEN("you can access the elements of the span using the index operator"){
            EXPECT(Bad::eighth({character, 20}) == 'Y');
          }

        }

        WHEN ("we pass in too little data") {
          char* character = (char*) "Yoda";
          THEN("span saves us from complete embarrasment") {
            EXPECT_THROWS(Bad::eighth({character, 4}));
          }

        }

      }

    }
  }
};

void Service::start()
{

  // Lest takes command line params
  char* argv[2] = {(char*)"test", (char*)"-p"};

  auto failed = lest::run(test_basic_gsl, 2, argv);

  assert(not failed);

  MYINFO("SUCCESS");

}
<|endoftext|>


<commit_before>// $Id$
//***************************************************************************
// File:
//	TraceValues.cpp
//
// Purpose:
//      Support for inserting LLVM code to print values at basic block
//      and method exits.  Also exports functions to create a call
//      "printf" instruction with one of the signatures listed below.
//
// History:
//	10/11/01	 -  Vikram Adve  -  Created
//**************************************************************************/

#include "llvm/Transforms/Instrumentation/TraceValues.h"
#include "llvm/GlobalVariable.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instruction.h"
#include "llvm/iTerminators.h"
#include "llvm/iOther.h"
#include "llvm/BasicBlock.h"
#include "llvm/Method.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "llvm/Support/HashExtras.h"
#include <hash_map>
#include <strstream.h>

//*********************** Internal Data Structures *************************/

const char* const PRINTF = "printf";

#undef DONT_EMBED_STRINGS_IN_FMT

//************************** Internal Functions ****************************/

#undef USE_PTRREF
#ifdef USE_PTRREF
static inline ConstPoolPointerRef*
GetStringRef(Module* module, const char* str)
{
  static hash_map<string, ConstPoolPointerRef*> stringRefCache;
  static Module* lastModule = NULL;

  if (lastModule != module)
    { // Let's make sure we create separate global references in each module
      stringRefCache.clear();
      lastModule = module;
    }

  ConstPoolPointerRef* result = stringRefCache[str];
  if (result == NULL)
    {
      ConstPoolArray* charArray = ConstPoolArray::get(str);
      GlobalVariable* stringVar =
        new GlobalVariable(charArray->getType(),/*isConst*/true,charArray,str);
      module->getGlobalList().push_back(stringVar);
      result = ConstPoolPointerRef::get(stringVar);
      assert(result && "Failed to create reference to string constant");
      stringRefCache[str] = result;
    }

  return result;
}
#endif USE_PTRREF

static inline GlobalVariable*
GetStringRef(Module* module, const char* str)
{
  static hash_map<string, GlobalVariable*> stringRefCache;
  static Module* lastModule = NULL;

  if (lastModule != module)
    { // Let's make sure we create separate global references in each module
      stringRefCache.clear();
      lastModule = module;
    }

  GlobalVariable* result = stringRefCache[str];
  if (result == NULL)
    {
      ConstPoolArray* charArray = ConstPoolArray::get(str);
      GlobalVariable* stringVar =
        new GlobalVariable(charArray->getType(),/*isConst*/true,charArray);
      module->getGlobalList().push_back(stringVar);
      result = stringVar;
      // result = ConstPoolPointerRef::get(stringVar);
      assert(result && "Failed to create reference to string constant");
      stringRefCache[str] = result;
    }

  return result;
}

static inline bool
TraceThisOpCode(unsigned opCode)
{
  // Explicitly test for opCodes *not* to trace so that any new opcodes will
  // be traced by default (or will fail in a later assertion on VoidTy)
  //
  return (opCode  < Instruction::FirstOtherOp &&
          opCode != Instruction::Ret &&
          opCode != Instruction::Br &&
          opCode != Instruction::Switch &&
          opCode != Instruction::Free &&
          opCode != Instruction::Alloca &&
          opCode != Instruction::Store &&
          opCode != Instruction::PHINode &&
          opCode != Instruction::Cast);
}

static void
FindValuesToTraceInBB(BasicBlock* bb,
                      vector<Value*>& valuesToTraceInBB)
{
  for (BasicBlock::iterator II = bb->begin(); II != bb->end(); ++II)
    if ((*II)->getType()->isPrimitiveType() &&
        TraceThisOpCode((*II)->getOpcode()))
      {
        valuesToTraceInBB.push_back(*II);
      }
}

//
// Insert print instructions at the end of the basic block *bb
// for each value in valueVec[].  *bb must postdominate the block
// in which the value is computed; this is not checked here.
//
static void
TraceValuesAtBBExit(const vector<Value*>& valueVec,
                    BasicBlock* bb,
                    Module* module,
                    unsigned int indent,
                    bool isMethodExit)
{
  // Get an iterator to point to the insertion location
  //
  BasicBlock::InstListType& instList = bb->getInstList();
  TerminatorInst* termInst = bb->getTerminator();
  BasicBlock::InstListType::iterator here = instList.end();
  while ((*here) != termInst && here != instList.begin())
    --here;
  assert((*here) == termInst);

  // Insert a print instruction for each value.
  //
  for (unsigned i=0, N=valueVec.size(); i < N; i++)
    {
      Instruction* traceInstr =
        CreatePrintInstr(valueVec[i], bb, module, indent, isMethodExit);
      here = instList.insert(here, traceInstr);
    }
}

static void
InsertCodeToShowMethodEntry(BasicBlock* entryBB)
{
}

static void
InsertCodeToShowMethodExit(BasicBlock* exitBB)
{
}

//************************** External Functions ****************************/

//
// The signatures of the print methods supported are:
//   int printf(ubyte*,  ubyte*,  ubyte*,  ubyte*,  int      intValue)
//   int printf(ubyte*,  ubyte*,  ubyte*,  ubyte*,  unsigned uintValue)
//   int printf(ubyte*,  ubyte*,  ubyte*,  ubyte*,  float    floatValue)
//   int printf(ubyte*,  ubyte*,  ubyte*,  ubyte*,  double   doubleValue)
//   int printf(ubyte*,  ubyte*,  ubyte*,  ubyte*,  char*    stringValue)
//   int printf(ubyte*,  ubyte*,  ubyte*,  ubyte*,  void*    ptrValue)
//
// The invocation should be:
//       call "printf"(fmt, bbName, valueName, valueTypeName, value).
//
Method*
GetPrintMethodForType(Module* module, const Type* valueType)
{
#ifdef DONT_EMBED_STRINGS_IN_FMT
  static const int LASTARGINDEX = 4;
#else
  static const int LASTARGINDEX = 1;
#endif
  static PointerType* ubytePtrTy = NULL;
  static vector<const Type*> argTypesVec(LASTARGINDEX + 1);

  if (ubytePtrTy == NULL)
    { // create these once since they are invariant
      ubytePtrTy = PointerType::get(ArrayType::get(Type::UByteTy));
      argTypesVec[0] = ubytePtrTy;
#ifdef DONT_EMBED_STRINGS_IN_FMT
      argTypesVec[1] = ubytePtrTy;
      argTypesVec[2] = ubytePtrTy;
      argTypesVec[3] = ubytePtrTy;
#endif DONT_EMBED_STRINGS_IN_FMT
    }

  SymbolTable* symtab = module->getSymbolTable();
  argTypesVec[LASTARGINDEX] = valueType;
  MethodType* printMethodTy = MethodType::get(Type::IntTy, argTypesVec,
                                              /*isVarArg*/ false);

  Method* printMethod =
    cast<Method>(symtab->lookup(PointerType::get(printMethodTy), PRINTF));
  if (printMethod == NULL)
    { // Create a new method and add it to the module
      printMethod = new Method(printMethodTy, PRINTF);
      module->getMethodList().push_back(printMethod);

      // Create the argument list for the method so that the full signature
      // can be declared.  The args can be anonymous.
      Method::ArgumentListType &argList = printMethod->getArgumentList();
      for (unsigned i=0; i < argTypesVec.size(); ++i)
        argList.push_back(new MethodArgument(argTypesVec[i]));
    }

  return printMethod;
}

Instruction*
CreatePrintInstr(Value* val,
                 const BasicBlock* bb,
                 Module* module,
                 unsigned int indent,
                 bool isMethodExit)
{
  strstream fmtString, scopeNameString, valNameString;
  vector<Value*> paramList;
  const Type* valueType = val->getType();
  Method* printMethod = GetPrintMethodForType(module, valueType);

  if (! valueType->isPrimitiveType() ||
      valueType->getPrimitiveID() == Type::VoidTyID ||
      valueType->getPrimitiveID() == Type::TypeTyID ||
      valueType->getPrimitiveID() == Type::LabelTyID)
    {
      assert(0 && "Unsupported type for printing");
      return NULL;
    }

  const Value* scopeToUse = (isMethodExit)? (const Value*) bb->getParent()
                                          : (const Value*) bb;
  if (scopeToUse->hasName())
    scopeNameString << scopeToUse->getName() << ends;
  else
    scopeNameString << scopeToUse << ends;

  if (val->hasName())
    valNameString << val->getName() << ends;
  else
    valNameString << val << ends;

  for (unsigned i=0; i < indent; i++)
    fmtString << " ";

#undef DONT_EMBED_STRINGS_IN_FMT
#ifdef DONT_EMBED_STRINGS_IN_FMT
  fmtString << " At exit of "
            << ((isMethodExit)? "Method " : "BB ")
            << "%s : val %s = %s ";

  GlobalVariable* scopeNameVal = GetStringRef(module, scopeNameString.str());
  GlobalVariable* valNameVal   = GetStringRef(module,valNameString.str());
  GlobalVariable* typeNameVal  = GetStringRef(module,
                                     val->getType()->getDescription().c_str());
#else
  fmtString << " At exit of "
            << ((isMethodExit)? "Method " : "BB ")
            << scopeNameString.str() << " : "
            << valNameString.str()   << " = "
            << val->getType()->getDescription().c_str();
#endif DONT_EMBED_STRINGS_IN_FMT

  switch(valueType->getPrimitiveID())
    {
    case Type::BoolTyID:
    case Type::UByteTyID: case Type::UShortTyID:
    case Type::UIntTyID:  case Type::ULongTyID:
    case Type::SByteTyID: case Type::ShortTyID:
    case Type::IntTyID:   case Type::LongTyID:
      fmtString << " %d\0A";
      break;

    case Type::FloatTyID:     case Type::DoubleTyID:
      fmtString << " %g\0A";
      break;

    case Type::PointerTyID:
      fmtString << " %p\0A";
      break;

    default:
      assert(0 && "Should not get here.  Check the IF expression above");
      return NULL;
    }

  fmtString << ends;
  GlobalVariable* fmtVal = GetStringRef(module, fmtString.str());

#ifdef DONT_EMBED_STRINGS_IN_FMT
  paramList.push_back(fmtVal);
  paramList.push_back(scopeNameVal);
  paramList.push_back(valNameVal);
  paramList.push_back(typeNameVal);
  paramList.push_back(val);
#else
  paramList.push_back(fmtVal);
  paramList.push_back(val);
#endif DONT_EMBED_STRINGS_IN_FMT

  free(fmtString.str());
  free(scopeNameString.str());
  free(valNameString.str());

  return new CallInst(printMethod, paramList);
}

void
InsertCodeToTraceValues(Method* method,
                        bool traceBasicBlockExits,
                        bool traceMethodExits)
{
  vector<Value*> valuesToTraceInMethod;
  Module* module = method->getParent();
  BasicBlock* exitBB = NULL;

  if (method->isExternal() ||
      (! traceBasicBlockExits && ! traceMethodExits))
    return;

  if (traceMethodExits)
    {
      InsertCodeToShowMethodEntry(method->getEntryNode());
#ifdef TODO_LATER
      exitBB = method->getExitNode();
#endif
    }

  for (Method::iterator BI = method->begin(); BI != method->end(); ++BI)
    {
      BasicBlock* bb = *BI;
      vector<Value*> valuesToTraceInBB;
      FindValuesToTraceInBB(bb, valuesToTraceInBB);

      if (traceBasicBlockExits && bb != exitBB)
        TraceValuesAtBBExit(valuesToTraceInBB, bb, module,
                            /*indent*/ 4, /*isMethodExit*/ false);

      if (traceMethodExits)
        valuesToTraceInMethod.insert(valuesToTraceInMethod.end(),
                                     valuesToTraceInBB.begin(),
                                     valuesToTraceInBB.end());
    }

  if (traceMethodExits)
    {
      TraceValuesAtBBExit(valuesToTraceInMethod, exitBB, module,
                          /*indent*/ 0, /*isMethodExit*/ true);
      InsertCodeToShowMethodExit(exitBB);
    }
}
<commit_msg>Massive hacks to try to fix subtle logic bugs.  I think it's all working now, at least what used to.  I should disable method exit code completely because it's broken (doesn't insert just post dominating values)<commit_after>// $Id$
//***************************************************************************
// File:
//	TraceValues.cpp
//
// Purpose:
//      Support for inserting LLVM code to print values at basic block
//      and method exits.  Also exports functions to create a call
//      "printf" instruction with one of the signatures listed below.
//
// History:
//	10/11/01	 -  Vikram Adve  -  Created
//**************************************************************************/

#include "llvm/Transforms/Instrumentation/TraceValues.h"
#include "llvm/GlobalVariable.h"
#include "llvm/ConstPoolVals.h"
#include "llvm/Type.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instruction.h"
#include "llvm/iTerminators.h"
#include "llvm/iOther.h"
#include "llvm/BasicBlock.h"
#include "llvm/Method.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include <strstream>
#include "llvm/Assembly/Writer.h"

const char* const PRINTF = "printVal";

static inline GlobalVariable *
GetStringRef(Module *M, const string &str)
{
  ConstPoolArray *Init = ConstPoolArray::get(str);
  GlobalVariable *V = new GlobalVariable(Init->getType(), /*Const*/true, Init);
  M->getGlobalList().push_back(V);

  return V;
}

static inline bool
TraceThisOpCode(unsigned opCode)
{
  // Explicitly test for opCodes *not* to trace so that any new opcodes will
  // be traced by default (VoidTy's are already excluded)
  //
  return (opCode  < Instruction::FirstOtherOp &&
          opCode != Instruction::Alloca &&
          opCode != Instruction::PHINode &&
          opCode != Instruction::Cast);
}

static void
FindValuesToTraceInBB(BasicBlock* bb, vector<Value*>& valuesToTraceInBB)
{
  for (BasicBlock::iterator II = bb->begin(); II != bb->end(); ++II)
    if ((*II)->getType()->isPrimitiveType() &&
        (*II)->getType() != Type::VoidTy &&
        TraceThisOpCode((*II)->getOpcode()))
      {
        valuesToTraceInBB.push_back(*II);
      }
}

// The invocation should be:
//       call "printf"(fmt, value).
//
static Value *GetPrintMethodForType(Module *Mod, const Type *valueType) {
  vector<const Type*> ArgTys;
  ArgTys.reserve(2);
  ArgTys.push_back(PointerType::get(ArrayType::get(Type::UByteTy)));
  ArgTys.push_back(valueType);

  MethodType *printMethodTy = MethodType::get(Type::VoidTy, ArgTys,
                                              /*isVarArg*/ false);

  SymbolTable *ST = Mod->getSymbolTableSure();
  if (Value *V = ST->lookup(PointerType::get(printMethodTy), PRINTF))
    return V;

  // Create a new method and add it to the module
  Method *M = new Method(printMethodTy, PRINTF);
  Mod->getMethodList().push_back(M);
  return M;
}

static Instruction*
CreatePrintInstr(Value* val,
                 const BasicBlock* bb,
                 Module* module,
                 unsigned int indent,
                 bool isMethodExit)
{
  strstream scopeNameString;
  const Type* valueType = val->getType();

  assert(valueType->isPrimitiveType() &&
         valueType->getPrimitiveID() != Type::VoidTyID &&
         valueType->getPrimitiveID() != Type::TypeTyID &&
         valueType->getPrimitiveID() != Type::LabelTyID &&
         "Unsupported type for printing");

  const Value* scopeToUse = (isMethodExit)? (const Value*) bb->getParent()
                                          : (const Value*) bb;
  WriteAsOperand(scopeNameString, scopeToUse) << " : ";
  WriteAsOperand(scopeNameString, val) << " = "
                                       << val->getType()->getDescription()
                                       << ends;
  string fmtString(indent, ' ');

  fmtString += " At exit of " + string(isMethodExit ? "Method " : "BB ") +
    scopeNameString.str();

  switch(valueType->getPrimitiveID()) {
  case Type::BoolTyID:
  case Type::UByteTyID: case Type::UShortTyID:
  case Type::UIntTyID:  case Type::ULongTyID:
  case Type::SByteTyID: case Type::ShortTyID:
  case Type::IntTyID:   case Type::LongTyID:
    fmtString += " %d\0A";
    break;

  case Type::FloatTyID:     case Type::DoubleTyID:
    fmtString += " %g\0A";
    break;

  case Type::PointerTyID:
    fmtString += " %p\0A";
    break;

  default:
    assert(0 && "Should not get here.  Check the IF expression above");
    return NULL;
  }

  GlobalVariable *fmtVal = GetStringRef(module, fmtString);

  vector<Value*> paramList;
  paramList.push_back(fmtVal);
  paramList.push_back(val);

  return new CallInst(GetPrintMethodForType(module, valueType), paramList);
}

//
// Insert print instructions at the end of the basic block *bb
// for each value in valueVec[].  *bb must postdominate the block
// in which the value is computed; this is not checked here.
//
static void
TraceValuesAtBBExit(const vector<Value*>& valueVec,
                    BasicBlock* bb,
                    Module* module,
                    unsigned int indent,
                    bool isMethodExit)
{
  // Get an iterator to point to the insertion location
  //
  BasicBlock::InstListType& instList = bb->getInstList();
  TerminatorInst* termInst = bb->getTerminator();
  BasicBlock::InstListType::iterator here = instList.end()-1;
  assert((*here)->isTerminator());

  // Insert a print instruction for each value.
  //
  for (unsigned i=0, N=valueVec.size(); i < N; i++)
    {
      Instruction* traceInstr =
        CreatePrintInstr(valueVec[i], bb, module, indent, isMethodExit);
      here = instList.insert(here, traceInstr);
    }
}

static void
InsertCodeToShowMethodEntry(BasicBlock* entryBB)
{
}

static void
InsertCodeToShowMethodExit(BasicBlock* exitBB)
{
}

bool InsertTraceCode::doInsertTraceCode(Method *M, bool traceBasicBlockExits,
                                        bool traceMethodExits) {
  vector<Value*> valuesToTraceInMethod;
  Module* module = M->getParent();
  BasicBlock* exitBB = NULL;

  if (M->isExternal() ||
      (! traceBasicBlockExits && ! traceMethodExits))
    return false;

  if (traceMethodExits) {
    InsertCodeToShowMethodEntry(M->getEntryNode());
    exitBB = M->getBasicBlocks().front(); //getExitNode();
  }

  for (Method::iterator BI = M->begin(); BI != M->end(); ++BI) {
    BasicBlock* bb = *BI;

    vector<Value*> valuesToTraceInBB;
    FindValuesToTraceInBB(bb, valuesToTraceInBB);

    if (traceBasicBlockExits && bb != exitBB)
      TraceValuesAtBBExit(valuesToTraceInBB, bb, module,
                          /*indent*/ 4, /*isMethodExit*/ false);

    if (traceMethodExits) {
      valuesToTraceInMethod.insert(valuesToTraceInMethod.end(),
                                   valuesToTraceInBB.begin(),
                                   valuesToTraceInBB.end());
    }
  }

  if (traceMethodExits) {
    TraceValuesAtBBExit(valuesToTraceInMethod, exitBB, module,
                        /*indent*/ 0, /*isMethodExit*/ true);
    InsertCodeToShowMethodExit(exitBB);
  }
  return true;
}
<|endoftext|>


<commit_before>//===- DeadStoreElimination.cpp - Dead Store Elimination ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a trivial dead store elimination that only considers
// basic-block local redundant stores.
//
// FIXME: This should eventually be extended to be a post-dominator tree
// traversal.  Doing so would be pretty trivial.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "Support/Statistic.h"
using namespace llvm;

namespace {
  Statistic<> NumStores("dse", "Number of stores deleted");
  Statistic<> NumOther ("dse", "Number of other instrs removed");

  struct DSE : public FunctionPass {

    virtual bool runOnFunction(Function &F) {
      bool Changed = false;
      for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
        Changed |= runOnBasicBlock(*I);
      return Changed;
    }

    bool runOnBasicBlock(BasicBlock &BB);

    void DeleteDeadValueChains(Value *V, AliasSetTracker &AST);

    // getAnalysisUsage - We require post dominance frontiers (aka Control
    // Dependence Graph)
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addRequired<TargetData>();
      AU.addRequired<AliasAnalysis>();
      AU.addPreserved<AliasAnalysis>();
    }
  };
  RegisterOpt<DSE> X("dse", "Dead Store Elimination");
}

Pass *llvm::createDeadStoreEliminationPass() { return new DSE(); }

bool DSE::runOnBasicBlock(BasicBlock &BB) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  AliasSetTracker KillLocs(AA);

  // If this block ends in a return, unwind, and eventually tailcall/barrier,
  // then all allocas are dead at its end.
  if (BB.getTerminator()->getNumSuccessors() == 0) {

  }

  bool MadeChange = false;
  for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ) {
    Instruction *I = --BBI;   // Keep moving iterator backwards

#if 0
    // AST doesn't support malloc/free/alloca???
    if (isa<FreeInst>(I)) {
      // Free instructions make any stores to the free'd location dead.
      KillLocs.insert(I);
    }
#endif

    if (!isa<FreeInst>(I) &&
        (!isa<StoreInst>(I) || cast<StoreInst>(I)->isVolatile())) {
      // If this is a non-store instruction, it makes everything referenced no
      // longer killed.  Remove anything aliased from the alias set tracker.
      KillLocs.remove(I);
      continue;
    }

    // If this is a non-volatile store instruction, and if it is already in
    // the stored location is already in the tracker, then this is a dead
    // store.  We can just delete it here, but while we're at it, we also
    // delete any trivially dead expression chains.
    unsigned ValSize;
    Value *Ptr;
    if (isa<StoreInst>(I)) {
      Ptr = I->getOperand(1);
      ValSize = TD.getTypeSize(I->getOperand(0)->getType());
    } else {
      Ptr = I->getOperand(0);
      ValSize = ~0;
    }

    if (AliasSet *AS = KillLocs.getAliasSetForPointerIfExists(Ptr, ValSize))
      for (AliasSet::iterator ASI = AS->begin(), E = AS->end(); ASI != E; ++ASI)
        if (AA.alias(ASI.getPointer(), ASI.getSize(), Ptr, ValSize)
               == AliasAnalysis::MustAlias) {
          // If we found a must alias in the killed set, then this store really
          // is dead.  Delete it now.
          ++BBI;                        // Don't invalidate iterator.
          Value *Val = I->getOperand(0);
          BB.getInstList().erase(I);    // Nuke the store!
          ++NumStores;
          DeleteDeadValueChains(Val, KillLocs);   // Delete any now-dead instrs
          DeleteDeadValueChains(Ptr, KillLocs);   // Delete any now-dead instrs
          MadeChange = true;
          goto BigContinue;
        }

    // Otherwise, this is a non-dead store just add it to the set of dead
    // locations.
    KillLocs.add(I);
  BigContinue:;
  }
  return MadeChange;
}

void DSE::DeleteDeadValueChains(Value *V, AliasSetTracker &AST) {
  // Value must be dead.
  if (!V->use_empty()) return;

  if (Instruction *I = dyn_cast<Instruction>(V))
    if (isInstructionTriviallyDead(I)) {
      AST.deleteValue(I);
      getAnalysis<AliasAnalysis>().deleteValue(I);

      // See if this made any operands dead.  We do it this way in case the
      // instruction uses the same operand twice.  We don't want to delete a
      // value then reference it.
      while (unsigned NumOps = I->getNumOperands()) {
        Value *Op = I->getOperand(NumOps-1);
        I->op_erase(I->op_end()-1);         // Drop from the operand list.
        DeleteDeadValueChains(Op, AST);  // Attempt to nuke it.
      }

      I->getParent()->getInstList().erase(I);
      ++NumOther;
    }
}
<commit_msg>* Substantially simplify how free instructions are handled (potentially fixing   a bug in DSE). * Delete dead operand uses iteratively instead of recursively, using a   SetVector. * Defer deletion of dead operand uses until the end of processing, which means   we don't have to bother with updating the AliasSetTracker.  This speeds up   DSE substantially.<commit_after>//===- DeadStoreElimination.cpp - Dead Store Elimination ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a trivial dead store elimination that only considers
// basic-block local redundant stores.
//
// FIXME: This should eventually be extended to be a post-dominator tree
// traversal.  Doing so would be pretty trivial.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Scalar.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/Utils/Local.h"
#include "Support/SetVector.h"
#include "Support/Statistic.h"
using namespace llvm;

namespace {
  Statistic<> NumStores("dse", "Number of stores deleted");
  Statistic<> NumOther ("dse", "Number of other instrs removed");

  struct DSE : public FunctionPass {

    virtual bool runOnFunction(Function &F) {
      bool Changed = false;
      for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
        Changed |= runOnBasicBlock(*I);
      return Changed;
    }

    bool runOnBasicBlock(BasicBlock &BB);

    void DeleteDeadInstructionChains(Instruction *I,
                                     SetVector<Instruction*> &DeadInsts);

    // getAnalysisUsage - We require post dominance frontiers (aka Control
    // Dependence Graph)
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.setPreservesCFG();
      AU.addRequired<TargetData>();
      AU.addRequired<AliasAnalysis>();
      AU.addPreserved<AliasAnalysis>();
    }
  };
  RegisterOpt<DSE> X("dse", "Dead Store Elimination");
}

Pass *llvm::createDeadStoreEliminationPass() { return new DSE(); }

bool DSE::runOnBasicBlock(BasicBlock &BB) {
  TargetData &TD = getAnalysis<TargetData>();
  AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
  AliasSetTracker KillLocs(AA);

  // If this block ends in a return, unwind, and eventually tailcall/barrier,
  // then all allocas are dead at its end.
  if (BB.getTerminator()->getNumSuccessors() == 0) {

  }

  // PotentiallyDeadInsts - Deleting dead stores from the program can make other
  // instructions die if they were only used as operands to stores.  Keep track
  // of the operands to stores so that we can try deleting them at the end of
  // the traversal.
  SetVector<Instruction*> PotentiallyDeadInsts;

  bool MadeChange = false;
  for (BasicBlock::iterator BBI = BB.end(); BBI != BB.begin(); ) {
    Instruction *I = --BBI;   // Keep moving iterator backwards

    // If this is a free instruction, it makes the free'd location dead!
    if (FreeInst *FI = dyn_cast<FreeInst>(I)) {
      // Free instructions make any stores to the free'd location dead.
      KillLocs.add(FI);
      continue;
    }

    if (!isa<StoreInst>(I) || cast<StoreInst>(I)->isVolatile()) {
      // If this is a non-store instruction, it makes everything referenced no
      // longer killed.  Remove anything aliased from the alias set tracker.
      KillLocs.remove(I);
      continue;
    }

    // If this is a non-volatile store instruction, and if it is already in
    // the stored location is already in the tracker, then this is a dead
    // store.  We can just delete it here, but while we're at it, we also
    // delete any trivially dead expression chains.
    unsigned ValSize = TD.getTypeSize(I->getOperand(0)->getType());
    Value *Ptr = I->getOperand(1);

    if (AliasSet *AS = KillLocs.getAliasSetForPointerIfExists(Ptr, ValSize))
      for (AliasSet::iterator ASI = AS->begin(), E = AS->end(); ASI != E; ++ASI)
        if (AA.alias(ASI.getPointer(), ASI.getSize(), Ptr, ValSize)
               == AliasAnalysis::MustAlias) {
          // If we found a must alias in the killed set, then this store really
          // is dead.  Remember that the various operands of the store now have
          // fewer users.  At the end we will see if we can delete any values
          // that are dead as part of the store becoming dead.
          if (Instruction *Op = dyn_cast<Instruction>(I->getOperand(0)))
            PotentiallyDeadInsts.insert(Op);
          if (Instruction *Op = dyn_cast<Instruction>(Ptr))
            PotentiallyDeadInsts.insert(Op);

          // Delete it now.
          ++BBI;                        // Don't invalidate iterator.
          BB.getInstList().erase(I);    // Nuke the store!
          ++NumStores;
          MadeChange = true;
          goto BigContinue;
        }

    // Otherwise, this is a non-dead store just add it to the set of dead
    // locations.
    KillLocs.add(cast<StoreInst>(I));
  BigContinue:;
  }

  while (!PotentiallyDeadInsts.empty()) {
    Instruction *I = PotentiallyDeadInsts.back();
    PotentiallyDeadInsts.pop_back();
    DeleteDeadInstructionChains(I, PotentiallyDeadInsts);
  }
  return MadeChange;
}

void DSE::DeleteDeadInstructionChains(Instruction *I,
                                      SetVector<Instruction*> &DeadInsts) {
  // Instruction must be dead.
  if (!I->use_empty() || !isInstructionTriviallyDead(I)) return;

  // Let the alias analysis know that we have nuked a value.
  getAnalysis<AliasAnalysis>().deleteValue(I);

  // See if this made any operands dead.  We do it this way in case the
  // instruction uses the same operand twice.  We don't want to delete a
  // value then reference it.
  while (unsigned NumOps = I->getNumOperands()) {
    Instruction *Op = dyn_cast<Instruction>(I->getOperand(NumOps-1));
    I->op_erase(I->op_end()-1);         // Drop from the operand list.

    if (Op) DeadInsts.insert(Op);       // Attempt to nuke it later.
  }

  I->getParent()->getInstList().erase(I);
  ++NumOther;
}
<|endoftext|>