<commit_before>/**
 * Filesystem lib from boost.
 * See http://www.boost.org/doc/libs/1_56_0/libs/filesystem/doc/tutorial.html
 */
/********************* Header Files ***********************/
/* C++ Headers */
#include <iostream> /* Input/output objects. */
//#include <fstream> /* File operations. */
//#include <sstream> /* String stream. */
#include <string> /* C++ String class. */
//#include <new> /* Defines bad_malloc exception, new functions. */
//#include <typeinfo> /* Casting header. */
//#include <exception> /* Top level exception header. */
//#include <stdexcept> /* Derived exception classes. */

/* STL Headers */
#include <vector>
//#include <list>
//#include <deque>
//#include <stack>
//#include <queue>
//#include <priority_queue>
//#include <bitset>
//#include <set> // multiset for multiple keys allowed.
//#include <map> // multimap for multiple keys allowed.
//#include <utility> // Has pair for map.
//#include <algorithm>
//#include <numeric>
//#include <functional> // Functional objects.
//#include <iterator> // Contains back_inserter function and like.

/* C Headers */
//#include <cstdlib>
//#include <cstddef>
//#include <cctype>
//#include <cstring>
//#include <cstdio>
//#include <climits>
//#include <cassert>

/* Project Headers */
#include <boost/foreach.hpp>
#include <boost/date_time.hpp>
#include <gtest/gtest.h>

/******************* Constants/Macros *********************/

/**************** Namespace Declarations ******************/
using std::cin;
using std::cout;
using std::endl;
using std::string;
namespace d = ::boost::gregorian;

/******************* Type Definitions *********************/
/* For enums: Try to namesapce the common elements.
 * typedef enum {
 *	VAL_,
 * } name_e;
 */

/* For structs:
 * typedef struct name_s {
 *	int index;
 * } name_t;
 */

/****************** Class Definitions *********************/

/****************** Global Functions **********************/
TEST(BoostDateTime, SimpleDate) {
    d::date weekStart(2002, d::Feb, 1);
    cout << weekStart;
}

/* Notes:
 * Force call to use another version of virtual function: baseP->Item_base::net_price(42);
 *
 */
<commit_msg>Adding tests for date, neat lib.<commit_after>/**
 * Filesystem lib from boost.
 * See http://www.boost.org/doc/libs/1_56_0/libs/filesystem/doc/tutorial.html
 */
/********************* Header Files ***********************/
/* C++ Headers */
#include <iostream> /* Input/output objects. */
//#include <fstream> /* File operations. */
#include <sstream> /* String stream. */
#include <string> /* C++ String class. */
//#include <new> /* Defines bad_malloc exception, new functions. */
//#include <typeinfo> /* Casting header. */
//#include <exception> /* Top level exception header. */
//#include <stdexcept> /* Derived exception classes. */

/* STL Headers */
#include <vector>
//#include <list>
//#include <deque>
//#include <stack>
//#include <queue>
//#include <priority_queue>
//#include <bitset>
//#include <set> // multiset for multiple keys allowed.
//#include <map> // multimap for multiple keys allowed.
//#include <utility> // Has pair for map.
//#include <algorithm>
//#include <numeric>
//#include <functional> // Functional objects.
//#include <iterator> // Contains back_inserter function and like.

/* C Headers */
//#include <cstdlib>
//#include <cstddef>
//#include <cctype>
//#include <cstring>
//#include <cstdio>
//#include <climits>
//#include <cassert>

/* Project Headers */
#include <boost/foreach.hpp>
#include <boost/date_time.hpp>
#include <gtest/gtest.h>

/******************* Constants/Macros *********************/

/**************** Namespace Declarations ******************/
using std::cin;
using std::cout;
using std::endl;
using std::string;
namespace d = ::boost::gregorian;

/******************* Type Definitions *********************/
/* For enums: Try to namesapce the common elements.
 * typedef enum {
 *	VAL_,
 * } name_e;
 */

/* For structs:
 * typedef struct name_s {
 *	int index;
 * } name_t;
 */

/****************** Class Definitions *********************/

/****************** Global Functions **********************/
void datesEqual(const d::date &dateExpect, const d::date &dateActual) {
    std::stringstream ssA, ssE;

    ssE << dateExpect;
    ssA << dateActual;

    ASSERT_STREQ(ssE.str().c_str(), ssA.str().c_str());
}

TEST(BoostDateTime, DateSimpleCreate) {
    std::stringstream ss;
    d::date date1(2002, d::Feb, 1);

    ss << date1;
    ASSERT_STREQ("2002-Feb-01", ss.str().c_str());
}

TEST(BoostDateTime, DateArithmetic) {
    d::date dateStart(2002, d::Feb, 1), dateExpect(2004, d::Feb, 3);
    d::date dateActual = dateStart + d::years(2) + d::days(2);

    datesEqual(dateExpect, dateActual);
}

TEST(BoostDateTime, DateIterator) {
    std::vector<d::date> vExpect = {d::date(2002, d::Feb, 1),
	d::date(2002, d::Feb, 2), d::date(2002, d::Feb, 3),
	d::date(2002, d::Feb, 4), d::date(2002, d::Feb, 5),
    };
    d::date dateStart(2002, d::Feb, 1), dateEnd(2002, d::Feb, 6);

    /* Iterate the days from a start to end */
    std::vector<d::date>::const_iterator itE = vExpect.begin();
    for(d::day_iterator itA(dateStart); itA != dateEnd; ++itA, ++itE) {
	datesEqual(*itE, *itA);
    }
}

TEST(BoostDateTime, DateGenerator) {
    d::date dateStart(2002, d::Feb, 1);
    d::date dateExpect(2002, d::Feb, 7);
    d::date dateActual = d::next_weekday(dateStart, d::greg_weekday(d::Thursday));

    datesEqual(dateExpect, dateActual);
}

/* Notes:
 * Force call to use another version of virtual function: baseP->Item_base::net_price(42);
 *
 */
<|endoftext|>


<commit_before>// @(#)root/pyroot:$Id$
// Author: Wim Lavrijsen, Apr 2004

// Bindings
#include "PyROOT.h"
#include "TPython.h"
#include "ObjectProxy.h"
#include "RootWrapper.h"
#include "TPyClassGenerator.h"

// ROOT
#include "TROOT.h"
#include "TObject.h"

// Standard
#include <stdio.h>
#include <Riostream.h>
#include <string>

//______________________________________________________________________________
//                          Python interpreter access
//                          =========================
//
// The TPython class allows for access to python objects from CINT. The current
// functionality is only basic: ROOT objects and builtin types can freely cross
// the boundary between the two interpreters, python objects can be instantiated
// and their methods can be called. All other cross-coding is based on strings
// that are run on the python interpreter.
//
// Examples:
//
//  $ cat MyPyClass.py
//  print 'creating class MyPyClass ... '
//
//  class MyPyClass:
//     def __init__( self ):
//        print 'in MyPyClass.__init__'
//
//     def gime( self, what ):
//        return what
//
//  $ root -l
//  // Execute a string of python code.
//  root [0] TPython::Exec( "print \'Hello World!\'" );
//  Hello World!
//
//  // Create a TBrowser on the python side, and transfer it back and forth.
//  // Note the required explicit (void*) cast!
//  root [1] TBrowser* b = (void*)TPython::Eval( "ROOT.TBrowser()" );
//  root [2] TPython::Bind( b, "b" );
//  root [3] b == (void*) TPython::Eval( "b" )
//  (int)1
//
//  // Builtin variables can cross-over by using implicit casts.
//  root [4] int i = TPython::Eval( "1 + 1" );
//  root [5] i
//  (int)2
//
//  // Load a python module with a class definition, and use it.
//  root [6] TPython::LoadMacro( "MyPyClass.py" );
//  creating class MyPyClass ...
//  root [7] MyPyClass m;
//  in MyPyClass.__init__
//  root [8] char* s = m.gime( "aap" );
//  root [9] s
//  (char* 0x41ee7754)"aap"
//
// It is possible to switch between interpreters by calling "TPython::Prompt()"
// on the CINT side, while returning with ^D (EOF). State is preserved between
// successive switches.
//
// The API part provides (direct) C++ access to the bindings functionality of
// PyROOT. It allows verifying that you deal with a PyROOT python object in the
// first place (ObjectProxy_Check for ObjectProxy and any derived types, as well
// as ObjectProxy_CheckExact for ObjectProxy's only); and it allows conversions
// of void* to an ObjectProxy and vice versa.

//- data ---------------------------------------------------------------------
ClassImp(TPython)

namespace {

   PyObject* gMainDict = 0;

   PyObject* gClassString  = 0;
   PyObject* gNameString   = 0;
   PyObject* gModuleString = 0;

} // unnamed namespace

//- static public members ----------------------------------------------------
Bool_t TPython::Initialize()
{
// Private initialization method: setup the python interpreter and load the
// ROOT module.

   static Bool_t isInitialized = kFALSE;
   if ( isInitialized )
      return kTRUE;

   if ( ! Py_IsInitialized() ) {
   // this happens if CINT comes in first
      PyEval_InitThreads();
      Py_Initialize();

   // try again
      if ( ! Py_IsInitialized() ) {
      // give up ...
         std::cerr << "Error: python has not been intialized; returning." << std::endl;
         return kFALSE;
      }

   // set argv
      char* argv[] = { const_cast< char* >( "root" ) };
      PySys_SetArgv( sizeof(argv)/sizeof(argv[0]), argv );

   // force loading of ROOT
      PyRun_SimpleString( const_cast< char* >( "import ROOT" ) );
   }

   if ( ! gMainDict ) {
   // initialize some handy strings
      gClassString  = PyString_FromString( "__class__" );
      gNameString   = PyString_FromString( "__name__" );
      gModuleString = PyString_FromString( "__module__" );

   // retrieve the main dictionary
      gMainDict = PyModule_GetDict(
         PyImport_AddModule( const_cast< char* >( "__main__" ) ) );
      Py_INCREF( gMainDict );
   }

// python side class construction, managed by ROOT
   gROOT->AddClassGenerator( new TPyClassGenerator );

// declare success ...
   isInitialized = kTRUE;
   return kTRUE;
}

//____________________________________________________________________________
void TPython::LoadMacro( const char* name )
{
// Execute the give python script as if it were a macro (effectively an
// execfile in __main__), and create CINT equivalents for any newly available
// python classes.

// setup
   if ( ! Initialize() )
      return;

// obtain a reference to look for new classes later
   PyObject* old = PyDict_Values( gMainDict );

// actual execution
   Exec( (std::string( "execfile(\"" ) + name + "\")").c_str() );

// obtain new __main__ contents
   PyObject* current = PyDict_Values( gMainDict );

// create CINT classes for all new python classes
   for ( int i = 0; i < PyList_GET_SIZE( current ); ++i ) {
      PyObject* value = PyList_GET_ITEM( current, i );
      Py_INCREF( value );

      if ( ! PySequence_Contains( old, value ) ) {
      // collect classes
         if ( PyClass_Check( value ) || PyObject_HasAttrString( value, (char*)"__bases__" ) ) {
         // get full class name (including module)
            PyObject* pyModName = PyObject_GetAttrString( value, (char*)"__module__" );
            PyObject* pyClName  = PyObject_GetAttrString( value, (char*)"__name__" );

            if ( PyErr_Occurred() )
               PyErr_Clear();

            if ( pyModName && pyClName &&\
                 PyString_Check( pyModName ) && PyString_Check( pyClName ) ) {
            // build full, qualified name
               std::string fullname = PyString_AS_STRING( pyModName );
               fullname += '.';
               fullname += PyString_AS_STRING( pyClName );

            // force class creation (this will eventually call TPyClassGenerator)
               TClass::GetClass( fullname.c_str() );
            }

            Py_XDECREF( pyClName );
            Py_XDECREF( pyModName );
         }
      }

      Py_DECREF( value );
   }

   Py_DECREF( current );
   Py_DECREF( old );
}

//____________________________________________________________________________
void TPython::ExecScript( const char* name, int argc, const char** argv )
{
// Execute a python stand-alone script, with argv CLI arguments.
//
// example of use:
//    const char* argv[] = { "1", "2", "3" };
//    TPython::ExecScript( "test.py", sizeof(argv)/sizeof(argv[0]), argv );

// setup
   if ( ! Initialize() )
      return;

// verify arguments
   if ( ! name ) {
      std::cerr << "Error: no file name specified." << std::endl;
      return;
   }

   FILE* fp = fopen( name, "r" );
   if ( ! fp ) {
      std::cerr << "Error: could not open file \"" << name << "\"." << std::endl;
      return;
   }

// setup command line part
   PyObject* oldargv = PySys_GetObject( const_cast< char* >( "argv" ) );
   if ( ! oldargv )                               // e.g. apache
      PyErr_Clear();
   else {
      PyObject* l = PyList_New( PyList_GET_SIZE( oldargv ) );
      for ( int i = 1; i < PyList_GET_SIZE( oldargv ); ++i ) {
         PyObject* item = PyList_GET_ITEM( oldargv, i );
         Py_INCREF( item );
         PyList_SET_ITEM( l, i, item );           // steals ref
      }
      oldargv = l;
   }

   argc += 1;
   const char** argv2 = new const char*[ argc ];
   for ( int i = 1; i < argc; ++i ) argv2[ i ] = argv[ i-1 ];
   argv2[ 0 ] = Py_GetProgramName();
   PySys_SetArgv( argc, const_cast< char** >( argv2 ) );
   delete argv2;

// actual script execution
   PyObject* gbl = PyDict_Copy( gMainDict );
   PyObject* result =   // PyRun_FileEx closes fp (b/c of last argument "1")
      PyRun_FileEx( fp, const_cast< char* >( name ), Py_file_input, gbl, gbl, 1 );
   if ( ! result )
      PyErr_Print();
   Py_XDECREF( result );
   Py_DECREF( gbl );

// restore original command line
   PySys_SetObject( const_cast< char* >( "argv" ), oldargv );
   Py_XDECREF( oldargv );
}

//____________________________________________________________________________
Bool_t TPython::Exec( const char* cmd )
{
// Execute a python statement (e.g. "import ROOT").

// setup
   if ( ! Initialize() )
      return kFALSE;

// execute the command
   PyObject* result =
      PyRun_String( const_cast< char* >( cmd ), Py_file_input, gMainDict, gMainDict );

// test for error
   if ( result ) {
      Py_DECREF( result );
      return kTRUE;
   } else {
      PyErr_Print();
      return kFALSE;
   }
}

//____________________________________________________________________________
const TPyReturn TPython::Eval( const char* expr )
{
// Evaluate a python expression (e.g. "ROOT.TBrowser()").
//
// Caution: do not hold on to the return value: either store it in a builtin
// type (implicit casting will work), or in a pointer to a ROOT object (explicit
// casting to a void* is required).

// setup
   if ( ! Initialize() )
      return TPyReturn();

// evaluate the expression
   PyObject* result =
      PyRun_String( const_cast< char* >( expr ), Py_eval_input, gMainDict, gMainDict );

// report errors as appropriate; return void
   if ( ! result ) {
      PyErr_Print();
      return TPyReturn();
   }

// results that require no converion
   if ( result == Py_None || PyROOT::ObjectProxy_Check( result ) )
      return TPyReturn( result );

// explicit conversion for python type required
   PyObject* pyclass = PyObject_GetAttr( result, gClassString );
   if ( pyclass != 0 ) {
   // retrieve class name and the module in which it resides
      PyObject* name = PyObject_GetAttr( pyclass, gNameString );
      PyObject* module = PyObject_GetAttr( pyclass, gModuleString );

   // concat name
      std::string qname =
         std::string( PyString_AS_STRING( module ) ) + '.' + PyString_AS_STRING( name );
      Py_DECREF( module );
      Py_DECREF( name );
      Py_DECREF( pyclass );

   // locate ROOT style class with this name
      TClass* klass = TClass::GetClass( qname.c_str() );

   // construct general ROOT python object that pretents to be of class 'klass'
      if ( klass != 0 )
         return TPyReturn( result );
   } else
      PyErr_Clear();

// no conversion, return null pointer object
   Py_DECREF( result );
   return TPyReturn();
}

//____________________________________________________________________________
Bool_t TPython::Bind( TObject* object, const char* label )
{
// Bind a ROOT object with, at the python side, the name "label".

// check given address and setup
   if ( ! ( object && Initialize() ) )
      return kFALSE;

// bind object in the main namespace
   TClass* klass = object->IsA();
   if ( klass != 0 ) {
      PyObject* bound = PyROOT::BindRootObject( (void*)object, klass );

      if ( bound ) {
         Bool_t bOk = PyDict_SetItemString( gMainDict, const_cast< char* >( label ), bound ) == 0;
         Py_DECREF( bound );

         return bOk;
      }
   }

   return kFALSE;
}

//____________________________________________________________________________
void TPython::Prompt() {
// Enter an interactive python session (exit with ^D). State is preserved
// between successive calls.

// setup
   if ( ! Initialize() ) {
      return;
   }

// enter i/o interactive mode
   PyRun_InteractiveLoop( stdin, const_cast< char* >( "\0" ) );
}

//____________________________________________________________________________
Bool_t TPython::ObjectProxy_Check( PyObject* pyobject )
{
// Test whether the type of the given pyobject is of ObjectProxy type or any
// derived type.

// setup
   if ( ! Initialize() )
      return kFALSE;

// detailed walk through inheritance hierarchy
   return PyROOT::ObjectProxy_Check( pyobject );
}

//____________________________________________________________________________
Bool_t TPython::ObjectProxy_CheckExact( PyObject* pyobject )
{
// Test whether the type of the given pyobject is ObjectProxy type.

// setup
   if ( ! Initialize() )
      return kFALSE;

// direct pointer comparison of type member
   return PyROOT::ObjectProxy_CheckExact( pyobject );
}

//____________________________________________________________________________
void* TPython::ObjectProxy_AsVoidPtr( PyObject* pyobject )
{
// Extract the object pointer held by the ObjectProxy pyobject.

// setup
   if ( ! Initialize() )
      return 0;

// check validity of cast
   if ( ! PyROOT::ObjectProxy_Check( pyobject ) )
      return 0;

// get held object (may be null)
   return ((PyROOT::ObjectProxy*)pyobject)->GetObject();
}

//____________________________________________________________________________
PyObject* TPython::ObjectProxy_FromVoidPtr( void* addr, const char* classname )
{
// Bind the addr to a python object of class defined by classname.

// setup
   if ( ! Initialize() )
      return 0;

// perform cast (the call will check TClass and addr, and set python errors)
   return PyROOT::BindRootObjectNoCast( addr, TClass::GetClass( classname ), kFALSE );
}
<commit_msg>fix index bug<commit_after>// @(#)root/pyroot:$Id$
// Author: Wim Lavrijsen, Apr 2004

// Bindings
#include "PyROOT.h"
#include "TPython.h"
#include "ObjectProxy.h"
#include "RootWrapper.h"
#include "TPyClassGenerator.h"

// ROOT
#include "TROOT.h"
#include "TObject.h"

// Standard
#include <stdio.h>
#include <Riostream.h>
#include <string>

//______________________________________________________________________________
//                          Python interpreter access
//                          =========================
//
// The TPython class allows for access to python objects from CINT. The current
// functionality is only basic: ROOT objects and builtin types can freely cross
// the boundary between the two interpreters, python objects can be instantiated
// and their methods can be called. All other cross-coding is based on strings
// that are run on the python interpreter.
//
// Examples:
//
//  $ cat MyPyClass.py
//  print 'creating class MyPyClass ... '
//
//  class MyPyClass:
//     def __init__( self ):
//        print 'in MyPyClass.__init__'
//
//     def gime( self, what ):
//        return what
//
//  $ root -l
//  // Execute a string of python code.
//  root [0] TPython::Exec( "print \'Hello World!\'" );
//  Hello World!
//
//  // Create a TBrowser on the python side, and transfer it back and forth.
//  // Note the required explicit (void*) cast!
//  root [1] TBrowser* b = (void*)TPython::Eval( "ROOT.TBrowser()" );
//  root [2] TPython::Bind( b, "b" );
//  root [3] b == (void*) TPython::Eval( "b" )
//  (int)1
//
//  // Builtin variables can cross-over by using implicit casts.
//  root [4] int i = TPython::Eval( "1 + 1" );
//  root [5] i
//  (int)2
//
//  // Load a python module with a class definition, and use it.
//  root [6] TPython::LoadMacro( "MyPyClass.py" );
//  creating class MyPyClass ...
//  root [7] MyPyClass m;
//  in MyPyClass.__init__
//  root [8] char* s = m.gime( "aap" );
//  root [9] s
//  (char* 0x41ee7754)"aap"
//
// It is possible to switch between interpreters by calling "TPython::Prompt()"
// on the CINT side, while returning with ^D (EOF). State is preserved between
// successive switches.
//
// The API part provides (direct) C++ access to the bindings functionality of
// PyROOT. It allows verifying that you deal with a PyROOT python object in the
// first place (ObjectProxy_Check for ObjectProxy and any derived types, as well
// as ObjectProxy_CheckExact for ObjectProxy's only); and it allows conversions
// of void* to an ObjectProxy and vice versa.

//- data ---------------------------------------------------------------------
ClassImp(TPython)

namespace {

   PyObject* gMainDict = 0;

   PyObject* gClassString  = 0;
   PyObject* gNameString   = 0;
   PyObject* gModuleString = 0;

} // unnamed namespace

//- static public members ----------------------------------------------------
Bool_t TPython::Initialize()
{
// Private initialization method: setup the python interpreter and load the
// ROOT module.

   static Bool_t isInitialized = kFALSE;
   if ( isInitialized )
      return kTRUE;

   if ( ! Py_IsInitialized() ) {
   // this happens if CINT comes in first
      PyEval_InitThreads();
      Py_Initialize();

   // try again
      if ( ! Py_IsInitialized() ) {
      // give up ...
         std::cerr << "Error: python has not been intialized; returning." << std::endl;
         return kFALSE;
      }

   // set argv
      char* argv[] = { const_cast< char* >( "root" ) };
      PySys_SetArgv( sizeof(argv)/sizeof(argv[0]), argv );

   // force loading of ROOT
      PyRun_SimpleString( const_cast< char* >( "import ROOT" ) );
   }

   if ( ! gMainDict ) {
   // initialize some handy strings
      gClassString  = PyString_FromString( "__class__" );
      gNameString   = PyString_FromString( "__name__" );
      gModuleString = PyString_FromString( "__module__" );

   // retrieve the main dictionary
      gMainDict = PyModule_GetDict(
         PyImport_AddModule( const_cast< char* >( "__main__" ) ) );
      Py_INCREF( gMainDict );
   }

// python side class construction, managed by ROOT
   gROOT->AddClassGenerator( new TPyClassGenerator );

// declare success ...
   isInitialized = kTRUE;
   return kTRUE;
}

//____________________________________________________________________________
void TPython::LoadMacro( const char* name )
{
// Execute the give python script as if it were a macro (effectively an
// execfile in __main__), and create CINT equivalents for any newly available
// python classes.

// setup
   if ( ! Initialize() )
      return;

// obtain a reference to look for new classes later
   PyObject* old = PyDict_Values( gMainDict );

// actual execution
   Exec( (std::string( "execfile(\"" ) + name + "\")").c_str() );

// obtain new __main__ contents
   PyObject* current = PyDict_Values( gMainDict );

// create CINT classes for all new python classes
   for ( int i = 0; i < PyList_GET_SIZE( current ); ++i ) {
      PyObject* value = PyList_GET_ITEM( current, i );
      Py_INCREF( value );

      if ( ! PySequence_Contains( old, value ) ) {
      // collect classes
         if ( PyClass_Check( value ) || PyObject_HasAttrString( value, (char*)"__bases__" ) ) {
         // get full class name (including module)
            PyObject* pyModName = PyObject_GetAttrString( value, (char*)"__module__" );
            PyObject* pyClName  = PyObject_GetAttrString( value, (char*)"__name__" );

            if ( PyErr_Occurred() )
               PyErr_Clear();

            if ( pyModName && pyClName &&\
                 PyString_Check( pyModName ) && PyString_Check( pyClName ) ) {
            // build full, qualified name
               std::string fullname = PyString_AS_STRING( pyModName );
               fullname += '.';
               fullname += PyString_AS_STRING( pyClName );

            // force class creation (this will eventually call TPyClassGenerator)
               TClass::GetClass( fullname.c_str() );
            }

            Py_XDECREF( pyClName );
            Py_XDECREF( pyModName );
         }
      }

      Py_DECREF( value );
   }

   Py_DECREF( current );
   Py_DECREF( old );
}

//____________________________________________________________________________
void TPython::ExecScript( const char* name, int argc, const char** argv )
{
// Execute a python stand-alone script, with argv CLI arguments.
//
// example of use:
//    const char* argv[] = { "1", "2", "3" };
//    TPython::ExecScript( "test.py", sizeof(argv)/sizeof(argv[0]), argv );

// setup
   if ( ! Initialize() )
      return;

// verify arguments
   if ( ! name ) {
      std::cerr << "Error: no file name specified." << std::endl;
      return;
   }

   FILE* fp = fopen( name, "r" );
   if ( ! fp ) {
      std::cerr << "Error: could not open file \"" << name << "\"." << std::endl;
      return;
   }

// store a copy of the old cli for restoration
   PyObject* oldargv = PySys_GetObject( const_cast< char* >( "argv" ) );   // borrowed
   if ( ! oldargv )                               // e.g. apache
      PyErr_Clear();
   else {
      PyObject* l = PyList_New( PyList_GET_SIZE( oldargv ) );
      for ( int i = 0; i < PyList_GET_SIZE( oldargv ); ++i ) {
         PyObject* item = PyList_GET_ITEM( oldargv, i );
         Py_INCREF( item );
         PyList_SET_ITEM( l, i, item );           // steals ref
      }
      oldargv = l;
   }

// create and set (add progam name) the new command line
   argc += 1;
   const char** argv2 = new const char*[ argc ];
   for ( int i = 1; i < argc; ++i ) argv2[ i ] = argv[ i-1 ];
   argv2[ 0 ] = Py_GetProgramName();
   PySys_SetArgv( argc, const_cast< char** >( argv2 ) );
   delete argv2;

// actual script execution
   PyObject* gbl = PyDict_Copy( gMainDict );
   PyObject* result =   // PyRun_FileEx closes fp (b/c of last argument "1")
      PyRun_FileEx( fp, const_cast< char* >( name ), Py_file_input, gbl, gbl, 1 );
   if ( ! result )
      PyErr_Print();
   Py_XDECREF( result );
   Py_DECREF( gbl );

// restore original command line
   if ( oldargv ) {
      PySys_SetObject( const_cast< char* >( "argv" ), oldargv );
      Py_DECREF( oldargv );
   }
}

//____________________________________________________________________________
Bool_t TPython::Exec( const char* cmd )
{
// Execute a python statement (e.g. "import ROOT").

// setup
   if ( ! Initialize() )
      return kFALSE;

// execute the command
   PyObject* result =
      PyRun_String( const_cast< char* >( cmd ), Py_file_input, gMainDict, gMainDict );

// test for error
   if ( result ) {
      Py_DECREF( result );
      return kTRUE;
   } else {
      PyErr_Print();
      return kFALSE;
   }
}

//____________________________________________________________________________
const TPyReturn TPython::Eval( const char* expr )
{
// Evaluate a python expression (e.g. "ROOT.TBrowser()").
//
// Caution: do not hold on to the return value: either store it in a builtin
// type (implicit casting will work), or in a pointer to a ROOT object (explicit
// casting to a void* is required).

// setup
   if ( ! Initialize() )
      return TPyReturn();

// evaluate the expression
   PyObject* result =
      PyRun_String( const_cast< char* >( expr ), Py_eval_input, gMainDict, gMainDict );

// report errors as appropriate; return void
   if ( ! result ) {
      PyErr_Print();
      return TPyReturn();
   }

// results that require no converion
   if ( result == Py_None || PyROOT::ObjectProxy_Check( result ) )
      return TPyReturn( result );

// explicit conversion for python type required
   PyObject* pyclass = PyObject_GetAttr( result, gClassString );
   if ( pyclass != 0 ) {
   // retrieve class name and the module in which it resides
      PyObject* name = PyObject_GetAttr( pyclass, gNameString );
      PyObject* module = PyObject_GetAttr( pyclass, gModuleString );

   // concat name
      std::string qname =
         std::string( PyString_AS_STRING( module ) ) + '.' + PyString_AS_STRING( name );
      Py_DECREF( module );
      Py_DECREF( name );
      Py_DECREF( pyclass );

   // locate ROOT style class with this name
      TClass* klass = TClass::GetClass( qname.c_str() );

   // construct general ROOT python object that pretents to be of class 'klass'
      if ( klass != 0 )
         return TPyReturn( result );
   } else
      PyErr_Clear();

// no conversion, return null pointer object
   Py_DECREF( result );
   return TPyReturn();
}

//____________________________________________________________________________
Bool_t TPython::Bind( TObject* object, const char* label )
{
// Bind a ROOT object with, at the python side, the name "label".

// check given address and setup
   if ( ! ( object && Initialize() ) )
      return kFALSE;

// bind object in the main namespace
   TClass* klass = object->IsA();
   if ( klass != 0 ) {
      PyObject* bound = PyROOT::BindRootObject( (void*)object, klass );

      if ( bound ) {
         Bool_t bOk = PyDict_SetItemString( gMainDict, const_cast< char* >( label ), bound ) == 0;
         Py_DECREF( bound );

         return bOk;
      }
   }

   return kFALSE;
}

//____________________________________________________________________________
void TPython::Prompt() {
// Enter an interactive python session (exit with ^D). State is preserved
// between successive calls.

// setup
   if ( ! Initialize() ) {
      return;
   }

// enter i/o interactive mode
   PyRun_InteractiveLoop( stdin, const_cast< char* >( "\0" ) );
}

//____________________________________________________________________________
Bool_t TPython::ObjectProxy_Check( PyObject* pyobject )
{
// Test whether the type of the given pyobject is of ObjectProxy type or any
// derived type.

// setup
   if ( ! Initialize() )
      return kFALSE;

// detailed walk through inheritance hierarchy
   return PyROOT::ObjectProxy_Check( pyobject );
}

//____________________________________________________________________________
Bool_t TPython::ObjectProxy_CheckExact( PyObject* pyobject )
{
// Test whether the type of the given pyobject is ObjectProxy type.

// setup
   if ( ! Initialize() )
      return kFALSE;

// direct pointer comparison of type member
   return PyROOT::ObjectProxy_CheckExact( pyobject );
}

//____________________________________________________________________________
void* TPython::ObjectProxy_AsVoidPtr( PyObject* pyobject )
{
// Extract the object pointer held by the ObjectProxy pyobject.

// setup
   if ( ! Initialize() )
      return 0;

// check validity of cast
   if ( ! PyROOT::ObjectProxy_Check( pyobject ) )
      return 0;

// get held object (may be null)
   return ((PyROOT::ObjectProxy*)pyobject)->GetObject();
}

//____________________________________________________________________________
PyObject* TPython::ObjectProxy_FromVoidPtr( void* addr, const char* classname )
{
// Bind the addr to a python object of class defined by classname.

// setup
   if ( ! Initialize() )
      return 0;

// perform cast (the call will check TClass and addr, and set python errors)
   return PyROOT::BindRootObjectNoCast( addr, TClass::GetClass( classname ), kFALSE );
}
<|endoftext|>


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

#include "controller/SlsPageSelector.hxx"

#include "SlideSorter.hxx"
#include "SlideSorterViewShell.hxx"
#include "controller/SlideSorterController.hxx"
#include "controller/SlsSelectionManager.hxx"
#include "controller/SlsAnimator.hxx"
#include "controller/SlsCurrentSlideManager.hxx"
#include "controller/SlsVisibleAreaManager.hxx"
#include "model/SlsPageDescriptor.hxx"
#include "model/SlsPageEnumerationProvider.hxx"
#include "model/SlideSorterModel.hxx"
#include "view/SlideSorterView.hxx"

#include "sdpage.hxx"
#include "ViewShell.hxx"
#include "DrawViewShell.hxx"
#include "ViewShellBase.hxx"
#include <com/sun/star/drawing/XDrawView.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <boost/shared_ptr.hpp>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::sd::slidesorter::model;
using namespace ::sd::slidesorter::view;

namespace sd { namespace slidesorter { namespace controller {

PageSelector::PageSelector (SlideSorter& rSlideSorter)
    : mrModel(rSlideSorter.GetModel()),
      mrSlideSorter(rSlideSorter),
      mrController(mrSlideSorter.GetController()),
      mnSelectedPageCount(0),
      mnBroadcastDisableLevel(0),
      mbSelectionChangeBroadcastPending(false),
      mpMostRecentlySelectedPage(),
      mpSelectionAnchor(),
      mpCurrentPage(),
      mnUpdateLockCount(0),
      mbIsUpdateCurrentPagePending(true)
{
    CountSelectedPages ();
}

void PageSelector::SelectAllPages (void)
{
    VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
    PageSelector::UpdateLock aLock (*this);

    int nPageCount = mrModel.GetPageCount();
    for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
        SelectPage(nPageIndex);
}

void PageSelector::DeselectAllPages (void)
{
    VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
    PageSelector::UpdateLock aLock (*this);

    int nPageCount = mrModel.GetPageCount();
    for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
        DeselectPage(nPageIndex);

    DBG_ASSERT (mnSelectedPageCount==0,
        "PageSelector::DeselectAllPages: the selected pages counter is not 0");
    mnSelectedPageCount = 0;
    mpSelectionAnchor.reset();
}

void PageSelector::GetCoreSelection (void)
{
    PageSelector::UpdateLock aLock (*this);

    bool bSelectionHasChanged (true);
    mnSelectedPageCount = 0;
    model::PageEnumeration aAllPages (
        model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
    while (aAllPages.HasMoreElements())
    {
        model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
        if (pDescriptor->GetCoreSelection())
        {
            mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(pDescriptor);
            mrSlideSorter.GetView().RequestRepaint(pDescriptor);
            bSelectionHasChanged = true;
        }

        if (pDescriptor->HasState(PageDescriptor::ST_Selected))
            mnSelectedPageCount++;
    }

    if (bSelectionHasChanged)
    {
        if (mnBroadcastDisableLevel > 0)
            mbSelectionChangeBroadcastPending = true;
        else
            mrController.GetSelectionManager()->SelectionHasChanged();
    }
}

void PageSelector::SetCoreSelection (void)
{
    model::PageEnumeration aAllPages (
        model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
    while (aAllPages.HasMoreElements())
    {
        model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
        pDescriptor->SetCoreSelection();
    }
}

void PageSelector::SelectPage (int nPageIndex)
{
    SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
    if (pDescriptor.get() != NULL)
        SelectPage(pDescriptor);
}

void PageSelector::SelectPage (const SdPage* pPage)
{
    const sal_Int32 nPageIndex (mrModel.GetIndex(pPage));
    SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
    if (pDescriptor.get()!=NULL && pDescriptor->GetPage()==pPage)
        SelectPage(pDescriptor);
}

void PageSelector::SelectPage (const SharedPageDescriptor& rpDescriptor)
{
    if (rpDescriptor.get()!=NULL
        && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, true))
    {
        ++mnSelectedPageCount;
        mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor,true);
        mrSlideSorter.GetView().RequestRepaint(rpDescriptor);

        mpMostRecentlySelectedPage = rpDescriptor;
        if (mpSelectionAnchor == 0)
            mpSelectionAnchor = rpDescriptor;

        if (mnBroadcastDisableLevel > 0)
            mbSelectionChangeBroadcastPending = true;
        else
            mrController.GetSelectionManager()->SelectionHasChanged();
        UpdateCurrentPage();

        CheckConsistency();
    }
}

void PageSelector::DeselectPage (
    int nPageIndex,
    const bool bUpdateCurrentPage)
{
    model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
    if (pDescriptor.get() != NULL)
        DeselectPage(pDescriptor, bUpdateCurrentPage);
}

void PageSelector::DeselectPage (
    const SharedPageDescriptor& rpDescriptor,
    const bool bUpdateCurrentPage)
{
    if (rpDescriptor.get()!=NULL
        && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, false))
    {
        --mnSelectedPageCount;
        mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor);
        mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
        if (mpMostRecentlySelectedPage == rpDescriptor)
            mpMostRecentlySelectedPage.reset();
        if (mnBroadcastDisableLevel > 0)
            mbSelectionChangeBroadcastPending = true;
        else
            mrController.GetSelectionManager()->SelectionHasChanged();
        if (bUpdateCurrentPage)
            UpdateCurrentPage();

        CheckConsistency();
    }
}

void PageSelector::CheckConsistency (void) const
{
    int nSelectionCount (0);
    for (int nPageIndex=0,nPageCount=mrModel.GetPageCount(); nPageIndex<nPageCount; nPageIndex++)
    {
        SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
        assert(pDescriptor);
        if (pDescriptor->HasState(PageDescriptor::ST_Selected))
            ++nSelectionCount;
    }
    if (nSelectionCount!=mnSelectedPageCount)
    {
        // #i120020# The former call to assert(..) internally calls
        // SlideSorterModel::GetPageDescriptor which will crash in this situation
        // (only in non-pro code). All what is wanted there is to assert it (the
        // error is already detected), so do this directly.
        OSL_ENSURE(false, "PageSelector: Consistency error (!)");
    }
}

bool PageSelector::IsPageSelected (int nPageIndex)
{
    SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
    if (pDescriptor.get() != NULL)
        return pDescriptor->HasState(PageDescriptor::ST_Selected);
    else
        return false;
}

int PageSelector::GetPageCount (void) const
{
    return mrModel.GetPageCount();
}

void PageSelector::CountSelectedPages (void)
{
    mnSelectedPageCount = 0;
    model::PageEnumeration aSelectedPages (
        model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
    while (aSelectedPages.HasMoreElements())
    {
        mnSelectedPageCount++;
        aSelectedPages.GetNextElement();
    }
}

void PageSelector::EnableBroadcasting (void)
{
    if (mnBroadcastDisableLevel > 0)
        mnBroadcastDisableLevel --;
    if (mnBroadcastDisableLevel==0 && mbSelectionChangeBroadcastPending)
    {
        mrController.GetSelectionManager()->SelectionHasChanged();
        mbSelectionChangeBroadcastPending = false;
    }
}

void PageSelector::DisableBroadcasting (void)
{
    mnBroadcastDisableLevel ++;
}

::boost::shared_ptr<PageSelector::PageSelection> PageSelector::GetPageSelection (void) const
{
    ::boost::shared_ptr<PageSelection> pSelection (new PageSelection());
    pSelection->reserve(GetSelectedPageCount());

    int nPageCount = GetPageCount();
    for (int nIndex=0; nIndex<nPageCount; nIndex++)
    {
        SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
        if (pDescriptor.get()!=NULL && pDescriptor->HasState(PageDescriptor::ST_Selected))
            pSelection->push_back(pDescriptor->GetPage());
    }

    return pSelection;
}

void PageSelector::SetPageSelection (
    const ::boost::shared_ptr<PageSelection>& rpSelection,
    const bool bUpdateCurrentPage)
{
    PageSelection::const_iterator iPage;
    for (iPage=rpSelection->begin(); iPage!=rpSelection->end(); ++iPage)
        SelectPage(*iPage);
    if (bUpdateCurrentPage)
        UpdateCurrentPage();
}

void PageSelector::UpdateCurrentPage (const bool bUpdateOnlyWhenPending)
{
    if (mnUpdateLockCount > 0)
    {
        mbIsUpdateCurrentPagePending = true;
        return;
    }

    if ( ! mbIsUpdateCurrentPagePending && bUpdateOnlyWhenPending)
        return;

    mbIsUpdateCurrentPagePending = false;

    // Make the first selected page the current page.
    SharedPageDescriptor pCurrentPageDescriptor;
    const sal_Int32 nPageCount (GetPageCount());
    for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex)
    {
        SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
        if ( ! pDescriptor)
            continue;
        if (pDescriptor->HasState(PageDescriptor::ST_Selected))
        {
            pCurrentPageDescriptor = pDescriptor;
            break;
        }
    }
    if ( ! pCurrentPageDescriptor && nPageCount>0)
    {
        // No page is selected.  Make the first slide the current page.
        pCurrentPageDescriptor = mrModel.GetPageDescriptor(0);
    }

    if (pCurrentPageDescriptor)
    {
        // Switching the current slide normally sets also the
        // selection to just the new current slide.  To prevent that,
        // we store (and at the end of this scope restore) the current
        // selection.
        ::boost::shared_ptr<PageSelection> pSelection (GetPageSelection());

        mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pCurrentPageDescriptor);

        // Restore the selection and prevent a recursive call to
        // UpdateCurrentPage().
        SetPageSelection(pSelection, false);
    }
}

//===== PageSelector::UpdateLock ==============================================

PageSelector::UpdateLock::UpdateLock (SlideSorter& rSlideSorter)
    : mpSelector(&rSlideSorter.GetController().GetPageSelector())
{
    ++mpSelector->mnUpdateLockCount;
}

PageSelector::UpdateLock::UpdateLock (PageSelector& rSelector)
    : mpSelector(&rSelector)
{
    ++mpSelector->mnUpdateLockCount;
}

PageSelector::UpdateLock::~UpdateLock (void)
{
    Release();
}

void PageSelector::UpdateLock::Release (void)
{
    if (mpSelector != NULL)
    {
        --mpSelector->mnUpdateLockCount;
        OSL_ASSERT(mpSelector->mnUpdateLockCount >= 0);
        if (mpSelector->mnUpdateLockCount == 0)
            mpSelector->UpdateCurrentPage(true);

        mpSelector = NULL;
    }
}

//===== PageSelector::BroadcastLock ==============================================

PageSelector::BroadcastLock::BroadcastLock (SlideSorter& rSlideSorter)
    : mrSelector(rSlideSorter.GetController().GetPageSelector())
{
    mrSelector.DisableBroadcasting();
}

PageSelector::BroadcastLock::BroadcastLock (PageSelector& rSelector)
    : mrSelector(rSelector)
{
    mrSelector.DisableBroadcasting();
}

PageSelector::BroadcastLock::~BroadcastLock (void)
{
    mrSelector.EnableBroadcasting();
}

} } } // end of namespace ::sd::slidesorter::controller

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

#include "controller/SlsPageSelector.hxx"

#include "SlideSorter.hxx"
#include "SlideSorterViewShell.hxx"
#include "controller/SlideSorterController.hxx"
#include "controller/SlsSelectionManager.hxx"
#include "controller/SlsAnimator.hxx"
#include "controller/SlsCurrentSlideManager.hxx"
#include "controller/SlsVisibleAreaManager.hxx"
#include "model/SlsPageDescriptor.hxx"
#include "model/SlsPageEnumerationProvider.hxx"
#include "model/SlideSorterModel.hxx"
#include "view/SlideSorterView.hxx"

#include "sdpage.hxx"
#include "ViewShell.hxx"
#include "DrawViewShell.hxx"
#include "ViewShellBase.hxx"
#include <com/sun/star/drawing/XDrawView.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <boost/shared_ptr.hpp>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::sd::slidesorter::model;
using namespace ::sd::slidesorter::view;

namespace sd { namespace slidesorter { namespace controller {

PageSelector::PageSelector (SlideSorter& rSlideSorter)
    : mrModel(rSlideSorter.GetModel()),
      mrSlideSorter(rSlideSorter),
      mrController(mrSlideSorter.GetController()),
      mnSelectedPageCount(0),
      mnBroadcastDisableLevel(0),
      mbSelectionChangeBroadcastPending(false),
      mpMostRecentlySelectedPage(),
      mpSelectionAnchor(),
      mpCurrentPage(),
      mnUpdateLockCount(0),
      mbIsUpdateCurrentPagePending(true)
{
    CountSelectedPages ();
}

void PageSelector::SelectAllPages (void)
{
    VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
    PageSelector::UpdateLock aLock (*this);

    int nPageCount = mrModel.GetPageCount();
    for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
        SelectPage(nPageIndex);
}

void PageSelector::DeselectAllPages (void)
{
    VisibleAreaManager::TemporaryDisabler aDisabler (mrSlideSorter);
    PageSelector::UpdateLock aLock (*this);

    int nPageCount = mrModel.GetPageCount();
    for (int nPageIndex=0; nPageIndex<nPageCount; nPageIndex++)
        DeselectPage(nPageIndex);

    DBG_ASSERT (mnSelectedPageCount==0,
        "PageSelector::DeselectAllPages: the selected pages counter is not 0");
    mnSelectedPageCount = 0;
    mpSelectionAnchor.reset();
}

void PageSelector::GetCoreSelection (void)
{
    PageSelector::UpdateLock aLock (*this);

    bool bSelectionHasChanged (true);
    mnSelectedPageCount = 0;
    model::PageEnumeration aAllPages (
        model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
    while (aAllPages.HasMoreElements())
    {
        model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
        if (pDescriptor->GetCoreSelection())
        {
            mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(pDescriptor);
            mrSlideSorter.GetView().RequestRepaint(pDescriptor);
            bSelectionHasChanged = true;
        }

        if (pDescriptor->HasState(PageDescriptor::ST_Selected))
            mnSelectedPageCount++;
    }

    if (bSelectionHasChanged)
    {
        if (mnBroadcastDisableLevel > 0)
            mbSelectionChangeBroadcastPending = true;
        else
            mrController.GetSelectionManager()->SelectionHasChanged();
    }
}

void PageSelector::SetCoreSelection (void)
{
    model::PageEnumeration aAllPages (
        model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
    while (aAllPages.HasMoreElements())
    {
        model::SharedPageDescriptor pDescriptor (aAllPages.GetNextElement());
        pDescriptor->SetCoreSelection();
    }
}

void PageSelector::SelectPage (int nPageIndex)
{
    SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
    if (pDescriptor.get() != NULL)
        SelectPage(pDescriptor);
}

void PageSelector::SelectPage (const SdPage* pPage)
{
    const sal_Int32 nPageIndex (mrModel.GetIndex(pPage));
    SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
    if (pDescriptor.get()!=NULL && pDescriptor->GetPage()==pPage)
        SelectPage(pDescriptor);
}

void PageSelector::SelectPage (const SharedPageDescriptor& rpDescriptor)
{
    if (rpDescriptor.get()!=NULL
        && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, true))
    {
        ++mnSelectedPageCount;
        mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor,true);
        mrSlideSorter.GetView().RequestRepaint(rpDescriptor);

        mpMostRecentlySelectedPage = rpDescriptor;
        if (mpSelectionAnchor == 0)
            mpSelectionAnchor = rpDescriptor;

        if (mnBroadcastDisableLevel > 0)
            mbSelectionChangeBroadcastPending = true;
        else
            mrController.GetSelectionManager()->SelectionHasChanged();
        UpdateCurrentPage();

        CheckConsistency();
    }
}

void PageSelector::DeselectPage (
    int nPageIndex,
    const bool bUpdateCurrentPage)
{
    model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
    if (pDescriptor.get() != NULL)
        DeselectPage(pDescriptor, bUpdateCurrentPage);
}

void PageSelector::DeselectPage (
    const SharedPageDescriptor& rpDescriptor,
    const bool bUpdateCurrentPage)
{
    if (rpDescriptor.get()!=NULL
        && mrSlideSorter.GetView().SetState(rpDescriptor, PageDescriptor::ST_Selected, false))
    {
        --mnSelectedPageCount;
        mrSlideSorter.GetController().GetVisibleAreaManager().RequestVisible(rpDescriptor);
        mrSlideSorter.GetView().RequestRepaint(rpDescriptor);
        if (mpMostRecentlySelectedPage == rpDescriptor)
            mpMostRecentlySelectedPage.reset();
        if (mnBroadcastDisableLevel > 0)
            mbSelectionChangeBroadcastPending = true;
        else
            mrController.GetSelectionManager()->SelectionHasChanged();
        if (bUpdateCurrentPage)
            UpdateCurrentPage();

        CheckConsistency();
    }
}

void PageSelector::CheckConsistency (void) const
{
    int nSelectionCount (0);
    for (int nPageIndex=0,nPageCount=mrModel.GetPageCount(); nPageIndex<nPageCount; nPageIndex++)
    {
        SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
        assert(pDescriptor);
        if (pDescriptor->HasState(PageDescriptor::ST_Selected))
            ++nSelectionCount;
    }
    if (nSelectionCount!=mnSelectedPageCount)
    {
        // #i120020# The former call to assert(..) internally calls
        // SlideSorterModel::GetPageDescriptor which will crash in this situation
        // (only in non-pro code). All what is wanted there is to assert it (the
        // error is already detected), so do this directly.
        OSL_ENSURE(false, "PageSelector: Consistency error (!)");
    }
}

bool PageSelector::IsPageSelected (int nPageIndex)
{
    SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nPageIndex));
    if (pDescriptor.get() != NULL)
        return pDescriptor->HasState(PageDescriptor::ST_Selected);
    else
        return false;
}

int PageSelector::GetPageCount (void) const
{
    return mrModel.GetPageCount();
}

void PageSelector::CountSelectedPages (void)
{
    mnSelectedPageCount = 0;
    model::PageEnumeration aSelectedPages (
        model::PageEnumerationProvider::CreateSelectedPagesEnumeration(mrModel));
    while (aSelectedPages.HasMoreElements())
    {
        mnSelectedPageCount++;
        aSelectedPages.GetNextElement();
    }
}

void PageSelector::EnableBroadcasting (void)
{
    if (mnBroadcastDisableLevel > 0)
        mnBroadcastDisableLevel --;
    if (mnBroadcastDisableLevel==0 && mbSelectionChangeBroadcastPending)
    {
        mrController.GetSelectionManager()->SelectionHasChanged();
        mbSelectionChangeBroadcastPending = false;
    }
}

void PageSelector::DisableBroadcasting (void)
{
    mnBroadcastDisableLevel ++;
}

::boost::shared_ptr<PageSelector::PageSelection> PageSelector::GetPageSelection (void) const
{
    ::boost::shared_ptr<PageSelection> pSelection (new PageSelection());
    pSelection->reserve(GetSelectedPageCount());

    int nPageCount = GetPageCount();
    for (int nIndex=0; nIndex<nPageCount; nIndex++)
    {
        SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
        if (pDescriptor.get()!=NULL && pDescriptor->HasState(PageDescriptor::ST_Selected))
            pSelection->push_back(pDescriptor->GetPage());
    }

    return pSelection;
}

void PageSelector::SetPageSelection (
    const ::boost::shared_ptr<PageSelection>& rpSelection,
    const bool bUpdateCurrentPage)
{
    PageSelection::const_iterator iPage;
    for (iPage=rpSelection->begin(); iPage!=rpSelection->end(); ++iPage)
        SelectPage(*iPage);
    if (bUpdateCurrentPage)
        UpdateCurrentPage();
}

void PageSelector::UpdateCurrentPage (const bool bUpdateOnlyWhenPending)
{
    if (mnUpdateLockCount > 0)
    {
        mbIsUpdateCurrentPagePending = true;
        return;
    }

    if ( ! mbIsUpdateCurrentPagePending && bUpdateOnlyWhenPending)
        return;

    mbIsUpdateCurrentPagePending = false;

    // Make the first selected page the current page.
    SharedPageDescriptor pCurrentPageDescriptor;
    const sal_Int32 nPageCount (GetPageCount());
    for (sal_Int32 nIndex=0; nIndex<nPageCount; ++nIndex)
    {
        SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
        if ( ! pDescriptor)
            continue;
        if (pDescriptor->HasState(PageDescriptor::ST_Selected))
        {
            pCurrentPageDescriptor = pDescriptor;
            break;
        }
    }

    if (pCurrentPageDescriptor)
    {
        // Switching the current slide normally sets also the
        // selection to just the new current slide.  To prevent that,
        // we store (and at the end of this scope restore) the current
        // selection.
        ::boost::shared_ptr<PageSelection> pSelection (GetPageSelection());

        mrController.GetCurrentSlideManager()->SwitchCurrentSlide(pCurrentPageDescriptor);

        // Restore the selection and prevent a recursive call to
        // UpdateCurrentPage().
        SetPageSelection(pSelection, false);
    }
}

//===== PageSelector::UpdateLock ==============================================

PageSelector::UpdateLock::UpdateLock (SlideSorter& rSlideSorter)
    : mpSelector(&rSlideSorter.GetController().GetPageSelector())
{
    ++mpSelector->mnUpdateLockCount;
}

PageSelector::UpdateLock::UpdateLock (PageSelector& rSelector)
    : mpSelector(&rSelector)
{
    ++mpSelector->mnUpdateLockCount;
}

PageSelector::UpdateLock::~UpdateLock (void)
{
    Release();
}

void PageSelector::UpdateLock::Release (void)
{
    if (mpSelector != NULL)
    {
        --mpSelector->mnUpdateLockCount;
        OSL_ASSERT(mpSelector->mnUpdateLockCount >= 0);
        if (mpSelector->mnUpdateLockCount == 0)
            mpSelector->UpdateCurrentPage(true);

        mpSelector = NULL;
    }
}

//===== PageSelector::BroadcastLock ==============================================

PageSelector::BroadcastLock::BroadcastLock (SlideSorter& rSlideSorter)
    : mrSelector(rSlideSorter.GetController().GetPageSelector())
{
    mrSelector.DisableBroadcasting();
}

PageSelector::BroadcastLock::BroadcastLock (PageSelector& rSelector)
    : mrSelector(rSelector)
{
    mrSelector.DisableBroadcasting();
}

PageSelector::BroadcastLock::~BroadcastLock (void)
{
    mrSelector.EnableBroadcasting();
}

} } } // end of namespace ::sd::slidesorter::controller

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


<commit_before>#include <kdebug.h>
#include <kopeteaccount.h>
#include <kopetechatsessionmanager.h>
#include <kopete/kopetetransfermanager.h>
#include <QTimer>
#include <QMessageBox>
#include <kopeteavatarmanager.h>
#include <kopeteuiglobal.h>
#include <kopetemetacontact.h>
#include <kopetegroup.h>
#include <kfiledialog.h>

#include "ui/contactinfo.h"
#include "mra/mraofflinemessage.h"
#include "mra/mra_proto.h"
#include "mra/transferrequestinfo.h"
#include "filetransfertask.h"
#include "debug.h"
#include "mrimaccount.h"
#include "mrimprotocol.h"
#include "mrimcontact.h"

struct MrimContact::Private {
    Kopete::ChatSession* msgManager;
    QTimer *typingTimer;
    QTimer *myselfTypingTimer;
    ContactInfo *infoDialog;
    KAction *requestForAuthorization;
    int flags;
    QMap<int, FileTransferTask*> transferTasks;

    Private()
        : msgManager(NULL)
        , typingTimer(0)
        , myselfTypingTimer(0)
        , infoDialog(0)
        , flags(0) {
    }

};

MrimContact::MrimContact( Kopete::Account* _account,
                          const QString &uniqueName,
                          const QString &displayName,
                          int flags,
                          Kopete::MetaContact *parent )
    : Kopete::Contact( _account, uniqueName, parent, QString("mrim_protocol") )
    , d(new Private)
{
    mrimDebug()<< " uniqueName: " << uniqueName << ", displayName: " << displayName;

    QTimer::singleShot( 10 * 1000, this, SLOT(slotLoadAvatar()) );

    d->requestForAuthorization = new KAction( KIcon("mail-reply-sender"), tr( "(Re)request Authorization From" ), this );
    connect( d->requestForAuthorization, SIGNAL(triggered(bool)), this, SLOT(slotPerformRequestForAuthorization()) );

    d->flags = flags;

    setFileCapable( true );

}

MrimContact::~MrimContact() {
    delete d;
}

void MrimContact::sendFile( const KUrl &sourceURL,
                   const QString &fileName, uint fileSize ) {

    kDebug(kdeDebugArea()) << sourceURL << fileName << fileSize;

    QStringList fileNames;
    //If the file location is null, then get it from a file open dialog
    if( !sourceURL.isValid() ) {
        fileNames = KFileDialog::getOpenFileNames( KUrl() ,"*", 0l  , tr( "Kopete File Transfer" ));
    } else {
        fileNames << sourceURL.path(KUrl::RemoveTrailingSlash);
    }

    kDebug(kdeDebugArea()) << "start transfer";

    FileTransferTask *task = new FileTransferTask(
                  dynamic_cast<MrimAccount*>( account() )
                , this
                , fileNames
                , FileTransferTask::Outgoing
                , 0
                , this);

    connect(task, SIGNAL(transferComplete()),
            this, SLOT(slotTransferFinished()) );

    connect(task, SIGNAL(transferFailed()),
            this, SLOT(slotTransferFinished()) );

    d->transferTasks[task->getSessionId()] = task;

}

void MrimContact::receiveFile(const TransferRequestInfo &transferInfo) {
    /// @todo ask user's confirmation
    kDebug(kdeDebugArea());
    FileTransferTask *task = new FileTransferTask(
                  dynamic_cast<MrimAccount*>( account() )
                , this
                , QStringList()
                , FileTransferTask::Incoming
                , &transferInfo
                , this);

    connect(task, SIGNAL(transferComplete()),
            this, SLOT(slotTransferFinished()) );

    connect(task, SIGNAL(transferFailed()),
            this, SLOT(slotTransferFinished()) );

    d->transferTasks[task->getSessionId()] = task;
}

void MrimContact::receiveFileCancel(const TransferRequestInfo &transferInfo) {
    if (d->transferTasks.contains(transferInfo.sessionId())) {
        d->transferTasks[transferInfo.sessionId()]->cancel();
    }
}

void MrimContact::slotTransferFinished() {
    FileTransferTask *task = (FileTransferTask *)sender();
    d->transferTasks.remove(task->getSessionId());
}

void MrimContact::setFlags(int arg) {
    d->flags = arg;
}

void MrimContact::slotPerformRequestForAuthorization() {
    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->requestForAuthorization(contactId() );
}

QList<KAction *> *MrimContact::customContextMenuActions( Kopete::ChatSession* ) {

    QList<KAction *> *list = new QList<KAction *>();
    list->append(d->requestForAuthorization);

    return list;
}

QList<KAction *> *MrimContact::customContextMenuActions(  ) {
    return Kopete::Contact::customContextMenuActions();
}

Kopete::ChatSession* MrimContact::manager( CanCreateFlags canCreateFlags )
{

    if ( d->msgManager )
    {
        return d->msgManager;
    }
    else if ( canCreateFlags == CanCreate )
    {
        QList<Kopete::Contact*> contacts;

        contacts.append(this);

        Kopete::ChatSession::Form form = Kopete::ChatSession::Small;
        if (d->flags & CONTACT_FLAG_CHAT) {
            form = Kopete::ChatSession::Chatroom;
            mrimDebug() << "Chat!";
            loadChatMembersList();
        }

        d->msgManager = Kopete::ChatSessionManager::self()->create(account()->myself(), contacts, protocol(), form );

        connect(d->msgManager, SIGNAL(messageSent(Kopete::Message&,Kopete::ChatSession*)),
                this, SLOT(sendMessage(Kopete::Message&)) );

        connect(d->msgManager, SIGNAL(myselfTyping(bool)),
                this, SLOT(slotMyselfTyping(bool)) );

        connect(d->msgManager, SIGNAL(destroyed()), this, SLOT(slotChatSessionDestroyed()));

        return d->msgManager;
    }
    else
    {
        return 0;
    }

    return 0;
}

void MrimContact::slotChatSessionDestroyed()
{
    d->msgManager = 0;
}

void MrimContact::sendMessage( Kopete::Message &message )
{
    mrimDebug();

    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );

    a->sendMessage( contactId(), message.plainBody() );

    // give it back to the manager to display
    manager()->appendMessage( message );
    // tell the manager it was sent successfully
    manager()->messageSucceeded();
}

void MrimContact::receivedMessage( const QString &text ) {

    Kopete::Message msg( this, account()->myself() );

    msg.setDirection( Kopete::Message::Inbound );

    msg.setPlainBody( text );

    msg.setManager( manager(CanCreate) );

    Kopete::ChatSession *session = manager(CanCreate);
    session->appendMessage(msg);
}

void MrimContact::receivedOfflineMessage( const MRAOfflineMessage &message ) {

    Kopete::Message msg( this, account()->myself() );

    msg.setDirection( Kopete::Message::Inbound );

    msg.setPlainBody( message.text() );

    msg.setManager( manager(CanCreate) );

    msg.setTimestamp( QDateTime::fromTime_t( message.date().toTime_t() ) );

    Kopete::ChatSession *session = manager(CanCreate);
    session->appendMessage(msg);
}

void MrimContact::typingMessage() {
    if ( d->typingTimer  ) {
        d->typingTimer->stop();
        d->typingTimer->deleteLater();
        d->typingTimer = 0;
    }

    manager(CanCreate)->receivedTypingMsg( this, true );

    d->typingTimer = new QTimer(this);
    connect(d->typingTimer, SIGNAL(timeout()), this, SLOT(slotTypingTimeOut()));
    d->typingTimer->setSingleShot(true);
    d->typingTimer->setInterval(10 * 1000);
}

void MrimContact::slotTypingTimeOut() {
    manager(CanCreate)->receivedTypingMsg( this, false );
    d->typingTimer->deleteLater();
    d->typingTimer = 0;
}

void MrimContact::slotMyselfTyping(bool typing) {
    if (typing && !d->myselfTypingTimer) {
        d->myselfTypingTimer = new QTimer(this);

        connect(d->myselfTypingTimer, SIGNAL(timeout()), this, SLOT(slotMyselfTypingTimeout()));
        d->myselfTypingTimer->setInterval(10 * 1000);

        slotMyselfTypingTimeout();

    } else if ( !typing && d->myselfTypingTimer ) {
        d->myselfTypingTimer->stop();
        d->myselfTypingTimer->deleteLater();
        d->myselfTypingTimer = 0;
    }
}

void MrimContact::slotMyselfTypingTimeout() {
    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->contactTypingAMessage( contactId() );
}

void MrimContact::slotUserInfo() {

    if ( !account()->isConnected() ) {
        return;
    }

    new ContactInfo( dynamic_cast<MrimAccount*>( account() ), this, Kopete::UI::Global::mainWidget () );

    mrimDebug() << __PRETTY_FUNCTION__;

    loadUserInfo();
}

void MrimContact::slotUserInfoLoaded(const MRAContactInfo &info) {

    mrimDebug() << __PRETTY_FUNCTION__;

    emit userInfoLoaded(info);
}

void MrimContact::loadUserInfo() {

    mrimDebug() << __PRETTY_FUNCTION__;

    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->loadUserInfo( contactId() );
}

void MrimContact::slotLoadAvatar() {

    if ( !contactId().isEmpty() )
    {
        if ( !property(MrimProtocol::protocol()->propPhoto).isNull() ) {
            return ;
        }
        MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
        a->loadAvatar( contactId() );

    } else {
        mrimDebug() << "empty!" << contactId();
    }

}

void MrimContact::avatarLoaded(const QImage &avatar) {

    // add the entry using the avatar manager
    Kopete::AvatarManager::AvatarEntry entry;
    entry.name = contactId();
    entry.image = avatar;
    entry.category = Kopete::AvatarManager::Contact;
    entry.contact = this;
    entry = Kopete::AvatarManager::self()->add(entry);

    // Save the image to the disk, then set the property.
    if(!entry.dataPath.isNull())
    {
        setProperty( MrimProtocol::protocol()->propPhoto, entry.dataPath );
    }

}

void MrimContact::deleteContact() {

    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->deleteContact( contactId() );

    Kopete::Contact::deleteContact();
}

void MrimContact::loadChatMembersList() {
    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->loadChatMembersList( contactId() );
}

void MrimContact::slotChatMembersListReceived(const QString &title, const QList<QString> &list) {
    foreach(const QString &contact, list) {
        mrimDebug() << contact;
        if ( account()->contacts().value(contact) ) {
            manager()->addContact( account()->contacts().value(contact) );
        }
    }
    manager()->setDisplayName(title);
}

void MrimContact::sync(unsigned int changed) {
    //
    mrimDebug() << metaContact()->displayName();
    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );

    if (changed & MovedBetweenGroup) {
        const QString &newGroup = metaContact()->groups().first()->displayName();
        a->moveContactToGroup( contactId(), newGroup );
    } else if (changed & DisplayNameChanged) {
        a->renameContact( contactId(), metaContact()->displayName() );
    } else {
        mrimDebug() << "unknown change action:" << changed;
    }
}

#include "mrimcontact.moc"
<commit_msg>Don't send files to chats<commit_after>#include <kdebug.h>
#include <kopeteaccount.h>
#include <kopetechatsessionmanager.h>
#include <kopete/kopetetransfermanager.h>
#include <QTimer>
#include <QMessageBox>
#include <kopeteavatarmanager.h>
#include <kopeteuiglobal.h>
#include <kopetemetacontact.h>
#include <kopetegroup.h>
#include <kfiledialog.h>

#include "ui/contactinfo.h"
#include "mra/mraofflinemessage.h"
#include "mra/mra_proto.h"
#include "mra/transferrequestinfo.h"
#include "filetransfertask.h"
#include "debug.h"
#include "mrimaccount.h"
#include "mrimprotocol.h"
#include "mrimcontact.h"

struct MrimContact::Private {
    Kopete::ChatSession* msgManager;
    QTimer *typingTimer;
    QTimer *myselfTypingTimer;
    ContactInfo *infoDialog;
    KAction *requestForAuthorization;
    int flags;
    QMap<int, FileTransferTask*> transferTasks;

    Private()
        : msgManager(NULL)
        , typingTimer(0)
        , myselfTypingTimer(0)
        , infoDialog(0)
        , flags(0) {
    }

};

MrimContact::MrimContact( Kopete::Account* _account,
                          const QString &uniqueName,
                          const QString &displayName,
                          int flags,
                          Kopete::MetaContact *parent )
    : Kopete::Contact( _account, uniqueName, parent, QString("mrim_protocol") )
    , d(new Private)
{
    mrimDebug()<< " uniqueName: " << uniqueName << ", displayName: " << displayName;

    QTimer::singleShot( 10 * 1000, this, SLOT(slotLoadAvatar()) );

    d->requestForAuthorization = new KAction( KIcon("mail-reply-sender"), tr( "(Re)request Authorization From" ), this );
    connect( d->requestForAuthorization, SIGNAL(triggered(bool)), this, SLOT(slotPerformRequestForAuthorization()) );

    d->flags = flags;

    if ( (d->flags & CONTACT_FLAG_CHAT) == 0 ) {
        setFileCapable( true );
    }

}

MrimContact::~MrimContact() {
    delete d;
}

void MrimContact::sendFile( const KUrl &sourceURL,
                   const QString &fileName, uint fileSize ) {

    kDebug(kdeDebugArea()) << sourceURL << fileName << fileSize;

    QStringList fileNames;
    //If the file location is null, then get it from a file open dialog
    if( !sourceURL.isValid() ) {
        fileNames = KFileDialog::getOpenFileNames( KUrl() ,"*", 0l  , tr( "Kopete File Transfer" ));
    } else {
        fileNames << sourceURL.path(KUrl::RemoveTrailingSlash);
    }

    kDebug(kdeDebugArea()) << "start transfer";

    FileTransferTask *task = new FileTransferTask(
                  dynamic_cast<MrimAccount*>( account() )
                , this
                , fileNames
                , FileTransferTask::Outgoing
                , 0
                , this);

    connect(task, SIGNAL(transferComplete()),
            this, SLOT(slotTransferFinished()) );

    connect(task, SIGNAL(transferFailed()),
            this, SLOT(slotTransferFinished()) );

    d->transferTasks[task->getSessionId()] = task;

}

void MrimContact::receiveFile(const TransferRequestInfo &transferInfo) {
    /// @todo ask user's confirmation
    kDebug(kdeDebugArea());
    FileTransferTask *task = new FileTransferTask(
                  dynamic_cast<MrimAccount*>( account() )
                , this
                , QStringList()
                , FileTransferTask::Incoming
                , &transferInfo
                , this);

    connect(task, SIGNAL(transferComplete()),
            this, SLOT(slotTransferFinished()) );

    connect(task, SIGNAL(transferFailed()),
            this, SLOT(slotTransferFinished()) );

    d->transferTasks[task->getSessionId()] = task;
}

void MrimContact::receiveFileCancel(const TransferRequestInfo &transferInfo) {
    if (d->transferTasks.contains(transferInfo.sessionId())) {
        d->transferTasks[transferInfo.sessionId()]->cancel();
    }
}

void MrimContact::slotTransferFinished() {
    FileTransferTask *task = (FileTransferTask *)sender();
    d->transferTasks.remove(task->getSessionId());
}

void MrimContact::setFlags(int arg) {
    d->flags = arg;
    if ( (d->flags & CONTACT_FLAG_CHAT) == 0 ) {
        setFileCapable( true );
    } else {
        setFileCapable( false );
    }
}

void MrimContact::slotPerformRequestForAuthorization() {
    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->requestForAuthorization(contactId() );
}

QList<KAction *> *MrimContact::customContextMenuActions( Kopete::ChatSession* ) {

    QList<KAction *> *list = new QList<KAction *>();
    list->append(d->requestForAuthorization);

    return list;
}

QList<KAction *> *MrimContact::customContextMenuActions(  ) {
    return Kopete::Contact::customContextMenuActions();
}

Kopete::ChatSession* MrimContact::manager( CanCreateFlags canCreateFlags )
{

    if ( d->msgManager )
    {
        return d->msgManager;
    }
    else if ( canCreateFlags == CanCreate )
    {
        QList<Kopete::Contact*> contacts;

        contacts.append(this);

        Kopete::ChatSession::Form form = Kopete::ChatSession::Small;
        if (d->flags & CONTACT_FLAG_CHAT) {
            form = Kopete::ChatSession::Chatroom;
            mrimDebug() << "Chat!";
            loadChatMembersList();
        }

        d->msgManager = Kopete::ChatSessionManager::self()->create(account()->myself(), contacts, protocol(), form );

        connect(d->msgManager, SIGNAL(messageSent(Kopete::Message&,Kopete::ChatSession*)),
                this, SLOT(sendMessage(Kopete::Message&)) );

        connect(d->msgManager, SIGNAL(myselfTyping(bool)),
                this, SLOT(slotMyselfTyping(bool)) );

        connect(d->msgManager, SIGNAL(destroyed()), this, SLOT(slotChatSessionDestroyed()));

        return d->msgManager;
    }
    else
    {
        return 0;
    }

    return 0;
}

void MrimContact::slotChatSessionDestroyed()
{
    d->msgManager = 0;
}

void MrimContact::sendMessage( Kopete::Message &message )
{
    mrimDebug();

    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );

    a->sendMessage( contactId(), message.plainBody() );

    // give it back to the manager to display
    manager()->appendMessage( message );
    // tell the manager it was sent successfully
    manager()->messageSucceeded();
}

void MrimContact::receivedMessage( const QString &text ) {

    Kopete::Message msg( this, account()->myself() );

    msg.setDirection( Kopete::Message::Inbound );

    msg.setPlainBody( text );

    msg.setManager( manager(CanCreate) );

    Kopete::ChatSession *session = manager(CanCreate);
    session->appendMessage(msg);
}

void MrimContact::receivedOfflineMessage( const MRAOfflineMessage &message ) {

    Kopete::Message msg( this, account()->myself() );

    msg.setDirection( Kopete::Message::Inbound );

    msg.setPlainBody( message.text() );

    msg.setManager( manager(CanCreate) );

    msg.setTimestamp( QDateTime::fromTime_t( message.date().toTime_t() ) );

    Kopete::ChatSession *session = manager(CanCreate);
    session->appendMessage(msg);
}

void MrimContact::typingMessage() {
    if ( d->typingTimer  ) {
        d->typingTimer->stop();
        d->typingTimer->deleteLater();
        d->typingTimer = 0;
    }

    manager(CanCreate)->receivedTypingMsg( this, true );

    d->typingTimer = new QTimer(this);
    connect(d->typingTimer, SIGNAL(timeout()), this, SLOT(slotTypingTimeOut()));
    d->typingTimer->setSingleShot(true);
    d->typingTimer->setInterval(10 * 1000);
}

void MrimContact::slotTypingTimeOut() {
    manager(CanCreate)->receivedTypingMsg( this, false );
    d->typingTimer->deleteLater();
    d->typingTimer = 0;
}

void MrimContact::slotMyselfTyping(bool typing) {
    if (typing && !d->myselfTypingTimer) {
        d->myselfTypingTimer = new QTimer(this);

        connect(d->myselfTypingTimer, SIGNAL(timeout()), this, SLOT(slotMyselfTypingTimeout()));
        d->myselfTypingTimer->setInterval(10 * 1000);

        slotMyselfTypingTimeout();

    } else if ( !typing && d->myselfTypingTimer ) {
        d->myselfTypingTimer->stop();
        d->myselfTypingTimer->deleteLater();
        d->myselfTypingTimer = 0;
    }
}

void MrimContact::slotMyselfTypingTimeout() {
    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->contactTypingAMessage( contactId() );
}

void MrimContact::slotUserInfo() {

    if ( !account()->isConnected() ) {
        return;
    }

    new ContactInfo( dynamic_cast<MrimAccount*>( account() ), this, Kopete::UI::Global::mainWidget () );

    mrimDebug() << __PRETTY_FUNCTION__;

    loadUserInfo();
}

void MrimContact::slotUserInfoLoaded(const MRAContactInfo &info) {

    mrimDebug() << __PRETTY_FUNCTION__;

    emit userInfoLoaded(info);
}

void MrimContact::loadUserInfo() {

    mrimDebug() << __PRETTY_FUNCTION__;

    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->loadUserInfo( contactId() );
}

void MrimContact::slotLoadAvatar() {

    if ( !contactId().isEmpty() )
    {
        if ( !property(MrimProtocol::protocol()->propPhoto).isNull() ) {
            return ;
        }
        MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
        a->loadAvatar( contactId() );

    } else {
        mrimDebug() << "empty!" << contactId();
    }

}

void MrimContact::avatarLoaded(const QImage &avatar) {

    // add the entry using the avatar manager
    Kopete::AvatarManager::AvatarEntry entry;
    entry.name = contactId();
    entry.image = avatar;
    entry.category = Kopete::AvatarManager::Contact;
    entry.contact = this;
    entry = Kopete::AvatarManager::self()->add(entry);

    // Save the image to the disk, then set the property.
    if(!entry.dataPath.isNull())
    {
        setProperty( MrimProtocol::protocol()->propPhoto, entry.dataPath );
    }

}

void MrimContact::deleteContact() {

    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->deleteContact( contactId() );

    Kopete::Contact::deleteContact();
}

void MrimContact::loadChatMembersList() {
    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );
    a->loadChatMembersList( contactId() );
}

void MrimContact::slotChatMembersListReceived(const QString &title, const QList<QString> &list) {
    foreach(const QString &contact, list) {
        mrimDebug() << contact;
        if ( account()->contacts().value(contact) ) {
            manager()->addContact( account()->contacts().value(contact) );
        }
    }
    manager()->setDisplayName(title);
}

void MrimContact::sync(unsigned int changed) {
    //
    mrimDebug() << metaContact()->displayName();
    MrimAccount *a = dynamic_cast<MrimAccount*>( account() );

    if (changed & MovedBetweenGroup) {
        const QString &newGroup = metaContact()->groups().first()->displayName();
        a->moveContactToGroup( contactId(), newGroup );
    } else if (changed & DisplayNameChanged) {
        a->renameContact( contactId(), metaContact()->displayName() );
    } else {
        mrimDebug() << "unknown change action:" << changed;
    }
}

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