<commit_before>
#include "managesievescriptsdialog.h"
#include "managesievescriptsdialog_p.h"

#include "sieveconfig.h"
#include "accountmanager.h"
#include "imapaccountbase.h"
#include "sievejob.h"
#include "kmkernel.h"

#include <klocale.h>
#include <kiconloader.h>
#include <kwindowsystem.h>
#include <kinputdialog.h>
#include <kglobalsettings.h>
#include <kmessagebox.h>

#include <QLayout>
#include <q3listview.h>
#include <QMenu>
//Added by qt3to4:
#include <QVBoxLayout>

#include <cassert>

inline Q3CheckListItem * qcli_cast( Q3ListViewItem * lvi ) {
  return lvi && lvi->rtti() == 1 ? static_cast<Q3CheckListItem*>( lvi ) : 0 ;
}
inline const Q3CheckListItem * qcli_cast( const Q3ListViewItem * lvi ) {
  return lvi && lvi->rtti() == 1 ? static_cast<const Q3CheckListItem*>( lvi ) : 0 ;
}

KMail::ManageSieveScriptsDialog::ManageSieveScriptsDialog( QWidget * parent, const char * name )
  : KDialog( parent ),
    mSieveEditor( 0 ),
    mContextMenuItem( 0 ),
    mWasActive( false )
{
  setCaption( i18n( "Manage Sieve Scripts" ) );
  setButtons( Close );
  setObjectName( name );
  setDefaultButton(  Close );
  setModal( false );
  setAttribute( Qt::WA_GroupLeader );
  setAttribute( Qt::WA_DeleteOnClose );
  KWindowSystem::setIcons( winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)) );
  QFrame *frame =new QFrame( this );
  setMainWidget( frame );
  QVBoxLayout * vlay = new QVBoxLayout( frame );
  vlay->setSpacing( 0 );
  vlay->setMargin( 0 );

  mListView = new Q3ListView( frame);
  mListView->addColumn( i18n( "Available Scripts" ) );
  mListView->setResizeMode( Q3ListView::LastColumn );
  mListView->setRootIsDecorated( true );
  mListView->setSelectionMode( Q3ListView::Single );
  connect( mListView, SIGNAL(contextMenuRequested(Q3ListViewItem*,const QPoint&,int)),
           this, SLOT(slotContextMenuRequested(Q3ListViewItem*, const QPoint&)) );
  connect( mListView, SIGNAL(doubleClicked(Q3ListViewItem*,const QPoint&,int)),
           this, SLOT(slotDoubleClicked(Q3ListViewItem*)) );
  connect( mListView, SIGNAL(selectionChanged(Q3ListViewItem*)),
           this, SLOT(slotSelectionChanged(Q3ListViewItem*)) );
  vlay->addWidget( mListView );

  resize( 2 * sizeHint().width(), sizeHint().height() );

  slotRefresh();
}

KMail::ManageSieveScriptsDialog::~ManageSieveScriptsDialog() {
  killAllJobs();
}

void KMail::ManageSieveScriptsDialog::killAllJobs() {
  for ( QMap<SieveJob*,Q3CheckListItem*>::const_iterator it = mJobs.constBegin(), end = mJobs.constEnd() ; it != end ; ++it )
    it.key()->kill();
  mJobs.clear();
}

static KUrl findUrlForAccount( const KMail::ImapAccountBase * a ) {
  assert( a );
  const KMail::SieveConfig sieve = a->sieveConfig();
  if ( !sieve.managesieveSupported() )
    return KUrl();
  if ( sieve.reuseConfig() ) {
    // assemble Sieve url from the settings of the account:
    KUrl u;
    u.setProtocol( "sieve" );
    u.setHost( a->host() );
    u.setUser( a->login() );
    u.setPass( a->passwd() );
    u.setPort( sieve.port() );
    // Translate IMAP LOGIN to PLAIN:
    u.setQuery( "x-mech=" + ( a->auth() == "*" ? "PLAIN" : a->auth() ) );
    return u;
  } else {
    return sieve.alternateURL();
  }
}

void KMail::ManageSieveScriptsDialog::slotRefresh() {
  killAllJobs();
  mUrls.clear();
  mListView->clear();

  KMail::AccountManager * am = kmkernel->acctMgr();
  assert( am );
  Q3CheckListItem * last = 0;
  QList<KMAccount*>::iterator accountIt = am->begin();
  while ( accountIt != am->end() ) {
    KMAccount *a = *accountIt;
    ++accountIt;
    last = new Q3CheckListItem( mListView, last, a->name(), Q3CheckListItem::Controller );
    last->setPixmap( 0, SmallIcon( "network-server" ) );
    if ( ImapAccountBase * iab = dynamic_cast<ImapAccountBase*>( a ) ) {
      const KUrl u = ::findUrlForAccount( iab );
      if ( u.isEmpty() )
        continue;
      SieveJob * job = SieveJob::list( u );
      connect( job, SIGNAL(item(KMail::SieveJob*,const QString&,bool)),
               this, SLOT(slotItem(KMail::SieveJob*,const QString&,bool)) );
      connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
               this, SLOT(slotResult(KMail::SieveJob*,bool,const QString&,bool)) );
      mJobs.insert( job, last );
      mUrls.insert( last, u );
    } else {
      Q3ListViewItem * item = new Q3ListViewItem( last, i18n( "No Sieve URL configured" ) );
      item->setEnabled( false );
      last->setOpen( true );
    }
  }
}

void KMail::ManageSieveScriptsDialog::slotResult( KMail::SieveJob * job, bool success, const QString &, bool ) {
  Q3CheckListItem * parent = mJobs[job];
  if ( !parent )
    return;

  mJobs.remove( job );

  parent->setOpen( true );

  if ( success )
    return;

  Q3ListViewItem * item = new Q3ListViewItem( parent, i18n( "Failed to fetch the list of scripts" ) );
  item->setEnabled( false );
}

void KMail::ManageSieveScriptsDialog::slotItem( KMail::SieveJob * job, const QString & filename, bool isActive ) {
  Q3CheckListItem * parent = mJobs[job];
  if ( !parent )
    return;
  Q3CheckListItem * item = new Q3CheckListItem( parent, filename, Q3CheckListItem::RadioButton );
  if ( isActive ) {
    item->setOn( true );
    mSelectedItems[parent] = item;
  }
}

void KMail::ManageSieveScriptsDialog::slotContextMenuRequested( Q3ListViewItem * i, const QPoint & p ) {
  Q3CheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  if ( !item->depth() && !mUrls.count( item ) )
    return;
  QMenu menu;
  mContextMenuItem = item;
  if ( item->depth() ) {
    // script items:
    menu.addAction( i18n( "Delete Script" ), this, SLOT(slotDeleteScript()) );
    menu.addAction( i18n( "Edit Script..." ), this, SLOT(slotEditScript()) );
  } else {
    // top-levels:
    menu.addAction( i18n( "New Script..." ), this, SLOT(slotNewScript()) );
  }
  menu.exec( p );
  mContextMenuItem = 0;
}

void KMail::ManageSieveScriptsDialog::slotSelectionChanged( Q3ListViewItem * i ) {
  Q3CheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  Q3CheckListItem * parent = qcli_cast( item->parent() );
  if ( !parent )
    return;
  if ( item->isOn() && mSelectedItems[parent] != item ) {
    mSelectedItems[parent] = item;
    changeActiveScript( parent );
  }
}

void KMail::ManageSieveScriptsDialog::changeActiveScript( Q3CheckListItem * item ) {
  if ( !item )
    return;
  if ( !mUrls.count( item ) )
    return;
  if ( !mSelectedItems.count( item ) )
    return;
  KUrl u = mUrls[item];
  if ( u.isEmpty() )
    return;
  Q3CheckListItem * selected = mSelectedItems[item];
  if ( !selected )
    return;
  u.setFileName( selected->text( 0 ) );

  SieveJob * job = SieveJob::activate( u );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotRefresh()) );
}

void KMail::ManageSieveScriptsDialog::slotDoubleClicked( Q3ListViewItem * i ) {
  Q3CheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  if ( !item->depth() )
    return;
  mContextMenuItem = item;
  slotEditScript();
  mContextMenuItem = 0;
}

void KMail::ManageSieveScriptsDialog::slotDeleteScript() {
  if ( !mContextMenuItem )
    return;
  if ( !mContextMenuItem->depth() )
    return;

  Q3CheckListItem * parent = qcli_cast( mContextMenuItem->parent() );
  if ( !parent )
    return;

  if ( !mUrls.count( parent ) )
    return;

  KUrl u = mUrls[parent];
  if ( u.isEmpty() )
    return;

  u.setFileName( mContextMenuItem->text( 0 ) );

  if ( KMessageBox::warningContinueCancel( this, i18n( "Really delete script \"%1\" from the server?", u.fileName() ),
                                   i18n( "Delete Sieve Script Confirmation" ),
                                   KStandardGuiItem::del() )
       != KMessageBox::Continue )
    return;

  SieveJob * job = SieveJob::del( u );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotRefresh()) );
}

void KMail::ManageSieveScriptsDialog::slotEditScript() {
  if ( !mContextMenuItem )
    return;
  if ( !mContextMenuItem->depth() )
    return;
  Q3CheckListItem * parent = qcli_cast( mContextMenuItem->parent() );
  if ( !mUrls.count( parent ) )
    return;
  KUrl url = mUrls[parent];
  if ( url.isEmpty() )
    return;
  url.setFileName( mContextMenuItem->text( 0 ) );
  mCurrentURL = url;
  SieveJob * job = SieveJob::get( url );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotGetResult(KMail::SieveJob*,bool,const QString&,bool)) );
}

void KMail::ManageSieveScriptsDialog::slotNewScript() {
  if ( !mContextMenuItem )
    return;
  if ( mContextMenuItem->depth() )
    mContextMenuItem = qcli_cast( mContextMenuItem->parent() );
  if ( !mContextMenuItem )
    return;

  if ( !mUrls.count( mContextMenuItem ) )
    return;

  KUrl u = mUrls[mContextMenuItem];
  if ( u.isEmpty() )
    return;

  bool ok = false;
  const QString name = KInputDialog::getText( i18n( "New Sieve Script" ),
                                              i18n( "Please enter a name for the new Sieve script:" ),
                                              i18n( "unnamed" ), &ok, this );
  if ( !ok || name.isEmpty() )
    return;

  u.setFileName( name );

  (void) new Q3CheckListItem( mContextMenuItem, name, Q3CheckListItem::RadioButton );

  mCurrentURL = u;
  slotGetResult( 0, true, QString(), false );
}

KMail::SieveEditor::SieveEditor( QWidget * parent, const char * name )
  : KDialog( parent )
{
  setCaption( i18n( "Edit Sieve Script" ) );
  setButtons( Ok|Cancel );
  setObjectName( name );
  setDefaultButton( Ok );
  setModal( true );
  QFrame *frame = new QFrame( this );
  setMainWidget( frame );
  QVBoxLayout * vlay = new QVBoxLayout( frame );
  vlay->setSpacing( spacingHint() );
  vlay->setMargin( 0 );
  mTextEdit = new KTextEdit( frame);
  vlay->addWidget( mTextEdit );
  mTextEdit->setAcceptRichText( false );
  mTextEdit->setWordWrapMode ( QTextOption::NoWrap );
  mTextEdit->setFont( KGlobalSettings::fixedFont() );

  resize( 3 * sizeHint() );
}

KMail::SieveEditor::~SieveEditor() {}

void KMail::ManageSieveScriptsDialog::slotGetResult( KMail::SieveJob *, bool success, const QString & script, bool isActive ) {
  if ( !success )
    return;

  if ( mSieveEditor )
    return;

  mSieveEditor = new SieveEditor( this );
  mSieveEditor->setScript( script );
  connect( mSieveEditor, SIGNAL(okClicked()), this, SLOT(slotSieveEditorOkClicked()) );
  connect( mSieveEditor, SIGNAL(cancelClicked()), this, SLOT(slotSieveEditorCancelClicked()) );
  mSieveEditor->show();
  mWasActive = isActive;
}

void KMail::ManageSieveScriptsDialog::slotSieveEditorOkClicked() {
  if ( !mSieveEditor )
    return;
  SieveJob * job = SieveJob::put( mCurrentURL,mSieveEditor->script(), mWasActive, mWasActive );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotPutResult(KMail::SieveJob*,bool)) );
}

void KMail::ManageSieveScriptsDialog::slotSieveEditorCancelClicked() {
  mSieveEditor->deleteLater(); mSieveEditor = 0;
  mCurrentURL = KUrl();
}

void KMail::ManageSieveScriptsDialog::slotPutResult( KMail::SieveJob *, bool success ) {
  if ( success ) {
    KMessageBox::information( this, i18n( "The Sieve script was successfully uploaded." ),
                              i18n( "Sieve Script Upload" ) );
    mSieveEditor->deleteLater(); mSieveEditor = 0;
    mCurrentURL = KUrl();
  } else {
    mSieveEditor->show();
  }
}

#include "managesievescriptsdialog.moc"
#include "managesievescriptsdialog_p.moc"
<commit_msg>Backport r924638 by tmcguire from trunk to the 4.2 branch:<commit_after>
#include "managesievescriptsdialog.h"
#include "managesievescriptsdialog_p.h"

#include "sieveconfig.h"
#include "accountmanager.h"
#include "imapaccountbase.h"
#include "sievejob.h"
#include "kmkernel.h"

#include <klocale.h>
#include <kiconloader.h>
#include <kwindowsystem.h>
#include <kinputdialog.h>
#include <kglobalsettings.h>
#include <kmessagebox.h>

#include <QLayout>
#include <q3listview.h>
#include <QMenu>
//Added by qt3to4:
#include <QVBoxLayout>

#include <cassert>

inline Q3CheckListItem * qcli_cast( Q3ListViewItem * lvi ) {
  return lvi && lvi->rtti() == 1 ? static_cast<Q3CheckListItem*>( lvi ) : 0 ;
}
inline const Q3CheckListItem * qcli_cast( const Q3ListViewItem * lvi ) {
  return lvi && lvi->rtti() == 1 ? static_cast<const Q3CheckListItem*>( lvi ) : 0 ;
}

KMail::ManageSieveScriptsDialog::ManageSieveScriptsDialog( QWidget * parent, const char * name )
  : KDialog( parent ),
    mSieveEditor( 0 ),
    mContextMenuItem( 0 ),
    mWasActive( false )
{
  setCaption( i18n( "Manage Sieve Scripts" ) );
  setButtons( Close );
  setObjectName( name );
  setDefaultButton(  Close );
  setModal( false );
  setAttribute( Qt::WA_GroupLeader );
  setAttribute( Qt::WA_DeleteOnClose );
  KWindowSystem::setIcons( winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)) );
  QFrame *frame =new QFrame( this );
  setMainWidget( frame );
  QVBoxLayout * vlay = new QVBoxLayout( frame );
  vlay->setSpacing( 0 );
  vlay->setMargin( 0 );

  mListView = new Q3ListView( frame);
  mListView->addColumn( i18n( "Available Scripts" ) );
  mListView->setResizeMode( Q3ListView::LastColumn );
  mListView->setRootIsDecorated( true );
  mListView->setSelectionMode( Q3ListView::Single );
  connect( mListView, SIGNAL(contextMenuRequested(Q3ListViewItem*,const QPoint&,int)),
           this, SLOT(slotContextMenuRequested(Q3ListViewItem*, const QPoint&)) );
  connect( mListView, SIGNAL(doubleClicked(Q3ListViewItem*,const QPoint&,int)),
           this, SLOT(slotDoubleClicked(Q3ListViewItem*)) );
  connect( mListView, SIGNAL(selectionChanged(Q3ListViewItem*)),
           this, SLOT(slotSelectionChanged(Q3ListViewItem*)) );
  vlay->addWidget( mListView );

  resize( 2 * sizeHint().width(), sizeHint().height() );

  slotRefresh();
}

KMail::ManageSieveScriptsDialog::~ManageSieveScriptsDialog() {
  killAllJobs();
}

void KMail::ManageSieveScriptsDialog::killAllJobs() {
  for ( QMap<SieveJob*,Q3CheckListItem*>::const_iterator it = mJobs.constBegin(), end = mJobs.constEnd() ; it != end ; ++it )
    it.key()->kill();
  mJobs.clear();
}

static KUrl findUrlForAccount( const KMail::ImapAccountBase * a ) {
  assert( a );
  const KMail::SieveConfig sieve = a->sieveConfig();
  if ( !sieve.managesieveSupported() )
    return KUrl();
  if ( sieve.reuseConfig() ) {
    // assemble Sieve url from the settings of the account:
    KUrl u;
    u.setProtocol( "sieve" );
    u.setHost( a->host() );
    u.setUser( a->login() );
    u.setPass( a->passwd() );
    u.setPort( sieve.port() );
    // Translate IMAP LOGIN to PLAIN:
    u.setQuery( "x-mech=" + ( a->auth() == "*" ? "PLAIN" : a->auth() ) );
    return u;
  } else {
    return sieve.alternateURL();
  }
}

void KMail::ManageSieveScriptsDialog::slotRefresh() {
  killAllJobs();
  mUrls.clear();
  mListView->clear();

  KMail::AccountManager * am = kmkernel->acctMgr();
  assert( am );
  Q3CheckListItem * last = 0;
  QList<KMAccount*>::iterator accountIt = am->begin();
  while ( accountIt != am->end() ) {
    KMAccount *a = *accountIt;
    ++accountIt;

    // Don't show POP3 accounts in the sieve list
    if ( a->type() != KAccount::Imap &&
         a->type() != KAccount::DImap )
      continue;

    last = new Q3CheckListItem( mListView, last, a->name(), Q3CheckListItem::Controller );
    last->setPixmap( 0, SmallIcon( "network-server" ) );
    if ( ImapAccountBase * iab = dynamic_cast<ImapAccountBase*>( a ) ) {
      const KUrl u = ::findUrlForAccount( iab );
      if ( u.isEmpty() )
        continue;
      SieveJob * job = SieveJob::list( u );
      connect( job, SIGNAL(item(KMail::SieveJob*,const QString&,bool)),
               this, SLOT(slotItem(KMail::SieveJob*,const QString&,bool)) );
      connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
               this, SLOT(slotResult(KMail::SieveJob*,bool,const QString&,bool)) );
      mJobs.insert( job, last );
      mUrls.insert( last, u );
    } else {
      Q3ListViewItem * item = new Q3ListViewItem( last, i18n( "No Sieve URL configured" ) );
      item->setEnabled( false );
      last->setOpen( true );
    }
  }
}

void KMail::ManageSieveScriptsDialog::slotResult( KMail::SieveJob * job, bool success, const QString &, bool ) {
  Q3CheckListItem * parent = mJobs[job];
  if ( !parent )
    return;

  mJobs.remove( job );

  parent->setOpen( true );

  if ( success )
    return;

  Q3ListViewItem * item = new Q3ListViewItem( parent, i18n( "Failed to fetch the list of scripts" ) );
  item->setEnabled( false );
}

void KMail::ManageSieveScriptsDialog::slotItem( KMail::SieveJob * job, const QString & filename, bool isActive ) {
  Q3CheckListItem * parent = mJobs[job];
  if ( !parent )
    return;
  Q3CheckListItem * item = new Q3CheckListItem( parent, filename, Q3CheckListItem::RadioButton );
  if ( isActive ) {
    item->setOn( true );
    mSelectedItems[parent] = item;
  }
}

void KMail::ManageSieveScriptsDialog::slotContextMenuRequested( Q3ListViewItem * i, const QPoint & p ) {
  Q3CheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  if ( !item->depth() && !mUrls.count( item ) )
    return;
  QMenu menu;
  mContextMenuItem = item;
  if ( item->depth() ) {
    // script items:
    menu.addAction( i18n( "Delete Script" ), this, SLOT(slotDeleteScript()) );
    menu.addAction( i18n( "Edit Script..." ), this, SLOT(slotEditScript()) );
  } else {
    // top-levels:
    menu.addAction( i18n( "New Script..." ), this, SLOT(slotNewScript()) );
  }
  menu.exec( p );
  mContextMenuItem = 0;
}

void KMail::ManageSieveScriptsDialog::slotSelectionChanged( Q3ListViewItem * i ) {
  Q3CheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  Q3CheckListItem * parent = qcli_cast( item->parent() );
  if ( !parent )
    return;
  if ( item->isOn() && mSelectedItems[parent] != item ) {
    mSelectedItems[parent] = item;
    changeActiveScript( parent );
  }
}

void KMail::ManageSieveScriptsDialog::changeActiveScript( Q3CheckListItem * item ) {
  if ( !item )
    return;
  if ( !mUrls.count( item ) )
    return;
  if ( !mSelectedItems.count( item ) )
    return;
  KUrl u = mUrls[item];
  if ( u.isEmpty() )
    return;
  Q3CheckListItem * selected = mSelectedItems[item];
  if ( !selected )
    return;
  u.setFileName( selected->text( 0 ) );

  SieveJob * job = SieveJob::activate( u );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotRefresh()) );
}

void KMail::ManageSieveScriptsDialog::slotDoubleClicked( Q3ListViewItem * i ) {
  Q3CheckListItem * item = qcli_cast( i );
  if ( !item )
    return;
  if ( !item->depth() )
    return;
  mContextMenuItem = item;
  slotEditScript();
  mContextMenuItem = 0;
}

void KMail::ManageSieveScriptsDialog::slotDeleteScript() {
  if ( !mContextMenuItem )
    return;
  if ( !mContextMenuItem->depth() )
    return;

  Q3CheckListItem * parent = qcli_cast( mContextMenuItem->parent() );
  if ( !parent )
    return;

  if ( !mUrls.count( parent ) )
    return;

  KUrl u = mUrls[parent];
  if ( u.isEmpty() )
    return;

  u.setFileName( mContextMenuItem->text( 0 ) );

  if ( KMessageBox::warningContinueCancel( this, i18n( "Really delete script \"%1\" from the server?", u.fileName() ),
                                   i18n( "Delete Sieve Script Confirmation" ),
                                   KStandardGuiItem::del() )
       != KMessageBox::Continue )
    return;

  SieveJob * job = SieveJob::del( u );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotRefresh()) );
}

void KMail::ManageSieveScriptsDialog::slotEditScript() {
  if ( !mContextMenuItem )
    return;
  if ( !mContextMenuItem->depth() )
    return;
  Q3CheckListItem * parent = qcli_cast( mContextMenuItem->parent() );
  if ( !mUrls.count( parent ) )
    return;
  KUrl url = mUrls[parent];
  if ( url.isEmpty() )
    return;
  url.setFileName( mContextMenuItem->text( 0 ) );
  mCurrentURL = url;
  SieveJob * job = SieveJob::get( url );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotGetResult(KMail::SieveJob*,bool,const QString&,bool)) );
}

void KMail::ManageSieveScriptsDialog::slotNewScript() {
  if ( !mContextMenuItem )
    return;
  if ( mContextMenuItem->depth() )
    mContextMenuItem = qcli_cast( mContextMenuItem->parent() );
  if ( !mContextMenuItem )
    return;

  if ( !mUrls.count( mContextMenuItem ) )
    return;

  KUrl u = mUrls[mContextMenuItem];
  if ( u.isEmpty() )
    return;

  bool ok = false;
  const QString name = KInputDialog::getText( i18n( "New Sieve Script" ),
                                              i18n( "Please enter a name for the new Sieve script:" ),
                                              i18n( "unnamed" ), &ok, this );
  if ( !ok || name.isEmpty() )
    return;

  u.setFileName( name );

  (void) new Q3CheckListItem( mContextMenuItem, name, Q3CheckListItem::RadioButton );

  mCurrentURL = u;
  slotGetResult( 0, true, QString(), false );
}

KMail::SieveEditor::SieveEditor( QWidget * parent, const char * name )
  : KDialog( parent )
{
  setCaption( i18n( "Edit Sieve Script" ) );
  setButtons( Ok|Cancel );
  setObjectName( name );
  setDefaultButton( Ok );
  setModal( true );
  QFrame *frame = new QFrame( this );
  setMainWidget( frame );
  QVBoxLayout * vlay = new QVBoxLayout( frame );
  vlay->setSpacing( spacingHint() );
  vlay->setMargin( 0 );
  mTextEdit = new KTextEdit( frame);
  vlay->addWidget( mTextEdit );
  mTextEdit->setAcceptRichText( false );
  mTextEdit->setWordWrapMode ( QTextOption::NoWrap );
  mTextEdit->setFont( KGlobalSettings::fixedFont() );

  resize( 3 * sizeHint() );
}

KMail::SieveEditor::~SieveEditor() {}

void KMail::ManageSieveScriptsDialog::slotGetResult( KMail::SieveJob *, bool success, const QString & script, bool isActive ) {
  if ( !success )
    return;

  if ( mSieveEditor )
    return;

  mSieveEditor = new SieveEditor( this );
  mSieveEditor->setScript( script );
  connect( mSieveEditor, SIGNAL(okClicked()), this, SLOT(slotSieveEditorOkClicked()) );
  connect( mSieveEditor, SIGNAL(cancelClicked()), this, SLOT(slotSieveEditorCancelClicked()) );
  mSieveEditor->show();
  mWasActive = isActive;
}

void KMail::ManageSieveScriptsDialog::slotSieveEditorOkClicked() {
  if ( !mSieveEditor )
    return;
  SieveJob * job = SieveJob::put( mCurrentURL,mSieveEditor->script(), mWasActive, mWasActive );
  connect( job, SIGNAL(result(KMail::SieveJob*,bool,const QString&,bool)),
           this, SLOT(slotPutResult(KMail::SieveJob*,bool)) );
}

void KMail::ManageSieveScriptsDialog::slotSieveEditorCancelClicked() {
  mSieveEditor->deleteLater(); mSieveEditor = 0;
  mCurrentURL = KUrl();
}

void KMail::ManageSieveScriptsDialog::slotPutResult( KMail::SieveJob *, bool success ) {
  if ( success ) {
    KMessageBox::information( this, i18n( "The Sieve script was successfully uploaded." ),
                              i18n( "Sieve Script Upload" ) );
    mSieveEditor->deleteLater(); mSieveEditor = 0;
    mCurrentURL = KUrl();
  } else {
    mSieveEditor->show();
  }
}

#include "managesievescriptsdialog.moc"
#include "managesievescriptsdialog_p.moc"
<|endoftext|>


<commit_before>/*
 * This file is part of telepathy-nepomuk-service
 *
 * Copyright (C) 2009-2011 Collabora Ltd. <info@collabora.co.uk>
 *   @author George Goldberg <george.goldberg@collabora.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "account.h"

#include <KDebug>

#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingContacts>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>

Account::Account(const Tp::AccountPtr &account, QObject *parent)
 : QObject(parent),
   m_account(account)
{
    // Do nothing here. Wait for init() to be called to allow
    // signal/slot connections to be set up first.
    kDebug() << "Account Constructed.";
}

void Account::init()
{
    // Connect to all the signals that indicate changes in properties we care about.
    connect(m_account.data(),
            SIGNAL(nicknameChanged(QString)),
            SLOT(onNicknameChanged(QString)));
    //    connect(m_account.data(),
    //            SIGNAL(avatarChanged(Tp::Avatar)),
    //            SLOT(onAvatarChanged(Tp::Avatar)));
    // ...... and any other properties we want to sync...
    connect(m_account.data(),
            SIGNAL(connectionChanged(Tp::ConnectionPtr)),
            SLOT(onConnectionChanged(Tp::ConnectionPtr)));

    connect(m_account.data(),
            SIGNAL(removed()),
            SLOT(onAccountRemoved()));

    QString protocolName = m_account->serviceName().isEmpty() ? m_account->protocolName() : m_account->serviceName();
    // Emit a signal to notify the storage that a new account has been constructed
    // FIXME: Some IM Accounts don't have an ID as such, e.g. Link-Local-XMPP.
    emit created(m_account->objectPath(),
                 m_account->parameters().value(QLatin1String("account")).toString(),
                 protocolName);

    // Simulate all the accounts properties being changed.
    onNicknameChanged(m_account->nickname());

    // Now that the storage stuff is done, simulate emission of all the account signals.
    onConnectionChanged(m_account->connection());
}

Account::~Account()
{
    kDebug();
}

void Account::shutdown()
{
    kDebug();

    // Emit a signal to say we were destroyed.
    emit accountDestroyed(m_account->objectPath());
}

void Account::onConnectionChanged(const Tp::ConnectionPtr &connection)
{
    if (! connection.isNull()) {

        m_connection = connection;

        // We need to destroy ourselves if the connection goes down.
        connect(m_connection.data(),
            SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
            SLOT(deleteLater()));

        if (!m_connection->contactManager()) {
            kWarning() << "ContactManager is Null. Abort getting contacts.";
            return;
        }

        //add contacts as soon as the contact manager is ready.
        connect(m_connection->contactManager().data(),
                SIGNAL(stateChanged(Tp::ContactListState)),
                SLOT(onContactManagerStateChanged(Tp::ContactListState)));
        // Simulate a state change signal in case it is already ready.
        onContactManagerStateChanged(m_connection->contactManager()->state());

    } else {
        // Connection has gone down. Delete our pointer to it.
        m_connection.reset();
        kDebug() << "Connection closed:" << this;
    }
}

void Account::onContactManagerStateChanged(Tp::ContactListState state)
{
//    kDebug() << "contact manager state changed to " << state;

    if (state == Tp::ContactListStateSuccess)  {
        Tp::Contacts contacts = m_connection->contactManager()->allKnownContacts();

        // Create the hash containing all the contacts to notify the storage of the
        // full set of contacts that still exist when the account is connected.
        // This *must* be done before creating the contact wrapper objects.
        QList<QString> initialContacts;
        foreach (const Tp::ContactPtr &contact, contacts) {
            initialContacts.append(contact->id());
        }
        emit initialContactsLoaded(m_account->objectPath(), contacts);

        // Create wrapper objects for all the Contacts.
        foreach (const Tp::ContactPtr &contact, contacts) {
            onNewContact(contact);
        }
//        kDebug() << "Loop over.";
    }
}

void Account::onNicknameChanged(const QString &nickname)
{
    emit nicknameChanged(m_account->objectPath(), nickname);
}

void Account::onAllKnownContactsChanged(const Tp::Contacts &added, const Tp::Contacts &removed)
{
    // For each added contact, let's check if we already have a Contact wrapper for it
    foreach (const Tp::ContactPtr &contact, added) {
        if (!m_contacts.contains(contact)) {
            // It's a brand new one
            onNewContact(contact);
        }
    }

    // If contacts are removed, we don't actually need to do anything!
    Q_UNUSED(removed);
}

void Account::onAccountRemoved()
{
    Tp::AccountPtr account(qobject_cast<Tp::Account*>(sender()));
    Q_ASSERT(account);

    kDebug() << "Account being removed";

    emit accountRemoved(account->objectPath());
}

void Account::onNewContact(const Tp::ContactPtr &contact)
{
    // Only create a new contact if one doesn't already exist.
    if (!m_contacts.contains(contact)) {

        m_contacts.append(contact);

        // Become ready asynchronously with the avatar data, since this may take some time and we
        // don't want to delay the rest of the contact's attributes being ready.
        // Fire and forget because we can't do anything even if this fails.
        contact->manager()->upgradeContacts(QList<Tp::ContactPtr>() << contact,
                                            Tp::Features() << Tp::Contact::FeatureAvatarData
                                                           << Tp::Contact::FeatureAvatarToken);

        // Connect to all its signals
        connect(contact.data(),
                SIGNAL(aliasChanged(QString)),
                SLOT(onContactAliasChanged()));
        connect(contact.data(),
                SIGNAL(addedToGroup(QString)),
                SLOT(onContactAddedToGroup()));
        connect(contact.data(),
                SIGNAL(removedFromGroup(QString)),
                SLOT(onContactRemovedFromGroup(QString)));
        connect(contact.data(),
                SIGNAL(avatarDataChanged(Tp::AvatarData)),
                SLOT(onContactAvatarChanged(Tp::AvatarData)));

        emit contactCreated(m_account->objectPath(), contact);

    }
}

void Account::onContactAddedToGroup()
{
    const Tp::ContactPtr contact(qobject_cast<Tp::Contact*>(sender()));
    Q_ASSERT(contact);

    onContactAddedToGroup(contact);
}

void Account::onContactAddedToGroup(const Tp::ContactPtr &contact)
{
    emit contactGroupsChanged(m_account->objectPath(), contact->id(), contact->groups());
}

void Account::onContactRemovedFromGroup(const QString &group)
{
    Q_UNUSED(group);
    const Tp::ContactPtr contact(qobject_cast<Tp::Contact*>(sender()));
    Q_ASSERT(contact);

    emit contactGroupsChanged(m_account->objectPath(), contact->id(), contact->groups());
}

void Account::onContactAliasChanged()
{
    const Tp::ContactPtr contact(qobject_cast<Tp::Contact*>(sender()));
    Q_ASSERT(contact);

    onContactAliasChanged(contact);
}

void Account::onContactAliasChanged(const Tp::ContactPtr &contact)
{
    emit contactAliasChanged(m_account->objectPath(), contact->id(), contact->alias());
}

void Account::onContactAvatarChanged(const Tp::AvatarData &avatar)
{
    const Tp::ContactPtr contact(qobject_cast<Tp::Contact*>(sender()));
    Q_ASSERT(contact);

    emit contactAvatarChanged(m_account->objectPath(), contact->id(), avatar);
}

#include "account.moc"
<commit_msg>Remove useless forloop<commit_after>/*
 * This file is part of telepathy-nepomuk-service
 *
 * Copyright (C) 2009-2011 Collabora Ltd. <info@collabora.co.uk>
 *   @author George Goldberg <george.goldberg@collabora.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "account.h"

#include <KDebug>

#include <TelepathyQt/ContactManager>
#include <TelepathyQt/PendingContacts>
#include <TelepathyQt/PendingOperation>
#include <TelepathyQt/PendingReady>

Account::Account(const Tp::AccountPtr &account, QObject *parent)
 : QObject(parent),
   m_account(account)
{
    // Do nothing here. Wait for init() to be called to allow
    // signal/slot connections to be set up first.
    kDebug() << "Account Constructed.";
}

void Account::init()
{
    // Connect to all the signals that indicate changes in properties we care about.
    connect(m_account.data(),
            SIGNAL(nicknameChanged(QString)),
            SLOT(onNicknameChanged(QString)));
    //    connect(m_account.data(),
    //            SIGNAL(avatarChanged(Tp::Avatar)),
    //            SLOT(onAvatarChanged(Tp::Avatar)));
    // ...... and any other properties we want to sync...
    connect(m_account.data(),
            SIGNAL(connectionChanged(Tp::ConnectionPtr)),
            SLOT(onConnectionChanged(Tp::ConnectionPtr)));

    connect(m_account.data(),
            SIGNAL(removed()),
            SLOT(onAccountRemoved()));

    QString protocolName = m_account->serviceName().isEmpty() ? m_account->protocolName() : m_account->serviceName();
    // Emit a signal to notify the storage that a new account has been constructed
    // FIXME: Some IM Accounts don't have an ID as such, e.g. Link-Local-XMPP.
    emit created(m_account->objectPath(),
                 m_account->parameters().value(QLatin1String("account")).toString(),
                 protocolName);

    // Simulate all the accounts properties being changed.
    onNicknameChanged(m_account->nickname());

    // Now that the storage stuff is done, simulate emission of all the account signals.
    onConnectionChanged(m_account->connection());
}

Account::~Account()
{
    kDebug();
}

void Account::shutdown()
{
    kDebug();

    // Emit a signal to say we were destroyed.
    emit accountDestroyed(m_account->objectPath());
}

void Account::onConnectionChanged(const Tp::ConnectionPtr &connection)
{
    if (! connection.isNull()) {

        m_connection = connection;

        // We need to destroy ourselves if the connection goes down.
        connect(m_connection.data(),
            SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)),
            SLOT(deleteLater()));

        if (!m_connection->contactManager()) {
            kWarning() << "ContactManager is Null. Abort getting contacts.";
            return;
        }

        //add contacts as soon as the contact manager is ready.
        connect(m_connection->contactManager().data(),
                SIGNAL(stateChanged(Tp::ContactListState)),
                SLOT(onContactManagerStateChanged(Tp::ContactListState)));
        // Simulate a state change signal in case it is already ready.
        onContactManagerStateChanged(m_connection->contactManager()->state());

    } else {
        // Connection has gone down. Delete our pointer to it.
        m_connection.reset();
        kDebug() << "Connection closed:" << this;
    }
}

void Account::onContactManagerStateChanged(Tp::ContactListState state)
{
//    kDebug() << "contact manager state changed to " << state;

    if (state == Tp::ContactListStateSuccess)  {
        Tp::Contacts contacts = m_connection->contactManager()->allKnownContacts();

        emit initialContactsLoaded(m_account->objectPath(), contacts);

        // Create wrapper objects for all the Contacts.
        foreach (const Tp::ContactPtr &contact, contacts) {
            onNewContact(contact);
        }
//        kDebug() << "Loop over.";
    }
}

void Account::onNicknameChanged(const QString &nickname)
{
    emit nicknameChanged(m_account->objectPath(), nickname);
}

void Account::onAllKnownContactsChanged(const Tp::Contacts &added, const Tp::Contacts &removed)
{
    // For each added contact, let's check if we already have a Contact wrapper for it
    foreach (const Tp::ContactPtr &contact, added) {
        if (!m_contacts.contains(contact)) {
            // It's a brand new one
            onNewContact(contact);
        }
    }

    // If contacts are removed, we don't actually need to do anything!
    Q_UNUSED(removed);
}

void Account::onAccountRemoved()
{
    Tp::AccountPtr account(qobject_cast<Tp::Account*>(sender()));
    Q_ASSERT(account);

    kDebug() << "Account being removed";

    emit accountRemoved(account->objectPath());
}

void Account::onNewContact(const Tp::ContactPtr &contact)
{
    // Only create a new contact if one doesn't already exist.
    if (!m_contacts.contains(contact)) {

        m_contacts.append(contact);

        // Become ready asynchronously with the avatar data, since this may take some time and we
        // don't want to delay the rest of the contact's attributes being ready.
        // Fire and forget because we can't do anything even if this fails.
        contact->manager()->upgradeContacts(QList<Tp::ContactPtr>() << contact,
                                            Tp::Features() << Tp::Contact::FeatureAvatarData
                                                           << Tp::Contact::FeatureAvatarToken);

        // Connect to all its signals
        connect(contact.data(),
                SIGNAL(aliasChanged(QString)),
                SLOT(onContactAliasChanged()));
        connect(contact.data(),
                SIGNAL(addedToGroup(QString)),
                SLOT(onContactAddedToGroup()));
        connect(contact.data(),
                SIGNAL(removedFromGroup(QString)),
                SLOT(onContactRemovedFromGroup(QString)));
        connect(contact.data(),
                SIGNAL(avatarDataChanged(Tp::AvatarData)),
                SLOT(onContactAvatarChanged(Tp::AvatarData)));

        emit contactCreated(m_account->objectPath(), contact);
    }
}

void Account::onContactAddedToGroup()
{
    const Tp::ContactPtr contact(qobject_cast<Tp::Contact*>(sender()));
    Q_ASSERT(contact);

    onContactAddedToGroup(contact);
}

void Account::onContactAddedToGroup(const Tp::ContactPtr &contact)
{
    emit contactGroupsChanged(m_account->objectPath(), contact->id(), contact->groups());
}

void Account::onContactRemovedFromGroup(const QString &group)
{
    Q_UNUSED(group);
    const Tp::ContactPtr contact(qobject_cast<Tp::Contact*>(sender()));
    Q_ASSERT(contact);

    emit contactGroupsChanged(m_account->objectPath(), contact->id(), contact->groups());
}

void Account::onContactAliasChanged()
{
    const Tp::ContactPtr contact(qobject_cast<Tp::Contact*>(sender()));
    Q_ASSERT(contact);

    onContactAliasChanged(contact);
}

void Account::onContactAliasChanged(const Tp::ContactPtr &contact)
{
    emit contactAliasChanged(m_account->objectPath(), contact->id(), contact->alias());
}

void Account::onContactAvatarChanged(const Tp::AvatarData &avatar)
{
    const Tp::ContactPtr contact(qobject_cast<Tp::Contact*>(sender()));
    Q_ASSERT(contact);

    emit contactAvatarChanged(m_account->objectPath(), contact->id(), avatar);
}

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


<commit_before>//===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/Config.h"

#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/HostInfoBase.h"

#include "llvm/ADT/Triple.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"

#include <thread>
#include <mutex> // std::once

using namespace lldb;
using namespace lldb_private;

namespace
{
    void
    CleanupProcessSpecificLLDBTempDir()
    {
        // Get the process specific LLDB temporary directory and delete it.
        FileSpec tmpdir_file_spec;
        if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
            return;

        // Remove the LLDB temporary directory if we have one. Set "recurse" to
        // true to all files that were created for the LLDB process can be cleaned up.
        FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true);
    }

    //----------------------------------------------------------------------
    // The HostInfoBaseFields is a work around for windows not supporting
    // static variables correctly in a thread safe way. Really each of the
    // variables in HostInfoBaseFields should live in the functions in which
    // they are used and each one should be static, but the work around is
    // in place to avoid this restriction. Ick.
    //----------------------------------------------------------------------

    struct HostInfoBaseFields
    {
        uint32_t m_number_cpus;
        std::string m_vendor_string;
        std::string m_os_string;
        std::string m_host_triple;

        ArchSpec m_host_arch_32;
        ArchSpec m_host_arch_64;

        FileSpec m_lldb_so_dir;
        FileSpec m_lldb_support_exe_dir;
        FileSpec m_lldb_headers_dir;
        FileSpec m_lldb_python_dir;
        FileSpec m_lldb_clang_resource_dir;
        FileSpec m_lldb_system_plugin_dir;
        FileSpec m_lldb_user_plugin_dir;
        FileSpec m_lldb_tmp_dir;
    };

    HostInfoBaseFields *g_fields = nullptr;
}

void
HostInfoBase::Initialize()
{
    g_fields = new HostInfoBaseFields();
}

uint32_t
HostInfoBase::GetNumberCPUS()
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_fields->m_number_cpus = std::thread::hardware_concurrency();
    });
    return g_fields->m_number_cpus;
}

uint32_t
HostInfoBase::GetMaxThreadNameLength()
{
    return 0;
}

llvm::StringRef
HostInfoBase::GetVendorString()
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_fields->m_vendor_string = std::move(HostInfo::GetArchitecture().GetTriple().getVendorName().str());
    });
    return g_fields->m_vendor_string;
}

llvm::StringRef
HostInfoBase::GetOSString()
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_fields->m_os_string = std::move(HostInfo::GetArchitecture().GetTriple().getOSName());
    });
    return g_fields->m_os_string;
}

llvm::StringRef
HostInfoBase::GetTargetTriple()
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple().getTriple();
    });
    return g_fields->m_host_triple;
}

const ArchSpec &
HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64);
    });

    // If an explicit 32 or 64-bit architecture was requested, return that.
    if (arch_kind == eArchKind32)
        return g_fields->m_host_arch_32;
    if (arch_kind == eArchKind64)
        return g_fields->m_host_arch_64;

    // Otherwise prefer the 64-bit architecture if it is valid.
    return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32;
}

bool
HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
{
    file_spec.Clear();

#if defined(LLDB_DISABLE_PYTHON)
    if (type == lldb::ePathTypePythonDir)
        return false;
#endif

    FileSpec *result = nullptr;
    switch (type)
    {
        case lldb::ePathTypeLLDBShlibDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeSharedLibraryDirectory (g_fields->m_lldb_so_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_so_dir;
            }
            break;
        case lldb::ePathTypeSupportExecutableDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeSupportExeDirectory (g_fields->m_lldb_support_exe_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
                                    g_fields->m_lldb_support_exe_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_support_exe_dir;
            }
            break;
        case lldb::ePathTypeHeaderDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeHeaderDirectory (g_fields->m_lldb_headers_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_headers_dir;
            }
            break;
        case lldb::ePathTypePythonDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputePythonDirectory (g_fields->m_lldb_python_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_python_dir;
            }
            break;
        case lldb::ePathTypeClangDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeClangDirectory (g_fields->m_lldb_clang_resource_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_clang_resource_dir;
            }
            break;
        case lldb::ePathTypeLLDBSystemPlugins:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeSystemPluginsDirectory (g_fields->m_lldb_system_plugin_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
                                    g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_system_plugin_dir;
            }
            break;
        case lldb::ePathTypeLLDBUserPlugins:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeUserPluginsDirectory (g_fields->m_lldb_user_plugin_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
                                    g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_user_plugin_dir;
            }
            break;
        case lldb::ePathTypeLLDBTempSystemDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeTempFileDirectory (g_fields->m_lldb_tmp_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_tmp_dir;
            }
            break;
    }

    if (!result)
        return false;
    file_spec = *result;
    return true;
}

bool
HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
{
    // To get paths related to LLDB we get the path to the executable that
    // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
    // on linux this is assumed to be the "lldb" main executable. If LLDB on
    // linux is actually in a shared library (liblldb.so) then this function will
    // need to be modified to "do the right thing".

    FileSpec lldb_file_spec(
        Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));

    // Remove the filename so that this FileSpec only represents the directory.
    file_spec.GetDirectory() = lldb_file_spec.GetDirectory();

    return (bool)file_spec.GetDirectory();
}

bool
HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
{
    return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
}

bool
HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
{
    const char *tmpdir_cstr = getenv("TMPDIR");
    if (tmpdir_cstr == NULL)
    {
        tmpdir_cstr = getenv("TMP");
        if (tmpdir_cstr == NULL)
            tmpdir_cstr = getenv("TEMP");
    }
    if (!tmpdir_cstr)
        return false;

    FileSpec temp_file_spec(tmpdir_cstr, false);
    temp_file_spec.AppendPathComponent("lldb");
    if (!FileSystem::MakeDirectory(temp_file_spec.GetPath().c_str(), eFilePermissionsDirectoryDefault).Success())
        return false;

    std::string pid_str;
    llvm::raw_string_ostream pid_stream(pid_str);
    pid_stream << Host::GetCurrentProcessID();
    temp_file_spec.AppendPathComponent(pid_stream.str().c_str());
    std::string final_path = temp_file_spec.GetPath();
    if (!FileSystem::MakeDirectory(final_path.c_str(), eFilePermissionsDirectoryDefault).Success())
        return false;

    // Make an atexit handler to clean up the process specify LLDB temp dir
    // and all of its contents.
    ::atexit(CleanupProcessSpecificLLDBTempDir);
    file_spec.GetDirectory().SetCStringWithLength(final_path.c_str(), final_path.size());
    return true;
}

bool
HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
{
    // TODO(zturner): Figure out how to compute the header directory for all platforms.
    return false;
}

bool
HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
{
    // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
    return false;
}

bool
HostInfoBase::ComputeClangDirectory(FileSpec &file_spec)
{
    return false;
}

bool
HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
{
    // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
    return false;
}

void
HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
{
    llvm::Triple triple(llvm::sys::getDefaultTargetTriple());

    arch_32.Clear();
    arch_64.Clear();

    switch (triple.getArch())
    {
        default:
            arch_32.SetTriple(triple);
            break;

        case llvm::Triple::x86_64:
        case llvm::Triple::ppc64:
            arch_64.SetTriple(triple);
            arch_32.SetTriple(triple.get32BitArchVariant());
            break;

        case llvm::Triple::aarch64:
        case llvm::Triple::mips64:
        case llvm::Triple::sparcv9:
            arch_64.SetTriple(triple);
            break;
    }
}
<commit_msg>Fix sorting.  Spotted by emaste.<commit_after>//===-- HostInfoBase.cpp ----------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/Config.h"

#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/HostInfoBase.h"

#include "llvm/ADT/Triple.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"

#include <thread>
#include <mutex> // std::once

using namespace lldb;
using namespace lldb_private;

namespace
{
    void
    CleanupProcessSpecificLLDBTempDir()
    {
        // Get the process specific LLDB temporary directory and delete it.
        FileSpec tmpdir_file_spec;
        if (!HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
            return;

        // Remove the LLDB temporary directory if we have one. Set "recurse" to
        // true to all files that were created for the LLDB process can be cleaned up.
        FileSystem::DeleteDirectory(tmpdir_file_spec.GetDirectory().GetCString(), true);
    }

    //----------------------------------------------------------------------
    // The HostInfoBaseFields is a work around for windows not supporting
    // static variables correctly in a thread safe way. Really each of the
    // variables in HostInfoBaseFields should live in the functions in which
    // they are used and each one should be static, but the work around is
    // in place to avoid this restriction. Ick.
    //----------------------------------------------------------------------

    struct HostInfoBaseFields
    {
        uint32_t m_number_cpus;
        std::string m_vendor_string;
        std::string m_os_string;
        std::string m_host_triple;

        ArchSpec m_host_arch_32;
        ArchSpec m_host_arch_64;

        FileSpec m_lldb_so_dir;
        FileSpec m_lldb_support_exe_dir;
        FileSpec m_lldb_headers_dir;
        FileSpec m_lldb_python_dir;
        FileSpec m_lldb_clang_resource_dir;
        FileSpec m_lldb_system_plugin_dir;
        FileSpec m_lldb_user_plugin_dir;
        FileSpec m_lldb_tmp_dir;
    };

    HostInfoBaseFields *g_fields = nullptr;
}

void
HostInfoBase::Initialize()
{
    g_fields = new HostInfoBaseFields();
}

uint32_t
HostInfoBase::GetNumberCPUS()
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_fields->m_number_cpus = std::thread::hardware_concurrency();
    });
    return g_fields->m_number_cpus;
}

uint32_t
HostInfoBase::GetMaxThreadNameLength()
{
    return 0;
}

llvm::StringRef
HostInfoBase::GetVendorString()
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_fields->m_vendor_string = std::move(HostInfo::GetArchitecture().GetTriple().getVendorName().str());
    });
    return g_fields->m_vendor_string;
}

llvm::StringRef
HostInfoBase::GetOSString()
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_fields->m_os_string = std::move(HostInfo::GetArchitecture().GetTriple().getOSName());
    });
    return g_fields->m_os_string;
}

llvm::StringRef
HostInfoBase::GetTargetTriple()
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        g_fields->m_host_triple = HostInfo::GetArchitecture().GetTriple().getTriple();
    });
    return g_fields->m_host_triple;
}

const ArchSpec &
HostInfoBase::GetArchitecture(ArchitectureKind arch_kind)
{
    static std::once_flag g_once_flag;
    std::call_once(g_once_flag,  []() {
        HostInfo::ComputeHostArchitectureSupport(g_fields->m_host_arch_32, g_fields->m_host_arch_64);
    });

    // If an explicit 32 or 64-bit architecture was requested, return that.
    if (arch_kind == eArchKind32)
        return g_fields->m_host_arch_32;
    if (arch_kind == eArchKind64)
        return g_fields->m_host_arch_64;

    // Otherwise prefer the 64-bit architecture if it is valid.
    return (g_fields->m_host_arch_64.IsValid()) ? g_fields->m_host_arch_64 : g_fields->m_host_arch_32;
}

bool
HostInfoBase::GetLLDBPath(lldb::PathType type, FileSpec &file_spec)
{
    file_spec.Clear();

#if defined(LLDB_DISABLE_PYTHON)
    if (type == lldb::ePathTypePythonDir)
        return false;
#endif

    FileSpec *result = nullptr;
    switch (type)
    {
        case lldb::ePathTypeLLDBShlibDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeSharedLibraryDirectory (g_fields->m_lldb_so_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBShlibDir) => '%s'", g_fields->m_lldb_so_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_so_dir;
            }
            break;
        case lldb::ePathTypeSupportExecutableDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeSupportExeDirectory (g_fields->m_lldb_support_exe_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeSupportExecutableDir) => '%s'",
                                    g_fields->m_lldb_support_exe_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_support_exe_dir;
            }
            break;
        case lldb::ePathTypeHeaderDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeHeaderDirectory (g_fields->m_lldb_headers_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeHeaderDir) => '%s'", g_fields->m_lldb_headers_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_headers_dir;
            }
            break;
        case lldb::ePathTypePythonDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputePythonDirectory (g_fields->m_lldb_python_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypePythonDir) => '%s'", g_fields->m_lldb_python_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_python_dir;
            }
            break;
        case lldb::ePathTypeClangDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeClangDirectory (g_fields->m_lldb_clang_resource_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeClangResourceDir) => '%s'", g_fields->m_lldb_clang_resource_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_clang_resource_dir;
            }
            break;
        case lldb::ePathTypeLLDBSystemPlugins:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeSystemPluginsDirectory (g_fields->m_lldb_system_plugin_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBSystemPlugins) => '%s'",
                                    g_fields->m_lldb_system_plugin_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_system_plugin_dir;
            }
            break;
        case lldb::ePathTypeLLDBUserPlugins:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeUserPluginsDirectory (g_fields->m_lldb_user_plugin_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBUserPlugins) => '%s'",
                                    g_fields->m_lldb_user_plugin_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_user_plugin_dir;
            }
            break;
        case lldb::ePathTypeLLDBTempSystemDir:
            {
                static std::once_flag g_once_flag;
                static bool success = false;
                std::call_once(g_once_flag,  []() {
                    success = HostInfo::ComputeTempFileDirectory (g_fields->m_lldb_tmp_dir);
                    Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
                    if (log)
                        log->Printf("HostInfoBase::GetLLDBPath(ePathTypeLLDBTempSystemDir) => '%s'", g_fields->m_lldb_tmp_dir.GetPath().c_str());
                });
                if (success)
                    result = &g_fields->m_lldb_tmp_dir;
            }
            break;
    }

    if (!result)
        return false;
    file_spec = *result;
    return true;
}

bool
HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec)
{
    // To get paths related to LLDB we get the path to the executable that
    // contains this function. On MacOSX this will be "LLDB.framework/.../LLDB",
    // on linux this is assumed to be the "lldb" main executable. If LLDB on
    // linux is actually in a shared library (liblldb.so) then this function will
    // need to be modified to "do the right thing".

    FileSpec lldb_file_spec(
        Host::GetModuleFileSpecForHostAddress(reinterpret_cast<void *>(reinterpret_cast<intptr_t>(HostInfoBase::GetLLDBPath))));

    // Remove the filename so that this FileSpec only represents the directory.
    file_spec.GetDirectory() = lldb_file_spec.GetDirectory();

    return (bool)file_spec.GetDirectory();
}

bool
HostInfoBase::ComputeSupportExeDirectory(FileSpec &file_spec)
{
    return GetLLDBPath(lldb::ePathTypeLLDBShlibDir, file_spec);
}

bool
HostInfoBase::ComputeTempFileDirectory(FileSpec &file_spec)
{
    const char *tmpdir_cstr = getenv("TMPDIR");
    if (tmpdir_cstr == NULL)
    {
        tmpdir_cstr = getenv("TMP");
        if (tmpdir_cstr == NULL)
            tmpdir_cstr = getenv("TEMP");
    }
    if (!tmpdir_cstr)
        return false;

    FileSpec temp_file_spec(tmpdir_cstr, false);
    temp_file_spec.AppendPathComponent("lldb");
    if (!FileSystem::MakeDirectory(temp_file_spec.GetPath().c_str(), eFilePermissionsDirectoryDefault).Success())
        return false;

    std::string pid_str;
    llvm::raw_string_ostream pid_stream(pid_str);
    pid_stream << Host::GetCurrentProcessID();
    temp_file_spec.AppendPathComponent(pid_stream.str().c_str());
    std::string final_path = temp_file_spec.GetPath();
    if (!FileSystem::MakeDirectory(final_path.c_str(), eFilePermissionsDirectoryDefault).Success())
        return false;

    // Make an atexit handler to clean up the process specify LLDB temp dir
    // and all of its contents.
    ::atexit(CleanupProcessSpecificLLDBTempDir);
    file_spec.GetDirectory().SetCStringWithLength(final_path.c_str(), final_path.size());
    return true;
}

bool
HostInfoBase::ComputeHeaderDirectory(FileSpec &file_spec)
{
    // TODO(zturner): Figure out how to compute the header directory for all platforms.
    return false;
}

bool
HostInfoBase::ComputeSystemPluginsDirectory(FileSpec &file_spec)
{
    // TODO(zturner): Figure out how to compute the system plugins directory for all platforms.
    return false;
}

bool
HostInfoBase::ComputeClangDirectory(FileSpec &file_spec)
{
    return false;
}

bool
HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec)
{
    // TODO(zturner): Figure out how to compute the user plugins directory for all platforms.
    return false;
}

void
HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
{
    llvm::Triple triple(llvm::sys::getDefaultTargetTriple());

    arch_32.Clear();
    arch_64.Clear();

    switch (triple.getArch())
    {
        default:
            arch_32.SetTriple(triple);
            break;

        case llvm::Triple::ppc64:
        case llvm::Triple::x86_64:
            arch_64.SetTriple(triple);
            arch_32.SetTriple(triple.get32BitArchVariant());
            break;

        case llvm::Triple::aarch64:
        case llvm::Triple::mips64:
        case llvm::Triple::sparcv9:
            arch_64.SetTriple(triple);
            break;
    }
}
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/context.hpp"
#include "flusspferd/object.hpp"
#include "flusspferd/implementation/context.hpp"
#include <boost/test/unit_test.hpp>

BOOST_TEST_DONT_PRINT_LOG_VALUE(flusspferd::context)

BOOST_AUTO_TEST_CASE( null_context ) {
  flusspferd::context null_context;
  BOOST_CHECK(!null_context.is_valid());
}

BOOST_AUTO_TEST_CASE( copy_null_context ) {
  flusspferd::context original_null_context;
  BOOST_REQUIRE(!original_null_context.is_valid());
  flusspferd::context null_context;
  BOOST_CHECK(!null_context.is_valid());
}

BOOST_AUTO_TEST_CASE( create_context ) {
  flusspferd::context const &context = flusspferd::context::create();
  BOOST_CHECK(context.is_valid());
}

BOOST_AUTO_TEST_CASE( copy_create_context ) {
  flusspferd::context const &original_context = flusspferd::context::create();
  BOOST_REQUIRE(original_context.is_valid());
  flusspferd::context context(original_context);
  BOOST_CHECK(context.is_valid());
}

BOOST_AUTO_TEST_CASE( equality ) {
  flusspferd::context const &context1 = flusspferd::context::create();
  BOOST_REQUIRE(context1.is_valid());
  flusspferd::context const &context2 = flusspferd::context::create();
  BOOST_REQUIRE(context2.is_valid());
  flusspferd::context context3;
  BOOST_REQUIRE(!context3.is_valid());

  BOOST_CHECK_EQUAL(context1, context1);
  BOOST_CHECK(!(context1 != context1));

  BOOST_CHECK_EQUAL(context2, context2);
  BOOST_CHECK(!(context2 != context2));

  BOOST_CHECK_EQUAL(context3, context3);
  BOOST_CHECK(!(context3 != context3));

  BOOST_CHECK_NE(context1, context2);
  BOOST_CHECK(!(context1 == context2));

  BOOST_CHECK_NE(context1, context3);
  BOOST_CHECK(!(context1 == context3));

  BOOST_CHECK_NE(context3, context2);
  BOOST_CHECK(!(context3 == context2));

  flusspferd::context copy_context1(context1);

  BOOST_CHECK_EQUAL(context1, copy_context1);
  BOOST_CHECK_EQUAL(copy_context1, context1);

  BOOST_CHECK_NE(copy_context1, context2);
  BOOST_CHECK_NE(context2, copy_context1);

  BOOST_CHECK_NE(copy_context1, context3);
  BOOST_CHECK_NE(context3, copy_context1);

  flusspferd::context copy_context3(context3);

  BOOST_CHECK_EQUAL(context3, copy_context3);
  BOOST_CHECK_EQUAL(copy_context3, context3);

  BOOST_CHECK_NE(copy_context3, context1);
  BOOST_CHECK_NE(context1, copy_context3);

  BOOST_CHECK_NE(copy_context3, context2);
  BOOST_CHECK_NE(context2, copy_context3);
}

BOOST_AUTO_TEST_CASE( gc ) {
  flusspferd::context context(flusspferd::context::create());
  BOOST_REQUIRE(context.is_valid());
  BOOST_CHECK_NO_THROW(context.gc());
  BOOST_REQUIRE(context.is_valid());
}

BOOST_AUTO_TEST_CASE( global ) {
  flusspferd::context context(flusspferd::context::create());
  BOOST_REQUIRE(context.is_valid());

  flusspferd::object global;
  BOOST_CHECK_NO_THROW(global = context.global());

  BOOST_CHECK(global.is_valid());
}

BOOST_AUTO_TEST_SUITE( spidermonkey )

BOOST_AUTO_TEST_CASE( direct_null_context ) {
  flusspferd::context const &null_context = flusspferd::Impl::wrap_context(0);
  BOOST_CHECK(!null_context.is_valid());
}

BOOST_AUTO_TEST_CASE( create_context ) {
  flusspferd::context context(flusspferd::context::create());
  BOOST_REQUIRE(context.is_valid());

  JSContext *cx;
  BOOST_CHECK_NO_THROW(cx = flusspferd::Impl::get_context(context));

  BOOST_CHECK_NE(cx, (JSContext*) 0);
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>non-working testcase<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
Copyright (c) 2008 Aristid Breitkreuz, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#include "flusspferd/context.hpp"
#include "flusspferd/object.hpp"
#include "flusspferd/implementation/context.hpp"
#include <boost/test/unit_test.hpp>

BOOST_TEST_DONT_PRINT_LOG_VALUE(flusspferd::context)

BOOST_AUTO_TEST_CASE( null_context ) {
  flusspferd::context null_context;
  BOOST_CHECK(!null_context.is_valid());
}

BOOST_AUTO_TEST_CASE( copy_null_context ) {
  flusspferd::context original_null_context;
  BOOST_REQUIRE(!original_null_context.is_valid());
  flusspferd::context null_context;
  BOOST_CHECK(!null_context.is_valid());
}

BOOST_AUTO_TEST_CASE( create_context ) {
  flusspferd::context const &context = flusspferd::context::create();
  BOOST_CHECK(context.is_valid());
}

BOOST_AUTO_TEST_CASE( copy_create_context ) {
  flusspferd::context const &original_context = flusspferd::context::create();
  BOOST_REQUIRE(original_context.is_valid());
  flusspferd::context context(original_context);
  BOOST_CHECK(context.is_valid());
}

BOOST_AUTO_TEST_CASE( equality ) {
  flusspferd::context const &context1 = flusspferd::context::create();
  BOOST_REQUIRE(context1.is_valid());
  flusspferd::context const &context2 = flusspferd::context::create();
  BOOST_REQUIRE(context2.is_valid());
  flusspferd::context context3;
  BOOST_REQUIRE(!context3.is_valid());

  BOOST_CHECK_EQUAL(context1, context1);
  BOOST_CHECK(!(context1 != context1));

  BOOST_CHECK_EQUAL(context2, context2);
  BOOST_CHECK(!(context2 != context2));

  BOOST_CHECK_EQUAL(context3, context3);
  BOOST_CHECK(!(context3 != context3));

  BOOST_CHECK_NE(context1, context2);
  BOOST_CHECK(!(context1 == context2));

  BOOST_CHECK_NE(context1, context3);
  BOOST_CHECK(!(context1 == context3));

  BOOST_CHECK_NE(context3, context2);
  BOOST_CHECK(!(context3 == context2));

  flusspferd::context copy_context1(context1);

  BOOST_CHECK_EQUAL(context1, copy_context1);
  BOOST_CHECK_EQUAL(copy_context1, context1);

  BOOST_CHECK_NE(copy_context1, context2);
  BOOST_CHECK_NE(context2, copy_context1);

  BOOST_CHECK_NE(copy_context1, context3);
  BOOST_CHECK_NE(context3, copy_context1);

  flusspferd::context copy_context3(context3);

  BOOST_CHECK_EQUAL(context3, copy_context3);
  BOOST_CHECK_EQUAL(copy_context3, context3);

  BOOST_CHECK_NE(copy_context3, context1);
  BOOST_CHECK_NE(context1, copy_context3);

  BOOST_CHECK_NE(copy_context3, context2);
  BOOST_CHECK_NE(context2, copy_context3);
}

BOOST_AUTO_TEST_CASE( gc ) {
  flusspferd::context context(flusspferd::context::create());
  BOOST_REQUIRE(context.is_valid());
  BOOST_CHECK_NO_THROW(context.gc());
  BOOST_REQUIRE(context.is_valid());
}

BOOST_AUTO_TEST_CASE( global ) {
  flusspferd::context context(flusspferd::context::create());
  BOOST_REQUIRE(context.is_valid());

  flusspferd::object global;
  BOOST_CHECK_NO_THROW(global = context.global());

  BOOST_CHECK(global.is_valid());
}

BOOST_AUTO_TEST_CASE( evaluate ) {
  flusspferd::context context(flusspferd::context::create());
  BOOST_REQUIRE(context.is_valid());

  BOOST_CHECK(context.evaluate("null", 0, __FILE__, 0).is_null());
  BOOST_CHECK(context.evaluate("null", __FILE__, 0).is_null());
  BOOST_CHECK(context.evaluate(std::string("null"), __FILE__, 0).is_null());
}

BOOST_AUTO_TEST_SUITE( spidermonkey )

BOOST_AUTO_TEST_CASE( direct_null_context ) {
  flusspferd::context const &null_context = flusspferd::Impl::wrap_context(0);
  BOOST_CHECK(!null_context.is_valid());
}

BOOST_AUTO_TEST_CASE( create_context ) {
  flusspferd::context context(flusspferd::context::create());
  BOOST_REQUIRE(context.is_valid());

  JSContext *cx;
  BOOST_CHECK_NO_THROW(cx = flusspferd::Impl::get_context(context));

  BOOST_CHECK_NE(cx, (JSContext*) 0);
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: surfaceProcessor.C,v 1.3 2002/12/17 14:13:21 anker Exp $

#include <BALL/STRUCTURE/surfaceProcessor.h>

namespace BALL
{

	SurfaceProcessor::SurfaceProcessor()
		:	ses_(true),
			surface_(),
			spheres_(),
			density_(4.5),
			probe_radius_(1.5)
	{
		radius_offset_ = 0.0;
		vdw_factor_ = 1.0;
	}

	bool SurfaceProcessor::start()
	{
		spheres_.clear();
		return true;
	}

	Processor::Result SurfaceProcessor::operator () (Atom& atom)
	{
		Vector3 pos_(atom.getPosition());
		TVector3<double> pos((double)pos_.x,(double)pos_.y,(double)pos_.z);
		/*if (Maths::isNotZero(atom.getRadius()))
		{
			spheres_.push_back(Sphere3(atom.getPosition(),atom.getRadius()));
		}
		else
		{
			if (atom.getElement() != Element::UNKNOWN)
			{
				if (atom.getElement().getVanDerWaalsRadius() > 0.0)
				{
					spheres_.push_back(Sphere3(atom.getPosition(),
																		 atom.getElement().getVanDerWaalsRadius()));
				}
				else
				{
					spheres_.push_back(Sphere3(atom.getPosition(), 1.0));
				}
			}
			else
			{
				spheres_.push_back(Sphere3(atom.getPosition(), 1.0));
			}
		}
		return Processor::CONTINUE;*/
		if (atom.getElement() != Element::UNKNOWN)
		{
			if (atom.getElement().getVanDerWaalsRadius() > 0.0)
			{
				spheres_.push_back(TSphere3<double>(pos,
													 vdw_factor_*atom.getElement().getVanDerWaalsRadius()+radius_offset_));
			}
			else
			{
				spheres_.push_back(TSphere3<double>(pos,radius_offset_+vdw_factor_));
			}
		}
		else
		{
			spheres_.push_back(TSphere3<double>(pos,radius_offset_+vdw_factor_));
		}
		return Processor::CONTINUE;
	}

	bool SurfaceProcessor::finish()
	{
		ReducedSurface* rs = new ReducedSurface(spheres_,probe_radius_);
		rs->compute();
		if (ses_)
		{
			SolventExcludedSurface* ses = new SolventExcludedSurface(rs);
			ses->compute();
				double diff = (probe_radius_ < 1.5 ? 0.1 : -0.1);
				int i = 0;
				bool ok = false;
				while (!ok && (i < 10))
				{
					i++;
					ok = ses->check();
					if (!ok)
					{
						delete ses;
						delete rs;
						probe_radius_ += diff;
						rs = new ReducedSurface(spheres_,probe_radius_);
						rs->compute();
						ses = new SolventExcludedSurface(rs);
						ses->compute();
					}
				}
			if (ok)
			{
				TriangulatedSES* surface = new TriangulatedSES(ses,density_);
				surface->compute();
				surface->exportSurface(surface_);
				delete surface;
			}
			delete ses;
				std::cout << "    ProbeRadius: " << probe_radius_
									<< "    Durchlufe: " << i;
		}
		else
		{
			SolventAccessibleSurface* sas = new SolventAccessibleSurface(rs);
			sas->compute();
			TriangulatedSAS* surface = new TriangulatedSAS(sas,density_);
			surface->compute();
			surface->exportSurface(surface_);
			delete surface;
			delete sas;
		}
		delete rs;
		return true;
	}

	const Surface& SurfaceProcessor::getSurface() const
	{
		return surface_;
	}

	void SurfaceProcessor::getSurface(Surface& surface) const
	{
		surface = surface_;
	}

	void SurfaceProcessor::setProbeRadius(double radius)
	{
		probe_radius_ = radius;
	}

	double SurfaceProcessor::getProbeRadius()
	{
		return probe_radius_;
	}

	void SurfaceProcessor::setDensity(double density)
	{
		density_ = density;
	}

	double SurfaceProcessor::getDensity()
	{
		return density_;
	}

	vector< TSphere3<double> >& SurfaceProcessor::getSpheres()
	{
		return spheres_;
	}

}
<commit_msg>removed commented code; cosmetich changes<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: surfaceProcessor.C,v 1.4 2002/12/17 15:54:07 anker Exp $

#include <BALL/STRUCTURE/surfaceProcessor.h>

namespace BALL
{

	SurfaceProcessor::SurfaceProcessor()
		:	ses_(true),
			surface_(),
			spheres_(),
			density_(4.5),
			probe_radius_(1.5),
			radius_offset_(0.0),
			vdw_factor_(1.0)
	{
	}

	bool SurfaceProcessor::start()
	{
		spheres_.clear();
		return true;
	}

	Processor::Result SurfaceProcessor::operator () (Atom& atom)
	{
		Vector3 float_position(atom.getPosition());
		TVector3<double> position((double)float_position.x,
				                      (double)float_position.y,
				                      (double)float_position.z);

		if (atom.getElement() != Element::UNKNOWN)
		{
			if (atom.getElement().getVanDerWaalsRadius() > 0.0)
			{
				spheres_.push_back(TSphere3<double>(position,
													 vdw_factor_*atom.getElement().getVanDerWaalsRadius()
													 + radius_offset_));
			}
			else
			{
				spheres_.push_back(TSphere3<double>(position,
							radius_offset_+vdw_factor_));
			}
		}
		else
		{
			spheres_.push_back(TSphere3<double>(position,
						radius_offset_+vdw_factor_));
		}
		return Processor::CONTINUE;
	}

	bool SurfaceProcessor::finish()
	{
		ReducedSurface* reduced_surface = new ReducedSurface(spheres_,probe_radius_);
		reduced_surface->compute();

		if (ses_ == true)
		{
			SolventExcludedSurface* ses = new SolventExcludedSurface(reduced_surface);
			ses->compute();
			double diff = (probe_radius_ < 1.5 ? 0.1 : -0.1);
			int i = 0;
			bool ok = false;
			while (!ok && (i < 10))
			{
				i++;
				ok = ses->check();
				if (!ok)
				{
					delete ses;
					delete reduced_surface;
					probe_radius_ += diff;
					reduced_surface = new ReducedSurface(spheres_,probe_radius_);
					reduced_surface->compute();
					ses = new SolventExcludedSurface(reduced_surface);
					ses->compute();
				}
			}
			if (ok)
			{
				TriangulatedSES* surface = new TriangulatedSES(ses,density_);
				surface->compute();
				surface->exportSurface(surface_);
				delete surface;
			}
			delete ses;
			std::cout << "    ProbeRadius: " << probe_radius_
				<< "    Durchlufe: " << i;
		}
		else
		{
			SolventAccessibleSurface* sas = new SolventAccessibleSurface(reduced_surface);
			sas->compute();
			TriangulatedSAS* surface = new TriangulatedSAS(sas,density_);
			surface->compute();
			surface->exportSurface(surface_);
			delete surface;
			delete sas;
		}
		delete reduced_surface;
		return true;
	}

	const Surface& SurfaceProcessor::getSurface() const
	{
		return surface_;
	}

	void SurfaceProcessor::getSurface(Surface& surface) const
	{
		surface = surface_;
	}

	void SurfaceProcessor::setProbeRadius(double radius)
	{
		probe_radius_ = radius;
	}

	double SurfaceProcessor::getProbeRadius()
	{
		return probe_radius_;
	}

	void SurfaceProcessor::setDensity(double density)
	{
		density_ = density;
	}

	double SurfaceProcessor::getDensity()
	{
		return density_;
	}

	vector< TSphere3<double> >& SurfaceProcessor::getSpheres()
	{
		return spheres_;
	}

}
<|endoftext|>


<commit_before>
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wswitch"
#endif

#include <QApplication>
#include <QMainWindow>
#include <QTimer>
#include <QResizeEvent>
#include <QWheelEvent>
#include <QSurfaceFormat>

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>

#include <glbinding/gl/gl.h>
#include <glbinding/ContextInfo.h>

#include <globjects/globjects.h>
#include <globjects/Uniform.h>
#include <globjects/Program.h>
#include <globjects/Shader.h>
#include <globjects/Buffer.h>
#include <globjects/logging.h>
#include <globjects/VertexArray.h>
#include <globjects/DebugMessage.h>

#include <globjects/base/File.h>

#include <common/AxisAlignedBoundingBox.h>
#include <common/Icosahedron.h>
#include <common/Camera.h>
#include <common/AbstractCoordinateProvider.h>
#include <common/WorldInHandNavigation.h>

#include "WindowQt.h"

using namespace gl;
using namespace globjects;

class Window : public WindowQt, AbstractCoordinateProvider
{
public:
    Window(QSurfaceFormat & format)
    : WindowQt(format)
    , m_camera(glm::vec3(0.f, 1.f, 4.f))
    {
        m_aabb.extend(glm::vec3(-8.f, -1.f, -8.f));
        m_aabb.extend(glm::vec3( 8.f,  1.f,  8.f));

        m_nav.setCamera(&m_camera);
        m_nav.setCoordinateProvider(this);
        m_nav.setBoundaryHint(m_aabb);

        m_timer = new QTimer(this);
        m_timer->setInterval(0);

        connect(m_timer, &QTimer::timeout, this, &WindowQt::updateGL);
    }

    virtual ~Window()
    {
    }

    virtual void initializeGL() override
    {
        init();
        DebugMessage::enable();

        std::cout << std::endl
            << "OpenGL Version:  " << glbinding::ContextInfo::version() << std::endl
            << "OpenGL Vendor:   " << glbinding::ContextInfo::vendor() << std::endl
            << "OpenGL Renderer: " << glbinding::ContextInfo::renderer() << std::endl << std::endl;

#ifdef __APPLE__
        Shader::clearGlobalReplacements();
        Shader::globalReplace("#version 140", "#version 150");

        debug() << "Using global OS X shader replacement '#version 140' -> '#version 150'" << std::endl;
#endif

        glClearColor(1.f, 1.f, 1.f, 0.f);

        m_sphere = new Program();
        m_sphere->attach(
            Shader::fromFile(GL_VERTEX_SHADER,   "data/gbuffers/sphere.vert")
          , Shader::fromFile(GL_FRAGMENT_SHADER, "data/gbuffers/sphere.frag"));

        m_icosahedron = new Icosahedron(2);

        m_camera.setZNear(1.f);
        m_camera.setZFar(16.f);

        m_timer->start();
    }

    virtual void resizeGL(QResizeEvent * event) override
    {
        glViewport(0, 0, event->size().width(), event->size().height());

        m_camera.setViewport(event->size().width(), event->size().height());
    }

    virtual void paintGL() override
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        m_sphere->setUniform("transform", m_camera.viewProjection());

        m_sphere->use();
        m_icosahedron->draw();
        m_sphere->release();
    }

    virtual void keyPressEvent(QKeyEvent * event) override
    {
        makeCurrent();

        switch (event->key())
        {
        case Qt::Key_F5:
            File::reloadAll();
            break;

        case Qt::Key_Space:
            m_camera.setCenter(glm::vec3());
            m_camera.setEye(glm::vec3( 0.f, 1.f, 4.f));
            m_camera.setUp (glm::vec3( 0.f, 1.f, 0.f));
            break;
        }
        doneCurrent();
    }

    virtual void mousePressEvent(QMouseEvent * event) override
    {
        glm::ivec2 pos(event->pos().x(), event->pos().y());

        makeCurrent();

        switch (event->button())
        {
        case Qt::LeftButton:
            m_nav.panBegin(pos);
            break;

        case Qt::RightButton:
            m_nav.rotateBegin(pos);
            break;

        default:
            break;
        }

        doneCurrent();
    }

    virtual void mouseMoveEvent(QMouseEvent * event) override
    {
        glm::ivec2 pos(event->pos().x(), event->pos().y());

        makeCurrent();

        switch (m_nav.mode())
        {
        case WorldInHandNavigation::PanInteraction:
            m_nav.panProcess(pos);
            break;

        case WorldInHandNavigation::RotateInteraction:
            m_nav.rotateProcess(pos);
            break;

        case WorldInHandNavigation::NoInteraction:
            break;
        }

        doneCurrent();
    }

    virtual void mouseReleaseEvent(QMouseEvent * event) override
    {
        makeCurrent();

        switch (event->button())
        {
        case Qt::LeftButton:
            m_nav.panEnd();
            break;

        case Qt::RightButton:
            m_nav.rotateEnd();
            break;

        default:
            break;
        }

        doneCurrent();
    }

    virtual void wheelEvent(QWheelEvent * event) override
    {
        if (WorldInHandNavigation::NoInteraction != m_nav.mode())
            return;

        makeCurrent();

        glm::vec2 pos(event->pos().x(), event->pos().y());

        m_nav.scaleAtMouse(glm::ivec2(pos), static_cast<float>(-event->delta()) * 0.001f);

        doneCurrent();
    }

    virtual float depthAt(const glm::ivec2 & windowCoordinates) const override
    {
        return AbstractCoordinateProvider::depthAt(m_camera, GL_DEPTH_COMPONENT, windowCoordinates);
    }

    virtual glm::vec3 objAt(const glm::ivec2 & windowCoordinates) const override
    {
        return unproject(m_camera, static_cast<GLenum>(GL_DEPTH_COMPONENT), windowCoordinates);
    }

    virtual glm::vec3 objAt(const glm::ivec2 & windowCoordinates, const float depth) const override
    {
        return unproject(m_camera, depth, windowCoordinates);
    }

    virtual glm::vec3 objAt(const glm::ivec2 & windowCoordinates, const float depth, const glm::mat4 & viewProjectionInverted) const override
    {
        return unproject(m_camera, viewProjectionInverted, depth, windowCoordinates);
    }

protected:
    ref_ptr<Program> m_sphere;

    ref_ptr<Icosahedron> m_icosahedron;

    Camera m_camera;
    WorldInHandNavigation m_nav;

    QTimer * m_timer;

    AxisAlignedBoundingBox m_aabb;
};

int main(int argc, char * argv[])
{
    QApplication app(argc, argv);

    QSurfaceFormat format;
#ifdef __APPLE__
    format.setVersion(3, 2);
    format.setProfile(QSurfaceFormat::CoreProfile);
#else
    format.setVersion(3, 1);
#endif
    format.setDepthBufferSize(16);

    Window * glwindow = new Window(format);

    QMainWindow window;
    window.setGeometry(0, 0, 640, 480);
    window.setCentralWidget(QWidget::createWindowContainer(glwindow));

    window.show();

    return app.exec();
}
<commit_msg>Add missing include<commit_after>
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wfloat-equal"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wswitch"
#endif

#include <iostream>

#include <QApplication>
#include <QMainWindow>
#include <QTimer>
#include <QResizeEvent>
#include <QWheelEvent>
#include <QSurfaceFormat>

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp>

#include <glbinding/gl/gl.h>
#include <glbinding/ContextInfo.h>

#include <globjects/globjects.h>
#include <globjects/Uniform.h>
#include <globjects/Program.h>
#include <globjects/Shader.h>
#include <globjects/Buffer.h>
#include <globjects/logging.h>
#include <globjects/VertexArray.h>
#include <globjects/DebugMessage.h>

#include <globjects/base/File.h>

#include <common/AxisAlignedBoundingBox.h>
#include <common/Icosahedron.h>
#include <common/Camera.h>
#include <common/AbstractCoordinateProvider.h>
#include <common/WorldInHandNavigation.h>

#include "WindowQt.h"

using namespace gl;
using namespace globjects;

class Window : public WindowQt, AbstractCoordinateProvider
{
public:
    Window(QSurfaceFormat & format)
    : WindowQt(format)
    , m_camera(glm::vec3(0.f, 1.f, 4.f))
    {
        m_aabb.extend(glm::vec3(-8.f, -1.f, -8.f));
        m_aabb.extend(glm::vec3( 8.f,  1.f,  8.f));

        m_nav.setCamera(&m_camera);
        m_nav.setCoordinateProvider(this);
        m_nav.setBoundaryHint(m_aabb);

        m_timer = new QTimer(this);
        m_timer->setInterval(0);

        connect(m_timer, &QTimer::timeout, this, &WindowQt::updateGL);
    }

    virtual ~Window()
    {
    }

    virtual void initializeGL() override
    {
        init();
        DebugMessage::enable();

        std::cout << std::endl
            << "OpenGL Version:  " << glbinding::ContextInfo::version() << std::endl
            << "OpenGL Vendor:   " << glbinding::ContextInfo::vendor() << std::endl
            << "OpenGL Renderer: " << glbinding::ContextInfo::renderer() << std::endl << std::endl;

#ifdef __APPLE__
        Shader::clearGlobalReplacements();
        Shader::globalReplace("#version 140", "#version 150");

        debug() << "Using global OS X shader replacement '#version 140' -> '#version 150'" << std::endl;
#endif

        glClearColor(1.f, 1.f, 1.f, 0.f);

        m_sphere = new Program();
        m_sphere->attach(
            Shader::fromFile(GL_VERTEX_SHADER,   "data/gbuffers/sphere.vert")
          , Shader::fromFile(GL_FRAGMENT_SHADER, "data/gbuffers/sphere.frag"));

        m_icosahedron = new Icosahedron(2);

        m_camera.setZNear(1.f);
        m_camera.setZFar(16.f);

        m_timer->start();
    }

    virtual void resizeGL(QResizeEvent * event) override
    {
        glViewport(0, 0, event->size().width(), event->size().height());

        m_camera.setViewport(event->size().width(), event->size().height());
    }

    virtual void paintGL() override
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        m_sphere->setUniform("transform", m_camera.viewProjection());

        m_sphere->use();
        m_icosahedron->draw();
        m_sphere->release();
    }

    virtual void keyPressEvent(QKeyEvent * event) override
    {
        makeCurrent();

        switch (event->key())
        {
        case Qt::Key_F5:
            File::reloadAll();
            break;

        case Qt::Key_Space:
            m_camera.setCenter(glm::vec3());
            m_camera.setEye(glm::vec3( 0.f, 1.f, 4.f));
            m_camera.setUp (glm::vec3( 0.f, 1.f, 0.f));
            break;
        }
        doneCurrent();
    }

    virtual void mousePressEvent(QMouseEvent * event) override
    {
        glm::ivec2 pos(event->pos().x(), event->pos().y());

        makeCurrent();

        switch (event->button())
        {
        case Qt::LeftButton:
            m_nav.panBegin(pos);
            break;

        case Qt::RightButton:
            m_nav.rotateBegin(pos);
            break;

        default:
            break;
        }

        doneCurrent();
    }

    virtual void mouseMoveEvent(QMouseEvent * event) override
    {
        glm::ivec2 pos(event->pos().x(), event->pos().y());

        makeCurrent();

        switch (m_nav.mode())
        {
        case WorldInHandNavigation::PanInteraction:
            m_nav.panProcess(pos);
            break;

        case WorldInHandNavigation::RotateInteraction:
            m_nav.rotateProcess(pos);
            break;

        case WorldInHandNavigation::NoInteraction:
            break;
        }

        doneCurrent();
    }

    virtual void mouseReleaseEvent(QMouseEvent * event) override
    {
        makeCurrent();

        switch (event->button())
        {
        case Qt::LeftButton:
            m_nav.panEnd();
            break;

        case Qt::RightButton:
            m_nav.rotateEnd();
            break;

        default:
            break;
        }

        doneCurrent();
    }

    virtual void wheelEvent(QWheelEvent * event) override
    {
        if (WorldInHandNavigation::NoInteraction != m_nav.mode())
            return;

        makeCurrent();

        glm::vec2 pos(event->pos().x(), event->pos().y());

        m_nav.scaleAtMouse(glm::ivec2(pos), static_cast<float>(-event->delta()) * 0.001f);

        doneCurrent();
    }

    virtual float depthAt(const glm::ivec2 & windowCoordinates) const override
    {
        return AbstractCoordinateProvider::depthAt(m_camera, GL_DEPTH_COMPONENT, windowCoordinates);
    }

    virtual glm::vec3 objAt(const glm::ivec2 & windowCoordinates) const override
    {
        return unproject(m_camera, static_cast<GLenum>(GL_DEPTH_COMPONENT), windowCoordinates);
    }

    virtual glm::vec3 objAt(const glm::ivec2 & windowCoordinates, const float depth) const override
    {
        return unproject(m_camera, depth, windowCoordinates);
    }

    virtual glm::vec3 objAt(const glm::ivec2 & windowCoordinates, const float depth, const glm::mat4 & viewProjectionInverted) const override
    {
        return unproject(m_camera, viewProjectionInverted, depth, windowCoordinates);
    }

protected:
    ref_ptr<Program> m_sphere;

    ref_ptr<Icosahedron> m_icosahedron;

    Camera m_camera;
    WorldInHandNavigation m_nav;

    QTimer * m_timer;

    AxisAlignedBoundingBox m_aabb;
};

int main(int argc, char * argv[])
{
    QApplication app(argc, argv);

    QSurfaceFormat format;
#ifdef __APPLE__
    format.setVersion(3, 2);
    format.setProfile(QSurfaceFormat::CoreProfile);
#else
    format.setVersion(3, 1);
#endif
    format.setDepthBufferSize(16);

    Window * glwindow = new Window(format);

    QMainWindow window;
    window.setGeometry(0, 0, 640, 480);
    window.setCentralWidget(QWidget::createWindowContainer(glwindow));

    window.show();

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