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

    Copyright (c) 1999 Preston Brown <pbrown@kde.org>
    Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
    Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>

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

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qlistview.h>
#include <qlayout.h>
#include <qpopupmenu.h>
#include <qcursor.h>

#include <klocale.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kglobal.h>

#include <libkcal/calendar.h>
#include <libkcal/incidenceformatter.h>

#include "koglobals.h"
#include "koprefs.h"
#include "koincidencetooltip.h"
#include "koeventpopupmenu.h"

#include "kolistview.h"
#include "kolistview.moc"

KOListViewToolTip::KOListViewToolTip( QWidget* parent,
                                      KListView* lv )
  :QToolTip(parent)
{
  eventlist=lv;
}

void KOListViewToolTip::maybeTip( const QPoint & pos)
{
  QRect r;
  QListViewItem *it = eventlist->itemAt(pos);
  KOListViewItem *i = static_cast<KOListViewItem*>(it);

  if( i && KOPrefs::instance()->mEnableToolTips ) {
    /* Calculate the rectangle. */
    r=eventlist->itemRect( it );
    /* Show the tip */
    QString tipText( IncidenceFormatter::toolTipString( i->data() ) );
    if ( !tipText.isEmpty() ) {
      tip(r, tipText);
    }
  }

}

/**
  This class provides the initialization of a KOListViewItem for calendar
  components using the Incidence::Visitor.
*/
class KOListView::ListItemVisitor : public IncidenceBase::Visitor
{
  public:
    ListItemVisitor( KOListViewItem *item ) : mItem( item ) {}
    ~ListItemVisitor() {}

    bool visit( Event * );
    bool visit( Todo * );
    bool visit( Journal * );

  private:
    KOListViewItem *mItem;
};

bool KOListView::ListItemVisitor::visit( Event *e )
{
  mItem->setText(0,e->summary());
  if ( e->isAlarmEnabled() ) {
    static const QPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" );
    mItem->setPixmap(1,alarmPxmp);
    mItem->setSortKey(1,"1");
  }
  else
    mItem->setSortKey(1,"0");

  if ( e->doesRecur() ) {
    static const QPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" );
    mItem->setPixmap(2,recurPxmp);
    mItem->setSortKey(2,"1");
  }
  else
    mItem->setSortKey(2,"0");

  static const QPixmap eventPxmp = KOGlobals::self()->smallIcon( "appointment" );
  mItem->setPixmap(0, eventPxmp);

  mItem->setText( 3,e->dtStartDateStr());
  if (e->doesFloat()) mItem->setText(4, "---"); else mItem->setText( 4, e->dtStartTimeStr() );
  mItem->setText( 5,e->dtEndDateStr());
  if (e->doesFloat()) mItem->setText(6, "---"); else mItem->setText( 6, e->dtEndTimeStr() );
  mItem->setText( 7,e->categoriesStr());

  QString key = e->dtStart().toString(Qt::ISODate);
  mItem->setSortKey(3,key);

  key = e->dtEnd().toString(Qt::ISODate);
  mItem->setSortKey(5,key);

  return true;
}

bool KOListView::ListItemVisitor::visit(Todo *t)
{
  static const QPixmap todoPxmp = KOGlobals::self()->smallIcon( "todo" );
  static const QPixmap todoDonePxmp = KOGlobals::self()->smallIcon( "checkedbox" );
  mItem->setPixmap(0, t->isCompleted() ? todoDonePxmp : todoPxmp );
  mItem->setText(0,t->summary());
  if ( t->isAlarmEnabled() ) {
    static const QPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" );
    mItem->setPixmap(1,alarmPxmp);
    mItem->setSortKey(1, "1");
  }
  else
    mItem->setSortKey(1, "0");

  if ( t->doesRecur() ) {
    static const QPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" );
    mItem->setPixmap(2,recurPxmp);
    mItem->setSortKey(2, "1");
  }
  else
    mItem->setSortKey(2, "0");

  if (t->hasStartDate()) {
    mItem->setText(3,t->dtStartDateStr());
    mItem->setSortKey(3,t->dtStart().toString(Qt::ISODate));
    if (t->doesFloat()) {
      mItem->setText(4,"---");
    } else {
      mItem->setText(4,t->dtStartTimeStr());
    }
  } else {
    mItem->setText(3,"---");
    mItem->setText(4,"---");
  }

  if (t->hasDueDate()) {
    mItem->setText(5,t->dtDueDateStr());
    if (t->doesFloat()) {
      mItem->setText(6,"---");
    } else {
      mItem->setText(6,t->dtDueTimeStr());
    }
  } else {
    mItem->setText(5,"---");
    mItem->setText(6,"---");
  }
  mItem->setText(7,t->categoriesStr());

  mItem->setSortKey(5,t->dtDue().toString(Qt::ISODate));

  return true;
}

bool KOListView::ListItemVisitor::visit( Journal *t )
{
  static const QPixmap jrnalPxmp = KOGlobals::self()->smallIcon( "journal" );
  mItem->setPixmap( 0, jrnalPxmp );
  if ( t->summary().isEmpty() ) {
    mItem->setText( 0, t->description().section( "\n", 0, 0 ) );
  } else {
    mItem->setText( 0, t->summary() );
  }
  mItem->setText( 3, t->dtStartDateStr() );

  mItem->setSortKey( 3, t->dtStart().toString( Qt::ISODate ) );

  return true;
}

KOListView::KOListView( Calendar *calendar, QWidget *parent,
                        const char *name)
  : KOEventView(calendar, parent, name)
{
  mActiveItem = 0;

  mListView = new KListView(this);
  mListView->addColumn(i18n("Summary"));
  mListView->addColumn(i18n("Reminder")); // alarm set?
  mListView->addColumn(i18n("Recurs")); // recurs?
  mListView->addColumn(i18n("Start Date"));
  mListView->setColumnAlignment(3,AlignHCenter);
  mListView->addColumn(i18n("Start Time"));
  mListView->setColumnAlignment(4,AlignHCenter);
  mListView->addColumn(i18n("End Date"));
  mListView->setColumnAlignment(5,AlignHCenter);
  mListView->addColumn(i18n("End Time"));
  mListView->setColumnAlignment(6,AlignHCenter);
  mListView->addColumn(i18n("Categories"));

  QBoxLayout *layoutTop = new QVBoxLayout(this);
  layoutTop->addWidget(mListView);

  mPopupMenu = eventPopup();
/*
  mPopupMenu->insertSeparator();
  mPopupMenu->insertItem(i18n("Show Dates"), this,
                      SLOT(showDates()));
  mPopupMenu->insertItem(i18n("Hide Dates"), this,
                      SLOT(hideDates()));
*/

  QObject::connect( mListView, SIGNAL( doubleClicked( QListViewItem * ) ),
                    SLOT( defaultItemAction( QListViewItem * ) ) );
  QObject::connect( mListView, SIGNAL( returnPressed( QListViewItem * ) ),
                    SLOT( defaultItemAction( QListViewItem * ) ) );
  QObject::connect( mListView, SIGNAL( rightButtonClicked ( QListViewItem *,
                                                            const QPoint &,
                                                            int ) ),
                    SLOT( popupMenu( QListViewItem *, const QPoint &, int ) ) );
  QObject::connect( mListView, SIGNAL( selectionChanged() ),
                    SLOT( processSelectionChange() ) );

//  setMinimumSize(100,100);
  mListView->restoreLayout(KOGlobals::self()->config(),"KOListView Layout");

  new KOListViewToolTip( mListView->viewport(), mListView );

  mSelectedDates.append( QDate::currentDate() );
}

KOListView::~KOListView()
{
  delete mPopupMenu;
}

int KOListView::maxDatesHint()
{
  return 0;
}

int KOListView::currentDateCount()
{
  return mSelectedDates.count();
}

Incidence::List KOListView::selectedIncidences()
{
  Incidence::List eventList;

  QListViewItem *item = mListView->selectedItem();
  if (item) eventList.append(((KOListViewItem *)item)->data());

  return eventList;
}

DateList KOListView::selectedDates()
{
  return mSelectedDates;
}

void KOListView::showDates(bool show)
{
  // Shouldn't we set it to a value greater 0? When showDates is called with
  // show == true at first, then the columnwidths are set to zero.
  static int oldColWidth1 = 0;
  static int oldColWidth3 = 0;

  if (!show) {
    oldColWidth1 = mListView->columnWidth(1);
    oldColWidth3 = mListView->columnWidth(3);
    mListView->setColumnWidth(1, 0);
    mListView->setColumnWidth(3, 0);
  } else {
    mListView->setColumnWidth(1, oldColWidth1);
    mListView->setColumnWidth(3, oldColWidth3);
  }
  mListView->repaint();
}

void KOListView::showDates()
{
  showDates(true);
}

void KOListView::hideDates()
{
  showDates(false);
}

void KOListView::updateView()
{
  kdDebug(5850) << "KOListView::updateView() does nothing" << endl;
}

void KOListView::showDates(const QDate &start, const QDate &end)
{
  clear();

  QDate date = start;
  while( date <= end ) {
    addIncidences( calendar()->incidences(date) );
    mSelectedDates.append( date );
    date = date.addDays( 1 );
  }

  emit incidenceSelected( 0 );
}

void KOListView::addIncidences( const Incidence::List &incidenceList )
{
  Incidence::List::ConstIterator it;
  for( it = incidenceList.begin(); it != incidenceList.end(); ++it ) {
    addIncidence( *it );
  }
}

void KOListView::addIncidence(Incidence *incidence)
{
  if ( mUidDict.find( incidence->uid() ) ) return;

  mUidDict.insert( incidence->uid(), incidence );

  KOListViewItem *item = new KOListViewItem( incidence, mListView );
  ListItemVisitor v(item);
  if (incidence->accept(v)) return;
  else delete item;
}

void KOListView::showIncidences( const Incidence::List &incidenceList )
{
  clear();

  addIncidences( incidenceList );

  // After new creation of list view no events are selected.
  emit incidenceSelected( 0 );
}

void KOListView::changeIncidenceDisplay(Incidence *incidence, int action)
{
  KOListViewItem *item;
  QDate f = mSelectedDates.first();
  QDate l = mSelectedDates.last();

  QDate date;
  if ( incidence->type() == "Todo" )
    date = static_cast<Todo *>(incidence)->dtDue().date();
  else
    date = incidence->dtStart().date();

  switch(action) {
    case KOGlobals::INCIDENCEADDED: {
      if ( date >= f && date <= l )
        addIncidence( incidence );
      break;
    }
    case KOGlobals::INCIDENCEEDITED: {
      item = getItemForIncidence(incidence);
      if (item) {
        delete item;
        mUidDict.remove( incidence->uid() );
      }
      if ( date >= f && date <= l )
        addIncidence( incidence );
    }
    break;
    case KOGlobals::INCIDENCEDELETED: {
      item = getItemForIncidence(incidence);
      if (item)
        delete item;
      break;
    }
    default:
      kdDebug(5850) << "KOListView::changeIncidenceDisplay(): Illegal action " << action << endl;
  }
}

KOListViewItem *KOListView::getItemForIncidence(Incidence *incidence)
{
  KOListViewItem *item = (KOListViewItem *)mListView->firstChild();
  while (item) {
//    kdDebug(5850) << "Item " << item->text(0) << " found" << endl;
    if (item->data() == incidence) return item;
    item = (KOListViewItem *)item->nextSibling();
  }
  return 0;
}

void KOListView::defaultItemAction(QListViewItem *i)
{
  KOListViewItem *item = static_cast<KOListViewItem *>( i );
  if ( item ) defaultAction( item->data() );
}

void KOListView::popupMenu(QListViewItem *item,const QPoint &,int)
{
  mActiveItem = (KOListViewItem *)item;
  if (mActiveItem) {
    Incidence *incidence = mActiveItem->data();
    // FIXME: For recurring incidences we don't know the date of this
    // occurrence, there's no reference to it at all!
    mPopupMenu->showIncidencePopup( incidence, QDate() );
  }
  else {
    showNewEventPopup();
  }
}

void KOListView::readSettings(KConfig *config)
{
  mListView->restoreLayout(config,"KOListView Layout");
}

void KOListView::writeSettings(KConfig *config)
{
  mListView->saveLayout(config,"KOListView Layout");
}

void KOListView::processSelectionChange()
{
  kdDebug(5850) << "KOListView::processSelectionChange()" << endl;

  KOListViewItem *item =
    static_cast<KOListViewItem *>( mListView->selectedItem() );

  if ( !item ) {
    emit incidenceSelected( 0 );
  } else {
    emit incidenceSelected( item->data() );
  }
}

void KOListView::clearSelection()
{
  mListView->selectAll( false );
}

void KOListView::clear()
{
  mSelectedDates.clear();
  mListView->clear();
  mUidDict.clear();
}
<commit_msg>Backport of SVN commit 632254 by kainhofe:<commit_after>/*
    This file is part of KOrganizer.

    Copyright (c) 1999 Preston Brown <pbrown@kde.org>
    Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
    Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>

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

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

    As a special exception, permission is given to link this program
    with any edition of Qt, and distribute the resulting executable,
    without including the source code for Qt in the source distribution.
*/

#include <qlistview.h>
#include <qlayout.h>
#include <qpopupmenu.h>
#include <qcursor.h>

#include <klocale.h>
#include <kdebug.h>
#include <kiconloader.h>
#include <kglobal.h>

#include <libkcal/calendar.h>
#include <libkcal/incidenceformatter.h>

#include "koglobals.h"
#include "koprefs.h"
#include "koincidencetooltip.h"
#include "koeventpopupmenu.h"

#include "kolistview.h"
#include "kolistview.moc"

KOListViewToolTip::KOListViewToolTip( QWidget* parent,
                                      KListView* lv )
  :QToolTip(parent)
{
  eventlist=lv;
}

void KOListViewToolTip::maybeTip( const QPoint & pos)
{
  QRect r;
  QListViewItem *it = eventlist->itemAt(pos);
  KOListViewItem *i = static_cast<KOListViewItem*>(it);

  if( i && KOPrefs::instance()->mEnableToolTips ) {
    /* Calculate the rectangle. */
    r=eventlist->itemRect( it );
    /* Show the tip */
    QString tipText( IncidenceFormatter::toolTipString( i->data() ) );
    if ( !tipText.isEmpty() ) {
      tip(r, tipText);
    }
  }

}

/**
  This class provides the initialization of a KOListViewItem for calendar
  components using the Incidence::Visitor.
*/
class KOListView::ListItemVisitor : public IncidenceBase::Visitor
{
  public:
    ListItemVisitor( KOListViewItem *item ) : mItem( item ) {}
    ~ListItemVisitor() {}

    bool visit( Event * );
    bool visit( Todo * );
    bool visit( Journal * );

  private:
    KOListViewItem *mItem;
};

bool KOListView::ListItemVisitor::visit( Event *e )
{
  mItem->setText(0,e->summary());
  if ( e->isAlarmEnabled() ) {
    static const QPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" );
    mItem->setPixmap(1,alarmPxmp);
    mItem->setSortKey(1,"1");
  }
  else
    mItem->setSortKey(1,"0");

  if ( e->doesRecur() ) {
    static const QPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" );
    mItem->setPixmap(2,recurPxmp);
    mItem->setSortKey(2,"1");
  }
  else
    mItem->setSortKey(2,"0");

  static const QPixmap eventPxmp = KOGlobals::self()->smallIcon( "appointment" );
  mItem->setPixmap(0, eventPxmp);

  mItem->setText( 3,e->dtStartDateStr());
  mItem->setSortKey( 3, e->dtStart().toString(Qt::ISODate));
  if (e->doesFloat()) mItem->setText(4, "---"); else {
    mItem->setText( 4, e->dtStartTimeStr() );
    mItem->setSortKey( 4,e->dtStart().time().toString(Qt::ISODate));
  }
  mItem->setText( 5,e->dtEndDateStr());
  mItem->setSortKey( 5, e->dtEnd().toString(Qt::ISODate));
  if (e->doesFloat()) mItem->setText(6, "---"); else {
    mItem->setText( 6, e->dtEndTimeStr() );
    mItem->setSortKey( 6, e->dtEnd().time().toString(Qt::ISODate));
  }
  mItem->setText( 7,e->categoriesStr());

  return true;
}

bool KOListView::ListItemVisitor::visit(Todo *t)
{
  static const QPixmap todoPxmp = KOGlobals::self()->smallIcon( "todo" );
  static const QPixmap todoDonePxmp = KOGlobals::self()->smallIcon( "checkedbox" );
  mItem->setPixmap(0, t->isCompleted() ? todoDonePxmp : todoPxmp );
  mItem->setText(0,t->summary());
  if ( t->isAlarmEnabled() ) {
    static const QPixmap alarmPxmp = KOGlobals::self()->smallIcon( "bell" );
    mItem->setPixmap(1,alarmPxmp);
    mItem->setSortKey(1, "1");
  }
  else
    mItem->setSortKey(1, "0");

  if ( t->doesRecur() ) {
    static const QPixmap recurPxmp = KOGlobals::self()->smallIcon( "recur" );
    mItem->setPixmap(2,recurPxmp);
    mItem->setSortKey(2, "1");
  }
  else
    mItem->setSortKey(2, "0");

  if (t->hasStartDate()) {
    mItem->setText(3,t->dtStartDateStr());
    mItem->setSortKey(3,t->dtStart().toString(Qt::ISODate));
    if (t->doesFloat()) {
      mItem->setText(4,"---");
    } else {
      mItem->setText(4,t->dtStartTimeStr());
      mItem->setSortKey( 4, t->dtStart().time().toString(Qt::ISODate) );
    }
  } else {
    mItem->setText(3,"---");
    mItem->setText(4,"---");
  }

  if (t->hasDueDate()) {
    mItem->setText(5,t->dtDueDateStr());
    mItem->setSortKey( 5, t->dtDue().toString(Qt::ISODate) );
    if (t->doesFloat()) {
      mItem->setText(6,"---");
    } else {
      mItem->setText(6,t->dtDueTimeStr());
      mItem->setSortKey( 6, t->dtDue().time().toString(Qt::ISODate) );
    }
  } else {
    mItem->setText(5,"---");
    mItem->setText(6,"---");
  }
  mItem->setText(7,t->categoriesStr());

  return true;
}

bool KOListView::ListItemVisitor::visit( Journal *t )
{
  static const QPixmap jrnalPxmp = KOGlobals::self()->smallIcon( "journal" );
  mItem->setPixmap( 0, jrnalPxmp );
  if ( t->summary().isEmpty() ) {
    mItem->setText( 0, t->description().section( "\n", 0, 0 ) );
  } else {
    mItem->setText( 0, t->summary() );
  }
  mItem->setText( 3, t->dtStartDateStr() );
  mItem->setSortKey( 3, t->dtStart().toString( Qt::ISODate ) );

  return true;
}

KOListView::KOListView( Calendar *calendar, QWidget *parent,
                        const char *name)
  : KOEventView(calendar, parent, name)
{
  mActiveItem = 0;

  mListView = new KListView(this);
  mListView->addColumn(i18n("Summary"));
  mListView->addColumn(i18n("Reminder")); // alarm set?
  mListView->addColumn(i18n("Recurs")); // recurs?
  mListView->addColumn(i18n("Start Date"));
  mListView->setColumnAlignment(3,AlignHCenter);
  mListView->addColumn(i18n("Start Time"));
  mListView->setColumnAlignment(4,AlignHCenter);
  mListView->addColumn(i18n("End Date"));
  mListView->setColumnAlignment(5,AlignHCenter);
  mListView->addColumn(i18n("End Time"));
  mListView->setColumnAlignment(6,AlignHCenter);
  mListView->addColumn(i18n("Categories"));

  QBoxLayout *layoutTop = new QVBoxLayout(this);
  layoutTop->addWidget(mListView);

  mPopupMenu = eventPopup();
/*
  mPopupMenu->insertSeparator();
  mPopupMenu->insertItem(i18n("Show Dates"), this,
                      SLOT(showDates()));
  mPopupMenu->insertItem(i18n("Hide Dates"), this,
                      SLOT(hideDates()));
*/

  QObject::connect( mListView, SIGNAL( doubleClicked( QListViewItem * ) ),
                    SLOT( defaultItemAction( QListViewItem * ) ) );
  QObject::connect( mListView, SIGNAL( returnPressed( QListViewItem * ) ),
                    SLOT( defaultItemAction( QListViewItem * ) ) );
  QObject::connect( mListView, SIGNAL( rightButtonClicked ( QListViewItem *,
                                                            const QPoint &,
                                                            int ) ),
                    SLOT( popupMenu( QListViewItem *, const QPoint &, int ) ) );
  QObject::connect( mListView, SIGNAL( selectionChanged() ),
                    SLOT( processSelectionChange() ) );

//  setMinimumSize(100,100);
  mListView->restoreLayout(KOGlobals::self()->config(),"KOListView Layout");

  new KOListViewToolTip( mListView->viewport(), mListView );

  mSelectedDates.append( QDate::currentDate() );
}

KOListView::~KOListView()
{
  delete mPopupMenu;
}

int KOListView::maxDatesHint()
{
  return 0;
}

int KOListView::currentDateCount()
{
  return mSelectedDates.count();
}

Incidence::List KOListView::selectedIncidences()
{
  Incidence::List eventList;

  QListViewItem *item = mListView->selectedItem();
  if (item) eventList.append(((KOListViewItem *)item)->data());

  return eventList;
}

DateList KOListView::selectedDates()
{
  return mSelectedDates;
}

void KOListView::showDates(bool show)
{
  // Shouldn't we set it to a value greater 0? When showDates is called with
  // show == true at first, then the columnwidths are set to zero.
  static int oldColWidth1 = 0;
  static int oldColWidth3 = 0;

  if (!show) {
    oldColWidth1 = mListView->columnWidth(1);
    oldColWidth3 = mListView->columnWidth(3);
    mListView->setColumnWidth(1, 0);
    mListView->setColumnWidth(3, 0);
  } else {
    mListView->setColumnWidth(1, oldColWidth1);
    mListView->setColumnWidth(3, oldColWidth3);
  }
  mListView->repaint();
}

void KOListView::showDates()
{
  showDates(true);
}

void KOListView::hideDates()
{
  showDates(false);
}

void KOListView::updateView()
{
  kdDebug(5850) << "KOListView::updateView() does nothing" << endl;
}

void KOListView::showDates(const QDate &start, const QDate &end)
{
  clear();

  QDate date = start;
  while( date <= end ) {
    addIncidences( calendar()->incidences(date) );
    mSelectedDates.append( date );
    date = date.addDays( 1 );
  }

  emit incidenceSelected( 0 );
}

void KOListView::addIncidences( const Incidence::List &incidenceList )
{
  Incidence::List::ConstIterator it;
  for( it = incidenceList.begin(); it != incidenceList.end(); ++it ) {
    addIncidence( *it );
  }
}

void KOListView::addIncidence(Incidence *incidence)
{
  if ( mUidDict.find( incidence->uid() ) ) return;

  mUidDict.insert( incidence->uid(), incidence );

  KOListViewItem *item = new KOListViewItem( incidence, mListView );
  ListItemVisitor v(item);
  if (incidence->accept(v)) return;
  else delete item;
}

void KOListView::showIncidences( const Incidence::List &incidenceList )
{
  clear();

  addIncidences( incidenceList );

  // After new creation of list view no events are selected.
  emit incidenceSelected( 0 );
}

void KOListView::changeIncidenceDisplay(Incidence *incidence, int action)
{
  KOListViewItem *item;
  QDate f = mSelectedDates.first();
  QDate l = mSelectedDates.last();

  QDate date;
  if ( incidence->type() == "Todo" )
    date = static_cast<Todo *>(incidence)->dtDue().date();
  else
    date = incidence->dtStart().date();

  switch(action) {
    case KOGlobals::INCIDENCEADDED: {
      if ( date >= f && date <= l )
        addIncidence( incidence );
      break;
    }
    case KOGlobals::INCIDENCEEDITED: {
      item = getItemForIncidence(incidence);
      if (item) {
        delete item;
        mUidDict.remove( incidence->uid() );
      }
      if ( date >= f && date <= l )
        addIncidence( incidence );
    }
    break;
    case KOGlobals::INCIDENCEDELETED: {
      item = getItemForIncidence(incidence);
      if (item)
        delete item;
      break;
    }
    default:
      kdDebug(5850) << "KOListView::changeIncidenceDisplay(): Illegal action " << action << endl;
  }
}

KOListViewItem *KOListView::getItemForIncidence(Incidence *incidence)
{
  KOListViewItem *item = (KOListViewItem *)mListView->firstChild();
  while (item) {
//    kdDebug(5850) << "Item " << item->text(0) << " found" << endl;
    if (item->data() == incidence) return item;
    item = (KOListViewItem *)item->nextSibling();
  }
  return 0;
}

void KOListView::defaultItemAction(QListViewItem *i)
{
  KOListViewItem *item = static_cast<KOListViewItem *>( i );
  if ( item ) defaultAction( item->data() );
}

void KOListView::popupMenu(QListViewItem *item,const QPoint &,int)
{
  mActiveItem = (KOListViewItem *)item;
  if (mActiveItem) {
    Incidence *incidence = mActiveItem->data();
    // FIXME: For recurring incidences we don't know the date of this
    // occurrence, there's no reference to it at all!
    mPopupMenu->showIncidencePopup( incidence, QDate() );
  }
  else {
    showNewEventPopup();
  }
}

void KOListView::readSettings(KConfig *config)
{
  mListView->restoreLayout(config,"KOListView Layout");
}

void KOListView::writeSettings(KConfig *config)
{
  mListView->saveLayout(config,"KOListView Layout");
}

void KOListView::processSelectionChange()
{
  kdDebug(5850) << "KOListView::processSelectionChange()" << endl;

  KOListViewItem *item =
    static_cast<KOListViewItem *>( mListView->selectedItem() );

  if ( !item ) {
    emit incidenceSelected( 0 );
  } else {
    emit incidenceSelected( item->data() );
  }
}

void KOListView::clearSelection()
{
  mListView->selectAll( false );
}

void KOListView::clear()
{
  mSelectedDates.clear();
  mListView->clear();
  mUidDict.clear();
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.

#include "browser/inspectable_web_contents_impl.h"

#include "browser/browser_client.h"
#include "browser/browser_context.h"
#include "browser/browser_main_parts.h"
#include "browser/inspectable_web_contents_delegate.h"
#include "browser/inspectable_web_contents_view.h"

#include "base/json/json_reader.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_client_host.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"

namespace brightray {

namespace {

const char kChromeUIDevToolsURL[] = "chrome-devtools://devtools/devtools.html?can_dock=true";
const char kDevToolsBoundsPref[] = "brightray.devtools.bounds";

const char kFrontendHostId[] = "id";
const char kFrontendHostMethod[] = "method";
const char kFrontendHostParams[] = "params";

void RectToDictionary(const gfx::Rect& bounds, base::DictionaryValue* dict) {
  dict->SetInteger("x", bounds.x());
  dict->SetInteger("y", bounds.y());
  dict->SetInteger("width", bounds.width());
  dict->SetInteger("height", bounds.height());
}

void DictionaryToRect(const base::DictionaryValue& dict, gfx::Rect* bounds) {
  int x = 0, y = 0, width = 800, height = 600;
  dict.GetInteger("x", &x);
  dict.GetInteger("y", &y);
  dict.GetInteger("width", &width);
  dict.GetInteger("height", &height);
  *bounds = gfx::Rect(x, y, width, height);
}

}  // namespace

// Implemented separately on each platform.
InspectableWebContentsView* CreateInspectableContentsView(
    InspectableWebContentsImpl* inspectable_web_contents_impl);

void InspectableWebContentsImpl::RegisterPrefs(PrefRegistrySimple* registry) {
  auto bounds_dict = make_scoped_ptr(new base::DictionaryValue);
  RectToDictionary(gfx::Rect(0, 0, 800, 600), bounds_dict.get());
  registry->RegisterDictionaryPref(kDevToolsBoundsPref, bounds_dict.release());
}

InspectableWebContentsImpl::InspectableWebContentsImpl(
    content::WebContents* web_contents)
    : web_contents_(web_contents),
      delegate_(nullptr) {
  auto context = static_cast<BrowserContext*>(web_contents_->GetBrowserContext());
  auto bounds_dict = context->prefs()->GetDictionary(kDevToolsBoundsPref);
  if (bounds_dict)
    DictionaryToRect(*bounds_dict, &devtools_bounds_);

  view_.reset(CreateInspectableContentsView(this));
}

InspectableWebContentsImpl::~InspectableWebContentsImpl() {
}

InspectableWebContentsView* InspectableWebContentsImpl::GetView() const {
  return view_.get();
}

content::WebContents* InspectableWebContentsImpl::GetWebContents() const {
  return web_contents_.get();
}

void InspectableWebContentsImpl::ShowDevTools() {
  // Show devtools only after it has done loading, this is to make sure the
  // SetIsDocked is called *BEFORE* ShowDevTools.
  if (!devtools_web_contents_) {
    embedder_message_dispatcher_.reset(
        new DevToolsEmbedderMessageDispatcher(this));

    auto create_params = content::WebContents::CreateParams(
        web_contents_->GetBrowserContext());
    devtools_web_contents_.reset(content::WebContents::Create(create_params));

    Observe(devtools_web_contents_.get());
    devtools_web_contents_->SetDelegate(this);

    agent_host_ = content::DevToolsAgentHost::GetOrCreateFor(
        web_contents_->GetRenderViewHost());
    frontend_host_.reset(
        content::DevToolsClientHost::CreateDevToolsFrontendHost(
            devtools_web_contents_.get(), this));
    content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
        agent_host_, frontend_host_.get());

    GURL devtools_url(kChromeUIDevToolsURL);
    devtools_web_contents_->GetController().LoadURL(
        devtools_url,
        content::Referrer(),
        content::PAGE_TRANSITION_AUTO_TOPLEVEL,
        std::string());
  } else {
    view_->ShowDevTools();
  }
}

void InspectableWebContentsImpl::CloseDevTools() {
  if (devtools_web_contents_) {
    view_->CloseDevTools();
    devtools_web_contents_.reset();
    web_contents_->GetView()->Focus();
  }
}

bool InspectableWebContentsImpl::IsDevToolsViewShowing() {
  return devtools_web_contents_ && view_->IsDevToolsViewShowing();
}

gfx::Rect InspectableWebContentsImpl::GetDevToolsBounds() const {
  return devtools_bounds_;
}

void InspectableWebContentsImpl::SaveDevToolsBounds(const gfx::Rect& bounds) {
  auto context = static_cast<BrowserContext*>(web_contents_->GetBrowserContext());
  base::DictionaryValue bounds_dict;
  RectToDictionary(bounds, &bounds_dict);
  context->prefs()->Set(kDevToolsBoundsPref, bounds_dict);
  devtools_bounds_ = bounds;
}

void InspectableWebContentsImpl::ActivateWindow() {
}

void InspectableWebContentsImpl::CloseWindow() {
  CloseDevTools();
}

void InspectableWebContentsImpl::SetContentsResizingStrategy(
    const gfx::Insets& insets, const gfx::Size& min_size) {
  DevToolsContentsResizingStrategy strategy(insets, min_size);
  if (contents_resizing_strategy_.Equals(strategy))
    return;

  contents_resizing_strategy_.CopyFrom(strategy);
  view_->SetContentsResizingStrategy(contents_resizing_strategy_);
}

void InspectableWebContentsImpl::InspectElementCompleted() {
}

void InspectableWebContentsImpl::MoveWindow(int x, int y) {
}

void InspectableWebContentsImpl::SetIsDocked(bool docked) {
  view_->SetIsDocked(docked);
}

void InspectableWebContentsImpl::OpenInNewTab(const std::string& url) {
}

void InspectableWebContentsImpl::SaveToFile(
    const std::string& url, const std::string& content, bool save_as) {
  if (delegate_)
    delegate_->DevToolsSaveToFile(url, content, save_as);
}

void InspectableWebContentsImpl::AppendToFile(
    const std::string& url, const std::string& content) {
  if (delegate_)
    delegate_->DevToolsAppendToFile(url, content);
}

void InspectableWebContentsImpl::RequestFileSystems() {
    devtools_web_contents()->GetMainFrame()->ExecuteJavaScript(
        base::ASCIIToUTF16("InspectorFrontendAPI.fileSystemsLoaded([])"));
}

void InspectableWebContentsImpl::AddFileSystem() {
}

void InspectableWebContentsImpl::RemoveFileSystem(
    const std::string& file_system_path) {
}

void InspectableWebContentsImpl::UpgradeDraggedFileSystemPermissions(
    const std::string& file_system_url) {
}

void InspectableWebContentsImpl::IndexPath(
    int request_id, const std::string& file_system_path) {
}

void InspectableWebContentsImpl::StopIndexing(int request_id) {
}

void InspectableWebContentsImpl::SearchInPath(
    int request_id,
    const std::string& file_system_path,
    const std::string& query) {
}

void InspectableWebContentsImpl::ZoomIn() {
}

void InspectableWebContentsImpl::ZoomOut() {
}

void InspectableWebContentsImpl::ResetZoom() {
}

void InspectableWebContentsImpl::DispatchOnEmbedder(
    const std::string& message) {
  std::string method;
  base::ListValue empty_params;
  base::ListValue* params = &empty_params;

  base::DictionaryValue* dict = NULL;
  scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message));
  if (!parsed_message ||
      !parsed_message->GetAsDictionary(&dict) ||
      !dict->GetString(kFrontendHostMethod, &method) ||
      (dict->HasKey(kFrontendHostParams) &&
          !dict->GetList(kFrontendHostParams, &params))) {
    LOG(ERROR) << "Invalid message was sent to embedder: " << message;
    return;
  }

  int id = 0;
  dict->GetInteger(kFrontendHostId, &id);

  std::string error = embedder_message_dispatcher_->Dispatch(method, params);
  if (id) {
    std::string ack = base::StringPrintf(
        "InspectorFrontendAPI.embedderMessageAck(%d, \"%s\");", id, error.c_str());
    devtools_web_contents()->GetMainFrame()->ExecuteJavaScript(base::UTF8ToUTF16(ack));
  }
}

void InspectableWebContentsImpl::InspectedContentsClosing() {
}

void InspectableWebContentsImpl::AboutToNavigateRenderView(
    content::RenderViewHost* render_view_host) {
  content::DevToolsClientHost::SetupDevToolsFrontendClient(
      web_contents()->GetRenderViewHost());
}

void InspectableWebContentsImpl::DidFinishLoad(int64 frame_id,
                                               const GURL& validated_url,
                                               bool is_main_frame,
                                               content::RenderViewHost*) {
  if (!is_main_frame)
    return;

  view_->ShowDevTools();
}

void InspectableWebContentsImpl::WebContentsDestroyed(content::WebContents*) {
  content::DevToolsManager::GetInstance()->ClientHostClosing(
      frontend_host_.get());
  Observe(nullptr);
  agent_host_ = nullptr;
  frontend_host_.reset();
}

void InspectableWebContentsImpl::HandleKeyboardEvent(
    content::WebContents* source,
    const content::NativeWebKeyboardEvent& event) {
  auto delegate = web_contents_->GetDelegate();
  if (delegate)
    delegate->HandleKeyboardEvent(source, event);
}

}  // namespace brightray
<commit_msg>Separate the message parsing into a new function.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.

#include "browser/inspectable_web_contents_impl.h"

#include "browser/browser_client.h"
#include "browser/browser_context.h"
#include "browser/browser_main_parts.h"
#include "browser/inspectable_web_contents_delegate.h"
#include "browser/inspectable_web_contents_view.h"

#include "base/json/json_reader.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_client_host.h"
#include "content/public/browser/devtools_http_handler.h"
#include "content/public/browser/devtools_manager.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"

namespace brightray {

namespace {

const char kChromeUIDevToolsURL[] = "chrome-devtools://devtools/devtools.html?can_dock=true";
const char kDevToolsBoundsPref[] = "brightray.devtools.bounds";

const char kFrontendHostId[] = "id";
const char kFrontendHostMethod[] = "method";
const char kFrontendHostParams[] = "params";

void RectToDictionary(const gfx::Rect& bounds, base::DictionaryValue* dict) {
  dict->SetInteger("x", bounds.x());
  dict->SetInteger("y", bounds.y());
  dict->SetInteger("width", bounds.width());
  dict->SetInteger("height", bounds.height());
}

void DictionaryToRect(const base::DictionaryValue& dict, gfx::Rect* bounds) {
  int x = 0, y = 0, width = 800, height = 600;
  dict.GetInteger("x", &x);
  dict.GetInteger("y", &y);
  dict.GetInteger("width", &width);
  dict.GetInteger("height", &height);
  *bounds = gfx::Rect(x, y, width, height);
}

bool ParseMessage(const std::string& message,
                  std::string* method,
                  base::ListValue* params,
                  int* id) {
  scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message));
  if (!parsed_message)
    return false;

  base::DictionaryValue* dict = NULL;
  if (!parsed_message->GetAsDictionary(&dict))
    return false;
  if (!dict->GetString(kFrontendHostMethod, method))
    return false;

  // "params" is optional.
  if (dict->HasKey(kFrontendHostParams)) {
    base::ListValue* internal_params;
    if (dict->GetList(kFrontendHostParams, &internal_params))
      params->Swap(internal_params);
    else
      return false;
  }

  *id = 0;
  dict->GetInteger(kFrontendHostId, id);
  return true;
}

}  // namespace

// Implemented separately on each platform.
InspectableWebContentsView* CreateInspectableContentsView(
    InspectableWebContentsImpl* inspectable_web_contents_impl);

void InspectableWebContentsImpl::RegisterPrefs(PrefRegistrySimple* registry) {
  auto bounds_dict = make_scoped_ptr(new base::DictionaryValue);
  RectToDictionary(gfx::Rect(0, 0, 800, 600), bounds_dict.get());
  registry->RegisterDictionaryPref(kDevToolsBoundsPref, bounds_dict.release());
}

InspectableWebContentsImpl::InspectableWebContentsImpl(
    content::WebContents* web_contents)
    : web_contents_(web_contents),
      delegate_(nullptr) {
  auto context = static_cast<BrowserContext*>(web_contents_->GetBrowserContext());
  auto bounds_dict = context->prefs()->GetDictionary(kDevToolsBoundsPref);
  if (bounds_dict)
    DictionaryToRect(*bounds_dict, &devtools_bounds_);

  view_.reset(CreateInspectableContentsView(this));
}

InspectableWebContentsImpl::~InspectableWebContentsImpl() {
}

InspectableWebContentsView* InspectableWebContentsImpl::GetView() const {
  return view_.get();
}

content::WebContents* InspectableWebContentsImpl::GetWebContents() const {
  return web_contents_.get();
}

void InspectableWebContentsImpl::ShowDevTools() {
  // Show devtools only after it has done loading, this is to make sure the
  // SetIsDocked is called *BEFORE* ShowDevTools.
  if (!devtools_web_contents_) {
    embedder_message_dispatcher_.reset(
        new DevToolsEmbedderMessageDispatcher(this));

    auto create_params = content::WebContents::CreateParams(
        web_contents_->GetBrowserContext());
    devtools_web_contents_.reset(content::WebContents::Create(create_params));

    Observe(devtools_web_contents_.get());
    devtools_web_contents_->SetDelegate(this);

    agent_host_ = content::DevToolsAgentHost::GetOrCreateFor(
        web_contents_->GetRenderViewHost());
    frontend_host_.reset(
        content::DevToolsClientHost::CreateDevToolsFrontendHost(
            devtools_web_contents_.get(), this));
    content::DevToolsManager::GetInstance()->RegisterDevToolsClientHostFor(
        agent_host_, frontend_host_.get());

    GURL devtools_url(kChromeUIDevToolsURL);
    devtools_web_contents_->GetController().LoadURL(
        devtools_url,
        content::Referrer(),
        content::PAGE_TRANSITION_AUTO_TOPLEVEL,
        std::string());
  } else {
    view_->ShowDevTools();
  }
}

void InspectableWebContentsImpl::CloseDevTools() {
  if (devtools_web_contents_) {
    view_->CloseDevTools();
    devtools_web_contents_.reset();
    web_contents_->GetView()->Focus();
  }
}

bool InspectableWebContentsImpl::IsDevToolsViewShowing() {
  return devtools_web_contents_ && view_->IsDevToolsViewShowing();
}

gfx::Rect InspectableWebContentsImpl::GetDevToolsBounds() const {
  return devtools_bounds_;
}

void InspectableWebContentsImpl::SaveDevToolsBounds(const gfx::Rect& bounds) {
  auto context = static_cast<BrowserContext*>(web_contents_->GetBrowserContext());
  base::DictionaryValue bounds_dict;
  RectToDictionary(bounds, &bounds_dict);
  context->prefs()->Set(kDevToolsBoundsPref, bounds_dict);
  devtools_bounds_ = bounds;
}

void InspectableWebContentsImpl::ActivateWindow() {
}

void InspectableWebContentsImpl::CloseWindow() {
  CloseDevTools();
}

void InspectableWebContentsImpl::SetContentsResizingStrategy(
    const gfx::Insets& insets, const gfx::Size& min_size) {
  DevToolsContentsResizingStrategy strategy(insets, min_size);
  if (contents_resizing_strategy_.Equals(strategy))
    return;

  contents_resizing_strategy_.CopyFrom(strategy);
  view_->SetContentsResizingStrategy(contents_resizing_strategy_);
}

void InspectableWebContentsImpl::InspectElementCompleted() {
}

void InspectableWebContentsImpl::MoveWindow(int x, int y) {
}

void InspectableWebContentsImpl::SetIsDocked(bool docked) {
  view_->SetIsDocked(docked);
}

void InspectableWebContentsImpl::OpenInNewTab(const std::string& url) {
}

void InspectableWebContentsImpl::SaveToFile(
    const std::string& url, const std::string& content, bool save_as) {
  if (delegate_)
    delegate_->DevToolsSaveToFile(url, content, save_as);
}

void InspectableWebContentsImpl::AppendToFile(
    const std::string& url, const std::string& content) {
  if (delegate_)
    delegate_->DevToolsAppendToFile(url, content);
}

void InspectableWebContentsImpl::RequestFileSystems() {
    devtools_web_contents()->GetMainFrame()->ExecuteJavaScript(
        base::ASCIIToUTF16("InspectorFrontendAPI.fileSystemsLoaded([])"));
}

void InspectableWebContentsImpl::AddFileSystem() {
}

void InspectableWebContentsImpl::RemoveFileSystem(
    const std::string& file_system_path) {
}

void InspectableWebContentsImpl::UpgradeDraggedFileSystemPermissions(
    const std::string& file_system_url) {
}

void InspectableWebContentsImpl::IndexPath(
    int request_id, const std::string& file_system_path) {
}

void InspectableWebContentsImpl::StopIndexing(int request_id) {
}

void InspectableWebContentsImpl::SearchInPath(
    int request_id,
    const std::string& file_system_path,
    const std::string& query) {
}

void InspectableWebContentsImpl::ZoomIn() {
}

void InspectableWebContentsImpl::ZoomOut() {
}

void InspectableWebContentsImpl::ResetZoom() {
}

void InspectableWebContentsImpl::DispatchOnEmbedder(
    const std::string& message) {
  std::string method;
  base::ListValue params;
  int id;
  if (!ParseMessage(message, &method, &params, &id)) {
    LOG(ERROR) << "Invalid message was sent to embedder: " << message;
    return;
  }

  std::string error = embedder_message_dispatcher_->Dispatch(method, &params);
  if (id) {
    std::string ack = base::StringPrintf(
        "InspectorFrontendAPI.embedderMessageAck(%d, \"%s\");", id, error.c_str());
    devtools_web_contents()->GetMainFrame()->ExecuteJavaScript(base::UTF8ToUTF16(ack));
  }
}

void InspectableWebContentsImpl::InspectedContentsClosing() {
}

void InspectableWebContentsImpl::AboutToNavigateRenderView(
    content::RenderViewHost* render_view_host) {
  content::DevToolsClientHost::SetupDevToolsFrontendClient(
      web_contents()->GetRenderViewHost());
}

void InspectableWebContentsImpl::DidFinishLoad(int64 frame_id,
                                               const GURL& validated_url,
                                               bool is_main_frame,
                                               content::RenderViewHost*) {
  if (!is_main_frame)
    return;

  view_->ShowDevTools();
}

void InspectableWebContentsImpl::WebContentsDestroyed(content::WebContents*) {
  content::DevToolsManager::GetInstance()->ClientHostClosing(
      frontend_host_.get());
  Observe(nullptr);
  agent_host_ = nullptr;
  frontend_host_.reset();
}

void InspectableWebContentsImpl::HandleKeyboardEvent(
    content::WebContents* source,
    const content::NativeWebKeyboardEvent& event) {
  auto delegate = web_contents_->GetDelegate();
  if (delegate)
    delegate->HandleKeyboardEvent(source, event);
}

}  // namespace brightray
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#if ENABLE(WEB_AUDIO)

#include "core/platform/audio/ReverbConvolverStage.h"

#include "core/platform/audio/ReverbAccumulationBuffer.h"
#include "core/platform/audio/ReverbConvolver.h"
#include "core/platform/audio/ReverbInputBuffer.h"
#include "core/platform/audio/VectorMath.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"

namespace WebCore {

using namespace VectorMath;

ReverbConvolverStage::ReverbConvolverStage(const float* impulseResponse, size_t, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength,
                                           size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer* accumulationBuffer, bool directMode)
    : m_accumulationBuffer(accumulationBuffer)
    , m_accumulationReadIndex(0)
    , m_inputReadIndex(0)
    , m_directMode(directMode)
{
    ASSERT(impulseResponse);
    ASSERT(accumulationBuffer);

    if (!m_directMode) {
        m_fftKernel = adoptPtr(new FFTFrame(fftSize));
        m_fftKernel->doPaddedFFT(impulseResponse + stageOffset, stageLength);
        m_fftConvolver = adoptPtr(new FFTConvolver(fftSize));
    } else {
        m_directKernel = adoptPtr(new AudioFloatArray(fftSize / 2));
        m_directKernel->copyToRange(impulseResponse + stageOffset, 0, fftSize / 2);
        m_directConvolver = adoptPtr(new DirectConvolver(renderSliceSize));
    }
    m_temporaryBuffer.allocate(renderSliceSize);

    // The convolution stage at offset stageOffset needs to have a corresponding delay to cancel out the offset.
    size_t totalDelay = stageOffset + reverbTotalLatency;

    // But, the FFT convolution itself incurs fftSize / 2 latency, so subtract this out...
    size_t halfSize = fftSize / 2;
    if (!m_directMode) {
        ASSERT(totalDelay >= halfSize);
        if (totalDelay >= halfSize)
            totalDelay -= halfSize;
    }

    // We divide up the total delay, into pre and post delay sections so that we can schedule at exactly the moment when the FFT will happen.
    // This is coordinated with the other stages, so they don't all do their FFTs at the same time...
    int maxPreDelayLength = std::min(halfSize, totalDelay);
    m_preDelayLength = totalDelay > 0 ? renderPhase % maxPreDelayLength : 0;
    if (m_preDelayLength > totalDelay)
        m_preDelayLength = 0;

    m_postDelayLength = totalDelay - m_preDelayLength;
    m_preReadWriteIndex = 0;
    m_framesProcessed = 0; // total frames processed so far

    size_t delayBufferSize = m_preDelayLength < fftSize ? fftSize : m_preDelayLength;
    delayBufferSize = delayBufferSize < renderSliceSize ? renderSliceSize : delayBufferSize;
    m_preDelayBuffer.allocate(delayBufferSize);
}

void ReverbConvolverStage::processInBackground(ReverbConvolver* convolver, size_t framesToProcess)
{
    ReverbInputBuffer* inputBuffer = convolver->inputBuffer();
    float* source = inputBuffer->directReadFrom(&m_inputReadIndex, framesToProcess);
    process(source, framesToProcess);
}

void ReverbConvolverStage::process(const float* source, size_t framesToProcess)
{
    ASSERT(source);
    if (!source)
        return;

    // Deal with pre-delay stream : note special handling of zero delay.

    const float* preDelayedSource;
    float* preDelayedDestination;
    float* temporaryBuffer;
    bool isTemporaryBufferSafe = false;
    if (m_preDelayLength > 0) {
        // Handles both the read case (call to process() ) and the write case (memcpy() )
        bool isPreDelaySafe = m_preReadWriteIndex + framesToProcess <= m_preDelayBuffer.size();
        ASSERT(isPreDelaySafe);
        if (!isPreDelaySafe)
            return;

        isTemporaryBufferSafe = framesToProcess <= m_temporaryBuffer.size();

        preDelayedDestination = m_preDelayBuffer.data() + m_preReadWriteIndex;
        preDelayedSource = preDelayedDestination;
        temporaryBuffer = m_temporaryBuffer.data();
    } else {
        // Zero delay
        preDelayedDestination = 0;
        preDelayedSource = source;
        temporaryBuffer = m_preDelayBuffer.data();

        isTemporaryBufferSafe = framesToProcess <= m_preDelayBuffer.size();
    }

    ASSERT(isTemporaryBufferSafe);
    if (!isTemporaryBufferSafe)
        return;

    if (m_framesProcessed < m_preDelayLength) {
        // For the first m_preDelayLength frames don't process the convolver, instead simply buffer in the pre-delay.
        // But while buffering the pre-delay, we still need to update our index.
        m_accumulationBuffer->updateReadIndex(&m_accumulationReadIndex, framesToProcess);
    } else {
        // Now, run the convolution (into the delay buffer).
        // An expensive FFT will happen every fftSize / 2 frames.
        // We process in-place here...
        if (!m_directMode)
            m_fftConvolver->process(m_fftKernel.get(), preDelayedSource, temporaryBuffer, framesToProcess);
        else
            m_directConvolver->process(m_directKernel.get(), preDelayedSource, temporaryBuffer, framesToProcess);

        // Now accumulate into reverb's accumulation buffer.
        m_accumulationBuffer->accumulate(temporaryBuffer, framesToProcess, &m_accumulationReadIndex, m_postDelayLength);
    }

    // Finally copy input to pre-delay.
    if (m_preDelayLength > 0) {
        memcpy(preDelayedDestination, source, sizeof(float) * framesToProcess);
        m_preReadWriteIndex += framesToProcess;

        ASSERT(m_preReadWriteIndex <= m_preDelayLength);
        if (m_preReadWriteIndex >= m_preDelayLength)
            m_preReadWriteIndex = 0;
    }

    m_framesProcessed += framesToProcess;
}

void ReverbConvolverStage::reset()
{
    if (!m_directMode)
        m_fftConvolver->reset();
    else
        m_directConvolver->reset();
    m_preDelayBuffer.zero();
    m_accumulationReadIndex = 0;
    m_inputReadIndex = 0;
    m_framesProcessed = 0;
}

} // namespace WebCore

#endif // ENABLE(WEB_AUDIO)
<commit_msg>Don't read past the end of the impulseResponse array<commit_after>/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#if ENABLE(WEB_AUDIO)

#include "core/platform/audio/ReverbConvolverStage.h"

#include "core/platform/audio/ReverbAccumulationBuffer.h"
#include "core/platform/audio/ReverbConvolver.h"
#include "core/platform/audio/ReverbInputBuffer.h"
#include "core/platform/audio/VectorMath.h"
#include "wtf/OwnPtr.h"
#include "wtf/PassOwnPtr.h"

namespace WebCore {

using namespace VectorMath;

ReverbConvolverStage::ReverbConvolverStage(const float* impulseResponse, size_t, size_t reverbTotalLatency, size_t stageOffset, size_t stageLength,
                                           size_t fftSize, size_t renderPhase, size_t renderSliceSize, ReverbAccumulationBuffer* accumulationBuffer, bool directMode)
    : m_accumulationBuffer(accumulationBuffer)
    , m_accumulationReadIndex(0)
    , m_inputReadIndex(0)
    , m_directMode(directMode)
{
    ASSERT(impulseResponse);
    ASSERT(accumulationBuffer);

    if (!m_directMode) {
        m_fftKernel = adoptPtr(new FFTFrame(fftSize));
        m_fftKernel->doPaddedFFT(impulseResponse + stageOffset, stageLength);
        m_fftConvolver = adoptPtr(new FFTConvolver(fftSize));
    } else {
        ASSERT(!stageOffset);
        ASSERT(stageLength <= fftSize / 2);

        m_directKernel = adoptPtr(new AudioFloatArray(fftSize / 2));
        m_directKernel->copyToRange(impulseResponse, 0, stageLength);
        m_directConvolver = adoptPtr(new DirectConvolver(renderSliceSize));
    }
    m_temporaryBuffer.allocate(renderSliceSize);

    // The convolution stage at offset stageOffset needs to have a corresponding delay to cancel out the offset.
    size_t totalDelay = stageOffset + reverbTotalLatency;

    // But, the FFT convolution itself incurs fftSize / 2 latency, so subtract this out...
    size_t halfSize = fftSize / 2;
    if (!m_directMode) {
        ASSERT(totalDelay >= halfSize);
        if (totalDelay >= halfSize)
            totalDelay -= halfSize;
    }

    // We divide up the total delay, into pre and post delay sections so that we can schedule at exactly the moment when the FFT will happen.
    // This is coordinated with the other stages, so they don't all do their FFTs at the same time...
    int maxPreDelayLength = std::min(halfSize, totalDelay);
    m_preDelayLength = totalDelay > 0 ? renderPhase % maxPreDelayLength : 0;
    if (m_preDelayLength > totalDelay)
        m_preDelayLength = 0;

    m_postDelayLength = totalDelay - m_preDelayLength;
    m_preReadWriteIndex = 0;
    m_framesProcessed = 0; // total frames processed so far

    size_t delayBufferSize = m_preDelayLength < fftSize ? fftSize : m_preDelayLength;
    delayBufferSize = delayBufferSize < renderSliceSize ? renderSliceSize : delayBufferSize;
    m_preDelayBuffer.allocate(delayBufferSize);
}

void ReverbConvolverStage::processInBackground(ReverbConvolver* convolver, size_t framesToProcess)
{
    ReverbInputBuffer* inputBuffer = convolver->inputBuffer();
    float* source = inputBuffer->directReadFrom(&m_inputReadIndex, framesToProcess);
    process(source, framesToProcess);
}

void ReverbConvolverStage::process(const float* source, size_t framesToProcess)
{
    ASSERT(source);
    if (!source)
        return;

    // Deal with pre-delay stream : note special handling of zero delay.

    const float* preDelayedSource;
    float* preDelayedDestination;
    float* temporaryBuffer;
    bool isTemporaryBufferSafe = false;
    if (m_preDelayLength > 0) {
        // Handles both the read case (call to process() ) and the write case (memcpy() )
        bool isPreDelaySafe = m_preReadWriteIndex + framesToProcess <= m_preDelayBuffer.size();
        ASSERT(isPreDelaySafe);
        if (!isPreDelaySafe)
            return;

        isTemporaryBufferSafe = framesToProcess <= m_temporaryBuffer.size();

        preDelayedDestination = m_preDelayBuffer.data() + m_preReadWriteIndex;
        preDelayedSource = preDelayedDestination;
        temporaryBuffer = m_temporaryBuffer.data();
    } else {
        // Zero delay
        preDelayedDestination = 0;
        preDelayedSource = source;
        temporaryBuffer = m_preDelayBuffer.data();

        isTemporaryBufferSafe = framesToProcess <= m_preDelayBuffer.size();
    }

    ASSERT(isTemporaryBufferSafe);
    if (!isTemporaryBufferSafe)
        return;

    if (m_framesProcessed < m_preDelayLength) {
        // For the first m_preDelayLength frames don't process the convolver, instead simply buffer in the pre-delay.
        // But while buffering the pre-delay, we still need to update our index.
        m_accumulationBuffer->updateReadIndex(&m_accumulationReadIndex, framesToProcess);
    } else {
        // Now, run the convolution (into the delay buffer).
        // An expensive FFT will happen every fftSize / 2 frames.
        // We process in-place here...
        if (!m_directMode)
            m_fftConvolver->process(m_fftKernel.get(), preDelayedSource, temporaryBuffer, framesToProcess);
        else
            m_directConvolver->process(m_directKernel.get(), preDelayedSource, temporaryBuffer, framesToProcess);

        // Now accumulate into reverb's accumulation buffer.
        m_accumulationBuffer->accumulate(temporaryBuffer, framesToProcess, &m_accumulationReadIndex, m_postDelayLength);
    }

    // Finally copy input to pre-delay.
    if (m_preDelayLength > 0) {
        memcpy(preDelayedDestination, source, sizeof(float) * framesToProcess);
        m_preReadWriteIndex += framesToProcess;

        ASSERT(m_preReadWriteIndex <= m_preDelayLength);
        if (m_preReadWriteIndex >= m_preDelayLength)
            m_preReadWriteIndex = 0;
    }

    m_framesProcessed += framesToProcess;
}

void ReverbConvolverStage::reset()
{
    if (!m_directMode)
        m_fftConvolver->reset();
    else
        m_directConvolver->reset();
    m_preDelayBuffer.zero();
    m_accumulationReadIndex = 0;
    m_inputReadIndex = 0;
    m_framesProcessed = 0;
}

} // namespace WebCore

#endif // ENABLE(WEB_AUDIO)
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Language:  C++

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
// This file has been generated by BuildHeaderTest.tcl
// Test to include each header file for Insight

#include "itkAnisotropicFourthOrderLevelSetImageFilter.txx"
#include "itkAntiAliasBinaryImageFilter.txx"
#include "itkAutomaticTopologyMeshSource.txx"
#include "itkBalloonForceFilter.txx"
#include "itkBayesianClassifierImageFilter.txx"
#include "itkBayesianClassifierInitializationImageFilter.txx"
#include "itkBinaryMask3DMeshSource.txx"
#include "itkBinaryMedialNodeMetric.txx"
#include "itkBinaryMinMaxCurvatureFlowFunction.txx"
#include "itkBinaryMinMaxCurvatureFlowImageFilter.txx"
#include "itkBinaryPruningImageFilter.txx"
#include "itkBinaryThinningImageFilter.txx"
#include "itkBioCell.txx"
#include "itkBioCellBase.h"
#include "itkBioCellularAggregate.txx"
#include "itkBioCellularAggregateBase.h"
#include "itkBioGene.h"
#include "itkBioGeneNetwork.h"
#include "itkBioGenome.h"
#include "itkCannySegmentationLevelSetFunction.txx"
#include "itkCannySegmentationLevelSetImageFilter.txx"
#include "itkClassifierBase.txx"
#include "itkCollidingFrontsImageFilter.txx"
#include "itkCompareHistogramImageToImageMetric.txx"
#include "itkConnectedRegionsMeshFilter.txx"
#include "itkCoreAtomImageToUnaryCorrespondenceMatrixProcess.txx"
#include "itkCorrelationCoefficientHistogramImageToImageMetric.txx"
#include "itkCurvatureFlowFunction.txx"
#include "itkCurvatureFlowImageFilter.txx"
#include "itkCurvatureRegistrationFilter.txx"
#include "itkCurvesLevelSetFunction.txx"
#include "itkCurvesLevelSetImageFilter.txx"
#include "itkDeformableMesh3DFilter.txx"
#include "itkDeformableSimplexMesh3DBalloonForceFilter.txx"
#include "itkDeformableSimplexMesh3DFilter.txx"
#include "itkDeformableSimplexMesh3DGradientConstraintForceFilter.txx"
#include "itkDemonsRegistrationFilter.txx"
#include "itkDemonsRegistrationFunction.txx"
#include "itkEuclideanDistancePointMetric.txx"
#include "itkExtensionVelocitiesImageFilter.txx"
#include "itkFEMFiniteDifferenceFunctionLoad.txx"
#include "itkFEMRegistrationFilter.txx"
#if defined(USE_FFTWF) || defined(USE_FFTWD)
#include "itkFFTComplexConjugateToRealImageFilter.txx"
#include "itkFFTRealToComplexConjugateImageFilter.txx"
#include "itkFFTWCommon.h"
#include "itkFFTWComplexConjugateToRealImageFilter.txx"
#include "itkFFTWRealToComplexConjugateImageFilter.txx"
#endif
#include "itkFastChamferDistanceImageFilter.txx"
#include "itkFastMarchingExtensionImageFilter.txx"
#include "itkFastMarchingImageFilter.txx"
#include "itkFastMarchingUpwindGradientImageFilter.txx"
#include "itkFastSymmetricForcesDemonsRegistrationFunction.txx"
#include "itkGeodesicActiveContourLevelSetFunction.txx"
#include "itkGeodesicActiveContourLevelSetImageFilter.txx"
#include "itkGeodesicActiveContourShapePriorLevelSetFunction.txx"
#include "itkGeodesicActiveContourShapePriorLevelSetImageFilter.txx"
#include "itkGradientDifferenceImageToImageMetric.txx"
#include "itkGradientVectorFlowImageFilter.txx"
#include "itkHistogramAlgorithmBase.txx"
#include "itkHistogramImageToImageMetric.txx"
#include "itkHistogramMatchingImageFilter.txx"
#include "itkImageClassifierBase.txx"
#include "itkImageGaussianModelEstimator.txx"
#include "itkImageKmeansModelEstimator.txx"
#include "itkImageModelEstimatorBase.txx"
#include "itkImageMomentsCalculator.txx"
#include "itkImagePCADecompositionCalculator.txx"
#include "itkImagePCAShapeModelEstimator.txx"
#include "itkImageRegistrationMethod.txx"
#include "itkImageShapeModelEstimatorBase.txx"
#include "itkImageToImageMetric.txx"
#include "itkImageToSpatialObjectMetric.txx"
#include "itkImageToSpatialObjectRegistrationMethod.txx"
#include "itkIsoContourDistanceImageFilter.txx"
#include "itkIsolatedWatershedImageFilter.txx"
#include "itkIsotropicFourthOrderLevelSetImageFilter.txx"
#include "itkKLMRegionGrowImageFilter.txx"
#include "itkKalmanLinearEstimator.h"
#include "itkKappaStatisticImageToImageMetric.txx"
#include "itkKullbackLeiblerCompareHistogramImageToImageMetric.txx"
#include "itkLabelVotingImageFilter.txx"
#include "itkLaplacianSegmentationLevelSetFunction.txx"
#include "itkLaplacianSegmentationLevelSetImageFilter.txx"
#include "itkLevelSetMotionRegistrationFilter.txx"
#include "itkLevelSetMotionRegistrationFunction.txx"
#include "itkLevelSetNeighborhoodExtractor.txx"
#include "itkLevelSetVelocityNeighborhoodExtractor.txx"
#include "itkMIRegistrationFunction.txx"
#include "itkMRASlabIdentifier.txx"
#include "itkMRFImageFilter.txx"
#include "itkMRIBiasFieldCorrectionFilter.txx"
#include "itkMatchCardinalityImageToImageMetric.txx"
#include "itkMattesMutualInformationImageToImageMetric.txx"
#include "itkMeanReciprocalSquareDifferenceImageToImageMetric.txx"
#include "itkMeanReciprocalSquareDifferencePointSetToImageMetric.txx"
#include "itkMeanSquareRegistrationFunction.txx"
#include "itkMeanSquaresHistogramImageToImageMetric.txx"
#include "itkMeanSquaresImageToImageMetric.txx"
#include "itkMeanSquaresPointSetToImageMetric.txx"
#include "itkMedialNodePairCorrespondenceProcess.txx"
#include "itkMedialNodeTripletCorrespondenceProcess.txx"
#include "itkMinMaxCurvatureFlowFunction.txx"
#include "itkMinMaxCurvatureFlowImageFilter.txx"
#include "itkMultiResolutionImageRegistrationMethod.txx"
#include "itkMultiResolutionPDEDeformableRegistration.txx"
#include "itkMultiResolutionPyramidImageFilter.txx"
#include "itkMutualInformationHistogramImageToImageMetric.txx"
#include "itkMutualInformationImageToImageMetric.txx"
#include "itkNCCRegistrationFunction.txx"
#include "itkNarrowBandCurvesLevelSetImageFilter.txx"
#include "itkNarrowBandLevelSetImageFilter.txx"
#include "itkNarrowBandThresholdSegmentationLevelSetImageFilter.txx"
#include "itkNormalizedCorrelationImageToImageMetric.txx"
#include "itkNormalizedCorrelationPointSetToImageMetric.txx"
#include "itkNormalizedMutualInformationHistogramImageToImageMetric.txx"
#include "itkOrthogonalSwath2DPathFilter.txx"
#include "itkOtsuMultipleThresholdsCalculator.txx"
#include "itkOtsuMultipleThresholdsImageFilter.txx"
#include "itkOtsuThresholdImageCalculator.txx"
#include "itkOtsuThresholdImageFilter.txx"
#include "itkPDEDeformableRegistrationFilter.txx"
#include "itkPDEDeformableRegistrationFunction.h"
#include "itkPointSetToImageMetric.txx"
#include "itkPointSetToImageRegistrationMethod.txx"
#include "itkPointSetToPointSetMetric.txx"
#include "itkPointSetToPointSetRegistrationMethod.txx"
#include "itkPointSetToSpatialObjectDemonsRegistration.txx"
#include "itkRGBGibbsPriorFilter.txx"
#include "itkRayCastInterpolateImageFunction.txx"
#include "itkRecursiveMultiResolutionPyramidImageFilter.txx"
#include "itkRegionGrowImageFilter.txx"
#include "itkRegularSphereMeshSource.txx"
#include "itkReinitializeLevelSetImageFilter.txx"
#include "itkSCSLComplexConjugateToRealImageFilter.txx"
#include "itkSCSLRealToComplexConjugateImageFilter.txx"
#include "itkSTAPLEImageFilter.txx"
#include "itkScalarImageKmeansImageFilter.txx"
#include "itkSegmentationLevelSetImageFilter.txx"
#include "itkShapeDetectionLevelSetFunction.txx"
#include "itkShapeDetectionLevelSetImageFilter.txx"
#include "itkShapePriorMAPCostFunction.txx"
#include "itkShapePriorMAPCostFunctionBase.txx"
#include "itkShapePriorSegmentationLevelSetFunction.txx"
#include "itkShapePriorSegmentationLevelSetImageFilter.txx"
#include "itkSimplexMeshVolumeCalculator.txx"
#include "itkSphereMeshSource.txx"
#include "itkStructHashFunction.h"
#include "itkSymmetricForcesDemonsRegistrationFilter.txx"
#include "itkSymmetricForcesDemonsRegistrationFunction.txx"
#include "itkThresholdMaximumConnectedComponentsImageFilter.txx"
#include "itkThresholdSegmentationLevelSetFunction.txx"
#include "itkThresholdSegmentationLevelSetImageFilter.txx"
#include "itkUnaryMedialNodeMetric.txx"
#include "itkUnsharpMaskLevelSetImageFilter.txx"
#include "itkVectorThresholdSegmentationLevelSetFunction.txx"
#include "itkVectorThresholdSegmentationLevelSetImageFilter.txx"
#include "itkVnlFFTComplexConjugateToRealImageFilter.txx"
#include "itkVnlFFTRealToComplexConjugateImageFilter.txx"
#include "itkVoronoiDiagram2D.txx"
#include "itkVoronoiDiagram2DGenerator.txx"
#include "itkVoronoiPartitioningImageFilter.txx"
#include "itkVoronoiSegmentationImageFilter.txx"
#include "itkVoronoiSegmentationImageFilterBase.txx"
#include "itkVoronoiSegmentationRGBImageFilter.txx"
#include "itkWatershedBoundary.txx"
#include "itkWatershedBoundaryResolver.txx"
#include "itkWatershedEquivalenceRelabeler.txx"
#include "itkWatershedImageFilter.txx"
#include "itkWatershedMiniPipelineProgressCommand.h"
#include "itkWatershedRelabeler.txx"
#include "itkWatershedSegmentTable.txx"
#include "itkWatershedSegmentTree.txx"
#include "itkWatershedSegmentTreeGenerator.txx"
#include "itkWatershedSegmenter.txx"
#include "vnl_fft_3d.h"

int main ( int , char*  )
{

  return EXIT_SUCCESS;
}

<commit_msg>COMP: Fixing signature of the main() method.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Language:  C++

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include <iostream>
// This file has been generated by BuildHeaderTest.tcl
// Test to include each header file for Insight

#include "itkAnisotropicFourthOrderLevelSetImageFilter.txx"
#include "itkAntiAliasBinaryImageFilter.txx"
#include "itkAutomaticTopologyMeshSource.txx"
#include "itkBalloonForceFilter.txx"
#include "itkBayesianClassifierImageFilter.txx"
#include "itkBayesianClassifierInitializationImageFilter.txx"
#include "itkBinaryMask3DMeshSource.txx"
#include "itkBinaryMedialNodeMetric.txx"
#include "itkBinaryMinMaxCurvatureFlowFunction.txx"
#include "itkBinaryMinMaxCurvatureFlowImageFilter.txx"
#include "itkBinaryPruningImageFilter.txx"
#include "itkBinaryThinningImageFilter.txx"
#include "itkBioCell.txx"
#include "itkBioCellBase.h"
#include "itkBioCellularAggregate.txx"
#include "itkBioCellularAggregateBase.h"
#include "itkBioGene.h"
#include "itkBioGeneNetwork.h"
#include "itkBioGenome.h"
#include "itkCannySegmentationLevelSetFunction.txx"
#include "itkCannySegmentationLevelSetImageFilter.txx"
#include "itkClassifierBase.txx"
#include "itkCollidingFrontsImageFilter.txx"
#include "itkCompareHistogramImageToImageMetric.txx"
#include "itkConnectedRegionsMeshFilter.txx"
#include "itkCoreAtomImageToUnaryCorrespondenceMatrixProcess.txx"
#include "itkCorrelationCoefficientHistogramImageToImageMetric.txx"
#include "itkCurvatureFlowFunction.txx"
#include "itkCurvatureFlowImageFilter.txx"
#include "itkCurvatureRegistrationFilter.txx"
#include "itkCurvesLevelSetFunction.txx"
#include "itkCurvesLevelSetImageFilter.txx"
#include "itkDeformableMesh3DFilter.txx"
#include "itkDeformableSimplexMesh3DBalloonForceFilter.txx"
#include "itkDeformableSimplexMesh3DFilter.txx"
#include "itkDeformableSimplexMesh3DGradientConstraintForceFilter.txx"
#include "itkDemonsRegistrationFilter.txx"
#include "itkDemonsRegistrationFunction.txx"
#include "itkEuclideanDistancePointMetric.txx"
#include "itkExtensionVelocitiesImageFilter.txx"
#include "itkFEMFiniteDifferenceFunctionLoad.txx"
#include "itkFEMRegistrationFilter.txx"
#if defined(USE_FFTWF) || defined(USE_FFTWD)
#include "itkFFTComplexConjugateToRealImageFilter.txx"
#include "itkFFTRealToComplexConjugateImageFilter.txx"
#include "itkFFTWCommon.h"
#include "itkFFTWComplexConjugateToRealImageFilter.txx"
#include "itkFFTWRealToComplexConjugateImageFilter.txx"
#endif
#include "itkFastChamferDistanceImageFilter.txx"
#include "itkFastMarchingExtensionImageFilter.txx"
#include "itkFastMarchingImageFilter.txx"
#include "itkFastMarchingUpwindGradientImageFilter.txx"
#include "itkFastSymmetricForcesDemonsRegistrationFunction.txx"
#include "itkGeodesicActiveContourLevelSetFunction.txx"
#include "itkGeodesicActiveContourLevelSetImageFilter.txx"
#include "itkGeodesicActiveContourShapePriorLevelSetFunction.txx"
#include "itkGeodesicActiveContourShapePriorLevelSetImageFilter.txx"
#include "itkGradientDifferenceImageToImageMetric.txx"
#include "itkGradientVectorFlowImageFilter.txx"
#include "itkHistogramAlgorithmBase.txx"
#include "itkHistogramImageToImageMetric.txx"
#include "itkHistogramMatchingImageFilter.txx"
#include "itkImageClassifierBase.txx"
#include "itkImageGaussianModelEstimator.txx"
#include "itkImageKmeansModelEstimator.txx"
#include "itkImageModelEstimatorBase.txx"
#include "itkImageMomentsCalculator.txx"
#include "itkImagePCADecompositionCalculator.txx"
#include "itkImagePCAShapeModelEstimator.txx"
#include "itkImageRegistrationMethod.txx"
#include "itkImageShapeModelEstimatorBase.txx"
#include "itkImageToImageMetric.txx"
#include "itkImageToSpatialObjectMetric.txx"
#include "itkImageToSpatialObjectRegistrationMethod.txx"
#include "itkIsoContourDistanceImageFilter.txx"
#include "itkIsolatedWatershedImageFilter.txx"
#include "itkIsotropicFourthOrderLevelSetImageFilter.txx"
#include "itkKLMRegionGrowImageFilter.txx"
#include "itkKalmanLinearEstimator.h"
#include "itkKappaStatisticImageToImageMetric.txx"
#include "itkKullbackLeiblerCompareHistogramImageToImageMetric.txx"
#include "itkLabelVotingImageFilter.txx"
#include "itkLaplacianSegmentationLevelSetFunction.txx"
#include "itkLaplacianSegmentationLevelSetImageFilter.txx"
#include "itkLevelSetMotionRegistrationFilter.txx"
#include "itkLevelSetMotionRegistrationFunction.txx"
#include "itkLevelSetNeighborhoodExtractor.txx"
#include "itkLevelSetVelocityNeighborhoodExtractor.txx"
#include "itkMIRegistrationFunction.txx"
#include "itkMRASlabIdentifier.txx"
#include "itkMRFImageFilter.txx"
#include "itkMRIBiasFieldCorrectionFilter.txx"
#include "itkMatchCardinalityImageToImageMetric.txx"
#include "itkMattesMutualInformationImageToImageMetric.txx"
#include "itkMeanReciprocalSquareDifferenceImageToImageMetric.txx"
#include "itkMeanReciprocalSquareDifferencePointSetToImageMetric.txx"
#include "itkMeanSquareRegistrationFunction.txx"
#include "itkMeanSquaresHistogramImageToImageMetric.txx"
#include "itkMeanSquaresImageToImageMetric.txx"
#include "itkMeanSquaresPointSetToImageMetric.txx"
#include "itkMedialNodePairCorrespondenceProcess.txx"
#include "itkMedialNodeTripletCorrespondenceProcess.txx"
#include "itkMinMaxCurvatureFlowFunction.txx"
#include "itkMinMaxCurvatureFlowImageFilter.txx"
#include "itkMultiResolutionImageRegistrationMethod.txx"
#include "itkMultiResolutionPDEDeformableRegistration.txx"
#include "itkMultiResolutionPyramidImageFilter.txx"
#include "itkMutualInformationHistogramImageToImageMetric.txx"
#include "itkMutualInformationImageToImageMetric.txx"
#include "itkNCCRegistrationFunction.txx"
#include "itkNarrowBandCurvesLevelSetImageFilter.txx"
#include "itkNarrowBandLevelSetImageFilter.txx"
#include "itkNarrowBandThresholdSegmentationLevelSetImageFilter.txx"
#include "itkNormalizedCorrelationImageToImageMetric.txx"
#include "itkNormalizedCorrelationPointSetToImageMetric.txx"
#include "itkNormalizedMutualInformationHistogramImageToImageMetric.txx"
#include "itkOrthogonalSwath2DPathFilter.txx"
#include "itkOtsuMultipleThresholdsCalculator.txx"
#include "itkOtsuMultipleThresholdsImageFilter.txx"
#include "itkOtsuThresholdImageCalculator.txx"
#include "itkOtsuThresholdImageFilter.txx"
#include "itkPDEDeformableRegistrationFilter.txx"
#include "itkPDEDeformableRegistrationFunction.h"
#include "itkPointSetToImageMetric.txx"
#include "itkPointSetToImageRegistrationMethod.txx"
#include "itkPointSetToPointSetMetric.txx"
#include "itkPointSetToPointSetRegistrationMethod.txx"
#include "itkPointSetToSpatialObjectDemonsRegistration.txx"
#include "itkRGBGibbsPriorFilter.txx"
#include "itkRayCastInterpolateImageFunction.txx"
#include "itkRecursiveMultiResolutionPyramidImageFilter.txx"
#include "itkRegionGrowImageFilter.txx"
#include "itkRegularSphereMeshSource.txx"
#include "itkReinitializeLevelSetImageFilter.txx"
#include "itkSCSLComplexConjugateToRealImageFilter.txx"
#include "itkSCSLRealToComplexConjugateImageFilter.txx"
#include "itkSTAPLEImageFilter.txx"
#include "itkScalarImageKmeansImageFilter.txx"
#include "itkSegmentationLevelSetImageFilter.txx"
#include "itkShapeDetectionLevelSetFunction.txx"
#include "itkShapeDetectionLevelSetImageFilter.txx"
#include "itkShapePriorMAPCostFunction.txx"
#include "itkShapePriorMAPCostFunctionBase.txx"
#include "itkShapePriorSegmentationLevelSetFunction.txx"
#include "itkShapePriorSegmentationLevelSetImageFilter.txx"
#include "itkSimplexMeshVolumeCalculator.txx"
#include "itkSphereMeshSource.txx"
#include "itkStructHashFunction.h"
#include "itkSymmetricForcesDemonsRegistrationFilter.txx"
#include "itkSymmetricForcesDemonsRegistrationFunction.txx"
#include "itkThresholdMaximumConnectedComponentsImageFilter.txx"
#include "itkThresholdSegmentationLevelSetFunction.txx"
#include "itkThresholdSegmentationLevelSetImageFilter.txx"
#include "itkUnaryMedialNodeMetric.txx"
#include "itkUnsharpMaskLevelSetImageFilter.txx"
#include "itkVectorThresholdSegmentationLevelSetFunction.txx"
#include "itkVectorThresholdSegmentationLevelSetImageFilter.txx"
#include "itkVnlFFTComplexConjugateToRealImageFilter.txx"
#include "itkVnlFFTRealToComplexConjugateImageFilter.txx"
#include "itkVoronoiDiagram2D.txx"
#include "itkVoronoiDiagram2DGenerator.txx"
#include "itkVoronoiPartitioningImageFilter.txx"
#include "itkVoronoiSegmentationImageFilter.txx"
#include "itkVoronoiSegmentationImageFilterBase.txx"
#include "itkVoronoiSegmentationRGBImageFilter.txx"
#include "itkWatershedBoundary.txx"
#include "itkWatershedBoundaryResolver.txx"
#include "itkWatershedEquivalenceRelabeler.txx"
#include "itkWatershedImageFilter.txx"
#include "itkWatershedMiniPipelineProgressCommand.h"
#include "itkWatershedRelabeler.txx"
#include "itkWatershedSegmentTable.txx"
#include "itkWatershedSegmentTree.txx"
#include "itkWatershedSegmentTreeGenerator.txx"
#include "itkWatershedSegmenter.txx"
#include "vnl_fft_3d.h"

int main ( int , char ** )
{

  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>#include "builtin/channel.hpp"
#include "builtin/list.hpp"
#include "builtin/symbol.hpp"
#include "builtin/thread.hpp"

#include "vm.hpp"
#include "objectmemory.hpp"
#include "event.hpp"

#include <cxxtest/TestSuite.h>
#include <sys/time.h>

using namespace rubinius;

class TestChannel : public CxxTest::TestSuite {
  public:

  VM* state;
  Channel* chan;

  void setUp() {
    state = new VM();
    chan = Channel::create(state);
  }

  void tearDown() {
    delete state;
  }

  void test_channel_fields() {
    TS_ASSERT_EQUALS(2U, Channel::fields);
  }

  void test_create() {
    TS_ASSERT(kind_of<Channel>(chan));
    TS_ASSERT(kind_of<List>(chan->waiting()));
  }

  void test_send_then_receive() {
    Task* task = Task::create(state, 10);

    state->globals.current_task.set(task);

    TS_ASSERT(chan->value()->nil_p());
    chan->send(state, Qtrue);

    TS_ASSERT(kind_of<List>(chan->value()));
    List* lst = as<List>(chan->value());
    TS_ASSERT_EQUALS(lst->size(), 1U);
    TS_ASSERT_EQUALS(lst->locate(state, 0), Qtrue);

    chan->receive(state);
    TS_ASSERT_EQUALS(task->calculate_sp(), 0);
    TS_ASSERT_EQUALS(task->stack_top(), Qtrue);
    TS_ASSERT_EQUALS(lst->size(), 0U);
  }

  void test_receive_causes_deadlock() {
    Task* task = Task::create(state, 10);

    state->globals.current_task.set(task);

    Thread* thread = Thread::create(state);
    state->globals.current_thread.set(thread);

    bool thrown = false;
    try {
      chan->receive(state);
    } catch(DeadLock& e) {
      thrown = true;
    }

    TS_ASSERT(thrown);
  }

  void test_receive_causes_thread_switch() {
    Thread* other = Thread::create(state);

    Thread* orig = G(current_thread);

    state->queue_thread(other);

    chan->receive(state);
    TS_ASSERT_EQUALS(G(current_thread), other);
    TS_ASSERT_EQUALS(orig->get_ivar(state, state->symbol("@sleep")), Qtrue);
  }

  void test_receive_causes_event_block() {
    ChannelCallback cb(state, chan);
    event::Timer* timer = new event::Timer(state, &cb, 0.2);

    Thread* orig = G(current_thread);
    state->events->start(timer);

    OBJECT* stack = G(current_task)->current_stack();

    TS_ASSERT(!state->wait_events);
    chan->receive(state);

    TS_ASSERT_EQUALS(chan->waiting()->locate(state, 0), G(current_thread));

    TS_ASSERT(state->wait_events);
    state->events->run_and_wait();

    TS_ASSERT(chan->waiting()->empty_p());

    TS_ASSERT_EQUALS(G(current_thread), orig);
    TS_ASSERT_EQUALS(G(current_task)->calculate_sp(), 0);
    TS_ASSERT_EQUALS(stack[0], Qnil);
  }

  void test_receive_polls_events() {
    ChannelCallback cb(state, chan);
    event::Timer* timer = new event::Timer(state, &cb, 0.2);

    Thread* orig = G(current_thread);
    state->events->start(timer);

    OBJECT* stack = G(current_task)->current_stack();

    TS_ASSERT(!state->wait_events);
    usleep(300000);
    chan->receive(state);
    TS_ASSERT(!state->wait_events);

    TS_ASSERT(chan->waiting()->empty_p());

    TS_ASSERT_EQUALS(G(current_thread), orig);
    TS_ASSERT_EQUALS(G(current_task)->calculate_sp(), 0);
    TS_ASSERT_EQUALS(stack[0], Qnil);
  }

  void test_has_readers_p() {
    TS_ASSERT(!chan->has_readers_p());
    chan->waiting()->append(state, G(current_thread));
    TS_ASSERT(chan->has_readers_p());
  }

  void compare_intervals(struct timeval start, struct timeval finish,
                         suseconds_t expected, suseconds_t delta) {
    time_t sec = finish.tv_sec - start.tv_sec;
    suseconds_t actual = sec * 1000000 - start.tv_usec + finish.tv_usec;
    TS_ASSERT_DELTA(expected, actual, delta);
  }

  void compare_interval_in_range(struct timeval start, struct timeval finish,
				 suseconds_t tmin, suseconds_t tmax) {
    time_t sec = finish.tv_sec - start.tv_sec;
    suseconds_t actual = sec * 1000000 - start.tv_usec + finish.tv_usec;
    TS_ASSERT_LESS_THAN(tmin, actual);
    TS_ASSERT_LESS_THAN(actual,tmax);
  }

  void test_send_in_microseconds() {
    struct timeval start, finish;

    Thread* orig = G(current_thread);
    SYMBOL done = state->symbol("done");
    gettimeofday(&start, NULL);

    OBJECT* stack = G(current_task)->current_stack();

    OBJECT ret = Channel::send_in_microseconds(state, chan, Fixnum::from(100000), done);
    usleep(200000);
    chan->receive(state);

    gettimeofday(&finish, NULL);
    TS_ASSERT(ret->nil_p());
    TS_ASSERT_EQUALS(G(current_thread), orig);
    TS_ASSERT_EQUALS(done, stack[0]);
    compare_interval_in_range(start,finish,200000U,250000U);
  }

  void test_send_in_seconds() {
    Float* point_one = Float::create(state, 0.1);
    struct timeval start, finish;

    Thread* orig = G(current_thread);
    SYMBOL done = state->symbol("done");
    gettimeofday(&start, NULL);

    OBJECT* stack = G(current_task)->current_stack();

    OBJECT ret = Channel::send_in_seconds(state, chan, point_one, done);
    usleep(201000);
    chan->receive(state);

    gettimeofday(&finish, NULL);
    TS_ASSERT(ret->nil_p());
    TS_ASSERT_EQUALS(G(current_thread), orig);
    TS_ASSERT_EQUALS(done, stack[0]);
    compare_intervals(start, finish, 201000U, 350U);
  }
};
<commit_msg>switched all interval tests to range tests<commit_after>#include "builtin/channel.hpp"
#include "builtin/list.hpp"
#include "builtin/symbol.hpp"
#include "builtin/thread.hpp"

#include "vm.hpp"
#include "objectmemory.hpp"
#include "event.hpp"

#include <cxxtest/TestSuite.h>
#include <sys/time.h>

using namespace rubinius;

class TestChannel : public CxxTest::TestSuite {
  public:

  VM* state;
  Channel* chan;

  void setUp() {
    state = new VM();
    chan = Channel::create(state);
  }

  void tearDown() {
    delete state;
  }

  void test_channel_fields() {
    TS_ASSERT_EQUALS(2U, Channel::fields);
  }

  void test_create() {
    TS_ASSERT(kind_of<Channel>(chan));
    TS_ASSERT(kind_of<List>(chan->waiting()));
  }

  void test_send_then_receive() {
    Task* task = Task::create(state, 10);

    state->globals.current_task.set(task);

    TS_ASSERT(chan->value()->nil_p());
    chan->send(state, Qtrue);

    TS_ASSERT(kind_of<List>(chan->value()));
    List* lst = as<List>(chan->value());
    TS_ASSERT_EQUALS(lst->size(), 1U);
    TS_ASSERT_EQUALS(lst->locate(state, 0), Qtrue);

    chan->receive(state);
    TS_ASSERT_EQUALS(task->calculate_sp(), 0);
    TS_ASSERT_EQUALS(task->stack_top(), Qtrue);
    TS_ASSERT_EQUALS(lst->size(), 0U);
  }

  void test_receive_causes_deadlock() {
    Task* task = Task::create(state, 10);

    state->globals.current_task.set(task);

    Thread* thread = Thread::create(state);
    state->globals.current_thread.set(thread);

    bool thrown = false;
    try {
      chan->receive(state);
    } catch(DeadLock& e) {
      thrown = true;
    }

    TS_ASSERT(thrown);
  }

  void test_receive_causes_thread_switch() {
    Thread* other = Thread::create(state);

    Thread* orig = G(current_thread);

    state->queue_thread(other);

    chan->receive(state);
    TS_ASSERT_EQUALS(G(current_thread), other);
    TS_ASSERT_EQUALS(orig->get_ivar(state, state->symbol("@sleep")), Qtrue);
  }

  void test_receive_causes_event_block() {
    ChannelCallback cb(state, chan);
    event::Timer* timer = new event::Timer(state, &cb, 0.2);

    Thread* orig = G(current_thread);
    state->events->start(timer);

    OBJECT* stack = G(current_task)->current_stack();

    TS_ASSERT(!state->wait_events);
    chan->receive(state);

    TS_ASSERT_EQUALS(chan->waiting()->locate(state, 0), G(current_thread));

    TS_ASSERT(state->wait_events);
    state->events->run_and_wait();

    TS_ASSERT(chan->waiting()->empty_p());

    TS_ASSERT_EQUALS(G(current_thread), orig);
    TS_ASSERT_EQUALS(G(current_task)->calculate_sp(), 0);
    TS_ASSERT_EQUALS(stack[0], Qnil);
  }

  void test_receive_polls_events() {
    ChannelCallback cb(state, chan);
    event::Timer* timer = new event::Timer(state, &cb, 0.2);

    Thread* orig = G(current_thread);
    state->events->start(timer);

    OBJECT* stack = G(current_task)->current_stack();

    TS_ASSERT(!state->wait_events);
    usleep(300000);
    chan->receive(state);
    TS_ASSERT(!state->wait_events);

    TS_ASSERT(chan->waiting()->empty_p());

    TS_ASSERT_EQUALS(G(current_thread), orig);
    TS_ASSERT_EQUALS(G(current_task)->calculate_sp(), 0);
    TS_ASSERT_EQUALS(stack[0], Qnil);
  }

  void test_has_readers_p() {
    TS_ASSERT(!chan->has_readers_p());
    chan->waiting()->append(state, G(current_thread));
    TS_ASSERT(chan->has_readers_p());
  }

  void compare_interval_in_range(struct timeval start, struct timeval finish,
				 suseconds_t tmin, suseconds_t tmax) {
    time_t sec = finish.tv_sec - start.tv_sec;
    suseconds_t actual = sec * 1000000 - start.tv_usec + finish.tv_usec;
    TS_ASSERT_LESS_THAN(tmin, actual);
    TS_ASSERT_LESS_THAN(actual,tmax);
  }

  void test_send_in_microseconds() {
    struct timeval start, finish;

    Thread* orig = G(current_thread);
    SYMBOL done = state->symbol("done");
    gettimeofday(&start, NULL);

    OBJECT* stack = G(current_task)->current_stack();

    OBJECT ret = Channel::send_in_microseconds(state, chan, Fixnum::from(100000), done);
    usleep(200000);
    chan->receive(state);

    gettimeofday(&finish, NULL);
    TS_ASSERT(ret->nil_p());
    TS_ASSERT_EQUALS(G(current_thread), orig);
    TS_ASSERT_EQUALS(done, stack[0]);
    compare_interval_in_range(start,finish,200000U,250000U);
  }

  void test_send_in_seconds() {
    Float* point_one = Float::create(state, 0.1);
    struct timeval start, finish;

    Thread* orig = G(current_thread);
    SYMBOL done = state->symbol("done");
    gettimeofday(&start, NULL);

    OBJECT* stack = G(current_task)->current_stack();

    OBJECT ret = Channel::send_in_seconds(state, chan, point_one, done);
    usleep(201000);
    chan->receive(state);

    gettimeofday(&finish, NULL);
    TS_ASSERT(ret->nil_p());
    TS_ASSERT_EQUALS(G(current_thread), orig);
    TS_ASSERT_EQUALS(done, stack[0]);
    compare_interval_in_range(start, finish, 201000U, 251000U);
  }
};
<|endoftext|>


<commit_before>#pragma once

// Simplified version of https://github.com/joboccara/NamedType
// Also see https://github.com/Enhex/phantom_type

// ----------------------------------------------------------------------

#include <type_traits>

namespace acmacs
{
    template <typename T, typename Tag> class named_t
    {
      public:
        using value_type = T;
        template <typename TT> using is_not_reference_t = typename std::enable_if<!std::is_reference<TT>::value, void>::type;

        explicit constexpr named_t(const T& value) : value_(value) {}
        template <typename T_ = T, typename = is_not_reference_t<T_>> explicit constexpr named_t(T&& value) : value_(std::move(value)) {}

        constexpr T& get() { return value_; }
        constexpr T const& get() const { return value_; }
        explicit constexpr operator T&() noexcept { return value_; }
        explicit constexpr operator const T&() const noexcept { return value_; }

      private:
        T value_;
    };

} // namespace acmacs

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>named-type<commit_after>#pragma once

#include <iostream>

// Simplified version of https://github.com/joboccara/NamedType
// Also see https://github.com/Enhex/phantom_type

// ----------------------------------------------------------------------

#include <type_traits>

namespace acmacs
{
    template <typename T, typename Tag> class named_t
    {
      public:
        using value_type = T;
        template <typename TT> using is_not_reference_t = typename std::enable_if<!std::is_reference<TT>::value, void>::type;

        explicit constexpr named_t(const T& value) : value_(value) {}
        template <typename T_ = T, typename = is_not_reference_t<T_>> explicit constexpr named_t(T&& value) : value_(std::move(value)) {}

        constexpr T& get() noexcept { return value_; }
        constexpr T const& get() const noexcept { return value_; }
        explicit constexpr operator T&() noexcept { return value_; }
        explicit constexpr operator const T&() const noexcept { return value_; }

        template <typename T1, typename Tag1> constexpr bool operator==(const named_t<T1, Tag1>& rhs) const noexcept { return get() == rhs.get(); }
        template <typename T1, typename Tag1> constexpr bool operator!=(const named_t<T1, Tag1>& rhs) const noexcept { return !operator==(rhs); }
        template <typename T1, typename Tag1> constexpr bool operator< (const named_t<T1, Tag1>& rhs) const noexcept { return get() < rhs.get(); }

      private:
        T value_;
    };

    template <typename T, typename Tag> inline std::ostream& operator<<(std::ostream& out, const named_t<T, Tag>& named) { return out << named.get(); }

} // namespace acmacs

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>