<commit_before>/*
    addcontactwizard.h - Kopete's Add Contact Wizard

    Copyright (c) 2003 by Will Stephenson        <will@stevello.free-online.co.uk>
    Copyright (c) 2002 by Nick Betcher           <nbetcher@kde.org>
    Copyright (c) 2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Kopete    (c) 2002-2004 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.                                   *
    *                                                                       *
    *************************************************************************
*/
//	CONDITIONS FOR PROGRESSING:
//	Welcome page
//		true
//	|
//	V
//	Select Address Book Entry
//		( Addressee is selected AND is not already associated with a contact )
//			OR Do not use address book is checked
//	|
//	V
//	Select Display Name and Group
//		true
//	|
//	V
//	Select Account
//		( Only 1 account ) OR ( An account is selected )
//	|
//	V
//	(Each AddContactPage)
//		( Own conditions)
//	|
//	V
//	Finish
//		true

#include <qcheckbox.h>
#include <klocale.h>
#include <kiconloader.h>

#include <kdeversion.h>
#include <kinputdialog.h>
#include <kinputdialog.h>

#include <kpushbutton.h>
#include <kdebug.h>
#include <klistview.h>
// used for its AddresseeItem class
#include <kabc/addresseedialog.h>
#include <kabc/addressbook.h>
#include <kabc/stdaddressbook.h>

#include <addcontactpage.h>
#include "addcontactwizard.h"
#include "kopetecontactlist.h"
#include "kopetemetacontact.h"
#include "kopeteaccountmanager.h"
#include "kopeteaccount.h"
#include "kopetegroup.h"

AddContactWizard::AddContactWizard( QWidget *parent, const char *name )
: AddContactWizard_Base( parent, name )
{
	m_addressBook = 0L;  // so we can tell if it's already loaded

	// Populate the groups list
	KopeteGroupList groups=KopeteContactList::contactList()->groups();
	for( KopeteGroup *it = groups.first(); it; it = groups.next() )
	{
		QString groupname = it->displayName();
		if ( !groupname.isEmpty() )
			m_groupItems.insert(new QCheckListItem( groupList, groupname, QCheckListItem::CheckBox) , it ) ;
	}

	protocolListView->clear();
	m_accountItems.clear();

	// Populate the accounts list
	QCheckListItem* accountLVI=0L;
	QPtrList<KopeteAccount>  accounts = KopeteAccountManager::manager()->accounts();
	for(KopeteAccount *i=accounts.first() ; i; i=accounts.next() )
	{
		accountLVI= new QCheckListItem( protocolListView, i->accountId(), QCheckListItem::CheckBox);
		accountLVI->setText(1,i->protocol()->displayName() + QString::fromLatin1(" ") );
		//FIXME - I'm not sure the column 1 is a right place for the colored icon -Olivier
		accountLVI->setPixmap( 1, i->accountIcon() );
		m_accountItems.insert(accountLVI,i);
	}

	if ( accounts.count() == 1 )
	{
		accountLVI->setOn( true );
		setAppropriate( selectService, false );
	}

	setNextEnabled( selectService, ( accounts.count() == 1 ) );
	setNextEnabled( selectAddressee, false );
	setFinishEnabled( finis, true );

	// Addressee validation connections
	connect( addAddresseeButton, SIGNAL( clicked() ), SLOT( slotAddAddresseeClicked() ) );
	connect( chkAddressee, SIGNAL( toggled( bool ) ),
			SLOT( slotCheckAddresseeChoice( bool ) ) );
	connect( addresseeListView, SIGNAL( clicked(QListViewItem * ) ),
			SLOT( slotAddresseeListClicked( QListViewItem * ) ) );
	connect( addresseeListView, SIGNAL( selectionChanged( QListViewItem * ) ),
			SLOT( slotAddresseeListClicked( QListViewItem * ) ) );
	connect( addresseeListView, SIGNAL( spacePressed( QListViewItem * ) ),
			SLOT( slotAddresseeListClicked( QListViewItem * ) ) );

	// Group manipulation connection
	connect( addGroupButton, SIGNAL(clicked()) , SLOT(slotAddGroupClicked()) );

	// Account choice validation connections
	connect( protocolListView, SIGNAL(clicked(QListViewItem *)), this, SLOT(slotProtocolListClicked(QListViewItem *)));
	connect( protocolListView, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(slotProtocolListClicked(QListViewItem *)));
	connect( protocolListView, SIGNAL(spacePressed(QListViewItem *)), this, SLOT(slotProtocolListClicked(QListViewItem *)));
}

AddContactWizard::~AddContactWizard()
{
}

void AddContactWizard::slotLoadAddressees()
{
	addresseeListView->clear();
	KABC::AddressBook::Iterator it;
	for( it = m_addressBook->begin(); it != m_addressBook->end(); ++it )
		/*KABC::AddresseeItem *item =*/ new KABC::AddresseeItem( addresseeListView, (*it) );
}

void AddContactWizard::slotAddAddresseeClicked()
{
	// Pop up add addressee dialog
	QString addresseeName = KInputDialog::getText( i18n( "New Address Book Entry" ),
												   i18n( "Name the new entry:" ),
												   QString::null, 0, this );

	if ( !addresseeName.isEmpty() )
	{
		KABC::Addressee addr;
		addr.setNameFromString( addresseeName );
		m_addressBook->insertAddressee( addr );
		KABC::Ticket *ticket = m_addressBook->requestSaveTicket();
		if ( !ticket )
		{
			kdError() << "Resource is locked by other application!" << endl;
		}
		else
		{
			if ( !m_addressBook->save( ticket ) )
			{
				kdError() << "Saving failed!" << endl;
#if KDE_IS_VERSION (3,1,90)
				m_addressBook->releaseSaveTicket( ticket );
#endif
			}
		}
	}
}

void AddContactWizard::slotCheckAddresseeChoice( bool on )
{
	setAppropriate( selectAddressee, on );
	if ( on )
	{
		// Get a reference to the address book
		if ( !m_addressBook )
		{
			m_addressBook = KABC::StdAddressBook::self( true );
			KABC::StdAddressBook::setAutomaticSave( false );
		}
		disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ),
										   this, SLOT( slotLoadAddressees() ) );
		connect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ),
										this, SLOT( slotLoadAddressees() ) );
	}
	else
		disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ),
										   this, SLOT( slotLoadAddressees() ) );
}

void AddContactWizard::slotAddresseeListClicked( QListViewItem *addressee )
{
	// enable next if a valid addressee is selected
	setNextEnabled( selectAddressee, addressee ? addressee->isSelected() : false );

	if ( KABC::AddresseeItem* i = static_cast<KABC::AddresseeItem *>( addressee ) )
		mDisplayName->setText( i->addressee().realName() );
}

void AddContactWizard::slotAddGroupClicked()
{
	QString groupName = KInputDialog::getText(
		i18n( "New Group" ),
		i18n( "Please enter the name for the new group:" )
		);
	if ( !groupName.isNull() )
		( new QCheckListItem( groupList, groupName, QCheckListItem::CheckBox ) )->setOn( true );
}

void AddContactWizard::slotProtocolListClicked( QListViewItem *)
{
	// Just makes sure a protocol is selected before allowing the user to continue
	bool oneIsChecked = false;

	for (QListViewItemIterator it(protocolListView); it.current(); ++it)
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>(it.current());
		if (check && check->isOn())
		{
			oneIsChecked = true;
			break;
		}
	}
	kdDebug( 0 ) << k_funcinfo << "setting next enabled: " << oneIsChecked << endl;
	setNextEnabled(selectService, oneIsChecked);
}

void AddContactWizard::accept()
{
	KopeteMetaContact *metaContact = new KopeteMetaContact();

	// set the display name if required
	if ( !mDisplayName->text().isEmpty() )
	{
		metaContact->setTrackChildNameChanges( false );
		metaContact->setDisplayName( mDisplayName->text() );
	}
	// NOT SURE IF I MEANT TO TAKE THIS OUT - WILL
	//// set the KABC uid in the metacontact
	KABC::AddresseeItem *item = 0L;
	item = static_cast<KABC::AddresseeItem *>( addresseeListView->selectedItem() );
	if ( addresseeListView->isEnabled() && item )
		metaContact->setMetaContactId( item->addressee().uid() );

	// set the metacontact's groups
	bool topLevel = true;
	for ( QListViewItemIterator it( groupList ); it.current(); ++it )
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>( it.current() );
		if ( check && check->isOn() )
		{
			if(m_groupItems.contains(check))
				metaContact->addToGroup(m_groupItems[check]);
			else //it's a new group
				metaContact->addToGroup( KopeteContactList::contactList()->getGroup( check->text() ) );
			topLevel = false;
		}
	}
	if(topLevel)
		metaContact->addToGroup( KopeteGroup::topLevel() );

	bool ok = protocolPages.isEmpty();

	// get each protocol's contact
	QMap <KopeteAccount*,AddContactPage*>::Iterator it;
	for ( it = protocolPages.begin(); it != protocolPages.end(); ++it )
		ok |= it.data()->apply( it.key(), metaContact );

	if ( ok )
	{
		// set the KABC uid in the metacontact
		KABC::AddresseeItem* i = 0L;
		i = static_cast<KABC::AddresseeItem *>( addresseeListView->selectedItem() );
		if ( addresseeListView->isEnabled() && i )
			metaContact->setMetaContactId( i->addressee().uid() );
		// add it to the contact list
		KopeteContactList::contactList()->addMetaContact( metaContact );
	}
	else
		delete metaContact;

	disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) );

	deleteLater();
}

void AddContactWizard::reject()
{
	disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) );
	QWizard::reject();
}

void AddContactWizard::next()
{
	// If the we're on the select account page
	// follow it with the add contact pages for
	// the chosen protocols
	if (currentPage() == selectService ||
		(currentPage() == intro && !appropriate( selectService )))
	{
		QMap <KopeteAccount*,AddContactPage*>::Iterator it;
		for ( it = protocolPages.begin(); it != protocolPages.end(); ++it )
		{
			delete it.data();
		}
		protocolPages.clear();

		// We don't keep track of this pointer because it gets deleted when the wizard does (which is what we want)
		for (QListViewItemIterator it(protocolListView); it.current(); ++it)
		{
			QCheckListItem *item = dynamic_cast<QCheckListItem *>(it.current());
			if (item && item->isOn())
			{
				// this shouldn't happen either, but I hate crashes
				if (!m_accountItems[item])
					continue;

				AddContactPage *addPage = m_accountItems[item]->protocol()->createAddContactWidget(this, m_accountItems[item] );
				if (!addPage)
					continue;

				connect(addPage, SIGNAL(dataValid( AddContactPage *, bool )),
					this, SLOT( slotDataValid( AddContactPage *, bool )));
				kdDebug( 14000 ) << k_funcinfo << "Connected slotDataValid" << endl;
				addPage->show();

				insertPage( addPage, i18n( "The account name is prepended here",
					"%1 Contact Information" ).arg( item->text(0) ), indexOf( finis ) );
				protocolPages.insert( m_accountItems[item] , addPage );
			}
		}
		QWizard::next();
		kdDebug( 14000 ) << k_funcinfo << "On next page after selectService" << endl;
		return;
	}

	// If we're not on any account specific pages,
	// we must be on an add account page, so make sure it validates
	if (currentPage() != intro &&
		currentPage() != selectAddressee &&
		currentPage() != selectService &&
		currentPage() != selectGroup &&
		currentPage() != finis)
	{
		AddContactPage *ePage = dynamic_cast<AddContactPage *>(currentPage());
		if (!ePage || !ePage->validateData())
			return;
	}

	QWizard::next();
}

void AddContactWizard::showPage( QWidget *page )
{
	if ( page == intro )
	{
		// make sure the first page's Next is always enabled
		setNextEnabled( page, true);
		if ( chkAddressee->isChecked() && addresseeListView->firstChild() == 0 ) // We must check this as we might be showing this page because the back button was pressed
		{
			// Get a reference to the address book
			if ( m_addressBook == 0L )
			{
				m_addressBook = KABC::StdAddressBook::self( true );
				KABC::StdAddressBook::setAutomaticSave( false );
			}
			disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) );
			connect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) );
			slotLoadAddressees();
		}
	}
	QWizard::showPage( page );
}

void AddContactWizard::slotDataValid(AddContactPage *onPage, bool bOn)
{
	// some plugins emit dataValid when they are not visible.
	// so we need to enable the page which is signalling, not just the current page
	setNextEnabled( onPage, bOn);
}

#include "addcontactwizard.moc"

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

<commit_msg>'cvs diff twice, commit once' as my dad says: remove unnecessary debug output. CVS_SILENT<commit_after>/*
    addcontactwizard.h - Kopete's Add Contact Wizard

    Copyright (c) 2003 by Will Stephenson        <will@stevello.free-online.co.uk>
    Copyright (c) 2002 by Nick Betcher           <nbetcher@kde.org>
    Copyright (c) 2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Kopete    (c) 2002-2004 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.                                   *
    *                                                                       *
    *************************************************************************
*/
//	CONDITIONS FOR PROGRESSING:
//	Welcome page
//		true
//	|
//	V
//	Select Address Book Entry
//		( Addressee is selected AND is not already associated with a contact )
//			OR Do not use address book is checked
//	|
//	V
//	Select Display Name and Group
//		true
//	|
//	V
//	Select Account
//		( Only 1 account ) OR ( An account is selected )
//	|
//	V
//	(Each AddContactPage)
//		( Own conditions)
//	|
//	V
//	Finish
//		true

#include <qcheckbox.h>
#include <klocale.h>
#include <kiconloader.h>

#include <kdeversion.h>
#include <kinputdialog.h>
#include <kinputdialog.h>

#include <kpushbutton.h>
#include <kdebug.h>
#include <klistview.h>
// used for its AddresseeItem class
#include <kabc/addresseedialog.h>
#include <kabc/addressbook.h>
#include <kabc/stdaddressbook.h>

#include <addcontactpage.h>
#include "addcontactwizard.h"
#include "kopetecontactlist.h"
#include "kopetemetacontact.h"
#include "kopeteaccountmanager.h"
#include "kopeteaccount.h"
#include "kopetegroup.h"

AddContactWizard::AddContactWizard( QWidget *parent, const char *name )
: AddContactWizard_Base( parent, name )
{
	m_addressBook = 0L;  // so we can tell if it's already loaded

	// Populate the groups list
	KopeteGroupList groups=KopeteContactList::contactList()->groups();
	for( KopeteGroup *it = groups.first(); it; it = groups.next() )
	{
		QString groupname = it->displayName();
		if ( !groupname.isEmpty() )
			m_groupItems.insert(new QCheckListItem( groupList, groupname, QCheckListItem::CheckBox) , it ) ;
	}

	protocolListView->clear();
	m_accountItems.clear();

	// Populate the accounts list
	QCheckListItem* accountLVI=0L;
	QPtrList<KopeteAccount>  accounts = KopeteAccountManager::manager()->accounts();
	for(KopeteAccount *i=accounts.first() ; i; i=accounts.next() )
	{
		accountLVI= new QCheckListItem( protocolListView, i->accountId(), QCheckListItem::CheckBox);
		accountLVI->setText(1,i->protocol()->displayName() + QString::fromLatin1(" ") );
		//FIXME - I'm not sure the column 1 is a right place for the colored icon -Olivier
		accountLVI->setPixmap( 1, i->accountIcon() );
		m_accountItems.insert(accountLVI,i);
	}

	if ( accounts.count() == 1 )
	{
		accountLVI->setOn( true );
		setAppropriate( selectService, false );
	}

	setNextEnabled( selectService, ( accounts.count() == 1 ) );
	setNextEnabled( selectAddressee, false );
	setFinishEnabled( finis, true );

	// Addressee validation connections
	connect( addAddresseeButton, SIGNAL( clicked() ), SLOT( slotAddAddresseeClicked() ) );
	connect( chkAddressee, SIGNAL( toggled( bool ) ),
			SLOT( slotCheckAddresseeChoice( bool ) ) );
	connect( addresseeListView, SIGNAL( clicked(QListViewItem * ) ),
			SLOT( slotAddresseeListClicked( QListViewItem * ) ) );
	connect( addresseeListView, SIGNAL( selectionChanged( QListViewItem * ) ),
			SLOT( slotAddresseeListClicked( QListViewItem * ) ) );
	connect( addresseeListView, SIGNAL( spacePressed( QListViewItem * ) ),
			SLOT( slotAddresseeListClicked( QListViewItem * ) ) );

	// Group manipulation connection
	connect( addGroupButton, SIGNAL(clicked()) , SLOT(slotAddGroupClicked()) );

	// Account choice validation connections
	connect( protocolListView, SIGNAL(clicked(QListViewItem *)), this, SLOT(slotProtocolListClicked(QListViewItem *)));
	connect( protocolListView, SIGNAL(selectionChanged(QListViewItem *)), this, SLOT(slotProtocolListClicked(QListViewItem *)));
	connect( protocolListView, SIGNAL(spacePressed(QListViewItem *)), this, SLOT(slotProtocolListClicked(QListViewItem *)));
}

AddContactWizard::~AddContactWizard()
{
}

void AddContactWizard::slotLoadAddressees()
{
	addresseeListView->clear();
	KABC::AddressBook::Iterator it;
	for( it = m_addressBook->begin(); it != m_addressBook->end(); ++it )
		/*KABC::AddresseeItem *item =*/ new KABC::AddresseeItem( addresseeListView, (*it) );
}

void AddContactWizard::slotAddAddresseeClicked()
{
	// Pop up add addressee dialog
	QString addresseeName = KInputDialog::getText( i18n( "New Address Book Entry" ),
												   i18n( "Name the new entry:" ),
												   QString::null, 0, this );

	if ( !addresseeName.isEmpty() )
	{
		KABC::Addressee addr;
		addr.setNameFromString( addresseeName );
		m_addressBook->insertAddressee( addr );
		KABC::Ticket *ticket = m_addressBook->requestSaveTicket();
		if ( !ticket )
		{
			kdError() << "Resource is locked by other application!" << endl;
		}
		else
		{
			if ( !m_addressBook->save( ticket ) )
			{
				kdError() << "Saving failed!" << endl;
#if KDE_IS_VERSION (3,1,90)
				m_addressBook->releaseSaveTicket( ticket );
#endif
			}
		}
	}
}

void AddContactWizard::slotCheckAddresseeChoice( bool on )
{
	setAppropriate( selectAddressee, on );
	if ( on )
	{
		// Get a reference to the address book
		if ( !m_addressBook )
		{
			m_addressBook = KABC::StdAddressBook::self( true );
			KABC::StdAddressBook::setAutomaticSave( false );
		}
		disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ),
										   this, SLOT( slotLoadAddressees() ) );
		connect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ),
										this, SLOT( slotLoadAddressees() ) );
	}
	else
		disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ),
										   this, SLOT( slotLoadAddressees() ) );
}

void AddContactWizard::slotAddresseeListClicked( QListViewItem *addressee )
{
	// enable next if a valid addressee is selected
	setNextEnabled( selectAddressee, addressee ? addressee->isSelected() : false );

	if ( KABC::AddresseeItem* i = static_cast<KABC::AddresseeItem *>( addressee ) )
		mDisplayName->setText( i->addressee().realName() );
}

void AddContactWizard::slotAddGroupClicked()
{
	QString groupName = KInputDialog::getText(
		i18n( "New Group" ),
		i18n( "Please enter the name for the new group:" )
		);
	if ( !groupName.isNull() )
		( new QCheckListItem( groupList, groupName, QCheckListItem::CheckBox ) )->setOn( true );
}

void AddContactWizard::slotProtocolListClicked( QListViewItem *)
{
	// Just makes sure a protocol is selected before allowing the user to continue
	bool oneIsChecked = false;

	for (QListViewItemIterator it(protocolListView); it.current(); ++it)
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>(it.current());
		if (check && check->isOn())
		{
			oneIsChecked = true;
			break;
		}
	}
	setNextEnabled(selectService, oneIsChecked);
}

void AddContactWizard::accept()
{
	KopeteMetaContact *metaContact = new KopeteMetaContact();

	// set the display name if required
	if ( !mDisplayName->text().isEmpty() )
	{
		metaContact->setTrackChildNameChanges( false );
		metaContact->setDisplayName( mDisplayName->text() );
	}
	// NOT SURE IF I MEANT TO TAKE THIS OUT - WILL
	//// set the KABC uid in the metacontact
	KABC::AddresseeItem *item = 0L;
	item = static_cast<KABC::AddresseeItem *>( addresseeListView->selectedItem() );
	if ( addresseeListView->isEnabled() && item )
		metaContact->setMetaContactId( item->addressee().uid() );

	// set the metacontact's groups
	bool topLevel = true;
	for ( QListViewItemIterator it( groupList ); it.current(); ++it )
	{
		QCheckListItem *check = dynamic_cast<QCheckListItem *>( it.current() );
		if ( check && check->isOn() )
		{
			if(m_groupItems.contains(check))
				metaContact->addToGroup(m_groupItems[check]);
			else //it's a new group
				metaContact->addToGroup( KopeteContactList::contactList()->getGroup( check->text() ) );
			topLevel = false;
		}
	}
	if(topLevel)
		metaContact->addToGroup( KopeteGroup::topLevel() );

	bool ok = protocolPages.isEmpty();

	// get each protocol's contact
	QMap <KopeteAccount*,AddContactPage*>::Iterator it;
	for ( it = protocolPages.begin(); it != protocolPages.end(); ++it )
		ok |= it.data()->apply( it.key(), metaContact );

	if ( ok )
	{
		// set the KABC uid in the metacontact
		KABC::AddresseeItem* i = 0L;
		i = static_cast<KABC::AddresseeItem *>( addresseeListView->selectedItem() );
		if ( addresseeListView->isEnabled() && i )
			metaContact->setMetaContactId( i->addressee().uid() );
		// add it to the contact list
		KopeteContactList::contactList()->addMetaContact( metaContact );
	}
	else
		delete metaContact;

	disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) );

	deleteLater();
}

void AddContactWizard::reject()
{
	disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) );
	QWizard::reject();
}

void AddContactWizard::next()
{
	// If the we're on the select account page
	// follow it with the add contact pages for
	// the chosen protocols
	if (currentPage() == selectService ||
		(currentPage() == intro && !appropriate( selectService )))
	{
		QMap <KopeteAccount*,AddContactPage*>::Iterator it;
		for ( it = protocolPages.begin(); it != protocolPages.end(); ++it )
		{
			delete it.data();
		}
		protocolPages.clear();

		// We don't keep track of this pointer because it gets deleted when the wizard does (which is what we want)
		for (QListViewItemIterator it(protocolListView); it.current(); ++it)
		{
			QCheckListItem *item = dynamic_cast<QCheckListItem *>(it.current());
			if (item && item->isOn())
			{
				// this shouldn't happen either, but I hate crashes
				if (!m_accountItems[item])
					continue;

				AddContactPage *addPage = m_accountItems[item]->protocol()->createAddContactWidget(this, m_accountItems[item] );
				if (!addPage)
					continue;

				connect(addPage, SIGNAL(dataValid( AddContactPage *, bool )),
					this, SLOT( slotDataValid( AddContactPage *, bool )));
				addPage->show();

				insertPage( addPage, i18n( "The account name is prepended here",
					"%1 Contact Information" ).arg( item->text(0) ), indexOf( finis ) );
				protocolPages.insert( m_accountItems[item] , addPage );
			}
		}
		QWizard::next();
		return;
	}

	// If we're not on any account specific pages,
	// we must be on an add account page, so make sure it validates
	if (currentPage() != intro &&
		currentPage() != selectAddressee &&
		currentPage() != selectService &&
		currentPage() != selectGroup &&
		currentPage() != finis)
	{
		AddContactPage *ePage = dynamic_cast<AddContactPage *>(currentPage());
		if (!ePage || !ePage->validateData())
			return;
	}

	QWizard::next();
}

void AddContactWizard::showPage( QWidget *page )
{
	if ( page == intro )
	{
		// make sure the first page's Next is always enabled
		setNextEnabled( page, true);
		if ( chkAddressee->isChecked() && addresseeListView->firstChild() == 0 ) // We must check this as we might be showing this page because the back button was pressed
		{
			// Get a reference to the address book
			if ( m_addressBook == 0L )
			{
				m_addressBook = KABC::StdAddressBook::self( true );
				KABC::StdAddressBook::setAutomaticSave( false );
			}
			disconnect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) );
			connect( m_addressBook, SIGNAL( addressBookChanged( AddressBook * ) ), this, SLOT( slotLoadAddressees() ) );
			slotLoadAddressees();
		}
	}
	QWizard::showPage( page );
}

void AddContactWizard::slotDataValid(AddContactPage *onPage, bool bOn)
{
	// some plugins emit dataValid when they are not visible.
	// so we need to enable the page which is signalling, not just the current page
	setNextEnabled( onPage, bOn);
}

#include "addcontactwizard.moc"

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

<|endoftext|>


<commit_before>/*

Copyright (c) 2015, Project OSRM contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef ROUND_TRIP_HPP
#define ROUND_TRIP_HPP

#include "plugin_base.hpp"

#include "../algorithms/object_encoder.hpp"
#include "../data_structures/query_edge.hpp"
#include "../data_structures/search_engine.hpp"
#include "../descriptors/descriptor_base.hpp"
#include "../descriptors/json_descriptor.hpp"
#include "../util/json_renderer.hpp"
#include "../util/make_unique.hpp"
#include "../util/string_util.hpp"
#include "../util/timing_util.hpp"
#include "../util/simple_logger.hpp"

#include <osrm/json_container.hpp>

#include <cstdlib>

#include <algorithm>
#include <memory>
#include <unordered_map>
#include <string>
#include <vector>
#include <limits>

template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
{
  private:
    std::string descriptor_string;
    DataFacadeT *facade;
    std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;

    void NearestNeighbour(const RouteParameters & route_parameters,
                          const PhantomNodeArray & phantom_node_vector,
                          std::vector<EdgeWeight> & dist_table,
                          InternalRouteResult & min_route,
                          std::vector<int> & min_loc_permutation) {
        //////////////////////////////////////////////////////////////////////////////////////////////////
        // START GREEDY NEAREST NEIGHBOUR HERE
        // 1. grab a random location and mark as starting point
        // 2. find the nearest unvisited neighbour, set it as the current location and mark as visited
        // 3. repeat 2 until there is no unvisited location
        // 4. return route back to starting point
        // 5. compute route
        // 6. repeat 1-5 with different starting points and choose iteration with shortest trip
        // 6. DONE!
        //////////////////////////////////////////////////////////////////////////////////////////////////

        const auto number_of_locations = phantom_node_vector.size();
        min_route.shortest_path_length = std::numeric_limits<int>::max();

        // is_lonely_island[i] indicates whether node i is a node that cannot be reached from other nodes
        //  1 means that node i is a lonely island
        //  0 means that it is not known for node i
        // -1 means that node i is not a lonely island but a reachable, connected node
        std::vector<int> is_lonely_island(number_of_locations, 0);
        int count_unreachables;

        // ALWAYS START AT ANOTHER STARTING POINT
        for(int start_node = 0; start_node < number_of_locations; ++start_node)
        {

            if (is_lonely_island[start_node] >= 0)
            {
                // if node is a lonely island it is an unsuitable node to start from and shall be skipped
                if (is_lonely_island[start_node])
                    continue;
                count_unreachables = 0;
                auto start_dist_begin = dist_table.begin() + (start_node * number_of_locations);
                auto start_dist_end = dist_table.begin() + ((start_node + 1) * number_of_locations);
                for (auto it2 = start_dist_begin; it2 != start_dist_end; ++it2) {
                    if (*it2 == 0 || *it2 == std::numeric_limits<int>::max()) {
                        ++count_unreachables;
                    }
                }
                if (count_unreachables >= number_of_locations) {
                    is_lonely_island[start_node] = 1;
                    continue;
                }
            }

            int curr_node = start_node;
            is_lonely_island[curr_node] = -1;
            InternalRouteResult raw_route;
            //TODO: Should we always use the same vector or does it not matter at all because of loop scope?
            std::vector<int> loc_permutation(number_of_locations, -1);
            loc_permutation[start_node] = 0;
            // visited[i] indicates whether node i was already visited by the salesman
            std::vector<bool> visited(number_of_locations, false);
            visited[start_node] = true;

            PhantomNodes viapoint;
            // 3. REPEAT FOR EVERY UNVISITED NODE
            for(int via_point = 1; via_point < number_of_locations; ++via_point)
            {
                int min_dist = std::numeric_limits<int>::max();
                int min_id = -1;

                // 2. FIND NEAREST NEIGHBOUR
                auto row_begin_iterator = dist_table.begin() + (curr_node * number_of_locations);
                auto row_end_iterator = dist_table.begin() + ((curr_node + 1) * number_of_locations);
                for (auto it = row_begin_iterator; it != row_end_iterator; ++it) {
                    auto index = std::distance(row_begin_iterator, it);
                    if (is_lonely_island[index] < 1 && !visited[index] && *it < min_dist)
                    {
                        min_dist = *it;
                        min_id = index;
                    }
                }
                // in case there was no unvisited and reachable node found, it means that all remaining (unvisited) nodes must be lonely islands
                if (min_id == -1)
                {
                    for(int loc = 0; loc < visited.size(); ++loc) {
                        if (!visited[loc]) {
                            is_lonely_island[loc] = 1;
                        }
                    }
                    break;
                }
                // set the nearest unvisited location as the next via_point
                else
                {
                    is_lonely_island[min_id] = -1;
                    loc_permutation[min_id] = via_point;
                    visited[min_id] = true;
                    viapoint = PhantomNodes{phantom_node_vector[curr_node][0], phantom_node_vector[min_id][0]};
                    raw_route.segment_end_coordinates.emplace_back(viapoint);
                    curr_node = min_id;
                }
            }

            // 4. ROUTE BACK TO STARTING POINT
            viapoint = PhantomNodes{raw_route.segment_end_coordinates.back().target_phantom, phantom_node_vector[start_node][0]};
            raw_route.segment_end_coordinates.emplace_back(viapoint);

            // 5. COMPUTE ROUTE
            search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, route_parameters.uturns, raw_route);

            // check round trip with this starting point is shorter than the shortest round trip found till now
            if (raw_route.shortest_path_length < min_route.shortest_path_length) {
                min_route = raw_route;
                min_loc_permutation = loc_permutation;
            }
        }

        SimpleLogger().Write() << "Shortest route " << min_route.shortest_path_length;
    }

  public:
    explicit RoundTripPlugin(DataFacadeT *facade)
        : descriptor_string("trip"), facade(facade)
    {
        search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
    }

    const std::string GetDescriptor() const override final { return descriptor_string; }

    int HandleRequest(const RouteParameters &route_parameters,
                      osrm::json::Object &json_result) override final
    {
        // check if all inputs are coordinates
        if (!check_all_coordinates(route_parameters.coordinates))
        {
            return 400;
        }
        const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());

        // find phantom nodes for all input coords
        PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size());
        for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size()))
        {
            // if client hints are helpful, encode hints
            if (checksum_OK && i < route_parameters.hints.size() &&
                !route_parameters.hints[i].empty())
            {
                PhantomNode current_phantom_node;
                ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node);
                if (current_phantom_node.is_valid(facade->GetNumberOfNodes()))
                {
                    phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
                    continue;
                }
            }
            facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
                                                            phantom_node_vector[i], 1);
            if (phantom_node_vector[i].size() > 1)
            {
                phantom_node_vector[i].erase(phantom_node_vector[i].begin());
            }
            BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
        }

        // compute the distance table of all phantom nodes
        const std::shared_ptr<std::vector<EdgeWeight>> result_table =
            search_engine_ptr->distance_table(phantom_node_vector);

        if (!result_table)
        {
            return 400;
        }

        // compute TSP round trip
        InternalRouteResult min_route;
        std::vector<int> min_loc_permutation;
        NearestNeighbour(route_parameters, phantom_node_vector, *result_table, min_route, min_loc_permutation);

        // return result to json
        std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
        descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);

        descriptor->SetConfig(route_parameters);
        descriptor->Run(min_route, json_result);

        osrm::json::Array json_loc_permutation;
        json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
        json_result.values["loc_permutation"] = json_loc_permutation;

        return 200;
    }

};

#endif // ROUND_TRIP_HPP
<commit_msg>add timer to check runtime of round trip algorithm<commit_after>/*

Copyright (c) 2015, Project OSRM contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef ROUND_TRIP_HPP
#define ROUND_TRIP_HPP

#include "plugin_base.hpp"

#include "../algorithms/object_encoder.hpp"
#include "../data_structures/query_edge.hpp"
#include "../data_structures/search_engine.hpp"
#include "../descriptors/descriptor_base.hpp"
#include "../descriptors/json_descriptor.hpp"
#include "../util/json_renderer.hpp"
#include "../util/make_unique.hpp"
#include "../util/string_util.hpp"
#include "../util/timing_util.hpp"
#include "../util/simple_logger.hpp"

#include <osrm/json_container.hpp>

#include <cstdlib>

#include <algorithm>
#include <memory>
#include <unordered_map>
#include <string>
#include <vector>
#include <limits>

template <class DataFacadeT> class RoundTripPlugin final : public BasePlugin
{
  private:
    std::string descriptor_string;
    DataFacadeT *facade;
    std::unique_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;

    void NearestNeighbour(const RouteParameters & route_parameters,
                          const PhantomNodeArray & phantom_node_vector,
                          std::vector<EdgeWeight> & dist_table,
                          InternalRouteResult & min_route,
                          std::vector<int> & min_loc_permutation) {
        //////////////////////////////////////////////////////////////////////////////////////////////////
        // START GREEDY NEAREST NEIGHBOUR HERE
        // 1. grab a random location and mark as starting point
        // 2. find the nearest unvisited neighbour, set it as the current location and mark as visited
        // 3. repeat 2 until there is no unvisited location
        // 4. return route back to starting point
        // 5. compute route
        // 6. repeat 1-5 with different starting points and choose iteration with shortest trip
        // 6. DONE!
        //////////////////////////////////////////////////////////////////////////////////////////////////

        const auto number_of_locations = phantom_node_vector.size();
        min_route.shortest_path_length = std::numeric_limits<int>::max();

        // is_lonely_island[i] indicates whether node i is a node that cannot be reached from other nodes
        //  1 means that node i is a lonely island
        //  0 means that it is not known for node i
        // -1 means that node i is not a lonely island but a reachable, connected node
        std::vector<int> is_lonely_island(number_of_locations, 0);
        int count_unreachables;

        // ALWAYS START AT ANOTHER STARTING POINT
        for(int start_node = 0; start_node < number_of_locations; ++start_node)
        {

            if (is_lonely_island[start_node] >= 0)
            {
                // if node is a lonely island it is an unsuitable node to start from and shall be skipped
                if (is_lonely_island[start_node])
                    continue;
                count_unreachables = 0;
                auto start_dist_begin = dist_table.begin() + (start_node * number_of_locations);
                auto start_dist_end = dist_table.begin() + ((start_node + 1) * number_of_locations);
                for (auto it2 = start_dist_begin; it2 != start_dist_end; ++it2) {
                    if (*it2 == 0 || *it2 == std::numeric_limits<int>::max()) {
                        ++count_unreachables;
                    }
                }
                if (count_unreachables >= number_of_locations) {
                    is_lonely_island[start_node] = 1;
                    continue;
                }
            }

            int curr_node = start_node;
            is_lonely_island[curr_node] = -1;
            InternalRouteResult raw_route;
            //TODO: Should we always use the same vector or does it not matter at all because of loop scope?
            std::vector<int> loc_permutation(number_of_locations, -1);
            loc_permutation[start_node] = 0;
            // visited[i] indicates whether node i was already visited by the salesman
            std::vector<bool> visited(number_of_locations, false);
            visited[start_node] = true;

            PhantomNodes viapoint;
            // 3. REPEAT FOR EVERY UNVISITED NODE
            for(int via_point = 1; via_point < number_of_locations; ++via_point)
            {
                int min_dist = std::numeric_limits<int>::max();
                int min_id = -1;

                // 2. FIND NEAREST NEIGHBOUR
                auto row_begin_iterator = dist_table.begin() + (curr_node * number_of_locations);
                auto row_end_iterator = dist_table.begin() + ((curr_node + 1) * number_of_locations);
                for (auto it = row_begin_iterator; it != row_end_iterator; ++it) {
                    auto index = std::distance(row_begin_iterator, it);
                    if (is_lonely_island[index] < 1 && !visited[index] && *it < min_dist)
                    {
                        min_dist = *it;
                        min_id = index;
                    }
                }
                // in case there was no unvisited and reachable node found, it means that all remaining (unvisited) nodes must be lonely islands
                if (min_id == -1)
                {
                    for(int loc = 0; loc < visited.size(); ++loc) {
                        if (!visited[loc]) {
                            is_lonely_island[loc] = 1;
                        }
                    }
                    break;
                }
                // set the nearest unvisited location as the next via_point
                else
                {
                    is_lonely_island[min_id] = -1;
                    loc_permutation[min_id] = via_point;
                    visited[min_id] = true;
                    viapoint = PhantomNodes{phantom_node_vector[curr_node][0], phantom_node_vector[min_id][0]};
                    raw_route.segment_end_coordinates.emplace_back(viapoint);
                    curr_node = min_id;
                }
            }

            // 4. ROUTE BACK TO STARTING POINT
            viapoint = PhantomNodes{raw_route.segment_end_coordinates.back().target_phantom, phantom_node_vector[start_node][0]};
            raw_route.segment_end_coordinates.emplace_back(viapoint);

            // 5. COMPUTE ROUTE
            search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, route_parameters.uturns, raw_route);

            // check round trip with this starting point is shorter than the shortest round trip found till now
            if (raw_route.shortest_path_length < min_route.shortest_path_length) {
                min_route = raw_route;
                min_loc_permutation = loc_permutation;
            }
        }
    }

  public:
    explicit RoundTripPlugin(DataFacadeT *facade)
        : descriptor_string("trip"), facade(facade)
    {
        search_engine_ptr = osrm::make_unique<SearchEngine<DataFacadeT>>(facade);
    }

    const std::string GetDescriptor() const override final { return descriptor_string; }

    int HandleRequest(const RouteParameters &route_parameters,
                      osrm::json::Object &json_result) override final
    {
        // check if all inputs are coordinates
        if (!check_all_coordinates(route_parameters.coordinates))
        {
            return 400;
        }
        const bool checksum_OK = (route_parameters.check_sum == facade->GetCheckSum());

        // find phantom nodes for all input coords
        PhantomNodeArray phantom_node_vector(route_parameters.coordinates.size());
        for (const auto i : osrm::irange<std::size_t>(0, route_parameters.coordinates.size()))
        {
            // if client hints are helpful, encode hints
            if (checksum_OK && i < route_parameters.hints.size() &&
                !route_parameters.hints[i].empty())
            {
                PhantomNode current_phantom_node;
                ObjectEncoder::DecodeFromBase64(route_parameters.hints[i], current_phantom_node);
                if (current_phantom_node.is_valid(facade->GetNumberOfNodes()))
                {
                    phantom_node_vector[i].emplace_back(std::move(current_phantom_node));
                    continue;
                }
            }
            facade->IncrementalFindPhantomNodeForCoordinate(route_parameters.coordinates[i],
                                                            phantom_node_vector[i], 1);
            if (phantom_node_vector[i].size() > 1)
            {
                phantom_node_vector[i].erase(phantom_node_vector[i].begin());
            }
            BOOST_ASSERT(phantom_node_vector[i].front().is_valid(facade->GetNumberOfNodes()));
        }

        // compute the distance table of all phantom nodes
        const std::shared_ptr<std::vector<EdgeWeight>> result_table =
            search_engine_ptr->distance_table(phantom_node_vector);

        if (!result_table)
        {
            return 400;
        }

        // compute TSP round trip
        InternalRouteResult min_route;
        std::vector<int> min_loc_permutation;
        TIMER_START(tsp_nn);
        NearestNeighbour(route_parameters, phantom_node_vector, *result_table, min_route, min_loc_permutation);
        TIMER_STOP(tsp_nn);

        SimpleLogger().Write() << "Distance " << min_route.shortest_path_length;
        SimpleLogger().Write() << "Time " << TIMER_MSEC(tsp_nn);

        // return result to json
        std::unique_ptr<BaseDescriptor<DataFacadeT>> descriptor;
        descriptor = osrm::make_unique<JSONDescriptor<DataFacadeT>>(facade);

        descriptor->SetConfig(route_parameters);
        descriptor->Run(min_route, json_result);

        osrm::json::Array json_loc_permutation;
        json_loc_permutation.values.insert(json_loc_permutation.values.end(), min_loc_permutation.begin(), min_loc_permutation.end());
        json_result.values["nn_loc_permutation"] = json_loc_permutation;
        json_result.values["nn_distance"] = min_route.shortest_path_length;
        json_result.values["nn_runtime"] = TIMER_MSEC(tsp_nn);

        return 200;
    }

};

#endif // ROUND_TRIP_HPP
<|endoftext|>


<commit_before>/**
 * Copyright (c) Sjors Gielen, 2010
 * See LICENSE for license.
 */

#include <QtCore/QDebug>
#include <ircclient-qt/IrcBuffer>

#include "testplugin.h"

TestPlugin::TestPlugin( PluginManager *man )
: Plugin( man )
{}

TestPlugin::~TestPlugin() {}

void TestPlugin::init()
{
  qDebug() << "TestPlugin initialising.";
}

void TestPlugin::connected( Network &net, const Server &serv )
{
  qDebug() << "Connected to network" << net;
  if( &serv != net.activeServer() )
  {
    qWarning() << "Warning! Connected to different server" << serv;
  }
}

void TestPlugin::welcomed( Network &net )
{
  qDebug() << "Authenticated to network " << net;
  net.joinChannel( "#dazjorz" );
}

void TestPlugin::joined( Network &net, const QString &who, Irc::Buffer *channel )
{
  User u( who, &net );
  qDebug() << "User " << u << " joined channel " << channel;
  /* if( u.isMe() )
  {
    channel->message( "Hi all!" );
  }
  else
  {
    channel->message( "Hi " + u.nick() + "!" );
  } */
}

void TestPlugin::parted( Network &net, const QString &who, const QString &leaveMessage,
                              Irc::Buffer *channel )
{
  qDebug() << "User " << who << " left channel " << channel << "on" << net
           << " (leave message " << leaveMessage << ")";
}

QHash<QString, Plugin::VariableScope> TestPlugin::variables()
{
  QHash<QString, Plugin::VariableScope> variables;
  return variables;
}
<commit_msg>Removed joinChannel in testplugin, and removed old stub method now in Plugin.<commit_after>/**
 * Copyright (c) Sjors Gielen, 2010
 * See LICENSE for license.
 */

#include <QtCore/QDebug>
#include <ircclient-qt/IrcBuffer>

#include "testplugin.h"

TestPlugin::TestPlugin( PluginManager *man )
: Plugin( man )
{}

TestPlugin::~TestPlugin() {}

void TestPlugin::init()
{
  qDebug() << "TestPlugin initialising.";
}

void TestPlugin::connected( Network &net, const Server &serv )
{
  qDebug() << "Connected to network" << net;
  if( &serv != net.activeServer() )
  {
    qWarning() << "Warning! Connected to different server" << serv;
  }
}

void TestPlugin::welcomed( Network &net )
{
  qDebug() << "Authenticated to network " << net;
}

void TestPlugin::joined( Network &net, const QString &who, Irc::Buffer *channel )
{
  User u( who, &net );
  qDebug() << "User " << u << " joined channel " << channel;
  /* if( u.isMe() )
  {
    channel->message( "Hi all!" );
  }
  else
  {
    channel->message( "Hi " + u.nick() + "!" );
  } */
}

void TestPlugin::parted( Network &net, const QString &who, const QString &leaveMessage,
                              Irc::Buffer *channel )
{
  qDebug() << "User " << who << " left channel " << channel << "on" << net
           << " (leave message " << leaveMessage << ")";
}
<|endoftext|>


<commit_before>
std::string shell_escape(const std::string& s) {
    //std::cout << "\n\nescape\n" << s << "\nto\n";
    std::stringstream ss;

    ss << "\"";

    for (auto c : s) {
        if (c == '"') {
            ss << "\\\"";
        } else {
            ss << c;
        }
    }

    ss << "\"";

    auto r = ss.str();

    //std::cout << r << "\n\n";

    return r;
}

std::string driver(std::string args) {
    using namespace std;

    FILE *in;
    char buff[512];
    std::stringstream ss;

    const std::string cmd = "./src/tudocomp_driver/tudocomp_driver " + args + " 2>&1";

    if(!(in = popen(cmd.data(), "r"))) {
        throw std::runtime_error("Error executing " + cmd);
    }

    while(fgets(buff, sizeof(buff), in)!=NULL){
        ss << buff;
    }
    pclose(in);

    return ss.str();
}

std::string roundtrip_in_file_name(std::string algo,
                                   std::string name_addition) {
    return algo + name_addition + ".txt";
}
std::string roundtrip_comp_file_name(std::string algo,
                                   std::string name_addition) {
    return algo + name_addition + ".tdc";
}
std::string roundtrip_decomp_file_name(std::string algo,
                                   std::string name_addition) {
    return algo + name_addition + ".decomp.txt";
}

std::string format_std_outputs(const std::vector<std::string>& v) {
    std::stringstream ss;

    for (size_t i = 0; i < v.size(); i+=2) {
        if (v[i+1].empty()) {
            continue;
        }
        ss << v[i] << ": \n";
        ss << v[i+1] << "\n";
        ss << "\n";
    }

    std::string r = ss.str();

    if (r.size() > 0) {
        //r = r + "---\n";
    }

    return r;
}

std::string format_escape(const std::string& s) {
    std::stringstream ss;
    ss << "\"";
    for (auto c : s) {
        uint8_t b = c;
        if (b == '\\') {
            ss << "\\\\";
        } else if (b == 0) {
            ss << "\\0";
        } else if (b == '\"') {
            ss << "\\\"";
        } else if (b < 32 || b > 127) {
            ss << "\\x" << std::hex << int(b);
        } else {
            ss << c;
        }
    }
    ss << "\"";
    return ss.str();
}

std::string format_diff(const std::string& a, const std::string& b) {
    std::string diff;
    for(size_t i = 0; i < std::max(a.size(), b.size()); i++) {
        if (i < std::min(a.size(), b.size())
            && a[i] == b[i]
        ) {
            diff.push_back('-');
        } else {
            diff.push_back('#');
        }
    }
    return diff;
}

struct Error {
    bool has_error;
    std::string test;
    std::string message;
    std::string compress_cmd;
    std::string compress_stdout;
    std::string decompress_cmd;
    std::string decompress_stdout;
    std::string text;
    std::string roundtrip_text;
};

Error roundtrip(std::string algo,
               std::string name_addition,
               std::string text,
               bool use_raw,
               bool& abort)
{
    Error current { false };

    std::string in_file   = roundtrip_in_file_name(algo, name_addition);
    std::string comp_file = roundtrip_comp_file_name(algo, name_addition);
    std::string decomp_file  = roundtrip_decomp_file_name(algo, name_addition);

    //std::cout << "Roundtrip with\n";
    std::cout << in_file << " -> ";
    std::cout.flush();

    remove_test_file(in_file);
    remove_test_file(comp_file);
    remove_test_file(decomp_file);

    write_test_file(in_file, text);

    std::string comp_out;
    std::string decomp_out;

    // Compress
    {
        std::string in = test_file_path(in_file);
        std::string out = test_file_path(comp_file);
        std::string cmd;
        if (use_raw) {
            cmd = "--raw --algorithm " + shell_escape(algo)
                + " --output " + shell_escape(out) + " " + shell_escape(in);
        } else {
            cmd = "--algorithm " + shell_escape(algo)
                + " --output " + shell_escape(out) + " " + shell_escape(in);
        }
        current.compress_cmd = cmd;
        comp_out = driver(cmd);
    }

    std::cout << comp_file << " -> ";
    std::cout.flush();

    bool compressed_file_exists = test_file_exists(comp_file);

    if (!compressed_file_exists) {
        current.has_error = true;
        current.compress_stdout = comp_out;
        current.message = "compression did not produce output";
        current.test = in_file + " -> " + comp_file;
        std::cout << "ERR\n";
        return current;
    }

    // Decompress
    {
        std::string in = test_file_path(comp_file);
        std::string out = test_file_path(decomp_file);
        std::string cmd;
        if (use_raw) {
            cmd = "--raw --decompress --algorithm " + shell_escape(algo)
                + " --output " + shell_escape(out) + " " + shell_escape(in);
        } else {
            cmd = "--decompress --output " + shell_escape(out) + " " + shell_escape(in);
        }
        current.decompress_cmd = cmd;
        decomp_out = driver(cmd);
    }

    std::cout << decomp_file << " ... ";
    std::cout.flush();

    bool decompressed_file_exists = test_file_exists(decomp_file);
    if (!decompressed_file_exists) {
        current.has_error = true;
        current.compress_stdout = comp_out;
        current.decompress_stdout = decomp_out;
        current.message = "decompression did not produce output";
        current.test = comp_file + " -> " + decomp_file;
        std::cout << "ERR\n";
        return current;
    } else {
        std::string read_text = read_test_file(decomp_file);
        if (read_text != text) {
            current.has_error = true;
            current.compress_stdout = comp_out;
            current.decompress_stdout = decomp_out;
            current.test = in_file + " -> " + comp_file + " -> " + decomp_file;
            current.message = "compression - decompression roundtrip did not preserve the same string";
            current.text = text;
            current.roundtrip_text = read_text;

            //abort = true;
            std::cout << "ERR\n";
            return current;
        } else {
            std::cout << "OK\n";
        }
    }

    return current;
}
<commit_msg>Add another layer of indirection to catch all errors of a process in matrix_tests<commit_after>
std::string shell_escape(const std::string& s) {
    //std::cout << "\n\nescape\n" << s << "\nto\n";
    std::stringstream ss;

    ss << "\"";

    for (auto c : s) {
        if (c == '"') {
            ss << "\\\"";
        } else {
            ss << c;
        }
    }

    ss << "\"";

    auto r = ss.str();

    //std::cout << r << "\n\n";

    return r;
}

std::string driver(std::string args) {
    using namespace std;

    FILE *in;
    char buff[512];
    std::stringstream ss;

    const std::string cmd_base = "./src/tudocomp_driver/tudocomp_driver " + args + " 2>&1";
    const std::string cmd = std::string("sh -c ") + shell_escape(cmd_base) + " 2>&1";

    if(!(in = popen(cmd.data(), "r"))) {
        throw std::runtime_error("Error executing " + cmd);
    }

    while(fgets(buff, sizeof(buff), in)!=NULL){
        ss << buff;
    }
    pclose(in);

    return ss.str();
}

std::string roundtrip_in_file_name(std::string algo,
                                   std::string name_addition) {
    return algo + name_addition + ".txt";
}
std::string roundtrip_comp_file_name(std::string algo,
                                   std::string name_addition) {
    return algo + name_addition + ".tdc";
}
std::string roundtrip_decomp_file_name(std::string algo,
                                   std::string name_addition) {
    return algo + name_addition + ".decomp.txt";
}

std::string format_std_outputs(const std::vector<std::string>& v) {
    std::stringstream ss;

    for (size_t i = 0; i < v.size(); i+=2) {
        if (v[i+1].empty()) {
            continue;
        }
        ss << v[i] << ": \n";
        ss << v[i+1] << "\n";
        ss << "\n";
    }

    std::string r = ss.str();

    if (r.size() > 0) {
        //r = r + "---\n";
    }

    return r;
}

std::string format_escape(const std::string& s) {
    std::stringstream ss;
    ss << "\"";
    for (auto c : s) {
        uint8_t b = c;
        if (b == '\\') {
            ss << "\\\\";
        } else if (b == 0) {
            ss << "\\0";
        } else if (b == '\"') {
            ss << "\\\"";
        } else if (b < 32 || b > 127) {
            ss << "\\x" << std::hex << int(b);
        } else {
            ss << c;
        }
    }
    ss << "\"";
    return ss.str();
}

std::string format_diff(const std::string& a, const std::string& b) {
    std::string diff;
    for(size_t i = 0; i < std::max(a.size(), b.size()); i++) {
        if (i < std::min(a.size(), b.size())
            && a[i] == b[i]
        ) {
            diff.push_back('-');
        } else {
            diff.push_back('#');
        }
    }
    return diff;
}

struct Error {
    bool has_error;
    std::string test;
    std::string message;
    std::string compress_cmd;
    std::string compress_stdout;
    std::string decompress_cmd;
    std::string decompress_stdout;
    std::string text;
    std::string roundtrip_text;
};

Error roundtrip(std::string algo,
               std::string name_addition,
               std::string text,
               bool use_raw,
               bool& abort)
{
    Error current { false };

    std::string in_file   = roundtrip_in_file_name(algo, name_addition);
    std::string comp_file = roundtrip_comp_file_name(algo, name_addition);
    std::string decomp_file  = roundtrip_decomp_file_name(algo, name_addition);

    //std::cout << "Roundtrip with\n";
    std::cout << in_file << " -> ";
    std::cout.flush();

    remove_test_file(in_file);
    remove_test_file(comp_file);
    remove_test_file(decomp_file);

    write_test_file(in_file, text);

    std::string comp_out;
    std::string decomp_out;

    // Compress
    {
        std::string in = test_file_path(in_file);
        std::string out = test_file_path(comp_file);
        std::string cmd;
        if (use_raw) {
            cmd = "--raw --algorithm " + shell_escape(algo)
                + " --output " + shell_escape(out) + " " + shell_escape(in);
        } else {
            cmd = "--algorithm " + shell_escape(algo)
                + " --output " + shell_escape(out) + " " + shell_escape(in);
        }
        current.compress_cmd = cmd;
        comp_out = driver(cmd);
    }

    std::cout << comp_file << " -> ";
    std::cout.flush();

    bool compressed_file_exists = test_file_exists(comp_file);

    if (!compressed_file_exists) {
        current.has_error = true;
        current.compress_stdout = comp_out;
        current.message = "compression did not produce output";
        current.test = in_file + " -> " + comp_file;
        std::cout << "ERR\n";
        return current;
    }

    // Decompress
    {
        std::string in = test_file_path(comp_file);
        std::string out = test_file_path(decomp_file);
        std::string cmd;
        if (use_raw) {
            cmd = "--raw --decompress --algorithm " + shell_escape(algo)
                + " --output " + shell_escape(out) + " " + shell_escape(in);
        } else {
            cmd = "--decompress --output " + shell_escape(out) + " " + shell_escape(in);
        }
        current.decompress_cmd = cmd;
        decomp_out = driver(cmd);
    }

    std::cout << decomp_file << " ... ";
    std::cout.flush();

    bool decompressed_file_exists = test_file_exists(decomp_file);
    if (!decompressed_file_exists) {
        current.has_error = true;
        current.compress_stdout = comp_out;
        current.decompress_stdout = decomp_out;
        current.message = "decompression did not produce output";
        current.test = comp_file + " -> " + decomp_file;
        std::cout << "ERR\n";
        return current;
    } else {
        std::string read_text = read_test_file(decomp_file);
        if (read_text != text) {
            current.has_error = true;
            current.compress_stdout = comp_out;
            current.decompress_stdout = decomp_out;
            current.test = in_file + " -> " + comp_file + " -> " + decomp_file;
            current.message = "compression - decompression roundtrip did not preserve the same string";
            current.text = text;
            current.roundtrip_text = read_text;

            //abort = true;
            std::cout << "ERR\n";
            return current;
        } else {
            std::cout << "OK\n";
        }
    }

    return current;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef RPT_XMLSTYLEIMPORT_HXX
#define RPT_XMLSTYLEIMPORT_HXX

#include <rtl/ustring.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmlictxt.hxx>
#include <xmloff/maptype.hxx>
#include <xmloff/prstylei.hxx>
#include <xmloff/xmlimppr.hxx>
#include <xmloff/XMLTextMasterPageContext.hxx>
#include <xmloff/XMLTextMasterStylesContext.hxx>
#include <xmloff/contextid.hxx>
#include <xmloff/controlpropertyhdl.hxx>
#include <vector>

namespace rptxml
{
    class ORptFilter;

    class OControlStyleContext : public XMLPropStyleContext
    {
        OUString             m_sDataStyleName;
        OUString             sPageStyle;
        const OUString         sNumberFormat;
        SvXMLStylesContext*         pStyles;
        //  std::vector<ScXMLMapContent>    aMaps;
        com::sun::star::uno::Any    aConditionalFormat;
        sal_Int32                   m_nNumberFormat;
        ORptFilter&                 m_rImport;
        sal_Bool                    bConditionalFormatCreated : 1;
        sal_Bool                    bParentSet : 1;

        ORptFilter& GetOwnImport() const;

        OControlStyleContext(const OControlStyleContext&);
        void operator =(const OControlStyleContext&);
    protected:

        virtual void SetAttribute( sal_uInt16 nPrefixKey,
                                const OUString& rLocalName,
                                const OUString& rValue ) SAL_OVERRIDE;

    public:

        TYPEINFO_OVERRIDE();

        OControlStyleContext( ORptFilter& rImport, sal_uInt16 nPrfx,
                const OUString& rLName,
                const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
                SvXMLStylesContext& rStyles, sal_uInt16 nFamily, sal_Bool bDefaultStyle = sal_False );

        virtual ~OControlStyleContext();

        virtual void FillPropertySet(const ::com::sun::star::uno::Reference<
                    ::com::sun::star::beans::XPropertySet > & rPropSet ) SAL_OVERRIDE;

        virtual void SetDefaults() SAL_OVERRIDE;

          void AddProperty(sal_Int16 nContextID, const com::sun::star::uno::Any& aValue);

        sal_Int32 GetNumberFormat() { return m_nNumberFormat; }
    };

    class OReportStylesContext : public SvXMLStylesContext
    {
        const OUString m_sTableStyleFamilyName;
        const OUString m_sColumnStyleFamilyName;
        const OUString m_sRowStyleFamilyName;
        const OUString m_sCellStyleFamilyName;
        ORptFilter&           m_rImport;
        sal_Int32 m_nNumberFormatIndex;
        sal_Int32 nMasterPageNameIndex;
        sal_Bool bAutoStyles : 1;

        //mutable UniReference < SvXMLImportPropertyMapper > m_xControlImpPropMapper;
        mutable UniReference < SvXMLImportPropertyMapper > m_xCellImpPropMapper;
        mutable UniReference < SvXMLImportPropertyMapper > m_xColumnImpPropMapper;
        mutable UniReference < SvXMLImportPropertyMapper > m_xRowImpPropMapper;
        mutable UniReference < SvXMLImportPropertyMapper > m_xTableImpPropMapper;

        mutable ::com::sun::star::uno::Reference <
                    ::com::sun::star::container::XNameContainer > m_xCellStyles;
        mutable ::com::sun::star::uno::Reference <
                        ::com::sun::star::container::XNameContainer > m_xColumnStyles;
        mutable ::com::sun::star::uno::Reference <
                        ::com::sun::star::container::XNameContainer > m_xRowStyles;
        mutable ::com::sun::star::uno::Reference <
                        ::com::sun::star::container::XNameContainer > m_xTableStyles;

        ORptFilter& GetOwnImport() const;

        OReportStylesContext(const OReportStylesContext&);
        void operator =(const OReportStylesContext&);
    protected:

        // Create a style context.
        virtual SvXMLStyleContext *CreateStyleStyleChildContext(
                sal_uInt16 nFamily,
                sal_uInt16 nPrefix,
                const OUString& rLocalName,
                const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList ) SAL_OVERRIDE;

        virtual SvXMLStyleContext *CreateDefaultStyleStyleChildContext(
                sal_uInt16 nFamily, sal_uInt16 nPrefix,
                const OUString& rLocalName,
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList ) SAL_OVERRIDE;

    public:

        TYPEINFO_OVERRIDE();

        OReportStylesContext( ORptFilter& rImport, sal_uInt16 nPrfx ,
                const OUString& rLName ,
                const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
                const sal_Bool bAutoStyles );
        virtual ~OReportStylesContext();

        virtual void EndElement() SAL_OVERRIDE;

        virtual UniReference < SvXMLImportPropertyMapper > GetImportPropertyMapper(
                            sal_uInt16 nFamily ) const SAL_OVERRIDE;
        virtual ::com::sun::star::uno::Reference <
                        ::com::sun::star::container::XNameContainer >
            GetStylesContainer( sal_uInt16 nFamily ) const SAL_OVERRIDE;
        virtual OUString GetServiceName( sal_uInt16 nFamily ) const SAL_OVERRIDE;
        virtual sal_uInt16 GetFamily( const OUString& rFamily ) const SAL_OVERRIDE;

        sal_Int32 GetIndex(const sal_Int16 nContextID);
    };

} // rptxml

#endif // RPT_XMLSTYLEIMPORT_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#707969 unused nMasterPageNameIndex<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

#ifndef RPT_XMLSTYLEIMPORT_HXX
#define RPT_XMLSTYLEIMPORT_HXX

#include <rtl/ustring.hxx>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmlictxt.hxx>
#include <xmloff/maptype.hxx>
#include <xmloff/prstylei.hxx>
#include <xmloff/xmlimppr.hxx>
#include <xmloff/XMLTextMasterPageContext.hxx>
#include <xmloff/XMLTextMasterStylesContext.hxx>
#include <xmloff/contextid.hxx>
#include <xmloff/controlpropertyhdl.hxx>
#include <vector>

namespace rptxml
{
    class ORptFilter;

    class OControlStyleContext : public XMLPropStyleContext
    {
        OUString             m_sDataStyleName;
        OUString             sPageStyle;
        const OUString         sNumberFormat;
        SvXMLStylesContext*         pStyles;
        //  std::vector<ScXMLMapContent>    aMaps;
        com::sun::star::uno::Any    aConditionalFormat;
        sal_Int32                   m_nNumberFormat;
        ORptFilter&                 m_rImport;
        sal_Bool                    bConditionalFormatCreated : 1;
        sal_Bool                    bParentSet : 1;

        ORptFilter& GetOwnImport() const;

        OControlStyleContext(const OControlStyleContext&);
        void operator =(const OControlStyleContext&);
    protected:

        virtual void SetAttribute( sal_uInt16 nPrefixKey,
                                const OUString& rLocalName,
                                const OUString& rValue ) SAL_OVERRIDE;

    public:

        TYPEINFO_OVERRIDE();

        OControlStyleContext( ORptFilter& rImport, sal_uInt16 nPrfx,
                const OUString& rLName,
                const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
                SvXMLStylesContext& rStyles, sal_uInt16 nFamily, sal_Bool bDefaultStyle = sal_False );

        virtual ~OControlStyleContext();

        virtual void FillPropertySet(const ::com::sun::star::uno::Reference<
                    ::com::sun::star::beans::XPropertySet > & rPropSet ) SAL_OVERRIDE;

        virtual void SetDefaults() SAL_OVERRIDE;

          void AddProperty(sal_Int16 nContextID, const com::sun::star::uno::Any& aValue);

        sal_Int32 GetNumberFormat() { return m_nNumberFormat; }
    };

    class OReportStylesContext : public SvXMLStylesContext
    {
        const OUString m_sTableStyleFamilyName;
        const OUString m_sColumnStyleFamilyName;
        const OUString m_sRowStyleFamilyName;
        const OUString m_sCellStyleFamilyName;
        ORptFilter&           m_rImport;
        sal_Int32 m_nNumberFormatIndex;
        sal_Bool bAutoStyles : 1;

        //mutable UniReference < SvXMLImportPropertyMapper > m_xControlImpPropMapper;
        mutable UniReference < SvXMLImportPropertyMapper > m_xCellImpPropMapper;
        mutable UniReference < SvXMLImportPropertyMapper > m_xColumnImpPropMapper;
        mutable UniReference < SvXMLImportPropertyMapper > m_xRowImpPropMapper;
        mutable UniReference < SvXMLImportPropertyMapper > m_xTableImpPropMapper;

        mutable ::com::sun::star::uno::Reference <
                    ::com::sun::star::container::XNameContainer > m_xCellStyles;
        mutable ::com::sun::star::uno::Reference <
                        ::com::sun::star::container::XNameContainer > m_xColumnStyles;
        mutable ::com::sun::star::uno::Reference <
                        ::com::sun::star::container::XNameContainer > m_xRowStyles;
        mutable ::com::sun::star::uno::Reference <
                        ::com::sun::star::container::XNameContainer > m_xTableStyles;

        ORptFilter& GetOwnImport() const;

        OReportStylesContext(const OReportStylesContext&);
        void operator =(const OReportStylesContext&);
    protected:

        // Create a style context.
        virtual SvXMLStyleContext *CreateStyleStyleChildContext(
                sal_uInt16 nFamily,
                sal_uInt16 nPrefix,
                const OUString& rLocalName,
                const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList ) SAL_OVERRIDE;

        virtual SvXMLStyleContext *CreateDefaultStyleStyleChildContext(
                sal_uInt16 nFamily, sal_uInt16 nPrefix,
                const OUString& rLocalName,
                const ::com::sun::star::uno::Reference<
                    ::com::sun::star::xml::sax::XAttributeList > & xAttrList ) SAL_OVERRIDE;

    public:

        TYPEINFO_OVERRIDE();

        OReportStylesContext( ORptFilter& rImport, sal_uInt16 nPrfx ,
                const OUString& rLName ,
                const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList > & xAttrList,
                const sal_Bool bAutoStyles );
        virtual ~OReportStylesContext();

        virtual void EndElement() SAL_OVERRIDE;

        virtual UniReference < SvXMLImportPropertyMapper > GetImportPropertyMapper(
                            sal_uInt16 nFamily ) const SAL_OVERRIDE;
        virtual ::com::sun::star::uno::Reference <
                        ::com::sun::star::container::XNameContainer >
            GetStylesContainer( sal_uInt16 nFamily ) const SAL_OVERRIDE;
        virtual OUString GetServiceName( sal_uInt16 nFamily ) const SAL_OVERRIDE;
        virtual sal_uInt16 GetFamily( const OUString& rFamily ) const SAL_OVERRIDE;

        sal_Int32 GetIndex(const sal_Int16 nContextID);
    };

} // rptxml

#endif // RPT_XMLSTYLEIMPORT_HXX

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include <glibmm.h>
#include <dbus-c++/dbus.h>
#include <dbus-c++/glib-integration.h>

#include <signal.h>
#include <unistd.h>
#include "CommandLineParser.h"
#include "log.h"
#include "paminterface.h"
#include "pelagicontain.h"
#include "pelagicontaintodbusadapter.h"
#include "dbusmainloop.h"
#include "generators.h" /* used for gen_ct_name */
#include "pulsegateway.h"
#include "networkgateway.h"
#include "dbusgateway.h"
#include <sys/stat.h>
#include "systemcallinterface.h"
#include "devicenodegateway.h"

LOG_DEFINE_APP_IDS("PCON", "Pelagicontain");
LOG_DECLARE_DEFAULT_CONTEXT(Pelagicontain_DefaultLogContext, "PCON", "Main context");

#ifndef CONFIG
    #error Must define CONFIG; path to configuration file (/etc/pelagicontain?)
#endif

/* Needs to be global in order to be reachable from the signal handler */
static Pelagicontain *pelagicontain;

void signalHandler(int signum)
{
    log_debug() << "caught signal " << signum;
    pelagicontain->shutdown();
}

int main(int argc, char **argv)
{

    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);

    const char *summary = "Pelagicore container utility. "
                          "Requires an absolute path to the container root, "
                          "the command to run inside the container and "
                          "an alphanumerical cookie string as first, second and"
                          "third argument respectively";
    const char *paramsDescription = "[container root directory (abs path)] "
                                    "[command] [cookie]";

    pelagicore::CommandLineParser commandLineParser(summary,
                                                    paramsDescription,
                                                    PACKAGE_VERSION,
                                                    "");

    std::string containerRoot;
    std::string containedCommand;
    std::string cookie;
    const char* configFilePath = CONFIG;
    commandLineParser.addOption(configFilePath,
                                "with-config-file",
                                'c',
                                "Config file");

    if (commandLineParser.parse(argc, argv)) {
        return -1;
    }

    if (argc < 4) {
        log_error("Invalid arguments");
        commandLineParser.printHelp();
        return -1;
    } else {
        containerRoot = std::string(argv[1]);
        containedCommand = std::string(argv[2]);
        cookie = std::string(argv[3]);
    }

    if (containerRoot.c_str()[0] != '/') {
        log_error("Path to container root must be absolute");
        commandLineParser.printHelp();
        return -1;
    }

    std::string containerName = Generator::gen_ct_name();
    std::string containerConfig(configFilePath);

    // Create gateway directory for container in containerRoot/gateways.
    // This dir will contain various sockets etc acting as gateways
    // in/out of the container.
    std::string containerDir = containerRoot + "/" + containerName;
    std::string gatewayDir = containerDir + "/gateways";
    if (mkdir(containerDir.c_str(), S_IRWXU) == -1) {
        log_error("Could not create container directory %s, %s.",
                  containerDir.c_str(),
                  strerror(errno));
        exit(-1);
    }
    if (mkdir(gatewayDir.c_str(), S_IRWXU) == -1) {
        log_error("Could not create gateway directory %s, %s.",
                  gatewayDir.c_str(),
                  strerror(errno));
        exit(-1);
    }

    Glib::RefPtr<Glib::MainLoop> ml = Glib::MainLoop::create();

    { // Create a new scope so that we can do a clean up after dtors
        DBus::Glib::BusDispatcher dispatcher;
        DBus::default_dispatcher = &dispatcher;
        dispatcher.attach(ml->get_context()->gobj());
        DBus::Connection bus = DBus::Connection::SessionBus();

        /* Pelagicontain needs an interface to the mainloop so it can
         * exit it when we are to clean up and shut down
         */
        DBusMainloop mainloopInterface(ml);

        /* The request_name call does not return anything but raises an
         * exception if the name cannot be requested.
         */
        std::string name = "com.pelagicore.Pelagicontain" + cookie;
        bus.request_name(name.c_str());

        PAMInterface pamInterface(bus);
        ControllerInterface controllerInterface(gatewayDir);
        SystemcallInterface systemcallInterface;
        pelagicontain = new Pelagicontain(&pamInterface,
                                          &mainloopInterface,
                                          &controllerInterface,
                                          cookie);

        std::string objectPath = "/com/pelagicore/Pelagicontain";

        PelagicontainToDBusAdapter pcAdapter(bus, objectPath, *pelagicontain);

        pelagicontain->addGateway(new NetworkGateway(controllerInterface,
                                                    systemcallInterface));

        pelagicontain->addGateway(new PulseGateway(gatewayDir, containerName,
                                                  controllerInterface));

        pelagicontain->addGateway(new DeviceNodeGateway(controllerInterface));

        pelagicontain->addGateway(new DBusGateway(controllerInterface,
                                                 systemcallInterface,
                                                 DBusGateway::SessionProxy,
                                                 gatewayDir,
                                                 containerName));

        pelagicontain->addGateway(new DBusGateway(controllerInterface,
                                                 systemcallInterface,
                                                 DBusGateway::SystemProxy,
                                                 gatewayDir,
                                                 containerName));

        pid_t pcPid = pelagicontain->preload(containerName,
                                            containerConfig,
                                            containerRoot,
                                            containedCommand);

        if (!pcPid) {
            // Fatal failure, only do necessary cleanup
            log_error() << "Could not start container, will shut down";
        } else {
            log_debug() << "Started container with PID " << pcPid;
            // setup IPC between Pelagicontain and Controller
            bool connected = pelagicontain->establishConnection();
            if (connected) {
                ml->run();
                // When we return here Pelagicontain has exited the mainloop
                log_debug("Exited mainloop");
            } else {
                // Fatal failure, only do necessary cleanup
                log_error() << "Could not connect to Controller";
                pelagicontain->shutdownContainer();
            }
        }
    }

    delete pelagicontain;

    // remove instance specific dirs again
    if (rmdir(gatewayDir.c_str()) == -1) {
        log_error("Cannot delete dir %s, %s",
                  gatewayDir.c_str(),
                  strerror(errno));
    }

    if (rmdir(containerDir.c_str()) == -1) {
        log_error("Cannot delete dir %s, %s",
                  gatewayDir.c_str(),
                  strerror(errno));
    }

    log_debug() << "Goodbye.";
}
<commit_msg>pelagicontain/main.cpp: Fixed typo and clarified debug output<commit_after>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include <glibmm.h>
#include <dbus-c++/dbus.h>
#include <dbus-c++/glib-integration.h>

#include <signal.h>
#include <unistd.h>
#include "CommandLineParser.h"
#include "log.h"
#include "paminterface.h"
#include "pelagicontain.h"
#include "pelagicontaintodbusadapter.h"
#include "dbusmainloop.h"
#include "generators.h" /* used for gen_ct_name */
#include "pulsegateway.h"
#include "networkgateway.h"
#include "dbusgateway.h"
#include <sys/stat.h>
#include "systemcallinterface.h"
#include "devicenodegateway.h"

LOG_DEFINE_APP_IDS("PCON", "Pelagicontain");
LOG_DECLARE_DEFAULT_CONTEXT(Pelagicontain_DefaultLogContext, "PCON", "Main context");

#ifndef CONFIG
    #error Must define CONFIG; path to configuration file (/etc/pelagicontain?)
#endif

/* Needs to be global in order to be reachable from the signal handler */
static Pelagicontain *pelagicontain;

void signalHandler(int signum)
{
    log_debug() << "caught signal " << signum;
    pelagicontain->shutdown();
}

int main(int argc, char **argv)
{

    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);

    const char *summary = "Pelagicore container utility. "
                          "Requires an absolute path to the container root, "
                          "the command to run inside the container and "
                          "an alphanumerical cookie string as first, second and"
                          "third argument respectively";
    const char *paramsDescription = "[container root directory (abs path)] "
                                    "[command] [cookie]";

    pelagicore::CommandLineParser commandLineParser(summary,
                                                    paramsDescription,
                                                    PACKAGE_VERSION,
                                                    "");

    std::string containerRoot;
    std::string containedCommand;
    std::string cookie;
    const char* configFilePath = CONFIG;
    commandLineParser.addOption(configFilePath,
                                "with-config-file",
                                'c',
                                "Config file");

    if (commandLineParser.parse(argc, argv)) {
        return -1;
    }

    if (argc < 4) {
        log_error("Invalid arguments");
        commandLineParser.printHelp();
        return -1;
    } else {
        containerRoot = std::string(argv[1]);
        containedCommand = std::string(argv[2]);
        cookie = std::string(argv[3]);
    }

    if (containerRoot.c_str()[0] != '/') {
        log_error("Path to container root must be absolute");
        commandLineParser.printHelp();
        return -1;
    }

    std::string containerName = Generator::gen_ct_name();
    std::string containerConfig(configFilePath);

    // Create gateway directory for container in containerRoot/gateways.
    // This dir will contain various sockets etc acting as gateways
    // in/out of the container.
    std::string containerDir = containerRoot + "/" + containerName;
    std::string gatewayDir = containerDir + "/gateways";
    if (mkdir(containerDir.c_str(), S_IRWXU) == -1) {
        log_error("Could not create container directory %s, %s.",
                  containerDir.c_str(),
                  strerror(errno));
        exit(-1);
    }
    if (mkdir(gatewayDir.c_str(), S_IRWXU) == -1) {
        log_error("Could not create gateway directory %s, %s.",
                  gatewayDir.c_str(),
                  strerror(errno));
        exit(-1);
    }

    Glib::RefPtr<Glib::MainLoop> ml = Glib::MainLoop::create();

    { // Create a new scope so that we can do a clean up after dtors
        DBus::Glib::BusDispatcher dispatcher;
        DBus::default_dispatcher = &dispatcher;
        dispatcher.attach(ml->get_context()->gobj());
        DBus::Connection bus = DBus::Connection::SessionBus();

        /* Pelagicontain needs an interface to the mainloop so it can
         * exit it when we are to clean up and shut down
         */
        DBusMainloop mainloopInterface(ml);

        /* The request_name call does not return anything but raises an
         * exception if the name cannot be requested.
         */
        std::string name = "com.pelagicore.Pelagicontain" + cookie;
        bus.request_name(name.c_str());

        PAMInterface pamInterface(bus);
        ControllerInterface controllerInterface(gatewayDir);
        SystemcallInterface systemcallInterface;
        pelagicontain = new Pelagicontain(&pamInterface,
                                          &mainloopInterface,
                                          &controllerInterface,
                                          cookie);

        std::string objectPath = "/com/pelagicore/Pelagicontain";

        PelagicontainToDBusAdapter pcAdapter(bus, objectPath, *pelagicontain);

        pelagicontain->addGateway(new NetworkGateway(controllerInterface,
                                                    systemcallInterface));

        pelagicontain->addGateway(new PulseGateway(gatewayDir, containerName,
                                                  controllerInterface));

        pelagicontain->addGateway(new DeviceNodeGateway(controllerInterface));

        pelagicontain->addGateway(new DBusGateway(controllerInterface,
                                                 systemcallInterface,
                                                 DBusGateway::SessionProxy,
                                                 gatewayDir,
                                                 containerName));

        pelagicontain->addGateway(new DBusGateway(controllerInterface,
                                                 systemcallInterface,
                                                 DBusGateway::SystemProxy,
                                                 gatewayDir,
                                                 containerName));

        pid_t pcPid = pelagicontain->preload(containerName,
                                            containerConfig,
                                            containerRoot,
                                            containedCommand);

        if (!pcPid) {
            // Fatal failure, only do necessary cleanup
            log_error() << "Could not start container, will shut down";
        } else {
            log_debug() << "Started container with PID " << pcPid;
            // setup IPC between Pelagicontain and Controller
            bool connected = pelagicontain->establishConnection();
            if (connected) {
                ml->run();
                // When we return here Pelagicontain has exited the mainloop
                log_debug("Exited mainloop");
            } else {
                // Fatal failure, only do necessary cleanup
                log_error() << "Got no connection from Controller";
                pelagicontain->shutdownContainer();
            }
        }
    }

    delete pelagicontain;

    // remove instance specific dirs again
    if (rmdir(gatewayDir.c_str()) == -1) {
        log_error("Cannot delete dir %s, %s",
                  gatewayDir.c_str(),
                  strerror(errno));
    }

    if (rmdir(containerDir.c_str()) == -1) {
        log_error("Cannot delete dir %s, %s",
                  containerDir.c_str(),
                  strerror(errno));
    }

    log_debug() << "Goodbye.";
}
<|endoftext|>