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

    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>

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

    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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 <qlayout.h>
#include <qpushbutton.h>
#include <qcombobox.h>
#include <qcheckbox.h>
#include <qradiobutton.h>
#include <qlistbox.h>

#include <kdebug.h>
#include <klocale.h>
#include <klineeditdlg.h>
#include <kmessagebox.h>

#include <libkdepim/categoryselectdialog.h>

#include "koprefs.h"
#include "filteredit_base.h"

#include "filtereditdialog.h"
#include "filtereditdialog.moc"

// TODO: Make dialog work on a copy of the filters objects.

FilterEditDialog::FilterEditDialog( QPtrList<CalFilter> *filters,
                                    QWidget *parent, const char *name)
  : KDialogBase( parent, name, false, i18n("Edit Calendar Filters"),
                 Ok | Apply | Cancel ),
    mCategorySelectDialog( 0 )
{
  mFilters = filters;

  QWidget *mainWidget = new QWidget( this );
  setMainWidget( mainWidget );

  mSelectionCombo = new QComboBox( mainWidget );
  connect( mSelectionCombo, SIGNAL( activated( int ) ),
           SLOT( filterSelected() ) );

  QPushButton *addButton = new QPushButton( i18n("Add Filter..."), mainWidget );
  connect( addButton, SIGNAL( clicked() ), SLOT( slotAdd() ) );

  mRemoveButton = new QPushButton( i18n("Remove"), mainWidget );
  connect( mRemoveButton, SIGNAL( clicked() ), SLOT( slotRemove() ) );

  mEditor = new FilterEdit_base( mainWidget );

  QGridLayout *topLayout = new QGridLayout( mainWidget, 2, 2 );
  topLayout->setSpacing( spacingHint() );
  topLayout->addWidget( mSelectionCombo, 0, 0 );
  topLayout->addWidget( addButton, 0, 1 );
  topLayout->addWidget( mRemoveButton, 0, 2 );
  topLayout->addMultiCellWidget( mEditor, 1, 1, 0, 2 );

  connect( mEditor->mCatEditButton, SIGNAL( clicked() ),
           SLOT( editCategorySelection() ) );

  // Clicking cancel exits the dialog without saving
  connect( this, SIGNAL( cancelClicked() ), SLOT( reject() ) );

  updateFilterList();
}

FilterEditDialog::~FilterEditDialog()
{
}

void FilterEditDialog::updateFilterList()
{
  mSelectionCombo->clear();

  CalFilter *filter = mFilters->first();

  if ( !filter ) {
    enableButtonOK( false );
    enableButtonApply( false );
  } else {
    while( filter ) {
      mSelectionCombo->insertItem( filter->name() );
      filter = mFilters->next();
    }

    CalFilter *f = mFilters->at( mSelectionCombo->currentItem() );
    if ( f ) readFilter( f );

    enableButtonOK( true );
    enableButtonApply( true );
  }

  mRemoveButton->setEnabled( mFilters->count() > 1 );
}

void FilterEditDialog::updateCategoryConfig()
{
  if ( mCategorySelectDialog ) mCategorySelectDialog->updateCategoryConfig();
}

void FilterEditDialog::slotDefault()
{
}

void FilterEditDialog::slotApply()
{
  CalFilter *f = mFilters->at( mSelectionCombo->currentItem() );
  writeFilter( f );
  emit filterChanged();
}

void FilterEditDialog::slotOk()
{
  CalFilter *f = mFilters->at( mSelectionCombo->currentItem() );
  writeFilter( f );
  emit filterChanged();
  accept();
}

void FilterEditDialog::slotAdd()
{
  KLineEditDlg dlg( i18n("Enter filter name:"), QString::null, this );
  dlg.setCaption( i18n("Add Filter") );
  if ( dlg.exec() ) {
    mFilters->append( new CalFilter( dlg.text() ) );
    updateFilterList();
  }
}

void FilterEditDialog::slotRemove()
{
  int currentItem = mSelectionCombo->currentItem();
  if ( currentItem < 0 ) return;

  // We need at least a default filter object.
  if ( mFilters->count() <= 1 ) return;

  int result = KMessageBox::questionYesNo( this,
     i18n("This item will be permanently deleted.") );

  if ( result != KMessageBox::Yes ) {
    return;
  }

  mFilters->remove( currentItem );
  updateFilterList();
  emit filterChanged();
}

void FilterEditDialog::editCategorySelection()
{
  if ( !mCategorySelectDialog ) {
    mCategorySelectDialog = new KPIM::CategorySelectDialog(
        KOPrefs::instance(), this, "filterCatSelect" );
    mCategorySelectDialog->setSelected( mCategories );
    connect( mCategorySelectDialog,
             SIGNAL( categoriesSelected( const QStringList & ) ),
             SLOT( updateCategorySelection( const QStringList & ) ) );
    connect( mCategorySelectDialog, SIGNAL( editCategories() ),
             SIGNAL( editCategories() ) );
  }

  mCategorySelectDialog->show();
}

void FilterEditDialog::updateCategorySelection( const QStringList &categories )
{
  mCategories = categories;

  mEditor->mCatList->clear();
  mEditor->mCatList->insertStringList( mCategories );
}

void FilterEditDialog::filterSelected()
{
  CalFilter *f = mFilters->at( mSelectionCombo->currentItem() );
  kdDebug(5850) << "Selected filter " << f->name() << endl;
  if ( f ) readFilter( f );
}

void FilterEditDialog::readFilter( CalFilter *filter )
{
  int c = filter->criteria();

  mEditor->mCompletedCheck->setChecked( c & CalFilter::HideCompleted );
  mEditor->mRecurringCheck->setChecked( c & CalFilter::HideRecurring );

  if ( c & CalFilter::ShowCategories ) {
    mEditor->mCatShowCheck->setChecked( true );
  } else {
    mEditor->mCatHideCheck->setChecked( true );
  }

  mEditor->mCatList->clear();
  mEditor->mCatList->insertStringList( filter->categoryList() );
  mCategories = filter->categoryList();
}

void FilterEditDialog::writeFilter( CalFilter *filter )
{
  int c = 0;

  if ( mEditor->mCompletedCheck->isChecked() ) c |= CalFilter::HideCompleted;
  if ( mEditor->mRecurringCheck->isChecked() ) c |= CalFilter::HideRecurring;
  if ( mEditor->mCatShowCheck->isChecked() ) c |= CalFilter::ShowCategories;

  filter->setCriteria( c );

  QStringList categoryList;
  for( uint i = 0; i < mEditor->mCatList->count(); ++i ) {
    categoryList.append( mEditor->mCatList->text( i ) );
  }
  filter->setCategoryList( categoryList );
}
<commit_msg>KLineEditDlg -> KInputDialog<commit_after>/*
    This file is part of KOrganizer.

    Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>

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

    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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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 <qlayout.h>
#include <qpushbutton.h>
#include <qcombobox.h>
#include <qcheckbox.h>
#include <qradiobutton.h>
#include <qlistbox.h>

#include <kdebug.h>
#include <klocale.h>
#include <kinputdialog.h>
#include <kmessagebox.h>

#include <libkdepim/categoryselectdialog.h>

#include "koprefs.h"
#include "filteredit_base.h"

#include "filtereditdialog.h"
#include "filtereditdialog.moc"

// TODO: Make dialog work on a copy of the filters objects.

FilterEditDialog::FilterEditDialog( QPtrList<CalFilter> *filters,
                                    QWidget *parent, const char *name)
  : KDialogBase( parent, name, false, i18n("Edit Calendar Filters"),
                 Ok | Apply | Cancel ),
    mCategorySelectDialog( 0 )
{
  mFilters = filters;

  QWidget *mainWidget = new QWidget( this );
  setMainWidget( mainWidget );

  mSelectionCombo = new QComboBox( mainWidget );
  connect( mSelectionCombo, SIGNAL( activated( int ) ),
           SLOT( filterSelected() ) );

  QPushButton *addButton = new QPushButton( i18n("Add Filter..."), mainWidget );
  connect( addButton, SIGNAL( clicked() ), SLOT( slotAdd() ) );

  mRemoveButton = new QPushButton( i18n("Remove"), mainWidget );
  connect( mRemoveButton, SIGNAL( clicked() ), SLOT( slotRemove() ) );

  mEditor = new FilterEdit_base( mainWidget );

  QGridLayout *topLayout = new QGridLayout( mainWidget, 2, 2 );
  topLayout->setSpacing( spacingHint() );
  topLayout->addWidget( mSelectionCombo, 0, 0 );
  topLayout->addWidget( addButton, 0, 1 );
  topLayout->addWidget( mRemoveButton, 0, 2 );
  topLayout->addMultiCellWidget( mEditor, 1, 1, 0, 2 );

  connect( mEditor->mCatEditButton, SIGNAL( clicked() ),
           SLOT( editCategorySelection() ) );

  // Clicking cancel exits the dialog without saving
  connect( this, SIGNAL( cancelClicked() ), SLOT( reject() ) );

  updateFilterList();
}

FilterEditDialog::~FilterEditDialog()
{
}

void FilterEditDialog::updateFilterList()
{
  mSelectionCombo->clear();

  CalFilter *filter = mFilters->first();

  if ( !filter ) {
    enableButtonOK( false );
    enableButtonApply( false );
  } else {
    while( filter ) {
      mSelectionCombo->insertItem( filter->name() );
      filter = mFilters->next();
    }

    CalFilter *f = mFilters->at( mSelectionCombo->currentItem() );
    if ( f ) readFilter( f );

    enableButtonOK( true );
    enableButtonApply( true );
  }

  mRemoveButton->setEnabled( mFilters->count() > 1 );
}

void FilterEditDialog::updateCategoryConfig()
{
  if ( mCategorySelectDialog ) mCategorySelectDialog->updateCategoryConfig();
}

void FilterEditDialog::slotDefault()
{
}

void FilterEditDialog::slotApply()
{
  CalFilter *f = mFilters->at( mSelectionCombo->currentItem() );
  writeFilter( f );
  emit filterChanged();
}

void FilterEditDialog::slotOk()
{
  CalFilter *f = mFilters->at( mSelectionCombo->currentItem() );
  writeFilter( f );
  emit filterChanged();
  accept();
}

void FilterEditDialog::slotAdd()
{
  QString txt = KInputDialog::getText( i18n("Add Filter"),
                                       i18n("Enter filter name:"),
                                       QString::null, 0, this );
  if ( !txt.isEmpty() ) {
    mFilters->append( new CalFilter( txt ) );
    updateFilterList();
  }
}

void FilterEditDialog::slotRemove()
{
  int currentItem = mSelectionCombo->currentItem();
  if ( currentItem < 0 ) return;

  // We need at least a default filter object.
  if ( mFilters->count() <= 1 ) return;

  int result = KMessageBox::questionYesNo( this,
     i18n("This item will be permanently deleted.") );

  if ( result != KMessageBox::Yes ) {
    return;
  }

  mFilters->remove( currentItem );
  updateFilterList();
  emit filterChanged();
}

void FilterEditDialog::editCategorySelection()
{
  if ( !mCategorySelectDialog ) {
    mCategorySelectDialog = new KPIM::CategorySelectDialog(
        KOPrefs::instance(), this, "filterCatSelect" );
    mCategorySelectDialog->setSelected( mCategories );
    connect( mCategorySelectDialog,
             SIGNAL( categoriesSelected( const QStringList & ) ),
             SLOT( updateCategorySelection( const QStringList & ) ) );
    connect( mCategorySelectDialog, SIGNAL( editCategories() ),
             SIGNAL( editCategories() ) );
  }

  mCategorySelectDialog->show();
}

void FilterEditDialog::updateCategorySelection( const QStringList &categories )
{
  mCategories = categories;

  mEditor->mCatList->clear();
  mEditor->mCatList->insertStringList( mCategories );
}

void FilterEditDialog::filterSelected()
{
  CalFilter *f = mFilters->at( mSelectionCombo->currentItem() );
  kdDebug(5850) << "Selected filter " << f->name() << endl;
  if ( f ) readFilter( f );
}

void FilterEditDialog::readFilter( CalFilter *filter )
{
  int c = filter->criteria();

  mEditor->mCompletedCheck->setChecked( c & CalFilter::HideCompleted );
  mEditor->mRecurringCheck->setChecked( c & CalFilter::HideRecurring );

  if ( c & CalFilter::ShowCategories ) {
    mEditor->mCatShowCheck->setChecked( true );
  } else {
    mEditor->mCatHideCheck->setChecked( true );
  }

  mEditor->mCatList->clear();
  mEditor->mCatList->insertStringList( filter->categoryList() );
  mCategories = filter->categoryList();
}

void FilterEditDialog::writeFilter( CalFilter *filter )
{
  int c = 0;

  if ( mEditor->mCompletedCheck->isChecked() ) c |= CalFilter::HideCompleted;
  if ( mEditor->mRecurringCheck->isChecked() ) c |= CalFilter::HideRecurring;
  if ( mEditor->mCatShowCheck->isChecked() ) c |= CalFilter::ShowCategories;

  filter->setCriteria( c );

  QStringList categoryList;
  for( uint i = 0; i < mEditor->mCatList->count(); ++i ) {
    categoryList.append( mEditor->mCatList->text( i ) );
  }
  filter->setCategoryList( categoryList );
}
<|endoftext|>


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

  Copyright (C) 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 "incidencechanger.h"
#include "kogroupware.h"
#include "koprefs.h"
#include "mailscheduler.h"

#include <KCal/AssignmentVisitor>
#include <KCal/CalendarResources>
#include <KCal/DndFactory>
#include <KCal/FreeBusy>
#include <KCal/Incidence>

#include <KDebug>
#include <KLocale>
#include <KMessageBox>

bool IncidenceChanger::beginChange( Incidence *incidence )
{
  if ( !incidence ) {
    return false;
  }
  kDebug() << "for incidence \"" << incidence->summary() << "\"";
  return mCalendar->beginChange( incidence );
}

bool IncidenceChanger::sendGroupwareMessage( KCal::Incidence *incidence,
                                             KCal::iTIPMethod method, bool deleting )
{
  if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) &&
       incidence->attendeeCount() > 0 &&
       !KOPrefs::instance()->mUseGroupwareCommunication ) {
    emit schedule( method, incidence );
    return true;
  } else if ( KOPrefs::instance()->mUseGroupwareCommunication ) {
    // FIXME: Find a widget to use as parent, instead of 0
    return KOGroupware::instance()->sendICalMessage( 0, method, incidence, deleting );
  }
  return true;
}

void IncidenceChanger::cancelAttendees( Incidence *incidence )
{
  if ( KOPrefs::instance()->mUseGroupwareCommunication ) {
    if ( KMessageBox::questionYesNo(
           0,
           i18n( "Some attendees were removed from the incidence. "
                 "Shall cancel messages be sent to these attendees?" ),
           i18n( "Attendees Removed" ), KGuiItem( i18n( "Send Messages" ) ),
           KGuiItem( i18n( "Do Not Send" ) ) ) == KMessageBox::Yes ) {
      // don't use KOGroupware::sendICalMessage here, because that asks just
      // a very general question "Other people are involved, send message to
      // them?", which isn't helpful at all in this situation. Afterwards, it
      // would only call the MailScheduler::performTransaction, so do this
      // manually.
      // FIXME: Groupware schedulling should be factored out to it's own class
      //        anyway
      MailScheduler scheduler( mCalendar );
      scheduler.performTransaction( incidence, iTIPCancel );
    }
  }
}

bool IncidenceChanger::endChange( Incidence *incidence )
{
  // FIXME: if that's a groupware incidence, and I'm not the organizer,
  // send out a mail to the organizer with a counterproposal instead
  // of actually changing the incidence. Then no locking is needed.
  // FIXME: if that's a groupware incidence, and the incidence was
  // never locked, we can't unlock it with endChange().
  if ( !incidence ) {
    return false;
  }

  kDebug() << "\"" << incidence->summary() << "\"";
  return mCalendar->endChange( incidence );
}

bool IncidenceChanger::deleteIncidence( Incidence *incidence )
{
  if ( !incidence ) {
    return true;
  }

  kDebug() << "\"" << incidence->summary() << "\"";
  bool doDelete = sendGroupwareMessage( incidence, KCal::iTIPCancel, true );
  if( doDelete ) {
    // @TODO: let Calendar::deleteIncidence do the locking...
    Incidence *tmp = incidence->clone();
    emit incidenceToBeDeleted( incidence );
    doDelete = mCalendar->deleteIncidence( incidence );
    if ( !KOPrefs::instance()->thatIsMe( tmp->organizer().email() ) ) {
      const QStringList myEmails = KOPrefs::instance()->allEmails();
      bool notifyOrganizer = false;
      for ( QStringList::ConstIterator it = myEmails.begin(); it != myEmails.end(); ++it ) {
        QString email = *it;
        Attendee *me = tmp->attendeeByMail(email);
        if ( me ) {
          if ( me->status() == KCal::Attendee::Accepted ||
               me->status() == KCal::Attendee::Delegated ) {
            notifyOrganizer = true;
          }
          Attendee *newMe = new Attendee( *me );
          newMe->setStatus( KCal::Attendee::Declined );
          tmp->clearAttendees();
          tmp->addAttendee( newMe );
          break;
        }
      }

      if ( notifyOrganizer ) {
        MailScheduler scheduler( mCalendar );
        scheduler.performTransaction( tmp, KCal::iTIPReply );
      }
    }
    emit incidenceDeleted( incidence );
  }
  return doDelete;
}

bool IncidenceChanger::cutIncidence( Incidence *incidence )
{
  if ( !incidence ) {
    return true;
  }

  kDebug() << "\"" << incidence->summary() << "\"";
  bool doDelete = sendGroupwareMessage( incidence, KCal::iTIPCancel );
  if( doDelete ) {
    // @TODO: the factory needs to do the locking!
    DndFactory factory( mCalendar );
    emit incidenceToBeDeleted( incidence );
    factory.cutIncidence( incidence );
    emit incidenceDeleted( incidence );
  }
  return doDelete;
}

class IncidenceChanger::ComparisonVisitor : public IncidenceBase::Visitor
{
  public:
    ComparisonVisitor() {}
    bool act( IncidenceBase *incidence, IncidenceBase *inc2 )
    {
      mIncidence2 = inc2;
      if ( incidence ) {
        return incidence->accept( *this );
      } else {
        return inc2 == 0;
      }
    }

  protected:
    bool visit( Event *event )
    {
      Event *ev2 = dynamic_cast<Event*>(mIncidence2);
      if ( event && ev2 ) {
        return *event == *ev2;
      } else {
        // either both 0, or return false;
        return ev2 == event;
      }
    }
    bool visit( Todo *todo )
    {
      Todo *to2 = dynamic_cast<Todo*>( mIncidence2 );
      if ( todo && to2 ) {
        return *todo == *to2;
      } else {
        // either both 0, or return false;
        return todo == to2;
      }
    }
    bool visit( Journal *journal )
    {
      Journal *j2 = dynamic_cast<Journal*>( mIncidence2 );
      if ( journal && j2 ) {
        return *journal == *j2;
      } else {
        // either both 0, or return false;
        return journal == j2;
      }
    }
    bool visit( FreeBusy *fb )
    {
      FreeBusy *fb2 = dynamic_cast<FreeBusy*>( mIncidence2 );
      if ( fb && fb2 ) {
        return *fb == *fb2;
      } else {
        // either both 0, or return false;
        return fb2 == fb;
      }
    }

  protected:
    IncidenceBase *mIncidence2;
};

bool IncidenceChanger::incidencesEqual( Incidence *inc1, Incidence *inc2 )
{
  ComparisonVisitor v;
  return ( v.act( inc1, inc2 ) );
}

bool IncidenceChanger::assignIncidence( Incidence *inc1, Incidence *inc2 )
{
  if ( !inc1 || !inc2 ) {
    return false;
  }

  AssignmentVisitor v;
  return v.assign( inc1, inc2 );
}

bool IncidenceChanger::myAttendeeStatusChanged( Incidence *oldInc, Incidence *newInc )
{
  Attendee *oldMe = oldInc->attendeeByMails( KOPrefs::instance()->allEmails() );
  Attendee *newMe = newInc->attendeeByMails( KOPrefs::instance()->allEmails() );
  if ( oldMe && newMe && ( oldMe->status() != newMe->status() ) ) {
    return true;
  }

  return false;
}

bool IncidenceChanger::changeIncidence( Incidence *oldinc, Incidence *newinc,
                                        int action )
{
  kDebug() << "for incidence \"" << newinc->summary() << "\""
           << "( old one was \"" << oldinc->summary() << "\")";

  if ( incidencesEqual( newinc, oldinc ) ) {
    // Don't do anything
    kDebug() << "Incidence not changed";
  } else {
    kDebug() << "Changing incidence";
    bool statusChanged = myAttendeeStatusChanged( oldinc, newinc );
    int revision = newinc->revision();
    newinc->setRevision( revision + 1 );
    // FIXME: Use a generic method for this! Ideally, have an interface class
    //        for group cheduling. Each implementation could then just do what
    //        it wants with the event. If no groupware is used,use the null
    //        pattern...
    bool success = true;
    if ( KOPrefs::instance()->mUseGroupwareCommunication ) {
      success = KOGroupware::instance()->sendICalMessage( 0,
                                                          KCal::iTIPRequest,
                                                          newinc, false, statusChanged );
    }

    if ( success ) {
      // Accept the event changes
      if ( action < 0 ) {
        emit incidenceChanged( oldinc, newinc );
      } else {
        emit incidenceChanged( oldinc, newinc, action );
      }
    } else {
      // revert changes
      assignIncidence( newinc, oldinc );
      return false;
    }
  }
  return true;
}

bool IncidenceChanger::addIncidence( Incidence *incidence, QWidget *parent )
{
  CalendarResources *stdcal = dynamic_cast<CalendarResources*>( mCalendar );
  if( stdcal && !stdcal->hasCalendarResources() ) {
    KMessageBox::sorry( parent, i18n( "No resources found. We can not add event." ));
    return false;
  }

  kDebug() << "\"" << incidence->summary() << "\"";
  if ( KOPrefs::instance()->mUseGroupwareCommunication ) {
    if ( !KOGroupware::instance()->sendICalMessage( parent,
                                                    KCal::iTIPRequest,
                                                    incidence ) ) {
      return false;
    }
  }
  // FIXME: This is a nasty hack, since we need to set a parent for the
  //        resource selection dialog. However, we don't have any UI methods
  //        in the calendar, only in the CalendarResources::DestinationPolicy
  //        So we need to type-cast it and extract it from the CalendarResources
  QWidget *tmpparent = 0;
  if ( stdcal ) {
    tmpparent = stdcal->dialogParentWidget();
    stdcal->setDialogParentWidget( parent );
  }
  bool success = mCalendar->addIncidence( incidence );
  if ( stdcal ) {
    // Reset the parent widget, otherwise we'll end up with pointers to deleted
    // widgets sooner or later
    stdcal->setDialogParentWidget( tmpparent );
  }
  if ( !success && stdcal ) {
    // We can have a failure if the user pressed [cancel] in the resource
    // selectdialog, so check the exception.
    ErrorFormat *e = stdcal->exception();
    if ( !e || ( e && ( e->errorCode() != KCal::ErrorFormat::UserCancel ) ) ) {
      KMessageBox::sorry( parent,
                          i18n( "Unable to save %1 \"%2\".",
                                i18n( incidence->type() ),
                                incidence->summary() ) );
    }
    return false;
  }
  emit incidenceAdded( incidence );
  return true;
}

#include "incidencechanger.moc"
<commit_msg>Proof-reading new message.<commit_after>/*
  This file is part of KOrganizer.

  Copyright (C) 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 "incidencechanger.h"
#include "kogroupware.h"
#include "koprefs.h"
#include "mailscheduler.h"

#include <KCal/AssignmentVisitor>
#include <KCal/CalendarResources>
#include <KCal/DndFactory>
#include <KCal/FreeBusy>
#include <KCal/Incidence>

#include <KDebug>
#include <KLocale>
#include <KMessageBox>

bool IncidenceChanger::beginChange( Incidence *incidence )
{
  if ( !incidence ) {
    return false;
  }
  kDebug() << "for incidence \"" << incidence->summary() << "\"";
  return mCalendar->beginChange( incidence );
}

bool IncidenceChanger::sendGroupwareMessage( KCal::Incidence *incidence,
                                             KCal::iTIPMethod method, bool deleting )
{
  if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) &&
       incidence->attendeeCount() > 0 &&
       !KOPrefs::instance()->mUseGroupwareCommunication ) {
    emit schedule( method, incidence );
    return true;
  } else if ( KOPrefs::instance()->mUseGroupwareCommunication ) {
    // FIXME: Find a widget to use as parent, instead of 0
    return KOGroupware::instance()->sendICalMessage( 0, method, incidence, deleting );
  }
  return true;
}

void IncidenceChanger::cancelAttendees( Incidence *incidence )
{
  if ( KOPrefs::instance()->mUseGroupwareCommunication ) {
    if ( KMessageBox::questionYesNo(
           0,
           i18n( "Some attendees were removed from the incidence. "
                 "Shall cancel messages be sent to these attendees?" ),
           i18n( "Attendees Removed" ), KGuiItem( i18n( "Send Messages" ) ),
           KGuiItem( i18n( "Do Not Send" ) ) ) == KMessageBox::Yes ) {
      // don't use KOGroupware::sendICalMessage here, because that asks just
      // a very general question "Other people are involved, send message to
      // them?", which isn't helpful at all in this situation. Afterwards, it
      // would only call the MailScheduler::performTransaction, so do this
      // manually.
      // FIXME: Groupware schedulling should be factored out to it's own class
      //        anyway
      MailScheduler scheduler( mCalendar );
      scheduler.performTransaction( incidence, iTIPCancel );
    }
  }
}

bool IncidenceChanger::endChange( Incidence *incidence )
{
  // FIXME: if that's a groupware incidence, and I'm not the organizer,
  // send out a mail to the organizer with a counterproposal instead
  // of actually changing the incidence. Then no locking is needed.
  // FIXME: if that's a groupware incidence, and the incidence was
  // never locked, we can't unlock it with endChange().
  if ( !incidence ) {
    return false;
  }

  kDebug() << "\"" << incidence->summary() << "\"";
  return mCalendar->endChange( incidence );
}

bool IncidenceChanger::deleteIncidence( Incidence *incidence )
{
  if ( !incidence ) {
    return true;
  }

  kDebug() << "\"" << incidence->summary() << "\"";
  bool doDelete = sendGroupwareMessage( incidence, KCal::iTIPCancel, true );
  if( doDelete ) {
    // @TODO: let Calendar::deleteIncidence do the locking...
    Incidence *tmp = incidence->clone();
    emit incidenceToBeDeleted( incidence );
    doDelete = mCalendar->deleteIncidence( incidence );
    if ( !KOPrefs::instance()->thatIsMe( tmp->organizer().email() ) ) {
      const QStringList myEmails = KOPrefs::instance()->allEmails();
      bool notifyOrganizer = false;
      for ( QStringList::ConstIterator it = myEmails.begin(); it != myEmails.end(); ++it ) {
        QString email = *it;
        Attendee *me = tmp->attendeeByMail(email);
        if ( me ) {
          if ( me->status() == KCal::Attendee::Accepted ||
               me->status() == KCal::Attendee::Delegated ) {
            notifyOrganizer = true;
          }
          Attendee *newMe = new Attendee( *me );
          newMe->setStatus( KCal::Attendee::Declined );
          tmp->clearAttendees();
          tmp->addAttendee( newMe );
          break;
        }
      }

      if ( notifyOrganizer ) {
        MailScheduler scheduler( mCalendar );
        scheduler.performTransaction( tmp, KCal::iTIPReply );
      }
    }
    emit incidenceDeleted( incidence );
  }
  return doDelete;
}

bool IncidenceChanger::cutIncidence( Incidence *incidence )
{
  if ( !incidence ) {
    return true;
  }

  kDebug() << "\"" << incidence->summary() << "\"";
  bool doDelete = sendGroupwareMessage( incidence, KCal::iTIPCancel );
  if( doDelete ) {
    // @TODO: the factory needs to do the locking!
    DndFactory factory( mCalendar );
    emit incidenceToBeDeleted( incidence );
    factory.cutIncidence( incidence );
    emit incidenceDeleted( incidence );
  }
  return doDelete;
}

class IncidenceChanger::ComparisonVisitor : public IncidenceBase::Visitor
{
  public:
    ComparisonVisitor() {}
    bool act( IncidenceBase *incidence, IncidenceBase *inc2 )
    {
      mIncidence2 = inc2;
      if ( incidence ) {
        return incidence->accept( *this );
      } else {
        return inc2 == 0;
      }
    }

  protected:
    bool visit( Event *event )
    {
      Event *ev2 = dynamic_cast<Event*>(mIncidence2);
      if ( event && ev2 ) {
        return *event == *ev2;
      } else {
        // either both 0, or return false;
        return ev2 == event;
      }
    }
    bool visit( Todo *todo )
    {
      Todo *to2 = dynamic_cast<Todo*>( mIncidence2 );
      if ( todo && to2 ) {
        return *todo == *to2;
      } else {
        // either both 0, or return false;
        return todo == to2;
      }
    }
    bool visit( Journal *journal )
    {
      Journal *j2 = dynamic_cast<Journal*>( mIncidence2 );
      if ( journal && j2 ) {
        return *journal == *j2;
      } else {
        // either both 0, or return false;
        return journal == j2;
      }
    }
    bool visit( FreeBusy *fb )
    {
      FreeBusy *fb2 = dynamic_cast<FreeBusy*>( mIncidence2 );
      if ( fb && fb2 ) {
        return *fb == *fb2;
      } else {
        // either both 0, or return false;
        return fb2 == fb;
      }
    }

  protected:
    IncidenceBase *mIncidence2;
};

bool IncidenceChanger::incidencesEqual( Incidence *inc1, Incidence *inc2 )
{
  ComparisonVisitor v;
  return ( v.act( inc1, inc2 ) );
}

bool IncidenceChanger::assignIncidence( Incidence *inc1, Incidence *inc2 )
{
  if ( !inc1 || !inc2 ) {
    return false;
  }

  AssignmentVisitor v;
  return v.assign( inc1, inc2 );
}

bool IncidenceChanger::myAttendeeStatusChanged( Incidence *oldInc, Incidence *newInc )
{
  Attendee *oldMe = oldInc->attendeeByMails( KOPrefs::instance()->allEmails() );
  Attendee *newMe = newInc->attendeeByMails( KOPrefs::instance()->allEmails() );
  if ( oldMe && newMe && ( oldMe->status() != newMe->status() ) ) {
    return true;
  }

  return false;
}

bool IncidenceChanger::changeIncidence( Incidence *oldinc, Incidence *newinc,
                                        int action )
{
  kDebug() << "for incidence \"" << newinc->summary() << "\""
           << "( old one was \"" << oldinc->summary() << "\")";

  if ( incidencesEqual( newinc, oldinc ) ) {
    // Don't do anything
    kDebug() << "Incidence not changed";
  } else {
    kDebug() << "Changing incidence";
    bool statusChanged = myAttendeeStatusChanged( oldinc, newinc );
    int revision = newinc->revision();
    newinc->setRevision( revision + 1 );
    // FIXME: Use a generic method for this! Ideally, have an interface class
    //        for group cheduling. Each implementation could then just do what
    //        it wants with the event. If no groupware is used,use the null
    //        pattern...
    bool success = true;
    if ( KOPrefs::instance()->mUseGroupwareCommunication ) {
      success = KOGroupware::instance()->sendICalMessage( 0,
                                                          KCal::iTIPRequest,
                                                          newinc, false, statusChanged );
    }

    if ( success ) {
      // Accept the event changes
      if ( action < 0 ) {
        emit incidenceChanged( oldinc, newinc );
      } else {
        emit incidenceChanged( oldinc, newinc, action );
      }
    } else {
      // revert changes
      assignIncidence( newinc, oldinc );
      return false;
    }
  }
  return true;
}

bool IncidenceChanger::addIncidence( Incidence *incidence, QWidget *parent )
{
  CalendarResources *stdcal = dynamic_cast<CalendarResources*>( mCalendar );
  if( stdcal && !stdcal->hasCalendarResources() ) {
    KMessageBox::sorry( parent, i18n( "No resources found, event cannot be added." ));
    return false;
  }

  kDebug() << "\"" << incidence->summary() << "\"";
  if ( KOPrefs::instance()->mUseGroupwareCommunication ) {
    if ( !KOGroupware::instance()->sendICalMessage( parent,
                                                    KCal::iTIPRequest,
                                                    incidence ) ) {
      return false;
    }
  }
  // FIXME: This is a nasty hack, since we need to set a parent for the
  //        resource selection dialog. However, we don't have any UI methods
  //        in the calendar, only in the CalendarResources::DestinationPolicy
  //        So we need to type-cast it and extract it from the CalendarResources
  QWidget *tmpparent = 0;
  if ( stdcal ) {
    tmpparent = stdcal->dialogParentWidget();
    stdcal->setDialogParentWidget( parent );
  }
  bool success = mCalendar->addIncidence( incidence );
  if ( stdcal ) {
    // Reset the parent widget, otherwise we'll end up with pointers to deleted
    // widgets sooner or later
    stdcal->setDialogParentWidget( tmpparent );
  }
  if ( !success && stdcal ) {
    // We can have a failure if the user pressed [cancel] in the resource
    // selectdialog, so check the exception.
    ErrorFormat *e = stdcal->exception();
    if ( !e || ( e && ( e->errorCode() != KCal::ErrorFormat::UserCancel ) ) ) {
      KMessageBox::sorry( parent,
                          i18n( "Unable to save %1 \"%2\".",
                                i18n( incidence->type() ),
                                incidence->summary() ) );
    }
    return false;
  }
  emit incidenceAdded( incidence );
  return true;
}

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


<commit_before>//=============================================================================================================
/**
* @file     main.cpp
* @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     July, 2012
*
* @section  LICENSE
*
* Copyright (C) 2012, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Example of a clusteredInverse application
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <fs/label.h>
#include <fs/surface.h>
#include <fs/surfaceset.h>
#include <fs/annotationset.h>

#include <fiff/fiff_evoked.h>
#include <mne/mne_sourceestimate.h>
#include <inverse/minimumNorm/minimumnorm.h>

#include <utils/mnemath.h>

#include <iostream>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QApplication>
#include <QCommandLineParser>
#include <QSet>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace MNELIB;
using namespace FSLIB;
using namespace FIFFLIB;
using namespace INVERSELIB;
using namespace DISP3DLIB;
using namespace UTILSLIB;

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

//=============================================================================================================
/**
* The function main marks the entry point of the program.
* By default, main has the storage class extern.
*
* @param [in] argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started.
* @param [in] argv (argument vector) is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started.
* @return the value that was set to exit() (which is 0 if exit() is called via quit()).
*/
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // Command Line Parser
    QCommandLineParser parser;
    parser.setApplicationDescription("Start clusteredInverse example");
    parser.addHelpOption();
    QCommandLineOption fwdFileOption("fwd", "Path to the forward solution <file>.", "file", "./MNE-sample-data/MEG/sample/sample_audvis-meg-eeg-oct-6-fwd.fif");
    QCommandLineOption evokedFileOption("ave", "Path to the evoked/average <file>.", "file", "./MNE-sample-data/MEG/sample/sample_audvis-ave.fif");
    QCommandLineOption snrOption("snr", "The <snr> value used for computation.", "snr", "1.0");//3.0f;//0.1f;//3.0f;
    QCommandLineOption annotOption("annotType", "Annotation type <type>.", "type", "aparc.a2009s");
    QCommandLineOption subjectOption("subject", "Selected subject <subject>.", "subject", "sample");
    QCommandLineOption subjectPathOption("subjectPath", "Selected subject path <subjectPath>.", "subjectPath", "./MNE-sample-data/subjects");
    QCommandLineOption hemiOption("hemi", "Selected hemisphere <hemi>.", "hemi", "2");
    QCommandLineOption evokedSetNoOption("setNo", "The average <setNo> to pick (must match ID or comment).", "setNo", "1");

    parser.addOption(fwdFileOption);
    parser.addOption(evokedFileOption);
    parser.addOption(snrOption);
    parser.addOption(annotOption);
    parser.addOption(subjectOption);
    parser.addOption(subjectPathOption);
    parser.addOption(evokedSetNoOption);

    parser.process(app);

    //Parse inputs
    QFile t_fileFwd(parser.value(fwdFileOption));
    QFile t_fileEvoked(parser.value(evokedFileOption));

    // Load data
    QPair<QVariant, QVariant> baseline(QVariant(), 0);
    FiffEvoked evoked(t_fileEvoked, parser.value(evokedSetNoOption).toInt(), baseline);
    if(evoked.isEmpty())
        return 1;

    std::cout << "evoked first " << evoked.first << "; last " << evoked.last << std::endl;

    MNEForwardSolution t_Fwd(t_fileFwd);
    if(t_Fwd.isEmpty())
        return 1;

    AnnotationSet t_annotationSet (parser.value(subjectOption), parser.value(hemiOption).toInt(), parser.value(annotOption), parser.value(subjectPathOption));

    //
    // Cluster forward solution;
    //
    MNEForwardSolution t_clusteredFwd = t_Fwd.cluster_forward_solution(t_annotationSet, 20);//40);

    return app.exec();//1;
}
<commit_msg>[LIB-63] Remove Disp3D namespace<commit_after>//=============================================================================================================
/**
* @file     main.cpp
* @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     July, 2012
*
* @section  LICENSE
*
* Copyright (C) 2012, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    Example of a clusteredInverse application
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <fs/label.h>
#include <fs/surface.h>
#include <fs/surfaceset.h>
#include <fs/annotationset.h>

#include <fiff/fiff_evoked.h>
#include <mne/mne_sourceestimate.h>
#include <inverse/minimumNorm/minimumnorm.h>

#include <utils/mnemath.h>

#include <iostream>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QApplication>
#include <QCommandLineParser>
#include <QSet>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace MNELIB;
using namespace FSLIB;
using namespace FIFFLIB;
using namespace INVERSELIB;
using namespace UTILSLIB;

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

//=============================================================================================================
/**
* The function main marks the entry point of the program.
* By default, main has the storage class extern.
*
* @param [in] argc (argument count) is an integer that indicates how many arguments were entered on the command line when the program was started.
* @param [in] argv (argument vector) is an array of pointers to arrays of character objects. The array objects are null-terminated strings, representing the arguments that were entered on the command line when the program was started.
* @return the value that was set to exit() (which is 0 if exit() is called via quit()).
*/
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // Command Line Parser
    QCommandLineParser parser;
    parser.setApplicationDescription("Start clusteredInverse example");
    parser.addHelpOption();
    QCommandLineOption fwdFileOption("fwd", "Path to the forward solution <file>.", "file", "./MNE-sample-data/MEG/sample/sample_audvis-meg-eeg-oct-6-fwd.fif");
    QCommandLineOption evokedFileOption("ave", "Path to the evoked/average <file>.", "file", "./MNE-sample-data/MEG/sample/sample_audvis-ave.fif");
    QCommandLineOption snrOption("snr", "The <snr> value used for computation.", "snr", "1.0");//3.0f;//0.1f;//3.0f;
    QCommandLineOption annotOption("annotType", "Annotation type <type>.", "type", "aparc.a2009s");
    QCommandLineOption subjectOption("subject", "Selected subject <subject>.", "subject", "sample");
    QCommandLineOption subjectPathOption("subjectPath", "Selected subject path <subjectPath>.", "subjectPath", "./MNE-sample-data/subjects");
    QCommandLineOption hemiOption("hemi", "Selected hemisphere <hemi>.", "hemi", "2");
    QCommandLineOption evokedSetNoOption("setNo", "The average <setNo> to pick (must match ID or comment).", "setNo", "1");

    parser.addOption(fwdFileOption);
    parser.addOption(evokedFileOption);
    parser.addOption(snrOption);
    parser.addOption(annotOption);
    parser.addOption(subjectOption);
    parser.addOption(subjectPathOption);
    parser.addOption(evokedSetNoOption);

    parser.process(app);

    //Parse inputs
    QFile t_fileFwd(parser.value(fwdFileOption));
    QFile t_fileEvoked(parser.value(evokedFileOption));

    // Load data
    QPair<QVariant, QVariant> baseline(QVariant(), 0);
    FiffEvoked evoked(t_fileEvoked, parser.value(evokedSetNoOption).toInt(), baseline);
    if(evoked.isEmpty())
        return 1;

    std::cout << "evoked first " << evoked.first << "; last " << evoked.last << std::endl;

    MNEForwardSolution t_Fwd(t_fileFwd);
    if(t_Fwd.isEmpty())
        return 1;

    AnnotationSet t_annotationSet (parser.value(subjectOption), parser.value(hemiOption).toInt(), parser.value(annotOption), parser.value(subjectPathOption));

    //
    // Cluster forward solution;
    //
    MNEForwardSolution t_clusteredFwd = t_Fwd.cluster_forward_solution(t_annotationSet, 20);//40);

    return app.exec();//1;
}
<|endoftext|>


<commit_before>#include "rubymotion.h"
#include "motion-game.h"

/// @class Director < Object
/// Director is a shared object that takes care of the scene graph.

VALUE rb_cDirector = Qnil;
static VALUE mc_director_instance = Qnil;
static VALUE director_using_scene = Qnil;

/// @group Constructors

/// @method .shared
/// @return [Director] the shared Director instance.

static VALUE
director_instance(VALUE rcv, SEL sel)
{
    if (mc_director_instance == Qnil) {
	VALUE obj = rb_class_wrap_new(
	    (void *)cocos2d::Director::getInstance(), rb_cDirector);
	mc_director_instance = rb_retain(obj);
    }
    return mc_director_instance;
}

#if CC_TARGET_OS_IPHONE || CC_TARGET_OS_APPLETV
static VALUE
director_view_set(VALUE rcv, SEL sel, VALUE obj)
{
    cocos2d::GLView *glview =
	cocos2d::GLViewImpl::createWithEAGLView((void *)obj);
    DIRECTOR(rcv)->setOpenGLView(glview);
    return obj;
}

static VALUE
director_view_get(VALUE rcv, SEL sel)
{
    return (VALUE)DIRECTOR(rcv)->getOpenGLView()->getEAGLView();
}
#endif

/// @group Managing Scenes

/// @method #run(scene)
/// Runs the given scene object.
/// @param scene [Scene] the scene to run.
/// @return [Director] the receiver.

static VALUE
director_run(VALUE rcv, SEL sel, VALUE obj)
{
    director_using_scene = rb_retain(obj);
    DIRECTOR(rcv)->runWithScene(rb_any_to_scene(obj));
    return rcv;
}

/// @method #replace(scene)
/// Replaces the current scene with a new one. The running scene will be
/// terminated.
/// @param scene [Scene] the scene to replace the current one with.
/// @return [Director] the receiver.

static VALUE
director_replace(VALUE rcv, SEL sel, VALUE obj)
{
    rb_release(director_using_scene);
    director_using_scene = rb_retain(obj);
    DIRECTOR(rcv)->replaceScene(rb_any_to_scene(obj));
    return rcv;
}

/// @method #push(scene)
/// Suspends the execution of the running scene, and starts running the given
/// scene instead.
/// @param scene [Scene] the new scene to run.
/// @return [Director] the receiver.

static VALUE
director_push(VALUE rcv, SEL sel, VALUE obj)
{
    DIRECTOR(rcv)->pushScene(rb_any_to_scene(obj));
    return rcv;
}

/// @method #pop
/// Pops the running scene from the stack, and starts running the previous
/// scene. If there are no more scenes to run, the execution will be stopped.
/// @return [Director] the receiver.

static VALUE
director_pop(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->popScene();
    return rcv;
}

/// @method #end
/// Ends the execution of the running scene.
/// @return [Director] the receiver.

static VALUE
director_end(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->end();
    return rcv;
}

/// @method #pause
/// Pauses the execution of the running scene.
/// @return [Director] the receiver.

static VALUE
director_pause(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->pause();
    return rcv;
}

/// @method #resume
/// Resumes the execution of the current paused scene.
/// @return [Director] the receiver.

static VALUE
director_resume(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->resume();
    return rcv;
}

/// @method #start_animation
/// The main loop is triggered again.
/// @return [Director] the receiver.

static VALUE
director_start_animation(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->startAnimation();
    return rcv;
}

/// @method #stop_animation
/// Stops the animation.
/// @return [Director] the receiver.

static VALUE
director_stop_animation(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->stopAnimation();
    return rcv;
}

/// @group Properties

/// @property-readonly #origin
/// @return [Point] the visible origin of the director view in points.

static VALUE
director_origin(VALUE rcv, SEL sel)
{
    return rb_ccvec2_to_obj(DIRECTOR(rcv)->getVisibleOrigin());
}

/// @property-readonly #size
/// @return [Size] the visible size of the director view in points.

static VALUE
director_size(VALUE rcv, SEL sel)
{
    return rb_ccsize_to_obj(DIRECTOR(rcv)->getVisibleSize());
}

/// @property #show_stats?
/// Controls whether the FPS (frame-per-second) statistic label is displayed
/// in the bottom-left corner of the director view. By default it is hidden.
/// @return [Boolean] whether the FPS label is displayed.

static VALUE
director_show_stats_set(VALUE rcv, SEL sel, VALUE val)
{
    DIRECTOR(rcv)->setDisplayStats(RTEST(val));
    return val;
}

static VALUE
director_show_stats(VALUE rcv, SEL sel)
{
    return DIRECTOR(rcv)->isDisplayStats() ? Qtrue : Qfalse;
}

extern "C"
void
Init_Director(void)
{
    rb_cDirector = rb_define_class_under(rb_mMC, "Director", rb_cObject);

    rb_define_singleton_method(rb_cDirector, "shared", director_instance, 0);
    rb_define_method(rb_cDirector, "run", director_run, 1);
    rb_define_method(rb_cDirector, "replace", director_replace, 1);
    rb_define_method(rb_cDirector, "push", director_push, 1);
    rb_define_method(rb_cDirector, "pop", director_pop, 0);
    rb_define_method(rb_cDirector, "end", director_end, 0);
    rb_define_method(rb_cDirector, "pause", director_pause, 0);
    rb_define_method(rb_cDirector, "resume", director_resume, 0);
    rb_define_method(rb_cDirector, "start_animation", director_start_animation, 0);
    rb_define_method(rb_cDirector, "stop_animation", director_stop_animation, 0);
    rb_define_method(rb_cDirector, "origin", director_origin, 0);
    rb_define_method(rb_cDirector, "size", director_size, 0);
    rb_define_method(rb_cDirector, "show_stats=", director_show_stats_set, 1);
    rb_define_method(rb_cDirector, "show_stats?", director_show_stats, 0);

    // Internal.
#if CC_TARGET_OS_IPHONE || CC_TARGET_OS_APPLETV
    rb_define_method(rb_cDirector, "_set_glview", director_view_set, 1);
    rb_define_method(rb_cDirector, "_get_glview", director_view_get, 0);
#endif
}
<commit_msg>[fix #59] better handling for keeping a scene instance<commit_after>#include "rubymotion.h"
#include "motion-game.h"

/// @class Director < Object
/// Director is a shared object that takes care of the scene graph.

VALUE rb_cDirector = Qnil;
static VALUE mc_director_instance = Qnil;
static std::vector<VALUE> director_using_scene(3);

/// @group Constructors

/// @method .shared
/// @return [Director] the shared Director instance.

static VALUE
director_instance(VALUE rcv, SEL sel)
{
    if (mc_director_instance == Qnil) {
	VALUE obj = rb_class_wrap_new(
	    (void *)cocos2d::Director::getInstance(), rb_cDirector);
	mc_director_instance = rb_retain(obj);
    }
    return mc_director_instance;
}

#if CC_TARGET_OS_IPHONE || CC_TARGET_OS_APPLETV
static VALUE
director_view_set(VALUE rcv, SEL sel, VALUE obj)
{
    cocos2d::GLView *glview =
	cocos2d::GLViewImpl::createWithEAGLView((void *)obj);
    DIRECTOR(rcv)->setOpenGLView(glview);
    return obj;
}

static VALUE
director_view_get(VALUE rcv, SEL sel)
{
    return (VALUE)DIRECTOR(rcv)->getOpenGLView()->getEAGLView();
}
#endif

/// @group Managing Scenes

/// @method #run(scene)
/// Runs the given scene object.
/// @param scene [Scene] the scene to run.
/// @return [Director] the receiver.

static VALUE
director_run(VALUE rcv, SEL sel, VALUE obj)
{
    director_using_scene[0] = rb_retain(obj);
    DIRECTOR(rcv)->runWithScene(rb_any_to_scene(obj));
    return rcv;
}

/// @method #replace(scene)
/// Replaces the current scene with a new one. The running scene will be
/// terminated.
/// @param scene [Scene] the scene to replace the current one with.
/// @return [Director] the receiver.

static VALUE
director_replace(VALUE rcv, SEL sel, VALUE obj)
{
    rb_release(director_using_scene[0]);
    director_using_scene[0] = rb_retain(obj);
    DIRECTOR(rcv)->replaceScene(rb_any_to_scene(obj));
    return rcv;
}

/// @method #push(scene)
/// Suspends the execution of the running scene, and starts running the given
/// scene instead.
/// @param scene [Scene] the new scene to run.
/// @return [Director] the receiver.

static VALUE
director_push(VALUE rcv, SEL sel, VALUE obj)
{
    director_using_scene.push_back(rb_retain(obj));
    DIRECTOR(rcv)->pushScene(rb_any_to_scene(obj));
    return rcv;
}

/// @method #pop
/// Pops the running scene from the stack, and starts running the previous
/// scene. If there are no more scenes to run, the execution will be stopped.
/// @return [Director] the receiver.

static VALUE
director_pop(VALUE rcv, SEL sel)
{
    VALUE last_scene = director_using_scene.back();
    director_using_scene.pop_back();
    rb_release(last_scene);
    DIRECTOR(rcv)->popScene();
    return rcv;
}

/// @method #end
/// Ends the execution of the running scene.
/// @return [Director] the receiver.

static VALUE
director_end(VALUE rcv, SEL sel)
{
    for (auto iter = director_using_scene.begin();
	 iter != director_using_scene.end(); ++iter) {
	if (*iter != 0) {
	    rb_release(*iter);
	    *iter = 0;
	}
    }
    DIRECTOR(rcv)->end();
    return rcv;
}

/// @method #pause
/// Pauses the execution of the running scene.
/// @return [Director] the receiver.

static VALUE
director_pause(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->pause();
    return rcv;
}

/// @method #resume
/// Resumes the execution of the current paused scene.
/// @return [Director] the receiver.

static VALUE
director_resume(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->resume();
    return rcv;
}

/// @method #start_animation
/// The main loop is triggered again.
/// @return [Director] the receiver.

static VALUE
director_start_animation(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->startAnimation();
    return rcv;
}

/// @method #stop_animation
/// Stops the animation.
/// @return [Director] the receiver.

static VALUE
director_stop_animation(VALUE rcv, SEL sel)
{
    DIRECTOR(rcv)->stopAnimation();
    return rcv;
}

/// @group Properties

/// @property-readonly #origin
/// @return [Point] the visible origin of the director view in points.

static VALUE
director_origin(VALUE rcv, SEL sel)
{
    return rb_ccvec2_to_obj(DIRECTOR(rcv)->getVisibleOrigin());
}

/// @property-readonly #size
/// @return [Size] the visible size of the director view in points.

static VALUE
director_size(VALUE rcv, SEL sel)
{
    return rb_ccsize_to_obj(DIRECTOR(rcv)->getVisibleSize());
}

/// @property #show_stats?
/// Controls whether the FPS (frame-per-second) statistic label is displayed
/// in the bottom-left corner of the director view. By default it is hidden.
/// @return [Boolean] whether the FPS label is displayed.

static VALUE
director_show_stats_set(VALUE rcv, SEL sel, VALUE val)
{
    DIRECTOR(rcv)->setDisplayStats(RTEST(val));
    return val;
}

static VALUE
director_show_stats(VALUE rcv, SEL sel)
{
    return DIRECTOR(rcv)->isDisplayStats() ? Qtrue : Qfalse;
}

extern "C"
void
Init_Director(void)
{
    rb_cDirector = rb_define_class_under(rb_mMC, "Director", rb_cObject);

    rb_define_singleton_method(rb_cDirector, "shared", director_instance, 0);
    rb_define_method(rb_cDirector, "run", director_run, 1);
    rb_define_method(rb_cDirector, "replace", director_replace, 1);
    rb_define_method(rb_cDirector, "push", director_push, 1);
    rb_define_method(rb_cDirector, "pop", director_pop, 0);
    rb_define_method(rb_cDirector, "end", director_end, 0);
    rb_define_method(rb_cDirector, "pause", director_pause, 0);
    rb_define_method(rb_cDirector, "resume", director_resume, 0);
    rb_define_method(rb_cDirector, "start_animation", director_start_animation, 0);
    rb_define_method(rb_cDirector, "stop_animation", director_stop_animation, 0);
    rb_define_method(rb_cDirector, "origin", director_origin, 0);
    rb_define_method(rb_cDirector, "size", director_size, 0);
    rb_define_method(rb_cDirector, "show_stats=", director_show_stats_set, 1);
    rb_define_method(rb_cDirector, "show_stats?", director_show_stats, 0);

    // Internal.
#if CC_TARGET_OS_IPHONE || CC_TARGET_OS_APPLETV
    rb_define_method(rb_cDirector, "_set_glview", director_view_set, 1);
    rb_define_method(rb_cDirector, "_get_glview", director_view_get, 0);
#endif
}
<|endoftext|>


<commit_before>
#include "types.h"
#include "depthmap.cc"

namespace csfm {

class DepthmapEstimatorWrapper {
 public:
  void AddView(PyObject *K,
               PyObject *R,
               PyObject *t,
               PyObject *image) {
    PyArrayContiguousView<double> K_view((PyArrayObject *)K);
    PyArrayContiguousView<double> R_view((PyArrayObject *)R);
    PyArrayContiguousView<double> t_view((PyArrayObject *)t);
    PyArrayContiguousView<unsigned char> image_view((PyArrayObject *)image);
    de_.AddView(K_view.data(), R_view.data(), t_view.data(),
                image_view.data(), image_view.shape(1), image_view.shape(0));
  }

  void SetDepthRange(double min_depth, double max_depth, int num_depth_planes) {
    de_.SetDepthRange(min_depth, max_depth, num_depth_planes);
  }

  void SetPatchMatchIterations(int n) {
    de_.SetPatchMatchIterations(n);
  }

  void SetMinPatchSD(float sd) {
    de_.SetMinPatchSD(sd);
  }

  bp::object ComputePatchMatch() {
    cv::Mat depth, plane, score, nghbr;
    de_.ComputePatchMatch(&depth, &plane, &score, &nghbr);
    return ComputeReturnValues(depth, plane, score, nghbr);
  }

  bp::object ComputePatchMatchSample() {
    cv::Mat depth, plane, score, nghbr;
    de_.ComputePatchMatchSample(&depth, &plane, &score, &nghbr);
    return ComputeReturnValues(depth, plane, score, nghbr);
  }

  bp::object ComputeBruteForce() {
    cv::Mat depth, plane, score, nghbr;
    de_.ComputeBruteForce(&depth, &plane, &score, &nghbr);
    return ComputeReturnValues(depth, plane, score, nghbr);
  }

  bp::object ComputeReturnValues(const cv::Mat &depth,
                                 const cv::Mat &plane,
                                 const cv::Mat &score,
                                 const cv::Mat &nghbr) {
    bp::list retn;
    npy_intp shape[2] = {depth.rows, depth.cols};
    npy_intp plane_shape[3] = {depth.rows, depth.cols, 3};
    retn.append(bpn_array_from_data(2, shape, depth.ptr<float>(0)));
    retn.append(bpn_array_from_data(3, plane_shape, plane.ptr<float>(0)));
    retn.append(bpn_array_from_data(2, shape, score.ptr<float>(0)));
    retn.append(bpn_array_from_data(2, shape, nghbr.ptr<int>(0)));
    return retn;
  }

 private:
  DepthmapEstimator de_;
};

class DepthmapCleanerWrapper {
 public:
  void SetSameDepthThreshold(float t) {
    dc_.SetSameDepthThreshold(t);
  }

  void SetMinConsistentViews(int n) {
    dc_.SetMinConsistentViews(n);
  }

  void AddView(PyObject *K,
               PyObject *R,
               PyObject *t,
               PyObject *depth) {
    PyArrayContiguousView<double> K_view((PyArrayObject *)K);
    PyArrayContiguousView<double> R_view((PyArrayObject *)R);
    PyArrayContiguousView<double> t_view((PyArrayObject *)t);
    PyArrayContiguousView<float> depth_view((PyArrayObject *)depth);
    dc_.AddView(K_view.data(), R_view.data(), t_view.data(),
                depth_view.data(), depth_view.shape(1), depth_view.shape(0));
  }

  bp::object Clean() {
    cv::Mat depth;
    dc_.Clean(&depth);
    npy_intp shape[2] = {depth.rows, depth.cols};
    return bpn_array_from_data(2, shape, depth.ptr<float>(0));
  }

 private:
  DepthmapCleaner dc_;
};

class DepthmapPrunerWrapper {
 public:
  void SetSameDepthThreshold(float t) {
    dp_.SetSameDepthThreshold(t);
  }

  void AddView(PyObject *K,
               PyObject *R,
               PyObject *t,
               PyObject *depth,
               PyObject *normal,
               PyObject *label,
               PyObject *color) {
    PyArrayContiguousView<double> K_view((PyArrayObject *)K);
    PyArrayContiguousView<double> R_view((PyArrayObject *)R);
    PyArrayContiguousView<double> t_view((PyArrayObject *)t);
    PyArrayContiguousView<float> depth_view((PyArrayObject *)depth);
    PyArrayContiguousView<float> plane_view((PyArrayObject *)normal);
    PyArrayContiguousView<unsigned char> color_view((PyArrayObject *)color);
    PyArrayContiguousView<unsigned char> label_view((PyArrayObject *)label);
    dp_.AddView(K_view.data(), R_view.data(), t_view.data(),
                depth_view.data(), plane_view.data(),
                color_view.data(), label_view.data(),
                depth_view.shape(1), depth_view.shape(0));
  }

  bp::object Prune() {
    std::vector<float> points;
    std::vector<float> normals;
    std::vector<unsigned char> colors;
    std::vector<unsigned char> labels;

    dp_.Prune(&points, &normals, &colors, &labels);

    bp::list retn;
    npy_intp shape3[2] = {int(points.size()) / 3, 3};
    npy_intp shape1[1] = {int(points.size()) / 3};
    retn.append(bpn_array_from_data(2, shape3, &points[0]));
    retn.append(bpn_array_from_data(2, shape3, &normals[0]));
    retn.append(bpn_array_from_data(2, shape3, &colors[0]));
    retn.append(bpn_array_from_data(1, shape1, &labels[0]));
    return retn;
  }

 private:
  DepthmapPruner dp_;
};

}

<commit_msg>fix(dense): argument order<commit_after>
#include "types.h"
#include "depthmap.cc"

namespace csfm {

class DepthmapEstimatorWrapper {
 public:
  void AddView(PyObject *K,
               PyObject *R,
               PyObject *t,
               PyObject *image) {
    PyArrayContiguousView<double> K_view((PyArrayObject *)K);
    PyArrayContiguousView<double> R_view((PyArrayObject *)R);
    PyArrayContiguousView<double> t_view((PyArrayObject *)t);
    PyArrayContiguousView<unsigned char> image_view((PyArrayObject *)image);
    de_.AddView(K_view.data(), R_view.data(), t_view.data(),
                image_view.data(), image_view.shape(1), image_view.shape(0));
  }

  void SetDepthRange(double min_depth, double max_depth, int num_depth_planes) {
    de_.SetDepthRange(min_depth, max_depth, num_depth_planes);
  }

  void SetPatchMatchIterations(int n) {
    de_.SetPatchMatchIterations(n);
  }

  void SetMinPatchSD(float sd) {
    de_.SetMinPatchSD(sd);
  }

  bp::object ComputePatchMatch() {
    cv::Mat depth, plane, score, nghbr;
    de_.ComputePatchMatch(&depth, &plane, &score, &nghbr);
    return ComputeReturnValues(depth, plane, score, nghbr);
  }

  bp::object ComputePatchMatchSample() {
    cv::Mat depth, plane, score, nghbr;
    de_.ComputePatchMatchSample(&depth, &plane, &score, &nghbr);
    return ComputeReturnValues(depth, plane, score, nghbr);
  }

  bp::object ComputeBruteForce() {
    cv::Mat depth, plane, score, nghbr;
    de_.ComputeBruteForce(&depth, &plane, &score, &nghbr);
    return ComputeReturnValues(depth, plane, score, nghbr);
  }

  bp::object ComputeReturnValues(const cv::Mat &depth,
                                 const cv::Mat &plane,
                                 const cv::Mat &score,
                                 const cv::Mat &nghbr) {
    bp::list retn;
    npy_intp shape[2] = {depth.rows, depth.cols};
    npy_intp plane_shape[3] = {depth.rows, depth.cols, 3};
    retn.append(bpn_array_from_data(2, shape, depth.ptr<float>(0)));
    retn.append(bpn_array_from_data(3, plane_shape, plane.ptr<float>(0)));
    retn.append(bpn_array_from_data(2, shape, score.ptr<float>(0)));
    retn.append(bpn_array_from_data(2, shape, nghbr.ptr<int>(0)));
    return retn;
  }

 private:
  DepthmapEstimator de_;
};

class DepthmapCleanerWrapper {
 public:
  void SetSameDepthThreshold(float t) {
    dc_.SetSameDepthThreshold(t);
  }

  void SetMinConsistentViews(int n) {
    dc_.SetMinConsistentViews(n);
  }

  void AddView(PyObject *K,
               PyObject *R,
               PyObject *t,
               PyObject *depth) {
    PyArrayContiguousView<double> K_view((PyArrayObject *)K);
    PyArrayContiguousView<double> R_view((PyArrayObject *)R);
    PyArrayContiguousView<double> t_view((PyArrayObject *)t);
    PyArrayContiguousView<float> depth_view((PyArrayObject *)depth);
    dc_.AddView(K_view.data(), R_view.data(), t_view.data(),
                depth_view.data(), depth_view.shape(1), depth_view.shape(0));
  }

  bp::object Clean() {
    cv::Mat depth;
    dc_.Clean(&depth);
    npy_intp shape[2] = {depth.rows, depth.cols};
    return bpn_array_from_data(2, shape, depth.ptr<float>(0));
  }

 private:
  DepthmapCleaner dc_;
};

class DepthmapPrunerWrapper {
 public:
  void SetSameDepthThreshold(float t) {
    dp_.SetSameDepthThreshold(t);
  }

  void AddView(PyObject *K,
               PyObject *R,
               PyObject *t,
               PyObject *depth,
               PyObject *normal,
               PyObject *color,
               PyObject *label) {
    PyArrayContiguousView<double> K_view((PyArrayObject *)K);
    PyArrayContiguousView<double> R_view((PyArrayObject *)R);
    PyArrayContiguousView<double> t_view((PyArrayObject *)t);
    PyArrayContiguousView<float> depth_view((PyArrayObject *)depth);
    PyArrayContiguousView<float> plane_view((PyArrayObject *)normal);
    PyArrayContiguousView<unsigned char> color_view((PyArrayObject *)color);
    PyArrayContiguousView<unsigned char> label_view((PyArrayObject *)label);
    dp_.AddView(K_view.data(), R_view.data(), t_view.data(),
                depth_view.data(), plane_view.data(),
                color_view.data(), label_view.data(),
                depth_view.shape(1), depth_view.shape(0));
  }

  bp::object Prune() {
    std::vector<float> points;
    std::vector<float> normals;
    std::vector<unsigned char> colors;
    std::vector<unsigned char> labels;

    dp_.Prune(&points, &normals, &colors, &labels);

    bp::list retn;
    npy_intp shape3[2] = {int(points.size()) / 3, 3};
    npy_intp shape1[1] = {int(points.size()) / 3};
    retn.append(bpn_array_from_data(2, shape3, &points[0]));
    retn.append(bpn_array_from_data(2, shape3, &normals[0]));
    retn.append(bpn_array_from_data(2, shape3, &colors[0]));
    retn.append(bpn_array_from_data(1, shape1, &labels[0]));
    return retn;
  }

 private:
  DepthmapPruner dp_;
};

}

<|endoftext|>


<commit_before>#include <download.h>
#include <pb_controller.h>
#include <config.h>
#include <string>

namespace podbeuter {

download::download(pb_controller * c) : dlstatus(DL_QUEUED), cursize(0), totalsize(0), ctrl(c) {
}

download::~download() {
}

const char * download::filename() {
	return fn.c_str();
}

const char * download::url() {
	return url_.c_str();
}

void download::set_filename(const std::string& str) {
	fn = str;
}

double download::percents_finished() {
	if (totalsize < 1) {
		return 0.0;
	} else {
		return (100*(offs + cursize))/totalsize;
	}
}

const char * download::status_text() {
	switch (dlstatus) {
		case DL_QUEUED:
			return _("queued");
		case DL_DOWNLOADING:
			return _("downloading");
		case DL_CANCELLED:
			return _("cancelled");
		case DL_DELETED:
			return _("deleted");
		case DL_FINISHED:
			return _("finished");
		case DL_FAILED:
			return _("failed");
		case DL_ALREADY_DOWNLOADED:
			return _("incomplete");
		default:
			return _("unknown (bug).");
	}
}

void download::set_url(const std::string& url) {
	url_ = url;
}

void download::set_progress(double cur, double max) {
	if (cur > cursize)
		ctrl->set_view_update_necessary(true);
	cursize = cur;
	totalsize = max;
}

void download::set_status(dlstatus_t dls) {
	if (dlstatus != dls) {
		ctrl->set_view_update_necessary(true);
	}
	dlstatus = dls;
}

void download::set_kbps(double kbps) {
	curkbps = kbps;
}

double download::kbps() {
	return curkbps;
}

void download::set_offset(unsigned long offset) {
	offs = offset;
}

}
<commit_msg>Andreas Krennmair: 	correctly add offset (otherwise we get e.g. 108 % finished...)<commit_after>#include <download.h>
#include <pb_controller.h>
#include <config.h>
#include <string>

namespace podbeuter {

download::download(pb_controller * c) : dlstatus(DL_QUEUED), cursize(0), totalsize(0), ctrl(c) {
}

download::~download() {
}

const char * download::filename() {
	return fn.c_str();
}

const char * download::url() {
	return url_.c_str();
}

void download::set_filename(const std::string& str) {
	fn = str;
}

double download::percents_finished() {
	if (totalsize < 1) {
		return 0.0;
	} else {
		return (100*(offs + cursize))/(offs + totalsize);
	}
}

const char * download::status_text() {
	switch (dlstatus) {
		case DL_QUEUED:
			return _("queued");
		case DL_DOWNLOADING:
			return _("downloading");
		case DL_CANCELLED:
			return _("cancelled");
		case DL_DELETED:
			return _("deleted");
		case DL_FINISHED:
			return _("finished");
		case DL_FAILED:
			return _("failed");
		case DL_ALREADY_DOWNLOADED:
			return _("incomplete");
		default:
			return _("unknown (bug).");
	}
}

void download::set_url(const std::string& url) {
	url_ = url;
}

void download::set_progress(double cur, double max) {
	if (cur > cursize)
		ctrl->set_view_update_necessary(true);
	cursize = cur;
	totalsize = max;
}

void download::set_status(dlstatus_t dls) {
	if (dlstatus != dls) {
		ctrl->set_view_update_necessary(true);
	}
	dlstatus = dls;
}

void download::set_kbps(double kbps) {
	curkbps = kbps;
}

double download::kbps() {
	return curkbps;
}

void download::set_offset(unsigned long offset) {
	offs = offset;
}

}
<|endoftext|>


<commit_before>#ifndef __RANK_FILTER__
#define __RANK_FILTER__

#include <list>
#include <set>
#include <cmath>
#include <cassert>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <utility>

#include <vigra/multi_array.hxx>
#include <vigra/linear_algebra.hxx>

namespace vigra
{

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N == 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = N - 1)
{
    // Will ignore boundaries initially.
    // Then will try adding reflection.

    // Rank must be in the range 0 to 1
    assert((0 <= rank) && (rank <= 1));

    const int rank_pos = round(rank * (2 * half_length));

    // The position of the
    typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 window_begin(0);
    std::multiset<T1> sorted_window;
    std::list< typename std::multiset<T1>::iterator > window_iters;

    // Get the initial sorted window.
    // Include the reflection.
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(half_length); j > 0; j--)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(0); j <= half_length; j++)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }

    typename std::multiset<T1>::iterator rank_point = sorted_window.begin();

    for (int i = 0; i < rank_pos; i++)
    {
        rank_point++;
    }

    while ( window_begin < src.size() )
    {
        dest[window_begin] = *rank_point;

        typename std::multiset<T1>::iterator prev_iter(window_iters.front());
        T1 prev_value = *prev_iter;
        window_iters.pop_front();

        window_begin++;

        T1 next_value;
        if ( window_begin < (src.size() - half_length) )
        {
            next_value = src[window_begin + half_length];
        }
        else
        {
            next_value = src[2 * src.size() - (window_begin + half_length + 2)];
        }

        if ( ( *rank_point < *prev_iter ) && ( *rank_point <= next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
        }
        else if ( ( *rank_point >= *prev_iter ) && ( *rank_point > next_value ) )
        {
            if ( rank_point == prev_iter )
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point--;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
            }
        }
        else if ( ( *rank_point < *prev_iter ) && ( *rank_point > next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));

            rank_point--;
        }
        else if ( ( *rank_point >= *prev_iter ) && ( *rank_point <= next_value ) )
        {
            if (rank_point == prev_iter)
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));

                rank_point++;
            }
        }
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N > 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = N - 1)
{
    typename vigra::MultiArrayView<N, T1, S1>::difference_type transposed_axes;

    for (unsigned int i = 0; i < N; i++)
    {
        transposed_axes[i] = i;
    }

    std::swap(transposed_axes[N - 1], transposed_axes[axis]);

    vigra::MultiArray<N, T1> src_transposed(src.transpose(transposed_axes));

    vigra::MultiArrayView<N, T1, S1> dest_transposed(dest.transpose(transposed_axes));

    typename vigra::MultiArrayView<N - 1, T1, S1>::difference_type pos;
    pos = 0;

    bool done = false;

    while (!done)
    {
        lineRankOrderFilterND(src_transposed.bindInner(pos), dest_transposed.bindInner(pos), half_length, rank);

        bool carry = true;
        for (unsigned int i = 0; ( carry && (i < (N - 1)) ); i++)
        {
            if ( (++pos[N - (i + 2)]) < src_transposed.shape(N - (i + 2)) )
            {
                carry = false;
            }
            else
            {
                pos[N - (i + 2)] = 0;
                carry = true;
            }
        }

        done = carry;
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2>
inline void lineRankOrderFilter(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = N - 1)
{
    lineRankOrderFilterND(src, dest, half_length, rank, axis);
}

}

#endif //__RANK_FILTER__
<commit_msg>rank_filter.hxx: Corrected to use Fortran-order index with VIGRA.<commit_after>#ifndef __RANK_FILTER__
#define __RANK_FILTER__

#include <list>
#include <set>
#include <cmath>
#include <cassert>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <utility>

#include <vigra/multi_array.hxx>
#include <vigra/linear_algebra.hxx>

namespace vigra
{

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N == 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = 0)
{
    // Will ignore boundaries initially.
    // Then will try adding reflection.

    // Rank must be in the range 0 to 1
    assert((0 <= rank) && (rank <= 1));

    const int rank_pos = round(rank * (2 * half_length));

    // The position of the
    typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 window_begin(0);
    std::multiset<T1> sorted_window;
    std::list< typename std::multiset<T1>::iterator > window_iters;

    // Get the initial sorted window.
    // Include the reflection.
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(half_length); j > 0; j--)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }
    for (typename vigra::MultiArrayView<N, T1, S1>::difference_type_1 j(0); j <= half_length; j++)
    {
        window_iters.push_back(sorted_window.insert(src[window_begin + j]));
    }

    typename std::multiset<T1>::iterator rank_point = sorted_window.begin();

    for (int i = 0; i < rank_pos; i++)
    {
        rank_point++;
    }

    while ( window_begin < src.size() )
    {
        dest[window_begin] = *rank_point;

        typename std::multiset<T1>::iterator prev_iter(window_iters.front());
        T1 prev_value = *prev_iter;
        window_iters.pop_front();

        window_begin++;

        T1 next_value;
        if ( window_begin < (src.size() - half_length) )
        {
            next_value = src[window_begin + half_length];
        }
        else
        {
            next_value = src[2 * src.size() - (window_begin + half_length + 2)];
        }

        if ( ( *rank_point < *prev_iter ) && ( *rank_point <= next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));
        }
        else if ( ( *rank_point >= *prev_iter ) && ( *rank_point > next_value ) )
        {
            if ( rank_point == prev_iter )
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point--;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));
            }
        }
        else if ( ( *rank_point < *prev_iter ) && ( *rank_point > next_value ) )
        {
            sorted_window.erase(prev_iter);
            window_iters.push_back(sorted_window.insert(next_value));

            rank_point--;
        }
        else if ( ( *rank_point >= *prev_iter ) && ( *rank_point <= next_value ) )
        {
            if (rank_point == prev_iter)
            {
                window_iters.push_back(sorted_window.insert(next_value));
                rank_point++;

                sorted_window.erase(prev_iter);
            }
            else
            {
                sorted_window.erase(prev_iter);
                window_iters.push_back(sorted_window.insert(next_value));

                rank_point++;
            }
        }
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2,
        typename std::enable_if<(N > 1), int>::type = 0>
inline void lineRankOrderFilterND(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = 0)
{
    typename vigra::MultiArrayView<N, T1, S1>::difference_type transposed_axes;

    for (unsigned int i = 0; i < N; i++)
    {
        transposed_axes[i] = i;
    }

    std::swap(transposed_axes[0], transposed_axes[axis]);

    vigra::MultiArray<N, T1> src_transposed(src.transpose(transposed_axes));

    vigra::MultiArrayView<N, T1, S1> dest_transposed(dest.transpose(transposed_axes));

    typename vigra::MultiArrayView<N - 1, T1, S1>::difference_type pos;
    pos = 0;

    bool done = false;

    while (!done)
    {
        lineRankOrderFilterND(src_transposed.bindOuter(pos), dest_transposed.bindOuter(pos), half_length, rank);

        bool carry = true;
        for (unsigned int i = 1; ( carry && (i < N) ); i++)
        {
            if ( (++pos[i]) < src_transposed.shape(i) )
            {
                carry = false;
            }
            else
            {
                pos[i] = 0;
                carry = true;
            }
        }

        done = carry;
    }
}

template<unsigned int N,
        class T1, class S1,
        class T2, class S2>
inline void lineRankOrderFilter(const vigra::MultiArrayView <N, T1, S1> &src,
        vigra::MultiArrayView <N, T2, S2> dest,
        unsigned int half_length, float rank, unsigned int axis = 0)
{
    lineRankOrderFilterND(src, dest, half_length, rank, axis);
}

}

#endif //__RANK_FILTER__
<|endoftext|>


<commit_before>#include "tags.h"

#include <0mq/context.h>
#include <0mq/socket.h>
#include <0mq/message.h>
#include <0mq/poller.h>

#include <iostream>
#include <cstddef>
#include <chrono>
#include <thread>
#include <list>
#include <unordered_map>
#include <cassert>

typedef std::size_t jobid_type;
typedef std::chrono::time_point<std::chrono::steady_clock> timepoint_type;
typedef std::list<std::size_t> waitingjobs_type;
typedef std::unordered_map<std::size_t, timepoint_type> busyjobs_type;

class ClientApplication {
  public:
    ClientApplication()
    : context_(), clientSocket_() {
    }

    ~ClientApplication() {
    }

    void init() {
      connect();
    }

    std::vector<zmq::Message> map(const std::vector<zmq::Message>& mapData) {
      std::size_t interval = intervalInit_;

      waitingjobs_type waitingJobs;
      busyjobs_type busyJobs;

      std::size_t unfinishedJobCount = mapData.size();
      for (std::size_t i = 0; i < unfinishedJobCount; ++i) {
        waitingJobs.push_back(i);
      }

      std::vector<zmq::Message> mappedData(unfinishedJobCount);

      while (unfinishedJobCount > 0) {
        requestJob(mapData, waitingJobs, busyJobs);

        std::vector<zmq::Socket> items = { clientSocket_ };

        std::vector<short> state = zmq::poll(items, heartbeatInterval_);

        if (state[0] & ZMQ_POLLIN) {
          zmq::Socket::messages_type messages = clientSocket_.receive();

          const std::size_t messageSize = messages.size();

          // check if we got a valid message
          if (messageSize < 2) {
            throw std::runtime_error("ClientApplication::go: got interrupted or "
                "got invalid message");
          }

          zmq::Socket::messages_type::iterator messagePtr =
            messages.begin();
          const zmq::Message& tag = *messagePtr++;
          jobid_type jobID = (*messagePtr++).data()[0];

          if (tag.size() != 1) {
            throw std::runtime_error("WorkerApplication::go: invalid tag size");
          }

          if (busyJobs.find(jobID) == busyJobs.end()) {
            std::cout << "WorkerApplication::go: invalid job id" << std::endl;
          }

          switch (tag.data()[0]) {
            case JOB_WAIT:
              // queue is busy; sleep and try again
              std::cout << "queue is full" << std::endl;

              handleJobWait(jobID, waitingJobs, busyJobs);

              std::this_thread::sleep_for(std::chrono::milliseconds(100));
              break;
            case JOB_QUEUED:
              // do nothing
              std::cout << "queued" << std::endl;

              updateJob(jobID, busyJobs);
              break;
            case JOB_BUSY:
              // do nothing
              std::cout << "busy" << std::endl;

              updateJob(jobID, busyJobs);
              break;
            case JOB_DONE:
              std::cout << "done" << std::endl;

              if (messageSize != 3) {
                throw std::runtime_error("WorkerApplication::go: invalid done message");
              }

              mappedData[jobID] == *messagePtr;
              handleJobDone(jobID, busyJobs);
              --unfinishedJobCount;
              break;
            default:
              throw std::runtime_error("ClientApplication::go: invalid job tag");
          }
        }

        if (false) {
          std::cout << "W: heartbeat failure, can't reach queue or worker "
            "died" << std::endl;
          std::cout << "W: reconnecting in " << interval << " msec..." <<
            std::endl;

          std::this_thread::sleep_for(std::chrono::milliseconds(interval));

          if (interval < intervalMax_)
            interval *= 2;

          connect();
        }

        checkJobs(waitingJobs, busyJobs);
      }

      return mappedData;
    }

  private:
    void checkJobs(waitingjobs_type& waitingJobs, busyjobs_type& busyJobs) const {
      timepoint_type now = std::chrono::steady_clock::now();

      busyjobs_type::iterator jobIt = busyJobs.begin();
      while (jobIt != busyJobs.end()) {
        if (jobIt->second < now) {
          std::cout << "delete" << std::endl;
          waitingJobs.push_back(jobIt->first);
          jobIt = busyJobs.erase(jobIt);
        } else {
          ++jobIt;
        }
      }
    }

    void handleJobDone(const jobid_type jobID, busyjobs_type& busyJobs) const {
      busyJobs.erase(jobID);
    }

    void updateJob(const jobid_type jobID, busyjobs_type& busyJobs) const {
      busyJobs[jobID] = std::chrono::steady_clock::now() +
        std::chrono::milliseconds(jobbeatInterval_);
    }

    void handleJobWait(const jobid_type jobID, waitingjobs_type&
        waitingJobs, busyjobs_type& busyJobs) const {
      waitingJobs.push_back(jobID);
      busyJobs.erase(jobID);
    }

    void requestJob(const std::vector<zmq::Message>& mapData, waitingjobs_type&
        waitingJobs, busyjobs_type& busyJobs) {
      if (waitingJobs.empty())
        return;

      std::size_t jobID = waitingJobs.front();
      waitingJobs.pop_front();

      zmq::Message job(1);
      job.data()[0] = jobID;

      zmq::Socket::messages_type request;
      request.push_back(std::move(job));
      request.push_back(mapData[jobID]);

      clientSocket_.send(request);

      assert(busyJobs.find(jobID) == busyJobs.end());
      updateJob(jobID, busyJobs);
    }

    // do not copy
    ClientApplication(const ClientApplication&);

    void connect() {
      clientSocket_ = context_.createSocket(ZMQ_DEALER);
      clientSocket_.connect("tcp://localhost:5555");
    }

    const std::size_t heartbeatInterval_ = 1000;
    // the time that maximally may pass between to messages for a job beat
    const std::size_t jobbeatInterval_ = 3000;
    const std::size_t intervalInit_ = 1000;
    const std::size_t intervalMax_ = 32000;

    zmq::Context context_;
    zmq::Socket clientSocket_;
};

int main(int /*argc*/, const char** /*argv*/) {
  ClientApplication client;
  client.init();

  zmq::Message data(1);

  std::vector<zmq::Message> mapData;
  mapData.push_back(data);
  mapData.push_back(data);
  mapData.push_back(data);
  mapData.push_back(data);

  client.map(mapData);
}
<commit_msg>Fixes client for queue error.<commit_after>#include "tags.h"

#include <0mq/context.h>
#include <0mq/socket.h>
#include <0mq/message.h>
#include <0mq/poller.h>

#include <iostream>
#include <cstddef>
#include <chrono>
#include <thread>
#include <list>
#include <unordered_map>
#include <cassert>

typedef std::size_t jobid_type;
typedef std::chrono::time_point<std::chrono::steady_clock> timepoint_type;
typedef std::list<std::size_t> waitingjobs_type;
typedef std::unordered_map<std::size_t, timepoint_type> busyjobs_type;

class ClientApplication {
  public:
    ClientApplication()
    : context_(), clientSocket_() {
    }

    ~ClientApplication() {
    }

    void init() {
      connect();
    }

    std::vector<zmq::Message> map(const std::vector<zmq::Message>& mapData) {
      std::size_t liveness = heartbeatLiveness_;
      std::size_t interval = intervalInit_;

      waitingjobs_type waitingJobs;
      busyjobs_type busyJobs;

      std::size_t unfinishedJobCount = mapData.size();
      for (std::size_t i = 0; i < unfinishedJobCount; ++i) {
        waitingJobs.push_back(i);
      }

      std::vector<zmq::Message> mappedData(unfinishedJobCount);

      while (unfinishedJobCount > 0) {
        requestJob(mapData, waitingJobs, busyJobs);

        std::vector<zmq::Socket> items = { clientSocket_ };

        std::vector<short> state = zmq::poll(items, heartbeatInterval_);

        if (state[0] & ZMQ_POLLIN) {
          zmq::Socket::messages_type messages = clientSocket_.receive();

          const std::size_t messageSize = messages.size();

          // check if we got a valid message
          if (messageSize < 2) {
            throw std::runtime_error("ClientApplication::go: got interrupted or "
                "got invalid message");
          }

          zmq::Socket::messages_type::iterator messagePtr =
            messages.begin();
          const zmq::Message& tag = *messagePtr++;
          jobid_type jobID = (*messagePtr++).data()[0];

          if (tag.size() != 1) {
            throw std::runtime_error("WorkerApplication::go: invalid tag size");
          }

          if (busyJobs.find(jobID) == busyJobs.end()) {
            std::cout << "WorkerApplication::go: invalid job id" << std::endl;
          }

          liveness = heartbeatLiveness_;
          switch (tag.data()[0]) {
            case JOB_WAIT:
              // queue is busy; sleep and try again
              std::cout << "queue is full" << std::endl;

              handleJobWait(jobID, waitingJobs, busyJobs);

              std::this_thread::sleep_for(std::chrono::milliseconds(100));
              break;
            case JOB_QUEUED:
              // do nothing
              std::cout << "queued" << std::endl;

              updateJob(jobID, busyJobs);
              break;
            case JOB_BUSY:
              // do nothing
              std::cout << "busy" << std::endl;

              updateJob(jobID, busyJobs);
              break;
            case JOB_DONE:
              std::cout << "done" << std::endl;

              if (messageSize != 3) {
                throw std::runtime_error("WorkerApplication::go: invalid done message");
              }

              mappedData[jobID] == *messagePtr;
              handleJobDone(jobID, busyJobs);
              --unfinishedJobCount;
              break;
            default:
              throw std::runtime_error("ClientApplication::go: invalid job tag");
          }
        }

        if (--liveness == 0) {
          std::cout << "W: heartbeat failure, can't reach queue or worker "
            "died" << std::endl;
          std::cout << "W: reconnecting in " << interval << " msec..." <<
            std::endl;

          std::this_thread::sleep_for(std::chrono::milliseconds(interval));

          if (interval < intervalMax_)
            interval *= 2;

          // get all the busy jobs and push them back to the waitingJobs
          resetWaitingJobs(waitingJobs, busyJobs);

          connect();
          liveness = heartbeatLiveness_;
        }

        checkJobs(waitingJobs, busyJobs);
      }

      return mappedData;
    }

  private:
    void resetWaitingJobs(waitingjobs_type& waitingJobs, busyjobs_type& busyJobs) const {
      busyjobs_type::iterator jobIt = busyJobs.begin();
      while (jobIt != busyJobs.end()) {
        std::cout << "back" << std::endl;
        waitingJobs.push_back(jobIt->first);
        jobIt = busyJobs.erase(jobIt);
      }
    }

    void checkJobs(waitingjobs_type& waitingJobs, busyjobs_type& busyJobs) const {
      timepoint_type now = std::chrono::steady_clock::now();

      busyjobs_type::iterator jobIt = busyJobs.begin();
      while (jobIt != busyJobs.end()) {
        if (jobIt->second < now) {
          std::cout << "delete" << std::endl;
          waitingJobs.push_back(jobIt->first);
          jobIt = busyJobs.erase(jobIt);
        } else {
          ++jobIt;
        }
      }
    }

    void handleJobDone(const jobid_type jobID, busyjobs_type& busyJobs) const {
      busyJobs.erase(jobID);
    }

    void updateJob(const jobid_type jobID, busyjobs_type& busyJobs) const {
      busyJobs[jobID] = std::chrono::steady_clock::now() +
        std::chrono::milliseconds(jobbeatInterval_);
    }

    void handleJobWait(const jobid_type jobID, waitingjobs_type&
        waitingJobs, busyjobs_type& busyJobs) const {
      waitingJobs.push_back(jobID);
      busyJobs.erase(jobID);
    }

    void requestJob(const std::vector<zmq::Message>& mapData, waitingjobs_type&
        waitingJobs, busyjobs_type& busyJobs) {
      if (waitingJobs.empty())
        return;

      std::size_t jobID = waitingJobs.front();
      waitingJobs.pop_front();

      zmq::Message job(1);
      job.data()[0] = jobID;

      zmq::Socket::messages_type request;
      request.push_back(std::move(job));
      request.push_back(mapData[jobID]);

      clientSocket_.send(request);

      assert(busyJobs.find(jobID) == busyJobs.end());
      updateJob(jobID, busyJobs);
    }

    // do not copy
    ClientApplication(const ClientApplication&);

    void connect() {
      clientSocket_ = context_.createSocket(ZMQ_DEALER);
      clientSocket_.connect("tcp://localhost:5555");
    }

    // number of times we may reach the heartbeatInterval_ timeout without a
    // message from the queue
    const std::size_t heartbeatLiveness_ = 3;
    // maximal time we wait for messages from the queue
    const std::size_t heartbeatInterval_ = 1000;
    // the time that maximally may pass between to messages for a job beat
    const std::size_t jobbeatInterval_ = 3000;
    const std::size_t intervalInit_ = 1000;
    const std::size_t intervalMax_ = 32000;

    zmq::Context context_;
    zmq::Socket clientSocket_;
};

int main(int /*argc*/, const char** /*argv*/) {
  ClientApplication client;
  client.init();

  zmq::Message data(1);

  std::vector<zmq::Message> mapData;
  mapData.push_back(data);
  mapData.push_back(data);
  mapData.push_back(data);
  mapData.push_back(data);

  client.map(mapData);
}
<|endoftext|>