<commit_before>/*
    This file is part of libkcal.

    Copyright (c) 2003,2004 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library 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
    Library General Public License for more details.

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

#include <qdatastream.h>
#include <qdatetime.h>
#include <qstring.h>
#include <qptrlist.h>

#include <kdebug.h>
#include <klocale.h>
#include <kurl.h>
#include <kstandarddirs.h>

#include "exceptions.h"
#include "incidence.h"
#include "event.h"
#include "todo.h"
#include "journal.h"

#include "resourcecached.h"

using namespace KCal;

ResourceCached::ResourceCached( const KConfig* config )
  : ResourceCalendar( config ), mReloadPolicy( ReloadNever ),
    mReloadInterval( 10 ), mReloaded( false ), mSavePolicy( SaveNever ),
    mSaveInterval( 10 ), mIdMapper( "kcal/uidmaps/" )
{
  connect( &mReloadTimer, SIGNAL( timeout() ), SLOT( slotReload() ) );
  connect( &mSaveTimer, SIGNAL( timeout() ), SLOT( slotSave() ) );
}

ResourceCached::~ResourceCached()
{
}

void ResourceCached::setReloadPolicy( int i )
{
  mReloadPolicy = i;

  setupReloadTimer();
}

int ResourceCached::reloadPolicy() const
{
  return mReloadPolicy;
}

void ResourceCached::setReloadInterval( int minutes )
{
  mReloadInterval = minutes;
}

int ResourceCached::reloadInterval() const
{
  return mReloadInterval;
}

void ResourceCached::setSavePolicy( int i )
{
  mSavePolicy = i;

  setupSaveTimer();
}

int ResourceCached::savePolicy() const
{
  return mSavePolicy;
}

void ResourceCached::setSaveInterval( int minutes )
{
  mSaveInterval = minutes;
}

int ResourceCached::saveInterval() const
{
  return mSaveInterval;
}

void ResourceCached::readConfig( const KConfig *config )
{
  mReloadPolicy = config->readNumEntry( "ReloadPolicy", ReloadNever );
  mReloadInterval = config->readNumEntry( "ReloadInterval", 10 );

  mSaveInterval = config->readNumEntry( "SaveInterval", 10 );
  mSavePolicy = config->readNumEntry( "SavePolicy", SaveNever );

  mLastLoad = config->readDateTimeEntry( "LastLoad" );
  mLastSave = config->readDateTimeEntry( "LastSave" );

  setupSaveTimer();
  setupReloadTimer();
}

void ResourceCached::setupSaveTimer()
{
  if ( mSavePolicy == SaveInterval ) {
    kdDebug(5800) << "ResourceCached::setSavePolicy(): start save timer (interval "
              << mSaveInterval << " minutes)." << endl;
    mSaveTimer.start( mSaveInterval * 60 * 1000 ); // n minutes
  } else {
    mSaveTimer.stop();
  }
}

void ResourceCached::setupReloadTimer()
{
  if ( mReloadPolicy == ReloadInterval ) {
    kdDebug(5800) << "ResourceCached::setSavePolicy(): start reload timer "
                 "(interval " << mReloadInterval << " minutes)" << endl;
    mReloadTimer.start( mReloadInterval * 60 * 1000 ); // n minutes
  } else {
    mReloadTimer.stop();
  }
}

void ResourceCached::writeConfig( KConfig *config )
{
  config->writeEntry( "ReloadPolicy", mReloadPolicy );
  config->writeEntry( "ReloadInterval", mReloadInterval );

  config->writeEntry( "SavePolicy", mSavePolicy );
  config->writeEntry( "SaveInterval", mSaveInterval );

  config->writeEntry( "LastLoad", mLastLoad );
  config->writeEntry( "LastSave", mLastSave );
}

bool ResourceCached::addEvent(Event *event)
{
  return mCalendar.addEvent( event );
}

// probably not really efficient, but...it works for now.
void ResourceCached::deleteEvent( Event *event )
{
  kdDebug(5800) << "ResourceCached::deleteEvent" << endl;

  mCalendar.deleteEvent( event );
}

Event *ResourceCached::event( const QString &uid )
{
  return mCalendar.event( uid );
}

Event::List ResourceCached::rawEventsForDate( const QDate &qd, bool sorted )
{
  Event::List list = mCalendar.rawEventsForDate( qd, sorted );

  return list;
}

Event::List ResourceCached::rawEvents( const QDate &start, const QDate &end,
                                       bool inclusive )
{
  return mCalendar.rawEvents( start, end, inclusive );
}

Event::List ResourceCached::rawEventsForDate( const QDateTime &qdt )
{
  return mCalendar.rawEventsForDate( qdt.date() );
}

Event::List ResourceCached::rawEvents( EventSortField sortField, SortDirection sortDirection )
{
  return mCalendar.rawEvents( sortField, sortDirection );
}

bool ResourceCached::addTodo( Todo *todo )
{
  return mCalendar.addTodo( todo );
}

void ResourceCached::deleteTodo( Todo *todo )
{
  mCalendar.deleteTodo( todo );
}

void ResourceCached::deleteJournal( Journal *journal )
{
  mCalendar.deleteJournal( journal );
}

Todo::List ResourceCached::rawTodos( TodoSortField sortField, SortDirection sortDirection )
{
  return mCalendar.rawTodos( sortField, sortDirection );
}

Todo *ResourceCached::todo( const QString &uid )
{
  return mCalendar.todo( uid );
}

Todo::List ResourceCached::rawTodosForDate( const QDate &date )
{
  return mCalendar.rawTodosForDate( date );
}

bool ResourceCached::addJournal( Journal *journal )
{
  kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl;

  return mCalendar.addJournal( journal );
}

Journal *ResourceCached::journal( const QString &uid )
{
  return mCalendar.journal( uid );
}

Journal::List ResourceCached::rawJournals( JournalSortField sortField, SortDirection sortDirection )
{
  return mCalendar.rawJournals( sortField, sortDirection );
}

Journal::List ResourceCached::rawJournalsForDate( const QDate &date )
{
  return mCalendar.rawJournalsForDate( date );
}

Alarm::List ResourceCached::alarmsTo( const QDateTime &to )
{
  return mCalendar.alarmsTo( to );
}

Alarm::List ResourceCached::alarms( const QDateTime &from, const QDateTime &to )
{
//  kdDebug(5800) << "ResourceCached::alarms(" << from.toString() << " - " << to.toString() << ")\n";

  return mCalendar.alarms( from, to );
}

void ResourceCached::setTimeZoneId( const QString& tzid )
{
  mCalendar.setTimeZoneId( tzid );
}

QString ResourceCached::timeZoneId() const
{
  return mCalendar.timeZoneId();
}

void ResourceCached::clearChanges()
{
  mAddedIncidences.clear();
  mChangedIncidences.clear();
  mDeletedIncidences.clear();
}

void ResourceCached::loadCache()
{
  setIdMapperIdentifier();
  mIdMapper.load();

  if ( KStandardDirs::exists( cacheFile() ) ) {
    mCalendar.load( cacheFile() );
  }
}

void ResourceCached::saveCache()
{
  kdDebug(5800) << "ResourceCached::saveCache(): " << cacheFile() << endl;

  setIdMapperIdentifier();
  mIdMapper.save();

  mCalendar.save( cacheFile() );
}

void ResourceCached::setIdMapperIdentifier()
{
  mIdMapper.setIdentifier( type() + "_" + identifier() );
}

void ResourceCached::clearCache()
{
  mCalendar.close();
}

void ResourceCached::cleanUpEventCache( const Event::List &eventList )
{
  CalendarLocal calendar;

  if ( KStandardDirs::exists( cacheFile() ) )
    calendar.load( cacheFile() );
  else
    return;

  Event::List list = calendar.events();
  Event::List::ConstIterator cacheIt, it;
  for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) {
    bool found = false;
    for ( it = eventList.begin(); it != eventList.end(); ++it ) {
      if ( (*it)->uid() == (*cacheIt)->uid() )
        found = true;
    }

    if ( !found ) {
      mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) );
      Event *event = mCalendar.event( (*cacheIt)->uid() );
      if ( event )
        mCalendar.deleteEvent( event );
    }
  }

  calendar.close();
}

void ResourceCached::cleanUpTodoCache( const Todo::List &todoList )
{
  CalendarLocal calendar;

  if ( KStandardDirs::exists( cacheFile() ) )
    calendar.load( cacheFile() );
  else
    return;

  Todo::List list = calendar.todos();
  Todo::List::ConstIterator cacheIt, it;
  for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) {

    bool found = false;
    for ( it = todoList.begin(); it != todoList.end(); ++it ) {
      if ( (*it)->uid() == (*cacheIt)->uid() )
        found = true;
    }

    if ( !found ) {
      mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) );
      Todo *todo = mCalendar.todo( (*cacheIt)->uid() );
      if ( todo )
        mCalendar.deleteTodo( todo );
    }
  }

  calendar.close();
}

KPIM::IdMapper& ResourceCached::idMapper()
{
  return mIdMapper;
}

QString ResourceCached::cacheFile() const
{
  return locateLocal( "cache", "kcal/kresources/" + identifier() );
}

void ResourceCached::calendarIncidenceAdded( Incidence *i )
{
#if 1
  kdDebug(5800) << "ResourceCached::calendarIncidenceAdded(): "
            <uid() << endl;
#endif

  QMap<Incidence *,bool>::ConstIterator it;
  it = mAddedIncidences.find( i );
  if ( it == mAddedIncidences.end() ) {
    mAddedIncidences.insert( i, true );
  }

  checkForAutomaticSave();
}

void ResourceCached::calendarIncidenceChanged( Incidence *i )
{
#if 1
  kdDebug(5800) << "ResourceCached::calendarIncidenceChanged(): "
            <uid() << endl;
#endif

  QMap<Incidence *,bool>::ConstIterator it;
  it = mChangedIncidences.find( i );
  if ( it == mChangedIncidences.end() ) {
    mChangedIncidences.insert( i, true );
  }

  checkForAutomaticSave();
}

void ResourceCached::calendarIncidenceDeleted( Incidence *i )
{
#if 1
  kdDebug(5800) << "ResourceCached::calendarIncidenceDeleted(): "
            <uid() << endl;
#endif

  QMap<Incidence *,bool>::ConstIterator it;
  it = mDeletedIncidences.find( i );
  if ( it == mDeletedIncidences.end() ) {
    mDeletedIncidences.insert( i, true );
  }

  checkForAutomaticSave();
}

Incidence::List ResourceCached::addedIncidences() const
{
  Incidence::List added;
  QMap<Incidence *,bool>::ConstIterator it;
  for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) {
    added.append( it.key() );
  }
  return added;
}

Incidence::List ResourceCached::changedIncidences() const
{
  Incidence::List changed;
  QMap<Incidence *,bool>::ConstIterator it;
  for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) {
    changed.append( it.key() );
  }
  return changed;
}

Incidence::List ResourceCached::deletedIncidences() const
{
  Incidence::List deleted;
  QMap<Incidence *,bool>::ConstIterator it;
  for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) {
    deleted.append( it.key() );
  }
  return deleted;
}

Incidence::List ResourceCached::allChanges() const
{
  Incidence::List changes;
  QMap<Incidence *,bool>::ConstIterator it;
  for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) {
    changes.append( it.key() );
  }
  for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) {
    changes.append( it.key() );
  }
  for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) {
    changes.append( it.key() );
  }
  return changes;
}

bool ResourceCached::hasChanges() const
{
  return !( mAddedIncidences.isEmpty() && mChangedIncidences.isEmpty() &&
            mDeletedIncidences.isEmpty() );
}

void ResourceCached::clearChange( Incidence *incidence )
{
  mAddedIncidences.remove( incidence );
  mChangedIncidences.remove( incidence );
  mDeletedIncidences.remove( incidence );
}

void ResourceCached::enableChangeNotification()
{
  mCalendar.registerObserver( this );
}

void ResourceCached::disableChangeNotification()
{
  mCalendar.unregisterObserver( this );
}

void ResourceCached::slotReload()
{
  if ( !isActive() ) return;

  kdDebug(5800) << "ResourceCached::slotReload()" << endl;

  load();
}

void ResourceCached::slotSave()
{
  if ( !isActive() ) return;

  kdDebug(5800) << "ResourceCached::slotSave()" << endl;

  save();
}

void ResourceCached::checkForAutomaticSave()
{
  if ( mSavePolicy == SaveAlways )  {
    kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save now" << endl;
    mSaveTimer.start( 1 * 1000, true ); // 1 second
  } else if ( mSavePolicy == SaveDelayed ) {
    kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save delayed"
              << endl;
    mSaveTimer.start( 15 * 1000, true ); // 15 seconds
  }
}

bool ResourceCached::checkForReload()
{
  if ( mReloadPolicy == ReloadNever ) return false;
  if ( mReloadPolicy == ReloadOnStartup ) return !mReloaded;
  return true;
}

bool ResourceCached::checkForSave()
{
  if ( mSavePolicy == SaveNever ) return false;
  return true;
}

void ResourceCached::addInfoText( QString &txt ) const
{
  if ( mLastLoad.isValid() ) {
    txt += "
";
    txt += i18n("Last loaded: %1")
           .arg( KGlobal::locale()->formatDateTime( mLastLoad ) );
  }
  if ( mLastSave.isValid() ) {
    txt += "
";
    txt += i18n("Last saved: %1")
           .arg( KGlobal::locale()->formatDateTime( mLastSave ) );
  }
}

void ResourceCached::doClose()
{
  mCalendar.close();
}

bool ResourceCached::doOpen()
{
  kdDebug(5800) << "Opening resource " << resourceName() << endl;
  return true;
}

#include "resourcecached.moc"
<commit_msg>CVS_SILENT: Added a TODO for myself<commit_after>/*
    This file is part of libkcal.

    Copyright (c) 2003,2004 Cornelius Schumacher <schumacher@kde.org>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library 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
    Library General Public License for more details.

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

#include <qdatastream.h>
#include <qdatetime.h>
#include <qstring.h>
#include <qptrlist.h>

#include <kdebug.h>
#include <klocale.h>
#include <kurl.h>
#include <kstandarddirs.h>

#include "exceptions.h"
#include "incidence.h"
#include "event.h"
#include "todo.h"
#include "journal.h"

#include "resourcecached.h"

using namespace KCal;

ResourceCached::ResourceCached( const KConfig* config )
  : ResourceCalendar( config ), mReloadPolicy( ReloadNever ),
    mReloadInterval( 10 ), mReloaded( false ), mSavePolicy( SaveNever ),
    mSaveInterval( 10 ), mIdMapper( "kcal/uidmaps/" )
{
  connect( &mReloadTimer, SIGNAL( timeout() ), SLOT( slotReload() ) );
  connect( &mSaveTimer, SIGNAL( timeout() ), SLOT( slotSave() ) );
}

ResourceCached::~ResourceCached()
{
}

void ResourceCached::setReloadPolicy( int i )
{
  mReloadPolicy = i;

  setupReloadTimer();
}

int ResourceCached::reloadPolicy() const
{
  return mReloadPolicy;
}

void ResourceCached::setReloadInterval( int minutes )
{
  mReloadInterval = minutes;
}

int ResourceCached::reloadInterval() const
{
  return mReloadInterval;
}

void ResourceCached::setSavePolicy( int i )
{
  mSavePolicy = i;

  setupSaveTimer();
}

int ResourceCached::savePolicy() const
{
  return mSavePolicy;
}

void ResourceCached::setSaveInterval( int minutes )
{
  mSaveInterval = minutes;
}

int ResourceCached::saveInterval() const
{
  return mSaveInterval;
}

void ResourceCached::readConfig( const KConfig *config )
{
  mReloadPolicy = config->readNumEntry( "ReloadPolicy", ReloadNever );
  mReloadInterval = config->readNumEntry( "ReloadInterval", 10 );

  mSaveInterval = config->readNumEntry( "SaveInterval", 10 );
  mSavePolicy = config->readNumEntry( "SavePolicy", SaveNever );

  mLastLoad = config->readDateTimeEntry( "LastLoad" );
  mLastSave = config->readDateTimeEntry( "LastSave" );

  setupSaveTimer();
  setupReloadTimer();
}

void ResourceCached::setupSaveTimer()
{
  if ( mSavePolicy == SaveInterval ) {
    kdDebug(5800) << "ResourceCached::setSavePolicy(): start save timer (interval "
              << mSaveInterval << " minutes)." << endl;
    mSaveTimer.start( mSaveInterval * 60 * 1000 ); // n minutes
  } else {
    mSaveTimer.stop();
  }
}

void ResourceCached::setupReloadTimer()
{
  if ( mReloadPolicy == ReloadInterval ) {
    kdDebug(5800) << "ResourceCached::setSavePolicy(): start reload timer "
                 "(interval " << mReloadInterval << " minutes)" << endl;
    mReloadTimer.start( mReloadInterval * 60 * 1000 ); // n minutes
  } else {
    mReloadTimer.stop();
  }
}

void ResourceCached::writeConfig( KConfig *config )
{
  config->writeEntry( "ReloadPolicy", mReloadPolicy );
  config->writeEntry( "ReloadInterval", mReloadInterval );

  config->writeEntry( "SavePolicy", mSavePolicy );
  config->writeEntry( "SaveInterval", mSaveInterval );

  config->writeEntry( "LastLoad", mLastLoad );
  config->writeEntry( "LastSave", mLastSave );
}

bool ResourceCached::addEvent(Event *event)
{
  return mCalendar.addEvent( event );
}

// probably not really efficient, but...it works for now.
void ResourceCached::deleteEvent( Event *event )
{
  kdDebug(5800) << "ResourceCached::deleteEvent" << endl;

  mCalendar.deleteEvent( event );
}

Event *ResourceCached::event( const QString &uid )
{
  return mCalendar.event( uid );
}

Event::List ResourceCached::rawEventsForDate( const QDate &qd, bool sorted )
{
  Event::List list = mCalendar.rawEventsForDate( qd, sorted );

  return list;
}

Event::List ResourceCached::rawEvents( const QDate &start, const QDate &end,
                                       bool inclusive )
{
  return mCalendar.rawEvents( start, end, inclusive );
}

Event::List ResourceCached::rawEventsForDate( const QDateTime &qdt )
{
  return mCalendar.rawEventsForDate( qdt.date() );
}

Event::List ResourceCached::rawEvents( EventSortField sortField, SortDirection sortDirection )
{
  return mCalendar.rawEvents( sortField, sortDirection );
}

bool ResourceCached::addTodo( Todo *todo )
{
  return mCalendar.addTodo( todo );
}

void ResourceCached::deleteTodo( Todo *todo )
{
  mCalendar.deleteTodo( todo );
}

void ResourceCached::deleteJournal( Journal *journal )
{
  mCalendar.deleteJournal( journal );
}

Todo::List ResourceCached::rawTodos( TodoSortField sortField, SortDirection sortDirection )
{
  return mCalendar.rawTodos( sortField, sortDirection );
}

Todo *ResourceCached::todo( const QString &uid )
{
  return mCalendar.todo( uid );
}

Todo::List ResourceCached::rawTodosForDate( const QDate &date )
{
  return mCalendar.rawTodosForDate( date );
}

bool ResourceCached::addJournal( Journal *journal )
{
  kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl;

  return mCalendar.addJournal( journal );
}

Journal *ResourceCached::journal( const QString &uid )
{
  return mCalendar.journal( uid );
}

Journal::List ResourceCached::rawJournals( JournalSortField sortField, SortDirection sortDirection )
{
  return mCalendar.rawJournals( sortField, sortDirection );
}

Journal::List ResourceCached::rawJournalsForDate( const QDate &date )
{
  return mCalendar.rawJournalsForDate( date );
}

Alarm::List ResourceCached::alarmsTo( const QDateTime &to )
{
  return mCalendar.alarmsTo( to );
}

Alarm::List ResourceCached::alarms( const QDateTime &from, const QDateTime &to )
{
//  kdDebug(5800) << "ResourceCached::alarms(" << from.toString() << " - " << to.toString() << ")\n";

  return mCalendar.alarms( from, to );
}

void ResourceCached::setTimeZoneId( const QString& tzid )
{
  mCalendar.setTimeZoneId( tzid );
}

QString ResourceCached::timeZoneId() const
{
  return mCalendar.timeZoneId();
}

void ResourceCached::clearChanges()
{
  mAddedIncidences.clear();
  mChangedIncidences.clear();
  mDeletedIncidences.clear();
}

void ResourceCached::loadCache()
{
  setIdMapperIdentifier();
  mIdMapper.load();

  if ( KStandardDirs::exists( cacheFile() ) ) {
    mCalendar.load( cacheFile() );
  }
}

void ResourceCached::saveCache()
{
  kdDebug(5800) << "ResourceCached::saveCache(): " << cacheFile() << endl;

  setIdMapperIdentifier();
  mIdMapper.save();

  mCalendar.save( cacheFile() );
}

void ResourceCached::setIdMapperIdentifier()
{
  mIdMapper.setIdentifier( type() + "_" + identifier() );
}

void ResourceCached::clearCache()
{
  mCalendar.close();
}

void ResourceCached::cleanUpEventCache( const Event::List &eventList )
{
  CalendarLocal calendar;

  if ( KStandardDirs::exists( cacheFile() ) )
    calendar.load( cacheFile() );
  else
    return;

  Event::List list = calendar.events();
  Event::List::ConstIterator cacheIt, it;
  for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) {
    bool found = false;
    for ( it = eventList.begin(); it != eventList.end(); ++it ) {
      if ( (*it)->uid() == (*cacheIt)->uid() )
        found = true;
    }

    if ( !found ) {
      mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) );
      Event *event = mCalendar.event( (*cacheIt)->uid() );
      if ( event )
        mCalendar.deleteEvent( event );
    }
  }

  calendar.close();
}

void ResourceCached::cleanUpTodoCache( const Todo::List &todoList )
{
  CalendarLocal calendar;

  if ( KStandardDirs::exists( cacheFile() ) )
    calendar.load( cacheFile() );
  else
    return;

  Todo::List list = calendar.todos();
  Todo::List::ConstIterator cacheIt, it;
  for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) {

    bool found = false;
    for ( it = todoList.begin(); it != todoList.end(); ++it ) {
      if ( (*it)->uid() == (*cacheIt)->uid() )
        found = true;
    }

    if ( !found ) {
      mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) );
      Todo *todo = mCalendar.todo( (*cacheIt)->uid() );
      if ( todo )
        mCalendar.deleteTodo( todo );
    }
  }

  calendar.close();
}

KPIM::IdMapper& ResourceCached::idMapper()
{
  return mIdMapper;
}

QString ResourceCached::cacheFile() const
{
  return locateLocal( "cache", "kcal/kresources/" + identifier() );
}

void ResourceCached::calendarIncidenceAdded( Incidence *i )
{
#if 1
  kdDebug(5800) << "ResourceCached::calendarIncidenceAdded(): "
            <uid() << endl;
#endif

  QMap<Incidence *,bool>::ConstIterator it;
  it = mAddedIncidences.find( i );
  if ( it == mAddedIncidences.end() ) {
    mAddedIncidences.insert( i, true );
  }

  checkForAutomaticSave();
}

void ResourceCached::calendarIncidenceChanged( Incidence *i )
{
#if 1
  kdDebug(5800) << "ResourceCached::calendarIncidenceChanged(): "
            <uid() << endl;
#endif

  QMap<Incidence *,bool>::ConstIterator it;
  it = mChangedIncidences.find( i );
  // FIXME: If you modify an added incidence, there's no need to add it to mChangedIncidences!
  if ( it == mChangedIncidences.end() ) {
    mChangedIncidences.insert( i, true );
  }

  checkForAutomaticSave();
}

void ResourceCached::calendarIncidenceDeleted( Incidence *i )
{
#if 1
  kdDebug(5800) << "ResourceCached::calendarIncidenceDeleted(): "
            <uid() << endl;
#endif

  QMap<Incidence *,bool>::ConstIterator it;
  it = mDeletedIncidences.find( i );
  if ( it == mDeletedIncidences.end() ) {
    mDeletedIncidences.insert( i, true );
  }

  checkForAutomaticSave();
}

Incidence::List ResourceCached::addedIncidences() const
{
  Incidence::List added;
  QMap<Incidence *,bool>::ConstIterator it;
  for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) {
    added.append( it.key() );
  }
  return added;
}

Incidence::List ResourceCached::changedIncidences() const
{
  Incidence::List changed;
  QMap<Incidence *,bool>::ConstIterator it;
  for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) {
    changed.append( it.key() );
  }
  return changed;
}

Incidence::List ResourceCached::deletedIncidences() const
{
  Incidence::List deleted;
  QMap<Incidence *,bool>::ConstIterator it;
  for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) {
    deleted.append( it.key() );
  }
  return deleted;
}

Incidence::List ResourceCached::allChanges() const
{
  Incidence::List changes;
  QMap<Incidence *,bool>::ConstIterator it;
  for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) {
    changes.append( it.key() );
  }
  for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) {
    changes.append( it.key() );
  }
  for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) {
    changes.append( it.key() );
  }
  return changes;
}

bool ResourceCached::hasChanges() const
{
  return !( mAddedIncidences.isEmpty() && mChangedIncidences.isEmpty() &&
            mDeletedIncidences.isEmpty() );
}

void ResourceCached::clearChange( Incidence *incidence )
{
  mAddedIncidences.remove( incidence );
  mChangedIncidences.remove( incidence );
  mDeletedIncidences.remove( incidence );
}

void ResourceCached::enableChangeNotification()
{
  mCalendar.registerObserver( this );
}

void ResourceCached::disableChangeNotification()
{
  mCalendar.unregisterObserver( this );
}

void ResourceCached::slotReload()
{
  if ( !isActive() ) return;

  kdDebug(5800) << "ResourceCached::slotReload()" << endl;

  load();
}

void ResourceCached::slotSave()
{
  if ( !isActive() ) return;

  kdDebug(5800) << "ResourceCached::slotSave()" << endl;

  save();
}

void ResourceCached::checkForAutomaticSave()
{
  if ( mSavePolicy == SaveAlways )  {
    kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save now" << endl;
    mSaveTimer.start( 1 * 1000, true ); // 1 second
  } else if ( mSavePolicy == SaveDelayed ) {
    kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save delayed"
              << endl;
    mSaveTimer.start( 15 * 1000, true ); // 15 seconds
  }
}

bool ResourceCached::checkForReload()
{
  if ( mReloadPolicy == ReloadNever ) return false;
  if ( mReloadPolicy == ReloadOnStartup ) return !mReloaded;
  return true;
}

bool ResourceCached::checkForSave()
{
  if ( mSavePolicy == SaveNever ) return false;
  return true;
}

void ResourceCached::addInfoText( QString &txt ) const
{
  if ( mLastLoad.isValid() ) {
    txt += "
";
    txt += i18n("Last loaded: %1")
           .arg( KGlobal::locale()->formatDateTime( mLastLoad ) );
  }
  if ( mLastSave.isValid() ) {
    txt += "
";
    txt += i18n("Last saved: %1")
           .arg( KGlobal::locale()->formatDateTime( mLastSave ) );
  }
}

void ResourceCached::doClose()
{
  mCalendar.close();
}

bool ResourceCached::doOpen()
{
  kdDebug(5800) << "Opening resource " << resourceName() << endl;
  return true;
}

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


<commit_before>
#include "Config.hpp"
#include <fstream>

#ifndef INSTALL_PREFIX
#error CMake has not defined INSTALL_PREFIX!
#endif

Json::Value Config::getQuorumNode()
{
  return loadFile(INSTALL_PREFIX + "/lib/tor-onions/quorum.json");
}

Json::Value Config::getMirror()
{
  return loadFile(INSTALL_PREFIX + "/lib/tor-onions/mirrors.json");
}

Json::Value Config::loadFile(const std::string& path)
{
  Json::Value value;
  std::ifstream file(path, std::ifstream::binary);
  file >> value;
  return value;
}
<commit_msg>Handle inability to open a resource<commit_after>
#include "Config.hpp"
#include "Log.hpp"
#include <fstream>

#ifndef INSTALL_PREFIX
#error CMake has not defined INSTALL_PREFIX!
#endif

Json::Value Config::getQuorumNode()
{
  return loadFile(INSTALL_PREFIX + "/lib/tor-onions/quorum.json");
}

Json::Value Config::getMirror()
{
  return loadFile(INSTALL_PREFIX + "/lib/tor-onions/mirrors.json");
}

Json::Value Config::loadFile(const std::string& path)
{
  Json::Value value;

  std::ifstream file;
  file.open(path, std::ifstream::binary);
  if (file.is_open())
    file >> value;
  else
    Log::get().error("Cannot open resource " + path);

  return value;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef SYNCOBJECT_HH
#define SYNCOBJECT_HH 1

#include <stdexcept>
#include <iostream>
#include <sstream>
#include <pthread.h>
#include <sys/time.h>

#include "common.hh"

/**
 * Abstraction built on top of pthread mutexes
 */
class SyncObject : public Mutex {
public:
    SyncObject() : Mutex() {
        if (pthread_cond_init(&cond, NULL) != 0) {
            throw std::runtime_error("MUTEX ERROR: Failed to initialize cond.");
        }
    }

    ~SyncObject() {
        if (pthread_cond_destroy(&cond) != 0) {
            throw std::runtime_error("MUTEX ERROR: Failed to destroy cond.");
        }
    }

    void wait() {
        if (pthread_cond_wait(&cond, &mutex) != 0) {
            throw std::runtime_error("Failed to wait for condition.");
        }
        holder = pthread_self();
    }

    bool wait(const struct timeval &tv) {
        struct timespec ts;
        ts.tv_sec = tv.tv_sec + 0;
        ts.tv_nsec = tv.tv_usec * 1000;

        switch (pthread_cond_timedwait(&cond, &mutex, &ts)) {
        case 0:
            holder = pthread_self();
            return true;
        case ETIMEDOUT:
            return false;
        default:
            throw std::runtime_error("Failed timed_wait for condition.");
        }
    }

    bool wait(const double secs) {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        advance_tv(tv, secs);
        return wait(tv);
    }

    void notify() {
        if(pthread_cond_broadcast(&cond) != 0) {
            throw std::runtime_error("Failed to broadcast change.");
        }
    }

private:
    pthread_cond_t cond;

    DISALLOW_COPY_AND_ASSIGN(SyncObject);
};

#endif

<commit_msg>Reset holder reference after a wait timeout.<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef SYNCOBJECT_HH
#define SYNCOBJECT_HH 1

#include <stdexcept>
#include <iostream>
#include <sstream>
#include <pthread.h>
#include <sys/time.h>

#include "common.hh"

/**
 * Abstraction built on top of pthread mutexes
 */
class SyncObject : public Mutex {
public:
    SyncObject() : Mutex() {
        if (pthread_cond_init(&cond, NULL) != 0) {
            throw std::runtime_error("MUTEX ERROR: Failed to initialize cond.");
        }
    }

    ~SyncObject() {
        if (pthread_cond_destroy(&cond) != 0) {
            throw std::runtime_error("MUTEX ERROR: Failed to destroy cond.");
        }
    }

    void wait() {
        if (pthread_cond_wait(&cond, &mutex) != 0) {
            throw std::runtime_error("Failed to wait for condition.");
        }
        holder = pthread_self();
    }

    bool wait(const struct timeval &tv) {
        struct timespec ts;
        ts.tv_sec = tv.tv_sec + 0;
        ts.tv_nsec = tv.tv_usec * 1000;

        switch (pthread_cond_timedwait(&cond, &mutex, &ts)) {
        case 0:
            holder = pthread_self();
            return true;
        case ETIMEDOUT:
            holder = pthread_self();
            return false;
        default:
            throw std::runtime_error("Failed timed_wait for condition.");
        }
    }

    bool wait(const double secs) {
        struct timeval tv;
        gettimeofday(&tv, NULL);
        advance_tv(tv, secs);
        return wait(tv);
    }

    void notify() {
        if(pthread_cond_broadcast(&cond) != 0) {
            throw std::runtime_error("Failed to broadcast change.");
        }
    }

private:
    pthread_cond_t cond;

    DISALLOW_COPY_AND_ASSIGN(SyncObject);
};

#endif

<|endoftext|>


<commit_before><commit_msg>TODO-758: WIP<commit_after><|endoftext|>


<commit_before>// @(#)root/eve:$Id$
// Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TEveBoxSetGL.h"
#include "TEveBoxSet.h"

#include "TGLIncludes.h"
#include "TGLRnrCtx.h"
#include "TGLScene.h"
#include "TGLSelectRecord.h"
#include "TGLContext.h"

//______________________________________________________________________________
// TEveBoxSetGL
//
// A GL rendering class for TEveBoxSet.
//

ClassImp(TEveBoxSetGL)

//______________________________________________________________________________
TEveBoxSetGL::TEveBoxSetGL() : fM(0), fBoxDL(0)
{
   // Default constructor.

   // fDLCache = false; // Disable display list.
}

/******************************************************************************/
// Protected methods
/******************************************************************************/

//______________________________________________________________________________
Int_t TEveBoxSetGL::PrimitiveType() const
{
   // Return GL primitive used to render the boxes, based on the
   // render-mode specified in the model object.

   return (fM->fRenderMode != TEveDigitSet::kRM_TEveLine) ? GL_QUADS : GL_LINE_LOOP;
}

//______________________________________________________________________________
inline Bool_t TEveBoxSetGL::SetupColor(const TEveDigitSet::DigitBase_t& q) const
{
   // Set GL color for given primitive.

   if (fM->fValueIsColor)
   {
      TGLUtil::Color4ubv((UChar_t*) & q.fValue);
      return kTRUE;
   }
   else
   {
      UChar_t c[4];
      Bool_t visible = fM->fPalette->ColorFromValue(q.fValue, fM->fDefaultValue, c);
      if (visible)
         TGLUtil::Color4ubv(c);
      return visible;
   }
}

//______________________________________________________________________________
void TEveBoxSetGL::MakeOriginBox(Float_t p[24], Float_t dx, Float_t dy, Float_t dz) const
{
   // Fill array p to represent a box (0,0,0) - (dx,dy,dz).

   // bottom
   p[0] = 0;  p[1] = dy; p[2] = 0;  p += 3;
   p[0] = dx; p[1] = dy; p[2] = 0;  p += 3;
   p[0] = dx; p[1] = 0;  p[2] = 0;  p += 3;
   p[0] = 0;  p[1] = 0;  p[2] = 0;  p += 3;
   // top
   p[0] = 0;  p[1] = dy; p[2] = dz; p += 3;
   p[0] = dx; p[1] = dy; p[2] = dz; p += 3;
   p[0] = dx; p[1] = 0;  p[2] = dz; p += 3;
   p[0] = 0;  p[1] = 0;  p[2] = dz;
}

//______________________________________________________________________________
inline void TEveBoxSetGL::RenderBox(const Float_t p[24]) const
{
   // Render a box specified by points in array p.

   // bottom: 0123
   glNormal3f(0, 0, -1);
   glVertex3fv(p);      glVertex3fv(p + 3);
   glVertex3fv(p + 6);  glVertex3fv(p + 9);
   // top:    7654
   glNormal3f(0, 0, 1);
   glVertex3fv(p + 21); glVertex3fv(p + 18);
   glVertex3fv(p + 15); glVertex3fv(p + 12);
   // back:  0451
   glNormal3f(0, 1, 0);
   glVertex3fv(p);      glVertex3fv(p + 12);
   glVertex3fv(p + 15); glVertex3fv(p + 3);
   // front:   3267
   glNormal3f(0, -1, 0);
   glVertex3fv(p + 9);   glVertex3fv(p + 6);
   glVertex3fv(p + 18);  glVertex3fv(p + 21);
   // left:    0374
   glNormal3f(-1, 0, 0);
   glVertex3fv(p);       glVertex3fv(p + 9);
   glVertex3fv(p + 21);  glVertex3fv(p + 12);
   // right:   1562
   glNormal3f(1, 0, 0);
   glVertex3fv(p + 3);   glVertex3fv(p + 15);
   glVertex3fv(p + 18);  glVertex3fv(p + 6);
}

//______________________________________________________________________________
void TEveBoxSetGL::MakeDisplayList() const
{
   // Create a display-list for rendering a single box, based on the
   // current box-type.
   // Some box-types don't benefit from the display-list rendering and
   // so display-list is not created.

   if (fM->fBoxType == TEveBoxSet::kBT_AABox ||
       fM->fBoxType == TEveBoxSet::kBT_AABoxFixedDim)
   {
      if (fBoxDL == 0)
         fBoxDL = glGenLists(1);

      Float_t p[24];
      if (fM->fBoxType == TEveBoxSet::kBT_AABox)
         MakeOriginBox(p, 1.0f, 1.0f, 1.0f);
      else
         MakeOriginBox(p, fM->fDefWidth, fM->fDefHeight, fM->fDefDepth);

      glNewList(fBoxDL, GL_COMPILE);
      glBegin(PrimitiveType());
      RenderBox(p);
      glEnd();
      glEndList();
   }
}

/******************************************************************************/
// Virtuals from base-classes
/******************************************************************************/

//______________________________________________________________________________
Bool_t TEveBoxSetGL::ShouldDLCache(const TGLRnrCtx & rnrCtx) const
{
   // Determines if display-list will be used for rendering.
   // Virtual from TGLLogicalShape.

   MakeDisplayList();

   if (rnrCtx.DrawPass() == TGLRnrCtx::kPassOutlineLine)
      return kFALSE;
   return TGLObject::ShouldDLCache(rnrCtx);
}

//______________________________________________________________________________
void TEveBoxSetGL::DLCacheDrop()
{
   // Called when display lists have been destroyed externally and the
   // internal display-list data needs to be cleare.
   // Virtual from TGLLogicalShape.

   fBoxDL = 0;
   TGLObject::DLCacheDrop();
}

//______________________________________________________________________________
void TEveBoxSetGL::DLCachePurge()
{
   // Called when display-lists need to be returned to the system.
   // Virtual from TGLLogicalShape.

   static const TEveException eH("TEveBoxSetGL::DLCachePurge ");

   if (fBoxDL == 0) return;
   if (fScene)
   {
      fScene->GetGLCtxIdentity()->RegisterDLNameRangeToWipe(fBoxDL, 1);
   }
   else
   {
      Warning(eH, "TEveScene unknown, attempting direct deletion.");
      glDeleteLists(fBoxDL, 1);
   }
   TGLObject::DLCachePurge();
}

/******************************************************************************/

//______________________________________________________________________________
Bool_t TEveBoxSetGL::SetModel(TObject* obj, const Option_t* /*opt*/)
{
   // Set model object.
   // Virtual from TGLObject.

   Bool_t isok = SetModelCheckClass(obj, TEveBoxSet::Class());
   fM = isok ? dynamic_cast<TEveBoxSet*>(obj) : 0;
   return isok;
}

//______________________________________________________________________________
void TEveBoxSetGL::SetBBox()
{
   // Fill the bounding-box data of the logical-shape.
   // Virtual from TGLObject.

   SetAxisAlignedBBox(fM->AssertBBox());
}

//______________________________________________________________________________
void TEveBoxSetGL::DirectDraw(TGLRnrCtx & rnrCtx) const
{
   // Actual rendering code.
   // Virtual from TGLLogicalShape.

   static const TEveException eH("TEveBoxSetGL::DirectDraw ");

   if (rnrCtx.DrawPass() == TGLRnrCtx::kPassOutlineLine)
      return;

   TEveBoxSet& mB = * fM;
   // printf("TEveBoxSetGL::DirectDraw N boxes %d\n", mB.fPlex.Size());

   // !!!! Missing frame rendering (wire-frame, of course).

   if(mB.fPlex.Size() == 0)
      return;

   glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);

   if (mB.fRenderMode == TEveDigitSet::kRM_Fill)
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   else if (mB.fRenderMode == TEveDigitSet::kRM_TEveLine)
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

   if (mB.fDisableLigting) glDisable(GL_LIGHTING);

   if (rnrCtx.SecSelection()) glPushName(0);

   Int_t boxSkip = 0;
   if (rnrCtx.ShapeLOD() < 50)
      boxSkip = 6 - (rnrCtx.ShapeLOD()+1)/10;

   TEveChunkManager::iterator bi(mB.fPlex);

   switch (mB.fBoxType)
   {

      case TEveBoxSet::kBT_FreeBox:
      {
         GLenum primitiveType = PrimitiveType();
         while (bi.next())
         {
            TEveBoxSet::BFreeBox_t& b = * (TEveBoxSet::BFreeBox_t*) bi();
            if (SetupColor(b))
            {
               if (rnrCtx.SecSelection()) glLoadName(bi.index());
               glBegin(primitiveType);
               RenderBox(b.fVertices);
               glEnd();
            }
            if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
         }
         break;
      } // end case free-box

      case TEveBoxSet::kBT_AABox:
      {
         glEnable(GL_NORMALIZE);
         while (bi.next())
         {
            TEveBoxSet::BAABox_t& b = * (TEveBoxSet::BAABox_t*) bi();
            if (SetupColor(b))
            {
               if (rnrCtx.SecSelection()) glLoadName(bi.index());
               glPushMatrix();
               glTranslatef(b.fA, b.fB, b.fC);
               glScalef    (b.fW, b.fH, b.fD);
               glCallList(fBoxDL);
               glPopMatrix();
            }
            if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
         }
         break;
      }

      case TEveBoxSet::kBT_AABoxFixedDim:
      {
         while (bi.next())
         {
            TEveBoxSet::BAABoxFixedDim_t& b = * (TEveBoxSet::BAABoxFixedDim_t*) bi();
            if (SetupColor(b))
            {
               if (rnrCtx.SecSelection()) glLoadName(bi.index());
               glTranslatef(b.fA, b.fB, b.fC);
               glCallList(fBoxDL);
               glTranslatef(-b.fA, -b.fB, -b.fC);
            }
            if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
         }
         break;
      }

      default:
      {
         throw(eH + "unsupported box-type.");
      }

   } // end switch box-type

   if (rnrCtx.SecSelection()) glPopName();

   glPopAttrib();
}

/******************************************************************************/

//______________________________________________________________________________
void TEveBoxSetGL::ProcessSelection(TGLRnrCtx & /*rnrCtx*/, TGLSelectRecord & rec)
{
   // Processes secondary selection from TGLViewer.
   // Calls TPointSet3D::PointSelected(Int_t) with index of selected
   // point as an argument.

   if (rec.GetN() < 2) return;
   fM->DigitSelected(rec.GetItem(1));
}

//______________________________________________________________________________
void TEveBoxSetGL::Render(TGLRnrCtx & rnrCtx)
{
   // Interface for direct rendering from classes that include TEveBoxSet
   // as a member.

   MakeDisplayList();
   DirectDraw(rnrCtx);
   glDeleteLists(fBoxDL, 1);
   fBoxDL = 0;
}
<commit_msg>When rendering box-set in signal-to-color mapping mode, assert that the palette has been initialized.<commit_after>// @(#)root/eve:$Id$
// Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TEveBoxSetGL.h"
#include "TEveBoxSet.h"

#include "TGLIncludes.h"
#include "TGLRnrCtx.h"
#include "TGLScene.h"
#include "TGLSelectRecord.h"
#include "TGLContext.h"

//==============================================================================
//==============================================================================
// TEveBoxSetGL
//==============================================================================

//______________________________________________________________________________
//
// A GL rendering class for TEveBoxSet.
//

ClassImp(TEveBoxSetGL);

//______________________________________________________________________________
TEveBoxSetGL::TEveBoxSetGL() : fM(0), fBoxDL(0)
{
   // Default constructor.

   // fDLCache = false; // Disable display list.
}

/******************************************************************************/
// Protected methods
/******************************************************************************/

//______________________________________________________________________________
Int_t TEveBoxSetGL::PrimitiveType() const
{
   // Return GL primitive used to render the boxes, based on the
   // render-mode specified in the model object.

   return (fM->fRenderMode != TEveDigitSet::kRM_TEveLine) ? GL_QUADS : GL_LINE_LOOP;
}

//______________________________________________________________________________
inline Bool_t TEveBoxSetGL::SetupColor(const TEveDigitSet::DigitBase_t& q) const
{
   // Set GL color for given primitive.

   if (fM->fValueIsColor)
   {
      TGLUtil::Color4ubv((UChar_t*) & q.fValue);
      return kTRUE;
   }
   else
   {
      UChar_t c[4];
      Bool_t visible = fM->fPalette->ColorFromValue(q.fValue, fM->fDefaultValue, c);
      if (visible)
         TGLUtil::Color4ubv(c);
      return visible;
   }
}

//______________________________________________________________________________
void TEveBoxSetGL::MakeOriginBox(Float_t p[24], Float_t dx, Float_t dy, Float_t dz) const
{
   // Fill array p to represent a box (0,0,0) - (dx,dy,dz).

   // bottom
   p[0] = 0;  p[1] = dy; p[2] = 0;  p += 3;
   p[0] = dx; p[1] = dy; p[2] = 0;  p += 3;
   p[0] = dx; p[1] = 0;  p[2] = 0;  p += 3;
   p[0] = 0;  p[1] = 0;  p[2] = 0;  p += 3;
   // top
   p[0] = 0;  p[1] = dy; p[2] = dz; p += 3;
   p[0] = dx; p[1] = dy; p[2] = dz; p += 3;
   p[0] = dx; p[1] = 0;  p[2] = dz; p += 3;
   p[0] = 0;  p[1] = 0;  p[2] = dz;
}

//______________________________________________________________________________
inline void TEveBoxSetGL::RenderBox(const Float_t p[24]) const
{
   // Render a box specified by points in array p.

   // bottom: 0123
   glNormal3f(0, 0, -1);
   glVertex3fv(p);      glVertex3fv(p + 3);
   glVertex3fv(p + 6);  glVertex3fv(p + 9);
   // top:    7654
   glNormal3f(0, 0, 1);
   glVertex3fv(p + 21); glVertex3fv(p + 18);
   glVertex3fv(p + 15); glVertex3fv(p + 12);
   // back:  0451
   glNormal3f(0, 1, 0);
   glVertex3fv(p);      glVertex3fv(p + 12);
   glVertex3fv(p + 15); glVertex3fv(p + 3);
   // front:   3267
   glNormal3f(0, -1, 0);
   glVertex3fv(p + 9);   glVertex3fv(p + 6);
   glVertex3fv(p + 18);  glVertex3fv(p + 21);
   // left:    0374
   glNormal3f(-1, 0, 0);
   glVertex3fv(p);       glVertex3fv(p + 9);
   glVertex3fv(p + 21);  glVertex3fv(p + 12);
   // right:   1562
   glNormal3f(1, 0, 0);
   glVertex3fv(p + 3);   glVertex3fv(p + 15);
   glVertex3fv(p + 18);  glVertex3fv(p + 6);
}

//______________________________________________________________________________
void TEveBoxSetGL::MakeDisplayList() const
{
   // Create a display-list for rendering a single box, based on the
   // current box-type.
   // Some box-types don't benefit from the display-list rendering and
   // so display-list is not created.

   if (fM->fBoxType == TEveBoxSet::kBT_AABox ||
       fM->fBoxType == TEveBoxSet::kBT_AABoxFixedDim)
   {
      if (fBoxDL == 0)
         fBoxDL = glGenLists(1);

      Float_t p[24];
      if (fM->fBoxType == TEveBoxSet::kBT_AABox)
         MakeOriginBox(p, 1.0f, 1.0f, 1.0f);
      else
         MakeOriginBox(p, fM->fDefWidth, fM->fDefHeight, fM->fDefDepth);

      glNewList(fBoxDL, GL_COMPILE);
      glBegin(PrimitiveType());
      RenderBox(p);
      glEnd();
      glEndList();
   }
}

/******************************************************************************/
// Virtuals from base-classes
/******************************************************************************/

//______________________________________________________________________________
Bool_t TEveBoxSetGL::ShouldDLCache(const TGLRnrCtx & rnrCtx) const
{
   // Determines if display-list will be used for rendering.
   // Virtual from TGLLogicalShape.

   MakeDisplayList();

   if (rnrCtx.DrawPass() == TGLRnrCtx::kPassOutlineLine)
      return kFALSE;
   return TGLObject::ShouldDLCache(rnrCtx);
}

//______________________________________________________________________________
void TEveBoxSetGL::DLCacheDrop()
{
   // Called when display lists have been destroyed externally and the
   // internal display-list data needs to be cleare.
   // Virtual from TGLLogicalShape.

   fBoxDL = 0;
   TGLObject::DLCacheDrop();
}

//______________________________________________________________________________
void TEveBoxSetGL::DLCachePurge()
{
   // Called when display-lists need to be returned to the system.
   // Virtual from TGLLogicalShape.

   static const TEveException eH("TEveBoxSetGL::DLCachePurge ");

   if (fBoxDL == 0) return;
   if (fScene)
   {
      fScene->GetGLCtxIdentity()->RegisterDLNameRangeToWipe(fBoxDL, 1);
   }
   else
   {
      Warning(eH, "TEveScene unknown, attempting direct deletion.");
      glDeleteLists(fBoxDL, 1);
   }
   TGLObject::DLCachePurge();
}

/******************************************************************************/

//______________________________________________________________________________
Bool_t TEveBoxSetGL::SetModel(TObject* obj, const Option_t* /*opt*/)
{
   // Set model object.
   // Virtual from TGLObject.

   Bool_t isok = SetModelCheckClass(obj, TEveBoxSet::Class());
   fM = isok ? dynamic_cast<TEveBoxSet*>(obj) : 0;
   return isok;
}

//______________________________________________________________________________
void TEveBoxSetGL::SetBBox()
{
   // Fill the bounding-box data of the logical-shape.
   // Virtual from TGLObject.

   SetAxisAlignedBBox(fM->AssertBBox());
}

//______________________________________________________________________________
void TEveBoxSetGL::DirectDraw(TGLRnrCtx & rnrCtx) const
{
   // Actual rendering code.
   // Virtual from TGLLogicalShape.

   static const TEveException eH("TEveBoxSetGL::DirectDraw ");

   if (rnrCtx.DrawPass() == TGLRnrCtx::kPassOutlineLine)
      return;

   TEveBoxSet& mB = * fM;
   // printf("TEveBoxSetGL::DirectDraw N boxes %d\n", mB.fPlex.Size());

   // !!!! Missing frame rendering (wire-frame, of course).

   if(mB.fPlex.Size() == 0)
      return;
   if ( ! mB.fValueIsColor && mB.fPalette == 0)
   {
      mB.AssertPalette();
   }

   glPushAttrib(GL_ENABLE_BIT | GL_POLYGON_BIT);

   if (mB.fRenderMode == TEveDigitSet::kRM_Fill)
      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   else if (mB.fRenderMode == TEveDigitSet::kRM_TEveLine)
      glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

   if (mB.fDisableLigting) glDisable(GL_LIGHTING);

   if (rnrCtx.SecSelection()) glPushName(0);

   Int_t boxSkip = 0;
   if (rnrCtx.ShapeLOD() < 50)
      boxSkip = 6 - (rnrCtx.ShapeLOD()+1)/10;

   TEveChunkManager::iterator bi(mB.fPlex);

   switch (mB.fBoxType)
   {

      case TEveBoxSet::kBT_FreeBox:
      {
         GLenum primitiveType = PrimitiveType();
         while (bi.next())
         {
            TEveBoxSet::BFreeBox_t& b = * (TEveBoxSet::BFreeBox_t*) bi();
            if (SetupColor(b))
            {
               if (rnrCtx.SecSelection()) glLoadName(bi.index());
               glBegin(primitiveType);
               RenderBox(b.fVertices);
               glEnd();
            }
            if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
         }
         break;
      } // end case free-box

      case TEveBoxSet::kBT_AABox:
      {
         glEnable(GL_NORMALIZE);
         while (bi.next())
         {
            TEveBoxSet::BAABox_t& b = * (TEveBoxSet::BAABox_t*) bi();
            if (SetupColor(b))
            {
               if (rnrCtx.SecSelection()) glLoadName(bi.index());
               glPushMatrix();
               glTranslatef(b.fA, b.fB, b.fC);
               glScalef    (b.fW, b.fH, b.fD);
               glCallList(fBoxDL);
               glPopMatrix();
            }
            if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
         }
         break;
      }

      case TEveBoxSet::kBT_AABoxFixedDim:
      {
         while (bi.next())
         {
            TEveBoxSet::BAABoxFixedDim_t& b = * (TEveBoxSet::BAABoxFixedDim_t*) bi();
            if (SetupColor(b))
            {
               if (rnrCtx.SecSelection()) glLoadName(bi.index());
               glTranslatef(b.fA, b.fB, b.fC);
               glCallList(fBoxDL);
               glTranslatef(-b.fA, -b.fB, -b.fC);
            }
            if (boxSkip) { Int_t s = boxSkip; while (s--) bi.next(); }
         }
         break;
      }

      default:
      {
         throw(eH + "unsupported box-type.");
      }

   } // end switch box-type

   if (rnrCtx.SecSelection()) glPopName();

   glPopAttrib();
}

/******************************************************************************/

//______________________________________________________________________________
void TEveBoxSetGL::ProcessSelection(TGLRnrCtx & /*rnrCtx*/, TGLSelectRecord & rec)
{
   // Processes secondary selection from TGLViewer.
   // Calls TPointSet3D::PointSelected(Int_t) with index of selected
   // point as an argument.

   if (rec.GetN() < 2) return;
   fM->DigitSelected(rec.GetItem(1));
}

//______________________________________________________________________________
void TEveBoxSetGL::Render(TGLRnrCtx & rnrCtx)
{
   // Interface for direct rendering from classes that include TEveBoxSet
   // as a member.

   MakeDisplayList();
   DirectDraw(rnrCtx);
   glDeleteLists(fBoxDL, 1);
   fBoxDL = 0;
}
<|endoftext|>


<commit_before>// The "Square Detector" program.
// It loads several images sequentially and tries to find squares in
// each image

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <math.h>
#include <string.h>
#include <stdio.h>

#include <ros/ros.h>
#include <osuar_vision/windowCoordinates.h>

using namespace cv;

int thresh = 50, N = 11;
int maxCosineThresh = 25;
int maxDiffThresh = 300;

// Find colors of any hue...
int wallHueLow  = 0;
int wallHueHigh = 179;

// ...of low saturation...
int wallSatLow  = 0;
int wallSatHigh = 60;

// ...ranging down to gray, but not completely dark. That is to say, white.
int wallValLow  = 50;
int wallValHigh = 255;

ros::Publisher visPub;
osuar_vision::windowCoordinates winCoords;

// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
static double angle( Point pt1, Point pt2, Point pt0 )
{
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

// returns sequence of squares detected on the image.
// the sequence is stored in the specified memory storage
static void findSquares( const Mat& image, vector<vector<Point> >& squares )
{
    squares.clear();

    Mat pyr, timg, gray0(image.size(), CV_8U), gray;

    // down-scale and upscale the image to filter out the noise
    pyrDown(image, pyr, Size(image.cols/2, image.rows/2));
    pyrUp(pyr, timg, image.size());
    vector<vector<Point> > contours;

    // find squares in every color plane of the image
    //for( int c = 0; c < 3; c++ )
    //{
        //int ch[] = {c, 0};
        //mixChannels(&timg, 1, &gray0, 1, ch, 1);

        // try several threshold levels
        for( int l = 0; l < N; l++ )
        {
            // hack: use Canny instead of zero threshold level.
            // Canny helps to catch squares with gradient shading
            if( l == 0 )
            {
                // apply Canny. Take the upper threshold from slider
                // and set the lower to 0 (which forces edges merging)
                Canny(image, gray, 0, thresh, 5);
                // dilate canny output to remove potential
                // holes between edge segments
                dilate(gray, gray, Mat(), Point(-1,-1));
            }
            else
            {
                // apply threshold if l!=0:
                //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
                gray = image >= (l+1)*255/N;
            }

            // find contours and store them all as a list
            findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

            vector<Point> approx;

            // test each contour
            for( size_t i = 0; i < contours.size(); i++ )
            {
                // approximate contour with accuracy proportional
                // to the contour perimeter
                approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

                // square contours should have 4 vertices after approximation
                // relatively large area (to filter out noisy contours)
                // and be convex.
                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
                if( approx.size() == 4 &&
                    fabs(contourArea(Mat(approx))) > 1000 &&
                    isContourConvex(Mat(approx)) )
                {
                    double maxCosine = 0;
                    double maxDiff = 0;

                    for( int j = 2; j < 5; j++ )
                    {
                        // find the maximum cosine of the angle between joint edges
                        double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
                        maxCosine = MAX(maxCosine, cosine);

                        // Find the maximum difference in length of adjacent
                        // sides
                        double diff = sqrt(pow((approx[j%4].x - approx[(j+1)%4].x), 2) + pow((approx[j%4].y - approx[(j+1)%4].y), 2));
                        maxDiff = MAX(maxDiff, diff);
                    }

                    // if cosines of all angles are small
                    // (all angles are ~90 degree) then write quandrange
                    // vertices to resultant sequence
                    if( maxCosine < ((double) maxCosineThresh)/100 && maxDiff < (double) maxDiffThresh )
                        squares.push_back(approx);
                }
            }
        }
    //}
}

// the function draws all the squares in the image
static void drawSquares( Mat& image, const vector<vector<Point> >& squares )
{
    for( size_t i = 0; i < squares.size(); i++ )
    {
        const Point* p = &squares[i][0];
        int n = (int)squares[i].size();
        polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA);

        std::cout << "x: " << squares[i][0].x << "  y: " << squares[i][0].y << "\n";

        // Only publish coordinates for one of the squares. Coordinates are
        // shifted over by half the camera resolution (which itself is scaled
        // down by a factor of two!) on each axis. The y coordinate is inverted
        // so up is positive.
        if (i == 0) {
            winCoords.x =   (squares[0][0].x + squares[0][2].x)/2 - 180;
            winCoords.y = -((squares[0][0].y + squares[0][2].y)/2 - 120);
            visPub.publish(winCoords);
        }
    }
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "vision");
    ros::NodeHandle nh;
    visPub = nh.advertise<osuar_vision::windowCoordinates>("window_coordinates", 1);

    // Instantiate VideoCapture object. See here for details:
    // http://opencv.willowgarage.com/documentation/cpp/reading_and_writing_images_and_video.html
    VideoCapture cap(1);

    // Configure video. Our camera NEEDS the frame width to be set to 720
    // pixels.
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 720);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    //cap.set(CV_CAP_PROP_FPS, 20);

    // Instantiate a Mat in which to store each video frame.
    Mat origFrame;
    Mat resizedFrame;   // Scaled-down from origFrame by factor of 2.
    Mat hsvFrame;   // Converted to HSV space from resizedFrame.
    Mat bwFrame;   // Black/white image after thresholding hsvFrame.

    namedWindow("origImage", 1);
    namedWindow("hsvImage", 1);
    namedWindow("bwImage", 1);
    cvNamedWindow("control panel");
    cvCreateTrackbar("threshold",   "control panel", &thresh,      300, NULL);
    cvCreateTrackbar("maxCosineThresh (x100)",   "control panel", &maxCosineThresh,      100, NULL);
    cvCreateTrackbar("maxDiffThresh",   "control panel", &maxDiffThresh,      1000, NULL);
    cvCreateTrackbar("wallHueLow",  "control panel", &wallHueLow,  179, NULL);
    cvCreateTrackbar("wallHueHigh", "control panel", &wallHueHigh, 179, NULL);
    cvCreateTrackbar("wallSatLow",  "control panel", &wallSatLow,  255, NULL);
    cvCreateTrackbar("wallSatHigh", "control panel", &wallSatHigh, 255, NULL);
    cvCreateTrackbar("wallValLow",  "control panel", &wallValLow,  255, NULL);
    cvCreateTrackbar("wallValHigh", "control panel", &wallValHigh, 255, NULL);
    vector<vector<Point> > squares;

    while (true) {
        // Capture image.
        cap >> origFrame;

        // Resize the image to increase processing rate. See here for details:
        // http://opencv.willowgarage.com/documentation/cpp/image_filtering.html
        pyrDown(origFrame, resizedFrame, Size(origFrame.cols/2, origFrame.rows/2));

        // Convert the frame to HSV. TODO: combine this with more filtering and
        // turn into function.
        cvtColor(resizedFrame, hsvFrame, CV_BGR2HSV);

        // Threshold hsvFrame for color of maze walls.
        inRange(hsvFrame, Scalar(wallHueLow,  wallSatLow,  wallValLow),
                          Scalar(wallHueHigh, wallSatHigh, wallValHigh), bwFrame);

        // Find and draw squares.
        findSquares(bwFrame, squares);
        drawSquares(resizedFrame, squares);

        // Show the image, with the squares overlaid.
        imshow("origImage", resizedFrame);
        imshow("hsvImage", hsvFrame);
        imshow("bwImage", bwFrame);

        // Wait 5 milliseconds for a keypress.
        int c = waitKey(5);
        // Exit if the spacebar is pressed. NOTE: killing the program with
        // Ctrl+C sometimes stops OpenCV at a bad place and effects a kernel
        // panic! If you really like Ctrl+C, do so at your own risk!
        if ((char) c == 32) {
            return 0;
        }
    }

    return 0;
}
<commit_msg>Measure side lengths and calculate ratio of min/max side lengths to recognize square.<commit_after>// The "Square Detector" program.
// It loads several images sequentially and tries to find squares in
// each image

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <iostream>
#include <math.h>
#include <string.h>
#include <stdio.h>

#include <ros/ros.h>
#include <osuar_vision/windowCoordinates.h>

using namespace cv;

int thresh = 50, N = 11;
int maxCosineThresh = 25;
int maxDiffThresh = 300;

// Find colors of any hue...
int wallHueLow  = 0;
int wallHueHigh = 179;

// ...of low saturation...
int wallSatLow  = 0;
int wallSatHigh = 60;

// ...ranging down to gray, but not completely dark. That is to say, white.
int wallValLow  = 50;
int wallValHigh = 255;

ros::Publisher visPub;
osuar_vision::windowCoordinates winCoords;

// helper function:
// finds a cosine of angle between vectors
// from pt0->pt1 and from pt0->pt2
static double angle( Point pt1, Point pt2, Point pt0 )
{
    double dx1 = pt1.x - pt0.x;
    double dy1 = pt1.y - pt0.y;
    double dx2 = pt2.x - pt0.x;
    double dy2 = pt2.y - pt0.y;
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}

// returns sequence of squares detected on the image.
// the sequence is stored in the specified memory storage
static void findSquares( const Mat& image, vector<vector<Point> >& squares )
{
    squares.clear();

    Mat pyr, timg, gray0(image.size(), CV_8U), gray;

    // down-scale and upscale the image to filter out the noise
    pyrDown(image, pyr, Size(image.cols/2, image.rows/2));
    pyrUp(pyr, timg, image.size());
    vector<vector<Point> > contours;

    // find squares in every color plane of the image
    //for( int c = 0; c < 3; c++ )
    //{
        //int ch[] = {c, 0};
        //mixChannels(&timg, 1, &gray0, 1, ch, 1);

        // try several threshold levels
        for( int l = 0; l < N; l++ )
        {
            // hack: use Canny instead of zero threshold level.
            // Canny helps to catch squares with gradient shading
            if( l == 0 )
            {
                // apply Canny. Take the upper threshold from slider
                // and set the lower to 0 (which forces edges merging)
                Canny(image, gray, 0, thresh, 5);
                // dilate canny output to remove potential
                // holes between edge segments
                dilate(gray, gray, Mat(), Point(-1,-1));
            }
            else
            {
                // apply threshold if l!=0:
                //     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
                gray = image >= (l+1)*255/N;
            }

            // find contours and store them all as a list
            findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);

            vector<Point> approx;

            // test each contour
            for( size_t i = 0; i < contours.size(); i++ )
            {
                // approximate contour with accuracy proportional
                // to the contour perimeter
                approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

                // square contours should have 4 vertices after approximation
                // relatively large area (to filter out noisy contours)
                // and be convex.
                // Note: absolute value of an area is used because
                // area may be positive or negative - in accordance with the
                // contour orientation
                if( approx.size() == 4 &&
                    fabs(contourArea(Mat(approx))) > 1000 &&
                    isContourConvex(Mat(approx)) )
                {
                    double maxCosine = 0;
                    double minSideLen = 100000;
                    double maxSideLen = 0;
                    double sideRatio = 0;

                    for( int j = 2; j < 5; j++ )
                    {
                        // find the maximum cosine of the angle between joint edges
                        double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
                        maxCosine = MAX(maxCosine, cosine);

                        // Find the maximum difference in length of adjacent
                        // sides
                        double sideLen = sqrt(pow((approx[j%4].x - approx[(j+1)%4].x), 2) + pow((approx[j%4].y - approx[(j+1)%4].y), 2));
                        minSideLen = MIN(minSideLen, sideLen);
                        maxSideLen = MAX(maxSideLen, sideLen);
                    }

                    sideRatio = minSideLen / maxSideLen;

                    std::cout << minSideLen << "  " << maxSideLen << "\n";

                    // if cosines of all angles are small
                    // (all angles are ~90 degree) then write quandrange
                    // vertices to resultant sequence
                    if( maxCosine < ((double) maxCosineThresh)/100 && sideRatio >= (double) sideRatioThresh/100 )
                        squares.push_back(approx);
                }
            }
        }
    //}
}

// the function draws all the squares in the image
static void drawSquares( Mat& image, const vector<vector<Point> >& squares )
{
    for( size_t i = 0; i < squares.size(); i++ )
    {
        const Point* p = &squares[i][0];
        int n = (int)squares[i].size();
        polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA);

        std::cout << "x: " << squares[i][0].x << "  y: " << squares[i][0].y << "\n";

        // Only publish coordinates for one of the squares. Coordinates are
        // shifted over by half the camera resolution (which itself is scaled
        // down by a factor of two!) on each axis. The y coordinate is inverted
        // so up is positive.
        if (i == 0) {
            winCoords.x =   (squares[0][0].x + squares[0][2].x)/2 - 180;
            winCoords.y = -((squares[0][0].y + squares[0][2].y)/2 - 120);
            visPub.publish(winCoords);
        }
    }
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "vision");
    ros::NodeHandle nh;
    visPub = nh.advertise<osuar_vision::windowCoordinates>("window_coordinates", 1);

    // Instantiate VideoCapture object. See here for details:
    // http://opencv.willowgarage.com/documentation/cpp/reading_and_writing_images_and_video.html
    VideoCapture cap(1);

    // Configure video. Our camera NEEDS the frame width to be set to 720
    // pixels.
    cap.set(CV_CAP_PROP_FRAME_WIDTH, 720);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, 480);
    //cap.set(CV_CAP_PROP_FPS, 20);

    // Instantiate a Mat in which to store each video frame.
    Mat origFrame;
    Mat resizedFrame;   // Scaled-down from origFrame by factor of 2.
    Mat hsvFrame;   // Converted to HSV space from resizedFrame.
    Mat bwFrame;   // Black/white image after thresholding hsvFrame.

    namedWindow("origImage", 1);
    namedWindow("hsvImage", 1);
    namedWindow("bwImage", 1);
    cvNamedWindow("control panel");
    cvCreateTrackbar("threshold",   "control panel", &thresh,      300, NULL);
    cvCreateTrackbar("maxCosineThresh (x100)",   "control panel", &maxCosineThresh,      100, NULL);
    cvCreateTrackbar("maxDiffThresh",   "control panel", &maxDiffThresh,      1000, NULL);
    cvCreateTrackbar("wallHueLow",  "control panel", &wallHueLow,  179, NULL);
    cvCreateTrackbar("wallHueHigh", "control panel", &wallHueHigh, 179, NULL);
    cvCreateTrackbar("wallSatLow",  "control panel", &wallSatLow,  255, NULL);
    cvCreateTrackbar("wallSatHigh", "control panel", &wallSatHigh, 255, NULL);
    cvCreateTrackbar("wallValLow",  "control panel", &wallValLow,  255, NULL);
    cvCreateTrackbar("wallValHigh", "control panel", &wallValHigh, 255, NULL);
    vector<vector<Point> > squares;

    while (true) {
        // Capture image.
        cap >> origFrame;

        // Resize the image to increase processing rate. See here for details:
        // http://opencv.willowgarage.com/documentation/cpp/image_filtering.html
        pyrDown(origFrame, resizedFrame, Size(origFrame.cols/2, origFrame.rows/2));

        // Convert the frame to HSV. TODO: combine this with more filtering and
        // turn into function.
        cvtColor(resizedFrame, hsvFrame, CV_BGR2HSV);

        // Threshold hsvFrame for color of maze walls.
        inRange(hsvFrame, Scalar(wallHueLow,  wallSatLow,  wallValLow),
                          Scalar(wallHueHigh, wallSatHigh, wallValHigh), bwFrame);

        // Find and draw squares.
        findSquares(bwFrame, squares);
        drawSquares(resizedFrame, squares);

        // Show the image, with the squares overlaid.
        imshow("origImage", resizedFrame);
        imshow("hsvImage", hsvFrame);
        imshow("bwImage", bwFrame);

        // Wait 5 milliseconds for a keypress.
        int c = waitKey(5);
        // Exit if the spacebar is pressed. NOTE: killing the program with
        // Ctrl+C sometimes stops OpenCV at a bad place and effects a kernel
        // panic! If you really like Ctrl+C, do so at your own risk!
        if ((char) c == 32) {
            return 0;
        }
    }

    return 0;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <signal.h>

extern "C" {
#include <lirc/lirc_client.h>
}

namespace {

const std::size_t UNIX_PATH_MAX = 108;
const std::size_t buffer_size = 4096;

// Configuration (this should be in a configuration file)
const char* server_socket_path = "/tmp/asgard_socket";
const char* client_socket_path = "/tmp/asgard_ir_socket";

//Buffers
char write_buffer[buffer_size + 1];
char receive_buffer[buffer_size + 1];

// The socket file descriptor
int socket_fd;

// The socket addresses
struct sockaddr_un client_address;
struct sockaddr_un server_address;

// The remote IDs
int source_id = -1;
int button_actuator_id = -1;

void stop(){
    std::cout << "asgard:ir: stop the driver" << std::endl;

    //Closes LIRC
    lirc_deinit();

    // Unregister the button actuator, if necessary
    if(temperature_sensor_id >= 0){
        auto nbytes = snprintf(write_buffer, buffer_size, "UNREG_ACTUATOR %d %d", source_id, button_actuator_id);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
    }

    // Unregister the source, if necessary
    if(source_id >= 0){
        auto nbytes = snprintf(write_buffer, buffer_size, "UNREG_SOURCE %d", source_id);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
    }

    // Unlink the client socket
    unlink(client_socket_path);

    // Close the socket
    close(socket_fd);
}

void terminate(int){
    stop();

    std::exit(0);
}

void ir_received(char* raw_code){
    std::string full_code(raw_code);

    auto code_end = full_code.find(' ');
    std::string code(full_code.begin(), full_code.begin() + code_end);

    auto repeat_end = full_code.find(' ', code_end + 1);
    std::string repeat(full_code.begin() + code_end + 1, full_code.begin() + repeat_end);

    auto key_end = full_code.find(' ', repeat_end + 1);
    std::string key(full_code.begin() + repeat_end + 1, full_code.begin() + key_end);

    std::cout << "asgard:ir: Received: " << code << ":" << repeat << ":" << key << std::endl;

    //Send the event to the server
    auto nbytes = snprintf(write_buffer, buffer_size, "EVENT %d %d %s", source_id, button_actuator_id, key.c_str());
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
}

} //End of anonymous namespace

int main(){
    //Initiate LIRC. Exit on failure
    char lirc_name[] = "lirc";
    if(lirc_init(lirc_name, 1) == -1){
        std::cout << "asgard:ir: Failed to init LIRC" << std::endl;
        return 1;
    }

    // Open the socket
    socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if(socket_fd < 0){
        std::cerr << "asgard:ir: socket() failed" << std::endl;
        return 1;
    }

    // Init the client address
    memset(&client_address, 0, sizeof(struct sockaddr_un));
    client_address.sun_family = AF_UNIX;
    snprintf(client_address.sun_path, UNIX_PATH_MAX, client_socket_path);

    // Unlink the client socket
    unlink(client_socket_path);

    // Bind to client socket
    if(bind(socket_fd, (const struct sockaddr *) &client_address, sizeof(struct sockaddr_un)) < 0){
        std::cerr << "asgard:ir: bind() failed" << std::endl;
        return 1;
    }

    //Register signals for "proper" shutdown
    signal(SIGTERM, terminate);
    signal(SIGINT, terminate);

    // Init the server address
    memset(&server_address, 0, sizeof(struct sockaddr_un));
    server_address.sun_family = AF_UNIX;
    snprintf(server_address.sun_path, UNIX_PATH_MAX, server_socket_path);

    socklen_t address_length = sizeof(struct sockaddr_un);

    // Register the source
    auto nbytes = snprintf(write_buffer, buffer_size, "REG_SOURCE ir");
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

    auto bytes_received = recvfrom(socket_fd, receive_buffer, buffer_size, 0, (struct sockaddr *) &(server_address), &address_length);
    receive_buffer[bytes_received] = '\0';

    source_id = atoi(receive_buffer);

    std::cout << "asgard:ir: remote source: " << source_id << std::endl;

    // Register the button actuator
    nbytes = snprintf(write_buffer, buffer_size, "REG_ACTUATOR %d %s", source_id, "ir_button_1");
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

    bytes_received = recvfrom(socket_fd, receive_buffer, buffer_size, 0, (struct sockaddr *) &(server_address), &address_length);
    receive_buffer[bytes_received] = '\0';

    button_actuator_id = atoi(receive_buffer);

    std::cout << "asgard:ir: remote button actuator: " << button_actuator_id << std::endl;

    //Read the default LIRC config
    struct lirc_config* config;
    if(lirc_readconfig(NULL,&config,NULL)==0){
        char* code;

        //Do stuff while LIRC socket is open  0=open  -1=closed.
        while(lirc_nextcode(&code)==0){
            //If code = NULL, nothing was returned from LIRC socket
            if(code){
                //Send code further
                ir_received(code);

                //Need to free up code before the next loop
                free(code);
            }
        }

        //Frees the data structures associated with config.
        lirc_freeconfig(config);
    } else {
        std::cout << "asgard:ir: Failed to read LIRC config" << std::endl;
    }

    stop();

    return 0;
}
<commit_msg>Fix the id<commit_after>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <signal.h>

extern "C" {
#include <lirc/lirc_client.h>
}

namespace {

const std::size_t UNIX_PATH_MAX = 108;
const std::size_t buffer_size = 4096;

// Configuration (this should be in a configuration file)
const char* server_socket_path = "/tmp/asgard_socket";
const char* client_socket_path = "/tmp/asgard_ir_socket";

//Buffers
char write_buffer[buffer_size + 1];
char receive_buffer[buffer_size + 1];

// The socket file descriptor
int socket_fd;

// The socket addresses
struct sockaddr_un client_address;
struct sockaddr_un server_address;

// The remote IDs
int source_id = -1;
int button_actuator_id = -1;

void stop(){
    std::cout << "asgard:ir: stop the driver" << std::endl;

    //Closes LIRC
    lirc_deinit();

    // Unregister the button actuator, if necessary
    if(button_actuator_id >= 0){
        auto nbytes = snprintf(write_buffer, buffer_size, "UNREG_ACTUATOR %d %d", source_id, button_actuator_id);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
    }

    // Unregister the source, if necessary
    if(source_id >= 0){
        auto nbytes = snprintf(write_buffer, buffer_size, "UNREG_SOURCE %d", source_id);
        sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
    }

    // Unlink the client socket
    unlink(client_socket_path);

    // Close the socket
    close(socket_fd);
}

void terminate(int){
    stop();

    std::exit(0);
}

void ir_received(char* raw_code){
    std::string full_code(raw_code);

    auto code_end = full_code.find(' ');
    std::string code(full_code.begin(), full_code.begin() + code_end);

    auto repeat_end = full_code.find(' ', code_end + 1);
    std::string repeat(full_code.begin() + code_end + 1, full_code.begin() + repeat_end);

    auto key_end = full_code.find(' ', repeat_end + 1);
    std::string key(full_code.begin() + repeat_end + 1, full_code.begin() + key_end);

    std::cout << "asgard:ir: Received: " << code << ":" << repeat << ":" << key << std::endl;

    //Send the event to the server
    auto nbytes = snprintf(write_buffer, buffer_size, "EVENT %d %d %s", source_id, button_actuator_id, key.c_str());
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));
}

} //End of anonymous namespace

int main(){
    //Initiate LIRC. Exit on failure
    char lirc_name[] = "lirc";
    if(lirc_init(lirc_name, 1) == -1){
        std::cout << "asgard:ir: Failed to init LIRC" << std::endl;
        return 1;
    }

    // Open the socket
    socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if(socket_fd < 0){
        std::cerr << "asgard:ir: socket() failed" << std::endl;
        return 1;
    }

    // Init the client address
    memset(&client_address, 0, sizeof(struct sockaddr_un));
    client_address.sun_family = AF_UNIX;
    snprintf(client_address.sun_path, UNIX_PATH_MAX, client_socket_path);

    // Unlink the client socket
    unlink(client_socket_path);

    // Bind to client socket
    if(bind(socket_fd, (const struct sockaddr *) &client_address, sizeof(struct sockaddr_un)) < 0){
        std::cerr << "asgard:ir: bind() failed" << std::endl;
        return 1;
    }

    //Register signals for "proper" shutdown
    signal(SIGTERM, terminate);
    signal(SIGINT, terminate);

    // Init the server address
    memset(&server_address, 0, sizeof(struct sockaddr_un));
    server_address.sun_family = AF_UNIX;
    snprintf(server_address.sun_path, UNIX_PATH_MAX, server_socket_path);

    socklen_t address_length = sizeof(struct sockaddr_un);

    // Register the source
    auto nbytes = snprintf(write_buffer, buffer_size, "REG_SOURCE ir");
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

    auto bytes_received = recvfrom(socket_fd, receive_buffer, buffer_size, 0, (struct sockaddr *) &(server_address), &address_length);
    receive_buffer[bytes_received] = '\0';

    source_id = atoi(receive_buffer);

    std::cout << "asgard:ir: remote source: " << source_id << std::endl;

    // Register the button actuator
    nbytes = snprintf(write_buffer, buffer_size, "REG_ACTUATOR %d %s", source_id, "ir_button_1");
    sendto(socket_fd, write_buffer, nbytes, 0, (struct sockaddr *) &server_address, sizeof(struct sockaddr_un));

    bytes_received = recvfrom(socket_fd, receive_buffer, buffer_size, 0, (struct sockaddr *) &(server_address), &address_length);
    receive_buffer[bytes_received] = '\0';

    button_actuator_id = atoi(receive_buffer);

    std::cout << "asgard:ir: remote button actuator: " << button_actuator_id << std::endl;

    //Read the default LIRC config
    struct lirc_config* config;
    if(lirc_readconfig(NULL,&config,NULL)==0){
        char* code;

        //Do stuff while LIRC socket is open  0=open  -1=closed.
        while(lirc_nextcode(&code)==0){
            //If code = NULL, nothing was returned from LIRC socket
            if(code){
                //Send code further
                ir_received(code);

                //Need to free up code before the next loop
                free(code);
            }
        }

        //Frees the data structures associated with config.
        lirc_freeconfig(config);
    } else {
        std::cout << "asgard:ir: Failed to read LIRC config" << std::endl;
    }

    stop();

    return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the config.tests of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylandintegration.h"

#include "qwaylanddisplay.h"
#include "qwaylandshmbackingstore.h"
#include "qwaylandshmwindow.h"
#include "qwaylandnativeinterface.h"
#include "qwaylandclipboard.h"
#include "qwaylanddnd.h"

#include "QtPlatformSupport/private/qgenericunixfontdatabase_p.h"
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>

#include <QtGui/private/qguiapplication_p.h>

#include <QtGui/QWindowSystemInterface>
#include <QtGui/QPlatformCursor>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOpenGLContext>

#include <private/qplatforminputcontextfactory_qpa_p.h>
#include <qplatformaccessibility_qpa.h>
#include <qplatforminputcontext_qpa.h>

#ifdef QT_WAYLAND_GL_SUPPORT
#include "gl_integration/qwaylandglintegration.h"
#endif

#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
#include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
#endif

QWaylandIntegration::QWaylandIntegration()
    : mFontDb(new QGenericUnixFontDatabase())
    , mEventDispatcher(createUnixEventDispatcher())
    , mNativeInterface(new QWaylandNativeInterface)
    , mAccessibility(new QPlatformAccessibility())
{
    QGuiApplicationPrivate::instance()->setEventDispatcher(mEventDispatcher);
    mDisplay = new QWaylandDisplay();
    mClipboard = new QWaylandClipboard(mDisplay);
    mDrag = new QWaylandDrag(mDisplay);

    foreach (QPlatformScreen *screen, mDisplay->screens())
        screenAdded(screen);

    mInputContext = QPlatformInputContextFactory::create();
}

QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const
{
    return mNativeInterface;
}

bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
    switch (cap) {
    case ThreadedPixmaps: return true;
    case OpenGL:
#ifdef QT_WAYLAND_GL_SUPPORT
        return true;
#else
        return false;
#endif
    case ThreadedOpenGL:
        return hasCapability(OpenGL);
    default: return QPlatformIntegration::hasCapability(cap);
    }
}

QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const
{
#ifdef QT_WAYLAND_GL_SUPPORT
    if (window->surfaceType() == QWindow::OpenGLSurface)
        return mDisplay->eglIntegration()->createEglWindow(window);
#endif
    return new QWaylandShmWindow(window);
}

QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
#ifdef QT_WAYLAND_GL_SUPPORT
    return mDisplay->eglIntegration()->createPlatformOpenGLContext(context->format(), context->shareHandle());
#else
    Q_UNUSED(glFormat);
    Q_UNUSED(share);
    return 0;
#endif
}

QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const
{
    return new QWaylandShmBackingStore(window);
}

QAbstractEventDispatcher *QWaylandIntegration::guiThreadEventDispatcher() const
{
    return mEventDispatcher;
}

QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const
{
    return mFontDb;
}

QPlatformClipboard *QWaylandIntegration::clipboard() const
{
    return mClipboard;
}

QPlatformDrag *QWaylandIntegration::drag() const
{
    return mDrag;
}

QPlatformInputContext *QWaylandIntegration::inputContext() const
{
    return mInputContext;
}

QVariant QWaylandIntegration::styleHint(StyleHint hint) const
{
#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
    if (hint == ShowIsFullScreen && mDisplay->windowManagerIntegration())
        return mDisplay->windowManagerIntegration()->showIsFullScreen();
#endif
    return QPlatformIntegration::styleHint(hint);
}

QPlatformAccessibility *QWaylandIntegration::accessibility() const
{
    return mAccessibility;
}
<commit_msg>We have buffer Queueing<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the config.tests of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qwaylandintegration.h"

#include "qwaylanddisplay.h"
#include "qwaylandshmbackingstore.h"
#include "qwaylandshmwindow.h"
#include "qwaylandnativeinterface.h"
#include "qwaylandclipboard.h"
#include "qwaylanddnd.h"

#include "QtPlatformSupport/private/qgenericunixfontdatabase_p.h"
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>

#include <QtGui/private/qguiapplication_p.h>

#include <QtGui/QWindowSystemInterface>
#include <QtGui/QPlatformCursor>
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOpenGLContext>

#include <private/qplatforminputcontextfactory_qpa_p.h>
#include <qplatformaccessibility_qpa.h>
#include <qplatforminputcontext_qpa.h>

#ifdef QT_WAYLAND_GL_SUPPORT
#include "gl_integration/qwaylandglintegration.h"
#endif

#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
#include "windowmanager_integration/qwaylandwindowmanagerintegration.h"
#endif

QWaylandIntegration::QWaylandIntegration()
    : mFontDb(new QGenericUnixFontDatabase())
    , mEventDispatcher(createUnixEventDispatcher())
    , mNativeInterface(new QWaylandNativeInterface)
    , mAccessibility(new QPlatformAccessibility())
{
    QGuiApplicationPrivate::instance()->setEventDispatcher(mEventDispatcher);
    mDisplay = new QWaylandDisplay();
    mClipboard = new QWaylandClipboard(mDisplay);
    mDrag = new QWaylandDrag(mDisplay);

    foreach (QPlatformScreen *screen, mDisplay->screens())
        screenAdded(screen);

    mInputContext = QPlatformInputContextFactory::create();
}

QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const
{
    return mNativeInterface;
}

bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
    switch (cap) {
    case ThreadedPixmaps: return true;
    case OpenGL:
#ifdef QT_WAYLAND_GL_SUPPORT
        return true;
#else
        return false;
#endif
    case ThreadedOpenGL:
        return hasCapability(OpenGL);
    case BufferQueueingOpenGL:
        return true;
    default: return QPlatformIntegration::hasCapability(cap);
    }
}

QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const
{
#ifdef QT_WAYLAND_GL_SUPPORT
    if (window->surfaceType() == QWindow::OpenGLSurface)
        return mDisplay->eglIntegration()->createEglWindow(window);
#endif
    return new QWaylandShmWindow(window);
}

QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
#ifdef QT_WAYLAND_GL_SUPPORT
    return mDisplay->eglIntegration()->createPlatformOpenGLContext(context->format(), context->shareHandle());
#else
    Q_UNUSED(glFormat);
    Q_UNUSED(share);
    return 0;
#endif
}

QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const
{
    return new QWaylandShmBackingStore(window);
}

QAbstractEventDispatcher *QWaylandIntegration::guiThreadEventDispatcher() const
{
    return mEventDispatcher;
}

QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const
{
    return mFontDb;
}

QPlatformClipboard *QWaylandIntegration::clipboard() const
{
    return mClipboard;
}

QPlatformDrag *QWaylandIntegration::drag() const
{
    return mDrag;
}

QPlatformInputContext *QWaylandIntegration::inputContext() const
{
    return mInputContext;
}

QVariant QWaylandIntegration::styleHint(StyleHint hint) const
{
#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
    if (hint == ShowIsFullScreen && mDisplay->windowManagerIntegration())
        return mDisplay->windowManagerIntegration()->showIsFullScreen();
#endif
    return QPlatformIntegration::styleHint(hint);
}

QPlatformAccessibility *QWaylandIntegration::accessibility() const
{
    return mAccessibility;
}
<|endoftext|>