<commit_before>/*
    kopeteaccount.cpp - Kopete Account

    Copyright (c) 2003      by Olivier Goffart       <ogoffart@tiscalinet.be>
    Copyright (c) 2003-2004 by Martijn Klingens      <klingens@kde.org>
    Copyright (c) 2004      by Richard Smith         <kde@metafoo.co.uk>
    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include <qapplication.h>
#include <qtimer.h>

#include <kconfig.h>
#include <kdebug.h>
#include <kdeversion.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kiconeffect.h>

#include "kopetecontactlist.h"
#include "kopeteaccount.h"
#include "kopeteaccountmanager.h"
#include "kopetemetacontact.h"
#include "kopeteprotocol.h"
#include "kopetepluginmanager.h"
#include "kopetegroup.h"
#include "kopetepassword.h"

namespace
{
QString configGroup( KopeteProtocol *protocol, const QString &accountId )
{
#if QT_VERSION < 0x030200
	return QString::fromLatin1( "Account_%2_%1" ).arg( accountId ).arg( protocol->pluginId() );
#else
	return QString::fromLatin1( "Account_%2_%1" ).arg( accountId, protocol->pluginId() );
#endif
}

}

class KopeteAccountPrivate
{
public:
	KopeteAccountPrivate( KopeteProtocol *protocol, const QString &accountId )
	 : protocol( protocol ), id( accountId )
	 , password( configGroup( protocol, accountId ) )
	 , autologin( false ), priority( 0 ), myself( 0 )
	 , suppressStatusTimer( 0 ), suppressStatusNotification( false )
	{
	}

	KopeteProtocol *protocol;
	QString id;
	Kopete::Password password;
	bool autologin;
	uint priority;
	QDict<KopeteContact> contacts;
	QColor color;
	KopeteContact *myself;
	QTimer *suppressStatusTimer;
	bool suppressStatusNotification;
};

KopeteAccount::KopeteAccount( KopeteProtocol *parent, const QString &accountId, const char *name )
 : KopetePluginDataObject( parent, name ), d( new KopeteAccountPrivate( parent, accountId ) )
{
	d->suppressStatusTimer = new QTimer( this, "suppressStatusTimer" );
	QObject::connect( d->suppressStatusTimer, SIGNAL( timeout() ),
		this, SLOT( slotStopSuppression() ) );

	KopeteAccountManager::manager()->registerAccount( this );

	QTimer::singleShot( 0, this, SLOT( slotAccountReady() ) );
}

KopeteAccount::~KopeteAccount()
{
	// Delete all registered child contacts first
	while ( !d->contacts.isEmpty() )
		delete *QDictIterator<KopeteContact>( d->contacts );
	KopeteAccountManager::manager()->unregisterAccount( this );

	delete d;
}

void KopeteAccount::slotAccountReady()
{
	KopeteAccountManager::manager()->notifyAccountReady( this );
}

KopeteProtocol *KopeteAccount::protocol() const
{
	return d->protocol;
}

QString KopeteAccount::accountId() const
{
	return d->id;
}

const QColor KopeteAccount::color() const
{
	return d->color;
}

void KopeteAccount::setColor( const QColor &color )
{
	d->color = color;
}

void KopeteAccount::setPriority( uint priority )
{
 	d->priority = priority;
}

const uint KopeteAccount::priority() const
{
	return d->priority;
}

void KopeteAccount::setAccountId( const QString &accountId )
{
	if ( d->id != accountId )
	{
		d->id = accountId;
		emit ( accountIdChanged() );
	}
}

QPixmap KopeteAccount::accountIcon(const int size) const
{
	QPixmap base = KGlobal::instance()->iconLoader()->loadIcon(
		d->protocol->pluginIcon(), KIcon::Small, size );

	if ( d->color.isValid() )
	{
		KIconEffect effect;
		base = effect.apply( base, KIconEffect::Colorize, 1, d->color, 0);
	}

	if ( size > 0 && base.width() != size )
	{
		base = QPixmap( base.convertToImage().smoothScale( size, size ) );
	}

	return base;
}

QString KopeteAccount::configGroup() const
{
	return ::configGroup( protocol(), accountId() );
}

void KopeteAccount::writeConfig( const QString &configGroupName )
{
	KConfig *config = KGlobal::config();
	config->setGroup( configGroupName );

	config->writeEntry( "Protocol", d->protocol->pluginId() );
	config->writeEntry( "AccountId", d->id );
	config->writeEntry( "Priority", d->priority );

	config->writeEntry( "AutoConnect", d->autologin );

	if ( d->color.isValid() )
		config->writeEntry( "Color", d->color );
	else
		config->deleteEntry( "Color" );

	// Store other plugin data
	KopetePluginDataObject::writeConfig( configGroupName );
}

void KopeteAccount::readConfig( const QString &configGroupName )
{
	KConfig *config = KGlobal::config();
	config->setGroup( configGroupName );

	d->autologin = config->readBoolEntry( "AutoConnect", false );
	d->color = config->readColorEntry( "Color", &d->color );
	d->priority = config->readNumEntry( "Priority", 0 );

	// Handle the plugin data, if any
	QMap<QString, QString> entries = config->entryMap( configGroupName );
	QMap<QString, QString>::Iterator entryIt;
	QMap<QString, QMap<QString, QString> > pluginData;
	for ( entryIt = entries.begin(); entryIt != entries.end(); ++entryIt )
	{
		if ( entryIt.key().startsWith( QString::fromLatin1( "PluginData_" ) ) )
		{
			QStringList data = QStringList::split( '_', entryIt.key(), true );
			data.pop_front(); // Strip "PluginData_" first
			QString pluginName = data.first();
			data.pop_front();

			// Join remainder and store it
			pluginData[ pluginName ][ data.join( QString::fromLatin1( "_" ) ) ] = entryIt.data();
		}
	}

	// Lastly, pass on the plugin data to the account
	QMap<QString, QMap<QString, QString> >::Iterator pluginDataIt;
	for ( pluginDataIt = pluginData.begin(); pluginDataIt != pluginData.end(); ++pluginDataIt )
	{
		KopetePlugin *plugin = KopetePluginManager::self()->plugin( pluginDataIt.key() );
		if ( plugin )
			setPluginData( plugin, pluginDataIt.data() );
		else
		{
			kdDebug( 14010 ) << k_funcinfo <<
				"No plugin object for id '" << pluginDataIt.key() << "'" << endl;
		}
	}

	loaded();
}

void KopeteAccount::loaded()
{
	/* do nothing in default implementation */
}

QString KopeteAccount::password( bool error, bool *ok, unsigned int maxLength ) const
{
	d->password.setMaximumLength( maxLength );
	QString prompt;
	if ( error )
	{
		prompt = i18n( "The password was wrong! Please re-enter your"\
			" password for %1 account %2" ).arg( protocol()->displayName(),
				accountId() );
	}
	else
	{
		prompt = i18n( "Please enter your password for %1 account %2" )
			.arg( protocol()->displayName(), accountId() );
	}

	QString pass = d->password.retrieve(
		accountIcon( Kopete::Password::preferredImageSize() ), prompt,
		error ? Kopete::Password::FromUser : Kopete::Password::FromConfigOrUser );

	if ( ok )
		*ok = !pass.isNull();
	return pass;
}

void KopeteAccount::setPassword( const QString &pass )
{
	d->password.set( pass );
}

void KopeteAccount::setAutoLogin( bool b )
{
	d->autologin = b;
}

bool KopeteAccount::autoLogin() const
{
	return d->autologin;
}

bool KopeteAccount::rememberPassword() const
{
	return d->password.remembered();
}

void KopeteAccount::registerContact( KopeteContact *c )
{
	d->contacts.insert( c->contactId(), c );
	QObject::connect( c, SIGNAL( contactDestroyed( KopeteContact * ) ),
		SLOT( slotKopeteContactDestroyed( KopeteContact * ) ) );
}

void KopeteAccount::slotKopeteContactDestroyed( KopeteContact *c )
{
	//kdDebug( 14010 ) << "KopeteProtocol::slotKopeteContactDestroyed: " << c->contactId() << endl;
	d->contacts.remove( c->contactId() );
}

const QDict<KopeteContact>& KopeteAccount::contacts()
{
	return d->contacts;
}

/*QDict<KopeteContact> KopeteAccount::contacts( KopeteMetaContact *mc )
{
	QDict<KopeteContact> result;

	QDictIterator<KopeteContact> it( d->contacts );
	for ( ; it.current() ; ++it )
	{
		if ( ( *it )->metaContact() == mc )
			result.insert( ( *it )->contactId(), *it );
	}
	return result;
}*/

bool KopeteAccount::addContact( const QString &contactId, const QString &displayName,
	KopeteMetaContact *parentContact, const AddMode mode, const QString &groupName, bool isTemporary )
{
	if ( contactId == accountId() )
	{
		kdDebug( 14010 ) << k_funcinfo <<
			"WARNING: the user try to add myself to his contactlist - abort" << endl;
		return false;
	}

	KopeteGroup *parentGroup = 0L;
	//If this is a temporary contact, use the temporary group
	if ( !groupName.isNull() )
		parentGroup = isTemporary ? KopeteGroup::temporary() : KopeteContactList::contactList()->getGroup( groupName );

	if(!parentGroup && parentContact)
		parentGroup=parentContact->groups().first();

	KopeteContact *c = d->contacts[ contactId ];
	if ( c && c->metaContact() )
	{
		if ( c->metaContact()->isTemporary() && !isTemporary )
		{
			kdDebug( 14010 ) <<
				"KopeteAccount::addContact: You are trying to add an existing temporary contact. Just add it on the list" << endl;
			/* //FIXME: calling this can produce a message to delete the old contazct which should be deleted in many case.
			if(c->metaContact() != parentContact)
				c->setMetaContact(parentContact);*/

			c->metaContact()->setTemporary(false, parentGroup );
			if(!KopeteContactList::contactList()->metaContacts().contains(c->metaContact()))
				KopeteContactList::contactList()->addMetaContact(c->metaContact());
		}
		else
		{
			// should we here add the contact to the parentContact if any?
			kdDebug( 14010 ) << "KopeteAccount::addContact: Contact already exists" << endl;
		}
		return false; //(the contact is not in the correct metacontact, so false)
	}

	if ( parentContact )
	{
		//If we are given a MetaContact to add to that is marked as temporary. but
		//this contact is not temporary, then change the metacontact to non-temporary
		if ( parentContact->isTemporary() && !isTemporary )
			parentContact->setTemporary( false, parentGroup );
		else
			parentContact->addToGroup( parentGroup );
	}
	else
	{
		//Create a new MetaContact
		parentContact = new KopeteMetaContact();
		parentContact->setDisplayName( displayName );

		//Set it as a temporary contact if requested
		if ( isTemporary )
			parentContact->setTemporary( true );
		else
			parentContact->addToGroup( parentGroup );

		KopeteContactList::contactList()->addMetaContact( parentContact );
	}

	if ( c )
	{
		c->setMetaContact( parentContact );
	}
	else
	{
		if ( !addContactToMetaContact( contactId, displayName, parentContact ) )
			return false;
	}

	if ( mode == ChangeKABC )
	{
		kdDebug( 14010 ) << k_funcinfo << " changing KABC" << endl;
		parentContact->updateKABC();
	}
	/*else
		kdDebug( 14010 ) << k_funcinfo << " leaving KABC" << endl;*/
	return true;
}

KActionMenu * KopeteAccount::actionMenu()
{
	//default implementation
	return 0L;
}

bool KopeteAccount::isConnected() const
{
	return d->myself && ( d->myself->onlineStatus().status() != KopeteOnlineStatus::Offline ) ;
}

bool KopeteAccount::isAway() const
{
	return d->myself && ( d->myself->onlineStatus().status() == KopeteOnlineStatus::Away );
}

KopeteContact * KopeteAccount::myself() const
{
	return d->myself;
}

void KopeteAccount::setMyself( KopeteContact *myself )
{
	d->myself = myself;

	QObject::connect( myself, SIGNAL( onlineStatusChanged( KopeteContact *, const KopeteOnlineStatus &, const KopeteOnlineStatus & ) ),
		this, SLOT( slotOnlineStatusChanged( KopeteContact *, const KopeteOnlineStatus &, const KopeteOnlineStatus & ) ) );
}

void KopeteAccount::slotOnlineStatusChanged( KopeteContact * /* contact */,
	const KopeteOnlineStatus &newStatus, const KopeteOnlineStatus &oldStatus )
{
	if ( oldStatus.status() == KopeteOnlineStatus::Offline ||
		oldStatus.status() == KopeteOnlineStatus::Connecting ||
		newStatus.status() == KopeteOnlineStatus::Offline )
	{
		// Wait for five seconds until we treat status notifications for contacts
		// as unrelated to our own status change.
		// Five seconds may seem like a long time, but just after your own
		// connection it's basically neglectible, and depending on your own
		// contact list's size, the protocol you are using, your internet
		// connection's speed and your computer's speed you *will* need it.
		d->suppressStatusNotification = true;
		d->suppressStatusTimer->start( 5000, true );
	}
}

void KopeteAccount::slotStopSuppression()
{
	d->suppressStatusNotification = false;
}

bool KopeteAccount::suppressStatusNotification() const
{
	return d->suppressStatusNotification;
}

#include "kopeteaccount.moc"
// vim: set noet ts=4 sts=4 sw=4:
<commit_msg>Fix creation of new metacontacts, they always got their nickname tracking disabled. KMC::addcontact() is already assigning a proper displayName so don't do it in here. This fixes the long standing 'new icq contacts have their uin as name' bug<commit_after>/*
    kopeteaccount.cpp - Kopete Account

    Copyright (c) 2003      by Olivier Goffart       <ogoffart@tiscalinet.be>
    Copyright (c) 2003-2004 by Martijn Klingens      <klingens@kde.org>
    Copyright (c) 2004      by Richard Smith         <kde@metafoo.co.uk>
    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This library is free software; you can redistribute it and/or         *
    * modify it under the terms of the GNU Lesser General Public            *
    * License as published by the Free Software Foundation; either          *
    * version 2 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include <qapplication.h>
#include <qtimer.h>

#include <kconfig.h>
#include <kdebug.h>
#include <kdeversion.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kiconeffect.h>

#include "kopetecontactlist.h"
#include "kopeteaccount.h"
#include "kopeteaccountmanager.h"
#include "kopetemetacontact.h"
#include "kopeteprotocol.h"
#include "kopetepluginmanager.h"
#include "kopetegroup.h"
#include "kopetepassword.h"

namespace
{
QString configGroup( KopeteProtocol *protocol, const QString &accountId )
{
#if QT_VERSION < 0x030200
	return QString::fromLatin1( "Account_%2_%1" ).arg( accountId ).arg( protocol->pluginId() );
#else
	return QString::fromLatin1( "Account_%2_%1" ).arg( accountId, protocol->pluginId() );
#endif
}

}

class KopeteAccountPrivate
{
public:
	KopeteAccountPrivate( KopeteProtocol *protocol, const QString &accountId )
	 : protocol( protocol ), id( accountId )
	 , password( configGroup( protocol, accountId ) )
	 , autologin( false ), priority( 0 ), myself( 0 )
	 , suppressStatusTimer( 0 ), suppressStatusNotification( false )
	{
	}

	KopeteProtocol *protocol;
	QString id;
	Kopete::Password password;
	bool autologin;
	uint priority;
	QDict<KopeteContact> contacts;
	QColor color;
	KopeteContact *myself;
	QTimer *suppressStatusTimer;
	bool suppressStatusNotification;
};

KopeteAccount::KopeteAccount( KopeteProtocol *parent, const QString &accountId, const char *name )
 : KopetePluginDataObject( parent, name ), d( new KopeteAccountPrivate( parent, accountId ) )
{
	d->suppressStatusTimer = new QTimer( this, "suppressStatusTimer" );
	QObject::connect( d->suppressStatusTimer, SIGNAL( timeout() ),
		this, SLOT( slotStopSuppression() ) );

	KopeteAccountManager::manager()->registerAccount( this );

	QTimer::singleShot( 0, this, SLOT( slotAccountReady() ) );
}

KopeteAccount::~KopeteAccount()
{
	// Delete all registered child contacts first
	while ( !d->contacts.isEmpty() )
		delete *QDictIterator<KopeteContact>( d->contacts );
	KopeteAccountManager::manager()->unregisterAccount( this );

	delete d;
}

void KopeteAccount::slotAccountReady()
{
	KopeteAccountManager::manager()->notifyAccountReady( this );
}

KopeteProtocol *KopeteAccount::protocol() const
{
	return d->protocol;
}

QString KopeteAccount::accountId() const
{
	return d->id;
}

const QColor KopeteAccount::color() const
{
	return d->color;
}

void KopeteAccount::setColor( const QColor &color )
{
	d->color = color;
}

void KopeteAccount::setPriority( uint priority )
{
 	d->priority = priority;
}

const uint KopeteAccount::priority() const
{
	return d->priority;
}

void KopeteAccount::setAccountId( const QString &accountId )
{
	if ( d->id != accountId )
	{
		d->id = accountId;
		emit ( accountIdChanged() );
	}
}

QPixmap KopeteAccount::accountIcon(const int size) const
{
	QPixmap base = KGlobal::instance()->iconLoader()->loadIcon(
		d->protocol->pluginIcon(), KIcon::Small, size );

	if ( d->color.isValid() )
	{
		KIconEffect effect;
		base = effect.apply( base, KIconEffect::Colorize, 1, d->color, 0);
	}

	if ( size > 0 && base.width() != size )
	{
		base = QPixmap( base.convertToImage().smoothScale( size, size ) );
	}

	return base;
}

QString KopeteAccount::configGroup() const
{
	return ::configGroup( protocol(), accountId() );
}

void KopeteAccount::writeConfig( const QString &configGroupName )
{
	KConfig *config = KGlobal::config();
	config->setGroup( configGroupName );

	config->writeEntry( "Protocol", d->protocol->pluginId() );
	config->writeEntry( "AccountId", d->id );
	config->writeEntry( "Priority", d->priority );

	config->writeEntry( "AutoConnect", d->autologin );

	if ( d->color.isValid() )
		config->writeEntry( "Color", d->color );
	else
		config->deleteEntry( "Color" );

	// Store other plugin data
	KopetePluginDataObject::writeConfig( configGroupName );
}

void KopeteAccount::readConfig( const QString &configGroupName )
{
	KConfig *config = KGlobal::config();
	config->setGroup( configGroupName );

	d->autologin = config->readBoolEntry( "AutoConnect", false );
	d->color = config->readColorEntry( "Color", &d->color );
	d->priority = config->readNumEntry( "Priority", 0 );

	// Handle the plugin data, if any
	QMap<QString, QString> entries = config->entryMap( configGroupName );
	QMap<QString, QString>::Iterator entryIt;
	QMap<QString, QMap<QString, QString> > pluginData;
	for ( entryIt = entries.begin(); entryIt != entries.end(); ++entryIt )
	{
		if ( entryIt.key().startsWith( QString::fromLatin1( "PluginData_" ) ) )
		{
			QStringList data = QStringList::split( '_', entryIt.key(), true );
			data.pop_front(); // Strip "PluginData_" first
			QString pluginName = data.first();
			data.pop_front();

			// Join remainder and store it
			pluginData[ pluginName ][ data.join( QString::fromLatin1( "_" ) ) ] = entryIt.data();
		}
	}

	// Lastly, pass on the plugin data to the account
	QMap<QString, QMap<QString, QString> >::Iterator pluginDataIt;
	for ( pluginDataIt = pluginData.begin(); pluginDataIt != pluginData.end(); ++pluginDataIt )
	{
		KopetePlugin *plugin = KopetePluginManager::self()->plugin( pluginDataIt.key() );
		if ( plugin )
			setPluginData( plugin, pluginDataIt.data() );
		else
		{
			kdDebug( 14010 ) << k_funcinfo <<
				"No plugin object for id '" << pluginDataIt.key() << "'" << endl;
		}
	}

	loaded();
}

void KopeteAccount::loaded()
{
	/* do nothing in default implementation */
}

QString KopeteAccount::password( bool error, bool *ok, unsigned int maxLength ) const
{
	d->password.setMaximumLength( maxLength );
	QString prompt;
	if ( error )
	{
		prompt = i18n( "The password was wrong! Please re-enter your"\
			" password for %1 account %2" ).arg( protocol()->displayName(),
				accountId() );
	}
	else
	{
		prompt = i18n( "Please enter your password for %1 account %2" )
			.arg( protocol()->displayName(), accountId() );
	}

	QString pass = d->password.retrieve(
		accountIcon( Kopete::Password::preferredImageSize() ), prompt,
		error ? Kopete::Password::FromUser : Kopete::Password::FromConfigOrUser );

	if ( ok )
		*ok = !pass.isNull();
	return pass;
}

void KopeteAccount::setPassword( const QString &pass )
{
	d->password.set( pass );
}

void KopeteAccount::setAutoLogin( bool b )
{
	d->autologin = b;
}

bool KopeteAccount::autoLogin() const
{
	return d->autologin;
}

bool KopeteAccount::rememberPassword() const
{
	return d->password.remembered();
}

void KopeteAccount::registerContact( KopeteContact *c )
{
	d->contacts.insert( c->contactId(), c );
	QObject::connect( c, SIGNAL( contactDestroyed( KopeteContact * ) ),
		SLOT( slotKopeteContactDestroyed( KopeteContact * ) ) );
}

void KopeteAccount::slotKopeteContactDestroyed( KopeteContact *c )
{
	//kdDebug( 14010 ) << "KopeteProtocol::slotKopeteContactDestroyed: " << c->contactId() << endl;
	d->contacts.remove( c->contactId() );
}

const QDict<KopeteContact>& KopeteAccount::contacts()
{
	return d->contacts;
}

/*QDict<KopeteContact> KopeteAccount::contacts( KopeteMetaContact *mc )
{
	QDict<KopeteContact> result;

	QDictIterator<KopeteContact> it( d->contacts );
	for ( ; it.current() ; ++it )
	{
		if ( ( *it )->metaContact() == mc )
			result.insert( ( *it )->contactId(), *it );
	}
	return result;
}*/

bool KopeteAccount::addContact( const QString &contactId, const QString &displayName,
	KopeteMetaContact *parentContact, const AddMode mode, const QString &groupName, bool isTemporary )
{
	if ( contactId == accountId() )
	{
		kdDebug( 14010 ) << k_funcinfo <<
			"WARNING: the user try to add myself to his contactlist - abort" << endl;
		return false;
	}

	KopeteGroup *parentGroup = 0L;
	//If this is a temporary contact, use the temporary group
	if ( !groupName.isNull() )
		parentGroup = isTemporary ? KopeteGroup::temporary() : KopeteContactList::contactList()->getGroup( groupName );

	if(!parentGroup && parentContact)
		parentGroup=parentContact->groups().first();

	KopeteContact *c = d->contacts[ contactId ];
	if ( c && c->metaContact() )
	{
		if ( c->metaContact()->isTemporary() && !isTemporary )
		{
			kdDebug( 14010 ) <<
				"KopeteAccount::addContact: You are trying to add an existing temporary contact. Just add it on the list" << endl;
			/* //FIXME: calling this can produce a message to delete the old contazct which should be deleted in many case.
			if(c->metaContact() != parentContact)
				c->setMetaContact(parentContact);*/

			c->metaContact()->setTemporary(false, parentGroup );
			if(!KopeteContactList::contactList()->metaContacts().contains(c->metaContact()))
				KopeteContactList::contactList()->addMetaContact(c->metaContact());
		}
		else
		{
			// should we here add the contact to the parentContact if any?
			kdDebug( 14010 ) << "KopeteAccount::addContact: Contact already exists" << endl;
		}
		return false; //(the contact is not in the correct metacontact, so false)
	}

	if ( parentContact )
	{
		//If we are given a MetaContact to add to that is marked as temporary. but
		//this contact is not temporary, then change the metacontact to non-temporary
		if ( parentContact->isTemporary() && !isTemporary )
			parentContact->setTemporary( false, parentGroup );
		else
			parentContact->addToGroup( parentGroup );
	}
	else
	{
		//Create a new MetaContact
		parentContact = new KopeteMetaContact();
		//parentContact->setDisplayName( displayName );

		//Set it as a temporary contact if requested
		if ( isTemporary )
			parentContact->setTemporary( true );
		else
			parentContact->addToGroup( parentGroup );

		KopeteContactList::contactList()->addMetaContact( parentContact );
	}

	if ( c )
	{
		c->setMetaContact( parentContact );
	}
	else
	{
		if ( !addContactToMetaContact( contactId, displayName, parentContact ) )
			return false;
	}

	if ( mode == ChangeKABC )
	{
		kdDebug( 14010 ) << k_funcinfo << " changing KABC" << endl;
		parentContact->updateKABC();
	}
	/*else
		kdDebug( 14010 ) << k_funcinfo << " leaving KABC" << endl;*/
	return true;
}

KActionMenu * KopeteAccount::actionMenu()
{
	//default implementation
	return 0L;
}

bool KopeteAccount::isConnected() const
{
	return d->myself && ( d->myself->onlineStatus().status() != KopeteOnlineStatus::Offline ) ;
}

bool KopeteAccount::isAway() const
{
	return d->myself && ( d->myself->onlineStatus().status() == KopeteOnlineStatus::Away );
}

KopeteContact * KopeteAccount::myself() const
{
	return d->myself;
}

void KopeteAccount::setMyself( KopeteContact *myself )
{
	d->myself = myself;

	QObject::connect( myself, SIGNAL( onlineStatusChanged( KopeteContact *, const KopeteOnlineStatus &, const KopeteOnlineStatus & ) ),
		this, SLOT( slotOnlineStatusChanged( KopeteContact *, const KopeteOnlineStatus &, const KopeteOnlineStatus & ) ) );
}

void KopeteAccount::slotOnlineStatusChanged( KopeteContact * /* contact */,
	const KopeteOnlineStatus &newStatus, const KopeteOnlineStatus &oldStatus )
{
	if ( oldStatus.status() == KopeteOnlineStatus::Offline ||
		oldStatus.status() == KopeteOnlineStatus::Connecting ||
		newStatus.status() == KopeteOnlineStatus::Offline )
	{
		// Wait for five seconds until we treat status notifications for contacts
		// as unrelated to our own status change.
		// Five seconds may seem like a long time, but just after your own
		// connection it's basically neglectible, and depending on your own
		// contact list's size, the protocol you are using, your internet
		// connection's speed and your computer's speed you *will* need it.
		d->suppressStatusNotification = true;
		d->suppressStatusTimer->start( 5000, true );
	}
}

void KopeteAccount::slotStopSuppression()
{
	d->suppressStatusNotification = false;
}

bool KopeteAccount::suppressStatusNotification() const
{
	return d->suppressStatusNotification;
}

#include "kopeteaccount.moc"
// vim: set noet ts=4 sts=4 sw=4:
<|endoftext|>


<commit_before>/*
    kopetecontact.cpp - Kopete Contact

    Copyright (c) 2002      by Duncan Mac-Vicar Prett <duncan@kde.org>
    Copyright (c) 2002-2003 by Martijn Klingens       <klingens@kde.org>

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "kopetecontact.h"

#include <qapplication.h>
#include <qimage.h>
#include <qlabel.h>
#include <qpixmap.h>
#include <qregexp.h>
#include <qvbox.h>

#include <kdebug.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kpopupmenu.h>
#include <kaction.h>
#include <klineeditdlg.h>
#include <kiconeffect.h>

#include "kopetecontactlist.h"
#include "kopetehistorydialog.h"
#include "kopetemetacontact.h"
#include "kopeteprotocol.h"
#include "kopetestdaction.h"
#include "kopeteviewmanager.h"

KopeteContact::KopeteContact( KopeteProtocol *protocol, const QString &contactId, KopeteMetaContact *parent )
: QObject( parent )
{
//	kdDebug() << "KopeteContact::KopeteContact: Creating contact with id " << contactId << endl;

	m_contactId = contactId;

	m_metaContact = parent;
	m_protocol = protocol;
	m_cachedSize = 0;
	m_cachedOldImportance = 0;
	contextMenu = 0L;
	mFileCapable = false;
	m_historyDialog = 0L;
	m_idleState = Unspecified;
	m_displayName = contactId;

	if( protocol )
	{
		protocol->registerContact( this );
		connect( protocol, SIGNAL( unloading() ), SLOT( slotProtocolUnloading() ) );
	}

	// Initialize the context menu
	actionSendMessage = KopeteStdAction::sendMessage( this,
		SLOT( sendMessage() ), this, "actionSendMessage" );
	actionChat = KopeteStdAction::chat( this,
		SLOT( startChat() ), this, "actionChat" );
	actionViewHistory = KopeteStdAction::viewHistory( this,
		SLOT( slotViewHistory() ), this, "actionViewHistory" );
	actionChangeMetaContact = KopeteStdAction::changeMetaContact( this,
		SLOT( slotChangeMetaContact() ), this, "actionChangeMetaContact" );
	actionDeleteContact = KopeteStdAction::deleteContact( this,
		SLOT( slotDeleteContact() ), this, "actionDeleteContact" );
	actionUserInfo = KopeteStdAction::contactInfo( this,
		SLOT( slotUserInfo() ), this, "actionUserInfo" );
	actionChangeAlias = KopeteStdAction::changeAlias( this,
		SLOT( slotChangeDisplayName() ), this, "actionChangeAlias" );
	actionSendFile = KopeteStdAction::sendFile( this,
		SLOT( sendFile() ), this, "actionSendFile");

	// Need to check this because myself() has no parent
	if( parent )
	{
		connect( parent, SIGNAL( aboutToSave( KopeteMetaContact * ) ),
			protocol, SLOT( slotMetaContactAboutToSave( KopeteMetaContact * ) ) );

		parent->addContact( this );
	}
}

KopeteContact::~KopeteContact()
{
	emit( contactDestroyed( this ) );
}

void KopeteContact::slotProtocolUnloading()
{
	delete this;
}

QString KopeteContact::identityId() const
{
	return QString::null;
}

void KopeteContact::rename( const QString &name )
{
	// Default implementation immediately sets the new name
	setDisplayName( name );
}

void KopeteContact::setDisplayName( const QString &name )
{
	if( name == m_displayName )
		return;

	m_displayName = name;
	emit displayNameChanged( name );
}

QString KopeteContact::displayName() const
{
	return m_displayName;
}

KopeteContact::ContactStatus KopeteContact::status() const
{
	return Online;
}

QString KopeteContact::statusText() const
{
	ContactStatus stat = status();

	//kdDebug(14010) << "[KopeteContact] statusText() with status= " << stat << endl;

	switch( stat )
	{
	case Online:
		return i18n("Online");
	case Away:
		return i18n("Away");
	case Unknown:
		return i18n("Status not available");
	case Offline:
	default:
		return i18n("Offline");
	}
}

QString KopeteContact::statusIcon() const
{
	return QString::fromLatin1( "unknown" );
}

QPixmap KopeteContact::scaledStatusIcon(int size)
{
	if ( (importance() != m_cachedOldImportance) || ( size != m_cachedSize ) )
	{
		QImage afScal = ((QPixmap(SmallIcon(statusIcon()))).convertToImage()).smoothScale( size, size );
		m_cachedScaledIcon = QPixmap(afScal);
		m_cachedOldImportance = importance();
		m_cachedSize = size;
	}
	if ( m_idleState == Idle )
	{
		QPixmap tmp = m_cachedScaledIcon;
		KIconEffect::semiTransparent(tmp);
		return tmp;
	}
	return m_cachedScaledIcon;
}

int KopeteContact::importance() const
{
	ContactStatus stat = status();

	if (stat == Online)
		return 20;

	if (stat == Away)
		return 10;

	if (stat == Offline)
		return 0;

	return 0;
}

void KopeteContact::slotViewHistory()
{
	kdDebug(14010) << "KopteContact::slotViewHistory()" << endl;

	if( m_historyDialog )
	{
		m_historyDialog->raise();
	}
	else
	{
		m_historyDialog = new KopeteHistoryDialog(this,
			true, 50, qApp->mainWidget(), "KopeteHistoryDialog" );

		connect ( m_historyDialog, SIGNAL( destroyed()),
			this, SLOT( slotHistoryDialogDestroyed() ) );
	}
}

void KopeteContact::slotHistoryDialogDestroyed()
{
	m_historyDialog = 0L;
}

void KopeteContact::sendFile( const KURL &, const QString &, const long unsigned int)
{
	kdDebug(14010) << "[KopeteContact] Opps, the plugin hasn't implemented file sending, yet it was turned on! :(" << endl;
}

KPopupMenu* KopeteContact::createContextMenu()
{
	//FIXME: this should perhaps be KActionCollection * KopeteContact::contactActions()
	//FIXME: to avoid passing around KPopupMenu's

	// Build the menu
	KPopupMenu *menu = new KPopupMenu();

	menu->insertTitle( QString::fromLatin1("%1 <%2> (%3)").arg(displayName()).arg(contactId()).arg(statusText()) );

	actionSendMessage->plug( menu );
	actionSendMessage->setEnabled( isReachable() );
	actionChat->plug( menu );
	actionChat->setEnabled( isReachable() );

	actionViewHistory->plug( menu );

	menu->insertSeparator();

	actionChangeMetaContact->setEnabled( !m_metaContact->isTemporary() );
	actionChangeMetaContact->plug( menu );
	actionUserInfo->plug( menu );
	actionChangeAlias->plug( menu );
	actionDeleteContact->plug( menu );

	if (mFileCapable)
		actionSendFile->plug( menu );

	// Protocol specific options will go below this separator
	// through the use of the customContextMenuActions() function

	// Get the custom actions from the protocols (pure virtual function)
	KActionCollection *customActions = customContextMenuActions();
	if(customActions != 0L)
	{
		if ( !customActions->isEmpty() )
			menu->insertSeparator();

		for(unsigned int i = 0; i < customActions->count(); i++)
		{
			customActions->action(i)->plug( menu );
		}
	}

	return menu;
}

KPopupMenu *KopeteContact::popupMenu()
{
	contextMenu = createContextMenu();
	return contextMenu;
}

void KopeteContact::showContextMenu(const QPoint& p)
{
	contextMenu = createContextMenu();
	contextMenu->exec( p );
	delete contextMenu;
	contextMenu = 0L;
}

void KopeteContact::slotChangeDisplayName(){
	bool okClicked;
	QString newName = KLineEditDlg::getText(i18n("Change Alias"), i18n("New alias for %1").arg(contactId()),
		displayName(), &okClicked);

	if(okClicked)
		setDisplayName( newName );
}

void KopeteContact::slotChangeMetaContact()
{
	KDialogBase *moveDialog= new KDialogBase( qApp->mainWidget(), "moveDialog" , true, i18n("Move Contact") , KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true )  ;
	QVBox *w = new QVBox(moveDialog);
	w->setSpacing( 8 );
	new QLabel(i18n("Choose the meta contact into which you want to move this contact.") , w);
	m_selectMetaContactListBox = new KListView ( w , "m_selectMetaContactListBox");
	m_selectMetaContactListBox->addColumn( i18n("Display Name") );
	m_selectMetaContactListBox->addColumn( i18n("Contact IDs") );

	QPtrList<KopeteMetaContact> metaContacts = KopeteContactList::contactList()->metaContacts();
	for( KopeteMetaContact *mc = metaContacts.first(); mc ; mc = metaContacts.next() )
	{
		if(!mc->isTemporary())
			new MetaContactListViewItem(mc , m_selectMetaContactListBox  ) ;
	}

	m_selectMetaContactListBox->sort();

	moveDialog->setMainWidget(w);
	connect( moveDialog, SIGNAL( okClicked()) , this, SLOT( slotMoveDialogOkClicked() ) );
	moveDialog->show();
}

void KopeteContact::slotMoveDialogOkClicked()
{
	KopeteMetaContact *mc= static_cast<MetaContactListViewItem*>( m_selectMetaContactListBox->currentItem() ) ->metaContact;
	if(!mc)
	{
		kdDebug(14010) << "KopeteContact::slotMoveDialogOkClicked : WARNING metaContact not found" << endl;
		return;
	}
	setMetaContact( mc );
}

void KopeteContact::setMetaContact( KopeteMetaContact *m )
{
	KopeteMetaContact *old = m_metaContact;
	m_metaContact->removeContact( this );
	m->addContact( this );

	KopeteGroupList newGroups = m->groups();
	KopeteGroupList oldGroups = m_metaContact->groups();
	KopeteGroupList currentGroups = groups();

	// Reparent the contact
	m_metaContact->removeChild( this );
	m->insertChild( this );
	m_metaContact = m;

	// Reconnect signals to the new meta contact
	disconnect( old, SIGNAL( aboutToSave( KopeteMetaContact * ) ),
		protocol(), SLOT( slotMetaContactAboutToSave( KopeteMetaContact * ) ) );
	connect( m_metaContact, SIGNAL( aboutToSave( KopeteMetaContact * ) ),
		protocol(), SLOT( slotMetaContactAboutToSave( KopeteMetaContact * ) ) );

	// Sync groups
	for( KopeteGroup *group = newGroups.first(); group; group = newGroups.next() )
	{
		if( !currentGroups.contains( group ) )
			addToGroup( group );
	}

	for( KopeteGroup *group = oldGroups.first(); group; group = oldGroups.next() )
	{
		if( currentGroups.contains( group ) && !newGroups.contains( group ) )
			removeFromGroup( group );
	}

	//the aboutToSave signal is disconnected from "old" , but it still contains
	//cached data in it, then, i serialize the old contact for removing old data
	protocol()->slotMetaContactAboutToSave(old);
}

KopeteContact::MetaContactListViewItem::MetaContactListViewItem(KopeteMetaContact *m, QListView *p)
		:QListViewItem(p)
{
	metaContact=m;
	setText( 0, m->displayName() );

	QString t;
	bool f=true;

	QPtrList<KopeteContact> contacts = metaContact->contacts();
	for( KopeteContact *c = contacts.first(); c ; c = contacts.next() )
	{
		if( f )
			t += QString::fromLatin1( "[ " );
		else
			t += QString::fromLatin1( " ; " );

		t += c->contactId();
		f = false;
	}
	if( !f )
		t += QString::fromLatin1( " ]" );

	setText( 1, t );
}

void KopeteContact::serialize( QMap<QString, QString> & /*serializedData */,
	QMap<QString, QString> & /* addressBookData */ )
{
	// Do nothing in the default implementation
}

void KopeteContact::setIdleState( KopeteContact::IdleState newState )
{
	m_idleState = newState;
	emit idleStateChanged( this, m_idleState );
}

void KopeteContact::addToGroup( KopeteGroup * /* newGroup */ )
{
	/* Default implementation does nothing */
}

void KopeteContact::removeFromGroup( KopeteGroup * /* group */ )
{
	/* Default implementation does nothing */
}

bool KopeteContact::isReachable()
{
	return false;
}

void KopeteContact::startChat()
{
	KopeteViewManager::viewManager()->launchWindow( manager(true), KopeteView::Chat);
}

void KopeteContact::sendMessage()
{
	KopeteViewManager::viewManager()->launchWindow( manager(true), KopeteView::Email);
}

void KopeteContact::execute()
{
	// FIXME: Implement, don't hardcode startChat()!
	startChat();
}

KopeteMessageManager *KopeteContact::manager( bool )
{
	kdDebug(14010) << "Manager() not implimented for " << protocol()->displayName() << ", crash!" << endl;
	return 0L;
}

void KopeteContact::slotDeleteContact()
{
	/* Default implementation does nothing */
}

void KopeteContact::slotUserInfo()
{
	/* Default implementation does nothing */
}

void KopeteContact::moveToGroup( KopeteGroup * /* from */, KopeteGroup * /* to */ )
{
	/* Default implementation does nothing */
}

KopeteGroupList KopeteContact::groups() const
{
	/* Default implementation does nothing */
	return KopeteGroupList();
}

#include "kopetecontact.moc"

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>Delete empty MCs after a merge<commit_after>/*
    kopetecontact.cpp - Kopete Contact

    Copyright (c) 2002      by Duncan Mac-Vicar Prett <duncan@kde.org>
    Copyright (c) 2002-2003 by Martijn Klingens       <klingens@kde.org>

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "kopetecontact.h"

#include <qapplication.h>
#include <qimage.h>
#include <qlabel.h>
#include <qpixmap.h>
#include <qregexp.h>
#include <qvbox.h>

#include <kdebug.h>
#include <kiconloader.h>
#include <klocale.h>
#include <kpopupmenu.h>
#include <kaction.h>
#include <klineeditdlg.h>
#include <kiconeffect.h>

#include "kopetecontactlist.h"
#include "kopetehistorydialog.h"
#include "kopetemetacontact.h"
#include "kopeteprotocol.h"
#include "kopetestdaction.h"
#include "kopeteviewmanager.h"

KopeteContact::KopeteContact( KopeteProtocol *protocol, const QString &contactId, KopeteMetaContact *parent )
: QObject( parent )
{
//	kdDebug() << "KopeteContact::KopeteContact: Creating contact with id " << contactId << endl;

	m_contactId = contactId;

	m_metaContact = parent;
	m_protocol = protocol;
	m_cachedSize = 0;
	m_cachedOldImportance = 0;
	contextMenu = 0L;
	mFileCapable = false;
	m_historyDialog = 0L;
	m_idleState = Unspecified;
	m_displayName = contactId;

	if( protocol )
	{
		protocol->registerContact( this );
		connect( protocol, SIGNAL( unloading() ), SLOT( slotProtocolUnloading() ) );
	}

	// Initialize the context menu
	actionSendMessage = KopeteStdAction::sendMessage( this,
		SLOT( sendMessage() ), this, "actionSendMessage" );
	actionChat = KopeteStdAction::chat( this,
		SLOT( startChat() ), this, "actionChat" );
	actionViewHistory = KopeteStdAction::viewHistory( this,
		SLOT( slotViewHistory() ), this, "actionViewHistory" );
	actionChangeMetaContact = KopeteStdAction::changeMetaContact( this,
		SLOT( slotChangeMetaContact() ), this, "actionChangeMetaContact" );
	actionDeleteContact = KopeteStdAction::deleteContact( this,
		SLOT( slotDeleteContact() ), this, "actionDeleteContact" );
	actionUserInfo = KopeteStdAction::contactInfo( this,
		SLOT( slotUserInfo() ), this, "actionUserInfo" );
	actionChangeAlias = KopeteStdAction::changeAlias( this,
		SLOT( slotChangeDisplayName() ), this, "actionChangeAlias" );
	actionSendFile = KopeteStdAction::sendFile( this,
		SLOT( sendFile() ), this, "actionSendFile");

	// Need to check this because myself() has no parent
	if( parent )
	{
		connect( parent, SIGNAL( aboutToSave( KopeteMetaContact * ) ),
			protocol, SLOT( slotMetaContactAboutToSave( KopeteMetaContact * ) ) );

		parent->addContact( this );
	}
}

KopeteContact::~KopeteContact()
{
	emit( contactDestroyed( this ) );
}

void KopeteContact::slotProtocolUnloading()
{
	delete this;
}

QString KopeteContact::identityId() const
{
	return QString::null;
}

void KopeteContact::rename( const QString &name )
{
	// Default implementation immediately sets the new name
	setDisplayName( name );
}

void KopeteContact::setDisplayName( const QString &name )
{
	if( name == m_displayName )
		return;

	m_displayName = name;
	emit displayNameChanged( name );
}

QString KopeteContact::displayName() const
{
	return m_displayName;
}

KopeteContact::ContactStatus KopeteContact::status() const
{
	return Online;
}

QString KopeteContact::statusText() const
{
	ContactStatus stat = status();

	//kdDebug(14010) << "[KopeteContact] statusText() with status= " << stat << endl;

	switch( stat )
	{
	case Online:
		return i18n("Online");
	case Away:
		return i18n("Away");
	case Unknown:
		return i18n("Status not available");
	case Offline:
	default:
		return i18n("Offline");
	}
}

QString KopeteContact::statusIcon() const
{
	return QString::fromLatin1( "unknown" );
}

QPixmap KopeteContact::scaledStatusIcon(int size)
{
	if ( (importance() != m_cachedOldImportance) || ( size != m_cachedSize ) )
	{
		QImage afScal = ((QPixmap(SmallIcon(statusIcon()))).convertToImage()).smoothScale( size, size );
		m_cachedScaledIcon = QPixmap(afScal);
		m_cachedOldImportance = importance();
		m_cachedSize = size;
	}
	if ( m_idleState == Idle )
	{
		QPixmap tmp = m_cachedScaledIcon;
		KIconEffect::semiTransparent(tmp);
		return tmp;
	}
	return m_cachedScaledIcon;
}

int KopeteContact::importance() const
{
	ContactStatus stat = status();

	if (stat == Online)
		return 20;

	if (stat == Away)
		return 10;

	if (stat == Offline)
		return 0;

	return 0;
}

void KopeteContact::slotViewHistory()
{
	kdDebug(14010) << "KopteContact::slotViewHistory()" << endl;

	if( m_historyDialog )
	{
		m_historyDialog->raise();
	}
	else
	{
		m_historyDialog = new KopeteHistoryDialog(this,
			true, 50, qApp->mainWidget(), "KopeteHistoryDialog" );

		connect ( m_historyDialog, SIGNAL( destroyed()),
			this, SLOT( slotHistoryDialogDestroyed() ) );
	}
}

void KopeteContact::slotHistoryDialogDestroyed()
{
	m_historyDialog = 0L;
}

void KopeteContact::sendFile( const KURL &, const QString &, const long unsigned int)
{
	kdDebug(14010) << "[KopeteContact] Opps, the plugin hasn't implemented file sending, yet it was turned on! :(" << endl;
}

KPopupMenu* KopeteContact::createContextMenu()
{
	//FIXME: this should perhaps be KActionCollection * KopeteContact::contactActions()
	//FIXME: to avoid passing around KPopupMenu's

	// Build the menu
	KPopupMenu *menu = new KPopupMenu();

	menu->insertTitle( QString::fromLatin1("%1 <%2> (%3)").arg(displayName()).arg(contactId()).arg(statusText()) );

	actionSendMessage->plug( menu );
	actionSendMessage->setEnabled( isReachable() );
	actionChat->plug( menu );
	actionChat->setEnabled( isReachable() );

	actionViewHistory->plug( menu );

	menu->insertSeparator();

	actionChangeMetaContact->setEnabled( !m_metaContact->isTemporary() );
	actionChangeMetaContact->plug( menu );
	actionUserInfo->plug( menu );
	actionChangeAlias->plug( menu );
	actionDeleteContact->plug( menu );

	if (mFileCapable)
		actionSendFile->plug( menu );

	// Protocol specific options will go below this separator
	// through the use of the customContextMenuActions() function

	// Get the custom actions from the protocols (pure virtual function)
	KActionCollection *customActions = customContextMenuActions();
	if(customActions != 0L)
	{
		if ( !customActions->isEmpty() )
			menu->insertSeparator();

		for(unsigned int i = 0; i < customActions->count(); i++)
		{
			customActions->action(i)->plug( menu );
		}
	}

	return menu;
}

KPopupMenu *KopeteContact::popupMenu()
{
	contextMenu = createContextMenu();
	return contextMenu;
}

void KopeteContact::showContextMenu(const QPoint& p)
{
	contextMenu = createContextMenu();
	contextMenu->exec( p );
	delete contextMenu;
	contextMenu = 0L;
}

void KopeteContact::slotChangeDisplayName(){
	bool okClicked;
	QString newName = KLineEditDlg::getText(i18n("Change Alias"), i18n("New alias for %1").arg(contactId()),
		displayName(), &okClicked);

	if(okClicked)
		setDisplayName( newName );
}

void KopeteContact::slotChangeMetaContact()
{
	KDialogBase *moveDialog= new KDialogBase( qApp->mainWidget(), "moveDialog" , true, i18n("Move Contact") , KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true )  ;
	QVBox *w = new QVBox(moveDialog);
	w->setSpacing( 8 );
	new QLabel(i18n("Choose the meta contact into which you want to move this contact.") , w);
	m_selectMetaContactListBox = new KListView ( w , "m_selectMetaContactListBox");
	m_selectMetaContactListBox->addColumn( i18n("Display Name") );
	m_selectMetaContactListBox->addColumn( i18n("Contact IDs") );

	QPtrList<KopeteMetaContact> metaContacts = KopeteContactList::contactList()->metaContacts();
	for( KopeteMetaContact *mc = metaContacts.first(); mc ; mc = metaContacts.next() )
	{
		if(!mc->isTemporary())
			new MetaContactListViewItem(mc , m_selectMetaContactListBox  ) ;
	}

	m_selectMetaContactListBox->sort();

	moveDialog->setMainWidget(w);
	connect( moveDialog, SIGNAL( okClicked()) , this, SLOT( slotMoveDialogOkClicked() ) );
	moveDialog->show();
}

void KopeteContact::slotMoveDialogOkClicked()
{
	KopeteMetaContact *mc= static_cast<MetaContactListViewItem*>( m_selectMetaContactListBox->currentItem() ) ->metaContact;
	if(!mc)
	{
		kdDebug(14010) << "KopeteContact::slotMoveDialogOkClicked : metaContact not found, will create a new one" << endl;
		return;
	}
	setMetaContact( mc );
}

void KopeteContact::setMetaContact( KopeteMetaContact *m )
{
	KopeteMetaContact *old = m_metaContact;
	m_metaContact->removeContact( this );
	m->addContact( this );

	KopeteGroupList newGroups = m->groups();
	KopeteGroupList oldGroups = m_metaContact->groups();
	KopeteGroupList currentGroups = groups();

	// Reparent the contact
	m_metaContact->removeChild( this );
	m->insertChild( this );
	m_metaContact = m;

	// Reconnect signals to the new meta contact
	disconnect( old, SIGNAL( aboutToSave( KopeteMetaContact * ) ),
		protocol(), SLOT( slotMetaContactAboutToSave( KopeteMetaContact * ) ) );
	connect( m_metaContact, SIGNAL( aboutToSave( KopeteMetaContact * ) ),
		protocol(), SLOT( slotMetaContactAboutToSave( KopeteMetaContact * ) ) );

	// Sync groups
	for( KopeteGroup *group = newGroups.first(); group; group = newGroups.next() )
	{
		if( !currentGroups.contains( group ) )
			addToGroup( group );
	}

	for( KopeteGroup *group = oldGroups.first(); group; group = oldGroups.next() )
	{
		if( currentGroups.contains( group ) && !newGroups.contains( group ) )
			removeFromGroup( group );
	}

	//the aboutToSave signal is disconnected from "old" , but it still contains
	//cached data in it, then, i serialize the old contact for removing old data
	protocol()->slotMetaContactAboutToSave(old);

	if( old->contacts().isEmpty() )
	{
		//Delete an empty MC after a move
		KopeteContactList::contactList()->removeMetaContact( old );
	}
}

KopeteContact::MetaContactListViewItem::MetaContactListViewItem(KopeteMetaContact *m, QListView *p)
		:QListViewItem(p)
{
	metaContact=m;
	setText( 0, m->displayName() );

	QString t;
	bool f=true;

	QPtrList<KopeteContact> contacts = metaContact->contacts();
	for( KopeteContact *c = contacts.first(); c ; c = contacts.next() )
	{
		if( f )
			t += QString::fromLatin1( "[ " );
		else
			t += QString::fromLatin1( " ; " );

		t += c->contactId();
		f = false;
	}
	if( !f )
		t += QString::fromLatin1( " ]" );

	setText( 1, t );
}

void KopeteContact::serialize( QMap<QString, QString> & /*serializedData */,
	QMap<QString, QString> & /* addressBookData */ )
{
	// Do nothing in the default implementation
}

void KopeteContact::setIdleState( KopeteContact::IdleState newState )
{
	m_idleState = newState;
	emit idleStateChanged( this, m_idleState );
}

void KopeteContact::addToGroup( KopeteGroup * /* newGroup */ )
{
	/* Default implementation does nothing */
}

void KopeteContact::removeFromGroup( KopeteGroup * /* group */ )
{
	/* Default implementation does nothing */
}

bool KopeteContact::isReachable()
{
	return false;
}

void KopeteContact::startChat()
{
	KopeteViewManager::viewManager()->launchWindow( manager(true), KopeteView::Chat);
}

void KopeteContact::sendMessage()
{
	KopeteViewManager::viewManager()->launchWindow( manager(true), KopeteView::Email);
}

void KopeteContact::execute()
{
	// FIXME: Implement, don't hardcode startChat()!
	startChat();
}

KopeteMessageManager *KopeteContact::manager( bool )
{
	kdDebug(14010) << "Manager() not implimented for " << protocol()->displayName() << ", crash!" << endl;
	return 0L;
}

void KopeteContact::slotDeleteContact()
{
	/* Default implementation does nothing */
}

void KopeteContact::slotUserInfo()
{
	/* Default implementation does nothing */
}

void KopeteContact::moveToGroup( KopeteGroup * /* from */, KopeteGroup * /* to */ )
{
	/* Default implementation does nothing */
}

KopeteGroupList KopeteContact::groups() const
{
	/* Default implementation does nothing */
	return KopeteGroupList();
}

#include "kopetecontact.moc"

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>// Copyright (c) 2015 G. Andrew Stone
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/lexical_cast.hpp>
#include <limits>

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "unlimitedmodel.h"

#include "bitcoinunits.h"
#include "guiutil.h"

#include "amount.h"
#include "init.h"
#include "main.h" // For DEFAULT_SCRIPTCHECK_THREADS
#include "net.h"
#include "tweak.h"
#include "txdb.h" // for -dbcache defaults

#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#endif

#include <QNetworkProxy>
#include <QSettings>
#include <QStringList>

extern CTweakRef<uint64_t> miningBlockSize;
extern CTweakRef<uint64_t> ebTweak;

UnlimitedModel::UnlimitedModel(QObject *parent) : QAbstractListModel(parent) { Init(); }
void UnlimitedModel::addOverriddenOption(const std::string &option)
{
    strOverriddenByCommandLine += QString::fromStdString(option) + "=" + QString::fromStdString(mapArgs[option]) + " ";
}

// Writes all missing QSettings with their default values
void UnlimitedModel::Init()
{
    QSettings settings;

    // Ensure restart flag is unset on client startup
    setRestartRequired(false);

    unsigned int tmpExcessiveBlockSize = excessiveBlockSize;
    unsigned int tmpMaxGeneratedBlock = maxGeneratedBlock;

    if (!settings.contains("excessiveBlockSize"))
        settings.setValue("excessiveBlockSize", QString::number(excessiveBlockSize));
    else
        tmpExcessiveBlockSize = settings.value("excessiveBlockSize").toInt();

    if (!settings.contains("excessiveAcceptDepth"))
        settings.setValue("excessiveAcceptDepth", QString::number(excessiveAcceptDepth));
    else
        excessiveAcceptDepth = settings.value("excessiveAcceptDepth").toInt();

    if (!settings.contains("maxGeneratedBlock"))
        settings.setValue("maxGeneratedBlock", QString::number(maxGeneratedBlock));
    else
        tmpMaxGeneratedBlock = settings.value("maxGeneratedBlock").toInt();

    if (!MiningAndExcessiveBlockValidatorRule(tmpExcessiveBlockSize, tmpMaxGeneratedBlock))
    {
        std::ostringstream emsg;
        emsg << "Sorry, your configured maximum mined block (" << tmpMaxGeneratedBlock
             << ") is larger than your configured excessive size (" << tmpExcessiveBlockSize
             << ").  This would cause you to orphan your own blocks.";
        LogPrintf(emsg.str().c_str());
    }
    else
    {
        miningBlockSize.Set(tmpMaxGeneratedBlock);
        ebTweak.Set(tmpExcessiveBlockSize);
    }

    if (!SoftSetArg("-excessiveblocksize", boost::lexical_cast<std::string>(excessiveBlockSize)))
        addOverriddenOption("-excessiveblocksize");
    if (!SoftSetArg("-excessiveacceptdepth", boost::lexical_cast<std::string>(excessiveAcceptDepth)))
        addOverriddenOption("-excessiveacceptdepth");

    bool inUse = settings.value("fUseReceiveShaping").toBool();
    int64_t burstKB = settings.value("nReceiveBurst").toLongLong();
    int64_t aveKB = settings.value("nReceiveAve").toLongLong();

    std::string avg = QString::number(inUse ? aveKB : std::numeric_limits<int64_t>::max()).toStdString();
    std::string burst = QString::number(inUse ? burstKB : std::numeric_limits<int64_t>::max()).toStdString();

    if (!SoftSetArg("-receiveavg", avg))
        addOverriddenOption("-receiveavg");
    if (!SoftSetArg("-receiveburst", burst))
        addOverriddenOption("-receiveburst");

    inUse = settings.value("fUseSendShaping").toBool();
    burstKB = settings.value("nSendBurst").toLongLong();
    aveKB = settings.value("nSendAve").toLongLong();

    avg = boost::lexical_cast<std::string>(inUse ? aveKB : std::numeric_limits<int64_t>::max());
    burst = boost::lexical_cast<std::string>(inUse ? burstKB : std::numeric_limits<int64_t>::max());

    if (!SoftSetArg("-sendavg", avg))
        addOverriddenOption("-sendavg");
    if (!SoftSetArg("-sendburst", burst))
        addOverriddenOption("-sendburst");
}

void UnlimitedModel::Reset()
{
    QSettings settings;

    // Remove all entries from our QSettings object
    settings.clear();

    // default setting for UnlimitedModel::StartAtStartup - disabled
    if (GUIUtil::GetStartOnSystemStartup())
        GUIUtil::SetStartOnSystemStartup(false);
}

int UnlimitedModel::rowCount(const QModelIndex &parent) const { return UOptIDRowCount; }
// read QSettings values and return them
QVariant UnlimitedModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::EditRole)
    {
        QSettings settings;
        switch (index.row())
        {
        case MaxGeneratedBlock:
            return QVariant((uint64_t)maxGeneratedBlock);
        case ExcessiveBlockSize:
            return QVariant((uint64_t)excessiveBlockSize);
        case ExcessiveAcceptDepth:
            return QVariant(excessiveAcceptDepth);
        case UseReceiveShaping:
            return settings.value("fUseReceiveShaping");
        case UseSendShaping:
            return settings.value("fUseSendShaping");
        case ReceiveBurst:
            return settings.value("nReceiveBurst");
        case ReceiveAve:
            return settings.value("nReceiveAve");
        case SendBurst:
            return settings.value("nSendBurst");
        case SendAve:
            return settings.value("nSendAve");
        default:
            return QVariant();
        }
    }
    return QVariant();
}

// write QSettings values
bool UnlimitedModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    bool successful = true; /* set to false on parse error */
    bool changeSendShaper = false;
    bool changeReceiveShaper = false;
    if (role == Qt::EditRole)
    {
        QSettings settings;
        switch (index.row())
        {
        case MaxGeneratedBlock:
        {
            unsigned int mgb = value.toUInt(&successful);
            if (successful && (settings.value("maxGeneratedBlock") != value))
            {
                settings.setValue("maxGeneratedBlock", value);
                miningBlockSize.Set(mgb);
            }
        }
        break;
        case ExcessiveBlockSize:
        {
            unsigned int ebs = value.toUInt(&successful);
            if (successful && (settings.value("excessiveBlockSize") != value))
            {
                settings.setValue("excessiveBlockSize", value);
                ebTweak.Set(ebs); // equivalant to: excessiveBlockSize = ebs;
            }
        }
        break;
        case ExcessiveAcceptDepth:
        {
            unsigned int ead = value.toUInt(&successful);
            if (successful && settings.value("excessiveAcceptDepth") != value)
            {
                settings.setValue("excessiveAcceptDepth", value);
                excessiveAcceptDepth = ead;
            }
        }
        break;
        case UseReceiveShaping:
            if (settings.value("fUseReceiveShaping") != value)
            {
                settings.setValue("fUseReceiveShaping", value);
                changeReceiveShaper = true;
            }
            break;
        case UseSendShaping:
            if (settings.value("fUseSendShaping") != value)
            {
                settings.setValue("fUseSendShaping", value);
                changeSendShaper = true;
            }
            break;
        case ReceiveBurst:
            if (settings.value("nReceiveBurst") != value)
            {
                settings.setValue("nReceiveBurst", value);
                changeReceiveShaper = true;
            }
            break;
        case ReceiveAve:
            if (settings.value("nReceiveAve") != value)
            {
                settings.setValue("nReceiveAve", value);
                changeReceiveShaper = true;
            }
            break;
        case SendBurst:
            if (settings.value("nSendBurst") != value)
            {
                settings.setValue("nSendBurst", value);
                changeSendShaper = true;
            }
            break;
        case SendAve:
            if (settings.value("nSendAve") != value)
            {
                settings.setValue("nSendAve", value);
                changeSendShaper = true;
            }
            break;
        default:
            break;
        }

        if (changeReceiveShaper)
        {
            if (settings.value("fUseReceiveShaping").toBool())
            {
                int64_t burst = 1024 * settings.value("nReceiveBurst").toLongLong();
                int64_t ave = 1024 * settings.value("nReceiveAve").toLongLong();
                receiveShaper.set(burst, ave);
            }
            else
                receiveShaper.disable();
        }

        if (changeSendShaper)
        {
            if (settings.value("fUseSendShaping").toBool())
            {
                int64_t burst = 1024 * settings.value("nSendBurst").toLongLong();
                int64_t ave = 1024 * settings.value("nSendAve").toLongLong();
                sendShaper.set(burst, ave);
            }
            else
                sendShaper.disable();
        }
    }

    Q_EMIT dataChanged(index, index);

    return successful;
}

void UnlimitedModel::setMaxGeneratedBlock(const QVariant &value)
{
    if (!value.isNull())
    {
        QSettings settings;
        maxGeneratedBlock = value.toInt();
        settings.setValue("maxGeneratedBlock", static_cast<qlonglong>(maxGeneratedBlock));
        // Q_EMIT your signal if you need one
    }
}

void UnlimitedModel::setRestartRequired(bool fRequired)
{
    QSettings settings;
    return settings.setValue("fRestartRequired", fRequired);
}

bool UnlimitedModel::isRestartRequired()
{
    QSettings settings;
    return settings.value("fRestartRequired", false).toBool();
}
<commit_msg>Use `qulonglong` rather than uint64_t per http://doc.qt.io/qt-5/qvariant.html<commit_after>// Copyright (c) 2015 G. Andrew Stone
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <boost/lexical_cast.hpp>
#include <limits>

#if defined(HAVE_CONFIG_H)
#include "config/bitcoin-config.h"
#endif

#include "unlimitedmodel.h"

#include "bitcoinunits.h"
#include "guiutil.h"

#include "amount.h"
#include "init.h"
#include "main.h" // For DEFAULT_SCRIPTCHECK_THREADS
#include "net.h"
#include "tweak.h"
#include "txdb.h" // for -dbcache defaults

#ifdef ENABLE_WALLET
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#endif

#include <QNetworkProxy>
#include <QSettings>
#include <QStringList>

extern CTweakRef<uint64_t> miningBlockSize;
extern CTweakRef<uint64_t> ebTweak;

UnlimitedModel::UnlimitedModel(QObject *parent) : QAbstractListModel(parent) { Init(); }
void UnlimitedModel::addOverriddenOption(const std::string &option)
{
    strOverriddenByCommandLine += QString::fromStdString(option) + "=" + QString::fromStdString(mapArgs[option]) + " ";
}

// Writes all missing QSettings with their default values
void UnlimitedModel::Init()
{
    QSettings settings;

    // Ensure restart flag is unset on client startup
    setRestartRequired(false);

    unsigned int tmpExcessiveBlockSize = excessiveBlockSize;
    unsigned int tmpMaxGeneratedBlock = maxGeneratedBlock;

    if (!settings.contains("excessiveBlockSize"))
        settings.setValue("excessiveBlockSize", QString::number(excessiveBlockSize));
    else
        tmpExcessiveBlockSize = settings.value("excessiveBlockSize").toInt();

    if (!settings.contains("excessiveAcceptDepth"))
        settings.setValue("excessiveAcceptDepth", QString::number(excessiveAcceptDepth));
    else
        excessiveAcceptDepth = settings.value("excessiveAcceptDepth").toInt();

    if (!settings.contains("maxGeneratedBlock"))
        settings.setValue("maxGeneratedBlock", QString::number(maxGeneratedBlock));
    else
        tmpMaxGeneratedBlock = settings.value("maxGeneratedBlock").toInt();

    if (!MiningAndExcessiveBlockValidatorRule(tmpExcessiveBlockSize, tmpMaxGeneratedBlock))
    {
        std::ostringstream emsg;
        emsg << "Sorry, your configured maximum mined block (" << tmpMaxGeneratedBlock
             << ") is larger than your configured excessive size (" << tmpExcessiveBlockSize
             << ").  This would cause you to orphan your own blocks.";
        LogPrintf(emsg.str().c_str());
    }
    else
    {
        miningBlockSize.Set(tmpMaxGeneratedBlock);
        ebTweak.Set(tmpExcessiveBlockSize);
    }

    if (!SoftSetArg("-excessiveblocksize", boost::lexical_cast<std::string>(excessiveBlockSize)))
        addOverriddenOption("-excessiveblocksize");
    if (!SoftSetArg("-excessiveacceptdepth", boost::lexical_cast<std::string>(excessiveAcceptDepth)))
        addOverriddenOption("-excessiveacceptdepth");

    bool inUse = settings.value("fUseReceiveShaping").toBool();
    int64_t burstKB = settings.value("nReceiveBurst").toLongLong();
    int64_t aveKB = settings.value("nReceiveAve").toLongLong();

    std::string avg = QString::number(inUse ? aveKB : std::numeric_limits<int64_t>::max()).toStdString();
    std::string burst = QString::number(inUse ? burstKB : std::numeric_limits<int64_t>::max()).toStdString();

    if (!SoftSetArg("-receiveavg", avg))
        addOverriddenOption("-receiveavg");
    if (!SoftSetArg("-receiveburst", burst))
        addOverriddenOption("-receiveburst");

    inUse = settings.value("fUseSendShaping").toBool();
    burstKB = settings.value("nSendBurst").toLongLong();
    aveKB = settings.value("nSendAve").toLongLong();

    avg = boost::lexical_cast<std::string>(inUse ? aveKB : std::numeric_limits<int64_t>::max());
    burst = boost::lexical_cast<std::string>(inUse ? burstKB : std::numeric_limits<int64_t>::max());

    if (!SoftSetArg("-sendavg", avg))
        addOverriddenOption("-sendavg");
    if (!SoftSetArg("-sendburst", burst))
        addOverriddenOption("-sendburst");
}

void UnlimitedModel::Reset()
{
    QSettings settings;

    // Remove all entries from our QSettings object
    settings.clear();

    // default setting for UnlimitedModel::StartAtStartup - disabled
    if (GUIUtil::GetStartOnSystemStartup())
        GUIUtil::SetStartOnSystemStartup(false);
}

int UnlimitedModel::rowCount(const QModelIndex &parent) const { return UOptIDRowCount; }
// read QSettings values and return them
QVariant UnlimitedModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::EditRole)
    {
        QSettings settings;
        switch (index.row())
        {
        case MaxGeneratedBlock:
            return QVariant((qulonglong)maxGeneratedBlock);
        case ExcessiveBlockSize:
            return QVariant((qulonglong)excessiveBlockSize);
        case ExcessiveAcceptDepth:
            return QVariant(excessiveAcceptDepth);
        case UseReceiveShaping:
            return settings.value("fUseReceiveShaping");
        case UseSendShaping:
            return settings.value("fUseSendShaping");
        case ReceiveBurst:
            return settings.value("nReceiveBurst");
        case ReceiveAve:
            return settings.value("nReceiveAve");
        case SendBurst:
            return settings.value("nSendBurst");
        case SendAve:
            return settings.value("nSendAve");
        default:
            return QVariant();
        }
    }
    return QVariant();
}

// write QSettings values
bool UnlimitedModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    bool successful = true; /* set to false on parse error */
    bool changeSendShaper = false;
    bool changeReceiveShaper = false;
    if (role == Qt::EditRole)
    {
        QSettings settings;
        switch (index.row())
        {
        case MaxGeneratedBlock:
        {
            unsigned int mgb = value.toUInt(&successful);
            if (successful && (settings.value("maxGeneratedBlock") != value))
            {
                settings.setValue("maxGeneratedBlock", value);
                miningBlockSize.Set(mgb);
            }
        }
        break;
        case ExcessiveBlockSize:
        {
            unsigned int ebs = value.toUInt(&successful);
            if (successful && (settings.value("excessiveBlockSize") != value))
            {
                settings.setValue("excessiveBlockSize", value);
                ebTweak.Set(ebs); // equivalant to: excessiveBlockSize = ebs;
            }
        }
        break;
        case ExcessiveAcceptDepth:
        {
            unsigned int ead = value.toUInt(&successful);
            if (successful && settings.value("excessiveAcceptDepth") != value)
            {
                settings.setValue("excessiveAcceptDepth", value);
                excessiveAcceptDepth = ead;
            }
        }
        break;
        case UseReceiveShaping:
            if (settings.value("fUseReceiveShaping") != value)
            {
                settings.setValue("fUseReceiveShaping", value);
                changeReceiveShaper = true;
            }
            break;
        case UseSendShaping:
            if (settings.value("fUseSendShaping") != value)
            {
                settings.setValue("fUseSendShaping", value);
                changeSendShaper = true;
            }
            break;
        case ReceiveBurst:
            if (settings.value("nReceiveBurst") != value)
            {
                settings.setValue("nReceiveBurst", value);
                changeReceiveShaper = true;
            }
            break;
        case ReceiveAve:
            if (settings.value("nReceiveAve") != value)
            {
                settings.setValue("nReceiveAve", value);
                changeReceiveShaper = true;
            }
            break;
        case SendBurst:
            if (settings.value("nSendBurst") != value)
            {
                settings.setValue("nSendBurst", value);
                changeSendShaper = true;
            }
            break;
        case SendAve:
            if (settings.value("nSendAve") != value)
            {
                settings.setValue("nSendAve", value);
                changeSendShaper = true;
            }
            break;
        default:
            break;
        }

        if (changeReceiveShaper)
        {
            if (settings.value("fUseReceiveShaping").toBool())
            {
                int64_t burst = 1024 * settings.value("nReceiveBurst").toLongLong();
                int64_t ave = 1024 * settings.value("nReceiveAve").toLongLong();
                receiveShaper.set(burst, ave);
            }
            else
                receiveShaper.disable();
        }

        if (changeSendShaper)
        {
            if (settings.value("fUseSendShaping").toBool())
            {
                int64_t burst = 1024 * settings.value("nSendBurst").toLongLong();
                int64_t ave = 1024 * settings.value("nSendAve").toLongLong();
                sendShaper.set(burst, ave);
            }
            else
                sendShaper.disable();
        }
    }

    Q_EMIT dataChanged(index, index);

    return successful;
}

void UnlimitedModel::setMaxGeneratedBlock(const QVariant &value)
{
    if (!value.isNull())
    {
        QSettings settings;
        maxGeneratedBlock = value.toInt();
        settings.setValue("maxGeneratedBlock", static_cast<qlonglong>(maxGeneratedBlock));
        // Q_EMIT your signal if you need one
    }
}

void UnlimitedModel::setRestartRequired(bool fRequired)
{
    QSettings settings;
    return settings.setValue("fRestartRequired", fRequired);
}

bool UnlimitedModel::isRestartRequired()
{
    QSettings settings;
    return settings.value("fRestartRequired", false).toBool();
}
<|endoftext|>


<commit_before>/*
 * PatternMatch.cc
 *
 * Linas Vepstas February 2008
 */

#include "Foreach.h"
#include "ForeachTwo.h"
#include "Link.h"
#include "Node.h"
#include "PatternMatch.h"
#include "TLB.h"

using namespace opencog;

PatternMatch::PatternMatch(AtomSpace *as)
{
	atom_space = as;
}

bool PatternMatch::prt(Atom *atom)
{
	if (!atom) return false;
	std::string str = atom->toString();
	printf ("%s\n", str.c_str());
	return false;
}

bool PatternMatch::prt(Handle h)
{
	return prt(TLB::getAtom(h));
}

/* ======================================================== */

/**
 * tree_compare compares two trees, side-by-side.
 *
 * Compare two incidence trees, side-by-side. It is assumed
 * that the first of these is the predicate, and so the
 * comparison is between the predicate, and a candidate
 * graph.
 *
 * The graph/tree refered to here is the incidence
 * graph/tree (aka Levi graph) of the hypergraph.
 * (and not the hypergraph itself).
 * The incidence graph is given by the "outgoing set"
 * of the atom.
 *
 * This routine is recursive, calling itself on each
 * subtree of the predicate, performing comparisions until
 * a match is found (or not found).
 *
 * Return true if there's a mis-match. The goal here
 * is to iterate the entire tree, without mismatches.
 * Since a return value of true stops the iteration,
 * true is used to signal a mistmatch.
 */
bool PatternMatch::tree_compare(Atom *aa, Atom *ab)
{
	Handle ha = TLB::getHandle(aa);

	// Atom aa is from the predicate, and it might be one
	// of the bound variables. If so, then declare a match.
	if (bound_vars.count(ha))
	{
		// If ab is the very same var, then its a mismatch.
		if (aa == ab) return true;

		// Else, we have a candidate solution.
		// Make a record of it.
		var_solution[ha] = ab;
		return false;
	}

	// If they're the same atom, then clearly they match.
	// ... but only if ab is not one of the predicates itself.
	if ((aa == ab) && (ab != curr_root))
	{
		var_solution[ha] = ab;
		return false;
	}

	// If one is null, but the other is not, there's clearly no match.
	if (aa && !ab) return true;
	if (ab && !aa) return true;

	// If types differ, then no match.
	if (aa->getType() != ab->getType()) return true;

	// printf ("tree_compare depth=%d comp "); prt(aa);
	// printf ("                       to "); prt(ab);

	// The recursion step: traverse down the tree.
	// Only links should have non-empty outgoing sets.
	if (dynamic_cast<Link *>(aa))
	{
		Handle hb = TLB::getHandle(ab);

		depth ++;
		bool mismatch = foreach_outgoing_atom_pair(ha, hb,
		              	      &PatternMatch::tree_compare, this);
		depth --;
		if (false == mismatch) var_solution[ha] = ab;
		// printf("tree_comp down link mismatch=%d\n", mismatch);
		return mismatch;
	}

	// Call the callback to make the final determination.
	bool mismatch = pmc->node_match(aa, ab);
	if (false == mismatch) var_solution[ha] = ab;
	return mismatch;
}

/* ======================================================== */

bool PatternMatch::soln_up(Handle hsoln)
{
	Atom *as = TLB::getAtom(hsoln);
	Atom *ap = TLB::getAtom(curr_pred_handle);
	depth = 1;
	bool no_match = tree_compare(ap, as);

	// If no match, try the next one.
	if (no_match) return false;

	curr_soln_handle = TLB::getHandle(as);

	// Ahh ! found a match!  If we've navigated to the top of the
	// predicate, then we're done with it.  Look for the next
	// unsovled predicate.
	if (curr_pred_handle == curr_root)
	{

		root_handle_stack.push(curr_root);
		pred_handle_stack.push(curr_pred_handle);
		soln_handle_stack.push(curr_soln_handle);
		pred_solutn_stack.push(predicate_solution);

		predicate_solution[curr_root] = curr_soln_handle;
		// printf("--------------------- \npred: "); prt(curr_root);
		// printf("soln: "); prt(curr_soln_handle);

		get_next_unsolved_pred();

		// printf("next handle is "); prt(curr_pred_handle);
		// printf("next pred is "); prt(curr_root);

		// If there are no further predicates to solve,
		// we are really done! Return true to terminate the search.
		if (UNDEFINED_HANDLE == curr_root)
		{
			// printf ("==================== FINITO!\n");
			return pmc->solution(predicate_solution, var_solution);
		}

		curr_soln_handle = var_solution[curr_pred_handle];
		bool found = soln_up(curr_soln_handle);

		// If we failed to find anything at this level,
		// we need to pop, and try other possible matches.
		if (!found)
		{
			curr_root = root_handle_stack.top();
			root_handle_stack.pop();

			curr_pred_handle = pred_handle_stack.top();
			pred_handle_stack.pop();

			curr_soln_handle = soln_handle_stack.top();
			soln_handle_stack.pop();

			predicate_solution = pred_solutn_stack.top();
			pred_solutn_stack.pop();
		}

		return found;
	}

	// printf("node has soln, move up: "); prt(as);

	// Move up the predicate, and hunt for a match, again.
	bool found = foreach_incoming_handle(curr_pred_handle,
	                &PatternMatch::pred_up, this);
	// printf("up pred find =%d\n", found);
	return found;
}

bool PatternMatch::pred_up(Handle h)
{
	// Is this atom even a part of the predicate we are considering?
	// If not, try the next atom.
	bool valid = ot.is_node_in_tree(curr_root, h);
	if (!valid) return false;

	// Now, move up the solution outgoing set, looking for a match.
	curr_pred_handle = h;

	bool found = foreach_incoming_handle(curr_soln_handle,
	                     &PatternMatch::soln_up, this);

	// printf("upward soln find =%d\n", found);
	return found;
}

void PatternMatch::get_next_unsolved_pred(void)
{
	// Search for an as-yet unsolved/unmatched predicate.
	// For each solved node, look up root to see if root is solved.
	// If not, start working on that.
	Handle pursue = UNDEFINED_HANDLE;
	Handle unsolved_pred = UNDEFINED_HANDLE;
	RootMap::iterator k;
	for (k=root_map.begin(); k != root_map.end(); k++)
	{
		RootPair vk = *k;
		RootList *rl = vk.second;
		pursue = vk.first;

		bool unsolved = false;
		bool solved = false;

		std::vector<Handle>::iterator i;
		for (i=rl->begin(); i != rl->end(); i++)
		{
			Handle root = *i;
			if(predicate_solution[root] != NULL)
			{
				solved = true;
			}
			else
			{
				unsolved_pred = root;
				unsolved = true;
			}
		}
		if (solved && unsolved) break;
	}

	// pursue is a pointer to a node that's shared between
	// several predicates. One of the predicates has been
	// solved, another has not.  We want to now traverse
	// upwards from this node, to find the top of the
	// unsolved predicate.
	curr_root = unsolved_pred;
	curr_pred_handle = pursue;
}

/* ======================================================== */
/**
 * do_candidate - examine candidates, looking for matches.
 *
 * This routine is invoked on every candidate atom taken from
 * the atom space. That atom is assumed to anchor some part of
 * a graph that hopefully will match the predicate.
 */
bool PatternMatch::do_candidate(Handle ah)
{
	// Don't stare at our navel.
	std::vector<Handle>::iterator i;
	for (i = normed_predicate.begin(); i != normed_predicate.end(); i++)
	{
		if (ah == *i) return false;
	}

	// Cleanup
	predicate_solution.clear();
	var_solution.clear();
	while(!pred_handle_stack.empty()) pred_handle_stack.pop();
	while(!soln_handle_stack.empty()) soln_handle_stack.pop();
	while(!root_handle_stack.empty()) root_handle_stack.pop();
	while(!pred_solutn_stack.empty()) pred_solutn_stack.pop();

	curr_root = normed_predicate[0];
	curr_pred_handle = curr_root;
	bool found = soln_up(ah);

	// If found is false, then there's no solution here.
	// Bail out, return false to try again with the next candidate.
	return found;
}

/**
 * Create an associative array that gives a list of all of the
 * predicatees that a given node participates in.
 */
bool PatternMatch::note_root(Handle h)
{
	RootList *rl = root_map[h];
	if (NULL == rl)
	{
		rl = new RootList();
		root_map[h] = rl;
	}
	rl->push_back(curr_root);

	foreach_outgoing_handle(h, &PatternMatch::note_root, this);
	return false;
}

/**
 * Solve a predicate.
 * Its understood that the input "graph" is a predicate, of sorts,
 * with the list of "bound vars" are to be solved for (or "evaluated")
 * bound vars must be, by definition, Nodes.
 */
void PatternMatch::match(PatternMatchCallback *cb,
                         std::vector<Handle> *preds,
                         std::vector<Handle> *vars)
{
	std::vector<Handle>::const_iterator i;

	normed_predicate = *preds;

	for (i = vars->begin();
	     i != vars->end(); i++)
	{
		Handle h = *i;
		bound_vars.insert(h);
	}

	var_solution.clear();
	predicate_solution.clear();

	if (normed_predicate.size() == 0) return;

	// Preparation prior to search.
	// Create a table of nodes in the predicates, with
	// a list of the predicates that each node participates in.
	root_map.clear();
	for (i = normed_predicate.begin();
	     i != normed_predicate.end(); i++)
	{
		Handle h = *i;
		curr_root = h;
		note_root(h);
	}
	pmc = cb;

#if 0
	// Print out the predicate ...
	printf("\nPredicate is\n");
	std::vector<Handle>::iterator i;
	for (i = normed_predicate.begin();
	     i != normed_predicate.end(); i++)
	{
		foreach_outgoing_atom(*i, &PatternMatch::prt, this);
	}

	// Print out the bound variables in the predicate.
	std::set<Handle>::const_iterator j;
	for (j=bound_vars.begin(); j != bound_vars.end(); j++)
	{
		Handle h = *j;
		Atom *a = TLB::getAtom(h);
		Node *n = dynamic_cast<Node *>(a);
		if (n)
		{
			printf(" bound var: %s\n", n->getName().c_str());
		}
	}
#endif

	// Get type of the first item in the predicate list.
	Handle h = normed_predicate[0];
	Atom *a = TLB::getAtom(h);
	Type ptype = a->getType();

	// Plunge into the deep end - start looking at all viable
	// candidates in the AtomSpace.
	foreach_handle_of_type(atom_space, ptype,
	      &PatternMatch::do_candidate, this);

}

void PatternMatch::print_solution(std::map<Handle, Handle> &preds,
                                  std::map<Handle, Handle> &vars)
{
#if 0
	printf("\nSolution variable bindings:\n");

	// Print out the bindings of solutions to variables.
	std::set<Handle>::const_iterator j;
	for (j=bound_vars.begin(); j != bound_vars.end(); j++)
	{
		Handle var = *j;
		Handle soln = vars[var];
		Atom *av = TLB::getAtom(var);
		Atom *as = TLB::getAtom(soln);
		Node *nv = dynamic_cast<Node *>(av);
		Node *ns = dynamic_cast<Node *>(as);
		if (ns && nv)
		{
			printf("var %s solved by %s\n",
			       nv->getName().c_str(), ns->getName().c_str());
		}
	}
#endif

	// Print out the full binding to all of the preds.
	printf("\nFull solution:\n");
	std::map<Handle, Handle>::const_iterator m;
	for (m = preds.begin(); m != preds.end(); m++)
	{
		std::pair<Handle, Handle> pm = *m;
		prt(pm.second);
	}
	fflush(stdout);
}

/* ===================== END OF FILE ===================== */
<commit_msg>more misc cleanup<commit_after>/*
 * PatternMatch.cc
 *
 * Linas Vepstas February 2008
 */

#include "Foreach.h"
#include "ForeachTwo.h"
#include "Link.h"
#include "Node.h"
#include "PatternMatch.h"
#include "TLB.h"

using namespace opencog;

PatternMatch::PatternMatch(AtomSpace *as)
{
	atom_space = as;
}

bool PatternMatch::prt(Atom *atom)
{
	if (!atom) return false;
	std::string str = atom->toString();
	printf ("%s\n", str.c_str());
	return false;
}

bool PatternMatch::prt(Handle h)
{
	return prt(TLB::getAtom(h));
}

/* ======================================================== */

/**
 * tree_compare compares two trees, side-by-side.
 *
 * Compare two incidence trees, side-by-side. It is assumed
 * that the first of these is the predicate, and so the
 * comparison is between the predicate, and a candidate
 * graph.
 *
 * The graph/tree refered to here is the incidence
 * graph/tree (aka Levi graph) of the hypergraph.
 * (and not the hypergraph itself).
 * The incidence graph is given by the "outgoing set"
 * of the atom.
 *
 * This routine is recursive, calling itself on each
 * subtree of the predicate, performing comparisions until
 * a match is found (or not found).
 *
 * Return true if there's a mis-match. The goal here
 * is to iterate the entire tree, without mismatches.
 * Since a return value of true stops the iteration,
 * true is used to signal a mistmatch.
 */
bool PatternMatch::tree_compare(Atom *aa, Atom *ab)
{
	Handle ha = TLB::getHandle(aa);

	// Atom aa is from the predicate, and it might be one
	// of the bound variables. If so, then declare a match.
	if (bound_vars.count(ha))
	{
		// If ab is the very same var, then its a mismatch.
		if (aa == ab) return true;

		// Else, we have a candidate solution.
		// Make a record of it.
		var_solution[ha] = ab;
		return false;
	}

	// If they're the same atom, then clearly they match.
	// ... but only if ab is not one of the predicates itself.
	if ((aa == ab) && (ab != curr_root))
	{
		var_solution[ha] = ab;
		return false;
	}

	// If one is null, but the other is not, there's clearly no match.
	if (aa && !ab) return true;
	if (ab && !aa) return true;

	// If types differ, then no match.
	if (aa->getType() != ab->getType()) return true;

	// printf ("tree_compare depth=%d comp "); prt(aa);
	// printf ("                       to "); prt(ab);

	// The recursion step: traverse down the tree.
	// Only links should have non-empty outgoing sets.
	if (dynamic_cast<Link *>(aa))
	{
		Handle hb = TLB::getHandle(ab);

		depth ++;
		bool mismatch = foreach_outgoing_atom_pair(ha, hb,
		              	      &PatternMatch::tree_compare, this);
		depth --;
		if (false == mismatch) var_solution[ha] = ab;
		// printf("tree_comp down link mismatch=%d\n", mismatch);
		return mismatch;
	}

	// Call the callback to make the final determination.
	bool mismatch = pmc->node_match(aa, ab);
	if (false == mismatch) var_solution[ha] = ab;
	return mismatch;
}

/* ======================================================== */

bool PatternMatch::soln_up(Handle hsoln)
{
	Atom *as = TLB::getAtom(hsoln);
	Atom *ap = TLB::getAtom(curr_pred_handle);
	depth = 1;
	bool no_match = tree_compare(ap, as);

	// If no match, try the next one.
	if (no_match) return false;

	curr_soln_handle = TLB::getHandle(as);

	// Ahh ! found a match!  If we've navigated to the top of the
	// predicate, then we're done with it.  Look for the next
	// unsovled predicate.
	if (curr_pred_handle == curr_root)
	{

		root_handle_stack.push(curr_root);
		pred_handle_stack.push(curr_pred_handle);
		soln_handle_stack.push(curr_soln_handle);
		pred_solutn_stack.push(predicate_solution);

		predicate_solution[curr_root] = curr_soln_handle;
		// printf("--------------------- \npred: "); prt(curr_root);
		// printf("soln: "); prt(curr_soln_handle);

		get_next_unsolved_pred();

		// printf("next handle is "); prt(curr_pred_handle);
		// printf("next pred is "); prt(curr_root);

		// If there are no further predicates to solve,
		// we are really done! Report the solution via callback.
		bool found = false;
		if (UNDEFINED_HANDLE == curr_root)
		{
			// printf ("==================== FINITO!\n");
			found = pmc->solution(predicate_solution, var_solution);
		}
		else
		{
			curr_soln_handle = var_solution[curr_pred_handle];
			found = soln_up(curr_soln_handle);
		}

		// If we failed to find anything at this level,
		// we need to pop, and try other possible matches.
		if (!found)
		{
			curr_root = root_handle_stack.top();
			root_handle_stack.pop();

			curr_pred_handle = pred_handle_stack.top();
			pred_handle_stack.pop();

			curr_soln_handle = soln_handle_stack.top();
			soln_handle_stack.pop();

			predicate_solution = pred_solutn_stack.top();
			pred_solutn_stack.pop();
		}

		return found;
	}

	// printf("node has soln, move up: "); prt(as);

	// Move up the predicate, and hunt for a match, again.
	bool found = foreach_incoming_handle(curr_pred_handle,
	                &PatternMatch::pred_up, this);
	// printf("up pred find =%d\n", found);
	return found;
}

bool PatternMatch::pred_up(Handle h)
{
	// Is this atom even a part of the predicate we are considering?
	// If not, try the next atom.
	bool valid = ot.is_node_in_tree(curr_root, h);
	if (!valid) return false;

	// Now, move up the solution outgoing set, looking for a match.
	curr_pred_handle = h;

	bool found = foreach_incoming_handle(curr_soln_handle,
	                     &PatternMatch::soln_up, this);

	// printf("upward soln find =%d\n", found);
	return found;
}

void PatternMatch::get_next_unsolved_pred(void)
{
	// Search for an as-yet unsolved/unmatched predicate.
	// For each solved node, look up root to see if root is solved.
	// If not, start working on that.
	Handle pursue = UNDEFINED_HANDLE;
	Handle unsolved_pred = UNDEFINED_HANDLE;
	RootMap::iterator k;
	for (k=root_map.begin(); k != root_map.end(); k++)
	{
		RootPair vk = *k;
		RootList *rl = vk.second;
		pursue = vk.first;

		bool unsolved = false;
		bool solved = false;

		std::vector<Handle>::iterator i;
		for (i=rl->begin(); i != rl->end(); i++)
		{
			Handle root = *i;
			if(predicate_solution[root] != NULL)
			{
				solved = true;
			}
			else
			{
				unsolved_pred = root;
				unsolved = true;
			}
		}
		if (solved && unsolved) break;
	}

	// pursue is a pointer to a node that's shared between
	// several predicates. One of the predicates has been
	// solved, another has not.  We want to now traverse
	// upwards from this node, to find the top of the
	// unsolved predicate.
	curr_root = unsolved_pred;
	curr_pred_handle = pursue;
}

/* ======================================================== */
/**
 * do_candidate - examine candidates, looking for matches.
 *
 * This routine is invoked on every candidate atom taken from
 * the atom space. That atom is assumed to anchor some part of
 * a graph that hopefully will match the predicate.
 */
bool PatternMatch::do_candidate(Handle ah)
{
	// Don't stare at our navel.
	std::vector<Handle>::iterator i;
	for (i = normed_predicate.begin(); i != normed_predicate.end(); i++)
	{
		if (ah == *i) return false;
	}

	// Cleanup
	predicate_solution.clear();
	var_solution.clear();
	while(!pred_handle_stack.empty()) pred_handle_stack.pop();
	while(!soln_handle_stack.empty()) soln_handle_stack.pop();
	while(!root_handle_stack.empty()) root_handle_stack.pop();
	while(!pred_solutn_stack.empty()) pred_solutn_stack.pop();

	curr_root = normed_predicate[0];
	curr_pred_handle = curr_root;
	bool found = soln_up(ah);

	// If found is false, then there's no solution here.
	// Bail out, return false to try again with the next candidate.
	return found;
}

/**
 * Create an associative array that gives a list of all of the
 * predicatees that a given node participates in.
 */
bool PatternMatch::note_root(Handle h)
{
	RootList *rl = root_map[h];
	if (NULL == rl)
	{
		rl = new RootList();
		root_map[h] = rl;
	}
	rl->push_back(curr_root);

	foreach_outgoing_handle(h, &PatternMatch::note_root, this);
	return false;
}

/**
 * Solve a predicate.
 * Its understood that the input "graph" is a predicate, of sorts,
 * with the list of "bound vars" are to be solved for (or "evaluated")
 * bound vars must be, by definition, Nodes.
 */
void PatternMatch::match(PatternMatchCallback *cb,
                         std::vector<Handle> *preds,
                         std::vector<Handle> *vars)
{
	std::vector<Handle>::const_iterator i;

	normed_predicate = *preds;

	for (i = vars->begin();
	     i != vars->end(); i++)
	{
		Handle h = *i;
		bound_vars.insert(h);
	}

	var_solution.clear();
	predicate_solution.clear();

	if (normed_predicate.size() == 0) return;

	// Preparation prior to search.
	// Create a table of nodes in the predicates, with
	// a list of the predicates that each node participates in.
	root_map.clear();
	for (i = normed_predicate.begin();
	     i != normed_predicate.end(); i++)
	{
		Handle h = *i;
		curr_root = h;
		note_root(h);
	}
	pmc = cb;

#ifdef DEBUG
	// Print out the predicate ...
	printf("\nPredicate is\n");
	std::vector<Handle>::iterator i;
	for (i = normed_predicate.begin();
	     i != normed_predicate.end(); i++)
	{
		foreach_outgoing_atom(*i, &PatternMatch::prt, this);
	}

	// Print out the bound variables in the predicate.
	std::set<Handle>::const_iterator j;
	for (j=bound_vars.begin(); j != bound_vars.end(); j++)
	{
		Handle h = *j;
		Atom *a = TLB::getAtom(h);
		Node *n = dynamic_cast<Node *>(a);
		if (n)
		{
			printf(" bound var: "); prt(a);
		}
	}
#endif

	// Get type of the first item in the predicate list.
	Handle h = normed_predicate[0];
	Atom *a = TLB::getAtom(h);
	Type ptype = a->getType();

	// Plunge into the deep end - start looking at all viable
	// candidates in the AtomSpace.
	foreach_handle_of_type(atom_space, ptype,
	      &PatternMatch::do_candidate, this);

}

void PatternMatch::print_solution(std::map<Handle, Handle> &preds,
                                  std::map<Handle, Handle> &vars)
{
	printf("\nSolution variable bindings:\n");

	// Print out the bindings of solutions to variables.
	std::map<Handle, Handle>::const_iterator j;
	for (j=vars.begin(); j != vars.end(); j++)
	{
		std::pair<Handle, Handle> pv = *j;
		Handle var = pv.first;
		Handle soln = pv.second;
		Atom *av = TLB::getAtom(var);
		Atom *as = TLB::getAtom(soln);
		Node *nv = dynamic_cast<Node *>(av);
		Node *ns = dynamic_cast<Node *>(as);
		if (ns && nv)
		{
			printf("var %s solved by %s\n",
			       nv->getName().c_str(), ns->getName().c_str());
		}
	}

	// Print out the full binding to all of the preds.
	printf("\nFull solution:\n");
	std::map<Handle, Handle>::const_iterator m;
	for (m = preds.begin(); m != preds.end(); m++)
	{
		std::pair<Handle, Handle> pm = *m;
		prt(pm.second);
	}
	fflush(stdout);
}

/* ===================== END OF FILE ===================== */
<|endoftext|>


<commit_before>/**
 * @file   Tblas.cpp
 * @brief  Tblas class implementation.
 * @author zer0
 * @date   2017-11-03
 */

#include <libtbag/math/blas/Tblas.hpp>
#include <libtbag/log/Log.hpp>

#include <openblas/cblas.h>

#if defined(TBAG_PLATFORM_WINDOWS)
# include <windows.h>
BOOL APIENTRY openblas_DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
#else
# include <libtbag/dummy/Win32.hpp>
using namespace ::libtbag::dummy::win32;
BOOL openblas_DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{ return TRUE; }
#endif

// -------------------
NAMESPACE_LIBTBAG_OPEN
// -------------------

namespace math {
namespace blas {

int openblas_dll_main(void * module, unsigned long reason, void * reserved)
{
    return openblas_DllMain((HMODULE)module, (DWORD)reason, (LPVOID)reserved);
}

void openblas_set_num_threads(int num_threads)
{
    ::openblas_set_num_threads(num_threads);
}

void goto_set_num_threads(int num_threads)
{
    ::goto_set_num_threads(num_threads);
}

int openblas_get_num_threads()
{
    return ::openblas_get_num_threads();
}

int openblas_get_num_procs()
{
    return ::openblas_get_num_procs();
}

char const * openblas_get_config()
{
    return ::openblas_get_config();
}

char const * openblas_get_corename()
{
    return ::openblas_get_corename();
}

int openblas_get_parallel()
{
    return ::openblas_get_parallel();
}

} // namespace blas
} // namespace math

// --------------------
NAMESPACE_LIBTBAG_CLOSE
// --------------------

<commit_msg>Remove openblas_DllMain() method.<commit_after>/**
 * @file   Tblas.cpp
 * @brief  Tblas class implementation.
 * @author zer0
 * @date   2017-11-03
 */

#include <libtbag/math/blas/Tblas.hpp>
#include <libtbag/log/Log.hpp>

#include <openblas/cblas.h>

//#if defined(TBAG_PLATFORM_WINDOWS)
//# include <windows.h>
//BOOL APIENTRY openblas_DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved);
//#else
//# include <libtbag/dummy/Win32.hpp>
//using namespace ::libtbag::dummy::win32;
//BOOL openblas_DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
//{ return TRUE; }
//#endif

// -------------------
NAMESPACE_LIBTBAG_OPEN
// -------------------

namespace math {
namespace blas {

int openblas_dll_main(void * module, unsigned long reason, void * reserved)
{
    //return openblas_DllMain((HMODULE)module, (DWORD)reason, (LPVOID)reserved);
    return 0;
}

void openblas_set_num_threads(int num_threads)
{
    ::openblas_set_num_threads(num_threads);
}

void goto_set_num_threads(int num_threads)
{
    ::goto_set_num_threads(num_threads);
}

int openblas_get_num_threads()
{
    return ::openblas_get_num_threads();
}

int openblas_get_num_procs()
{
    return ::openblas_get_num_procs();
}

char const * openblas_get_config()
{
    return ::openblas_get_config();
}

char const * openblas_get_corename()
{
    return ::openblas_get_corename();
}

int openblas_get_parallel()
{
    return ::openblas_get_parallel();
}

} // namespace blas
} // namespace math

// --------------------
NAMESPACE_LIBTBAG_CLOSE
// --------------------

<|endoftext|>