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

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

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

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

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

#include <qtooltip.h>
#include <qframe.h>
#include <qpixmap.h>
#include <qlayout.h>
#include <qwidgetstack.h>
#include <qwhatsthis.h>

#include <kiconloader.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <libkcal/calendarresources.h>
#include <libkcal/resourcecalendar.h>

#include <libkcal/calendarlocal.h>

#include "koprefs.h"
#include "koeditorgeneralevent.h"
#include "koeditoralarms.h"
#include "koeditorrecurrence.h"
#include "koeditordetails.h"
#include "koeditorattachments.h"
#include "koeditorfreebusy.h"
#include "kogroupware.h"
#include "kodialogmanager.h"
#include "incidencechanger.h"

#include "koeventeditor.h"

KOEventEditor::KOEventEditor( Calendar *calendar, QWidget *parent )
  : KOIncidenceEditor( QString::null, calendar, parent ),
    mEvent( 0 ), mGeneral( 0 ), mRecurrence( 0 ), mFreeBusy( 0 )
{
}

KOEventEditor::~KOEventEditor()
{
  mFreeBusy = 0; // see note in processInput()
  emit dialogClose( mEvent );
}

void KOEventEditor::init()
{
  setupGeneral();
//  setupAlarmsTab();
  setupRecurrence();
  setupAttendeesTab();
  setupFreeBusy();
  setupAttachmentsTab();
  setupDesignerTabs( "event" );

  mDetails->setFreeBusyWidget( mFreeBusy );

  // Propagate date time settings to recurrence tab
  connect( mGeneral, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
           mRecurrence, SLOT( setDateTimes( const QDateTime &, const QDateTime &) ) );
  connect( mGeneral, SIGNAL( dateTimeStrChanged( const QString & ) ),
           mRecurrence, SLOT( setDateTimeStr( const QString & ) ) );
  connect( mFreeBusy, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
           mRecurrence, SLOT( setDateTimes( const QDateTime &, const QDateTime & ) ) );

  // Propagate date time settings to gantt tab and back
  connect( mGeneral, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
           mFreeBusy, SLOT( slotUpdateGanttView( const QDateTime &, const QDateTime & ) ) );
  connect( mFreeBusy, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
           mGeneral, SLOT( setDateTimes( const QDateTime &, const QDateTime & ) ) );

  connect( mGeneral, SIGNAL( focusReceivedSignal() ),
           SIGNAL( focusReceivedSignal() ) );

  connect( mGeneral, SIGNAL( openCategoryDialog() ),
           SIGNAL( editCategories() ) );
}

void KOEventEditor::reload()
{
  kdDebug(5850) << "KOEventEditor::reload()" << endl;

  if ( mEvent ) readEvent( mEvent );
}

void KOEventEditor::setupGeneral()
{
  mGeneral = new KOEditorGeneralEvent( this );

  if( KOPrefs::instance()->mCompactDialogs ) {
    QFrame *topFrame = addPage(i18n("General"));
    QWhatsThis::add( topFrame,
                     i18n("The General tab allows you to set the most common "
                          "options for the event.") );

    QBoxLayout *topLayout = new QVBoxLayout(topFrame);
    topLayout->setSpacing(spacingHint());

    mGeneral->initHeader(topFrame,topLayout);
    mGeneral->initTime(topFrame,topLayout);
//    QBoxLayout *alarmLineLayout = new QHBoxLayout(topLayout);
    mGeneral->initAlarm(topFrame,topLayout);
    mGeneral->enableAlarm( false );
    mGeneral->initCategories( topFrame, topLayout );

    topLayout->addStretch( 1 );

    QFrame *topFrame2 = addPage(i18n("Details"));

    QBoxLayout *topLayout2 = new QVBoxLayout(topFrame2);
    topLayout2->setSpacing(spacingHint());

    mGeneral->initClass(topFrame2,topLayout2);
    mGeneral->initSecrecy( topFrame2, topLayout2 );
    mGeneral->initDescription(topFrame2,topLayout2);
  } else {
    QFrame *topFrame = addPage(i18n("&General"));
    QWhatsThis::add( topFrame,
                     i18n("The General tab allows you to set the most common "
                          "options for the event.") );

    QBoxLayout *topLayout = new QVBoxLayout(topFrame);
    topLayout->setSpacing(spacingHint());

    mGeneral->initHeader(topFrame,topLayout);
    mGeneral->initTime(topFrame,topLayout);
    QBoxLayout *alarmLineLayout = new QHBoxLayout(topLayout);
    mGeneral->initAlarm(topFrame,alarmLineLayout);
    alarmLineLayout->addStretch( 1 );
    mGeneral->initClass(topFrame,alarmLineLayout);
    mGeneral->initDescription(topFrame,topLayout);
    QBoxLayout *detailsLayout = new QHBoxLayout(topLayout);
    mGeneral->initCategories( topFrame, detailsLayout );
    mGeneral->initSecrecy( topFrame, detailsLayout );
  }

  mGeneral->finishSetup();
}

void KOEventEditor::modified (int /*modification*/)
{
  // Play dump, just reload the event. This dialog has become so complicated
  // that there is no point in trying to be smart here...
  reload();
}

void KOEventEditor::setupRecurrence()
{
  QFrame *topFrame = addPage( i18n("Rec&urrence") );

  QWhatsThis::add( topFrame,
        i18n("The Recurrence tab allows you to set options on "
       "how often this event recurs.") );

  QBoxLayout *topLayout = new QVBoxLayout( topFrame );

  mRecurrence = new KOEditorRecurrence( topFrame );
  topLayout->addWidget( mRecurrence );
}

void KOEventEditor::setupFreeBusy()
{
  QFrame *freeBusyPage = addPage( i18n("&Free/Busy") );
  QWhatsThis::add( freeBusyPage,
        i18n("The Free/Busy tab allows you to see whether "
       "other attendees are free or busy during your event.") );

  QBoxLayout *topLayout = new QVBoxLayout( freeBusyPage );

  mFreeBusy = new KOEditorFreeBusy( spacingHint(), freeBusyPage );
  topLayout->addWidget( mFreeBusy );
}

void KOEventEditor::editIncidence( Incidence *incidence )
{
  Event*event = dynamic_cast<Event*>(incidence);
  if ( event ) {
    init();

    mEvent = event;
    readEvent(mEvent);
  }

  setCaption( i18n("Edit Event") );
}

void KOEventEditor::newEvent()
{
  init();
  mEvent = 0;
  loadDefaults();
  setCaption( i18n("New Event") );
}

void KOEventEditor::setDates( const QDateTime &from, const QDateTime &to, bool allDay )
{
  mGeneral->setDefaults( from, to, allDay );
  mDetails->setDefaults();
  mAttachments->setDefaults();
  mRecurrence->setDefaults( from, to, allDay );
  if( mFreeBusy ) {
    if ( allDay )
      mFreeBusy->setDateTimes( from, to.addDays( 1 ) );
    else
      mFreeBusy->setDateTimes( from, to );
  }
}

void KOEventEditor::setTexts( const QString &summary, const QString &description )
{
  if ( description.isEmpty() && summary.contains("\n") ) {
    mGeneral->setDescription( summary );
    int pos = summary.find( "\n" );
    mGeneral->setSummary( summary.left( pos ) );
  } else {
    mGeneral->setSummary( summary );
    mGeneral->setDescription( description );
  }
}

void KOEventEditor::loadDefaults()
{
  QDateTime from( QDate::currentDate(), KOPrefs::instance()->mStartTime.time() );
  int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour()*3600 ) +
                ( KOPrefs::instance()->mDefaultDuration.time().minute()*60 );
  QDateTime to( from.addSecs( addSecs ) );

  setDates( from, to, false );
}

bool KOEventEditor::processInput()
{
  kdDebug(5850) << "KOEventEditor::processInput()" << endl;

  if ( !validateInput() || !mChanger ) return false;

  if ( mEvent ) {
    bool rc = true;
    Event *oldEvent = mEvent->clone();
    Event *event = mEvent->clone();

    kdDebug(5850) << "KOEventEditor::processInput() write event." << endl;
    writeEvent( event );
    kdDebug(5850) << "KOEventEditor::processInput() event written." << endl;

    if( *event == *mEvent )
      // Don't do anything
      kdDebug(5850) << "Event not changed\n";
    else {
      kdDebug(5850) << "Event changed\n";
      //IncidenceChanger::assignIncidence( mEvent, event );
      writeEvent( mEvent );
      mChanger->changeIncidence( oldEvent, mEvent );
    }
    delete event;
    delete oldEvent;
    return rc;
  } else {
    mEvent = new Event;
    mEvent->setOrganizer( Person( KOPrefs::instance()->fullName(),
                          KOPrefs::instance()->email() ) );
    writeEvent( mEvent );
    // NOTE: triggered by addIncidence, the kolab resource might open a non-modal dialog (parent is not available in the resource) to select a resource folder. Thus the user can close this dialog before addIncidence() returns.
    if ( !mChanger->addIncidence( mEvent, this ) ) {
      delete mEvent;
      mEvent = 0;
      return false;
    }
  }
  // safe, b/c mFreeBusy is reset to 0 in the dtor
  if ( mFreeBusy ) mFreeBusy->cancelReload();

  return true;
}

void KOEventEditor::processCancel()
{
  kdDebug(5850) << "KOEventEditor::processCancel()" << endl;

  if ( mFreeBusy ) mFreeBusy->cancelReload();
}

void KOEventEditor::deleteEvent()
{
  kdDebug(5850) << "Delete event" << endl;

  if ( mEvent )
    emit deleteIncidenceSignal( mEvent );
  emit dialogClose( mEvent );
  reject();
}

void KOEventEditor::readEvent( Event *event, bool tmpl )
{
  mGeneral->readEvent( event, tmpl );
  mDetails->readEvent( event );
  mRecurrence->readIncidence( event );
  mAttachments->readIncidence( event );
//  mAlarms->readIncidence( event );
  if ( mFreeBusy ) {
    mFreeBusy->readEvent( event );
    mFreeBusy->triggerReload();
  }

  createEmbeddedURLPages( event );
  readDesignerFields( event );
}

void KOEventEditor::writeEvent( Event *event )
{
  mGeneral->writeEvent( event );
  mDetails->writeEvent( event );
  mAttachments->writeIncidence( event );

  cancelRemovedAttendees( event );

  mRecurrence->writeIncidence( event );

  writeDesignerFields( event );
}

bool KOEventEditor::validateInput()
{
  if ( !mGeneral->validateInput() ) return false;
  if ( !mDetails->validateInput() ) return false;
  if ( !mRecurrence->validateInput() ) return false;

  return true;
}

int KOEventEditor::msgItemDelete()
{
  return KMessageBox::warningContinueCancel(this,
      i18n("This item will be permanently deleted."),
      i18n("KOrganizer Confirmation"),KGuiItem(i18n("Delete"),"editdelete"));
}

void KOEventEditor::loadTemplate( /*const*/ CalendarLocal& cal )
{
  const Event::List events = cal.events();
  if ( events.count() == 0 ) {
    KMessageBox::error( this,
        i18n("Template does not contain a valid event.") );
  } else {
    kdDebug(5850) << "KOEventEditor::slotLoadTemplate(): readTemplate" << endl;
    readEvent( events.first(), true );
  }
}

QStringList& KOEventEditor::templates() const
{
  return KOPrefs::instance()->mEventTemplates;
}

void KOEventEditor::slotSaveTemplate( const QString &templateName )
{
  kdDebug(5006) << "SlotSaveTemplate" << endl;
  Event *event = new Event;
  writeEvent( event );
  saveAsTemplate( event, templateName );
}

QObject *KOEventEditor::typeAheadReceiver() const
{
  return mGeneral->typeAheadReceiver();
}

#include "koeventeditor.moc"
<commit_msg>Kolab issue 1784 (prokde35): next try. Prevent crash using a QGuardedPtr<commit_after>/*
    This file is part of KOrganizer.

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

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

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

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

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

#include <qtooltip.h>
#include <qframe.h>
#include <qpixmap.h>
#include <qlayout.h>
#include <qwidgetstack.h>
#include <qwhatsthis.h>

#include <kiconloader.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <libkcal/calendarresources.h>
#include <libkcal/resourcecalendar.h>

#include <libkcal/calendarlocal.h>

#include "koprefs.h"
#include "koeditorgeneralevent.h"
#include "koeditoralarms.h"
#include "koeditorrecurrence.h"
#include "koeditordetails.h"
#include "koeditorattachments.h"
#include "koeditorfreebusy.h"
#include "kogroupware.h"
#include "kodialogmanager.h"
#include "incidencechanger.h"

#include "koeventeditor.h"

KOEventEditor::KOEventEditor( Calendar *calendar, QWidget *parent )
  : KOIncidenceEditor( QString::null, calendar, parent ),
    mEvent( 0 ), mGeneral( 0 ), mRecurrence( 0 ), mFreeBusy( 0 )
{
}

KOEventEditor::~KOEventEditor()
{
  emit dialogClose( mEvent );
}

void KOEventEditor::init()
{
  setupGeneral();
//  setupAlarmsTab();
  setupRecurrence();
  setupAttendeesTab();
  setupFreeBusy();
  setupAttachmentsTab();
  setupDesignerTabs( "event" );

  mDetails->setFreeBusyWidget( mFreeBusy );

  // Propagate date time settings to recurrence tab
  connect( mGeneral, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
           mRecurrence, SLOT( setDateTimes( const QDateTime &, const QDateTime &) ) );
  connect( mGeneral, SIGNAL( dateTimeStrChanged( const QString & ) ),
           mRecurrence, SLOT( setDateTimeStr( const QString & ) ) );
  connect( mFreeBusy, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
           mRecurrence, SLOT( setDateTimes( const QDateTime &, const QDateTime & ) ) );

  // Propagate date time settings to gantt tab and back
  connect( mGeneral, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
           mFreeBusy, SLOT( slotUpdateGanttView( const QDateTime &, const QDateTime & ) ) );
  connect( mFreeBusy, SIGNAL( dateTimesChanged( const QDateTime &, const QDateTime & ) ),
           mGeneral, SLOT( setDateTimes( const QDateTime &, const QDateTime & ) ) );

  connect( mGeneral, SIGNAL( focusReceivedSignal() ),
           SIGNAL( focusReceivedSignal() ) );

  connect( mGeneral, SIGNAL( openCategoryDialog() ),
           SIGNAL( editCategories() ) );
}

void KOEventEditor::reload()
{
  kdDebug(5850) << "KOEventEditor::reload()" << endl;

  if ( mEvent ) readEvent( mEvent );
}

void KOEventEditor::setupGeneral()
{
  mGeneral = new KOEditorGeneralEvent( this );

  if( KOPrefs::instance()->mCompactDialogs ) {
    QFrame *topFrame = addPage(i18n("General"));
    QWhatsThis::add( topFrame,
                     i18n("The General tab allows you to set the most common "
                          "options for the event.") );

    QBoxLayout *topLayout = new QVBoxLayout(topFrame);
    topLayout->setSpacing(spacingHint());

    mGeneral->initHeader(topFrame,topLayout);
    mGeneral->initTime(topFrame,topLayout);
//    QBoxLayout *alarmLineLayout = new QHBoxLayout(topLayout);
    mGeneral->initAlarm(topFrame,topLayout);
    mGeneral->enableAlarm( false );
    mGeneral->initCategories( topFrame, topLayout );

    topLayout->addStretch( 1 );

    QFrame *topFrame2 = addPage(i18n("Details"));

    QBoxLayout *topLayout2 = new QVBoxLayout(topFrame2);
    topLayout2->setSpacing(spacingHint());

    mGeneral->initClass(topFrame2,topLayout2);
    mGeneral->initSecrecy( topFrame2, topLayout2 );
    mGeneral->initDescription(topFrame2,topLayout2);
  } else {
    QFrame *topFrame = addPage(i18n("&General"));
    QWhatsThis::add( topFrame,
                     i18n("The General tab allows you to set the most common "
                          "options for the event.") );

    QBoxLayout *topLayout = new QVBoxLayout(topFrame);
    topLayout->setSpacing(spacingHint());

    mGeneral->initHeader(topFrame,topLayout);
    mGeneral->initTime(topFrame,topLayout);
    QBoxLayout *alarmLineLayout = new QHBoxLayout(topLayout);
    mGeneral->initAlarm(topFrame,alarmLineLayout);
    alarmLineLayout->addStretch( 1 );
    mGeneral->initClass(topFrame,alarmLineLayout);
    mGeneral->initDescription(topFrame,topLayout);
    QBoxLayout *detailsLayout = new QHBoxLayout(topLayout);
    mGeneral->initCategories( topFrame, detailsLayout );
    mGeneral->initSecrecy( topFrame, detailsLayout );
  }

  mGeneral->finishSetup();
}

void KOEventEditor::modified (int /*modification*/)
{
  // Play dump, just reload the event. This dialog has become so complicated
  // that there is no point in trying to be smart here...
  reload();
}

void KOEventEditor::setupRecurrence()
{
  QFrame *topFrame = addPage( i18n("Rec&urrence") );

  QWhatsThis::add( topFrame,
        i18n("The Recurrence tab allows you to set options on "
       "how often this event recurs.") );

  QBoxLayout *topLayout = new QVBoxLayout( topFrame );

  mRecurrence = new KOEditorRecurrence( topFrame );
  topLayout->addWidget( mRecurrence );
}

void KOEventEditor::setupFreeBusy()
{
  QFrame *freeBusyPage = addPage( i18n("&Free/Busy") );
  QWhatsThis::add( freeBusyPage,
        i18n("The Free/Busy tab allows you to see whether "
       "other attendees are free or busy during your event.") );

  QBoxLayout *topLayout = new QVBoxLayout( freeBusyPage );

  mFreeBusy = new KOEditorFreeBusy( spacingHint(), freeBusyPage );
  topLayout->addWidget( mFreeBusy );
}

void KOEventEditor::editIncidence( Incidence *incidence )
{
  Event*event = dynamic_cast<Event*>(incidence);
  if ( event ) {
    init();

    mEvent = event;
    readEvent(mEvent);
  }

  setCaption( i18n("Edit Event") );
}

void KOEventEditor::newEvent()
{
  init();
  mEvent = 0;
  loadDefaults();
  setCaption( i18n("New Event") );
}

void KOEventEditor::setDates( const QDateTime &from, const QDateTime &to, bool allDay )
{
  mGeneral->setDefaults( from, to, allDay );
  mDetails->setDefaults();
  mAttachments->setDefaults();
  mRecurrence->setDefaults( from, to, allDay );
  if( mFreeBusy ) {
    if ( allDay )
      mFreeBusy->setDateTimes( from, to.addDays( 1 ) );
    else
      mFreeBusy->setDateTimes( from, to );
  }
}

void KOEventEditor::setTexts( const QString &summary, const QString &description )
{
  if ( description.isEmpty() && summary.contains("\n") ) {
    mGeneral->setDescription( summary );
    int pos = summary.find( "\n" );
    mGeneral->setSummary( summary.left( pos ) );
  } else {
    mGeneral->setSummary( summary );
    mGeneral->setDescription( description );
  }
}

void KOEventEditor::loadDefaults()
{
  QDateTime from( QDate::currentDate(), KOPrefs::instance()->mStartTime.time() );
  int addSecs = ( KOPrefs::instance()->mDefaultDuration.time().hour()*3600 ) +
                ( KOPrefs::instance()->mDefaultDuration.time().minute()*60 );
  QDateTime to( from.addSecs( addSecs ) );

  setDates( from, to, false );
}

bool KOEventEditor::processInput()
{
  kdDebug(5850) << "KOEventEditor::processInput()" << endl;

  if ( !validateInput() || !mChanger ) return false;

  QGuardedPtr<KOEditorFreeBusy> freeBusy( mFreeBusy );

  if ( mEvent ) {
    bool rc = true;
    Event *oldEvent = mEvent->clone();
    Event *event = mEvent->clone();

    kdDebug(5850) << "KOEventEditor::processInput() write event." << endl;
    writeEvent( event );
    kdDebug(5850) << "KOEventEditor::processInput() event written." << endl;

    if( *event == *mEvent )
      // Don't do anything
      kdDebug(5850) << "Event not changed\n";
    else {
      kdDebug(5850) << "Event changed\n";
      //IncidenceChanger::assignIncidence( mEvent, event );
      writeEvent( mEvent );
      mChanger->changeIncidence( oldEvent, mEvent );
    }
    delete event;
    delete oldEvent;
    return rc;
  } else {
    mEvent = new Event;
    mEvent->setOrganizer( Person( KOPrefs::instance()->fullName(),
                          KOPrefs::instance()->email() ) );
    writeEvent( mEvent );
    // NOTE: triggered by addIncidence, the kolab resource might open a non-modal dialog (parent is not available in the resource) to select a resource folder. Thus the user can close this dialog before addIncidence() returns.
    if ( !mChanger->addIncidence( mEvent, this ) ) {
      delete mEvent;
      mEvent = 0;
      return false;
    }
  }
  // if "this" was deleted, freeBusy is 0 (being a guardedptr)
  if ( freeBusy ) freeBusy->cancelReload();

  return true;
}

void KOEventEditor::processCancel()
{
  kdDebug(5850) << "KOEventEditor::processCancel()" << endl;

  if ( mFreeBusy ) mFreeBusy->cancelReload();
}

void KOEventEditor::deleteEvent()
{
  kdDebug(5850) << "Delete event" << endl;

  if ( mEvent )
    emit deleteIncidenceSignal( mEvent );
  emit dialogClose( mEvent );
  reject();
}

void KOEventEditor::readEvent( Event *event, bool tmpl )
{
  mGeneral->readEvent( event, tmpl );
  mDetails->readEvent( event );
  mRecurrence->readIncidence( event );
  mAttachments->readIncidence( event );
//  mAlarms->readIncidence( event );
  if ( mFreeBusy ) {
    mFreeBusy->readEvent( event );
    mFreeBusy->triggerReload();
  }

  createEmbeddedURLPages( event );
  readDesignerFields( event );
}

void KOEventEditor::writeEvent( Event *event )
{
  mGeneral->writeEvent( event );
  mDetails->writeEvent( event );
  mAttachments->writeIncidence( event );

  cancelRemovedAttendees( event );

  mRecurrence->writeIncidence( event );

  writeDesignerFields( event );
}

bool KOEventEditor::validateInput()
{
  if ( !mGeneral->validateInput() ) return false;
  if ( !mDetails->validateInput() ) return false;
  if ( !mRecurrence->validateInput() ) return false;

  return true;
}

int KOEventEditor::msgItemDelete()
{
  return KMessageBox::warningContinueCancel(this,
      i18n("This item will be permanently deleted."),
      i18n("KOrganizer Confirmation"),KGuiItem(i18n("Delete"),"editdelete"));
}

void KOEventEditor::loadTemplate( /*const*/ CalendarLocal& cal )
{
  const Event::List events = cal.events();
  if ( events.count() == 0 ) {
    KMessageBox::error( this,
        i18n("Template does not contain a valid event.") );
  } else {
    kdDebug(5850) << "KOEventEditor::slotLoadTemplate(): readTemplate" << endl;
    readEvent( events.first(), true );
  }
}

QStringList& KOEventEditor::templates() const
{
  return KOPrefs::instance()->mEventTemplates;
}

void KOEventEditor::slotSaveTemplate( const QString &templateName )
{
  kdDebug(5006) << "SlotSaveTemplate" << endl;
  Event *event = new Event;
  writeEvent( event );
  saveAsTemplate( event, templateName );
}

QObject *KOEventEditor::typeAheadReceiver() const
{
  return mGeneral->typeAheadReceiver();
}

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


<commit_before>#include "config.h"

#ifdef CONFIG_GDK_PIXBUF_XLIB

#include "yimage.h"
#include "yxapp.h"

extern "C" {
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
}

class YImageGDK: public YImage {
public:
    YImageGDK(unsigned width, unsigned height, GdkPixbuf *pixbuf): YImage(width, height) {
        fPixbuf = pixbuf;
    }
    virtual ~YImageGDK() {
        g_object_unref(G_OBJECT(fPixbuf));
    }
    virtual ref<YPixmap> renderToPixmap();
    virtual ref<YImage> scale(unsigned width, unsigned height);
    virtual void draw(Graphics &g, int dx, int dy);
    virtual void draw(Graphics &g, int x, int y, unsigned w, unsigned h, int dx, int dy);
    virtual void composite(Graphics &g, int x, int y, unsigned w, unsigned h, int dx, int dy);
    virtual bool valid() const { return fPixbuf != 0; }
private:
    GdkPixbuf *fPixbuf;
};

ref<YImage> YImage::create(unsigned width, unsigned height) {
    ref<YImage> image;
    GdkPixbuf *pixbuf =
        gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
    if (pixbuf != NULL) {
        image.init(new YImageGDK(width, height, pixbuf));
    }
    return image;
}

ref<YImage> YImage::load(upath filename) {
    ref<YImage> image;
    GError *gerror = 0;
    GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename.string(), &gerror);

    if (pixbuf != NULL) {
        image.init(new YImageGDK(gdk_pixbuf_get_width(pixbuf),
                                 gdk_pixbuf_get_height(pixbuf),
                                 pixbuf));
    }
    return image;
}

ref<YImage> YImageGDK::scale(unsigned w, unsigned h) {
    ref<YImage> image;
    GdkPixbuf *pixbuf;
    pixbuf = gdk_pixbuf_scale_simple(fPixbuf,
                                     w, h,
                                     GDK_INTERP_BILINEAR);
    if (pixbuf != NULL) {
        image.init(new YImageGDK(w, h, pixbuf));
    }

    return image;
}

ref<YImage> YImage::createFromPixmap(ref<YPixmap> pixmap) {
    return createFromPixmapAndMask(pixmap->pixmap(),
                                   pixmap->mask(),
                                   pixmap->width(),
                                   pixmap->height());
}

ref<YImage> YImage::createFromPixmapAndMask(Pixmap pixmap, Pixmap mask,
                                            unsigned width, unsigned height)
{
    ref<YImage> image;
    GdkPixbuf *pixbuf =
        gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
                       width, height);

    if (pixbuf) {
        pixbuf =
            gdk_pixbuf_xlib_get_from_drawable(pixbuf,
                                              pixmap,
                                              xlib_rgb_get_cmap(),
                                              xlib_rgb_get_visual(),
                                              0, 0,
                                              0, 0,
                                              width,
                                              height);

        if (mask != None) {
            XImage *image = XGetImage(xapp->display(), mask,
                                      0, 0, width, height,
                                      AllPlanes, ZPixmap);
            guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);

            if (image) {
                //unsigned char *pix = image->data;
                for (unsigned r = 0; r < height; r++) {
                    for (unsigned c = 0; c < width; c++) {
                        unsigned int pix = XGetPixel(image, c, r);
                        pixels[c * 4 + 3] = (unsigned char)(pix ? 255 : 0);
                    }
                    pixels += gdk_pixbuf_get_rowstride(pixbuf);
                    //pix += image->bytes_per_line;
                }
                XDestroyImage(image);
            }
        }

        image.init(new YImageGDK(width,
                                 height,
                                 pixbuf));
    }
    return image;
}

ref<YImage> YImage::createFromIconProperty(long *prop_pixels,
                                           unsigned width, unsigned height)
{
    ref<YImage> image;
    GdkPixbuf *pixbuf =
        gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
                       width, height);

    if (!pixbuf)
        return null;

    guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);

    for (unsigned r = 0; r < height; r++) {
        for (unsigned c = 0; c < width; c++) {
            unsigned long pix =
                prop_pixels[c + r * width];
            pixels[c * 4 + 2] = (unsigned char)(pix & 0xFF);
            pixels[c * 4 + 1] = (unsigned char)((pix >> 8) & 0xFF);
            pixels[c * 4] = (unsigned char)((pix >> 16) & 0xFF);
            pixels[c * 4 + 3] = (unsigned char)((pix >> 24) & 0xFF);
        }
        pixels += gdk_pixbuf_get_rowstride(pixbuf);
    }
    image.init(new YImageGDK(width,
                             height,
                             pixbuf));
    return image;
}

ref<YImage> YImage::createFromPixmapAndMaskScaled(Pixmap pix, Pixmap mask,
                                                  unsigned width, unsigned height,
                                                  unsigned nw, unsigned nh)
{
    ref<YImage> image = createFromPixmapAndMask(pix, mask, width, height);
    if (image != null)
        image = image->scale(nw, nh);
    return image;
}

ref<YPixmap> YImageGDK::renderToPixmap() {
    Pixmap pixmap = None, mask = None;
    gdk_pixbuf_xlib_render_pixmap_and_mask(fPixbuf, &pixmap, &mask, 128);

    return createPixmap(pixmap, mask,
                        gdk_pixbuf_get_width(fPixbuf),
                        gdk_pixbuf_get_height(fPixbuf),
                        xapp->depth());
}

ref<YPixmap> YImage::createPixmap(Pixmap pixmap, Pixmap mask, unsigned w, unsigned h, unsigned depth) {
    ref<YPixmap> n;

    n.init(new YPixmap(pixmap, mask, w, h, depth));
    return n;
}

void YImageGDK::draw(Graphics &g, int dx, int dy) {
#if 1
    composite(g, 0, 0, width(), height(), dx, dy);
#else
    gdk_pixbuf_xlib_render_to_drawable_alpha(fPixbuf, g.drawable(), //g.handleX(),
                                             0, 0, dx, dy, width(), height(),
                                             GDK_PIXBUF_ALPHA_FULL,
                                             128,
                                             XLIB_RGB_DITHER_NORMAL, 0, 0);
#endif
}

void YImageGDK::draw(Graphics &g, int x, int y, unsigned w, unsigned h, int dx, int dy) {
#if 1
    composite(g, x, y, w, h, dx, dy);
#else
    gdk_pixbuf_xlib_render_to_drawable_alpha(fPixbuf, g.drawable(), //g.handleX(),
                                             x, y, dx, dy, w, h,
                                             GDK_PIXBUF_ALPHA_BILEVEL, 128,
                                             XLIB_RGB_DITHER_NORMAL, 0, 0);
#endif
}

void YImageGDK::composite(Graphics &g, int x, int y, unsigned w, unsigned h, int dx, int dy) {

    //MSG(("composite -- %d %d %d %d | %d %d", x, y, w, h, dx, dy));
    if (g.xorigin() > dx) {
        if ((int) w <= g.xorigin() - dx)
            return;
        w -= g.xorigin() - dx;
        x += g.xorigin() - dx;
        dx = g.xorigin();
    }
    if (g.yorigin() > dy) {
        if ((int) h <= g.xorigin() - dx)
            return;
        h -= g.yorigin() - dy;
        y += g.yorigin() - dy;
        dy = g.yorigin();
    }
    if ((int) (dx + w) > (int) (g.xorigin() + g.rwidth())) {
        if ((int) (g.xorigin() + g.rwidth()) <= dx)
            return;
        w = g.xorigin() + g.rwidth() - dx;
    }
    if ((int) (dy + h) > (int) (g.yorigin() + g.rheight())) {
        if ((int) (g.yorigin() + g.rheight()) <= dy)
            return;
        h = g.yorigin() + g.rheight() - dy;
    }
    if (w <= 0 || h <= 0)
        return;

    //MSG(("composite ++ %d %d %d %d | %d %d", x, y, w, h, dx, dy));
    GdkPixbuf *pixbuf =
        gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h);
    gdk_pixbuf_xlib_get_from_drawable(pixbuf,
                                      g.drawable(),
                                      xapp->colormap(),
                                      xapp->visual(),
                                      dx - g.xorigin(), dy - g.yorigin(), 0, 0, w, h);
    gdk_pixbuf_composite(fPixbuf, pixbuf,
                         0, 0, w, h,
                         -x, -y, 1.0, 1.0,
                         GDK_INTERP_BILINEAR, 255);
    gdk_pixbuf_xlib_render_to_drawable(pixbuf, g.drawable(), g.handleX(),
                                             0, 0, dx - g.xorigin(), dy - g.yorigin(), w, h,
//                                             GDK_PIXBUF_ALPHA_BILEVEL, 128,
                                             XLIB_RGB_DITHER_NONE, 0, 0);
    g_object_unref(G_OBJECT(pixbuf));
}

void image_init() {
#if (GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION < 36 && GLIB_MICRO_VERSION <= 0)
    g_type_init();
#endif
    xlib_rgb_init(xapp->display(), ScreenOfDisplay(xapp->display(), xapp->screen()));
    gdk_pixbuf_xlib_init(xapp->display(), xapp->screen());
}

#endif

// vim: set sw=4 ts=4 et:
<commit_msg>Fixes for gdk_pixbuf with and height being signed. Prevent unsigned underflow.<commit_after>#include "config.h"

#ifdef CONFIG_GDK_PIXBUF_XLIB

#include "yimage.h"
#include "yxapp.h"

extern "C" {
#include <gdk-pixbuf-xlib/gdk-pixbuf-xlib.h>
}

class YImageGDK: public YImage {
public:
    YImageGDK(unsigned width, unsigned height, GdkPixbuf *pixbuf): YImage(width, height) {
        fPixbuf = pixbuf;
    }
    virtual ~YImageGDK() {
        g_object_unref(G_OBJECT(fPixbuf));
    }
    virtual ref<YPixmap> renderToPixmap();
    virtual ref<YImage> scale(unsigned width, unsigned height);
    virtual void draw(Graphics &g, int dx, int dy);
    virtual void draw(Graphics &g, int x, int y, unsigned w, unsigned h, int dx, int dy);
    virtual void composite(Graphics &g, int x, int y, unsigned w, unsigned h, int dx, int dy);
    virtual bool valid() const { return fPixbuf != 0; }
private:
    GdkPixbuf *fPixbuf;
};

ref<YImage> YImage::create(unsigned width, unsigned height) {
    ref<YImage> image;
    GdkPixbuf *pixbuf =
        gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, width, height);
    if (pixbuf != NULL) {
        image.init(new YImageGDK(width, height, pixbuf));
    }
    return image;
}

ref<YImage> YImage::load(upath filename) {
    ref<YImage> image;
    GError *gerror = 0;
    GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(filename.string(), &gerror);

    if (pixbuf != NULL) {
        image.init(new YImageGDK(gdk_pixbuf_get_width(pixbuf),
                                 gdk_pixbuf_get_height(pixbuf),
                                 pixbuf));
    }
    return image;
}

ref<YImage> YImageGDK::scale(unsigned w, unsigned h) {
    ref<YImage> image;
    GdkPixbuf *pixbuf;
    pixbuf = gdk_pixbuf_scale_simple(fPixbuf,
                                     w, h,
                                     GDK_INTERP_BILINEAR);
    if (pixbuf != NULL) {
        image.init(new YImageGDK(w, h, pixbuf));
    }

    return image;
}

ref<YImage> YImage::createFromPixmap(ref<YPixmap> pixmap) {
    return createFromPixmapAndMask(pixmap->pixmap(),
                                   pixmap->mask(),
                                   pixmap->width(),
                                   pixmap->height());
}

ref<YImage> YImage::createFromPixmapAndMask(Pixmap pixmap, Pixmap mask,
                                            unsigned width, unsigned height)
{
    ref<YImage> image;
    GdkPixbuf *pixbuf =
        gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
                       width, height);

    if (pixbuf) {
        pixbuf =
            gdk_pixbuf_xlib_get_from_drawable(pixbuf,
                                              pixmap,
                                              xlib_rgb_get_cmap(),
                                              xlib_rgb_get_visual(),
                                              0, 0,
                                              0, 0,
                                              width,
                                              height);

        if (mask != None) {
            XImage *image = XGetImage(xapp->display(), mask,
                                      0, 0, width, height,
                                      AllPlanes, ZPixmap);
            guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);

            if (image) {
                //unsigned char *pix = image->data;
                for (unsigned r = 0; r < height; r++) {
                    for (unsigned c = 0; c < width; c++) {
                        unsigned int pix = XGetPixel(image, c, r);
                        pixels[c * 4 + 3] = (unsigned char)(pix ? 255 : 0);
                    }
                    pixels += gdk_pixbuf_get_rowstride(pixbuf);
                    //pix += image->bytes_per_line;
                }
                XDestroyImage(image);
            }
        }

        image.init(new YImageGDK(width,
                                 height,
                                 pixbuf));
    }
    return image;
}

ref<YImage> YImage::createFromIconProperty(long *prop_pixels,
                                           unsigned width, unsigned height)
{
    ref<YImage> image;
    GdkPixbuf *pixbuf =
        gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
                       width, height);

    if (!pixbuf)
        return null;

    guchar *pixels = gdk_pixbuf_get_pixels(pixbuf);

    for (unsigned r = 0; r < height; r++) {
        for (unsigned c = 0; c < width; c++) {
            unsigned long pix =
                prop_pixels[c + r * width];
            pixels[c * 4 + 2] = (unsigned char)(pix & 0xFF);
            pixels[c * 4 + 1] = (unsigned char)((pix >> 8) & 0xFF);
            pixels[c * 4] = (unsigned char)((pix >> 16) & 0xFF);
            pixels[c * 4 + 3] = (unsigned char)((pix >> 24) & 0xFF);
        }
        pixels += gdk_pixbuf_get_rowstride(pixbuf);
    }
    image.init(new YImageGDK(width,
                             height,
                             pixbuf));
    return image;
}

ref<YImage> YImage::createFromPixmapAndMaskScaled(Pixmap pix, Pixmap mask,
                                                  unsigned width, unsigned height,
                                                  unsigned nw, unsigned nh)
{
    ref<YImage> image = createFromPixmapAndMask(pix, mask, width, height);
    if (image != null)
        image = image->scale(nw, nh);
    return image;
}

ref<YPixmap> YImageGDK::renderToPixmap() {
    Pixmap pixmap = None, mask = None;
    gdk_pixbuf_xlib_render_pixmap_and_mask(fPixbuf, &pixmap, &mask, 128);

    return createPixmap(pixmap, mask,
                        gdk_pixbuf_get_width(fPixbuf),
                        gdk_pixbuf_get_height(fPixbuf),
                        xapp->depth());
}

ref<YPixmap> YImage::createPixmap(Pixmap pixmap, Pixmap mask, unsigned w, unsigned h, unsigned depth) {
    ref<YPixmap> n;

    n.init(new YPixmap(pixmap, mask, w, h, depth));
    return n;
}

void YImageGDK::draw(Graphics &g, int dx, int dy) {
#if 1
    composite(g, 0, 0, width(), height(), dx, dy);
#else
    gdk_pixbuf_xlib_render_to_drawable_alpha(fPixbuf, g.drawable(), //g.handleX(),
                                             0, 0, dx, dy, width(), height(),
                                             GDK_PIXBUF_ALPHA_FULL,
                                             128,
                                             XLIB_RGB_DITHER_NORMAL, 0, 0);
#endif
}

void YImageGDK::draw(Graphics &g, int x, int y, unsigned w, unsigned h, int dx, int dy) {
#if 1
    composite(g, x, y, w, h, dx, dy);
#else
    gdk_pixbuf_xlib_render_to_drawable_alpha(fPixbuf, g.drawable(), //g.handleX(),
                                             x, y, dx, dy, w, h,
                                             GDK_PIXBUF_ALPHA_BILEVEL, 128,
                                             XLIB_RGB_DITHER_NORMAL, 0, 0);
#endif
}

void YImageGDK::composite(Graphics &g, int x, int y, unsigned width, unsigned height, int dx, int dy) {
    int w = (int) width;
    int h = (int) height;

    //MSG(("composite -- %d %d %d %d | %d %d", x, y, w, h, dx, dy));
    if (g.xorigin() > dx) {
        if (w <= g.xorigin() - dx)
            return;
        w -= g.xorigin() - dx;
        x += g.xorigin() - dx;
        dx = g.xorigin();
    }
    if (g.yorigin() > dy) {
        if (h <= g.xorigin() - dx)
            return;
        h -= g.yorigin() - dy;
        y += g.yorigin() - dy;
        dy = g.yorigin();
    }
    if (dx + w > (int) (g.xorigin() + g.rwidth())) {
        if ((int) (g.xorigin() + g.rwidth()) <= dx)
            return;
        w = g.xorigin() + g.rwidth() - dx;
    }
    if (dy + h > (int) (g.yorigin() + g.rheight())) {
        if ((int) (g.yorigin() + g.rheight()) <= dy)
            return;
        h = g.yorigin() + g.rheight() - dy;
    }
    if (w <= 0 || h <= 0)
        return;

    const int src_x = int(dx - g.xorigin());
    const int src_y = int(dy - g.yorigin());

    //MSG(("composite ++ %d %d %d %d | %d %d", x, y, w, h, dx, dy));
    GdkPixbuf *pixbuf =
        gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h);
    gdk_pixbuf_xlib_get_from_drawable(pixbuf,
                                      g.drawable(),
                                      xapp->colormap(),
                                      xapp->visual(),
                                      src_x, src_y, 0, 0, w, h);
    gdk_pixbuf_composite(fPixbuf, pixbuf,
                         0, 0, w, h,
                         -x, -y, 1.0, 1.0,
                         GDK_INTERP_BILINEAR, 255);
    gdk_pixbuf_xlib_render_to_drawable(pixbuf, g.drawable(), g.handleX(),
                                             0, 0, src_x, src_y, w, h,
//                                             GDK_PIXBUF_ALPHA_BILEVEL, 128,
                                             XLIB_RGB_DITHER_NONE, 0, 0);
    g_object_unref(G_OBJECT(pixbuf));
}

void image_init() {
#if (GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION < 36 && GLIB_MICRO_VERSION <= 0)
    g_type_init();
#endif
    xlib_rgb_init(xapp->display(), ScreenOfDisplay(xapp->display(), xapp->screen()));
    gdk_pixbuf_xlib_init(xapp->display(), xapp->screen());
}

#endif

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


<commit_before>//  Copyright 2010 Gregory Szorc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include <zippylog/zippylog.hpp>
#include <zippylog/zippylogd/broker.hpp>
#include <zippylog/zippylogd/util.hpp>

#include <iostream>
#include <string>

using ::zippylog::zippylogd::ZippylogdStartParams;
using ::zippylog::zippylogd::Broker;
using ::std::cout;
using ::std::endl;
using ::std::string;
using ::std::vector;

#ifdef LINUX
static volatile sig_atomic_t active = 1;

void signal_handler(int signo)
{
    active = 0;

    signal(signo, SIG_DFL);
}
#endif

int main(int argc, const char * const argv[])
{
    string error;
    ZippylogdStartParams params;

    vector<string> args;
    for (int i = 0; i < argc; i++) {
        args.push_back(argv[i]);
    }

    if (!::zippylog::zippylogd::ParseCommandArguments(args, params, error)) {
        cout << error << endl;
        return 1;
    }

#ifdef LINUX
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
#endif

    try {
        ::zippylog::initialize_library();

        ::zippylog::zippylogd::Zippylogd instance(params);
        instance.Run();

        // TODO remove broker code in favor of zippylogd class
        Broker broker(argv[1]);

#ifdef LINUX
        broker.RunAsync();
        while (active) pause();
#elif WINDOWS
        broker.Run();
#else
#error "not implemented on this platform"
#endif
    }
    catch (string s) {
        cout << "Exception:" << endl;
        cout << s;
        return 1;
    }
    catch (...) {
        cout << "received an exception" << endl;
        return 1;
    }

    ::zippylog::shutdown_library();

    return 0;
}
<commit_msg>catch char * exceptions<commit_after>//  Copyright 2010 Gregory Szorc
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

#include <zippylog/zippylog.hpp>
#include <zippylog/zippylogd/broker.hpp>
#include <zippylog/zippylogd/util.hpp>

#include <iostream>
#include <string>

using ::zippylog::zippylogd::ZippylogdStartParams;
using ::zippylog::zippylogd::Broker;
using ::std::cout;
using ::std::endl;
using ::std::string;
using ::std::vector;

#ifdef LINUX
static volatile sig_atomic_t active = 1;

void signal_handler(int signo)
{
    active = 0;

    signal(signo, SIG_DFL);
}
#endif

int main(int argc, const char * const argv[])
{
    string error;
    ZippylogdStartParams params;

    vector<string> args;
    for (int i = 0; i < argc; i++) {
        args.push_back(argv[i]);
    }

    if (!::zippylog::zippylogd::ParseCommandArguments(args, params, error)) {
        cout << error << endl;
        return 1;
    }

#ifdef LINUX
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
#endif

    try {
        ::zippylog::initialize_library();

        ::zippylog::zippylogd::Zippylogd instance(params);
        instance.Run();

        // TODO remove broker code in favor of zippylogd class
        Broker broker(argv[1]);

#ifdef LINUX
        broker.RunAsync();
        while (active) pause();
#elif WINDOWS
        broker.Run();
#else
#error "not implemented on this platform"
#endif
    }
    catch (string s) {
        cout << "Exception:" << endl;
        cout << s;
        return 1;
    }
    catch (char * s) {
        cout << "Exception: " << s << endl;
        return 1;
    }
    catch (...) {
        cout << "received an exception" << endl;
        return 1;
    }

    ::zippylog::shutdown_library();

    return 0;
}
<|endoftext|>


<commit_before>#include "ossimS3StreamBuffer.h"

#include <aws/s3/model/PutObjectRequest.h>
#include <aws/s3/model/GetObjectRequest.h>
#include <aws/s3/model/GetObjectResult.h>
#include <aws/s3/model/HeadObjectRequest.h>

#include <aws/core/Aws.h>
#include <aws/core/utils/memory/stl/AWSStringStream.h>
#include <iostream>
#include <ossim/base/ossimUrl.h>
//static const char* KEY = "test-file.txt";
//static const char* BUCKET = "ossimlabs";
#include <cstdio> /* for EOF */
#include <streambuf>
#include <sstream>
#include <iosfwd>
#include <ios>
#include <vector>
#include <cstring> /* for memcpy */

using namespace Aws::S3;
using namespace Aws::S3::Model;

ossim::S3StreamBuffer::S3StreamBuffer()
:
  m_bucket(""),
  m_key(""),
  m_buffer(1024*1024),
  m_bufferActualDataSize(0),
  m_currentPosition(-1),
  m_bufferPtr(0),
  m_currentPtr(0),
  m_fileSize(0),
  m_opened(false),
  m_mode(0)
{
//    std::cout << "CONSTRUCTED!!!!!" << std::endl;
//  setp(0);
  setg(m_currentPtr, m_currentPtr, m_currentPtr);
}

ossim_int64 ossim::S3StreamBuffer::getBlockIndex(ossim_int64 byteOffset)const
{
  ossim_int64 blockNumber = -1;

  if(byteOffset < m_fileSize)
  {
    if(m_buffer.size()>0)
    {
      blockNumber = byteOffset/m_buffer.size();
    }
  }

  return blockNumber;
}

ossim_int64 ossim::S3StreamBuffer::getBlockOffset(ossim_int64 byteOffset)const
{
  ossim_int64 blockOffset = -1;

  if(m_buffer.size()>0)
  {
    blockOffset = byteOffset%m_buffer.size();
  }

  return blockOffset;
}

bool ossim::S3StreamBuffer::getBlockRangeInBytes(ossim_int64 blockIndex,
  ossim_int64& startRange,
  ossim_int64& endRange)const
{
  bool result = false;

  if(blockIndex >= 0)
  {
    startRange = blockIndex*m_buffer.size();
    endRange = startRange + m_buffer.size()-1;

    result = true;
  }

  return result;
}

bool ossim::S3StreamBuffer::loadBlock(ossim_int64 blockIndex)
{
    bool result = false;
    m_bufferPtr = 0;
    m_currentPtr = 0;
    GetObjectRequest getObjectRequest;
    std::stringstream stringStream;
    ossim_int64 startRange, endRange;
    if(getBlockRangeInBytes(blockIndex, startRange, endRange))
    {
      stringStream << "bytes=" << startRange << "-" << endRange;
      getObjectRequest.WithBucket(m_bucket.c_str())
          .WithKey(m_key.c_str()).WithRange(stringStream.str().c_str());
      auto getObjectOutcome = m_client.GetObject(getObjectRequest);

      if(getObjectOutcome.IsSuccess())
      {
//        std::cout << "GOOD CALL!!!!!!!!!!!!\n";
        Aws::IOStream& bodyStream = getObjectOutcome.GetResult().GetBody();
        ossim_uint64 bufSize = getObjectOutcome.GetResult().GetContentLength();
//        std::cout << "SIZE OF RESULT ======== " << bufSize << std::endl;
        m_bufferActualDataSize = bufSize;
        bodyStream.read(&m_buffer.front(), bufSize);
        m_bufferPtr = &m_buffer.front();
        m_currentPtr = m_bufferPtr;

        if(m_currentPosition>=0)
        {
          ossim_int64 delta = m_currentPosition-startRange;
          setg(m_bufferPtr, m_bufferPtr + delta, m_bufferPtr+m_bufferActualDataSize);
        }
        else
        {
          setg(m_bufferPtr, m_bufferPtr, m_bufferPtr + m_bufferActualDataSize);
          m_currentPosition = startRange;
        }
        result = true;
          //std::cout << "Successfully retrieved object from s3 with value: " << std::endl;
          //std::cout << getObjectOutcome.GetResult().GetBody().rdbuf() << std::endl << std::endl;;
      }
    }

    return result;
}

ossim::S3StreamBuffer* ossim::S3StreamBuffer::open (const char* connectionString,
                                                    std::ios_base::openmode m)
{
  std::string temp(connectionString);
  return open(temp, m);
}

ossim::S3StreamBuffer* ossim::S3StreamBuffer::open (const std::string& connectionString,
                                                    std::ios_base::openmode mode)
{
  bool result = false;
  ossimUrl url(connectionString);
  clearAll();
  m_mode = mode;

  if(url.getProtocol() == "s3")
  {
    m_bucket = url.getIp().c_str();
    m_key = url.getPath().c_str();

    if(!m_bucket.empty() && !m_key.empty())
    {
      HeadObjectRequest headObjectRequest;
      headObjectRequest.WithBucket(m_bucket.c_str())
          .WithKey(m_key.c_str());
      auto headObject = m_client.HeadObject(headObjectRequest);
      if(headObject.IsSuccess())
      {
        m_fileSize = headObject.GetResult().GetContentLength();
        m_opened = true;
      }
    }
  }

  if(m_opened) return this;

  return 0;
}

void ossim::S3StreamBuffer::clearAll()
{
  m_bucket = "";
  m_key    = "";
  m_currentPtr = 0;
  m_fileSize = 0;
  m_opened = false;

}

int ossim::S3StreamBuffer::underflow()
{
  if((!gptr())&&is_open())
  {
    if(m_currentPosition >= 0)
    {
      loadBlock(getBlockIndex(m_currentPosition));
    }
    else
    {
      loadBlock(0);
    }

    if(!gptr())
    {
      return EOF;
    }
  }
  else if(!is_open())
  {
    return EOF;
  }
  else if(egptr() == gptr())
  {
    m_currentPosition += m_buffer.size();
    if(m_currentPosition < m_fileSize)
    {
      if(!loadBlock(getBlockIndex(m_currentPosition)))
      {
        return EOF;
      }
    }
    else
    {
     // std::cout << "SHOULD BE EOF RETURNED\n";
      return EOF;
    }
  }

//  std::cout << "GPTR CHARACTER ========== " << (int)(*gptr()) << std::endl;
  return (int)(*gptr());
}
#if 0
int ossim::S3StreamBuffer::uflow()
{
 // std::cout << "ossim::S3StreamBuffer::uflow()\n";

  int result = underflow();

  if(result != EOF)
  {
    result = (int) (*gptr());
    ++m_currentPosition;
    pbump(1);

  }

  return result;
}
#endif
ossim::S3StreamBuffer::pos_type ossim::S3StreamBuffer::seekoff(off_type offset,
                                                               std::ios_base::seekdir dir,
                                                               std::ios_base::openmode mode)
{
//  std::cout << "ossim::S3StreamBuffer::seekoff\n";
  pos_type result = pos_type(off_type(-1));
  bool withinBlock = true;
  if((mode & std::ios_base::in)&&
    (mode & std::ios_base::out))
  {
    return result;
  }
  switch(dir)
  {
    case std::ios_base::beg:
    {
      // if we are determing an absolute position from the beginning then
      // just make sure the offset is within range of the current buffer size
      //
      if((offset < m_fileSize)&&
         (offset >=0))
      {
         result = pos_type(offset);
      }
      break;
    }
    case std::ios_base::cur:
    {
      ossim_int64 testOffset = m_currentPosition + offset;
      if((testOffset >= 0)||(testOffset<m_fileSize))
      {
        result = testOffset;
      }

      break;
    }
    case std::ios_base::end:
    {
      ossim_int64 testOffset = m_fileSize - offset;

      if((testOffset >= 0)||(testOffset<m_fileSize))
      {
        result = testOffset;
      }

      break;
    }
    default:
    {
       break;
    }
  }
  if(m_currentPosition != result)
  {
    adjustForSeekgPosition(result);
  }

  return result;
}

ossim::S3StreamBuffer::pos_type ossim::S3StreamBuffer::seekpos(pos_type pos, std::ios_base::openmode mode)
{
//  std::cout << "ossim::S3StreamBuffer::seekpos\n";
   pos_type result = pos_type(off_type(-1));
   if(mode & std::ios_base::in)
   {
      if(pos >= 0)
      {
         if(pos < m_fileSize)
         {
            result = pos;
         }
      }
      adjustForSeekgPosition(result);
   }

   return result;
}

void ossim::S3StreamBuffer::adjustForSeekgPosition(ossim_int64 seekPosition)
{
  if(seekPosition >= 0)
  {
    ossim_int64 testPosition = static_cast<ossim_int64> (seekPosition);

    if(m_currentPosition >= 0 )
    {
      ossim_int64 blockIndex1 = getBlockIndex(testPosition);
      ossim_int64 blockIndex2 = getBlockIndex(m_currentPosition);

      if(blockIndex1 != blockIndex2)
      {
        m_bufferPtr = m_currentPtr = 0;

        // clear out the pointers and force a load on next read
        setg(m_bufferPtr, m_bufferPtr, m_bufferPtr);
        m_currentPosition = seekPosition;
      }
      else
      {
        ossim_int64 startOffset, endOffset;
        ossim_int64 delta;
        getBlockRangeInBytes(blockIndex1, startOffset, endOffset);
        delta = testPosition-startOffset;
        m_currentPosition = testPosition;
        setg(m_bufferPtr, m_bufferPtr+delta, m_bufferPtr+m_buffer.size());
      }
    }
    else
    {
      m_bufferPtr = m_currentPtr = 0;
      m_currentPosition = seekPosition;
      setg(m_bufferPtr, m_bufferPtr, m_bufferPtr);
    }
  }
  else
  {
    if(m_currentPosition < 0)
    {
      m_bufferPtr = m_currentPtr = 0;
      setg(m_bufferPtr, m_bufferPtr, m_bufferPtr);
    }
  }
}

std::streamsize ossim::S3StreamBuffer::xsgetn(char_type* s, std::streamsize n)
{
//  std::cout << "ossim::S3StreamBuffer::xsgetn" << std::endl;

  if(!is_open()) return EOF;
   // unsigned long int bytesLeftToRead = egptr()-gptr();
  // initialize if we need to to load the block at current position
  if((egptr()==gptr())&&is_open())
  {
    if(m_currentPosition >= 0)
    {
      loadBlock(getBlockIndex(m_currentPosition));
    }
    else
    {
      loadBlock(0);
    }
  }
  ossim_int64 bytesNeedToRead = n;
  ossim_int64 bytesToRead = 0;
  ossim_int64 bytesRead = 0;
  ossim_int64 startOffset, endOffset;
  if(m_currentPosition >= m_fileSize)
  {
    return EOF;
  }
  else if((m_currentPosition + bytesNeedToRead)>(m_fileSize))
  {
    bytesNeedToRead = (m_fileSize - m_currentPosition);
  }

  while(bytesNeedToRead > 0)
  {
    if(egptr()==gptr())
    {
      // load next block
      if(m_currentPosition < m_fileSize)
      {
        if(!loadBlock(getBlockIndex(m_currentPosition)))
        {
          return bytesRead;
        }
      }
      else
      {
        return bytesRead;
      }
    }

    // get each bloc
    if(m_currentPosition>=0)
    {
      //getBlockRangeInBytes(getBlockIndex(m_currentPosition), startOffset, endOffset);

      ossim_int64 delta = (egptr()-gptr());//(endOffset - m_currentPosition)+1;

      if(delta <= bytesNeedToRead)
      {
        std::memcpy(s+bytesRead, gptr(), delta);
        m_currentPosition += delta;
        setg(eback(), egptr(), egptr());
        bytesRead+=delta;
        bytesNeedToRead-=delta;
      }
      else
      {
        std::memcpy(s+bytesRead, gptr(), bytesNeedToRead);
        m_currentPosition += bytesNeedToRead;
        setg(eback(), gptr()+bytesNeedToRead, egptr());
        bytesRead+=bytesNeedToRead;
        bytesNeedToRead=0;
      }
    }
    else
    {
      break;
    }
  }
  return std::streamsize(bytesRead);
}
<commit_msg>Changed default buffer to be 4k.  Probably be better to have 1 meg blocksize<commit_after>#include "ossimS3StreamBuffer.h"

#include <aws/s3/model/PutObjectRequest.h>
#include <aws/s3/model/GetObjectRequest.h>
#include <aws/s3/model/GetObjectResult.h>
#include <aws/s3/model/HeadObjectRequest.h>

#include <aws/core/Aws.h>
#include <aws/core/utils/memory/stl/AWSStringStream.h>
#include <iostream>
#include <ossim/base/ossimUrl.h>
//static const char* KEY = "test-file.txt";
//static const char* BUCKET = "ossimlabs";
#include <cstdio> /* for EOF */
#include <streambuf>
#include <sstream>
#include <iosfwd>
#include <ios>
#include <vector>
#include <cstring> /* for memcpy */

using namespace Aws::S3;
using namespace Aws::S3::Model;

ossim::S3StreamBuffer::S3StreamBuffer()
:
  m_bucket(""),
  m_key(""),
  m_buffer(4096),
  m_bufferActualDataSize(0),
  m_currentPosition(-1),
  m_bufferPtr(0),
  m_currentPtr(0),
  m_fileSize(0),
  m_opened(false),
  m_mode(0)
{
//    std::cout << "CONSTRUCTED!!!!!" << std::endl;
//  setp(0);
  setg(m_currentPtr, m_currentPtr, m_currentPtr);
}

ossim_int64 ossim::S3StreamBuffer::getBlockIndex(ossim_int64 byteOffset)const
{
  ossim_int64 blockNumber = -1;

  if(byteOffset < m_fileSize)
  {
    if(m_buffer.size()>0)
    {
      blockNumber = byteOffset/m_buffer.size();
    }
  }

  return blockNumber;
}

ossim_int64 ossim::S3StreamBuffer::getBlockOffset(ossim_int64 byteOffset)const
{
  ossim_int64 blockOffset = -1;

  if(m_buffer.size()>0)
  {
    blockOffset = byteOffset%m_buffer.size();
  }

  return blockOffset;
}

bool ossim::S3StreamBuffer::getBlockRangeInBytes(ossim_int64 blockIndex,
  ossim_int64& startRange,
  ossim_int64& endRange)const
{
  bool result = false;

  if(blockIndex >= 0)
  {
    startRange = blockIndex*m_buffer.size();
    endRange = startRange + m_buffer.size()-1;

    result = true;
  }

  return result;
}

bool ossim::S3StreamBuffer::loadBlock(ossim_int64 blockIndex)
{
    bool result = false;
    m_bufferPtr = 0;
    m_currentPtr = 0;
    GetObjectRequest getObjectRequest;
    std::stringstream stringStream;
    ossim_int64 startRange, endRange;
    if(getBlockRangeInBytes(blockIndex, startRange, endRange))
    {
      stringStream << "bytes=" << startRange << "-" << endRange;
      getObjectRequest.WithBucket(m_bucket.c_str())
          .WithKey(m_key.c_str()).WithRange(stringStream.str().c_str());
      auto getObjectOutcome = m_client.GetObject(getObjectRequest);

      if(getObjectOutcome.IsSuccess())
      {
//        std::cout << "GOOD CALL!!!!!!!!!!!!\n";
        Aws::IOStream& bodyStream = getObjectOutcome.GetResult().GetBody();
        ossim_uint64 bufSize = getObjectOutcome.GetResult().GetContentLength();
//        std::cout << "SIZE OF RESULT ======== " << bufSize << std::endl;
        m_bufferActualDataSize = bufSize;
        bodyStream.read(&m_buffer.front(), bufSize);
        m_bufferPtr = &m_buffer.front();
        m_currentPtr = m_bufferPtr;

        if(m_currentPosition>=0)
        {
          ossim_int64 delta = m_currentPosition-startRange;
          setg(m_bufferPtr, m_bufferPtr + delta, m_bufferPtr+m_bufferActualDataSize);
        }
        else
        {
          setg(m_bufferPtr, m_bufferPtr, m_bufferPtr + m_bufferActualDataSize);
          m_currentPosition = startRange;
        }
        result = true;
          //std::cout << "Successfully retrieved object from s3 with value: " << std::endl;
          //std::cout << getObjectOutcome.GetResult().GetBody().rdbuf() << std::endl << std::endl;;
      }
    }

    return result;
}

ossim::S3StreamBuffer* ossim::S3StreamBuffer::open (const char* connectionString,
                                                    std::ios_base::openmode m)
{
  std::string temp(connectionString);
  return open(temp, m);
}

ossim::S3StreamBuffer* ossim::S3StreamBuffer::open (const std::string& connectionString,
                                                    std::ios_base::openmode mode)
{
  bool result = false;
  ossimUrl url(connectionString);
  clearAll();
  m_mode = mode;

  if(url.getProtocol() == "s3")
  {
    m_bucket = url.getIp().c_str();
    m_key = url.getPath().c_str();

    if(!m_bucket.empty() && !m_key.empty())
    {
      HeadObjectRequest headObjectRequest;
      headObjectRequest.WithBucket(m_bucket.c_str())
          .WithKey(m_key.c_str());
      auto headObject = m_client.HeadObject(headObjectRequest);
      if(headObject.IsSuccess())
      {
        m_fileSize = headObject.GetResult().GetContentLength();
        m_opened = true;
      }
    }
  }

  if(m_opened) return this;

  return 0;
}

void ossim::S3StreamBuffer::clearAll()
{
  m_bucket = "";
  m_key    = "";
  m_currentPtr = 0;
  m_fileSize = 0;
  m_opened = false;

}

int ossim::S3StreamBuffer::underflow()
{
  if((!gptr())&&is_open())
  {
    if(m_currentPosition >= 0)
    {
      loadBlock(getBlockIndex(m_currentPosition));
    }
    else
    {
      loadBlock(0);
    }

    if(!gptr())
    {
      return EOF;
    }
  }
  else if(!is_open())
  {
    return EOF;
  }
  else if(egptr() == gptr())
  {
    m_currentPosition += m_buffer.size();
    if(m_currentPosition < m_fileSize)
    {
      if(!loadBlock(getBlockIndex(m_currentPosition)))
      {
        return EOF;
      }
    }
    else
    {
     // std::cout << "SHOULD BE EOF RETURNED\n";
      return EOF;
    }
  }

//  std::cout << "GPTR CHARACTER ========== " << (int)(*gptr()) << std::endl;
  return (int)(*gptr());
}
#if 0
int ossim::S3StreamBuffer::uflow()
{
 // std::cout << "ossim::S3StreamBuffer::uflow()\n";

  int result = underflow();

  if(result != EOF)
  {
    result = (int) (*gptr());
    ++m_currentPosition;
    pbump(1);

  }

  return result;
}
#endif
ossim::S3StreamBuffer::pos_type ossim::S3StreamBuffer::seekoff(off_type offset,
                                                               std::ios_base::seekdir dir,
                                                               std::ios_base::openmode mode)
{
//  std::cout << "ossim::S3StreamBuffer::seekoff\n";
  pos_type result = pos_type(off_type(-1));
  bool withinBlock = true;
  if((mode & std::ios_base::in)&&
    (mode & std::ios_base::out))
  {
    return result;
  }
  switch(dir)
  {
    case std::ios_base::beg:
    {
      // if we are determing an absolute position from the beginning then
      // just make sure the offset is within range of the current buffer size
      //
      if((offset < m_fileSize)&&
         (offset >=0))
      {
         result = pos_type(offset);
      }
      break;
    }
    case std::ios_base::cur:
    {
      ossim_int64 testOffset = m_currentPosition + offset;
      if((testOffset >= 0)||(testOffset<m_fileSize))
      {
        result = testOffset;
      }

      break;
    }
    case std::ios_base::end:
    {
      ossim_int64 testOffset = m_fileSize - offset;

      if((testOffset >= 0)||(testOffset<m_fileSize))
      {
        result = testOffset;
      }

      break;
    }
    default:
    {
       break;
    }
  }
  if(m_currentPosition != result)
  {
    adjustForSeekgPosition(result);
  }

  return result;
}

ossim::S3StreamBuffer::pos_type ossim::S3StreamBuffer::seekpos(pos_type pos, std::ios_base::openmode mode)
{
//  std::cout << "ossim::S3StreamBuffer::seekpos\n";
   pos_type result = pos_type(off_type(-1));
   if(mode & std::ios_base::in)
   {
      if(pos >= 0)
      {
         if(pos < m_fileSize)
         {
            result = pos;
         }
      }
      adjustForSeekgPosition(result);
   }

   return result;
}

void ossim::S3StreamBuffer::adjustForSeekgPosition(ossim_int64 seekPosition)
{
  if(seekPosition >= 0)
  {
    ossim_int64 testPosition = static_cast<ossim_int64> (seekPosition);

    if(m_currentPosition >= 0 )
    {
      ossim_int64 blockIndex1 = getBlockIndex(testPosition);
      ossim_int64 blockIndex2 = getBlockIndex(m_currentPosition);

      if(blockIndex1 != blockIndex2)
      {
        m_bufferPtr = m_currentPtr = 0;

        // clear out the pointers and force a load on next read
        setg(m_bufferPtr, m_bufferPtr, m_bufferPtr);
        m_currentPosition = seekPosition;
      }
      else
      {
        ossim_int64 startOffset, endOffset;
        ossim_int64 delta;
        getBlockRangeInBytes(blockIndex1, startOffset, endOffset);
        delta = testPosition-startOffset;
        m_currentPosition = testPosition;
        setg(m_bufferPtr, m_bufferPtr+delta, m_bufferPtr+m_buffer.size());
      }
    }
    else
    {
      m_bufferPtr = m_currentPtr = 0;
      m_currentPosition = seekPosition;
      setg(m_bufferPtr, m_bufferPtr, m_bufferPtr);
    }
  }
  else
  {
    if(m_currentPosition < 0)
    {
      m_bufferPtr = m_currentPtr = 0;
      setg(m_bufferPtr, m_bufferPtr, m_bufferPtr);
    }
  }
}

std::streamsize ossim::S3StreamBuffer::xsgetn(char_type* s, std::streamsize n)
{
//  std::cout << "ossim::S3StreamBuffer::xsgetn" << std::endl;

  if(!is_open()) return EOF;
   // unsigned long int bytesLeftToRead = egptr()-gptr();
  // initialize if we need to to load the block at current position
  if((egptr()==gptr())&&is_open())
  {
    if(m_currentPosition >= 0)
    {
      loadBlock(getBlockIndex(m_currentPosition));
    }
    else
    {
      loadBlock(0);
    }
  }
  ossim_int64 bytesNeedToRead = n;
  ossim_int64 bytesToRead = 0;
  ossim_int64 bytesRead = 0;
  ossim_int64 startOffset, endOffset;
  if(m_currentPosition >= m_fileSize)
  {
    return EOF;
  }
  else if((m_currentPosition + bytesNeedToRead)>(m_fileSize))
  {
    bytesNeedToRead = (m_fileSize - m_currentPosition);
  }

  while(bytesNeedToRead > 0)
  {
    if(egptr()==gptr())
    {
      // load next block
      if(m_currentPosition < m_fileSize)
      {
        if(!loadBlock(getBlockIndex(m_currentPosition)))
        {
          return bytesRead;
        }
      }
      else
      {
        return bytesRead;
      }
    }

    // get each bloc
    if(m_currentPosition>=0)
    {
      //getBlockRangeInBytes(getBlockIndex(m_currentPosition), startOffset, endOffset);

      ossim_int64 delta = (egptr()-gptr());//(endOffset - m_currentPosition)+1;

      if(delta <= bytesNeedToRead)
      {
        std::memcpy(s+bytesRead, gptr(), delta);
        m_currentPosition += delta;
        setg(eback(), egptr(), egptr());
        bytesRead+=delta;
        bytesNeedToRead-=delta;
      }
      else
      {
        std::memcpy(s+bytesRead, gptr(), bytesNeedToRead);
        m_currentPosition += bytesNeedToRead;
        setg(eback(), gptr()+bytesNeedToRead, egptr());
        bytesRead+=bytesNeedToRead;
        bytesNeedToRead=0;
      }
    }
    else
    {
      break;
    }
  }
  return std::streamsize(bytesRead);
}
<|endoftext|>


<commit_before>#include <NeuralNetwork/NeuralLayer/ConvolutionLayer.h>
#include <NeuralNetwork/NeuralLayer/NeuralLayer.h>
#include <NeuralNetwork/Neuron/ActivationFunction/SigmoidFunction.h>
#include <NeuralNetwork/Neuron/Neuron.h>

#include <range/v3/all.hpp>

#define CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS
#include <catch.hpp>

namespace {
    template< typename Neuron >
    bool hasValidInputs(const Neuron& neuron, const std::vector< float >& expected) {
        for(int i = 0; i < expected.size(); i++) {
            if(neuron[i].value != expected[i])
                return false;
        }

        return true;
    }
} // namespace

SCENARIO("Perceptron calculation with convolution layer",
         "[perceptron][convolution][forward]") {
    GIVEN(
     "A convolution layer with  the given set of connections:\n"
     "[0-5]->0,\n"
     "[2-7]->2,\n"
     "[4-9]->3,\n"
     "[6-10]->4") {
        using ConvolutionLayer =
         nn::ConvolutionLayer< nn::NeuralLayer< nn::Neuron, nn::SigmoidFunction, 4, 10 >,
                               nn::Connection< nn::InputRange< 0, 5 >, 0 >,
                               nn::Connection< nn::InputRange< 2, 7 >, 1 >,
                               nn::Connection< nn::InputRange< 4, 9 >, 2 >,
                               nn::Connection< nn::InputRange< 6, 10 >, 3 > >;

        WHEN("Input is [0,1,2,3,4,5,6,7,8,9]") {
            ConvolutionLayer layer;
            for(const auto input : ranges::v3::view::ints(0, 10)) {
                layer.setInput(input, input);
            }
            THEN(
             "neuron 0 has inputs = [0,1,2,3,4,0,0,0,0,0]\n"
             "neuron 1 has inputs = [0,0,2,3,4,5,6,0,0,0]\n"
             "neuron 2 has inputs = [0,0,0,0,4,5,6,7,8,0]\n"
             "neuron 3 has inputs = [0,0,0,0,0,0,6,7,8,9]\n") {
                std::vector< std::vector< float > > inputs = {
                 {0, 1, 2, 3, 4, 0, 0, 0, 0, 0},
                 {0, 0, 2, 3, 4, 5, 6, 0, 0, 0},
                 {0, 0, 0, 0, 4, 5, 6, 7, 8, 0},
                 {0, 0, 0, 0, 0, 0, 6, 7, 8, 9}};

                for(const auto id : ranges::v3::view::ints(0, 4)) {
                    REQUIRE(hasValidInputs(layer[id], inputs[id]));
                }
            }
        }
    }
}<commit_msg>Fix test<commit_after><|endoftext|>


<commit_before>#include "window.hh"

#include "assert.hh"
#include "context.hh"
#include "highlighter.hh"
#include "hook_manager.hh"
#include "input_handler.hh"
#include "user_interface.hh"

#include <algorithm>
#include <sstream>

namespace Kakoune
{

// Implementation in highlighters.cc
void highlight_selections(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange range);
void expand_tabulations(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange range);
void expand_unprintable(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange range);

Window::Window(Buffer& buffer)
    : Scope(buffer),
      m_buffer(&buffer)
{
    run_hook_in_own_context("WinCreate", buffer.name());

    options().register_watcher(*this);

    m_builtin_highlighters.add_child({"tabulations"_str, make_simple_highlighter(expand_tabulations)});
    m_builtin_highlighters.add_child({"unprintable"_str, make_simple_highlighter(expand_unprintable)});
    m_builtin_highlighters.add_child({"selections"_str,  make_simple_highlighter(highlight_selections)});

    for (auto& option : options().flatten_options())
        on_option_changed(*option);
}

Window::~Window()
{
    run_hook_in_own_context("WinClose", buffer().name());
    options().unregister_watcher(*this);
}

void Window::display_line_at(LineCount buffer_line, LineCount display_line)
{
    if (display_line >= 0 or display_line < m_dimensions.line)
        m_position.line = std::max(0_line, buffer_line - display_line);
}

void Window::center_line(LineCount buffer_line)
{
    display_line_at(buffer_line, m_dimensions.line/2_line);
}

void Window::scroll(LineCount offset)
{
    m_position.line = std::max(0_line, m_position.line + offset);
}

void Window::scroll(CharCount offset)
{
    m_position.column = std::max(0_char, m_position.column + offset);
}

size_t Window::compute_hash(const Context& context) const
{
    size_t res = hash_values(m_position, context.ui().dimensions(), context.buffer().timestamp());

    auto& selections = context.selections();
    res = combine_hash(res, hash_value(selections.main_index()));
    for (auto& sel : selections)
        res = combine_hash(res, hash_values((const ByteCoord&)sel.cursor(), sel.anchor()));

    return res;
}

bool Window::needs_redraw(const Context& context) const
{
    size_t hash = compute_hash(context);
    return hash != m_hash;
}

const DisplayBuffer& Window::update_display_buffer(const Context& context)
{
    DisplayBuffer::LineList& lines = m_display_buffer.lines();
    lines.clear();

    m_dimensions = context.ui().dimensions();
    if (m_dimensions == CharCoord{0,0})
        return m_display_buffer;

    kak_assert(&buffer() == &context.buffer());
    scroll_to_keep_selection_visible_ifn(context);

    for (LineCount line = 0; line < m_dimensions.line; ++line)
    {
        LineCount buffer_line = m_position.line + line;
        if (buffer_line >= buffer().line_count())
            break;
        lines.emplace_back(AtomList{ {buffer(), buffer_line, buffer_line+1} });
    }

    m_display_buffer.compute_range();
    BufferRange range{{0,0}, buffer().end_coord()};
    m_highlighters.highlight(context, HighlightFlags::Highlight, m_display_buffer, range);
    m_builtin_highlighters.highlight(context, HighlightFlags::Highlight, m_display_buffer, range);

    // cut the start of the line before m_position.column
    for (auto& line : lines)
        line.trim(m_position.column, m_dimensions.column, true);
    m_display_buffer.optimize();

    m_hash = compute_hash(context);

    return m_display_buffer;
}

void Window::set_position(CharCoord position)
{
    m_position.line = std::max(0_line, position.line);
    m_position.column = std::max(0_char, position.column);
}

void Window::set_dimensions(CharCoord dimensions)
{
    m_dimensions = dimensions;
}

static LineCount adapt_view_pos(LineCount line, LineCount offset,
                                LineCount view_pos, LineCount view_size,
                                LineCount buffer_size)
{
    if (line - offset < view_pos)
        return std::max(0_line, line - offset);
    else if (line + offset >= view_pos + view_size)
        return std::max(0_line, std::min(buffer_size - view_size,
                                         line + offset - (view_size - 1)));
    return view_pos;
}

static CharCount adapt_view_pos(const DisplayBuffer& display_buffer, CharCount offset,
                                ByteCoord pos, CharCount view_pos, CharCount view_size)
{
    CharCount buffer_column = 0;
    CharCount non_buffer_column = 0;
    for (auto& line : display_buffer.lines())
    {
        for (auto& atom : line)
        {
            if (atom.has_buffer_range())
            {
                if (atom.begin() <= pos and atom.end() > pos)
                {
                    CharCount pos_beg, pos_end;
                    if (atom.type() == DisplayAtom::BufferRange)
                    {
                        auto& buf = atom.buffer();
                        pos_beg = buffer_column
                                + utf8::distance(buf.iterator_at(atom.begin()),
                                                 buf.iterator_at(pos));
                        pos_end = pos_beg+1;
                    }
                    else
                    {
                        pos_beg = buffer_column;
                        pos_end = pos_beg + atom.length();
                    }

                    if (pos_beg - offset < view_pos)
                        return std::max(0_char, pos_beg - offset);

                    if (pos_end + offset >= view_pos + view_size - non_buffer_column)
                        return pos_end + offset - view_size + non_buffer_column;
                }
                buffer_column += atom.length();
            }
            else
                non_buffer_column += atom.length();
        }
    }
    return view_pos;
}

void Window::scroll_to_keep_selection_visible_ifn(const Context& context)
{
    auto& selection = context.selections().main();
    const auto& anchor = selection.anchor();
    const auto& cursor  = selection.cursor();

    const CharCoord max_offset{(m_dimensions.line - 1)/2,
                               (m_dimensions.column - 1)/2};
    const CharCoord offset = std::min(options()["scrolloff"].get<CharCoord>(),
                                      max_offset);

    // scroll lines if needed, try to get as much of the selection visible as possible
    m_position.line = adapt_view_pos(anchor.line, offset.line, m_position.line,
                                     m_dimensions.line, buffer().line_count());
    m_position.line = adapt_view_pos(cursor.line,  offset.line, m_position.line,
                                     m_dimensions.line, buffer().line_count());

    // highlight only the line containing the cursor
    DisplayBuffer display_buffer;
    DisplayBuffer::LineList& lines = display_buffer.lines();
    lines.emplace_back(AtomList{ {buffer(), cursor.line, cursor.line+1} });

    display_buffer.compute_range();
    BufferRange range{cursor.line, cursor.line + 1};
    m_highlighters.highlight(context, HighlightFlags::MoveOnly, display_buffer, range);
    m_builtin_highlighters.highlight(context, HighlightFlags::MoveOnly, display_buffer, range);

    // now we can compute where the cursor is in display columns
    // (this is only valid if highlighting one line and multiple lines put
    // the cursor in the same position, however I do not find any sane example
    // of highlighters not doing that)
    m_position.column = adapt_view_pos(display_buffer, offset.column,
                                       anchor.line == cursor.line ? anchor : cursor.line,
                                       m_position.column, m_dimensions.column);
    m_position.column = adapt_view_pos(display_buffer, offset.column, cursor,
                                       m_position.column, m_dimensions.column);
}

namespace
{
CharCount find_display_column(const DisplayLine& line, const Buffer& buffer,
                              ByteCoord coord)
{
    CharCount column = 0;
    for (auto& atom : line)
    {
        if (atom.has_buffer_range() and
            coord >= atom.begin() and coord < atom.end())
        {
            if (atom.type() == DisplayAtom::BufferRange)
                column += utf8::distance(buffer.iterator_at(atom.begin()),
                                         buffer.iterator_at(coord));
            return column;
        }
        column += atom.length();
    }
    return column;
}

ByteCoord find_buffer_coord(const DisplayLine& line, const Buffer& buffer,
                            CharCount column)
{
    auto& range = line.range();
    for (auto& atom : line)
    {
        CharCount len = atom.length();
        if (atom.has_buffer_range() and column < len)
        {
            if (atom.type() == DisplayAtom::BufferRange)
                return utf8::advance(buffer.iterator_at(atom.begin()), buffer.iterator_at(range.end),
                                     std::max(0_char, column)).coord();
             return atom.begin();
        }
        column -= len;
    }
    return buffer.clamp(buffer.prev(range.end));
}
}

CharCoord Window::display_position(ByteCoord coord) const
{
    LineCount l = 0;
    for (auto& line : m_display_buffer.lines())
    {
        auto& range = line.range();
        if (range.begin <= coord and coord < range.end)
            return {l, find_display_column(line, buffer(), coord)};
        ++l;
    }
    return { 0, 0 };
}

ByteCoord Window::buffer_coord(CharCoord coord) const
{
    if (coord <= 0_line)
        coord = {0,0};
    if ((int)coord.line >= m_display_buffer.lines().size())
        coord = CharCoord{(int)m_display_buffer.lines().size()-1, INT_MAX};

    return find_buffer_coord(m_display_buffer.lines()[(int)coord.line],
                             buffer(), coord.column);
}

ByteCoord Window::offset_coord(ByteCoord coord, CharCount offset)
{
    return buffer().offset_coord(coord, offset);
}

ByteCoordAndTarget Window::offset_coord(ByteCoordAndTarget coord, LineCount offset)
{
    auto line = clamp(coord.line + offset, 0_line, buffer().line_count()-1);
    DisplayBuffer display_buffer;
    DisplayBuffer::LineList& lines = display_buffer.lines();
    lines.emplace_back(AtomList{ {buffer(), coord.line, coord.line+1} });
    lines.emplace_back(AtomList{ {buffer(), line, line+1} });
    display_buffer.compute_range();

    BufferRange range{ std::min(line, coord.line), std::max(line,coord.line)+1};

    InputHandler input_handler{{ *m_buffer, Selection{} }, Context::Flags::Transient};
    input_handler.context().set_window(*this);
    m_highlighters.highlight(input_handler.context(), HighlightFlags::MoveOnly, display_buffer, range);
    m_builtin_highlighters.highlight(input_handler.context(), HighlightFlags::MoveOnly, display_buffer, range);

    CharCount column = coord.target == -1 ? find_display_column(lines[0], buffer(), coord) : coord.target;
    return { find_buffer_coord(lines[1], buffer(), column), column };
}

void Window::clear_display_buffer()
{
    m_display_buffer = DisplayBuffer{};
}

void Window::on_option_changed(const Option& option)
{
    run_hook_in_own_context("WinSetOption",
                            format("{}={}", option.name(), option.get_as_string()));

    // an highlighter might depend on the option, so we need to redraw
    force_redraw();
}

void Window::run_hook_in_own_context(StringView hook_name, StringView param)
{
    InputHandler hook_handler({ *m_buffer, Selection{} }, Context::Flags::Transient);
    hook_handler.context().set_window(*this);
    hooks().run_hook(hook_name, param, hook_handler.context());
}
}
<commit_msg>Change scrolloff behaviour, allow displaying pas the end of buffer<commit_after>#include "window.hh"

#include "assert.hh"
#include "context.hh"
#include "highlighter.hh"
#include "hook_manager.hh"
#include "input_handler.hh"
#include "user_interface.hh"

#include <algorithm>
#include <sstream>

namespace Kakoune
{

// Implementation in highlighters.cc
void highlight_selections(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange range);
void expand_tabulations(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange range);
void expand_unprintable(const Context& context, HighlightFlags flags, DisplayBuffer& display_buffer, BufferRange range);

Window::Window(Buffer& buffer)
    : Scope(buffer),
      m_buffer(&buffer)
{
    run_hook_in_own_context("WinCreate", buffer.name());

    options().register_watcher(*this);

    m_builtin_highlighters.add_child({"tabulations"_str, make_simple_highlighter(expand_tabulations)});
    m_builtin_highlighters.add_child({"unprintable"_str, make_simple_highlighter(expand_unprintable)});
    m_builtin_highlighters.add_child({"selections"_str,  make_simple_highlighter(highlight_selections)});

    for (auto& option : options().flatten_options())
        on_option_changed(*option);
}

Window::~Window()
{
    run_hook_in_own_context("WinClose", buffer().name());
    options().unregister_watcher(*this);
}

void Window::display_line_at(LineCount buffer_line, LineCount display_line)
{
    if (display_line >= 0 or display_line < m_dimensions.line)
        m_position.line = std::max(0_line, buffer_line - display_line);
}

void Window::center_line(LineCount buffer_line)
{
    display_line_at(buffer_line, m_dimensions.line/2_line);
}

void Window::scroll(LineCount offset)
{
    m_position.line = std::max(0_line, m_position.line + offset);
}

void Window::scroll(CharCount offset)
{
    m_position.column = std::max(0_char, m_position.column + offset);
}

size_t Window::compute_hash(const Context& context) const
{
    size_t res = hash_values(m_position, context.ui().dimensions(), context.buffer().timestamp());

    auto& selections = context.selections();
    res = combine_hash(res, hash_value(selections.main_index()));
    for (auto& sel : selections)
        res = combine_hash(res, hash_values((const ByteCoord&)sel.cursor(), sel.anchor()));

    return res;
}

bool Window::needs_redraw(const Context& context) const
{
    size_t hash = compute_hash(context);
    return hash != m_hash;
}

const DisplayBuffer& Window::update_display_buffer(const Context& context)
{
    DisplayBuffer::LineList& lines = m_display_buffer.lines();
    lines.clear();

    m_dimensions = context.ui().dimensions();
    if (m_dimensions == CharCoord{0,0})
        return m_display_buffer;

    kak_assert(&buffer() == &context.buffer());
    scroll_to_keep_selection_visible_ifn(context);

    for (LineCount line = 0; line < m_dimensions.line; ++line)
    {
        LineCount buffer_line = m_position.line + line;
        if (buffer_line >= buffer().line_count())
            break;
        lines.emplace_back(AtomList{ {buffer(), buffer_line, buffer_line+1} });
    }

    m_display_buffer.compute_range();
    BufferRange range{{0,0}, buffer().end_coord()};
    m_highlighters.highlight(context, HighlightFlags::Highlight, m_display_buffer, range);
    m_builtin_highlighters.highlight(context, HighlightFlags::Highlight, m_display_buffer, range);

    // cut the start of the line before m_position.column
    for (auto& line : lines)
        line.trim(m_position.column, m_dimensions.column, true);
    m_display_buffer.optimize();

    m_hash = compute_hash(context);

    return m_display_buffer;
}

void Window::set_position(CharCoord position)
{
    m_position.line = std::max(0_line, position.line);
    m_position.column = std::max(0_char, position.column);
}

void Window::set_dimensions(CharCoord dimensions)
{
    m_dimensions = dimensions;
}

static LineCount adapt_view_pos(LineCount line, LineCount offset,
                                LineCount view_pos, LineCount view_size,
                                LineCount buffer_size)
{
    offset = std::min(offset, (view_size + 1) / 2);
    if (line - offset < view_pos)
        return std::max(0_line, line - offset);
    else if (line + offset >= view_pos + view_size)
        return std::max(0_line, line + offset - view_size);
    return view_pos;
}

static CharCount adapt_view_pos(const DisplayBuffer& display_buffer, CharCount offset,
                                ByteCoord pos, CharCount view_pos, CharCount view_size)
{
    offset = std::min(offset, (view_size + 1) / 2);
    CharCount buffer_column = 0;
    CharCount non_buffer_column = 0;
    for (auto& line : display_buffer.lines())
    {
        for (auto& atom : line)
        {
            if (atom.has_buffer_range())
            {
                if (atom.begin() <= pos and atom.end() > pos)
                {
                    CharCount pos_beg, pos_end;
                    if (atom.type() == DisplayAtom::BufferRange)
                    {
                        auto& buf = atom.buffer();
                        pos_beg = buffer_column
                                + utf8::distance(buf.iterator_at(atom.begin()),
                                                 buf.iterator_at(pos));
                        pos_end = pos_beg+1;
                    }
                    else
                    {
                        pos_beg = buffer_column;
                        pos_end = pos_beg + atom.length();
                    }

                    if (pos_beg - offset < view_pos)
                        return std::max(0_char, pos_beg - offset);

                    if (pos_end + offset >= view_pos + view_size - non_buffer_column)
                        return pos_end + offset - view_size + non_buffer_column;
                }
                buffer_column += atom.length();
            }
            else
                non_buffer_column += atom.length();
        }
    }
    return view_pos;
}

void Window::scroll_to_keep_selection_visible_ifn(const Context& context)
{
    auto& selection = context.selections().main();
    const auto& anchor = selection.anchor();
    const auto& cursor  = selection.cursor();

    const CharCoord offset = options()["scrolloff"].get<CharCoord>();

    // scroll lines if needed, try to get as much of the selection visible as possible
    m_position.line = adapt_view_pos(anchor.line, offset.line, m_position.line,
                                     m_dimensions.line, buffer().line_count());
    m_position.line = adapt_view_pos(cursor.line,  offset.line, m_position.line,
                                     m_dimensions.line, buffer().line_count());

    // highlight only the line containing the cursor
    DisplayBuffer display_buffer;
    DisplayBuffer::LineList& lines = display_buffer.lines();
    lines.emplace_back(AtomList{ {buffer(), cursor.line, cursor.line+1} });

    display_buffer.compute_range();
    BufferRange range{cursor.line, cursor.line + 1};
    m_highlighters.highlight(context, HighlightFlags::MoveOnly, display_buffer, range);
    m_builtin_highlighters.highlight(context, HighlightFlags::MoveOnly, display_buffer, range);

    // now we can compute where the cursor is in display columns
    // (this is only valid if highlighting one line and multiple lines put
    // the cursor in the same position, however I do not find any sane example
    // of highlighters not doing that)
    m_position.column = adapt_view_pos(display_buffer, offset.column,
                                       anchor.line == cursor.line ? anchor : cursor.line,
                                       m_position.column, m_dimensions.column);
    m_position.column = adapt_view_pos(display_buffer, offset.column, cursor,
                                       m_position.column, m_dimensions.column);
}

namespace
{
CharCount find_display_column(const DisplayLine& line, const Buffer& buffer,
                              ByteCoord coord)
{
    CharCount column = 0;
    for (auto& atom : line)
    {
        if (atom.has_buffer_range() and
            coord >= atom.begin() and coord < atom.end())
        {
            if (atom.type() == DisplayAtom::BufferRange)
                column += utf8::distance(buffer.iterator_at(atom.begin()),
                                         buffer.iterator_at(coord));
            return column;
        }
        column += atom.length();
    }
    return column;
}

ByteCoord find_buffer_coord(const DisplayLine& line, const Buffer& buffer,
                            CharCount column)
{
    auto& range = line.range();
    for (auto& atom : line)
    {
        CharCount len = atom.length();
        if (atom.has_buffer_range() and column < len)
        {
            if (atom.type() == DisplayAtom::BufferRange)
                return utf8::advance(buffer.iterator_at(atom.begin()), buffer.iterator_at(range.end),
                                     std::max(0_char, column)).coord();
             return atom.begin();
        }
        column -= len;
    }
    return buffer.clamp(buffer.prev(range.end));
}
}

CharCoord Window::display_position(ByteCoord coord) const
{
    LineCount l = 0;
    for (auto& line : m_display_buffer.lines())
    {
        auto& range = line.range();
        if (range.begin <= coord and coord < range.end)
            return {l, find_display_column(line, buffer(), coord)};
        ++l;
    }
    return { 0, 0 };
}

ByteCoord Window::buffer_coord(CharCoord coord) const
{
    if (coord <= 0_line)
        coord = {0,0};
    if ((int)coord.line >= m_display_buffer.lines().size())
        coord = CharCoord{(int)m_display_buffer.lines().size()-1, INT_MAX};

    return find_buffer_coord(m_display_buffer.lines()[(int)coord.line],
                             buffer(), coord.column);
}

ByteCoord Window::offset_coord(ByteCoord coord, CharCount offset)
{
    return buffer().offset_coord(coord, offset);
}

ByteCoordAndTarget Window::offset_coord(ByteCoordAndTarget coord, LineCount offset)
{
    auto line = clamp(coord.line + offset, 0_line, buffer().line_count()-1);
    DisplayBuffer display_buffer;
    DisplayBuffer::LineList& lines = display_buffer.lines();
    lines.emplace_back(AtomList{ {buffer(), coord.line, coord.line+1} });
    lines.emplace_back(AtomList{ {buffer(), line, line+1} });
    display_buffer.compute_range();

    BufferRange range{ std::min(line, coord.line), std::max(line,coord.line)+1};

    InputHandler input_handler{{ *m_buffer, Selection{} }, Context::Flags::Transient};
    input_handler.context().set_window(*this);
    m_highlighters.highlight(input_handler.context(), HighlightFlags::MoveOnly, display_buffer, range);
    m_builtin_highlighters.highlight(input_handler.context(), HighlightFlags::MoveOnly, display_buffer, range);

    CharCount column = coord.target == -1 ? find_display_column(lines[0], buffer(), coord) : coord.target;
    return { find_buffer_coord(lines[1], buffer(), column), column };
}

void Window::clear_display_buffer()
{
    m_display_buffer = DisplayBuffer{};
}

void Window::on_option_changed(const Option& option)
{
    run_hook_in_own_context("WinSetOption",
                            format("{}={}", option.name(), option.get_as_string()));

    // an highlighter might depend on the option, so we need to redraw
    force_redraw();
}

void Window::run_hook_in_own_context(StringView hook_name, StringView param)
{
    InputHandler hook_handler({ *m_buffer, Selection{} }, Context::Flags::Transient);
    hook_handler.context().set_window(*this);
    hooks().run_hook(hook_name, param, hook_handler.context());
}
}
<|endoftext|>