<commit_before>//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  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.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

//
// This is the glue logic needed to connect the wm-FPU-emu
// FPU emulator written by Bill Metzenthen to bochs.
//

#include "bochs.h"
extern "C" {
#include "fpu_emu.h"
#include "linux/signal.h"
}

// Use this to hold a pointer to the instruction since
// we can't pass this to the FPU emulation routines, which
// will ultimately call routines here.
static BxInstruction_t *fpu_iptr = NULL;
static BX_CPU_C *fpu_cpu_ptr = NULL;

i387_t i387;

extern "C" void
math_emulate2(fpu_addr_modes addr_modes,
              u_char  FPU_modrm,
              u_char byte1,
              void *data_address,
              struct address data_sel_off,
              struct address entry_sel_off);

extern "C" void printfp(char *s, FPU_REG *r);

  // This is called by bochs upon reset
  void
BX_CPU_C::fpu_init(void)
{
  finit();
}

  void
BX_CPU_C::fpu_execute(BxInstruction_t *i)
{
  fpu_addr_modes addr_modes;
  void *data_address;
  struct address data_sel_off;
  struct address entry_sel_off;
  Boolean is_32;

  fpu_iptr = i;
  fpu_cpu_ptr = this;

#if 0
  addr_modes.default_mode = VM86;
  addr_modes.default_mode = 0; // FPU_CS == __USER_CS && FPU_DS == __USER_DS
  addr_modes.default_mode = SEG32;
  addr_modes.default_mode = PM16;
#endif
  if (protected_mode()) {
    addr_modes.default_mode = SEG32;
    }
  else if (v8086_mode()) {
    addr_modes.default_mode = VM86;
    }
  else {
    // real mode, use vm86 for now
    addr_modes.default_mode = VM86;
    }

  // Mark if instruction used opsize or addrsize prefixes
  // Actually, addr_modes.override.address_size is not used,
  // could delete that code.
  is_32 = sregs[BX_SEG_REG_CS].cache.u.segment.d_b;
  if (i->as_32 == is_32)
    addr_modes.override.address_size = 0;
  else
    addr_modes.override.address_size = ADDR_SIZE_PREFIX;
  if (i->os_32 == is_32)
    addr_modes.override.operand_size = 0;
  else
    addr_modes.override.operand_size = OP_SIZE_PREFIX;

  // For now set access_limit to max.  It seems to be
  // a number from 0..255 denoting how many bytes the
  // current instruction can access according to its
  // memory operand.  255 means >= 255.
access_limit = 0xff;

  // fill in orig eip here in offset
  // fill in CS in selector
  entry_sel_off.offset = prev_eip;
  entry_sel_off.selector =
    sregs[BX_SEG_REG_CS].selector.value;

// should set these fields to 0 if mem operand not used
  data_address = (void *) i->rm_addr;
  data_sel_off.offset = i->rm_addr;
  data_sel_off.selector = sregs[i->seg].selector.value;

  math_emulate2(addr_modes, i->modrm, i->b1, data_address,
                data_sel_off, entry_sel_off);
}

  unsigned
fpu_get_ds(void)
{
  return(fpu_cpu_ptr->sregs[BX_SEG_REG_DS].selector.value);
}

  void
fpu_set_ax(unsigned short val16)
{
// define to set AX in the current CPU -- not ideal.
#define AX (fpu_cpu_ptr->gen_reg[0].word.rx)
  AX = val16;
#undef AX
//fprintf(stderr, "fpu_set_ax(0x%04x)\n", (unsigned) val16);
}

  void
fpu_verify_area(unsigned what, void *ptr, unsigned n)
{
  bx_segment_reg_t *seg;

  seg = &fpu_cpu_ptr->sregs[fpu_iptr->seg];

  if (what == VERIFY_READ) {
    fpu_cpu_ptr->read_virtual_checks(seg, PTR2INT(ptr), n);
    }
  else {  // VERIFY_WRITE
    fpu_cpu_ptr->write_virtual_checks(seg, PTR2INT(ptr), n);
    }
//fprintf(stderr, "verify_area: 0x%x\n", PTR2INT(ptr));
}

  void
FPU_printall(void)
{
  bx_panic("FPU_printall\n");
}

  unsigned
fpu_get_user(void *ptr, unsigned len)
{
  Bit32u val32;
  Bit16u val16;
  Bit8u  val8;

  switch (len) {
    case 1:
      fpu_cpu_ptr->read_virtual_byte(fpu_iptr->seg, PTR2INT(ptr), &val8);
      val32 = val8;
      break;
    case 2:
      fpu_cpu_ptr->read_virtual_word(fpu_iptr->seg, PTR2INT(ptr), &val16);
      val32 = val16;
      break;
    case 4:
      fpu_cpu_ptr->read_virtual_dword(fpu_iptr->seg, PTR2INT(ptr), &val32);
      break;
    default:
      bx_panic("fpu_get_user: len=%u\n", len);
    }
  return(val32);
}

  void
fpu_put_user(unsigned val, void *ptr, unsigned len)
{
  Bit32u val32;
  Bit16u val16;
  Bit8u  val8;

  switch (len) {
    case 1:
      val8 = val;
      fpu_cpu_ptr->write_virtual_byte(fpu_iptr->seg, PTR2INT(ptr), &val8);
      break;
    case 2:
      val16 = val;
      fpu_cpu_ptr->write_virtual_word(fpu_iptr->seg, PTR2INT(ptr), &val16);
      break;
    case 4:
      val32 = val;
      fpu_cpu_ptr->write_virtual_dword(fpu_iptr->seg, PTR2INT(ptr), &val32);
      break;
    default:
      bx_panic("fpu_put_user: len=%u\n", len);
    }
}

  void
math_abort(struct info *info, unsigned int signal)
{
  UNUSED(info); // info is always passed NULL
#if BX_CPU_LEVEL >= 4

// values of signal:
//   SIGILL  : opcodes which are illegal
//   SIGFPE  : unmasked FP exception before WAIT or non-control instruction
//   SIGSEGV : access data beyond segment violation
  switch (signal) {
    case SIGFPE:
      if (fpu_cpu_ptr->cr0.ne == 0) {
        // MSDOS compatibility external interrupt (IRQ13)
        bx_panic("math_abort: MSDOS compatibility not supported yet\n");
        }
      fpu_cpu_ptr->exception(BX_MF_EXCEPTION, 0, 0);
      // execution does not reach here

    case SIGILL:
      bx_panic("math_abort: SIGILL not implemented yet.\n");
      break;
    case SIGSEGV:
      bx_panic("math_abort: SIGSEGV not implemented yet.\n");
      break;
    }

#else
  UNUSED(signal);
  bx_panic("math_abort: CPU<4 not supported yet\n");
#endif
}

  int
printk(const char * fmt, ...)
{
  bx_printf("printk not complete: %s\n", fmt);
  return(0); // for now
}
<commit_msg>- this code already had fpu_iptr, a pointer to the instruction that the   FPU library is currently executing.  So it wasn't much of a stretch to   add fpu_cpu_ptr, the CPU that the FPU library is working on.  The CPU   pointer is needed so that FPU code can read and write registers on the   correct processor.<commit_after>//  Copyright (C) 2000  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  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.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

//
// This is the glue logic needed to connect the wm-FPU-emu
// FPU emulator written by Bill Metzenthen to bochs.
//

#include "bochs.h"
extern "C" {
#include "fpu_emu.h"
#include "linux/signal.h"
}

// Use this to hold a pointer to the instruction since
// we can't pass this to the FPU emulation routines, which
// will ultimately call routines here.
static BxInstruction_t *fpu_iptr = NULL;
static BX_CPU_C *fpu_cpu_ptr = NULL;

i387_t i387;

extern "C" void
math_emulate2(fpu_addr_modes addr_modes,
              u_char  FPU_modrm,
              u_char byte1,
              void *data_address,
              struct address data_sel_off,
              struct address entry_sel_off);

extern "C" void printfp(char *s, FPU_REG *r);

  // This is called by bochs upon reset
  void
BX_CPU_C::fpu_init(void)
{
  finit();
}

  void
BX_CPU_C::fpu_execute(BxInstruction_t *i)
{
  fpu_addr_modes addr_modes;
  void *data_address;
  struct address data_sel_off;
  struct address entry_sel_off;
  Boolean is_32;

  fpu_iptr = i;
  fpu_cpu_ptr = this;

#if 0
  addr_modes.default_mode = VM86;
  addr_modes.default_mode = 0; // FPU_CS == __USER_CS && FPU_DS == __USER_DS
  addr_modes.default_mode = SEG32;
  addr_modes.default_mode = PM16;
#endif
  if (protected_mode()) {
    addr_modes.default_mode = SEG32;
    }
  else if (v8086_mode()) {
    addr_modes.default_mode = VM86;
    }
  else {
    // real mode, use vm86 for now
    addr_modes.default_mode = VM86;
    }

  // Mark if instruction used opsize or addrsize prefixes
  // Actually, addr_modes.override.address_size is not used,
  // could delete that code.
  is_32 = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b;
  if (i->as_32 == is_32)
    addr_modes.override.address_size = 0;
  else
    addr_modes.override.address_size = ADDR_SIZE_PREFIX;
  if (i->os_32 == is_32)
    addr_modes.override.operand_size = 0;
  else
    addr_modes.override.operand_size = OP_SIZE_PREFIX;

  // For now set access_limit to max.  It seems to be
  // a number from 0..255 denoting how many bytes the
  // current instruction can access according to its
  // memory operand.  255 means >= 255.
access_limit = 0xff;

  // fill in orig eip here in offset
  // fill in CS in selector
  entry_sel_off.offset = BX_CPU_THIS_PTR prev_eip;
  entry_sel_off.selector =
    BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value;

// should set these fields to 0 if mem operand not used
  data_address = (void *) i->rm_addr;
  data_sel_off.offset = i->rm_addr;
  data_sel_off.selector = BX_CPU_THIS_PTR sregs[i->seg].selector.value;

  math_emulate2(addr_modes, i->modrm, i->b1, data_address,
                data_sel_off, entry_sel_off);
}

  unsigned
fpu_get_ds(void)
{
  return(BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value);
}

  void
fpu_set_ax(unsigned short val16)
{
  AX = val16;
//fprintf(stderr, "fpu_set_ax(0x%04x)\n", (unsigned) val16);
}

  void
fpu_verify_area(unsigned what, void *ptr, unsigned n)
{
  bx_segment_reg_t *seg;

  seg = &BX_CPU_THIS_PTR sregs[fpu_iptr->seg];

  if (what == VERIFY_READ) {
    fpu_cpu_ptr->read_virtual_checks(seg, (Bit32u) ptr, n);
    }
  else {  // VERIFY_WRITE
    fpu_cpu_ptr->write_virtual_checks(seg, (Bit32u) ptr, n);
    }
//fprintf(stderr, "verify_area: 0x%x\n", (Bit32u) ptr);
}

  void
FPU_printall(void)
{
  bx_panic("FPU_printall\n");
}

  unsigned
fpu_get_user(void *ptr, unsigned len)
{
  Bit32u val32;
  Bit16u val16;
  Bit8u  val8;

  switch (len) {
    case 1:
      fpu_cpu_ptr->read_virtual_byte(fpu_iptr->seg, (Bit32u) ptr, &val8);
      val32 = val8;
      break;
    case 2:
      fpu_cpu_ptr->read_virtual_word(fpu_iptr->seg, (Bit32u) ptr, &val16);
      val32 = val16;
      break;
    case 4:
      fpu_cpu_ptr->read_virtual_dword(fpu_iptr->seg, (Bit32u) ptr, &val32);
      break;
    default:
      bx_panic("fpu_get_user: len=%u\n", len);
    }
  return(val32);
}

  void
fpu_put_user(unsigned val, void *ptr, unsigned len)
{
  Bit32u val32;
  Bit16u val16;
  Bit8u  val8;

  switch (len) {
    case 1:
      val8 = val;
      fpu_cpu_ptr->write_virtual_byte(fpu_iptr->seg, (Bit32u) ptr, &val8);
      break;
    case 2:
      val16 = val;
      fpu_cpu_ptr->write_virtual_word(fpu_iptr->seg, (Bit32u) ptr, &val16);
      break;
    case 4:
      val32 = val;
      fpu_cpu_ptr->write_virtual_dword(fpu_iptr->seg, (Bit32u) ptr, &val32);
      break;
    default:
      bx_panic("fpu_put_user: len=%u\n", len);
    }
}

  void
math_abort(struct info *info, unsigned int signal)
{
  UNUSED(info); // info is always passed NULL
#if BX_CPU_LEVEL >= 4

// values of signal:
//   SIGILL  : opcodes which are illegal
//   SIGFPE  : unmasked FP exception before WAIT or non-control instruction
//   SIGSEGV : access data beyond segment violation
  switch (signal) {
    case SIGFPE:
      if (fpu_cpu_ptr->cr0.ne == 0) {
        // MSDOS compatibility external interrupt (IRQ13)
        bx_panic("math_abort: MSDOS compatibility not supported yet\n");
        }
      fpu_cpu_ptr->exception(BX_MF_EXCEPTION, 0, 0);
      // execution does not reach here

    case SIGILL:
      bx_panic("math_abort: SIGILL not implemented yet.\n");
      break;
    case SIGSEGV:
      bx_panic("math_abort: SIGSEGV not implemented yet.\n");
      break;
    }

#else
  UNUSED(signal);
  bx_panic("math_abort: CPU<4 not supported yet\n");
#endif
}

  int
printk(const char * fmt, ...)
{
  bx_printf("printk not complete: %s\n", fmt);
  return(0); // for now
}
<|endoftext|>


<commit_before>/*
    kopeteaccountmanager.cpp - Kopete Account Manager

    Copyright (c) 2002-2003 by Martijn Klingens      <klingens@kde.org>
    Copyright (c) 2003      by Olivier Goffart       <ogoffart@tiscalinet.be>

    Kopete    (c) 2002-2003 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 "kopeteaccountmanager.h"

#include <qapplication.h>
#include <qregexp.h>
#include <qfile.h>

#include <kconfig.h>
#include <kdebug.h>
#include <kglobal.h>

#include "kopeteaway.h"
#include "kopeteprotocol.h"
#include "kopetepluginmanager.h"
#include "kopeteaccount.h"

KopeteAccountManager* KopeteAccountManager::s_manager = 0L;

KopeteAccountManager* KopeteAccountManager::manager()
{
	if( !s_manager )
			s_manager = new KopeteAccountManager;

	return s_manager;
}

KopeteAccountManager::KopeteAccountManager()
: QObject( qApp, "KopeteAccountManager" )
{
}

KopeteAccountManager::~KopeteAccountManager()
{
	s_manager = 0L;
}

void KopeteAccountManager::connectAll()
{
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		account->connect();
	}
}

void KopeteAccountManager::disconnectAll()
{
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		account->disconnect();
	}
}

void KopeteAccountManager::setAwayAll( const QString &awayReason )
{
	KopeteAway::setGlobalAway( true );

	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->isConnected() && !account->isAway() )
			account->setAway( true, awayReason.isNull() ? KopeteAway::message() : awayReason );
	}
}

void KopeteAccountManager::setAvailableAll()
{
	KopeteAway::setGlobalAway( false );

	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->isConnected() && account->isAway() )
			account->setAway( false );
	}
}

QColor KopeteAccountManager::guessColor( KopeteProtocol *protocol )
{
	// FIXME: Use a different algoritm. It should check if the color is really not
	//        used - Olivier

	int thisProtocolCounter = 0;
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->protocol()->pluginId() == protocol->pluginId() )
			thisProtocolCounter++;
	}

	// let's figure a color
	QColor color;
	switch ( thisProtocolCounter % 7 )
	{
	case 0:
		color = QColor();
		break;
	case 1:
		color = Qt::red;
		break;
	case 2:
		color = Qt::green;
		break;
	case 3:
		color = Qt::blue;
		break;
	case 4:
		color = Qt::yellow;
		break;
	case 5:
		color = Qt::magenta;
		break;
	case 6:
		color = Qt::cyan;
		break;
	}

	return color;
}

void KopeteAccountManager::registerAccount(KopeteAccount *i)
{

	if ( !i || i->accountId().isNull() )
		return;

	// If this account already exists, do nothing
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if ( ( i->protocol() == account->protocol() ) && ( i->accountId() == account->accountId() ) )
			return;
	}

	m_accounts.append( i );
}

const QPtrList<KopeteAccount>& KopeteAccountManager::accounts() const
{
	return m_accounts;
}

QDict<KopeteAccount> KopeteAccountManager::accounts(const KopeteProtocol *p)
{
	QDict<KopeteAccount> dict;
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( ( account->protocol() == p ) && !account->accountId().isNull() )
			dict.insert( account->accountId(), account );
	}
	return dict;
}

KopeteAccount* KopeteAccountManager::findAccount(const QString& protocolId, const QString& accountId)
{
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->protocol()->pluginId() == protocolId && account->accountId() == accountId )
			return account;
	}
	return 0L;
}

void KopeteAccountManager::removeAccount( KopeteAccount *account )
{
	kdDebug(14010) << k_funcinfo << "Removing account and cleanning up config" << account->accountId() << endl;

	KConfig *config = KGlobal::config();
	QString groupName = account->configGroup();

	delete account;

	// Clean up configuration
	config->deleteGroup( groupName );
	config->sync();
}

void KopeteAccountManager::unregisterAccount( KopeteAccount *account )
{
	kdDebug(14010) << k_funcinfo << "Unregistering account " << account->accountId() << endl;
	m_accounts.remove( account );
	emit accountUnregistered( account );
}

void KopeteAccountManager::save()
{
	kdDebug( 14010 ) << k_funcinfo << endl;

	KConfig *config = KGlobal::config();
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		account->writeConfig( account->configGroup() );
	}

	config->sync();
}

void KopeteAccountManager::load()
{
	connect( KopetePluginManager::self(), SIGNAL( pluginLoaded( KopetePlugin* ) ), SLOT( slotPluginLoaded( KopetePlugin * ) ) );
}

void KopeteAccountManager::slotPluginLoaded( KopetePlugin *plugin )
{
	KopeteProtocol* protocol = dynamic_cast<KopeteProtocol*>( plugin );
	if ( !protocol )
		return;

	// Iterate over all groups that start with "Account_" as those are accounts
	// and parse them if they are from this protocol
	KConfig *config = KGlobal::config();
	QStringList accountGroups = config->groupList().grep( QRegExp( QString::fromLatin1( "^Account_" ) ) );
	for ( QStringList::Iterator it = accountGroups.begin(); it != accountGroups.end(); ++it )
	{
		config->setGroup( *it );

		if ( config->readEntry("Protocol") != protocol->pluginId() )
			continue;

		QString accountId = config->readEntry( "AccountId" );
		if ( accountId.isEmpty() )
		{
			kdDebug(14010) << k_funcinfo << "NOT creating account for empty accountId." << endl;
			continue; //return;
		}

		kdDebug(14010) << k_funcinfo << "Creating account for '" << accountId << "'" << endl;

		KopeteAccount *account = protocol->createNewAccount( accountId );
		if (!account)
		{
			kdDebug(14010) << k_funcinfo << "FAILED creating account for " << accountId << endl;
			continue; //return;
		}
		account->readConfig( *it );
	}
}

void KopeteAccountManager::autoConnect()
{
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->autoLogin() )
			account->connect();
	}
}

/**
 * Called to cause KopeteAccountManager to inform others that
 * an account is fully created and ready for use
 */
void KopeteAccountManager::notifyAccountReady( KopeteAccount *account )
{
	emit accountReady( account );
}

void KopeteAccountManager::moveAccount(KopeteAccount *account , KopeteAccountManager::moveDirrection dirrection)
{
	int index=m_accounts.findRef(account);

	m_accounts.take(index);
	switch(dirrection)
	{
		case Up:
			index--;
			break;
		case Down:
			index++;
			break;
	}

	if(index<0) index=0;

	m_accounts.insert(index, account);

}

#include "kopeteaccountmanager.moc"

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

<commit_msg>- Some kdDebug->kdWarning - Add an Enabled flag in an account to disable them. There won't be a GUI   for this, but it makes it possible for developers to disable them.<commit_after>/*
    kopeteaccountmanager.cpp - Kopete Account Manager

    Copyright (c) 2002-2003 by Martijn Klingens      <klingens@kde.org>
    Copyright (c) 2003      by Olivier Goffart       <ogoffart@tiscalinet.be>

    Kopete    (c) 2002-2003 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 "kopeteaccountmanager.h"

#include <qapplication.h>
#include <qregexp.h>
#include <qfile.h>

#include <kconfig.h>
#include <kdebug.h>
#include <kglobal.h>

#include "kopeteaway.h"
#include "kopeteprotocol.h"
#include "kopetepluginmanager.h"
#include "kopeteaccount.h"

KopeteAccountManager* KopeteAccountManager::s_manager = 0L;

KopeteAccountManager* KopeteAccountManager::manager()
{
	if( !s_manager )
			s_manager = new KopeteAccountManager;

	return s_manager;
}

KopeteAccountManager::KopeteAccountManager()
: QObject( qApp, "KopeteAccountManager" )
{
}

KopeteAccountManager::~KopeteAccountManager()
{
	s_manager = 0L;
}

void KopeteAccountManager::connectAll()
{
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		account->connect();
	}
}

void KopeteAccountManager::disconnectAll()
{
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		account->disconnect();
	}
}

void KopeteAccountManager::setAwayAll( const QString &awayReason )
{
	KopeteAway::setGlobalAway( true );

	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->isConnected() && !account->isAway() )
			account->setAway( true, awayReason.isNull() ? KopeteAway::message() : awayReason );
	}
}

void KopeteAccountManager::setAvailableAll()
{
	KopeteAway::setGlobalAway( false );

	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->isConnected() && account->isAway() )
			account->setAway( false );
	}
}

QColor KopeteAccountManager::guessColor( KopeteProtocol *protocol )
{
	// FIXME: Use a different algoritm. It should check if the color is really not
	//        used - Olivier

	int thisProtocolCounter = 0;
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->protocol()->pluginId() == protocol->pluginId() )
			thisProtocolCounter++;
	}

	// let's figure a color
	QColor color;
	switch ( thisProtocolCounter % 7 )
	{
	case 0:
		color = QColor();
		break;
	case 1:
		color = Qt::red;
		break;
	case 2:
		color = Qt::green;
		break;
	case 3:
		color = Qt::blue;
		break;
	case 4:
		color = Qt::yellow;
		break;
	case 5:
		color = Qt::magenta;
		break;
	case 6:
		color = Qt::cyan;
		break;
	}

	return color;
}

void KopeteAccountManager::registerAccount(KopeteAccount *i)
{

	if ( !i || i->accountId().isNull() )
		return;

	// If this account already exists, do nothing
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if ( ( i->protocol() == account->protocol() ) && ( i->accountId() == account->accountId() ) )
			return;
	}

	m_accounts.append( i );
}

const QPtrList<KopeteAccount>& KopeteAccountManager::accounts() const
{
	return m_accounts;
}

QDict<KopeteAccount> KopeteAccountManager::accounts(const KopeteProtocol *p)
{
	QDict<KopeteAccount> dict;
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( ( account->protocol() == p ) && !account->accountId().isNull() )
			dict.insert( account->accountId(), account );
	}
	return dict;
}

KopeteAccount* KopeteAccountManager::findAccount(const QString& protocolId, const QString& accountId)
{
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->protocol()->pluginId() == protocolId && account->accountId() == accountId )
			return account;
	}
	return 0L;
}

void KopeteAccountManager::removeAccount( KopeteAccount *account )
{
	kdDebug(14010) << k_funcinfo << "Removing account and cleanning up config" << account->accountId() << endl;

	KConfig *config = KGlobal::config();
	QString groupName = account->configGroup();

	delete account;

	// Clean up configuration
	config->deleteGroup( groupName );
	config->sync();
}

void KopeteAccountManager::unregisterAccount( KopeteAccount *account )
{
	kdDebug(14010) << k_funcinfo << "Unregistering account " << account->accountId() << endl;
	m_accounts.remove( account );
	emit accountUnregistered( account );
}

void KopeteAccountManager::save()
{
	kdDebug( 14010 ) << k_funcinfo << endl;

	KConfig *config = KGlobal::config();
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		account->writeConfig( account->configGroup() );
	}

	config->sync();
}

void KopeteAccountManager::load()
{
	connect( KopetePluginManager::self(), SIGNAL( pluginLoaded( KopetePlugin* ) ), SLOT( slotPluginLoaded( KopetePlugin * ) ) );
}

void KopeteAccountManager::slotPluginLoaded( KopetePlugin *plugin )
{
	KopeteProtocol* protocol = dynamic_cast<KopeteProtocol*>( plugin );
	if ( !protocol )
		return;

	// Iterate over all groups that start with "Account_" as those are accounts
	// and parse them if they are from this protocol
	KConfig *config = KGlobal::config();
	QStringList accountGroups = config->groupList().grep( QRegExp( QString::fromLatin1( "^Account_" ) ) );
	for ( QStringList::Iterator it = accountGroups.begin(); it != accountGroups.end(); ++it )
	{
		config->setGroup( *it );

		if ( config->readEntry( "Protocol" ) != protocol->pluginId() )
			continue;

		// There's no GUI for this, but developers may want to disable an account.
		if ( !config->readBoolEntry( "Enabled", true ) )
			continue;

		QString accountId = config->readEntry( "AccountId" );
		if ( accountId.isEmpty() )
		{
			kdWarning( 14010 ) << k_funcinfo << "Not creating account for empty accountId." << endl;
			continue;
		}

		kdDebug( 14010 ) << k_funcinfo << "Creating account for '" << accountId << "'" << endl;

		KopeteAccount *account = protocol->createNewAccount( accountId );
		if ( !account )
		{
			kdWarning( 14010 ) << k_funcinfo << "Failed to create account for '" << accountId << "'" << endl;
			continue;
		}
		account->readConfig( *it );
	}
}

void KopeteAccountManager::autoConnect()
{
	QPtrListIterator<KopeteAccount> it( m_accounts );
	KopeteAccount *account;
	while ( ( account = it.current() ) != 0 )
	{
		++it;
		if( account->autoLogin() )
			account->connect();
	}
}

/**
 * Called to cause KopeteAccountManager to inform others that
 * an account is fully created and ready for use
 */
void KopeteAccountManager::notifyAccountReady( KopeteAccount *account )
{
	emit accountReady( account );
}

void KopeteAccountManager::moveAccount(KopeteAccount *account , KopeteAccountManager::moveDirrection dirrection)
{
	int index=m_accounts.findRef(account);

	m_accounts.take(index);
	switch(dirrection)
	{
		case Up:
			index--;
			break;
		case Down:
			index++;
			break;
	}

	if(index<0) index=0;

	m_accounts.insert(index, account);

}

#include "kopeteaccountmanager.moc"

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

<|endoftext|>


<commit_before>/*
    kopetemessagemanager.cpp - Manages all chats

    Copyright (c) 2002      by Duncan Mac-Vicar Prett <duncan@kde.org>
    Copyright (c) 2002      by Daniel Stone <dstone@kde.org>
    Copyright (c) 2002      by Martijn Klingens <klingens@kde.org>
    Copyright (c) 2002-2003 by Olivier Goffart <ogoffart@tiscalinet.be>
    Copyright (c) 2003      by Jason Keirstead   <jason@keirstead.org>

    Kopete    (c) 2002-2003 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 <kdebug.h>
#include <klocale.h>
#include <kopetenotifyclient.h>
#include <qapplication.h>
#include <kglobal.h>
#include <qregexp.h>
#include <kmessagebox.h>

#include "kopeteaccount.h"
#include "kopetemessagemanager.h"
#include "kopetemessagemanagerfactory.h"
#include "kopeteprefs.h"
#include "kopetemetacontact.h"
#include "kopetecommandhandler.h"
#include "kopeteview.h"

struct KMMPrivate
{
	KopeteContactPtrList mContactList;
	const KopeteContact *mUser;
	QMap<const KopeteContact *, KopeteOnlineStatus> contactStatus;
	KopeteProtocol *mProtocol;
	int mId;
	bool isEmpty;
	bool mCanBeDeleted;
	QDateTime awayTime;
	QString displayName;
	KopeteView *view;
};

KopeteMessageManager::KopeteMessageManager( const KopeteContact *user,
	KopeteContactPtrList others, KopeteProtocol *protocol, int id, const char *name )
: QObject( user->account(), name )
{
	d = new KMMPrivate;
	d->mUser = user;
	d->mProtocol = protocol;
	d->mId = id;
	d->isEmpty= others.isEmpty();
	d->mCanBeDeleted = true;
	d->view=0L;

	for( KopeteContact *c = others.first(); c; c = others.next() )
	{
		addContact(c,true);
	}

	connect( user, SIGNAL( onlineStatusChanged( KopeteContact *, const KopeteOnlineStatus &, const KopeteOnlineStatus & ) ), this,
		SLOT( slotStatusChanged( KopeteContact *, const KopeteOnlineStatus &, const KopeteOnlineStatus & ) ) );

	connect( this, SIGNAL( contactChanged() ), this, SLOT( slotUpdateDisplayName() ) );
}

KopeteMessageManager::~KopeteMessageManager()
{
/*	for( KopeteContact *c = d->mContactList.first(); c; c = d->mContactList.next() )
		c->setConversations( c->conversations() - 1 );*/

	if (!d) return;
	d->mCanBeDeleted = false; //prevent double deletion
	KopeteMessageManagerFactory::factory()->removeSession( this );
	emit(closing( this ) );
	delete d;
}

void KopeteMessageManager::slotStatusChanged( KopeteContact *c, const KopeteOnlineStatus &status, const KopeteOnlineStatus &oldStatus )
{
	if(!KopetePrefs::prefs()->notifyAway())
		return;
	if( status.status() == KopeteOnlineStatus::Away )
	{
		d->awayTime = QDateTime::currentDateTime();
		KopeteMessage msg(c, d->mContactList, i18n("%1 has been marked as away.")
			.arg( QString::fromLatin1("/me") ), KopeteMessage::Outbound, KopeteMessage::PlainText);
		sendMessage( msg );
	}
	else if( oldStatus.status() == KopeteOnlineStatus::Away && status.status() == KopeteOnlineStatus::Online )
	{
		KopeteMessage msg(c, d->mContactList, i18n("%1 is no longer marked as away. Gone since %1")
			.arg( QString::fromLatin1("/me") ).arg(KGlobal::locale()->formatDateTime(d->awayTime, true)), KopeteMessage::Outbound, KopeteMessage::PlainText);
		sendMessage( msg );
	}
}

void KopeteMessageManager::setContactOnlineStatus( const KopeteContact *contact, const KopeteOnlineStatus &status )
{
	d->contactStatus[ contact ] = status;
}

const KopeteOnlineStatus KopeteMessageManager::contactOnlineStatus( const KopeteContact *contact ) const
{
	if( d->contactStatus.contains( contact ) )
		return d->contactStatus[ contact ];

	return contact->onlineStatus();
}

const QString KopeteMessageManager::displayName()
{
	if( d->displayName.isNull() )
	{
		connect( this, SIGNAL( contactChanged() ), this, SLOT( slotUpdateDisplayName() ) );
		slotUpdateDisplayName();
	}

	return d->displayName;
}

void KopeteMessageManager::setDisplayName( const QString &newName )
{
	disconnect( this, SIGNAL( contactChanged() ), this, SLOT( slotUpdateDisplayName() ) );

	d->displayName = newName;

	emit( displayNameChanged() );
}

void KopeteMessageManager::slotUpdateDisplayName()
{
	QString nextDisplayName;

	KopeteContact *c = d->mContactList.first();
	if( c->metaContact() )
		d->displayName = c->metaContact()->displayName();
	else
		d->displayName = c->displayName();

	//If we have only 1 contact, add the status of him
	if( d->mContactList.count() == 1 )
	{
		d->displayName.append( QString::fromLatin1( " (%1)").arg( c->onlineStatus().description() ) );
	}
	else
	{
		while( ( c = d->mContactList.next() ) )
		{
			if( c->metaContact() )
				nextDisplayName = c->metaContact()->displayName();
			else
				nextDisplayName = c->displayName();
			d->displayName.append( QString::fromLatin1( ", " ) ).append( nextDisplayName );
		}
	}

	emit( displayNameChanged() );
}

const KopeteContactPtrList& KopeteMessageManager::members() const
{
	return d->mContactList;
}

const KopeteContact* KopeteMessageManager::user() const
{
	return d->mUser;
}

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

int KopeteMessageManager::mmId() const
{
	return d->mId;
}

void KopeteMessageManager::setMMId( int id )
{
	d->mId = id;
}

void KopeteMessageManager::sendMessage(KopeteMessage &message)
{
	message.setManager(this);
	KopeteMessage sentMessage = message;
	if( !KopeteCommandHandler::commandHandler()->processMessage( message, this ) )
	{
		emit messageSent(sentMessage, this);
		if ( !account()->isAway() || KopetePrefs::prefs()->soundIfAway() )
			KopeteNotifyClient::event( QString::fromLatin1( "kopete_outgoing"), i18n("Outgoing Message Sent") );
	}
	else
		emit( messageSuccess() );
}

void KopeteMessageManager::messageSucceeded()
{
	emit( messageSuccess() );
}

void KopeteMessageManager::appendMessage( KopeteMessage &msg )
{
	msg.setManager(this);

	if( msg.direction() == KopeteMessage::Inbound )
	{
		if( KopetePrefs::prefs()->highlightEnabled() && !user()->displayName().isEmpty() && msg.plainBody().contains( QRegExp(QString::fromLatin1("\\b(%1)\\b").arg(user()->displayName()),false) ) )
			msg.setImportance( KopeteMessage::Highlight );

		emit( messageReceived( msg, this ) );
	}

	emit messageAppended( msg, this );
}

void KopeteMessageManager::addContact( const KopeteContact *c, bool suppress )
{
	if ( d->mContactList.contains(c) )
	{
		kdDebug(14010) << k_funcinfo << "Contact already exists" <<endl;
		emit contactAdded(c, suppress);
	}
	else
	{
		if(d->mContactList.count()==1 && d->isEmpty)
		{
			KopeteContact *old=d->mContactList.first();
			d->mContactList.remove(old);
			d->mContactList.append(c);
			//disconnect (old, SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
			disconnect (old, SIGNAL(onlineStatusChanged( KopeteContact*, const KopeteOnlineStatus&, const KopeteOnlineStatus&)), this, SIGNAL(contactChanged()));
			if(old->metaContact())
				disconnect (old->metaContact(), SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
			emit contactAdded(c, suppress);
			emit contactRemoved(old, QString::null);
		}
		else
		{
			d->mContactList.append(c);
			emit contactAdded(c, suppress);
		}
		//c->setConversations( c->conversations() + 1 );
		//connect (c, SIGNAL(displayNameChanged(const QString &,const QString &)), this, SIGNAL(contactChanged()));
		connect (c, SIGNAL(onlineStatusChanged( KopeteContact*, const KopeteOnlineStatus&, const KopeteOnlineStatus&)), this, SIGNAL(contactChanged()));
		if(c->metaContact())
			connect (c->metaContact(), SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
		connect (c, SIGNAL(contactDestroyed(KopeteContact*)) , this , SLOT(slotContactDestroyed(KopeteContact*)));
	}
	d->isEmpty=false;
	slotUpdateDisplayName();
}

void KopeteMessageManager::removeContact( const KopeteContact *c, const QString& raison )
{
	if(!c || !d->mContactList.contains(c))
		return;

	if(d->mContactList.count()==1)
	{
		kdDebug(14010) << k_funcinfo << "Contact not removed. Keep always one contact" <<endl;
		d->isEmpty=true;
	}
	else
	{
		d->mContactList.remove( c );
		//disconnect (c, SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
		disconnect (c, SIGNAL(onlineStatusChanged( KopeteContact*, const KopeteOnlineStatus&, const KopeteOnlineStatus&)), this, SIGNAL(contactChanged()));
		if(c->metaContact())
			disconnect (c->metaContact(), SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
		disconnect (c, SIGNAL(contactDestroyed(KopeteContact*)) , this , SLOT(slotContactDestroyed(KopeteContact*)));
		//c->setConversations( c->conversations() - 1 );
	}
	emit contactRemoved(c, raison);
	slotUpdateDisplayName();
}

void KopeteMessageManager::receivedTypingMsg( const KopeteContact *c , bool t )
{
	emit(remoteTyping( c, t ));
}

void KopeteMessageManager::receivedTypingMsg( const QString &contactId , bool t )
{
	for( KopeteContact *it = d->mContactList.first(); it; it = d->mContactList.next() )
	{
		if( it->contactId() == contactId )
		{
			receivedTypingMsg( it, t );
			return;
		}
	}
}

void KopeteMessageManager::typing ( bool t )
{
	emit typingMsg(t);
}

void KopeteMessageManager::setCanBeDeleted ( bool b )
{
	d->mCanBeDeleted = b;
	if(b && !d->view)
		deleteLater();
}

KopeteView* KopeteMessageManager::view(bool canCreate  , KopeteMessage::MessageType type )
{
	if(!d->view && canCreate)
	{
		d->view=KopeteMessageManagerFactory::factory()->createView( this , type );
		if(d->view)
			connect( d->view->mainWidget(), SIGNAL( closing( KopeteView * ) ), this, SLOT( slotViewDestroyed( ) ) );
		else
			KMessageBox::error( 0L, i18n( "<qt>An error has occured when creating a new chatwindow. The chtwindow has not been created</qt>" ),
							i18n( "Error while creating the chatwindow - Kopete" )  );

	}
	return d->view;
}

void KopeteMessageManager::slotViewDestroyed()
{
	d->view=0L;
	if(d->mCanBeDeleted)
		deleteLater();
}

KopeteAccount *KopeteMessageManager::account() const
{
	return user()->account();
}

void KopeteMessageManager::slotContactDestroyed(KopeteContact* c)
{
	if(!c || !d->mContactList.contains(c))
		return;

	if(d->mContactList.count()==1)
	{
		deleteLater(); //the contact has been deleted, it is better to delete this
	}
	else
	{
		d->mContactList.remove( c );
		emit contactRemoved(c , QString::null);
	}
}

#include "kopetemessagemanager.moc"

// vim: set noet ts=4 sts=4 sw=4:
<commit_msg>CVS_SILENT fix typo<commit_after>/*
    kopetemessagemanager.cpp - Manages all chats

    Copyright (c) 2002      by Duncan Mac-Vicar Prett <duncan@kde.org>
    Copyright (c) 2002      by Daniel Stone <dstone@kde.org>
    Copyright (c) 2002      by Martijn Klingens <klingens@kde.org>
    Copyright (c) 2002-2003 by Olivier Goffart <ogoffart@tiscalinet.be>
    Copyright (c) 2003      by Jason Keirstead   <jason@keirstead.org>

    Kopete    (c) 2002-2003 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 <kdebug.h>
#include <klocale.h>
#include <kopetenotifyclient.h>
#include <qapplication.h>
#include <kglobal.h>
#include <qregexp.h>
#include <kmessagebox.h>

#include "kopeteaccount.h"
#include "kopetemessagemanager.h"
#include "kopetemessagemanagerfactory.h"
#include "kopeteprefs.h"
#include "kopetemetacontact.h"
#include "kopetecommandhandler.h"
#include "kopeteview.h"

struct KMMPrivate
{
	KopeteContactPtrList mContactList;
	const KopeteContact *mUser;
	QMap<const KopeteContact *, KopeteOnlineStatus> contactStatus;
	KopeteProtocol *mProtocol;
	int mId;
	bool isEmpty;
	bool mCanBeDeleted;
	QDateTime awayTime;
	QString displayName;
	KopeteView *view;
};

KopeteMessageManager::KopeteMessageManager( const KopeteContact *user,
	KopeteContactPtrList others, KopeteProtocol *protocol, int id, const char *name )
: QObject( user->account(), name )
{
	d = new KMMPrivate;
	d->mUser = user;
	d->mProtocol = protocol;
	d->mId = id;
	d->isEmpty= others.isEmpty();
	d->mCanBeDeleted = true;
	d->view=0L;

	for( KopeteContact *c = others.first(); c; c = others.next() )
	{
		addContact(c,true);
	}

	connect( user, SIGNAL( onlineStatusChanged( KopeteContact *, const KopeteOnlineStatus &, const KopeteOnlineStatus & ) ), this,
		SLOT( slotStatusChanged( KopeteContact *, const KopeteOnlineStatus &, const KopeteOnlineStatus & ) ) );

	connect( this, SIGNAL( contactChanged() ), this, SLOT( slotUpdateDisplayName() ) );
}

KopeteMessageManager::~KopeteMessageManager()
{
/*	for( KopeteContact *c = d->mContactList.first(); c; c = d->mContactList.next() )
		c->setConversations( c->conversations() - 1 );*/

	if (!d) return;
	d->mCanBeDeleted = false; //prevent double deletion
	KopeteMessageManagerFactory::factory()->removeSession( this );
	emit(closing( this ) );
	delete d;
}

void KopeteMessageManager::slotStatusChanged( KopeteContact *c, const KopeteOnlineStatus &status, const KopeteOnlineStatus &oldStatus )
{
	if(!KopetePrefs::prefs()->notifyAway())
		return;
	if( status.status() == KopeteOnlineStatus::Away )
	{
		d->awayTime = QDateTime::currentDateTime();
		KopeteMessage msg(c, d->mContactList, i18n("%1 has been marked as away.")
			.arg( QString::fromLatin1("/me") ), KopeteMessage::Outbound, KopeteMessage::PlainText);
		sendMessage( msg );
	}
	else if( oldStatus.status() == KopeteOnlineStatus::Away && status.status() == KopeteOnlineStatus::Online )
	{
		KopeteMessage msg(c, d->mContactList, i18n("%1 is no longer marked as away. Gone since %1")
			.arg( QString::fromLatin1("/me") ).arg(KGlobal::locale()->formatDateTime(d->awayTime, true)), KopeteMessage::Outbound, KopeteMessage::PlainText);
		sendMessage( msg );
	}
}

void KopeteMessageManager::setContactOnlineStatus( const KopeteContact *contact, const KopeteOnlineStatus &status )
{
	d->contactStatus[ contact ] = status;
}

const KopeteOnlineStatus KopeteMessageManager::contactOnlineStatus( const KopeteContact *contact ) const
{
	if( d->contactStatus.contains( contact ) )
		return d->contactStatus[ contact ];

	return contact->onlineStatus();
}

const QString KopeteMessageManager::displayName()
{
	if( d->displayName.isNull() )
	{
		connect( this, SIGNAL( contactChanged() ), this, SLOT( slotUpdateDisplayName() ) );
		slotUpdateDisplayName();
	}

	return d->displayName;
}

void KopeteMessageManager::setDisplayName( const QString &newName )
{
	disconnect( this, SIGNAL( contactChanged() ), this, SLOT( slotUpdateDisplayName() ) );

	d->displayName = newName;

	emit( displayNameChanged() );
}

void KopeteMessageManager::slotUpdateDisplayName()
{
	QString nextDisplayName;

	KopeteContact *c = d->mContactList.first();
	if( c->metaContact() )
		d->displayName = c->metaContact()->displayName();
	else
		d->displayName = c->displayName();

	//If we have only 1 contact, add the status of him
	if( d->mContactList.count() == 1 )
	{
		d->displayName.append( QString::fromLatin1( " (%1)").arg( c->onlineStatus().description() ) );
	}
	else
	{
		while( ( c = d->mContactList.next() ) )
		{
			if( c->metaContact() )
				nextDisplayName = c->metaContact()->displayName();
			else
				nextDisplayName = c->displayName();
			d->displayName.append( QString::fromLatin1( ", " ) ).append( nextDisplayName );
		}
	}

	emit( displayNameChanged() );
}

const KopeteContactPtrList& KopeteMessageManager::members() const
{
	return d->mContactList;
}

const KopeteContact* KopeteMessageManager::user() const
{
	return d->mUser;
}

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

int KopeteMessageManager::mmId() const
{
	return d->mId;
}

void KopeteMessageManager::setMMId( int id )
{
	d->mId = id;
}

void KopeteMessageManager::sendMessage(KopeteMessage &message)
{
	message.setManager(this);
	KopeteMessage sentMessage = message;
	if( !KopeteCommandHandler::commandHandler()->processMessage( message, this ) )
	{
		emit messageSent(sentMessage, this);
		if ( !account()->isAway() || KopetePrefs::prefs()->soundIfAway() )
			KopeteNotifyClient::event( QString::fromLatin1( "kopete_outgoing"), i18n("Outgoing Message Sent") );
	}
	else
		emit( messageSuccess() );
}

void KopeteMessageManager::messageSucceeded()
{
	emit( messageSuccess() );
}

void KopeteMessageManager::appendMessage( KopeteMessage &msg )
{
	msg.setManager(this);

	if( msg.direction() == KopeteMessage::Inbound )
	{
		if( KopetePrefs::prefs()->highlightEnabled() && !user()->displayName().isEmpty() && msg.plainBody().contains( QRegExp(QString::fromLatin1("\\b(%1)\\b").arg(user()->displayName()),false) ) )
			msg.setImportance( KopeteMessage::Highlight );

		emit( messageReceived( msg, this ) );
	}

	emit messageAppended( msg, this );
}

void KopeteMessageManager::addContact( const KopeteContact *c, bool suppress )
{
	if ( d->mContactList.contains(c) )
	{
		kdDebug(14010) << k_funcinfo << "Contact already exists" <<endl;
		emit contactAdded(c, suppress);
	}
	else
	{
		if(d->mContactList.count()==1 && d->isEmpty)
		{
			KopeteContact *old=d->mContactList.first();
			d->mContactList.remove(old);
			d->mContactList.append(c);
			//disconnect (old, SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
			disconnect (old, SIGNAL(onlineStatusChanged( KopeteContact*, const KopeteOnlineStatus&, const KopeteOnlineStatus&)), this, SIGNAL(contactChanged()));
			if(old->metaContact())
				disconnect (old->metaContact(), SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
			emit contactAdded(c, suppress);
			emit contactRemoved(old, QString::null);
		}
		else
		{
			d->mContactList.append(c);
			emit contactAdded(c, suppress);
		}
		//c->setConversations( c->conversations() + 1 );
		//connect (c, SIGNAL(displayNameChanged(const QString &,const QString &)), this, SIGNAL(contactChanged()));
		connect (c, SIGNAL(onlineStatusChanged( KopeteContact*, const KopeteOnlineStatus&, const KopeteOnlineStatus&)), this, SIGNAL(contactChanged()));
		if(c->metaContact())
			connect (c->metaContact(), SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
		connect (c, SIGNAL(contactDestroyed(KopeteContact*)) , this , SLOT(slotContactDestroyed(KopeteContact*)));
	}
	d->isEmpty=false;
	slotUpdateDisplayName();
}

void KopeteMessageManager::removeContact( const KopeteContact *c, const QString& raison )
{
	if(!c || !d->mContactList.contains(c))
		return;

	if(d->mContactList.count()==1)
	{
		kdDebug(14010) << k_funcinfo << "Contact not removed. Keep always one contact" <<endl;
		d->isEmpty=true;
	}
	else
	{
		d->mContactList.remove( c );
		//disconnect (c, SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
		disconnect (c, SIGNAL(onlineStatusChanged( KopeteContact*, const KopeteOnlineStatus&, const KopeteOnlineStatus&)), this, SIGNAL(contactChanged()));
		if(c->metaContact())
			disconnect (c->metaContact(), SIGNAL(displayNameChanged(const QString &, const QString &)), this, SIGNAL(contactChanged()));
		disconnect (c, SIGNAL(contactDestroyed(KopeteContact*)) , this , SLOT(slotContactDestroyed(KopeteContact*)));
		//c->setConversations( c->conversations() - 1 );
	}
	emit contactRemoved(c, raison);
	slotUpdateDisplayName();
}

void KopeteMessageManager::receivedTypingMsg( const KopeteContact *c , bool t )
{
	emit(remoteTyping( c, t ));
}

void KopeteMessageManager::receivedTypingMsg( const QString &contactId , bool t )
{
	for( KopeteContact *it = d->mContactList.first(); it; it = d->mContactList.next() )
	{
		if( it->contactId() == contactId )
		{
			receivedTypingMsg( it, t );
			return;
		}
	}
}

void KopeteMessageManager::typing ( bool t )
{
	emit typingMsg(t);
}

void KopeteMessageManager::setCanBeDeleted ( bool b )
{
	d->mCanBeDeleted = b;
	if(b && !d->view)
		deleteLater();
}

KopeteView* KopeteMessageManager::view(bool canCreate  , KopeteMessage::MessageType type )
{
	if(!d->view && canCreate)
	{
		d->view=KopeteMessageManagerFactory::factory()->createView( this , type );
		if(d->view)
			connect( d->view->mainWidget(), SIGNAL( closing( KopeteView * ) ), this, SLOT( slotViewDestroyed( ) ) );
		else
			KMessageBox::error( 0L, i18n( "<qt>An error has occured when creating a new chatwindow. The chatwindow has not been created</qt>" ),
							i18n( "Error while creating the chatwindow - Kopete" )  );

	}
	return d->view;
}

void KopeteMessageManager::slotViewDestroyed()
{
	d->view=0L;
	if(d->mCanBeDeleted)
		deleteLater();
}

KopeteAccount *KopeteMessageManager::account() const
{
	return user()->account();
}

void KopeteMessageManager::slotContactDestroyed(KopeteContact* c)
{
	if(!c || !d->mContactList.contains(c))
		return;

	if(d->mContactList.count()==1)
	{
		deleteLater(); //the contact has been deleted, it is better to delete this
	}
	else
	{
		d->mContactList.remove( c );
		emit contactRemoved(c , QString::null);
	}
}

#include "kopetemessagemanager.moc"

// vim: set noet ts=4 sts=4 sw=4:
<|endoftext|>


<commit_before>//
// @file main.cc
// @brief Screen capture tool.
// @author Mamoru Kaminaga
// @date 2019-09-21 18:22:39
// Copyright 2019 Mamoru Kaminaga
//
#include <stdio.h>
#include <wchar.h>
#include <windows.h>
#include <windowsx.h>
#include "./capture.h"
#include "./folder_dialog.h"
#include "./key_hook.h"
#include "./png_tool.h"
#include "./resource.h"
#include "./task_tray.h"
#include "./util.h"

namespace {
constexpr wchar_t MODULE_FILE_NAME[] = L"ScreenCaptureTool.exe";
constexpr wchar_t WINDOW_NAME[] = L"ScreenCaptureTool";
constexpr wchar_t CLASS_NAME[] = L"ScreenCaptureTool";
constexpr int TRAY_ICON_ID = 1;
wchar_t save_dir[256] = {0};
CaptureData capture;
}  // namespace

BOOL Cls_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) {
  (void)hwnd;
  (void)lpCreateStruct;

  HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);

  // Initialization of output path
  if (GetModuleFileName(hInstance, save_dir, ARRAYSIZE(save_dir)) == 0) {
    MessageBox(hwnd, L"Failed to get module file name", L"Error", MB_OK);
    PostQuitMessage(0);
    return (-1);
  }
  save_dir[wcslen(save_dir) - wcslen(MODULE_FILE_NAME) - 1] =
      L'\0';  // Module file path is converted to directory.
#ifdef DEBUG
  fwprintf(stderr, L"Module file dir:%ls\n", save_dir);
#endif

  // Initialization of task tray
  if (!SetTaskTrayIcon(hwnd, TRAY_ICON_ID, IDI_ICON1)) {
    MessageBox(hwnd, L"Failed to initialize task tray.\n", L"Error", MB_OK);
    return (-1);
  }

  // Initialization of key hook
  if (!SetKeyHook(hwnd)) {
    MessageBox(hwnd, L"Failed to set key hook.\n", L"Error", MB_OK);
    RemoveTaskTrayIcon(hwnd, TRAY_ICON_ID);
    return (-1);
  }

  // Initialization of capture data
  if (!InitializeCapture(&capture)) {
    MessageBox(hwnd, L"Failed to initialize capture.\n", L"Error", MB_OK);
    RemoveTaskTrayIcon(hwnd, TRAY_ICON_ID);
    RemoveKeyHook();
    return (-1);
  }
  return TRUE;
}

void Cls_OnDestroy(HWND hwnd) {
  (void)hwnd;

  // Finalization of key hook
  RemoveKeyHook();

  // Finalization of task tray
  RemoveTaskTrayIcon(hwnd, TRAY_ICON_ID);

  // Finalization of capture data
  FinalizeCapture(&capture);

  PostQuitMessage(0);
}

void Cls_OnClose(HWND hwnd) { DestroyWindow(hwnd); }

void Cls_OnCommand(HWND hwnd, int id, HWND hWndCtl, UINT codeNotify) {
  (void)hwnd;
  (void)id;
  (void)hWndCtl;
  (void)codeNotify;

  switch (id) {
    case IDM_FOLDER: {
      // Folder select dialog is called.
      wchar_t buffer[256] = {0};
      if (!GetDirectoryName(hwnd, L"Folder select", NULL, buffer)) {
        MessageBox(hwnd, L"Invalid directory", L"Error", MB_OK);
      } else {
        wcscpy_s(save_dir, ARRAYSIZE(save_dir), buffer);
      }
#ifdef DEBUG
      fwprintf(stderr, L"%ls\n", save_dir);
#endif
    } break;
    case IDM_QUIT:
      DestroyWindow(hwnd);
      break;
    default:
      break;
  }
}

void Cls_OnTaskTray(HWND hwnd, UINT id, UINT uMsg) {
  (void)hwnd;

  if (id != TRAY_ICON_ID) {
    return;
  }
  switch (uMsg) {
    case WM_RBUTTONDOWN: {
      // Display menu when right button is clicked on task tray icon.
      POINT point;
      GetCursorPos(&point);
      HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
      HMENU hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));
      HMENU hSubMenu = GetSubMenu(hMenu, 0);
      SetForegroundWindow(hwnd);
      TrackPopupMenu(hSubMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN, point.x,
                     point.y, 0, hwnd, NULL);
      DestroyMenu(hMenu);
      PostMessage(hwnd, WM_NULL, 0, 0);
    } break;
    case WM_LBUTTONDOWN:
      MessageBox(hwnd, L"Screen capture tool.\nCopyright 2019 Mamoru Kaminaga",
                 MODULE_FILE_NAME, MB_OK);
      break;
    default:
      break;
  }
}

void Cls_OnKeyHook(HWND hwnd, WPARAM wParam, LPARAM lParam) {
  (void)hwnd;
  const UINT vk = (UINT)wParam;
  const BOOL fDown = ((lParam & 0x80000000) == 0) ? TRUE : FALSE;

  if (fDown == TRUE) {
    return;
  }

  // Any shutter button is pushed.
  if ((vk == VK_SCROLL) || (vk == VK_PAUSE)) {
    // File is named by time.
    wchar_t file[256] = {0};
    GetTimeString(file, ARRAYSIZE(file));
    wcscat_s(file, ARRAYSIZE(file), L".png");

    // File path is created.
    wchar_t path[256] = {0};
    wcscat_s(path, ARRAYSIZE(path), save_dir);
    wcscat_s(path, ARRAYSIZE(path), L"\\");
    wcscat_s(path, ARRAYSIZE(path), file);
#ifdef DEBUG
    fwprintf(stderr, L"PNG file name:%ls\n", path);
#endif

    // Screen is captured.
    if (!Capture(&capture)) {
      MessageBox(hwnd, L"Failed to capture screen.", L"Error", MB_OK);
      return;
    }
    if (!WritePNGFile(path, capture.png_data)) {
      MessageBox(hwnd, L"Failed to write PNG file.", L"Error", MB_OK);
      return;
    }

    MessageBox(hwnd, file, MODULE_FILE_NAME, MB_OK);
    return;
  }
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
                         LPARAM lParam) {
  switch (message) {
    HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate);
    HANDLE_MSG(hwnd, WM_DESTROY, Cls_OnDestroy);
    HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand);
    HANDLE_MSG(hwnd, WM_CLOSE, Cls_OnClose);
    HANDLE_MSG(hwnd, WM_TASKTRAY, Cls_OnTaskTray);
    HANDLE_MSG(hwnd, WM_KEYHOOK, Cls_OnKeyHook);
    default:
      return DefWindowProc(hwnd, message, wParam, lParam);
  }
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPTSTR lpsCmdLine, int nCmdShow) {
  (void)hPrevInstance;
  (void)lpsCmdLine;
  (void)nCmdShow;

#ifdef DEBUG
  FILE* fp = nullptr;
  AllocConsole();
  _wfreopen_s(&fp, L"CONOUT$", L"w", stdout);
  _wfreopen_s(&fp, L"CONOUT$", L"w", stderr);
  _wfreopen_s(&fp, L"CONIN$", L"r", stdin);
#endif

#ifdef DEBUG
  fwprintf(stdout, L"Hello world to stdout!\n");
  fwprintf(stderr, L"Hello world to stderr!\n");
  fwprintf(stderr, L"\n");
#endif

  // Initialization of COM.
  CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

  WNDCLASS wc;
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = WndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wc.lpszMenuName = NULL;
  wc.lpszClassName = CLASS_NAME;
  if (!RegisterClass(&wc)) {
    return FALSE;
  }

  HWND hWnd = CreateWindow(CLASS_NAME, WINDOW_NAME, WS_DISABLED, CW_USEDEFAULT,
                           CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
                           NULL, hInstance, NULL);
  if (hWnd == NULL) {
    return FALSE;
  }
  ShowWindow(hWnd, SW_HIDE);

  MSG msg;
  while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

#ifdef DEBUG
  FreeConsole();
#endif

  // Finalization of COM.
  CoUninitialize();
  return 0;
}
<commit_msg>Captured dialog now foreground<commit_after>//
// @file main.cc
// @brief Screen capture tool.
// @author Mamoru Kaminaga
// @date 2019-09-21 18:22:39
// Copyright 2019 Mamoru Kaminaga
//
#include <stdio.h>
#include <wchar.h>
#include <windows.h>
#include <windowsx.h>
#include "./capture.h"
#include "./folder_dialog.h"
#include "./key_hook.h"
#include "./png_tool.h"
#include "./resource.h"
#include "./task_tray.h"
#include "./util.h"

namespace {
constexpr wchar_t MODULE_FILE_NAME[] = L"ScreenCaptureTool.exe";
constexpr wchar_t WINDOW_NAME[] = L"ScreenCaptureTool";
constexpr wchar_t CLASS_NAME[] = L"ScreenCaptureTool";
constexpr int TRAY_ICON_ID = 1;
wchar_t save_dir[256] = {0};
CaptureData capture;
}  // namespace

BOOL Cls_OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) {
  (void)hwnd;
  (void)lpCreateStruct;

  HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);

  // Initialization of output path
  if (GetModuleFileName(hInstance, save_dir, ARRAYSIZE(save_dir)) == 0) {
    MessageBox(hwnd, L"Failed to get module file name", L"Error", MB_OK);
    PostQuitMessage(0);
    return (-1);
  }
  save_dir[wcslen(save_dir) - wcslen(MODULE_FILE_NAME) - 1] =
      L'\0';  // Module file path is converted to directory.
#ifdef DEBUG
  fwprintf(stderr, L"Module file dir:%ls\n", save_dir);
#endif

  // Initialization of task tray
  if (!SetTaskTrayIcon(hwnd, TRAY_ICON_ID, IDI_ICON1)) {
    MessageBox(hwnd, L"Failed to initialize task tray.\n", L"Error", MB_OK);
    return (-1);
  }

  // Initialization of key hook
  if (!SetKeyHook(hwnd)) {
    MessageBox(hwnd, L"Failed to set key hook.\n", L"Error", MB_OK);
    RemoveTaskTrayIcon(hwnd, TRAY_ICON_ID);
    return (-1);
  }

  // Initialization of capture data
  if (!InitializeCapture(&capture)) {
    MessageBox(hwnd, L"Failed to initialize capture.\n", L"Error", MB_OK);
    RemoveTaskTrayIcon(hwnd, TRAY_ICON_ID);
    RemoveKeyHook();
    return (-1);
  }
  return TRUE;
}

void Cls_OnDestroy(HWND hwnd) {
  (void)hwnd;

  // Finalization of key hook
  RemoveKeyHook();

  // Finalization of task tray
  RemoveTaskTrayIcon(hwnd, TRAY_ICON_ID);

  // Finalization of capture data
  FinalizeCapture(&capture);

  PostQuitMessage(0);
}

void Cls_OnClose(HWND hwnd) { DestroyWindow(hwnd); }

void Cls_OnCommand(HWND hwnd, int id, HWND hWndCtl, UINT codeNotify) {
  (void)hwnd;
  (void)id;
  (void)hWndCtl;
  (void)codeNotify;

  switch (id) {
    case IDM_FOLDER: {
      // Folder select dialog is called.
      wchar_t buffer[256] = {0};
      if (!GetDirectoryName(hwnd, L"Folder select", NULL, buffer)) {
        MessageBox(hwnd, L"Invalid directory", L"Error", MB_OK);
      } else {
        wcscpy_s(save_dir, ARRAYSIZE(save_dir), buffer);
      }
#ifdef DEBUG
      fwprintf(stderr, L"%ls\n", save_dir);
#endif
    } break;
    case IDM_QUIT:
      DestroyWindow(hwnd);
      break;
    default:
      break;
  }
}

void Cls_OnTaskTray(HWND hwnd, UINT id, UINT uMsg) {
  (void)hwnd;

  if (id != TRAY_ICON_ID) {
    return;
  }
  switch (uMsg) {
    case WM_RBUTTONDOWN: {
      // Display menu when right button is clicked on task tray icon.
      POINT point;
      GetCursorPos(&point);
      HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE);
      HMENU hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));
      HMENU hSubMenu = GetSubMenu(hMenu, 0);
      SetForegroundWindow(hwnd);
      TrackPopupMenu(hSubMenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN, point.x,
                     point.y, 0, hwnd, NULL);
      DestroyMenu(hMenu);
      PostMessage(hwnd, WM_NULL, 0, 0);
    } break;
    case WM_LBUTTONDOWN:
      MessageBox(hwnd, L"Screen capture tool.\nCopyright 2019 Mamoru Kaminaga",
                 MODULE_FILE_NAME, MB_OK);
      break;
    default:
      break;
  }
}

void Cls_OnKeyHook(HWND hwnd, WPARAM wParam, LPARAM lParam) {
  (void)hwnd;
  const UINT vk = (UINT)wParam;
  const BOOL fDown = ((lParam & 0x80000000) == 0) ? TRUE : FALSE;

  if (fDown == TRUE) {
    return;
  }

  // Any shutter button is pushed.
  if ((vk == VK_SCROLL) || (vk == VK_PAUSE)) {
    // File is named by time.
    wchar_t file[256] = {0};
    GetTimeString(file, ARRAYSIZE(file));
    wcscat_s(file, ARRAYSIZE(file), L".png");

    // File path is created.
    wchar_t path[256] = {0};
    wcscat_s(path, ARRAYSIZE(path), save_dir);
    wcscat_s(path, ARRAYSIZE(path), L"\\");
    wcscat_s(path, ARRAYSIZE(path), file);
#ifdef DEBUG
    fwprintf(stderr, L"PNG file name:%ls\n", path);
#endif

    // Screen is captured.
    if (!Capture(&capture)) {
      MessageBox(hwnd, L"Failed to capture screen.", L"Error", MB_OK);
      return;
    }
    if (!WritePNGFile(path, capture.png_data)) {
      MessageBox(hwnd, L"Failed to write PNG file.", L"Error", MB_OK);
      return;
    }

    SetForegroundWindow(hwnd);
    MessageBox(hwnd, file, MODULE_FILE_NAME, MB_OK | MB_TOPMOST);
    return;
  }
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam,
                         LPARAM lParam) {
  switch (message) {
    HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate);
    HANDLE_MSG(hwnd, WM_DESTROY, Cls_OnDestroy);
    HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand);
    HANDLE_MSG(hwnd, WM_CLOSE, Cls_OnClose);
    HANDLE_MSG(hwnd, WM_TASKTRAY, Cls_OnTaskTray);
    HANDLE_MSG(hwnd, WM_KEYHOOK, Cls_OnKeyHook);
    default:
      return DefWindowProc(hwnd, message, wParam, lParam);
  }
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPTSTR lpsCmdLine, int nCmdShow) {
  (void)hPrevInstance;
  (void)lpsCmdLine;
  (void)nCmdShow;

#ifdef DEBUG
  FILE* fp = nullptr;
  AllocConsole();
  _wfreopen_s(&fp, L"CONOUT$", L"w", stdout);
  _wfreopen_s(&fp, L"CONOUT$", L"w", stderr);
  _wfreopen_s(&fp, L"CONIN$", L"r", stdin);
#endif

#ifdef DEBUG
  fwprintf(stdout, L"Hello world to stdout!\n");
  fwprintf(stderr, L"Hello world to stderr!\n");
  fwprintf(stderr, L"\n");
#endif

  // Initialization of COM.
  CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

  WNDCLASS wc;
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = WndProc;
  wc.cbClsExtra = 0;
  wc.cbWndExtra = 0;
  wc.hInstance = hInstance;
  wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  wc.lpszMenuName = NULL;
  wc.lpszClassName = CLASS_NAME;
  if (!RegisterClass(&wc)) {
    return FALSE;
  }

  HWND hWnd = CreateWindow(CLASS_NAME, WINDOW_NAME, WS_DISABLED, CW_USEDEFAULT,
                           CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL,
                           NULL, hInstance, NULL);
  if (hWnd == NULL) {
    return FALSE;
  }
  ShowWindow(hWnd, SW_HIDE);

  MSG msg;
  while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

#ifdef DEBUG
  FreeConsole();
#endif

  // Finalization of COM.
  CoUninitialize();
  return 0;
}
<|endoftext|>


<commit_before>// $Id: SchemaInternal.cpp 3513 2013-06-29 00:27:49Z jamshid.esmaelnezhad $

/*
 * The Software is made available solely for use according to the License Agreement. Any reproduction
 * or redistribution of the Software not in accordance with the License Agreement is expressly prohibited
 * by law, and may result in severe civil and criminal penalties. Violators will be prosecuted to the
 * maximum extent possible.
 *
 * THE SOFTWARE IS WARRANTED, IF AT ALL, ONLY ACCORDING TO THE TERMS OF THE LICENSE AGREEMENT. EXCEPT
 * AS WARRANTED IN THE LICENSE AGREEMENT, SRCH2 INC. HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS WITH
 * REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT.  IN NO EVENT SHALL SRCH2 INC. BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF SOFTWARE.

 * Copyright �� 2010 SRCH2 Inc. All rights reserved
 */

#include "SchemaInternal.h"
#include "util/Assert.h"
#include <map>
#include <vector>
#include <numeric>
#include <string>

using std::vector;
using std::string;
using std::map;
using std::pair;

namespace srch2 {
namespace instantsearch {

SchemaInternal::SchemaInternal(srch2::instantsearch::IndexType indexType,
        srch2::instantsearch::PositionIndexType positionIndexType) {
    this->indexType = indexType;
    this->positionIndexType = positionIndexType;
    this->scoringExpressionString = "1"; // DEFAULT SCORE
    this->nonSearchableAttributeNameToId.clear();
    this->nonSearchableAttributeDefaultValueVector.clear();
    this->nonSearchableAttributeTypeVector.clear();
}

SchemaInternal::SchemaInternal(const SchemaInternal &schemaInternal) {
    this->primaryKey = schemaInternal.primaryKey;
    this->searchableAttributeNameToId =
            schemaInternal.searchableAttributeNameToId;
    this->searchableAttributeBoostVector =
            schemaInternal.searchableAttributeBoostVector;
    this->nonSearchableAttributeNameToId =
            schemaInternal.nonSearchableAttributeNameToId;
    this->nonSearchableAttributeTypeVector =
            schemaInternal.nonSearchableAttributeTypeVector;
    this->nonSearchableAttributeDefaultValueVector =
            schemaInternal.nonSearchableAttributeDefaultValueVector;
    this->scoringExpressionString = schemaInternal.scoringExpressionString;
    this->indexType = schemaInternal.indexType;
    this->positionIndexType = schemaInternal.positionIndexType;
    this->commited = schemaInternal.commited;
}

srch2::instantsearch::IndexType SchemaInternal::getIndexType() const {
    return this->indexType;
}

srch2::instantsearch::PositionIndexType SchemaInternal::getPositionIndexType() const {
    return this->positionIndexType;
}

unsigned SchemaInternal::getBoostSumOfSearchableAttributes() const {
    return std::accumulate(this->searchableAttributeBoostVector.begin(),
            this->searchableAttributeBoostVector.end(), 0);
}

int SchemaInternal::getSearchableAttributeId(
        const string &attributeName) const {
    map<string, unsigned>::const_iterator iter =
            this->searchableAttributeNameToId.find(attributeName.c_str());
    if (iter != this->searchableAttributeNameToId.end()) {
        return iter->second;
    } else {
        return -1;
    }
}

int SchemaInternal::getNonSearchableAttributeId(
        const std::string &nonSearchableAttributeName) const {

    map<string, unsigned>::const_iterator iter =
            this->nonSearchableAttributeNameToId.find(
                    nonSearchableAttributeName.c_str());
    if (iter != this->nonSearchableAttributeNameToId.end()) {
        return iter->second;
    } else {
        return -1;
    }
}

SchemaInternal::~SchemaInternal() {

}

void SchemaInternal::setPrimaryKey(const string &primaryKey) {
    this->primaryKey = primaryKey;
}

const std::string* SchemaInternal::getPrimaryKey() const {
    return &this->primaryKey;
}

int SchemaInternal::setSearchableAttribute(const string &attributeName,
        unsigned attributeBoost) {
    //ASSERT (this->boostVector.size() <= 255);

//    if( this->searchableAttributeNameToId.size() > 255)
//    {
//        return -1;
//    }

    if (attributeBoost < 1 || attributeBoost > 100) {
        attributeBoost = 100;
    }

    map<string, unsigned>::iterator iter;
    iter = this->searchableAttributeNameToId.find(attributeName);
    if (iter != this->searchableAttributeNameToId.end()) {
        this->searchableAttributeBoostVector[iter->second] = attributeBoost;
    } else {
        int searchAttributeMapSize = this->searchableAttributeNameToId.size();
        this->searchableAttributeNameToId[attributeName] =
                searchAttributeMapSize;
        this->searchableAttributeBoostVector.push_back(attributeBoost);
    }
    return this->searchableAttributeNameToId.size() - 1;
}

int SchemaInternal::setNonSearchableAttribute(const std::string &attributeName,
        FilterType type, const std::string & defaultValue) {
//    if (this->nonSearchableAttributeNameToId.size() > 255) {
//        return -1;
//    }

    map<string, unsigned>::iterator iter;
    iter = this->nonSearchableAttributeNameToId.find(attributeName);
    if (iter != this->nonSearchableAttributeNameToId.end()) {
        this->nonSearchableAttributeDefaultValueVector[iter->second] =
                defaultValue;
        this->nonSearchableAttributeTypeVector[iter->second] = type;
    } else {
        unsigned sizeNonSearchable = this->nonSearchableAttributeNameToId.size();
        this->nonSearchableAttributeNameToId[attributeName] = sizeNonSearchable;

        this->nonSearchableAttributeDefaultValueVector.push_back(defaultValue);
        this->nonSearchableAttributeTypeVector.push_back(type);
    }
    return this->nonSearchableAttributeNameToId.size();

}

const std::string* SchemaInternal::getDefaultValueOfNonSearchableAttribute(
        const unsigned nonSearchableAttributeNameId) const {
    if (nonSearchableAttributeNameId
            < this->nonSearchableAttributeDefaultValueVector.size()) {
        return &this->nonSearchableAttributeDefaultValueVector[nonSearchableAttributeNameId];
    } else {
        return NULL;
    }
    return NULL;
}

void SchemaInternal::setScoringExpression(
        const std::string &scoringExpression) {
    this->scoringExpressionString = scoringExpression;
}

const std::string SchemaInternal::getScoringExpression() const {
    return this->scoringExpressionString;
}

FilterType SchemaInternal::getTypeOfNonSearchableAttribute(
        const unsigned nonSearchableAttributeNameId) const {

    if (nonSearchableAttributeNameId
            >= this->nonSearchableAttributeTypeVector.size() || nonSearchableAttributeNameId < 0) {
        ASSERT(false);
        return srch2::instantsearch::ATTRIBUTE_TYPE_TEXT; // TODO default is text, is it ok?
    }
    return this->nonSearchableAttributeTypeVector[nonSearchableAttributeNameId];

}

const std::map<std::string, unsigned> * SchemaInternal::getNonSearchableAttributes() const {
    return &this->nonSearchableAttributeNameToId;
}

unsigned SchemaInternal::getBoostOfSearchableAttribute(
        const unsigned attributeId) const {
    if (attributeId < this->searchableAttributeBoostVector.size()) {
        return this->searchableAttributeBoostVector[attributeId];
    } else {
        return 0;
    }
}

const std::map<std::string, unsigned>& SchemaInternal::getSearchableAttribute() const {
    return this->searchableAttributeNameToId;
}

unsigned SchemaInternal::getNumberOfSearchableAttributes() const {
    return this->searchableAttributeNameToId.size();
}

unsigned SchemaInternal::getNumberOfNonSearchableAttributes() const {

    return this->nonSearchableAttributeNameToId.size();
}

}
}
<commit_msg>Warning fixed.<commit_after>// $Id: SchemaInternal.cpp 3513 2013-06-29 00:27:49Z jamshid.esmaelnezhad $

/*
 * The Software is made available solely for use according to the License Agreement. Any reproduction
 * or redistribution of the Software not in accordance with the License Agreement is expressly prohibited
 * by law, and may result in severe civil and criminal penalties. Violators will be prosecuted to the
 * maximum extent possible.
 *
 * THE SOFTWARE IS WARRANTED, IF AT ALL, ONLY ACCORDING TO THE TERMS OF THE LICENSE AGREEMENT. EXCEPT
 * AS WARRANTED IN THE LICENSE AGREEMENT, SRCH2 INC. HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS WITH
 * REGARD TO THE SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT.  IN NO EVENT SHALL SRCH2 INC. BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF SOFTWARE.

 * Copyright �� 2010 SRCH2 Inc. All rights reserved
 */

#include "SchemaInternal.h"
#include "util/Assert.h"
#include <map>
#include <vector>
#include <numeric>
#include <string>

using std::vector;
using std::string;
using std::map;
using std::pair;

namespace srch2 {
namespace instantsearch {

SchemaInternal::SchemaInternal(srch2::instantsearch::IndexType indexType,
        srch2::instantsearch::PositionIndexType positionIndexType) {
    this->indexType = indexType;
    this->positionIndexType = positionIndexType;
    this->scoringExpressionString = "1"; // DEFAULT SCORE
    this->nonSearchableAttributeNameToId.clear();
    this->nonSearchableAttributeDefaultValueVector.clear();
    this->nonSearchableAttributeTypeVector.clear();
}

SchemaInternal::SchemaInternal(const SchemaInternal &schemaInternal) {
    this->primaryKey = schemaInternal.primaryKey;
    this->searchableAttributeNameToId =
            schemaInternal.searchableAttributeNameToId;
    this->searchableAttributeBoostVector =
            schemaInternal.searchableAttributeBoostVector;
    this->nonSearchableAttributeNameToId =
            schemaInternal.nonSearchableAttributeNameToId;
    this->nonSearchableAttributeTypeVector =
            schemaInternal.nonSearchableAttributeTypeVector;
    this->nonSearchableAttributeDefaultValueVector =
            schemaInternal.nonSearchableAttributeDefaultValueVector;
    this->scoringExpressionString = schemaInternal.scoringExpressionString;
    this->indexType = schemaInternal.indexType;
    this->positionIndexType = schemaInternal.positionIndexType;
    this->commited = schemaInternal.commited;
}

srch2::instantsearch::IndexType SchemaInternal::getIndexType() const {
    return this->indexType;
}

srch2::instantsearch::PositionIndexType SchemaInternal::getPositionIndexType() const {
    return this->positionIndexType;
}

unsigned SchemaInternal::getBoostSumOfSearchableAttributes() const {
    return std::accumulate(this->searchableAttributeBoostVector.begin(),
            this->searchableAttributeBoostVector.end(), 0);
}

int SchemaInternal::getSearchableAttributeId(
        const string &attributeName) const {
    map<string, unsigned>::const_iterator iter =
            this->searchableAttributeNameToId.find(attributeName.c_str());
    if (iter != this->searchableAttributeNameToId.end()) {
        return iter->second;
    } else {
        return -1;
    }
}

int SchemaInternal::getNonSearchableAttributeId(
        const std::string &nonSearchableAttributeName) const {

    map<string, unsigned>::const_iterator iter =
            this->nonSearchableAttributeNameToId.find(
                    nonSearchableAttributeName.c_str());
    if (iter != this->nonSearchableAttributeNameToId.end()) {
        return iter->second;
    } else {
        return -1;
    }
}

SchemaInternal::~SchemaInternal() {

}

void SchemaInternal::setPrimaryKey(const string &primaryKey) {
    this->primaryKey = primaryKey;
}

const std::string* SchemaInternal::getPrimaryKey() const {
    return &this->primaryKey;
}

int SchemaInternal::setSearchableAttribute(const string &attributeName,
        unsigned attributeBoost) {
    //ASSERT (this->boostVector.size() <= 255);

//    if( this->searchableAttributeNameToId.size() > 255)
//    {
//        return -1;
//    }

    if (attributeBoost < 1 || attributeBoost > 100) {
        attributeBoost = 100;
    }

    map<string, unsigned>::iterator iter;
    iter = this->searchableAttributeNameToId.find(attributeName);
    if (iter != this->searchableAttributeNameToId.end()) {
        this->searchableAttributeBoostVector[iter->second] = attributeBoost;
    } else {
        int searchAttributeMapSize = this->searchableAttributeNameToId.size();
        this->searchableAttributeNameToId[attributeName] =
                searchAttributeMapSize;
        this->searchableAttributeBoostVector.push_back(attributeBoost);
    }
    return this->searchableAttributeNameToId.size() - 1;
}

int SchemaInternal::setNonSearchableAttribute(const std::string &attributeName,
        FilterType type, const std::string & defaultValue) {
//    if (this->nonSearchableAttributeNameToId.size() > 255) {
//        return -1;
//    }

    map<string, unsigned>::iterator iter;
    iter = this->nonSearchableAttributeNameToId.find(attributeName);
    if (iter != this->nonSearchableAttributeNameToId.end()) {
        this->nonSearchableAttributeDefaultValueVector[iter->second] =
                defaultValue;
        this->nonSearchableAttributeTypeVector[iter->second] = type;
    } else {
        unsigned sizeNonSearchable = this->nonSearchableAttributeNameToId.size();
        this->nonSearchableAttributeNameToId[attributeName] = sizeNonSearchable;

        this->nonSearchableAttributeDefaultValueVector.push_back(defaultValue);
        this->nonSearchableAttributeTypeVector.push_back(type);
    }
    return this->nonSearchableAttributeNameToId.size();

}

const std::string* SchemaInternal::getDefaultValueOfNonSearchableAttribute(
        const unsigned nonSearchableAttributeNameId) const {
    if (nonSearchableAttributeNameId
            < this->nonSearchableAttributeDefaultValueVector.size()) {
        return &this->nonSearchableAttributeDefaultValueVector[nonSearchableAttributeNameId];
    } else {
        return NULL;
    }
    return NULL;
}

void SchemaInternal::setScoringExpression(
        const std::string &scoringExpression) {
    this->scoringExpressionString = scoringExpression;
}

const std::string SchemaInternal::getScoringExpression() const {
    return this->scoringExpressionString;
}

FilterType SchemaInternal::getTypeOfNonSearchableAttribute(
        const unsigned nonSearchableAttributeNameId) const {

    if (nonSearchableAttributeNameId
            >= this->nonSearchableAttributeTypeVector.size() ) {
        ASSERT(false);
        return srch2::instantsearch::ATTRIBUTE_TYPE_TEXT; // TODO default is text, is it ok?
    }
    return this->nonSearchableAttributeTypeVector[nonSearchableAttributeNameId];

}

const std::map<std::string, unsigned> * SchemaInternal::getNonSearchableAttributes() const {
    return &this->nonSearchableAttributeNameToId;
}

unsigned SchemaInternal::getBoostOfSearchableAttribute(
        const unsigned attributeId) const {
    if (attributeId < this->searchableAttributeBoostVector.size()) {
        return this->searchableAttributeBoostVector[attributeId];
    } else {
        return 0;
    }
}

const std::map<std::string, unsigned>& SchemaInternal::getSearchableAttribute() const {
    return this->searchableAttributeNameToId;
}

unsigned SchemaInternal::getNumberOfSearchableAttributes() const {
    return this->searchableAttributeNameToId.size();
}

unsigned SchemaInternal::getNumberOfNonSearchableAttributes() const {

    return this->nonSearchableAttributeNameToId.size();
}

}
}
<|endoftext|>


<commit_before>/*
 * DesktopWebPage.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopWebPage.hpp"
#include <QWidget>
#include <QtDebug>
#include "DesktopNetworkAccessManager.hpp"
#include "DesktopWindowTracker.hpp"
#include "DesktopSatelliteWindow.hpp"
#include "DesktopSecondaryWindow.hpp"
#include "DesktopMainWindow.hpp"

#include "DesktopUtils.hpp"

extern QString sharedSecret;

namespace desktop {

namespace {

WindowTracker s_windowTracker;

} // anonymous namespace

WebPage::WebPage(QUrl baseUrl, QWidget *parent) :
      QWebPage(parent),
      baseUrl_(baseUrl),
      navigated_(false)
{
   //settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
   settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
   setNetworkAccessManager(new NetworkAccessManager(sharedSecret, parent));
}

void WebPage::setBaseUrl(const QUrl& baseUrl)
{
   baseUrl_ = baseUrl;
}

void WebPage::activateSatelliteWindow(QString name)
{
   BrowserWindow* pSatellite = s_windowTracker.getWindow(name);
   if (pSatellite)
      desktop::raiseAndActivateWindow(pSatellite);
}

void WebPage::prepareForSatelliteWindow(
                              const PendingSatelliteWindow& pendingWnd)
{
   pendingSatelliteWindow_ = pendingWnd;
}

QWebPage* WebPage::createWindow(QWebPage::WebWindowType)
{
   // check if this is a satellite window
   if (!pendingSatelliteWindow_.isEmpty())
   {
      // capture pending window params then clear them (one time only)
      QString name = pendingSatelliteWindow_.name;
      MainWindow* pMainWindow = pendingSatelliteWindow_.pMainWindow;
      int width = pendingSatelliteWindow_.width;
      int height = pendingSatelliteWindow_.height;
      pendingSatelliteWindow_ = PendingSatelliteWindow();

      // check for an existing window of this name
      BrowserWindow* pSatellite = s_windowTracker.getWindow(name);
      if (pSatellite)
      {
         // activate the browser then return NULL to indicate
         // we didn't create a new WebView
         desktop::raiseAndActivateWindow(pSatellite);
         return NULL;
      }
      // create a new window if we didn't find one
      else
      {
         // create and size
         pSatellite = new SatelliteWindow(pMainWindow);
         pSatellite->resize(width, height);

         // try to tile the window (but leave pdf window alone
         // since it is so large)
         if (name != QString::fromAscii("pdf"))
         {
            // calculate location to move to

            // y always attempts to be 25 pixels above then faults back
            // to 25 pixels below if that would be offscreen
            const int OVERLAP = 25;
            int moveY = pMainWindow->y() - OVERLAP;
            if (moveY < 0)
               moveY = pMainWindow->y() + OVERLAP;

            // x is based on centering over main window
            int moveX = pMainWindow->x() +
                        (pMainWindow->width() / 2) -
                        (width / 2);

            // perform movve
            pSatellite->move(moveX, moveY);
         }

         // add to tracker
         s_windowTracker.addWindow(name, pSatellite);

         // show and return the browser
         pSatellite->show();
         return pSatellite->webView()->webPage();
      }
   }
   else
   {
      SecondaryWindow* pWindow = new SecondaryWindow(baseUrl_);
      pWindow->show();
      return pWindow->webView()->webPage();
   }
}

bool WebPage::shouldInterruptJavaScript()
{
   return false;
}

void WebPage::javaScriptConsoleMessage(const QString& message, int /*lineNumber*/, const QString& /*sourceID*/)
{
   qDebug() << message;
}

QString WebPage::userAgentForUrl(const QUrl &url) const
{
   return this->QWebPage::userAgentForUrl(url) + QString::fromAscii(" Qt/") + QString::fromAscii(qVersion());
}

bool WebPage::acceptNavigationRequest(QWebFrame*,
                                       const QNetworkRequest& request,
                                       NavigationType navType)
{
   QUrl url = request.url();

   if (url.toString() == QString::fromAscii("about:blank"))
      return true;

   if (url.scheme() != QString::fromAscii("http")
       && url.scheme() != QString::fromAscii("https")
       && url.scheme() != QString::fromAscii("mailto")
       && url.scheme() != QString::fromAscii("data"))
   {
      qDebug() << url.toString();
      return false;
   }

   // determine if this is a local request (handle internally only if local)
   std::string host = url.host().toStdString();
   bool isLocal = host == "localhost" || host == "127.0.0.1" ||
                  url.scheme() == QString::fromAscii("data");

   if ((baseUrl_.isEmpty() && isLocal) ||
       (url.scheme() == baseUrl_.scheme()
        && url.host() == baseUrl_.host()
        && url.port() == baseUrl_.port()))
   {
      navigated_ = true;
      return true;
   }
   // allow local viewer urls to be handled internally by Qt
   else if (isLocal && !viewerUrl_.isEmpty() &&
            url.toString().startsWith(viewerUrl_))
   {
      navigated_ = true;
      return true;
   }
   else
   {
      desktop::openUrl(url);

      if (!navigated_)
         this->view()->window()->deleteLater();

      return false;
   }
}

}
<commit_msg>always enable webkit developer extras<commit_after>/*
 * DesktopWebPage.cpp
 *
 * Copyright (C) 2009-12 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "DesktopWebPage.hpp"
#include <QWidget>
#include <QtDebug>
#include "DesktopNetworkAccessManager.hpp"
#include "DesktopWindowTracker.hpp"
#include "DesktopSatelliteWindow.hpp"
#include "DesktopSecondaryWindow.hpp"
#include "DesktopMainWindow.hpp"

#include "DesktopUtils.hpp"

extern QString sharedSecret;

namespace desktop {

namespace {

WindowTracker s_windowTracker;

} // anonymous namespace

WebPage::WebPage(QUrl baseUrl, QWidget *parent) :
      QWebPage(parent),
      baseUrl_(baseUrl),
      navigated_(false)
{
   settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
   settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
   setNetworkAccessManager(new NetworkAccessManager(sharedSecret, parent));
}

void WebPage::setBaseUrl(const QUrl& baseUrl)
{
   baseUrl_ = baseUrl;
}

void WebPage::activateSatelliteWindow(QString name)
{
   BrowserWindow* pSatellite = s_windowTracker.getWindow(name);
   if (pSatellite)
      desktop::raiseAndActivateWindow(pSatellite);
}

void WebPage::prepareForSatelliteWindow(
                              const PendingSatelliteWindow& pendingWnd)
{
   pendingSatelliteWindow_ = pendingWnd;
}

QWebPage* WebPage::createWindow(QWebPage::WebWindowType)
{
   // check if this is a satellite window
   if (!pendingSatelliteWindow_.isEmpty())
   {
      // capture pending window params then clear them (one time only)
      QString name = pendingSatelliteWindow_.name;
      MainWindow* pMainWindow = pendingSatelliteWindow_.pMainWindow;
      int width = pendingSatelliteWindow_.width;
      int height = pendingSatelliteWindow_.height;
      pendingSatelliteWindow_ = PendingSatelliteWindow();

      // check for an existing window of this name
      BrowserWindow* pSatellite = s_windowTracker.getWindow(name);
      if (pSatellite)
      {
         // activate the browser then return NULL to indicate
         // we didn't create a new WebView
         desktop::raiseAndActivateWindow(pSatellite);
         return NULL;
      }
      // create a new window if we didn't find one
      else
      {
         // create and size
         pSatellite = new SatelliteWindow(pMainWindow);
         pSatellite->resize(width, height);

         // try to tile the window (but leave pdf window alone
         // since it is so large)
         if (name != QString::fromAscii("pdf"))
         {
            // calculate location to move to

            // y always attempts to be 25 pixels above then faults back
            // to 25 pixels below if that would be offscreen
            const int OVERLAP = 25;
            int moveY = pMainWindow->y() - OVERLAP;
            if (moveY < 0)
               moveY = pMainWindow->y() + OVERLAP;

            // x is based on centering over main window
            int moveX = pMainWindow->x() +
                        (pMainWindow->width() / 2) -
                        (width / 2);

            // perform movve
            pSatellite->move(moveX, moveY);
         }

         // add to tracker
         s_windowTracker.addWindow(name, pSatellite);

         // show and return the browser
         pSatellite->show();
         return pSatellite->webView()->webPage();
      }
   }
   else
   {
      SecondaryWindow* pWindow = new SecondaryWindow(baseUrl_);
      pWindow->show();
      return pWindow->webView()->webPage();
   }
}

bool WebPage::shouldInterruptJavaScript()
{
   return false;
}

void WebPage::javaScriptConsoleMessage(const QString& message, int /*lineNumber*/, const QString& /*sourceID*/)
{
   qDebug() << message;
}

QString WebPage::userAgentForUrl(const QUrl &url) const
{
   return this->QWebPage::userAgentForUrl(url) + QString::fromAscii(" Qt/") + QString::fromAscii(qVersion());
}

bool WebPage::acceptNavigationRequest(QWebFrame*,
                                       const QNetworkRequest& request,
                                       NavigationType navType)
{
   QUrl url = request.url();

   if (url.toString() == QString::fromAscii("about:blank"))
      return true;

   if (url.scheme() != QString::fromAscii("http")
       && url.scheme() != QString::fromAscii("https")
       && url.scheme() != QString::fromAscii("mailto")
       && url.scheme() != QString::fromAscii("data"))
   {
      qDebug() << url.toString();
      return false;
   }

   // determine if this is a local request (handle internally only if local)
   std::string host = url.host().toStdString();
   bool isLocal = host == "localhost" || host == "127.0.0.1" ||
                  url.scheme() == QString::fromAscii("data");

   if ((baseUrl_.isEmpty() && isLocal) ||
       (url.scheme() == baseUrl_.scheme()
        && url.host() == baseUrl_.host()
        && url.port() == baseUrl_.port()))
   {
      navigated_ = true;
      return true;
   }
   // allow local viewer urls to be handled internally by Qt
   else if (isLocal && !viewerUrl_.isEmpty() &&
            url.toString().startsWith(viewerUrl_))
   {
      navigated_ = true;
      return true;
   }
   else
   {
      desktop::openUrl(url);

      if (!navigated_)
         this->view()->window()->deleteLater();

      return false;
   }
}

}
<|endoftext|>