<commit_before>/* -*- mode: c++; c-basic-offset:4 -*-
    systemtrayicon.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

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

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

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

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "systrayicon.h"
#include "mainwindow.h"

#include <utils/kdsignalblocker.h>

#include <commands/encryptclipboardcommand.h>
#include <commands/signclipboardcommand.h>
#include <commands/decryptverifyclipboardcommand.h>

#include <conf/configuredialog.h>

#include <KIcon>
#include <KLocale>
#include <KAboutApplicationDialog>
#include <KAboutData>
#include <KComponentData>
#include <KWindowSystem>

#include <QMenu>
#include <QAction>
#include <QTimer>
#include <QApplication>
#include <QClipboard>
#include <QPointer>
#include <QDebug>

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>

#include <cassert>

using namespace boost;
using namespace Kleo;
using namespace Kleo::Commands;

namespace {
    class SetInitialPinCommand : public Kleo::Command {
    public:
        explicit SetInitialPinCommand( KeyListController * ctrl )
            : Kleo::Command( ctrl ), m_dialog( 0 ) {}

        void doStart() {
            emit finished();
        }
        void doCancel() {}

        QDialog * dialog() {
            if ( !m_dialog ) {
                m_dialog = new QDialog;
                m_dialog->setAttribute( Qt::WA_DeleteOnClose );
                m_dialog->setWindowTitle( i18n("Set Initial PIN") );
                m_dialog->show();
            }
            return m_dialog;
        }
        QDialog * m_dialog;
    };

    class LearnCertificatesCommand : public Kleo::Command {
    public:
        explicit LearnCertificatesCommand( KeyListController * ctrl )
            : Kleo::Command( ctrl ), m_dialog( 0 ) {}

        void doStart() {
            emit finished();
        }
        void doCancel() {}

        QDialog * dialog() {
            if ( !m_dialog ) {
                m_dialog = new QDialog;
                m_dialog->setAttribute( Qt::WA_DeleteOnClose );
                m_dialog->setWindowTitle( i18n("Learn Keys") );
                m_dialog->show();
            }
            return m_dialog;
        }
        QDialog * m_dialog;
    };
}

class SysTrayIcon::Private {
    friend class ::SysTrayIcon;
    SysTrayIcon * const q;
public:
    explicit Private( SysTrayIcon * qq );
    ~Private();

private:
    void slotAbout() {
        if ( !aboutDialog ) {
            aboutDialog = new KAboutApplicationDialog( KGlobal::mainComponent().aboutData() );
            aboutDialog->setAttribute( Qt::WA_DeleteOnClose );
        }

        if ( aboutDialog->isVisible() )
            aboutDialog->raise();
        else
            aboutDialog->show();
    }

    void enableDisableActions() {
        //work around a Qt bug (seen with Qt 4.4.0, Windows): QClipBoard->mimeData() triggers QClipboard::changed(),
        //triggering slotEnableDisableActions again
        const KDSignalBlocker blocker( QApplication::clipboard() );
        openCertificateManagerAction.setEnabled( !q->mainWindow() || !q->mainWindow()->isVisible() );
        encryptClipboardAction.setEnabled( EncryptClipboardCommand::canEncryptCurrentClipboard() );
        openPGPSignClipboardAction.setEnabled( SignClipboardCommand::canSignCurrentClipboard() );
        smimeSignClipboardAction.setEnabled( SignClipboardCommand::canSignCurrentClipboard() );
        decryptVerifyClipboardAction.setEnabled( DecryptVerifyClipboardCommand::canDecryptVerifyCurrentClipboard() );
        setInitialPinAction.setEnabled( anyCardHasNullPin );
        learnCertificatesAction.setEnabled( anyCardCanLearnKeys );

        q->setAttentionWanted( anyCardHasNullPin || anyCardCanLearnKeys );
    }

    void startCommand( Command * cmd ) {
        assert( cmd );
        cmd->setParent( q->mainWindow() );
        cmd->start();
    }

    void slotEncryptClipboard() {
        startCommand( new EncryptClipboardCommand( 0 ) );
    }

    void slotOpenPGPSignClipboard() {
        startCommand( new SignClipboardCommand( GpgME::OpenPGP, 0 ) );
    }

    void slotSMIMESignClipboard() {
        startCommand( new SignClipboardCommand( GpgME::CMS, 0 ) );
    }

    void slotDecryptVerifyClipboard() {
        startCommand( new DecryptVerifyClipboardCommand( 0 ) );
    }

    void slotSetInitialPin() {
        SetInitialPinCommand * cmd = new SetInitialPinCommand( 0 );
        q->setAttentionWindow( cmd->dialog() );
        startCommand( cmd );
    }

    void slotLearnCertificates() {
        LearnCertificatesCommand * cmd = new LearnCertificatesCommand( 0 );
        q->setAttentionWindow( cmd->dialog() );
        startCommand( cmd );
    }

private:
    void connectConfigureDialog() {
        if ( configureDialog && q->mainWindow() )
            connect( configureDialog, SIGNAL(configCommitted()), q->mainWindow(), SLOT(slotConfigCommitted()) );
    }
    void disconnectConfigureDialog() {
        if ( configureDialog && q->mainWindow() )
            disconnect( configureDialog, SIGNAL(configCommitted()), q->mainWindow(), SLOT(slotConfigCommitted()) );
    }
    void connectMainWindow() {
        if ( q->mainWindow() )
            connect( q->mainWindow(), SIGNAL(configDialogRequested()), q, SLOT(openOrRaiseConfigDialog()) );
    }
    void disconnectMainWindow() {
        if ( q->mainWindow() )
            connect( q->mainWindow(), SIGNAL(configDialogRequested()), q, SLOT(openOrRaiseConfigDialog()) );
    }

private:
    bool anyCardHasNullPin;
    bool anyCardCanLearnKeys;

    QMenu menu;
    QAction openCertificateManagerAction;
    QAction configureAction;
    QAction aboutAction;
    QAction quitAction;
    QMenu clipboardMenu;
    QAction encryptClipboardAction;
    QAction smimeSignClipboardAction;
    QAction openPGPSignClipboardAction;
    QAction decryptVerifyClipboardAction;
    QMenu cardMenu;
    QAction setInitialPinAction;
    QAction learnCertificatesAction;

    QPointer<KAboutApplicationDialog> aboutDialog;
    QPointer<ConfigureDialog> configureDialog;

    QRect mainWindowPreviousGeometry;
};

SysTrayIcon::Private::Private( SysTrayIcon * qq )
    : q( qq ),
      anyCardHasNullPin( false ),
      anyCardCanLearnKeys( false ),
      menu(),
      openCertificateManagerAction( i18n("&Open Certificate Manager..."), q ),
      configureAction( i18n("&Configure %1...", KGlobal::mainComponent().aboutData()->programName() ), q ),
      aboutAction( i18n("&About %1...", KGlobal::mainComponent().aboutData()->programName() ), q ),
      quitAction( i18n("&Shutdown Kleopatra"), q ),
      clipboardMenu( i18n("Clipboard" ) ),
      encryptClipboardAction( i18n("Encrypt..."), q ),
      smimeSignClipboardAction( i18n("S/MIME-Sign..."), q ),
      openPGPSignClipboardAction( i18n("OpenPGP-Sign..."), q ),
      decryptVerifyClipboardAction( i18n("Decrypt/Verify..."), q ),
      cardMenu( i18n("SmartCard") ),
      setInitialPinAction( i18n("Set Initial PIN..."), q ),
      learnCertificatesAction( i18n("Learn Card Certificates..."), q ),
      aboutDialog(),
      mainWindowPreviousGeometry()
{
    q->setNormalIcon( KIcon( "kleopatra" ) );
    q->setAttentionIcon( KIcon( "smartcard" ) );

    KDAB_SET_OBJECT_NAME( menu );
    KDAB_SET_OBJECT_NAME( openCertificateManagerAction );
    KDAB_SET_OBJECT_NAME( configureAction );
    KDAB_SET_OBJECT_NAME( aboutAction );
    KDAB_SET_OBJECT_NAME( quitAction );
    KDAB_SET_OBJECT_NAME( clipboardMenu );
    KDAB_SET_OBJECT_NAME( encryptClipboardAction );
    KDAB_SET_OBJECT_NAME( smimeSignClipboardAction );
    KDAB_SET_OBJECT_NAME( openPGPSignClipboardAction );
    KDAB_SET_OBJECT_NAME( decryptVerifyClipboardAction );
    KDAB_SET_OBJECT_NAME( cardMenu );
    KDAB_SET_OBJECT_NAME( setInitialPinAction );
    KDAB_SET_OBJECT_NAME( learnCertificatesAction );

    connect( &openCertificateManagerAction, SIGNAL(triggered()), q, SLOT(openOrRaiseMainWindow()) );
    connect( &configureAction, SIGNAL(triggered()), q, SLOT(openOrRaiseConfigDialog()) );
    connect( &aboutAction, SIGNAL(triggered()), q, SLOT(slotAbout()) );
    connect( &quitAction, SIGNAL(triggered()), QCoreApplication::instance(), SLOT(quit()) );
    connect( &encryptClipboardAction, SIGNAL(triggered()), q, SLOT(slotEncryptClipboard()) );
    connect( &smimeSignClipboardAction, SIGNAL(triggered()), q, SLOT(slotSMIMESignClipboard()) );
    connect( &openPGPSignClipboardAction, SIGNAL(triggered()), q, SLOT(slotOpenPGPSignClipboard()) );
    connect( &decryptVerifyClipboardAction, SIGNAL(triggered()), q, SLOT(slotDecryptVerifyClipboard()) );
    connect( &setInitialPinAction, SIGNAL(triggered()), q, SLOT(slotSetInitialPin()) );
    connect( &learnCertificatesAction, SIGNAL(triggered()), q, SLOT(slotLearnCertificates()) );

    connect( QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)),
             q, SLOT(slotEnableDisableActions()) );

    menu.addAction( &openCertificateManagerAction );
    menu.addAction( &configureAction );
    menu.addAction( &aboutAction );
    menu.addSeparator();
    menu.addMenu( &clipboardMenu );
    clipboardMenu.addAction( &encryptClipboardAction );
    clipboardMenu.addAction( &smimeSignClipboardAction );
    clipboardMenu.addAction( &openPGPSignClipboardAction );
    clipboardMenu.addAction( &decryptVerifyClipboardAction );
    menu.addSeparator();
    menu.addMenu( &cardMenu );
    cardMenu.addAction( &setInitialPinAction );
    cardMenu.addAction( &learnCertificatesAction );
    menu.addSeparator();
    menu.addAction( &quitAction );

    q->setContextMenu( &menu );
}

SysTrayIcon::Private::~Private() {}

SysTrayIcon::SysTrayIcon( QObject * p )
    : SystemTrayIcon( p ), d( new Private( this ) )
{
    KGlobal::ref();
    slotEnableDisableActions();
}

SysTrayIcon::~SysTrayIcon() {
    KGlobal::deref();
}

void SysTrayIcon::doMainWindowClosed( QWidget * mw ) {
    d->mainWindowPreviousGeometry = mw->geometry();
}

MainWindow * SysTrayIcon::mainWindow() const {
    return static_cast<MainWindow*>( SystemTrayIcon::mainWindow() );
}

QDialog * SysTrayIcon::attentionWindow() const {
    return static_cast<QDialog*>( SysTrayIcon::attentionWindow() );
}

static void open_or_raise( QWidget * w ) {
    if ( w->isMinimized() ) {
        KWindowSystem::unminimizeWindow( w->winId());
        w->raise();
    } else if ( w->isVisible() ) {
        w->raise();
    } else {
        w->show();
    }
}

void SysTrayIcon::openOrRaiseMainWindow() {
    MainWindow * mw = mainWindow();
    if ( !mw ) {
        mw = new MainWindow;
        mw->setAttribute( Qt::WA_DeleteOnClose );
        if ( d->mainWindowPreviousGeometry.isValid() )
            mw->setGeometry( d->mainWindowPreviousGeometry );
        setMainWindow( mw );
        d->connectConfigureDialog();
        d->connectMainWindow();
    }
    open_or_raise( mw );
}

void SysTrayIcon::doActivated() {
    if ( d->anyCardHasNullPin )
        d->slotSetInitialPin();
    else if ( d->anyCardCanLearnKeys )
        d->slotLearnCertificates();
    else
        openOrRaiseMainWindow();
}

void SysTrayIcon::openOrRaiseConfigDialog() {
    if ( !d->configureDialog ) {
        d->configureDialog = new ConfigureDialog;
        d->configureDialog->setAttribute( Qt::WA_DeleteOnClose );
        d->connectConfigureDialog();
    }
    open_or_raise( d->configureDialog );
}

void SysTrayIcon::setAnyCardHasNullPin( bool on ) {
    if ( d->anyCardHasNullPin == on )
        return;
    d->anyCardHasNullPin = on;
    slotEnableDisableActions();
}

void SysTrayIcon::setAnyCardCanLearnKeys( bool on ) {
    if ( d->anyCardCanLearnKeys == on )
        return;
    d->anyCardCanLearnKeys = on;
    slotEnableDisableActions();
}

void SysTrayIcon::slotEnableDisableActions() {
    d->enableDisableActions();
}

#include "moc_systrayicon.cpp"

<commit_msg>SysTrayIcon: * fix infinite recursion in attentionWindow() * don't blink when an attentionWindow() is already up<commit_after>/* -*- mode: c++; c-basic-offset:4 -*-
    systemtrayicon.cpp

    This file is part of Kleopatra, the KDE keymanager
    Copyright (c) 2007 Klarälvdalens Datakonsult AB

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

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

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

    In addition, as a special exception, the copyright holders give
    permission to link the code of this program with any edition of
    the Qt library by Trolltech AS, Norway (or with modified versions
    of Qt that use the same license as Qt), and distribute linked
    combinations including the two.  You must obey the GNU General
    Public License in all respects for all of the code used other than
    Qt.  If you modify this file, you may extend this exception to
    your version of the file, but you are not obligated to do so.  If
    you do not wish to do so, delete this exception statement from
    your version.
*/

#include <config-kleopatra.h>

#include "systrayicon.h"
#include "mainwindow.h"

#include <utils/kdsignalblocker.h>

#include <commands/encryptclipboardcommand.h>
#include <commands/signclipboardcommand.h>
#include <commands/decryptverifyclipboardcommand.h>

#include <conf/configuredialog.h>

#include <KIcon>
#include <KLocale>
#include <KAboutApplicationDialog>
#include <KAboutData>
#include <KComponentData>
#include <KWindowSystem>

#include <QMenu>
#include <QAction>
#include <QTimer>
#include <QApplication>
#include <QClipboard>
#include <QPointer>
#include <QDebug>

#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>

#include <cassert>

using namespace boost;
using namespace Kleo;
using namespace Kleo::Commands;

namespace {
    class SetInitialPinCommand : public Kleo::Command {
    public:
        explicit SetInitialPinCommand( KeyListController * ctrl )
            : Kleo::Command( ctrl ), m_dialog( 0 ) {}

        void doStart() {
            emit finished();
        }
        void doCancel() {}

        QDialog * dialog() {
            if ( !m_dialog ) {
                m_dialog = new QDialog;
                m_dialog->setAttribute( Qt::WA_DeleteOnClose );
                m_dialog->setWindowTitle( i18n("Set Initial PIN") );
                m_dialog->show();
            }
            return m_dialog;
        }
        QDialog * m_dialog;
    };

    class LearnCertificatesCommand : public Kleo::Command {
    public:
        explicit LearnCertificatesCommand( KeyListController * ctrl )
            : Kleo::Command( ctrl ), m_dialog( 0 ) {}

        void doStart() {
            emit finished();
        }
        void doCancel() {}

        QDialog * dialog() {
            if ( !m_dialog ) {
                m_dialog = new QDialog;
                m_dialog->setAttribute( Qt::WA_DeleteOnClose );
                m_dialog->setWindowTitle( i18n("Learn Keys") );
                m_dialog->show();
            }
            return m_dialog;
        }
        QDialog * m_dialog;
    };
}

class SysTrayIcon::Private {
    friend class ::SysTrayIcon;
    SysTrayIcon * const q;
public:
    explicit Private( SysTrayIcon * qq );
    ~Private();

private:
    void slotAbout() {
        if ( !aboutDialog ) {
            aboutDialog = new KAboutApplicationDialog( KGlobal::mainComponent().aboutData() );
            aboutDialog->setAttribute( Qt::WA_DeleteOnClose );
        }

        if ( aboutDialog->isVisible() )
            aboutDialog->raise();
        else
            aboutDialog->show();
    }

    void enableDisableActions() {
        //work around a Qt bug (seen with Qt 4.4.0, Windows): QClipBoard->mimeData() triggers QClipboard::changed(),
        //triggering slotEnableDisableActions again
        const KDSignalBlocker blocker( QApplication::clipboard() );
        openCertificateManagerAction.setEnabled( !q->mainWindow() || !q->mainWindow()->isVisible() );
        encryptClipboardAction.setEnabled( EncryptClipboardCommand::canEncryptCurrentClipboard() );
        openPGPSignClipboardAction.setEnabled( SignClipboardCommand::canSignCurrentClipboard() );
        smimeSignClipboardAction.setEnabled( SignClipboardCommand::canSignCurrentClipboard() );
        decryptVerifyClipboardAction.setEnabled( DecryptVerifyClipboardCommand::canDecryptVerifyCurrentClipboard() );
        setInitialPinAction.setEnabled( anyCardHasNullPin );
        learnCertificatesAction.setEnabled( anyCardCanLearnKeys );

        q->setAttentionWanted( ( anyCardHasNullPin || anyCardCanLearnKeys ) && !q->attentionWindow() );
    }

    void startCommand( Command * cmd ) {
        assert( cmd );
        cmd->setParent( q->mainWindow() );
        cmd->start();
    }

    void slotEncryptClipboard() {
        startCommand( new EncryptClipboardCommand( 0 ) );
    }

    void slotOpenPGPSignClipboard() {
        startCommand( new SignClipboardCommand( GpgME::OpenPGP, 0 ) );
    }

    void slotSMIMESignClipboard() {
        startCommand( new SignClipboardCommand( GpgME::CMS, 0 ) );
    }

    void slotDecryptVerifyClipboard() {
        startCommand( new DecryptVerifyClipboardCommand( 0 ) );
    }

    void slotSetInitialPin() {
        SetInitialPinCommand * cmd = new SetInitialPinCommand( 0 );
        q->setAttentionWindow( cmd->dialog() );
        startCommand( cmd );
    }

    void slotLearnCertificates() {
        LearnCertificatesCommand * cmd = new LearnCertificatesCommand( 0 );
        q->setAttentionWindow( cmd->dialog() );
        startCommand( cmd );
    }

private:
    void connectConfigureDialog() {
        if ( configureDialog && q->mainWindow() )
            connect( configureDialog, SIGNAL(configCommitted()), q->mainWindow(), SLOT(slotConfigCommitted()) );
    }
    void disconnectConfigureDialog() {
        if ( configureDialog && q->mainWindow() )
            disconnect( configureDialog, SIGNAL(configCommitted()), q->mainWindow(), SLOT(slotConfigCommitted()) );
    }
    void connectMainWindow() {
        if ( q->mainWindow() )
            connect( q->mainWindow(), SIGNAL(configDialogRequested()), q, SLOT(openOrRaiseConfigDialog()) );
    }
    void disconnectMainWindow() {
        if ( q->mainWindow() )
            connect( q->mainWindow(), SIGNAL(configDialogRequested()), q, SLOT(openOrRaiseConfigDialog()) );
    }

private:
    bool anyCardHasNullPin;
    bool anyCardCanLearnKeys;

    QMenu menu;
    QAction openCertificateManagerAction;
    QAction configureAction;
    QAction aboutAction;
    QAction quitAction;
    QMenu clipboardMenu;
    QAction encryptClipboardAction;
    QAction smimeSignClipboardAction;
    QAction openPGPSignClipboardAction;
    QAction decryptVerifyClipboardAction;
    QMenu cardMenu;
    QAction setInitialPinAction;
    QAction learnCertificatesAction;

    QPointer<KAboutApplicationDialog> aboutDialog;
    QPointer<ConfigureDialog> configureDialog;

    QRect mainWindowPreviousGeometry;
};

SysTrayIcon::Private::Private( SysTrayIcon * qq )
    : q( qq ),
      anyCardHasNullPin( false ),
      anyCardCanLearnKeys( false ),
      menu(),
      openCertificateManagerAction( i18n("&Open Certificate Manager..."), q ),
      configureAction( i18n("&Configure %1...", KGlobal::mainComponent().aboutData()->programName() ), q ),
      aboutAction( i18n("&About %1...", KGlobal::mainComponent().aboutData()->programName() ), q ),
      quitAction( i18n("&Shutdown Kleopatra"), q ),
      clipboardMenu( i18n("Clipboard" ) ),
      encryptClipboardAction( i18n("Encrypt..."), q ),
      smimeSignClipboardAction( i18n("S/MIME-Sign..."), q ),
      openPGPSignClipboardAction( i18n("OpenPGP-Sign..."), q ),
      decryptVerifyClipboardAction( i18n("Decrypt/Verify..."), q ),
      cardMenu( i18n("SmartCard") ),
      setInitialPinAction( i18n("Set Initial PIN..."), q ),
      learnCertificatesAction( i18n("Learn Card Certificates..."), q ),
      aboutDialog(),
      mainWindowPreviousGeometry()
{
    q->setNormalIcon( KIcon( "kleopatra" ) );
    q->setAttentionIcon( KIcon( "smartcard" ) );

    KDAB_SET_OBJECT_NAME( menu );
    KDAB_SET_OBJECT_NAME( openCertificateManagerAction );
    KDAB_SET_OBJECT_NAME( configureAction );
    KDAB_SET_OBJECT_NAME( aboutAction );
    KDAB_SET_OBJECT_NAME( quitAction );
    KDAB_SET_OBJECT_NAME( clipboardMenu );
    KDAB_SET_OBJECT_NAME( encryptClipboardAction );
    KDAB_SET_OBJECT_NAME( smimeSignClipboardAction );
    KDAB_SET_OBJECT_NAME( openPGPSignClipboardAction );
    KDAB_SET_OBJECT_NAME( decryptVerifyClipboardAction );
    KDAB_SET_OBJECT_NAME( cardMenu );
    KDAB_SET_OBJECT_NAME( setInitialPinAction );
    KDAB_SET_OBJECT_NAME( learnCertificatesAction );

    connect( &openCertificateManagerAction, SIGNAL(triggered()), q, SLOT(openOrRaiseMainWindow()) );
    connect( &configureAction, SIGNAL(triggered()), q, SLOT(openOrRaiseConfigDialog()) );
    connect( &aboutAction, SIGNAL(triggered()), q, SLOT(slotAbout()) );
    connect( &quitAction, SIGNAL(triggered()), QCoreApplication::instance(), SLOT(quit()) );
    connect( &encryptClipboardAction, SIGNAL(triggered()), q, SLOT(slotEncryptClipboard()) );
    connect( &smimeSignClipboardAction, SIGNAL(triggered()), q, SLOT(slotSMIMESignClipboard()) );
    connect( &openPGPSignClipboardAction, SIGNAL(triggered()), q, SLOT(slotOpenPGPSignClipboard()) );
    connect( &decryptVerifyClipboardAction, SIGNAL(triggered()), q, SLOT(slotDecryptVerifyClipboard()) );
    connect( &setInitialPinAction, SIGNAL(triggered()), q, SLOT(slotSetInitialPin()) );
    connect( &learnCertificatesAction, SIGNAL(triggered()), q, SLOT(slotLearnCertificates()) );

    connect( QApplication::clipboard(), SIGNAL(changed(QClipboard::Mode)),
             q, SLOT(slotEnableDisableActions()) );

    menu.addAction( &openCertificateManagerAction );
    menu.addAction( &configureAction );
    menu.addAction( &aboutAction );
    menu.addSeparator();
    menu.addMenu( &clipboardMenu );
    clipboardMenu.addAction( &encryptClipboardAction );
    clipboardMenu.addAction( &smimeSignClipboardAction );
    clipboardMenu.addAction( &openPGPSignClipboardAction );
    clipboardMenu.addAction( &decryptVerifyClipboardAction );
    menu.addSeparator();
    menu.addMenu( &cardMenu );
    cardMenu.addAction( &setInitialPinAction );
    cardMenu.addAction( &learnCertificatesAction );
    menu.addSeparator();
    menu.addAction( &quitAction );

    q->setContextMenu( &menu );
}

SysTrayIcon::Private::~Private() {}

SysTrayIcon::SysTrayIcon( QObject * p )
    : SystemTrayIcon( p ), d( new Private( this ) )
{
    KGlobal::ref();
    slotEnableDisableActions();
}

SysTrayIcon::~SysTrayIcon() {
    KGlobal::deref();
}

void SysTrayIcon::doMainWindowClosed( QWidget * mw ) {
    d->mainWindowPreviousGeometry = mw->geometry();
}

MainWindow * SysTrayIcon::mainWindow() const {
    return static_cast<MainWindow*>( SystemTrayIcon::mainWindow() );
}

QDialog * SysTrayIcon::attentionWindow() const {
    return static_cast<QDialog*>( SystemTrayIcon::attentionWindow() );
}

static void open_or_raise( QWidget * w ) {
    if ( w->isMinimized() ) {
        KWindowSystem::unminimizeWindow( w->winId());
        w->raise();
    } else if ( w->isVisible() ) {
        w->raise();
    } else {
        w->show();
    }
}

void SysTrayIcon::openOrRaiseMainWindow() {
    MainWindow * mw = mainWindow();
    if ( !mw ) {
        mw = new MainWindow;
        mw->setAttribute( Qt::WA_DeleteOnClose );
        if ( d->mainWindowPreviousGeometry.isValid() )
            mw->setGeometry( d->mainWindowPreviousGeometry );
        setMainWindow( mw );
        d->connectConfigureDialog();
        d->connectMainWindow();
    }
    open_or_raise( mw );
}

void SysTrayIcon::doActivated() {
    if ( d->anyCardHasNullPin )
        d->slotSetInitialPin();
    else if ( d->anyCardCanLearnKeys )
        d->slotLearnCertificates();
    else
        openOrRaiseMainWindow();
}

void SysTrayIcon::openOrRaiseConfigDialog() {
    if ( !d->configureDialog ) {
        d->configureDialog = new ConfigureDialog;
        d->configureDialog->setAttribute( Qt::WA_DeleteOnClose );
        d->connectConfigureDialog();
    }
    open_or_raise( d->configureDialog );
}

void SysTrayIcon::setAnyCardHasNullPin( bool on ) {
    if ( d->anyCardHasNullPin == on )
        return;
    d->anyCardHasNullPin = on;
    slotEnableDisableActions();
}

void SysTrayIcon::setAnyCardCanLearnKeys( bool on ) {
    if ( d->anyCardCanLearnKeys == on )
        return;
    d->anyCardCanLearnKeys = on;
    slotEnableDisableActions();
}

void SysTrayIcon::slotEnableDisableActions() {
    d->enableDisableActions();
}

#include "moc_systrayicon.cpp"

<|endoftext|>


<commit_before>// ------------------ //
//  Standard Solver   //
// ------------------ //

template<typename VectorType, typename MatrixType>
auto Standard::solve(const MatrixType &A,const VectorType &v)
    -> VectorType
{
    return A.solve(v);
}

// -------------------------  //
//  Conjugate Gradient Solver //
// -------------------------  //

ConjugateGradient::ConjugateGradient(double tol, int verbosity_)
    : verbosity(verbosity_), tolerance(tol)
{
    // Nothing to do here.
}

template
<
typename VectorType,
typename MatrixType,
template <LogType> class Log
>
auto ConjugateGradient::solve(const MatrixType &A,
                              const VectorType &v)
    -> VectorType
{
    using RealType = typename VectorType::RealType;

    Log<LogType::SOL_CG> log(verbosity);

    RealType tol, alpha, beta, rnorm, vnorm;
    VectorType x, r, p, xnew, rnew, pnew;

    x = v;
    r = A * x - v;
    p = -1.0 * r;
    vnorm = v.norm();
    rnorm = r.norm();

    log.init(tolerance, rnorm, vnorm);

    int i = 0;
    while (rnorm / vnorm > tolerance)
    {
        alpha = dot(r, r) / dot(p, A * p);
        xnew  = x + alpha *     p;
        rnew  = A * x - v;
        beta  = dot(rnew, rnew) / dot(r, r);
        pnew  = beta * p - rnew;

        x = xnew;
        r = rnew; rnorm = r.norm();
        p = pnew;

        i++;
        if (i % 10 == 0)
            log.step(i, rnorm);
    }
    log.finalize(i);

    return x;
}

// -----------------------  //
//  Preconditioned Solver   //
// -----------------------  //

template<typename Solver, typename Transformation>
PreconditionedSolver<Solver, Transformation>::
PreconditionedSolver(Solver s, Transformation t)
    : solver(s), transformation(t)
{
    // Nothin to do here.
}

template<typename Solver, typename Transformation>
    template<typename VectorType, typename MatrixType>
auto PreconditionedSolver<Solver, Transformation>::solve(const MatrixType &A,
                                                         const VectorType &v)
    -> VectorType
{
    VectorType vt = transformation.apply(v);
    auto At       = transformation.apply(A);
    VectorType x  = transformation.apply(solver.solve(At, vt));
    return x;
}
<commit_msg>Fixed residual computation in CG.<commit_after>// ------------------ //
//  Standard Solver   //
// ------------------ //

template<typename VectorType, typename MatrixType>
auto Standard::solve(const MatrixType &A,const VectorType &v)
    -> VectorType
{
    return A.solve(v);
}

// -------------------------  //
//  Conjugate Gradient Solver //
// -------------------------  //

ConjugateGradient::ConjugateGradient(double tol, int verbosity_)
    : verbosity(verbosity_), tolerance(tol)
{
    // Nothing to do here.
}

template
<
typename VectorType,
typename MatrixType,
template <LogType> class Log
>
auto ConjugateGradient::solve(const MatrixType &A,
                              const VectorType &v)
    -> VectorType
{
    using RealType = typename VectorType::RealType;

    Log<LogType::SOL_CG> log(verbosity);

    RealType tol, alpha, beta, rnorm, vnorm;
    VectorType x, r, p, xnew, rnew, pnew;

    x = v;
    r = A * x - v;
    p = -1.0 * r;
    vnorm = v.norm();
    rnorm = r.norm();

    log.init(tolerance, rnorm, vnorm);

    int i = 0;
    while (rnorm / vnorm > tolerance)
    {
        alpha = dot(r, r) / dot(p, A * p);
        xnew  = x + alpha *     p;
        rnew  = A * xnew - v;
        beta  = dot(rnew, rnew) / dot(r, r);
        pnew  = beta * p - rnew;

        x = xnew;
        r = rnew; rnorm = r.norm();
        p = pnew;

        i++;
        if (i % 10 == 0)
            log.step(i, rnorm);
    }
    log.finalize(i);

    return x;
}

// -----------------------  //
//  Preconditioned Solver   //
// -----------------------  //

template<typename Solver, typename Transformation>
PreconditionedSolver<Solver, Transformation>::
PreconditionedSolver(Solver s, Transformation t)
    : solver(s), transformation(t)
{
    // Nothin to do here.
}

template<typename Solver, typename Transformation>
    template<typename VectorType, typename MatrixType>
auto PreconditionedSolver<Solver, Transformation>::solve(const MatrixType &A,
                                                         const VectorType &v)
    -> VectorType
{
    VectorType vt = transformation.apply(v);
    auto At       = transformation.apply(A);
    VectorType x  = transformation.apply(solver.solve(At, vt));
    return x;
}
<|endoftext|>


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

  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
  Copyright (c) 2007 Bruno Virlet <bruno@virlet.org>

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

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

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

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

#include "timelabels.h"
#include "timelabelszone.h"
#include "timescaleconfigdialog.h"
#include "koprefs.h"
#include "views/agendaview/koagenda.h"

#include <KIcon>

#include <QAction>
#include <QMenu>
#include <QPainter>

using namespace KOrg;

TimeLabels::TimeLabels( const KDateTime::Spec &spec, int rows,
                        TimeLabelsZone *parent, Qt::WFlags f )
  : Q3ScrollView( parent, /*name*/0, f )
{
  mTimeLabelsZone = parent;
  mSpec = spec;

  mRows = rows;
  mMiniWidth = 0;

  mCellHeight = KOPrefs::instance()->mHourSize * 4;

  enableClipper( true );

  setHScrollBarMode( AlwaysOff );
  setVScrollBarMode( AlwaysOff );
  setFrameStyle( Plain );

  resizeContents( 50, int( mRows * mCellHeight ) );

  viewport()->setBackgroundRole( QPalette::Background );
  setBackgroundRole( QPalette::Background );

  mMousePos = new QFrame( this );
  mMousePos->setLineWidth( 1 );
  mMousePos->setFrameStyle( QFrame::HLine | QFrame::Plain );
//  mMousePos->setMargin(0);
  QPalette pal;
  pal.setColor( QPalette::Window, // for Oxygen
                KOPrefs::instance()->agendaMarcusBainsLineLineColor() );
  pal.setColor( QPalette::WindowText, // for Plastique
                KOPrefs::instance()->agendaMarcusBainsLineLineColor() );
  mMousePos->setPalette( pal );
  mMousePos->setFixedSize( width(), 1 );
  addChild( mMousePos, 0, 0 );

  if ( mSpec.isValid() ) {
    setToolTip( i18n( "Timezone:" ) + mSpec.timeZone().name() );
  }
}

void TimeLabels::mousePosChanged( const QPoint &pos )
{
  moveChild( mMousePos, 0, pos.y() );

  // The repaint somehow prevents that the red line leaves a black artifact when
  // moved down. It's not a full solution, though.
  repaint();
}

void TimeLabels::showMousePos()
{
  mMousePos->show();
}

void TimeLabels::hideMousePos()
{
  mMousePos->hide();
}

void TimeLabels::setCellHeight( double height )
{
  mCellHeight = height;
}

/*
  Optimization so that only the "dirty" portion of the scroll view is redrawn.
  Unfortunately, this is not called by default paintEvent() method.
*/
void TimeLabels::drawContents( QPainter *p, int cx, int cy, int cw, int ch )
{
  int beginning;

  if ( !mSpec.isValid() ) {
    beginning = 0;
  } else {
    beginning = ( mSpec.timeZone().currentOffset() -
                  KOPrefs::instance()->timeSpec().timeZone().currentOffset() ) / ( 60 * 60 );
  }

  p->setBrush( palette().window() ); // TODO: theming, see if we want sth here...
  p->fillRect( cx, cy, cw, ch, p->brush() );

  // bug:  the parameters cx and cw are the areas that need to be
  //       redrawn, not the area of the widget.  unfortunately, this
  //       code assumes the latter...

  // now, for a workaround...
  cx = contentsX() + frameWidth() * 2;
  cw = contentsWidth();

  // end of workaround
  int cell = ( (int)( cy / mCellHeight ) ) + beginning;  // the hour we start drawing with
  double y = ( cell - beginning ) * mCellHeight;
  QFontMetrics fm = fontMetrics();
  QString hour;
  int timeHeight = fm.ascent();
  QFont hourFont = KOPrefs::instance()->agendaTimeLabelsFont();
  p->setFont( font() );

  QString suffix;
  if ( ! KGlobal::locale()->use12Clock() ) {
      suffix = "00";
  } else {
    suffix = "am";
    if ( cell > 11 ) {
      suffix = "pm";
    }
  }

  // We adjust the size of the hour font to keep it reasonable
  if ( timeHeight >  mCellHeight ) {
    timeHeight = int( mCellHeight - 1 );
    int pointS = hourFont.pointSize();
    while ( pointS > 4 ) { // TODO: use smallestReadableFont() when added to kdelibs
      hourFont.setPointSize( pointS );
      fm = QFontMetrics( hourFont );
      if ( fm.ascent() < mCellHeight ) {
        break;
      }
      --pointS;
    }
    fm = QFontMetrics( hourFont );
    timeHeight = fm.ascent();
  }
  //timeHeight -= (timeHeight/4-2);
  QFont suffixFont = hourFont;
  suffixFont.setPointSize( suffixFont.pointSize() / 2 );
  QFontMetrics fmS( suffixFont );
  int startW = mMiniWidth - frameWidth() - 2 ;
  int tw2 = fmS.width( suffix );
  int divTimeHeight = ( timeHeight - 1 ) / 2 - 1;
  //testline
  //p->drawLine(0,0,0,contentsHeight());
  while ( y < cy + ch + mCellHeight ) {
    // hour, full line
    p->drawLine( cx, int( y ), cw + 2, int( y ) );

    hour.setNum( cell % 24 );
    // handle different timezones
    if ( cell < 0 ) {
      hour.setNum( cell + 24 );
    }
    // handle 24h and am/pm time formats
    if ( KGlobal::locale()->use12Clock() ) {
      if ( cell == 12 ) {
        suffix = "pm";
      }
      if ( cell == 0 ) {
        hour.setNum( 12 );
      }
      if ( cell > 12 ) {
        hour.setNum( cell - 12 );
      }
    }

    QPen pen;
    if ( cell < 0 || cell >= 24 ) {
      pen.setColor( QColor( 150, 150, 150 ) );
    } else {
      pen.setColor( QPalette::Text );
    }
    p->setPen( pen );

    // center and draw the time label
    int timeWidth = fm.width( hour );
    int offset = startW - timeWidth - tw2 -1 ;
    p->setFont( hourFont );
    p->drawText( offset, int( y + timeHeight ), hour );
    p->setFont( suffixFont );
    offset = startW - tw2;
    p->drawText( offset, int( y + timeHeight - divTimeHeight ), suffix );

    // increment indices
    y += mCellHeight;
    cell++;
  }
}

/**
   Calculates the minimum width.
*/
int TimeLabels::minimumWidth() const
{
  return mMiniWidth;
}

/** updates widget's internal state */
void TimeLabels::updateConfig()
{
  setFont( KOPrefs::instance()->agendaTimeLabelsFont() );

  QString test = "20";
  if ( KGlobal::locale()->use12Clock() ) {
      test = "12";
  }
  mMiniWidth = fontMetrics().width( test );
  if ( KGlobal::locale()->use12Clock() ) {
    test = "pm";
  } else {
    test = "00";
  }
  QFont sFont = font();
  sFont.setPointSize( sFont.pointSize() / 2 );
  QFontMetrics fmS( sFont );
  mMiniWidth += fmS.width( test ) + frameWidth() * 2 + 4 ;
  // update geometry restrictions based on new settings
  setFixedWidth( mMiniWidth );

  // update HourSize
  mCellHeight = KOPrefs::instance()->mHourSize * 4;
  // If the agenda is zoomed out so that more than 24 would be shown,
  // the agenda only shows 24 hours, so we need to take the cell height
  // from the agenda, which is larger than the configured one!
  if ( mCellHeight < 4 * mAgenda->gridSpacingY() ) {
       mCellHeight = 4 * mAgenda->gridSpacingY();
  }
  resizeContents( mMiniWidth, int( mRows * mCellHeight + 1 ) );
}

/** update time label positions */
void TimeLabels::positionChanged()
{
  int adjustment = mAgenda->contentsY();
  if ( adjustment != contentsY() ) {
    setContentsPos( 0, adjustment );
  }
}

void TimeLabels::positionChanged( int pos )
{
  if ( pos != contentsY() ) {
    setContentsPos( 0, pos );
  }
}

/**  */
void TimeLabels::setAgenda( KOAgenda *agenda )
{
  mAgenda = agenda;

  connect( mAgenda, SIGNAL(mousePosSignal(const QPoint &)),
           this, SLOT(mousePosChanged(const QPoint &)) );
  connect( mAgenda, SIGNAL(enterAgenda()), this, SLOT(showMousePos()) );
  connect( mAgenda, SIGNAL(leaveAgenda()), this, SLOT(hideMousePos()) );
  connect( mAgenda, SIGNAL(gridSpacingYChanged(double)),
           this, SLOT(setCellHeight(double)) );
}

/** This is called in response to repaint() */
void TimeLabels::paintEvent( QPaintEvent * )
{
//  kDebug();
  QPainter painter( this );
  drawContents( &painter, contentsX(), contentsY(), visibleWidth(), visibleHeight() );
}

void TimeLabels::contextMenuEvent( QContextMenuEvent *event )
{
  Q_UNUSED( event );

  QMenu popup( this );
  QAction *editTimeZones =
    popup.addAction( KIcon( "document-properties" ), i18n( "&Edit Timezones..." ) );
  QAction *removeTimeZone =
    popup.addAction( KIcon( "edit-delete" ),
                     i18n( "&Remove %1 Timezone", mSpec.timeZone().name() ) );
  if ( !mSpec.isValid() ||
       !KOPrefs::instance()->timeScaleTimezones().count() ||
       mSpec == KOPrefs::instance()->timeSpec() ) {
    removeTimeZone->setEnabled( false );
  }

  QAction *activatedAction = popup.exec( QCursor::pos() );
  if ( activatedAction == editTimeZones ) {
    TimeScaleConfigDialog dialog( this );
    if ( dialog.exec() == QDialog::Accepted ) {
      mTimeLabelsZone->reset();
    }
  } else if ( activatedAction == removeTimeZone ) {
    QStringList list = KOPrefs::instance()->timeScaleTimezones();
    list.removeAll( mSpec.timeZone().name() );
    KOPrefs::instance()->setTimeScaleTimezones( list );
    mTimeLabelsZone->reset();
    hide();
    deleteLater();
  }
}

KDateTime::Spec TimeLabels::timeSpec()
{
  return mSpec;
}

QString TimeLabels::header() const
{
  KTimeZone tz = mSpec.timeZone();

  QString header = tz.countryCode();
  if ( header.isEmpty() ) {
    header = tz.name();
  }

  return header;
}

QString TimeLabels::headerToolTip() const
{
  KTimeZone tz = mSpec.timeZone();

  QString toolTip;
  toolTip += "<qt>";
  toolTip += i18n( "Timezone: %1", tz.name() );
  toolTip += "
";
  toolTip += i18n( "Country Code: %1", tz.countryCode() );
  if ( !tz.abbreviations().isEmpty() ) {
    toolTip += "
";
    toolTip += i18n( "Abbreviations:" );
    foreach ( const QByteArray &a, tz.abbreviations() ) {
      toolTip += "
";
      toolTip += " " + QString::fromLocal8Bit( a );
    }
  }
  if ( !tz.comment().isEmpty() ) {
    toolTip += "
";
    toolTip += i18n( "Comment:
%1", tz.comment() );
  }
  toolTip += "</qt>";

  return toolTip;
}

#include "timelabels.moc"
<commit_msg>add a TODO SVN_SILENT:<commit_after>/*
  This file is part of KOrganizer.

  Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
  Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
  Copyright (c) 2007 Bruno Virlet <bruno@virlet.org>

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

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

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

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

#include "timelabels.h"
#include "timelabelszone.h"
#include "timescaleconfigdialog.h"
#include "koprefs.h"
#include "views/agendaview/koagenda.h"

#include <KIcon>

#include <QAction>
#include <QMenu>
#include <QPainter>

using namespace KOrg;

TimeLabels::TimeLabels( const KDateTime::Spec &spec, int rows,
                        TimeLabelsZone *parent, Qt::WFlags f )
  : Q3ScrollView( parent, /*name*/0, f )
{
  mTimeLabelsZone = parent;
  mSpec = spec;

  mRows = rows;
  mMiniWidth = 0;

  mCellHeight = KOPrefs::instance()->mHourSize * 4;

  enableClipper( true );

  setHScrollBarMode( AlwaysOff );
  setVScrollBarMode( AlwaysOff );
  setFrameStyle( Plain );

  resizeContents( 50, int( mRows * mCellHeight ) );

  viewport()->setBackgroundRole( QPalette::Background );
  setBackgroundRole( QPalette::Background );

  mMousePos = new QFrame( this );
  mMousePos->setLineWidth( 1 );
  mMousePos->setFrameStyle( QFrame::HLine | QFrame::Plain );
//  mMousePos->setMargin(0);
  QPalette pal;
  pal.setColor( QPalette::Window, // for Oxygen
                KOPrefs::instance()->agendaMarcusBainsLineLineColor() );
  pal.setColor( QPalette::WindowText, // for Plastique
                KOPrefs::instance()->agendaMarcusBainsLineLineColor() );
  mMousePos->setPalette( pal );
  mMousePos->setFixedSize( width(), 1 );
  addChild( mMousePos, 0, 0 );

  if ( mSpec.isValid() ) {
    setToolTip( i18n( "Timezone:" ) + mSpec.timeZone().name() );
  }
}

void TimeLabels::mousePosChanged( const QPoint &pos )
{
  moveChild( mMousePos, 0, pos.y() );

  // The repaint somehow prevents that the red line leaves a black artifact when
  // moved down. It's not a full solution, though.
  repaint();
}

void TimeLabels::showMousePos()
{
  mMousePos->show();
}

void TimeLabels::hideMousePos()
{
  mMousePos->hide();
}

void TimeLabels::setCellHeight( double height )
{
  mCellHeight = height;
}

/*
  Optimization so that only the "dirty" portion of the scroll view is redrawn.
  Unfortunately, this is not called by default paintEvent() method.
*/
void TimeLabels::drawContents( QPainter *p, int cx, int cy, int cw, int ch )
{
  int beginning;

  if ( !mSpec.isValid() ) {
    beginning = 0;
  } else {
    beginning = ( mSpec.timeZone().currentOffset() -
                  KOPrefs::instance()->timeSpec().timeZone().currentOffset() ) / ( 60 * 60 );
  }

  p->setBrush( palette().window() ); // TODO: theming, see if we want sth here...
  p->fillRect( cx, cy, cw, ch, p->brush() );

  // bug:  the parameters cx and cw are the areas that need to be
  //       redrawn, not the area of the widget.  unfortunately, this
  //       code assumes the latter...

  // now, for a workaround...
  cx = contentsX() + frameWidth() * 2;
  cw = contentsWidth();

  // end of workaround
  int cell = ( (int)( cy / mCellHeight ) ) + beginning;  // the hour we start drawing with
  double y = ( cell - beginning ) * mCellHeight;
  QFontMetrics fm = fontMetrics();
  QString hour;
  int timeHeight = fm.ascent();
  QFont hourFont = KOPrefs::instance()->agendaTimeLabelsFont();
  p->setFont( font() );

  //TODO: rewrite this using KLocale's time formats. "am/pm" doesn't make sense
  // in some locale's
  QString suffix;
  if ( ! KGlobal::locale()->use12Clock() ) {
      suffix = "00";
  } else {
    suffix = "am";
    if ( cell > 11 ) {
      suffix = "pm";
    }
  }

  // We adjust the size of the hour font to keep it reasonable
  if ( timeHeight >  mCellHeight ) {
    timeHeight = int( mCellHeight - 1 );
    int pointS = hourFont.pointSize();
    while ( pointS > 4 ) { // TODO: use smallestReadableFont() when added to kdelibs
      hourFont.setPointSize( pointS );
      fm = QFontMetrics( hourFont );
      if ( fm.ascent() < mCellHeight ) {
        break;
      }
      --pointS;
    }
    fm = QFontMetrics( hourFont );
    timeHeight = fm.ascent();
  }
  //timeHeight -= (timeHeight/4-2);
  QFont suffixFont = hourFont;
  suffixFont.setPointSize( suffixFont.pointSize() / 2 );
  QFontMetrics fmS( suffixFont );
  int startW = mMiniWidth - frameWidth() - 2 ;
  int tw2 = fmS.width( suffix );
  int divTimeHeight = ( timeHeight - 1 ) / 2 - 1;
  //testline
  //p->drawLine(0,0,0,contentsHeight());
  while ( y < cy + ch + mCellHeight ) {
    // hour, full line
    p->drawLine( cx, int( y ), cw + 2, int( y ) );

    hour.setNum( cell % 24 );
    // handle different timezones
    if ( cell < 0 ) {
      hour.setNum( cell + 24 );
    }
    // handle 24h and am/pm time formats
    if ( KGlobal::locale()->use12Clock() ) {
      if ( cell == 12 ) {
        suffix = "pm";
      }
      if ( cell == 0 ) {
        hour.setNum( 12 );
      }
      if ( cell > 12 ) {
        hour.setNum( cell - 12 );
      }
    }

    QPen pen;
    if ( cell < 0 || cell >= 24 ) {
      pen.setColor( QColor( 150, 150, 150 ) );
    } else {
      pen.setColor( QPalette::Text );
    }
    p->setPen( pen );

    // center and draw the time label
    int timeWidth = fm.width( hour );
    int offset = startW - timeWidth - tw2 -1 ;
    p->setFont( hourFont );
    p->drawText( offset, int( y + timeHeight ), hour );
    p->setFont( suffixFont );
    offset = startW - tw2;
    p->drawText( offset, int( y + timeHeight - divTimeHeight ), suffix );

    // increment indices
    y += mCellHeight;
    cell++;
  }
}

/**
   Calculates the minimum width.
*/
int TimeLabels::minimumWidth() const
{
  return mMiniWidth;
}

/** updates widget's internal state */
void TimeLabels::updateConfig()
{
  setFont( KOPrefs::instance()->agendaTimeLabelsFont() );

  QString test = "20";
  if ( KGlobal::locale()->use12Clock() ) {
      test = "12";
  }
  mMiniWidth = fontMetrics().width( test );
  if ( KGlobal::locale()->use12Clock() ) {
    test = "pm";
  } else {
    test = "00";
  }
  QFont sFont = font();
  sFont.setPointSize( sFont.pointSize() / 2 );
  QFontMetrics fmS( sFont );
  mMiniWidth += fmS.width( test ) + frameWidth() * 2 + 4 ;
  // update geometry restrictions based on new settings
  setFixedWidth( mMiniWidth );

  // update HourSize
  mCellHeight = KOPrefs::instance()->mHourSize * 4;
  // If the agenda is zoomed out so that more than 24 would be shown,
  // the agenda only shows 24 hours, so we need to take the cell height
  // from the agenda, which is larger than the configured one!
  if ( mCellHeight < 4 * mAgenda->gridSpacingY() ) {
       mCellHeight = 4 * mAgenda->gridSpacingY();
  }
  resizeContents( mMiniWidth, int( mRows * mCellHeight + 1 ) );
}

/** update time label positions */
void TimeLabels::positionChanged()
{
  int adjustment = mAgenda->contentsY();
  if ( adjustment != contentsY() ) {
    setContentsPos( 0, adjustment );
  }
}

void TimeLabels::positionChanged( int pos )
{
  if ( pos != contentsY() ) {
    setContentsPos( 0, pos );
  }
}

/**  */
void TimeLabels::setAgenda( KOAgenda *agenda )
{
  mAgenda = agenda;

  connect( mAgenda, SIGNAL(mousePosSignal(const QPoint &)),
           this, SLOT(mousePosChanged(const QPoint &)) );
  connect( mAgenda, SIGNAL(enterAgenda()), this, SLOT(showMousePos()) );
  connect( mAgenda, SIGNAL(leaveAgenda()), this, SLOT(hideMousePos()) );
  connect( mAgenda, SIGNAL(gridSpacingYChanged(double)),
           this, SLOT(setCellHeight(double)) );
}

/** This is called in response to repaint() */
void TimeLabels::paintEvent( QPaintEvent * )
{
//  kDebug();
  QPainter painter( this );
  drawContents( &painter, contentsX(), contentsY(), visibleWidth(), visibleHeight() );
}

void TimeLabels::contextMenuEvent( QContextMenuEvent *event )
{
  Q_UNUSED( event );

  QMenu popup( this );
  QAction *editTimeZones =
    popup.addAction( KIcon( "document-properties" ), i18n( "&Edit Timezones..." ) );
  QAction *removeTimeZone =
    popup.addAction( KIcon( "edit-delete" ),
                     i18n( "&Remove %1 Timezone", mSpec.timeZone().name() ) );
  if ( !mSpec.isValid() ||
       !KOPrefs::instance()->timeScaleTimezones().count() ||
       mSpec == KOPrefs::instance()->timeSpec() ) {
    removeTimeZone->setEnabled( false );
  }

  QAction *activatedAction = popup.exec( QCursor::pos() );
  if ( activatedAction == editTimeZones ) {
    TimeScaleConfigDialog dialog( this );
    if ( dialog.exec() == QDialog::Accepted ) {
      mTimeLabelsZone->reset();
    }
  } else if ( activatedAction == removeTimeZone ) {
    QStringList list = KOPrefs::instance()->timeScaleTimezones();
    list.removeAll( mSpec.timeZone().name() );
    KOPrefs::instance()->setTimeScaleTimezones( list );
    mTimeLabelsZone->reset();
    hide();
    deleteLater();
  }
}

KDateTime::Spec TimeLabels::timeSpec()
{
  return mSpec;
}

QString TimeLabels::header() const
{
  KTimeZone tz = mSpec.timeZone();

  QString header = tz.countryCode();
  if ( header.isEmpty() ) {
    header = tz.name();
  }

  return header;
}

QString TimeLabels::headerToolTip() const
{
  KTimeZone tz = mSpec.timeZone();

  QString toolTip;
  toolTip += "<qt>";
  toolTip += i18n( "Timezone: %1", tz.name() );
  toolTip += "
";
  toolTip += i18n( "Country Code: %1", tz.countryCode() );
  if ( !tz.abbreviations().isEmpty() ) {
    toolTip += "
";
    toolTip += i18n( "Abbreviations:" );
    foreach ( const QByteArray &a, tz.abbreviations() ) {
      toolTip += "
";
      toolTip += " " + QString::fromLocal8Bit( a );
    }
  }
  if ( !tz.comment().isEmpty() ) {
    toolTip += "
";
    toolTip += i18n( "Comment:
%1", tz.comment() );
  }
  toolTip += "</qt>";

  return toolTip;
}

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


<commit_before>/*
    Crystal Space Windowing System: Windowing System client system driver
    Copyright (C) 1998,1999 by Andrew Zabolotny <bit@eltech.ru>

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "sysdef.h"
#include "csws/cswssys.h"
#include "csws/csapp.h"
#include "itxtmgr.h"

// We need the Virtual File System plugin
REGISTER_STATIC_CLASS (csVFS, "crystalspace.kernel.vfs",
  "Crystal Space Virtual File System plug-in")

/*
 * Do a large debug dump just before the program
 * exits. This function can be installed as a last signal
 * handler if the program crashes (for systems that support
 * this).
 */
void debug_dump ()
{
}

/*
 * This function is installed with atexit()
 */
void cleanup ()
{
}

// -------------------------------------------------- cswsSystemDriver class ---

cswsSystemDriver::cswsSystemDriver (csApp *ParentApp) :
  SysSystemDriver ()
{
  textline = NULL;
  application = ParentApp;
}

cswsSystemDriver::~cswsSystemDriver ()
{
  CHK (delete [] linecolor);
  if (textline)
    for (int i = 0; i < maxlines; i++)
      CHKB (delete [] textline [i]);
  CHK (delete [] textline);
  application = NULL;
}

bool cswsSystemDriver::Initialize (int argc, const char* const argv[],
  const char *iConfigName)
{
  if (!SysSystemDriver::Initialize (argc, argv, iConfigName))
    return false;

  int Width = G2D->GetWidth ();
  int Height = G2D->GetHeight ();

  // Initialize console data
  curline = 0;
  textcolor = cs_Color_White;
  maxwidth = Width / 4;
  maxlines = Height / (G2D->GetTextHeight (application->GetFont ()) + 2);

  CHK (textline = new char *[maxlines]);
  CHK (linecolor = new int [maxlines]);
  for (int i = 0; i < maxlines; i++)
  {
    CHK (textline [i] = new char [maxwidth + 1]);
    memset (textline [i], 0, maxwidth + 1);
    linecolor [i] = cs_Color_Black;
  } /* endfor */

  // Open the visual, initialize keyboard and mouse
  if (!Open (application->GetText ()))
    return false;

  // Initialize palette etc (no textures at this time anyway)
  application->PrepareTextures ();

  atexit (cleanup);
  return true;
};

/*
 * The routine to update the screen in demo mode.
 */
void cswsSystemDriver::DemoWrite (const char* buf)
{
  char *crpos;
  while ((crpos = strchr (buf, '\n')))
  {
    *crpos = 0;
    int len = maxwidth - strlen (textline [curline]);
    if (len > 0)
    {
      strncat (textline [curline], buf, len);
      linecolor [curline] = textcolor;
    }
    buf = crpos + 1;
    curline++;
    if (curline >= maxlines)
    {
      for (int i = 1; i < maxlines; i++)
      {
        strcpy (textline [i - 1], textline [i]);
        linecolor [i - 1] = linecolor [i];
      } /* endfor */
      curline--;
    } /* endif */
    strcpy (textline [curline], "");
  } /* endwhile */
  strcpy (textline [curline], buf);
  linecolor [curline] = textcolor;
  RefreshConsole ();
}

void cswsSystemDriver::RefreshConsole ()
{
  if (!G2D)
    return;

  if (G2D->BeginDraw ())
  {
    application->Invalidate(true);
    G2D->Clear (application->Pal [cs_Color_Gray_D]);
    G2D->SetFontID (application->GetFont ());
    int fh = ((csComponent *) application)->TextHeight () + 2;
    for (int i = 0; i < maxlines; i++)
      if (*textline [i])
      {
        G2D->Write (1, 1 + i * fh,
          application->Pal [cs_Color_Black], -1, textline [i]);
        G2D->Write (0, 0 + i * fh,
          application->Pal [linecolor [i]], -1, textline [i]);
      } /* endfor */
    G2D->FinishDraw ();
    G2D->Print (NULL);
  } /* endif */
}

void cswsSystemDriver::Alert (const char *msg)
{
  csSystemDriver::Alert (msg);
  if (ConsoleReady)
  {
    int oldcolor = textcolor;
    textcolor = cs_Color_Red_L;
    DemoWrite (msg);
    textcolor = oldcolor;
  }
}

void cswsSystemDriver::Warn (const char *msg)
{
  csSystemDriver::Warn (msg);
  if (ConsoleReady)
  {
    int oldcolor = textcolor;
    textcolor = cs_Color_Yellow;
    DemoWrite (msg);
    textcolor = oldcolor;
  }
}

void cswsSystemDriver::NextFrame (time_t elapsed_time, time_t current_time)
{
  SysSystemDriver::NextFrame (elapsed_time, current_time);
  application->NextFrame (elapsed_time, current_time);
}

bool cswsSystemDriver::ProcessEvents ()
{
  return application->ProcessEvents ();
}
<commit_msg>Avoided writing to const char*<commit_after>/*
    Crystal Space Windowing System: Windowing System client system driver
    Copyright (C) 1998,1999 by Andrew Zabolotny <bit@eltech.ru>

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

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#define SYSDEF_ALLOCA
#include "sysdef.h"
#include "csws/cswssys.h"
#include "csws/csapp.h"
#include "itxtmgr.h"

// We need the Virtual File System plugin
REGISTER_STATIC_CLASS (csVFS, "crystalspace.kernel.vfs",
  "Crystal Space Virtual File System plug-in")

/*
 * Do a large debug dump just before the program
 * exits. This function can be installed as a last signal
 * handler if the program crashes (for systems that support
 * this).
 */
void debug_dump ()
{
}

/*
 * This function is installed with atexit()
 */
void cleanup ()
{
}

// -------------------------------------------------- cswsSystemDriver class ---

cswsSystemDriver::cswsSystemDriver (csApp *ParentApp) :
  SysSystemDriver ()
{
  textline = NULL;
  application = ParentApp;
}

cswsSystemDriver::~cswsSystemDriver ()
{
  CHK (delete [] linecolor);
  if (textline)
    for (int i = 0; i < maxlines; i++)
      CHKB (delete [] textline [i]);
  CHK (delete [] textline);
  application = NULL;
}

bool cswsSystemDriver::Initialize (int argc, const char* const argv[],
  const char *iConfigName)
{
  if (!SysSystemDriver::Initialize (argc, argv, iConfigName))
    return false;

  int Width = G2D->GetWidth ();
  int Height = G2D->GetHeight ();

  // Initialize console data
  curline = 0;
  textcolor = cs_Color_White;
  maxwidth = Width / 4;
  maxlines = Height / (G2D->GetTextHeight (application->GetFont ()) + 2);

  CHK (textline = new char *[maxlines]);
  CHK (linecolor = new int [maxlines]);
  for (int i = 0; i < maxlines; i++)
  {
    CHK (textline [i] = new char [maxwidth + 1]);
    memset (textline [i], 0, maxwidth + 1);
    linecolor [i] = cs_Color_Black;
  } /* endfor */

  // Open the visual, initialize keyboard and mouse
  if (!Open (application->GetText ()))
    return false;

  // Initialize palette etc (no textures at this time anyway)
  application->PrepareTextures ();

  atexit (cleanup);
  return true;
};

/*
 * The routine to update the screen in demo mode.
 */
void cswsSystemDriver::DemoWrite (const char* buf)
{
  const char *crpos;
  while ((crpos = strchr (buf, '\n')))
  {
    size_t sl = crpos - buf;
    size_t rl = maxwidth - strlen (textline [curline]);
    if (sl > rl) sl = rl;
    if (sl > 0)
    {
      rl = strlen (textline [curline]);
      memcpy (textline [curline] + rl, buf, sl);
      textline [curline][rl + sl] = 0;
      linecolor [curline] = textcolor;
    }
    buf = crpos + 1;
    curline++;
    if (curline >= maxlines)
    {
      for (int i = 1; i < maxlines; i++)
      {
        strcpy (textline [i - 1], textline [i]);
        linecolor [i - 1] = linecolor [i];
      } /* endfor */
      curline--;
    } /* endif */
    strcpy (textline [curline], "");
  } /* endwhile */
  strcpy (textline [curline], buf);
  linecolor [curline] = textcolor;
  RefreshConsole ();
}

void cswsSystemDriver::RefreshConsole ()
{
  if (!G2D)
    return;

  if (G2D->BeginDraw ())
  {
    application->Invalidate(true);
    G2D->Clear (application->Pal [cs_Color_Gray_D]);
    G2D->SetFontID (application->GetFont ());
    int fh = ((csComponent *) application)->TextHeight () + 2;
    for (int i = 0; i < maxlines; i++)
      if (*textline [i])
      {
        G2D->Write (1, 1 + i * fh,
          application->Pal [cs_Color_Black], -1, textline [i]);
        G2D->Write (0, 0 + i * fh,
          application->Pal [linecolor [i]], -1, textline [i]);
      } /* endfor */
    G2D->FinishDraw ();
    G2D->Print (NULL);
  } /* endif */
}

void cswsSystemDriver::Alert (const char *msg)
{
  csSystemDriver::Alert (msg);
  if (ConsoleReady)
  {
    int oldcolor = textcolor;
    textcolor = cs_Color_Red_L;
    DemoWrite (msg);
    textcolor = oldcolor;
  }
}

void cswsSystemDriver::Warn (const char *msg)
{
  csSystemDriver::Warn (msg);
  if (ConsoleReady)
  {
    int oldcolor = textcolor;
    textcolor = cs_Color_Yellow;
    DemoWrite (msg);
    textcolor = oldcolor;
  }
}

void cswsSystemDriver::NextFrame (time_t elapsed_time, time_t current_time)
{
  SysSystemDriver::NextFrame (elapsed_time, current_time);
  application->NextFrame (elapsed_time, current_time);
}

bool cswsSystemDriver::ProcessEvents ()
{
  return application->ProcessEvents ();
}
<|endoftext|>


<commit_before>// @(#)root/krb5auth:$Name: PROOF_MLM $:$Id: TKSocket.cxx,v 1.1.4.2 2004/11/02 22:02:54 maartenb Exp $
// Author: Maarten Ballintijn   27/10/2003

#include "config.h"
#include <stdlib.h>

#include <netinet/in.h>

#include "TKSocket.h"
#include "TSocket.h"
#include "TError.h"

extern "C" {
// missing from "krb5.h"
extern int krb5_net_read(/*IN*/ krb5_context context, int fd,
                         /*OUT*/ char *buf,/*IN*/ int len);

extern int krb5_net_write(/*IN*/ krb5_context context, int fd,
                          const char *buf, int len);
}

ClassImp(TKSocket)

krb5_context TKSocket::fgContext = 0;
krb5_ccache TKSocket::fgCCDef = 0;
krb5_principal TKSocket::fgClient = 0;

TKSocket::TKSocket(TSocket *s)
   : fSocket(s), fServer(0), fAuthContext(0)
{
}

TKSocket::~TKSocket()
{
   krb5_free_principal(fgContext, fServer);
   krb5_auth_con_free(fgContext, fAuthContext);
   delete fSocket;
}

TKSocket *TKSocket::Connect(const char *server, Int_t port)
{
   Int_t rc;

   if (fgContext == 0) {
      rc = krb5_init_context(&fgContext);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while initializing krb5 (%d), %s",
                 rc, error_message(rc));
         return 0;
      }

      rc = krb5_cc_default(fgContext, &fgCCDef);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while getting default credential cache (%d), %s",
                 rc, error_message(rc));
         krb5_free_context(fgContext); fgContext = 0;
         return 0;
      }

      rc = krb5_cc_get_principal(fgContext, fgCCDef, &fgClient);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while getting client principal from %s (%d), %s",
                 krb5_cc_get_name(fgContext,fgCCDef), rc, error_message(rc));
         krb5_cc_close(fgContext,fgCCDef); fgCCDef = 0;
         krb5_free_context(fgContext); fgContext = 0;
         return 0;
      }
   }

   TSocket  *s = new TSocket(server, port);

   if (!s->IsValid()) {
      ::SysError("TKSocket::Connect","Cannot connect to %s:%d", server, port);
      delete s;
      return 0;
   }

   TKSocket *ks = new TKSocket(s);

   rc = krb5_sname_to_principal(fgContext, server, "host", KRB5_NT_SRV_HST, &ks->fServer);
   if (rc != 0) {
      ::Error("TKSocket::Connect","while getting server principal (%d), %s",
              rc, error_message(rc));
      delete ks;
      return 0;
   }

   krb5_data cksum_data;
   cksum_data.data = StrDup(server);
   cksum_data.length = strlen(server);

   krb5_error *err_ret;
   krb5_ap_rep_enc_part *rep_ret;

   int sock = ks->fSocket->GetDescriptor();
   rc = krb5_sendauth(fgContext, &ks->fAuthContext, (krb5_pointer) &sock,
                           "KRB5_TCP_Python_v1.0", fgClient, ks->fServer,
                           AP_OPTS_MUTUAL_REQUIRED,
                           &cksum_data,
                           0,           /* no creds, use ccache instead */
                           fgCCDef, &err_ret, &rep_ret, NULL);

   delete [] cksum_data.data;

   if (rc != 0) {
      ::Error("TKSocket::Connect","while sendauth (%d), %s",
              rc, error_message(rc));
      delete ks;
      return 0;
   }

   return ks;
}

Int_t TKSocket::BlockRead(char *&buf, EEncoding &type)
{
   Int_t rc;
   TDesc desc;
   Int_t fd = fSocket->GetDescriptor();

   rc = krb5_net_read(fgContext, fd, (char *)&desc, sizeof(desc));
   if (rc == 0) errno = ECONNABORTED;

   if (rc <= 0) {
      SysError("BlockRead","reading descriptor (%d), %s",
               rc, error_message(rc));
      return -1;
   }

   type = static_cast<EEncoding>(ntohs(desc.type));

   krb5_data enc;
   enc.length = ntohs(desc.length);
   enc.data = new char[enc.length+1];

Info("BlockRead","read descriptor (%d bytes): lenght %d, type %d",sizeof(desc), enc.length, type);

   rc = krb5_net_read(fgContext, fd, enc.data, enc.length);
   enc.data[enc.length] = 0;

   if (rc == 0) errno = ECONNABORTED;

   if (rc <= 0) {
      SysError("BlockRead","reading data (%d), %s",
               rc, error_message(rc));
      return -1;
   } else {
Info("BlockRead","read %d bytes (rc=%d)",enc.length, rc);
   }

   krb5_data out;
   switch (type) {
   case kNone:
         buf = enc.data;
         rc = enc.length;
         break;
   case kSafe:
         rc = krb5_rd_safe(fgContext, fAuthContext, &enc, &out, 0);
         break;
   case kPriv:
         rc = krb5_rd_priv(fgContext, fAuthContext, &enc, &out, 0);
         break;
   default:
         Error("BlockWrite","unknown encoding type (%d)", type);
         return -1;
   }

   if (type != kNone) {
      // copy data to buffer that is new'ed
      buf = new char[out.length+1];
      memcpy(buf, out.data,out.length);
      buf[out.length] = 0;
      free(out.data);
      delete enc.data;
      rc = out.length;
   }

   return rc;
}

Int_t TKSocket::BlockWrite(const char *buf, Int_t length, EEncoding type)
{
   TDesc desc;
   krb5_data in;
   krb5_data enc;
   Int_t rc;
   in.data = const_cast<char*>(buf);
   in.length = length;

   switch (type) {
   case kNone:
         enc.data = in.data;
         enc.length = in.length;
         break;
   case kSafe:
         rc = krb5_mk_safe(fgContext, fAuthContext, &in, &enc, 0);
         break;
   case kPriv:
         rc = krb5_mk_priv(fgContext, fAuthContext, &in, &enc, 0);
         break;
   default:
         Error("BlockWrite","unknown encoding type (%d)", type);
         return -1;
   }

   desc.length = htons(enc.length);
   desc.type = htons(type);

   Int_t fd = fSocket->GetDescriptor();
   rc = krb5_net_write(fgContext, fd, (char *)&desc, sizeof(desc));
   if (rc <= 0) {
      Error("BlockWrite","writing descriptor (%d), %s",
            rc, error_message(rc));
      return -1;
   }

   rc = krb5_net_write(fgContext, fd, (char *)enc.data, enc.length);
   if (rc <= 0) {
      Error("BlockWrite","writing data (%d), %s",
            rc, error_message(rc));
      return -1;
   }

   if (type != kNone) free(enc.data);

   return rc;
}
<commit_msg>include <sys/types.h> is needed on MacOS X.<commit_after>// @(#)root/krb5auth:$Name:  $:$Id: TKSocket.cxx,v 1.1 2005/02/07 18:02:36 rdm Exp $
// Author: Maarten Ballintijn   27/10/2003

#include "config.h"
#include <stdlib.h>

#include <sys/types.h>
#include <netinet/in.h>

#include "TKSocket.h"
#include "TSocket.h"
#include "TError.h"

extern "C" {
// missing from "krb5.h"
extern int krb5_net_read(/*IN*/ krb5_context context, int fd,
                         /*OUT*/ char *buf,/*IN*/ int len);

extern int krb5_net_write(/*IN*/ krb5_context context, int fd,
                          const char *buf, int len);
}

ClassImp(TKSocket)

krb5_context TKSocket::fgContext = 0;
krb5_ccache TKSocket::fgCCDef = 0;
krb5_principal TKSocket::fgClient = 0;

TKSocket::TKSocket(TSocket *s)
   : fSocket(s), fServer(0), fAuthContext(0)
{
}

TKSocket::~TKSocket()
{
   krb5_free_principal(fgContext, fServer);
   krb5_auth_con_free(fgContext, fAuthContext);
   delete fSocket;
}

TKSocket *TKSocket::Connect(const char *server, Int_t port)
{
   Int_t rc;

   if (fgContext == 0) {
      rc = krb5_init_context(&fgContext);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while initializing krb5 (%d), %s",
                 rc, error_message(rc));
         return 0;
      }

      rc = krb5_cc_default(fgContext, &fgCCDef);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while getting default credential cache (%d), %s",
                 rc, error_message(rc));
         krb5_free_context(fgContext); fgContext = 0;
         return 0;
      }

      rc = krb5_cc_get_principal(fgContext, fgCCDef, &fgClient);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while getting client principal from %s (%d), %s",
                 krb5_cc_get_name(fgContext,fgCCDef), rc, error_message(rc));
         krb5_cc_close(fgContext,fgCCDef); fgCCDef = 0;
         krb5_free_context(fgContext); fgContext = 0;
         return 0;
      }
   }

   TSocket  *s = new TSocket(server, port);

   if (!s->IsValid()) {
      ::SysError("TKSocket::Connect","Cannot connect to %s:%d", server, port);
      delete s;
      return 0;
   }

   TKSocket *ks = new TKSocket(s);

   rc = krb5_sname_to_principal(fgContext, server, "host", KRB5_NT_SRV_HST, &ks->fServer);
   if (rc != 0) {
      ::Error("TKSocket::Connect","while getting server principal (%d), %s",
              rc, error_message(rc));
      delete ks;
      return 0;
   }

   krb5_data cksum_data;
   cksum_data.data = StrDup(server);
   cksum_data.length = strlen(server);

   krb5_error *err_ret;
   krb5_ap_rep_enc_part *rep_ret;

   int sock = ks->fSocket->GetDescriptor();
   rc = krb5_sendauth(fgContext, &ks->fAuthContext, (krb5_pointer) &sock,
                           "KRB5_TCP_Python_v1.0", fgClient, ks->fServer,
                           AP_OPTS_MUTUAL_REQUIRED,
                           &cksum_data,
                           0,           /* no creds, use ccache instead */
                           fgCCDef, &err_ret, &rep_ret, NULL);

   delete [] cksum_data.data;

   if (rc != 0) {
      ::Error("TKSocket::Connect","while sendauth (%d), %s",
              rc, error_message(rc));
      delete ks;
      return 0;
   }

   return ks;
}

Int_t TKSocket::BlockRead(char *&buf, EEncoding &type)
{
   Int_t rc;
   TDesc desc;
   Int_t fd = fSocket->GetDescriptor();

   rc = krb5_net_read(fgContext, fd, (char *)&desc, sizeof(desc));
   if (rc == 0) errno = ECONNABORTED;

   if (rc <= 0) {
      SysError("BlockRead","reading descriptor (%d), %s",
               rc, error_message(rc));
      return -1;
   }

   type = static_cast<EEncoding>(ntohs(desc.type));

   krb5_data enc;
   enc.length = ntohs(desc.length);
   enc.data = new char[enc.length+1];

Info("BlockRead","read descriptor (%d bytes): lenght %d, type %d",sizeof(desc), enc.length, type);

   rc = krb5_net_read(fgContext, fd, enc.data, enc.length);
   enc.data[enc.length] = 0;

   if (rc == 0) errno = ECONNABORTED;

   if (rc <= 0) {
      SysError("BlockRead","reading data (%d), %s",
               rc, error_message(rc));
      return -1;
   } else {
Info("BlockRead","read %d bytes (rc=%d)",enc.length, rc);
   }

   krb5_data out;
   switch (type) {
   case kNone:
         buf = enc.data;
         rc = enc.length;
         break;
   case kSafe:
         rc = krb5_rd_safe(fgContext, fAuthContext, &enc, &out, 0);
         break;
   case kPriv:
         rc = krb5_rd_priv(fgContext, fAuthContext, &enc, &out, 0);
         break;
   default:
         Error("BlockWrite","unknown encoding type (%d)", type);
         return -1;
   }

   if (type != kNone) {
      // copy data to buffer that is new'ed
      buf = new char[out.length+1];
      memcpy(buf, out.data,out.length);
      buf[out.length] = 0;
      free(out.data);
      delete enc.data;
      rc = out.length;
   }

   return rc;
}

Int_t TKSocket::BlockWrite(const char *buf, Int_t length, EEncoding type)
{
   TDesc desc;
   krb5_data in;
   krb5_data enc;
   Int_t rc;
   in.data = const_cast<char*>(buf);
   in.length = length;

   switch (type) {
   case kNone:
         enc.data = in.data;
         enc.length = in.length;
         break;
   case kSafe:
         rc = krb5_mk_safe(fgContext, fAuthContext, &in, &enc, 0);
         break;
   case kPriv:
         rc = krb5_mk_priv(fgContext, fAuthContext, &in, &enc, 0);
         break;
   default:
         Error("BlockWrite","unknown encoding type (%d)", type);
         return -1;
   }

   desc.length = htons(enc.length);
   desc.type = htons(type);

   Int_t fd = fSocket->GetDescriptor();
   rc = krb5_net_write(fgContext, fd, (char *)&desc, sizeof(desc));
   if (rc <= 0) {
      Error("BlockWrite","writing descriptor (%d), %s",
            rc, error_message(rc));
      return -1;
   }

   rc = krb5_net_write(fgContext, fd, (char *)enc.data, enc.length);
   if (rc <= 0) {
      Error("BlockWrite","writing data (%d), %s",
            rc, error_message(rc));
      return -1;
   }

   if (type != kNone) free(enc.data);

   return rc;
}
<|endoftext|>


<commit_before>/*
 * opencog/learning/moses/moses/select_bscore.cc
 *
 * Copyright (C) 2002-2008 Novamente LLC
 * Copyright (C) 2012,2013 Poulin Holdings LLC
 * Copyright (C) 2014 Aidyia Limited
 * All Rights Reserved
 *
 * Written by Moshe Looks, Nil Geisweiller, Linas Vepstas
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "select_bscore.h"

namespace opencog { namespace moses {

using namespace combo;

/**
 * Return the highest-weighted value (and its weight) in a given CTable row.
 *
 * CTable rows may have multiple, weighted output values. Several of
 * these output values may have the same weight, and only one of these
 * will be the largest. Find and return that.
 */
std::pair<double, double>
select_bscore::get_weightiest(const Counter<vertex, count_t>& orow) const
{
    score_t weightiest_val = very_worst_score;
    score_t weightiest = 0.0;
    for (const CTable::counter_t::value_type& tcv : orow) {
        score_t val = get_contin(tcv.first);
        if (not _positive) val = -val;
        // The weight for a given value is in tcv.second.
        // We look for weightiest, or, if tied, then for the
        // largest value. This gives a unique sort order, even
        // for randomly re-ordereed tables.
        if (weightiest < tcv.second or
            (weightiest == tcv.second and weightiest_val < val))
        {
            weightiest = tcv.second;
            weightiest_val = val;
        }
    }
    return std::pair<double, double>(weightiest_val, weightiest);
}

select_bscore::select_bscore(const CTable& ctable,
                             double lower_percentile,
                             double upper_percentile,
                             double hardness,
                             bool positive) :
    bscore_ctable_base(ctable), _positive(positive)
{
    OC_ASSERT(id::contin_type == _wrk_ctable.get_output_type(),
        "The selection scorer can only be used with contin-valued tables!");

    // Verify that the bounds are sane
    OC_ASSERT((0.0 <= lower_percentile) and
              (lower_percentile < 1.0) and
              (0.0 < upper_percentile) and
              (upper_percentile <= 1.0) and
              (0.0 <= hardness) and
              (hardness <= 1.0),
        "Selection scorer, invalid bounds.");

    // Maps are implicitly ordered, so the below has the effect of
    // putting the rows into sorted order, by output score.
    std::map<score_t, const CTable::value_type&> ranked_out;

    score_t total_weight = 0.0;
    for (const CTable::value_type& io_row : ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        ranked_out.insert(std::pair<score_t, const CTable::value_type&>(weightiest_val, io_row));
        total_weight += weightiest;
    }

    logger().info() << "select_bscore: lower_percentile = " << lower_percentile
                    << " upper percentile = " << upper_percentile
                    << " total wieght = " << total_weight;

    // Now, carve out the selected range.
    upper_percentile *= total_weight;
    lower_percentile *= total_weight;
    score_t running_weight = 0.0;
    bool found_lower = false;
    bool found_upper = false;
    for (auto score_row : ranked_out) {
        score_t weightiest_val = score_row.first;

        auto w = get_weightiest(score_row.second.second);
        score_t weightiest = w.second;
        running_weight += weightiest;

        if (not found_lower and lower_percentile < running_weight) {
            _lower_bound = weightiest_val;
            found_lower = true;
        }
        if (not found_upper and upper_percentile < running_weight) {
            _upper_bound = weightiest_val;
            found_upper = true;
        }
    }

    logger().info() << "select_bscore: lower_bound = " << _lower_bound
                    << " upper bound = " << _upper_bound;
}

behavioral_score select_bscore::operator()(const combo_tree& tr) const
{
    behavioral_score bs;

    interpreter_visitor iv(tr);
    auto interpret_tr = boost::apply_visitor(iv);

    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        if (interpret_tr(io_row.first.get_variant()) == id::logical_true) {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(weightiest);
            else
                bs.push_back(-weightiest);
        } else {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(-weightiest);
            else
                bs.push_back(weightiest);
        }
    }

    return bs;
}

behavioral_score select_bscore::operator()(const scored_combo_tree_set& ensemble) const
{
    // Step 1: accumulate the weighted prediction of each tree in
    // the ensemble.
    behavioral_score hypoth (_size);
    for (const scored_combo_tree& sct: ensemble) {
        const combo_tree& tr = sct.get_tree();
        score_t trweight = sct.get_weight();

        interpreter_visitor iv(tr);
        auto interpret_tr = boost::apply_visitor(iv);

        size_t i=0;
        for (const CTable::value_type& io_row : _wrk_ctable) {
            // io_row.first = input vector
            bool select = (interpret_tr(io_row.first.get_variant()) == id::logical_true);
            hypoth[i] += trweight * (2.0 * ((score_t) select) - 1.0);
            i++;
        }
    }

    // Step 2: compare the prediction of the ensemble to the desired
    // result. The array "hypoth" is positive to predict true, and
    // negative to predict false.  The resulting score is 0 if corrrect,
    // and -1 if incorrect.
    behavioral_score bs;
    size_t i = 0;
    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        if (0 < hypoth[i]) {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(weightiest);
            else
                bs.push_back(-weightiest);
        } else {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(-weightiest);
            else
                bs.push_back(weightiest);
        }
        i++;
    }

    return bs;
}

behavioral_score select_bscore::best_possible_bscore() const
{
    behavioral_score bs;

    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest = w.second;

        bs.push_back(weightiest);
    }
    return bs;
}

score_t select_bscore::min_improv() const
{
    return 1.0 / _ctable_usize;
}

} // ~namespace moses
} // ~namespace opencog
<commit_msg>Added documentation<commit_after>/*
 * opencog/learning/moses/moses/select_bscore.cc
 *
 * Copyright (C) 2002-2008 Novamente LLC
 * Copyright (C) 2012,2013 Poulin Holdings LLC
 * Copyright (C) 2014 Aidyia Limited
 * All Rights Reserved
 *
 * Written by Moshe Looks, Nil Geisweiller, Linas Vepstas
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "select_bscore.h"

namespace opencog { namespace moses {

using namespace combo;

/**
 * Return the highest-weighted value (and its weight) in a given CTable row.
 *
 * CTable rows may have multiple, weighted output values. Several of
 * these output values may have the same weight, and only one of these
 * will be the largest. Find and return that.
 */
std::pair<double, double>
select_bscore::get_weightiest(const Counter<vertex, count_t>& orow) const
{
    score_t weightiest_val = very_worst_score;
    score_t weightiest = 0.0;
    for (const CTable::counter_t::value_type& tcv : orow) {
        score_t val = get_contin(tcv.first);
        if (not _positive) val = -val;
        // The weight for a given value is in tcv.second.
        // We look for weightiest, or, if tied, then for the
        // largest value. This gives a unique sort order, even
        // for randomly re-ordereed tables.
        if (weightiest < tcv.second or
            (weightiest == tcv.second and weightiest_val < val))
        {
            weightiest = tcv.second;
            weightiest_val = val;
        }
    }
    return std::pair<double, double>(weightiest_val, weightiest);
}

/**
 * The selection scorer will learn a window that selects a target range
 * of values in a continuous-valued dataset.
 *
 * The dataset is assumed to have a contin-valued output column. The
 * highest and lowest values are found in the output column, and the
 * window is then framed relative to these two boundaries.  That is,
 * if 'low_val' and 'hi_val' are the smallest and largest values in the
 * table, then the bottom of the selected window is located at
 *
 *    window_bottom = low_val + lower_percentile * (hi_val - low_val)
 *
 * and the top is located at
 *
 *    window_top = low_val + upper_percentile * (hi_val - low_val)
 *
 * If the rows are weighted, then the weighted equivalent of the above
 * boundaries is used.
 */
select_bscore::select_bscore(const CTable& ctable,
                             double lower_percentile,
                             double upper_percentile,
                             double hardness,
                             bool positive) :
    bscore_ctable_base(ctable), _positive(positive)
{
    OC_ASSERT(id::contin_type == _wrk_ctable.get_output_type(),
        "The selection scorer can only be used with contin-valued tables!");

    // Verify that the bounds are sane
    OC_ASSERT((0.0 <= lower_percentile) and
              (lower_percentile < 1.0) and
              (0.0 < upper_percentile) and
              (upper_percentile <= 1.0) and
              (0.0 <= hardness) and
              (hardness <= 1.0),
        "Selection scorer, invalid bounds.");

    // Maps are implicitly ordered, so the below has the effect of
    // putting the rows into sorted order, by output score.
    std::map<score_t, const CTable::value_type&> ranked_out;

    score_t total_weight = 0.0;
    for (const CTable::value_type& io_row : ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        ranked_out.insert(std::pair<score_t, const CTable::value_type&>(weightiest_val, io_row));
        total_weight += weightiest;
    }

    logger().info() << "select_bscore: lower_percentile = " << lower_percentile
                    << " upper percentile = " << upper_percentile
                    << " total wieght = " << total_weight;

    // Now, carve out the selected range.
    upper_percentile *= total_weight;
    lower_percentile *= total_weight;
    score_t running_weight = 0.0;
    bool found_lower = false;
    bool found_upper = false;
    for (auto score_row : ranked_out) {
        score_t weightiest_val = score_row.first;

        auto w = get_weightiest(score_row.second.second);
        score_t weightiest = w.second;
        running_weight += weightiest;

        if (not found_lower and lower_percentile < running_weight) {
            _lower_bound = weightiest_val;
            found_lower = true;
        }
        if (not found_upper and upper_percentile < running_weight) {
            _upper_bound = weightiest_val;
            found_upper = true;
        }
    }

    logger().info() << "select_bscore: lower_bound = " << _lower_bound
                    << " upper bound = " << _upper_bound;
}

/// scorer, as described in the constructor, above.
behavioral_score select_bscore::operator()(const combo_tree& tr) const
{
    behavioral_score bs;

    interpreter_visitor iv(tr);
    auto interpret_tr = boost::apply_visitor(iv);

    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        if (interpret_tr(io_row.first.get_variant()) == id::logical_true) {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(weightiest);
            else
                bs.push_back(-weightiest);
        } else {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(-weightiest);
            else
                bs.push_back(weightiest);
        }
    }

    return bs;
}

/// scorer, suitable for use with boosting.
behavioral_score select_bscore::operator()(const scored_combo_tree_set& ensemble) const
{
    // Step 1: accumulate the weighted prediction of each tree in
    // the ensemble.
    behavioral_score hypoth (_size);
    for (const scored_combo_tree& sct: ensemble) {
        const combo_tree& tr = sct.get_tree();
        score_t trweight = sct.get_weight();

        interpreter_visitor iv(tr);
        auto interpret_tr = boost::apply_visitor(iv);

        size_t i=0;
        for (const CTable::value_type& io_row : _wrk_ctable) {
            // io_row.first = input vector
            bool select = (interpret_tr(io_row.first.get_variant()) == id::logical_true);
            hypoth[i] += trweight * (2.0 * ((score_t) select) - 1.0);
            i++;
        }
    }

    // Step 2: compare the prediction of the ensemble to the desired
    // result. The array "hypoth" is positive to predict true, and
    // negative to predict false.  The resulting score is 0 if corrrect,
    // and -1 if incorrect.
    behavioral_score bs;
    size_t i = 0;
    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest_val = w.first;
        score_t weightiest = w.second;

        if (0 < hypoth[i]) {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(weightiest);
            else
                bs.push_back(-weightiest);
        } else {
            if (_lower_bound <= weightiest_val and weightiest_val <= _upper_bound)
                bs.push_back(-weightiest);
            else
                bs.push_back(weightiest);
        }
        i++;
    }

    return bs;
}

behavioral_score select_bscore::best_possible_bscore() const
{
    behavioral_score bs;

    for (const CTable::value_type& io_row : _wrk_ctable) {
        // io_row.first = input vector
        // io_row.second = counter of outputs
        auto w = get_weightiest(io_row.second);
        score_t weightiest = w.second;

        bs.push_back(weightiest);
    }
    return bs;
}

score_t select_bscore::min_improv() const
{
    return 1.0 / _ctable_usize;
}

} // ~namespace moses
} // ~namespace opencog
<|endoftext|>