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

/**
 * @file
 *  This file defines OpenThread Notifier class.
 */

#ifndef NOTIFIER_HPP_
#define NOTIFIER_HPP_

#include "openthread-core-config.h"

#include "utils/wrap_stdbool.h"
#include "utils/wrap_stdint.h"

#include <openthread/instance.h>
#include <openthread/platform/toolchain.h>

#include "common/locator.hpp"
#include "common/tasklet.hpp"

namespace ot {

/**
 * @addtogroup core-notifier
 *
 * @brief
 *   This module includes definitions for OpenThread Notifier class.
 *
 * @{
 *
 */

/**
 * This class implements the OpenThread Notifier.
 *
 * It can be used to register callbacks to be notified of state or configuration changes within OpenThread.
 *
 */
class Notifier : public InstanceLocator
{
public:
    /**
     * This class defines a callback instance that can be registered with the `Notifier`.
     *
     */
    class Callback : public OwnerLocator
    {
        friend class Notifier;

    public:
        /**
         * This type defines the function pointer which is called to notify of state or configuration changes.
         *
         * @param[in] aCallback    A reference to callback instance.
         * @param[in] aFlags       A bit-field indicating specific state or configuration that has changed.
         *
         */
        typedef void (*Handler)(Callback &aCallback, otChangedFlags aFlags);

        /**
         * This constructor initializes a `Callback` instance
         *
         * @param[in] aInstance   A reference to OpenThread instance.
         * @param[in] aHandler    A function pointer to the callback handler.
         * @param[in] aOwner      A pointer to the owner of the `Callback` instance.
         *
         */
        Callback(Instance &aInstance, Handler aHandler, void *aOwner);

    private:
        void Invoke(otChangedFlags aFlags) { mHandler(*this, aFlags); }

        Handler   mHandler;
        Callback *mNext;
    };

    /**
     * This constructor initializes a `Notifier` instance.
     *
     *  @param[in] aInstance     A reference to OpenThread instance.
     *
     */
    explicit Notifier(Instance &aInstance);

    /**
     * This method registers an `otStateChangedCallback` handler.
     *
     * @param[in]  aCallback     A pointer to the handler function that is called to notify of the changes.
     * @param[in]  aContext      A pointer to arbitrary context information.
     *
     * @retval OT_ERROR_NONE     Successfully registered the callback.
     * @retval OT_ERROR_ALREADY  The callback was already registered.
     * @retval OT_ERROR_NO_BUFS  Could not add the callback due to resource constraints.
     *
     */
    otError RegisterCallback(otStateChangedCallback aCallback, void *aContext);

    /**
     * This method removes/unregisters a previously registered `otStateChangedCallback` handler.
     *
     * @param[in]  aCallback     A pointer to the callback function pointer.
     * @param[in]  aContex       A pointer to arbitrary context information.
     *
     */
    void RemoveCallback(otStateChangedCallback aCallback, void *aContext);

    /**
     * This method schedules signaling of changed flags.
     *
     * @param[in]  aFlags       A bit-field indicating what configuration or state has changed.
     *
     */
    void Signal(otChangedFlags aFlags);

    /**
     * This method schedules signaling of changed flags only if the set of flags has not been signaled before (first
     * time signal).
     *
     * @param[in]  aFlags       A bit-field indicating what configuration or state has changed.
     *
     */
    void SignalIfFirst(otChangedFlags aFlags);

    /**
     * This method indicates whether or not a changed callback is pending.
     *
     * @returns TRUE if a state changed callback is pending, FALSE otherwise.
     *
     */
    bool IsPending(void) const { return (mFlagsToSignal != 0); }

    /**
     * This method indicates whether or not a changed notification for a given set of flags has been signaled before.
     *
     * @param[in]  aFlags   A bit-field containing the flag-bits to check.
     *
     * @retval TRUE    All flag bits in @p aFlags have been signaled before.
     * @retval FALSE   At least one flag bit in @p aFlags has not been signaled before.
     *
     */
    bool HasSignaled(otChangedFlags aFlags) const { return (mSignaledFlags & aFlags) == aFlags; }

private:
    enum
    {
        kMaxExternalHandlers   = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS,
        kFlagsStringLineLimit  = 70, // Character limit to divide the log into multiple lines in `LogChangedFlags()`.
        kMaxFlagNameLength     = 25, // Max length for string representation of a flag by `FlagToString()`.
        kFlagsStringBufferSize = kFlagsStringLineLimit + kMaxFlagNameLength,
    };

    struct ExternalCallback
    {
        otStateChangedCallback mHandler;
        void *                 mContext;
    };

    void        RegisterCallback(Callback &aCallback);
    static void HandleStateChanged(Tasklet &aTasklet);
    void        HandleStateChanged(void);

    void        LogChangedFlags(otChangedFlags aFlags) const;
    const char *FlagToString(otChangedFlags aFlag) const;

    otChangedFlags   mFlagsToSignal;
    otChangedFlags   mSignaledFlags;
    Tasklet          mTask;
    Callback *       mCallbacks;
    ExternalCallback mExternalCallbacks[kMaxExternalHandlers];
};

/**
 * @}
 *
 */

} // namespace ot

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

/**
 * @file
 *  This file defines OpenThread Notifier class.
 */

#ifndef NOTIFIER_HPP_
#define NOTIFIER_HPP_

#include "openthread-core-config.h"

#include "utils/wrap_stdbool.h"
#include "utils/wrap_stdint.h"

#include <openthread/instance.h>
#include <openthread/platform/toolchain.h>

#include "common/locator.hpp"
#include "common/tasklet.hpp"

namespace ot {

/**
 * @addtogroup core-notifier
 *
 * @brief
 *   This module includes definitions for OpenThread Notifier class.
 *
 * @{
 *
 */

/**
 * This class implements the OpenThread Notifier.
 *
 * It can be used to register callbacks that notify of state or configuration changes within OpenThread.
 *
 * Two callback models are provided:
 *
 * - A `Notifier::Callback` object that upon initialization (from its constructor) auto-registers itself with
 *   the `Notifier`. This model is mainly used by OpenThread core modules.
 *
 * - A `otStateChangedCallback` callback handler which needs to be explicitly registered with the `Notifier`. This is
 *   commonly used by external users (provided as an OpenThread public API). Max number of such callbacks that can be
 *   registered at the same time is specified by `OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS` configuration parameter.
 *
 */
class Notifier : public InstanceLocator
{
public:
    /**
     * This class defines a `Notifier` callback instance.
     *
     */
    class Callback : public OwnerLocator
    {
        friend class Notifier;

    public:
        /**
         * This type defines the function pointer which is called to notify of state or configuration changes.
         *
         * @param[in] aCallback    A reference to callback instance.
         * @param[in] aFlags       A bit-field indicating specific state or configuration that has changed.
         *
         */
        typedef void (*Handler)(Callback &aCallback, otChangedFlags aFlags);

        /**
         * This constructor initializes a `Callback` instance and registers it with `Notifier`.
         *
         * @param[in] aInstance   A reference to OpenThread instance.
         * @param[in] aHandler    A function pointer to the callback handler.
         * @param[in] aOwner      A pointer to the owner of the `Callback` instance.
         *
         */
        Callback(Instance &aInstance, Handler aHandler, void *aOwner);

    private:
        void Invoke(otChangedFlags aFlags) { mHandler(*this, aFlags); }

        Handler   mHandler;
        Callback *mNext;
    };

    /**
     * This constructor initializes a `Notifier` instance.
     *
     *  @param[in] aInstance     A reference to OpenThread instance.
     *
     */
    explicit Notifier(Instance &aInstance);

    /**
     * This method registers an `otStateChangedCallback` handler.
     *
     * @param[in]  aCallback     A pointer to the handler function that is called to notify of the changes.
     * @param[in]  aContext      A pointer to arbitrary context information.
     *
     * @retval OT_ERROR_NONE     Successfully registered the callback.
     * @retval OT_ERROR_ALREADY  The callback was already registered.
     * @retval OT_ERROR_NO_BUFS  Could not add the callback due to resource constraints.
     *
     */
    otError RegisterCallback(otStateChangedCallback aCallback, void *aContext);

    /**
     * This method removes/unregisters a previously registered `otStateChangedCallback` handler.
     *
     * @param[in]  aCallback     A pointer to the callback function pointer.
     * @param[in]  aContex       A pointer to arbitrary context information.
     *
     */
    void RemoveCallback(otStateChangedCallback aCallback, void *aContext);

    /**
     * This method schedules signaling of changed flags.
     *
     * @param[in]  aFlags       A bit-field indicating what configuration or state has changed.
     *
     */
    void Signal(otChangedFlags aFlags);

    /**
     * This method schedules signaling of changed flags only if the set of flags has not been signaled before (first
     * time signal).
     *
     * @param[in]  aFlags       A bit-field indicating what configuration or state has changed.
     *
     */
    void SignalIfFirst(otChangedFlags aFlags);

    /**
     * This method indicates whether or not a changed callback is pending.
     *
     * @returns TRUE if a state changed callback is pending, FALSE otherwise.
     *
     */
    bool IsPending(void) const { return (mFlagsToSignal != 0); }

    /**
     * This method indicates whether or not a changed notification for a given set of flags has been signaled before.
     *
     * @param[in]  aFlags   A bit-field containing the flag-bits to check.
     *
     * @retval TRUE    All flag bits in @p aFlags have been signaled before.
     * @retval FALSE   At least one flag bit in @p aFlags has not been signaled before.
     *
     */
    bool HasSignaled(otChangedFlags aFlags) const { return (mSignaledFlags & aFlags) == aFlags; }

private:
    enum
    {
        kMaxExternalHandlers   = OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS,
        kFlagsStringLineLimit  = 70, // Character limit to divide the log into multiple lines in `LogChangedFlags()`.
        kMaxFlagNameLength     = 25, // Max length for string representation of a flag by `FlagToString()`.
        kFlagsStringBufferSize = kFlagsStringLineLimit + kMaxFlagNameLength,
    };

    struct ExternalCallback
    {
        otStateChangedCallback mHandler;
        void *                 mContext;
    };

    void        RegisterCallback(Callback &aCallback);
    static void HandleStateChanged(Tasklet &aTasklet);
    void        HandleStateChanged(void);

    void        LogChangedFlags(otChangedFlags aFlags) const;
    const char *FlagToString(otChangedFlags aFlag) const;

    otChangedFlags   mFlagsToSignal;
    otChangedFlags   mSignaledFlags;
    Tasklet          mTask;
    Callback *       mCallbacks;
    ExternalCallback mExternalCallbacks[kMaxExternalHandlers];
};

/**
 * @}
 *
 */

} // namespace ot

#endif // NOTIFIER_HPP_
<|endoftext|>


<commit_before>/*
    This file is part of Zanshin Todo.

    Copyright (C) 2012  Christian Mollekopf <chrigi_1@fastmail.fm>

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "globaldefs.h"
#include "core/projectstrategy.h"
#include "core/incidenceitem.h"
#include "core/pimitemmodel.h"
#include "core/pimitemservices.h"
#include "reparentingmodel/todonode.h"
#include "reparentingmodel/reparentingmodel.h"
#include "todohelpers.h"
#include <KLocalizedString>
#include <KIcon>
#include <QMimeData>
#include <Akonadi/ItemModifyJob>
#include <Akonadi/ItemFetchJob>
#include <Akonadi/ItemFetchScope>
#include <KUrl>

ProjectStrategy::ProjectStrategy(ProjectStructureCache *structure)
:   ReparentingStrategy(),
    mInbox(1),
    mRelations(structure)
{
    PimItemServices::projectInstance().setRelationsStructure(mRelations.data());
    mReparentOnRemoval = false;
    connect(mRelations.data(), SIGNAL(nodeRemoved(Id)), this, SLOT(doRemoveNode(Id)));
    connect(mRelations.data(), SIGNAL(parentsChanged(Id,IdList)), this, SLOT(doChangeParents(Id, IdList)));
}

void ProjectStrategy::init()
{
    ReparentingStrategy::init();
    //FIXME we should be setting this earlier, here the inserted signals have already been emitted

    QList<TodoNode*> nodes = createNode(mInbox, IdList(), "Inbox");
    Q_ASSERT(nodes.size() == 1);
    TodoNode *node = nodes.first();
    node->setData(i18n("Inbox"), 0, Qt::DisplayRole);
    node->setData(KIcon("mail-folder-inbox"), 0, Qt::DecorationRole);
    node->setRowData(Zanshin::Inbox, Zanshin::ItemTypeRole);
}

static Id translateFrom(Id id)
{
    //TODO proper id mapping
    return id+10;
}

static Id translateTo(Id id)
{
    //TODO proper id mapping
    return id-10;
}

static IdList translateFrom(IdList l)
{
    IdList list;
    foreach (Id id, l) {
        list << translateFrom(id);
    }
    return list;
}

void ProjectStrategy::doRemoveNode(Id id)
{
    kDebug() << id;
    //FIXME
//     ReparentingStrategy::removeNode(translateFrom(id));
}

void ProjectStrategy::doChangeParents(Id id, IdList parents)
{
    IdList p;
    if (parents.isEmpty()) {
        bool isProject = mRelations->hasChildren(id);
        if (isProject) {
            const Akonadi::Collection col = getParentCollection(translateFrom(id));
            if (col.isValid()) {
                p << translateFrom(mRelations->addCollection(col));
            }
        } else {
            p << mInbox;
        }
    } else {
        p << translateFrom(parents);
    }
    ReparentingStrategy::updateParents(translateFrom(id), p);
}

Id ProjectStrategy::getId(const QModelIndex &sourceChildIndex)
{
    Zanshin::ItemType type = (Zanshin::ItemType) sourceChildIndex.data(Zanshin::ItemTypeRole).toInt();
    if (type==Zanshin::Collection) {
        return translateFrom(mRelations->addCollection(sourceChildIndex.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>()));
    }
//     kDebug() << sourceChildIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>().url() << sourceChildIndex << type;
    const Akonadi::Item &item = sourceChildIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
    Q_ASSERT(item.isValid());
    Id id = mRelations->addItem(item);
    if (id < 0) {
        return -1;
    }
    return translateFrom(id);
}

bool ProjectStrategy::isProject(Id id, Zanshin::ItemType itemType) const
{
    if (itemType == Zanshin::ProjectTodo
    || ((itemType == Zanshin::StandardTodo) && mRelations->hasChildren(translateTo(id)))) {
        return true;
    }
    return false;
}

IdList ProjectStrategy::getParents(const QModelIndex &sourceChildIndex, const IdList &ignore)
{
    Q_ASSERT(sourceChildIndex.isValid());
//     kDebug() << sourceChildIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>().url();
//     kDebug() << sourceChildIndex.data().toString();
//     mRelations->printCache();
    IdList parents;
    Zanshin::ItemType type = (Zanshin::ItemType) sourceChildIndex.data(Zanshin::ItemTypeRole).toInt();
    if (type==Zanshin::Collection) {
        const QModelIndex &parent = sourceChildIndex.parent();
        if (parent.isValid()) {
            return IdList() << getId(parent);
        }
        return IdList();
    }

    const Akonadi::Item &item = sourceChildIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
    Id id = mRelations->getItemId(item);
    parents = translateFrom(mRelations->getParents(id));
    bool isNote = (sourceChildIndex.data(PimItemModel::ItemTypeRole).toInt() == PimItem::Note);
    if (parents.isEmpty() || isNote) {
        if (!isProject(translateFrom(id), type) && !isNote) {
            return IdList() << mInbox;
        }
        const QModelIndex &parent = sourceChildIndex.parent();
        if (parent.isValid()) {
            parents << getId(parent);
        }
    }
    Q_ASSERT(!parents.contains(translateFrom(id)));

    foreach(Id i, ignore) {
        parents.removeAll(i);
    }
//     kDebug() << id << parents;
    checkParents(parents);
    return parents;
}

void ProjectStrategy::onNodeRemoval(const Id& changed)
{
    IdList parents = translateFrom(mRelations->getParents(translateTo(changed)));
//     kDebug() << changed << parents;
    mRelations->removeNode(translateTo(changed));
    checkParents(parents);
}

void ProjectStrategy::checkParents(const IdList &parentsToCheck)
{
    foreach(Id id, parentsToCheck) {
        //Because we may have just removed a project
        ReparentingStrategy::updateParents(id);
    }
}

void ProjectStrategy::reset()
{
    ReparentingStrategy::reset();
}

Qt::ItemFlags ProjectStrategy::flags(const QModelIndex& index, Qt::ItemFlags existingFlags)
{
    Zanshin::ItemType type = (Zanshin::ItemType)index.data(Zanshin::ItemTypeRole).toInt();

    if (type == Zanshin::Inbox) {
        return Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
    }

    Akonadi::Collection collection;
    if (type==Zanshin::Collection) {
        collection = index.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
    } else if (type == Zanshin::ProjectTodo) { //isProject(getId(index), type) FIXME for some reason the item is invalid in getid
        // We use ParentCollectionRole instead of Akonadi::Item::parentCollection() because the
        // information about the rights is not valid on retrieved items.
        collection = index.data(Akonadi::EntityTreeModel::ParentCollectionRole).value<Akonadi::Collection>();
    }

    if (!(collection.rights() & Akonadi::Collection::CanCreateItem)) {
        existingFlags &= ~Qt::ItemIsDropEnabled;
    } else {
        existingFlags |= Qt::ItemIsDropEnabled;
    }

    return existingFlags;
}

Qt::DropActions ProjectStrategy::supportedDropActions() const
{
    return Qt::MoveAction/*|Qt::LinkAction*/;
}

bool ProjectStrategy::onDropMimeData(Id id, const QMimeData* mimeData, Qt::DropAction action)
{
    if (action != Qt::MoveAction || !KUrl::List::canDecode(mimeData)) {
        return false;
    }

    KUrl::List urls = KUrl::List::fromMimeData(mimeData);

    Akonadi::Collection collection;
    bool forward;
    Zanshin::ItemType parentType = (Zanshin::ItemType)data(id, 0, Zanshin::ItemTypeRole, forward).toInt();
    if (parentType == Zanshin::Collection) {
        collection = getData(id, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
    } else {
        const Akonadi::Item parentItem = getData(id, Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
        collection = parentItem.parentCollection();
    }

    QString parentUid = getData(id, Zanshin::UidRole).toString();

    foreach (const KUrl &url, urls) {
        const Akonadi::Item urlItem = Akonadi::Item::fromUrl(url);
        //TODO make sure we never get here during testing (although we normally shouldn't anyways
        if (urlItem.isValid()) {
            //TODO replace by getData/setData?
            Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob(urlItem);
            job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent);
            job->fetchScope().fetchFullPayload();
            if ( !job->exec() ) {
                continue;
            }
            Q_ASSERT(job->items().size()==1);
            Akonadi::Item item = job->items().first();
            Q_ASSERT(item.isValid());
            if (PimItem::itemType(item) == PimItem::Todo) {
                return TodoHelpers::moveTodoToProject(item, parentUid, parentType, collection);
            } else if (PimItem::itemType(item) == PimItem::Note) {
                TodoHelpers::moveToProject(item, parentUid);
                setData(id, QVariant::fromValue<Akonadi::Item>(item), Akonadi::EntityTreeModel::ItemRole);
                return true;
            }
        }
    }

    return false;
}

QVariant ProjectStrategy::data(Id id, int column, int role, bool &forward) const
{
    //We simply override the todometadatamodel data for todos with children (which are also projects)
    const Zanshin::ItemType itemType = static_cast<Zanshin::ItemType>(getData(id, Zanshin::ItemTypeRole).toInt());
    bool project = isProject(id, itemType);

    switch (role) {
        case Zanshin::ItemTypeRole: {
            if (id == mInbox) {
                return Zanshin::Inbox;
            }
            if (project) {
                return Zanshin::ProjectTodo;
            }
            return itemType;
        }
        case Qt::CheckStateRole:
            if (project) {
                forward = false;
                return QVariant();
            }
            break;
        case Qt::DecorationRole:
            if (project && !column) {
                return KIcon("view-pim-tasks");
            }
            break;
    }
    return QVariant();
}
<commit_msg>Use PimItemServices instead of Todohelpers<commit_after>/*
    This file is part of Zanshin Todo.

    Copyright (C) 2012  Christian Mollekopf <chrigi_1@fastmail.fm>

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "globaldefs.h"
#include "core/projectstrategy.h"
#include "core/incidenceitem.h"
#include "core/pimitemmodel.h"
#include "core/pimitemservices.h"
#include "reparentingmodel/todonode.h"
#include "reparentingmodel/reparentingmodel.h"
#include "todohelpers.h"
#include <KLocalizedString>
#include <KIcon>
#include <QMimeData>
#include <Akonadi/ItemModifyJob>
#include <Akonadi/ItemFetchJob>
#include <Akonadi/ItemFetchScope>
#include <KUrl>

ProjectStrategy::ProjectStrategy(ProjectStructureCache *structure)
:   ReparentingStrategy(),
    mInbox(1),
    mRelations(structure)
{
    PimItemServices::projectInstance().setRelationsStructure(mRelations.data());
    mReparentOnRemoval = false;
    connect(mRelations.data(), SIGNAL(nodeRemoved(Id)), this, SLOT(doRemoveNode(Id)));
    connect(mRelations.data(), SIGNAL(parentsChanged(Id,IdList)), this, SLOT(doChangeParents(Id, IdList)));
}

void ProjectStrategy::init()
{
    ReparentingStrategy::init();
    //FIXME we should be setting this earlier, here the inserted signals have already been emitted

    QList<TodoNode*> nodes = createNode(mInbox, IdList(), "Inbox");
    Q_ASSERT(nodes.size() == 1);
    TodoNode *node = nodes.first();
    node->setData(i18n("Inbox"), 0, Qt::DisplayRole);
    node->setData(KIcon("mail-folder-inbox"), 0, Qt::DecorationRole);
    node->setRowData(Zanshin::Inbox, Zanshin::ItemTypeRole);
}

static Id translateFrom(Id id)
{
    //TODO proper id mapping
    return id+10;
}

static Id translateTo(Id id)
{
    //TODO proper id mapping
    return id-10;
}

static IdList translateFrom(IdList l)
{
    IdList list;
    foreach (Id id, l) {
        list << translateFrom(id);
    }
    return list;
}

void ProjectStrategy::doRemoveNode(Id id)
{
    kDebug() << id;
    //FIXME
//     ReparentingStrategy::removeNode(translateFrom(id));
}

void ProjectStrategy::doChangeParents(Id id, IdList parents)
{
    IdList p;
    if (parents.isEmpty()) {
        bool isProject = mRelations->hasChildren(id);
        if (isProject) {
            const Akonadi::Collection col = getParentCollection(translateFrom(id));
            if (col.isValid()) {
                p << translateFrom(mRelations->addCollection(col));
            }
        } else {
            p << mInbox;
        }
    } else {
        p << translateFrom(parents);
    }
    ReparentingStrategy::updateParents(translateFrom(id), p);
}

Id ProjectStrategy::getId(const QModelIndex &sourceChildIndex)
{
    Zanshin::ItemType type = (Zanshin::ItemType) sourceChildIndex.data(Zanshin::ItemTypeRole).toInt();
    if (type==Zanshin::Collection) {
        return translateFrom(mRelations->addCollection(sourceChildIndex.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>()));
    }
//     kDebug() << sourceChildIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>().url() << sourceChildIndex << type;
    const Akonadi::Item &item = sourceChildIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
    Q_ASSERT(item.isValid());
    Id id = mRelations->addItem(item);
    if (id < 0) {
        return -1;
    }
    return translateFrom(id);
}

bool ProjectStrategy::isProject(Id id, Zanshin::ItemType itemType) const
{
    if (itemType == Zanshin::ProjectTodo
    || ((itemType == Zanshin::StandardTodo) && mRelations->hasChildren(translateTo(id)))) {
        return true;
    }
    return false;
}

IdList ProjectStrategy::getParents(const QModelIndex &sourceChildIndex, const IdList &ignore)
{
    Q_ASSERT(sourceChildIndex.isValid());
//     kDebug() << sourceChildIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>().url();
//     kDebug() << sourceChildIndex.data().toString();
//     mRelations->printCache();
    IdList parents;
    Zanshin::ItemType type = (Zanshin::ItemType) sourceChildIndex.data(Zanshin::ItemTypeRole).toInt();
    if (type==Zanshin::Collection) {
        const QModelIndex &parent = sourceChildIndex.parent();
        if (parent.isValid()) {
            return IdList() << getId(parent);
        }
        return IdList();
    }

    const Akonadi::Item &item = sourceChildIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
    Id id = mRelations->getItemId(item);
    parents = translateFrom(mRelations->getParents(id));
    bool isNote = (sourceChildIndex.data(PimItemModel::ItemTypeRole).toInt() == PimItem::Note);
    if (parents.isEmpty() || isNote) {
        if (!isProject(translateFrom(id), type) && !isNote) {
            return IdList() << mInbox;
        }
        const QModelIndex &parent = sourceChildIndex.parent();
        if (parent.isValid()) {
            parents << getId(parent);
        }
    }
    Q_ASSERT(!parents.contains(translateFrom(id)));

    foreach(Id i, ignore) {
        parents.removeAll(i);
    }
//     kDebug() << id << parents;
    checkParents(parents);
    return parents;
}

void ProjectStrategy::onNodeRemoval(const Id& changed)
{
    IdList parents = translateFrom(mRelations->getParents(translateTo(changed)));
//     kDebug() << changed << parents;
    mRelations->removeNode(translateTo(changed));
    checkParents(parents);
}

void ProjectStrategy::checkParents(const IdList &parentsToCheck)
{
    foreach(Id id, parentsToCheck) {
        //Because we may have just removed a project
        ReparentingStrategy::updateParents(id);
    }
}

void ProjectStrategy::reset()
{
    ReparentingStrategy::reset();
}

Qt::ItemFlags ProjectStrategy::flags(const QModelIndex& index, Qt::ItemFlags existingFlags)
{
    Zanshin::ItemType type = (Zanshin::ItemType)index.data(Zanshin::ItemTypeRole).toInt();

    if (type == Zanshin::Inbox) {
        return Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled;
    }

    Akonadi::Collection collection;
    if (type==Zanshin::Collection) {
        collection = index.data(Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
    } else if (type == Zanshin::ProjectTodo) { //isProject(getId(index), type) FIXME for some reason the item is invalid in getid
        // We use ParentCollectionRole instead of Akonadi::Item::parentCollection() because the
        // information about the rights is not valid on retrieved items.
        collection = index.data(Akonadi::EntityTreeModel::ParentCollectionRole).value<Akonadi::Collection>();
    }

    if (!(collection.rights() & Akonadi::Collection::CanCreateItem)) {
        existingFlags &= ~Qt::ItemIsDropEnabled;
    } else {
        existingFlags |= Qt::ItemIsDropEnabled;
    }

    return existingFlags;
}

Qt::DropActions ProjectStrategy::supportedDropActions() const
{
    return Qt::MoveAction/*|Qt::LinkAction*/;
}

bool ProjectStrategy::onDropMimeData(Id id, const QMimeData* mimeData, Qt::DropAction action)
{
    if (action != Qt::MoveAction || !KUrl::List::canDecode(mimeData)) {
        return false;
    }

    KUrl::List urls = KUrl::List::fromMimeData(mimeData);

    PimNode parentNode(PimNode::Invalid);
    bool forward;
    Zanshin::ItemType parentType = (Zanshin::ItemType)data(id, 0, Zanshin::ItemTypeRole, forward).toInt();
    if (parentType == Zanshin::Collection) {
        parentNode.collection = getData(id, Akonadi::EntityTreeModel::CollectionRole).value<Akonadi::Collection>();
        parentNode.type = PimNode::Collection;
    } else {
        parentNode.item = getData(id, Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
        parentNode.collection = parentNode.item.parentCollection();
        parentNode.type = PimNode::Project;
        parentNode.uid = getData(id, Zanshin::UidRole).toString();
    }

    foreach (const KUrl &url, urls) {
        const Akonadi::Item urlItem = Akonadi::Item::fromUrl(url);
        //TODO make sure we never get here during testing (although we normally shouldn't anyways
        if (urlItem.isValid()) {
            //TODO replace by getData/setData?
            Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob(urlItem);
            job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent);
            job->fetchScope().fetchFullPayload();
            if ( !job->exec() ) {
                continue;
            }
            Q_ASSERT(job->items().size()==1);
            Akonadi::Item item = job->items().first();
            Q_ASSERT(item.isValid());

            PimNode node(PimNode::Invalid);
            if (PimItem::itemType(item) == PimItem::Todo) {
                node.type = PimNode::Todo;
            } else {
                node.type = PimNode::Note;
            }
            node.item = item;

            PimItemServices::moveTo(node, parentNode);
            return true;
        }
    }

    return false;
}

QVariant ProjectStrategy::data(Id id, int column, int role, bool &forward) const
{
    //We simply override the todometadatamodel data for todos with children (which are also projects)
    const Zanshin::ItemType itemType = static_cast<Zanshin::ItemType>(getData(id, Zanshin::ItemTypeRole).toInt());
    bool project = isProject(id, itemType);

    switch (role) {
        case Zanshin::ItemTypeRole: {
            if (id == mInbox) {
                return Zanshin::Inbox;
            }
            if (project) {
                return Zanshin::ProjectTodo;
            }
            return itemType;
        }
        case Qt::CheckStateRole:
            if (project) {
                forward = false;
                return QVariant();
            }
            break;
        case Qt::DecorationRole:
            if (project && !column) {
                return KIcon("view-pim-tasks");
            }
            break;
    }
    return QVariant();
}
<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/util/logcentral.h>
#include <inviwo/core/util/stacktrace.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/processors/processor.h>
#include <inviwo/core/network/processornetwork.h>

namespace inviwo {

void Logger::logProcessor(Processor* processor, LogLevel level, LogAudience audience,
                          std::string msg, const char* file, const char* function, int line) {
    log("Processor " + processor->getIdentifier(), level, audience, file, function, line, msg);
}

void Logger::logNetwork(LogLevel level, LogAudience audience, std::string msg, const char* file,
                        const char* function, int line) {
    log("ProcessorNetwork", level, audience, file, function, line, msg);
}

void Logger::logAssertion(const char* fileName, const char* functionName, long lineNumber,
                          std::string message) {
    log("Assertion failed", LogLevel::Error, LogAudience::Developer, fileName, functionName,
        lineNumber, message);
}

LogCentral::LogCentral() : logLevel_(LogLevel::Info), logStacktrace_(false) {}

void LogCentral::registerLogger(std::weak_ptr<Logger> logger) { loggers_.push_back(logger); }

void LogCentral::log(std::string source, LogLevel level, LogAudience audience, const char* file,
                     const char* function, int line, std::string msg) {
    if (logStacktrace_ && level == LogLevel::Error && audience == LogAudience::Developer) {
        std::stringstream ss;
        ss << msg;

        std::vector<std::string> stacktrace = getStackTrace();
        // start at i == 3 to remove log and getStacktrace from stackgrace
        for (size_t i = 3; i < stacktrace.size(); ++i) {
            ss << std::endl << stacktrace[i];
        }
        // append an extra line break to easier separate several stacktraces in a row
        ss << std::endl;

        msg = ss.str();
    }

    if (level >= logLevel_) {
        // use remove if here to remove expired weak pointers while calling the loggers.
        util::erase_remove_if(loggers_, [&](const std::weak_ptr<Logger>& logger) {
            if (auto l = logger.lock()) {
                l->log(source, level, audience, file, function, line, msg);
                return false;
            } else {
                return true;
            }
        });
    }
}

void LogCentral::logProcessor(Processor* processor, LogLevel level, LogAudience audience,
                              std::string msg, const char* file, const char* function, int line) {
    if (level >= logLevel_) {
        // use remove if here to remove expired weak pointers while calling the loggers.
        util::erase_remove_if(loggers_, [&](const std::weak_ptr<Logger>& logger) {
            if (auto l = logger.lock()) {
                l->logProcessor(processor, level, audience, msg, file, function, line);
                return false;
            } else {
                return true;
            }
        });
    }
}

void LogCentral::logNetwork(LogLevel level, LogAudience audience, std::string msg, const char* file,
                            const char* function, int line) {
    if (level >= logLevel_) {
        // use remove if here to remove expired weak pointers while calling the loggers.
        util::erase_remove_if(loggers_, [&](const std::weak_ptr<Logger>& logger) {
            if (auto l = logger.lock()) {
                l->logNetwork(level, audience, msg, file, function, line);
                return false;
            } else {
                return true;
            }
        });
    }
}

void LogCentral::logAssertion(const char* fileName, const char* functionName, long lineNumber,
                              std::string message) {
    util::erase_remove_if(loggers_, [&](const std::weak_ptr<Logger>& logger) {
        if (auto l = logger.lock()) {
            l->logAssertion(fileName, functionName, lineNumber, message);
            return false;
        } else {
            return true;
        }
    });
}

void LogCentral::setLogStacktrace(const bool& logStacktrace) { logStacktrace_ = logStacktrace; }

bool LogCentral::getLogStacktrace() const { return logStacktrace_; }

void util::log(ExceptionContext context, std::string message, LogLevel level,
               LogAudience audience) {
    LogCentral::getPtr()->log(context.getCaller(), level, audience, context.getFile().c_str(),
                              context.getFunction().c_str(), context.getLine(), message);
}

}  // namespace inviwo<commit_msg>Core: added newline<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2012-2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <inviwo/core/util/logcentral.h>
#include <inviwo/core/util/stacktrace.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/common/inviwoapplication.h>
#include <inviwo/core/processors/processor.h>
#include <inviwo/core/network/processornetwork.h>

namespace inviwo {

void Logger::logProcessor(Processor* processor, LogLevel level, LogAudience audience,
                          std::string msg, const char* file, const char* function, int line) {
    log("Processor " + processor->getIdentifier(), level, audience, file, function, line, msg);
}

void Logger::logNetwork(LogLevel level, LogAudience audience, std::string msg, const char* file,
                        const char* function, int line) {
    log("ProcessorNetwork", level, audience, file, function, line, msg);
}

void Logger::logAssertion(const char* fileName, const char* functionName, long lineNumber,
                          std::string message) {
    log("Assertion failed", LogLevel::Error, LogAudience::Developer, fileName, functionName,
        lineNumber, message);
}

LogCentral::LogCentral() : logLevel_(LogLevel::Info), logStacktrace_(false) {}

void LogCentral::registerLogger(std::weak_ptr<Logger> logger) { loggers_.push_back(logger); }

void LogCentral::log(std::string source, LogLevel level, LogAudience audience, const char* file,
                     const char* function, int line, std::string msg) {
    if (logStacktrace_ && level == LogLevel::Error && audience == LogAudience::Developer) {
        std::stringstream ss;
        ss << msg;

        std::vector<std::string> stacktrace = getStackTrace();
        // start at i == 3 to remove log and getStacktrace from stackgrace
        for (size_t i = 3; i < stacktrace.size(); ++i) {
            ss << std::endl << stacktrace[i];
        }
        // append an extra line break to easier separate several stacktraces in a row
        ss << std::endl;

        msg = ss.str();
    }

    if (level >= logLevel_) {
        // use remove if here to remove expired weak pointers while calling the loggers.
        util::erase_remove_if(loggers_, [&](const std::weak_ptr<Logger>& logger) {
            if (auto l = logger.lock()) {
                l->log(source, level, audience, file, function, line, msg);
                return false;
            } else {
                return true;
            }
        });
    }
}

void LogCentral::logProcessor(Processor* processor, LogLevel level, LogAudience audience,
                              std::string msg, const char* file, const char* function, int line) {
    if (level >= logLevel_) {
        // use remove if here to remove expired weak pointers while calling the loggers.
        util::erase_remove_if(loggers_, [&](const std::weak_ptr<Logger>& logger) {
            if (auto l = logger.lock()) {
                l->logProcessor(processor, level, audience, msg, file, function, line);
                return false;
            } else {
                return true;
            }
        });
    }
}

void LogCentral::logNetwork(LogLevel level, LogAudience audience, std::string msg, const char* file,
                            const char* function, int line) {
    if (level >= logLevel_) {
        // use remove if here to remove expired weak pointers while calling the loggers.
        util::erase_remove_if(loggers_, [&](const std::weak_ptr<Logger>& logger) {
            if (auto l = logger.lock()) {
                l->logNetwork(level, audience, msg, file, function, line);
                return false;
            } else {
                return true;
            }
        });
    }
}

void LogCentral::logAssertion(const char* fileName, const char* functionName, long lineNumber,
                              std::string message) {
    util::erase_remove_if(loggers_, [&](const std::weak_ptr<Logger>& logger) {
        if (auto l = logger.lock()) {
            l->logAssertion(fileName, functionName, lineNumber, message);
            return false;
        } else {
            return true;
        }
    });
}

void LogCentral::setLogStacktrace(const bool& logStacktrace) { logStacktrace_ = logStacktrace; }

bool LogCentral::getLogStacktrace() const { return logStacktrace_; }

void util::log(ExceptionContext context, std::string message, LogLevel level,
               LogAudience audience) {
    LogCentral::getPtr()->log(context.getCaller(), level, audience, context.getFile().c_str(),
                              context.getFunction().c_str(), context.getLine(), message);
}

}  // namespace inviwo
<|endoftext|>


<commit_before>/* Copyright (c) 2008-2014, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "jni.h"
#include "avian/machine.h"
#include "sockets.h"
#include "jni-util.h"

using namespace avian::classpath::sockets;

extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_init(JNIEnv* e, jclass)
{
  init(e);
}

extern "C" JNIEXPORT SOCKET JNICALL
    Java_java_net_Socket_create(JNIEnv* e, jclass)
{
  return create(e);
}

extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_connect(JNIEnv* e,
                                                               jclass,
                                                               SOCKET sock,
                                                               long addr,
                                                               short port)
{
  connect(e, sock, addr, port);
}

extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_bind(JNIEnv* e,
                                                            jclass,
                                                            SOCKET sock,
                                                            long addr,
                                                            short port)
{
  bind(e, sock, addr, port);
}

extern "C" JNIEXPORT void JNICALL
    Java_java_net_Socket_abort(JNIEnv* e, jclass, SOCKET sock)
{
  abort(e, sock);
}

extern "C" JNIEXPORT void JNICALL
    Java_java_net_Socket_close(JNIEnv* e, jclass, SOCKET sock)
{
  close(e, sock);
}

extern "C" JNIEXPORT void JNICALL
    Java_java_net_Socket_closeOutput(JNIEnv* e, jclass, SOCKET sock)
{
  close_output(e, sock);
}

extern "C" JNIEXPORT void JNICALL
    Java_java_net_Socket_closeInput(JNIEnv* e, jclass, SOCKET sock)
{
  close_input(e, sock);
}

extern "C" JNIEXPORT void JNICALL
    Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments)
{ /* SOCKET s, object buffer_obj, int start_pos, int count  */
  SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
  vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
      t, reinterpret_cast<vm::object>(arguments[2]));
  int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
  int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
  char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
  avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
}

extern "C" JNIEXPORT int64_t JNICALL
    Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments)
{ /* SOCKET s, object buffer_obj, int start_pos, int count  */
  SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
  vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
      t, reinterpret_cast<vm::object>(arguments[2]));
  int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
  int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
  char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
  return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count);
}

extern "C" JNIEXPORT jint JNICALL
    Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
                                                 jclass,
                                                 jstring name)
{
  const char* chars = e->GetStringUTFChars(name, 0);
  if (chars) {
#ifdef PLATFORM_WINDOWS
    hostent* host = gethostbyname(chars);
    e->ReleaseStringUTFChars(name, chars);
    if (host) {
      return ntohl(reinterpret_cast<in_addr*>(host->h_addr_list[0])->s_addr);
    } else {
      throwNew(e, "java/net/UnknownHostException", 0);
      return 0;
    }
#else
    addrinfo hints;
    memset(&hints, 0, sizeof(addrinfo));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    addrinfo* result;
    int r = getaddrinfo(chars, 0, &hints, &result);
    e->ReleaseStringUTFChars(name, chars);

    if (r != 0) {
      throwNew(e, "java/net/UnknownHostException", 0);
      return 0;
    } else {
      int address = ntohl(
          reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);

      freeaddrinfo(result);
      return address;
    }
#endif
  } else {
    throwNew(e, "java/lang/OutOfMemoryError", 0);
    return 0;
  }
}
<commit_msg>cp/avian/java-net.cpp: fix segfault<commit_after>/* Copyright (c) 2008-2014, Avian Contributors

   Permission to use, copy, modify, and/or distribute this software
   for any purpose with or without fee is hereby granted, provided
   that the above copyright notice and this permission notice appear
   in all copies.

   There is NO WARRANTY for this software.  See license.txt for
   details. */

#include "jni.h"
#include "avian/machine.h"
#include "sockets.h"
#include "jni-util.h"

using namespace avian::classpath::sockets;

extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_init(JNIEnv* e, jclass)
{
  init(e);
}

extern "C" JNIEXPORT SOCKET JNICALL
    Java_java_net_Socket_create(JNIEnv* e, jclass)
{
  return create(e);
}

extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_connect(JNIEnv* e,
                                                               jclass,
                                                               SOCKET sock,
                                                               long addr,
                                                               short port)
{
  connect(e, sock, addr, port);
}

extern "C" JNIEXPORT void JNICALL Java_java_net_Socket_bind(JNIEnv* e,
                                                            jclass,
                                                            SOCKET sock,
                                                            long addr,
                                                            short port)
{
  bind(e, sock, addr, port);
}

extern "C" JNIEXPORT void JNICALL
    Java_java_net_Socket_abort(JNIEnv* e, jclass, SOCKET sock)
{
  abort(e, sock);
}

extern "C" JNIEXPORT void JNICALL
    Java_java_net_Socket_close(JNIEnv* e, jclass, SOCKET sock)
{
  close(e, sock);
}

extern "C" JNIEXPORT void JNICALL
    Java_java_net_Socket_closeOutput(JNIEnv* e, jclass, SOCKET sock)
{
  close_output(e, sock);
}

extern "C" JNIEXPORT void JNICALL
    Java_java_net_Socket_closeInput(JNIEnv* e, jclass, SOCKET sock)
{
  close_input(e, sock);
}

extern "C" JNIEXPORT void JNICALL
    Avian_java_net_Socket_send(vm::Thread* t, vm::object, uintptr_t* arguments)
{ /* SOCKET s, object buffer_obj, int start_pos, int count  */
  SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
  vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
      t, reinterpret_cast<vm::object>(arguments[2]));
  int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
  int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
  char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
  avian::classpath::sockets::send((JNIEnv*)t, s, buffer, count);
}

extern "C" JNIEXPORT int64_t JNICALL
    Avian_java_net_Socket_recv(vm::Thread* t, vm::object, uintptr_t* arguments)
{ /* SOCKET s, object buffer_obj, int start_pos, int count  */
  SOCKET& s = *(reinterpret_cast<SOCKET*>(&arguments[0]));
  vm::GcByteArray* buffer_obj = vm::cast<vm::GcByteArray>(
      t, reinterpret_cast<vm::object>(arguments[2]));
  int32_t& start_pos = *(reinterpret_cast<int32_t*>(&arguments[3]));
  int32_t& count = *(reinterpret_cast<int32_t*>(&arguments[4]));
  char* buffer = reinterpret_cast<char*>(&buffer_obj->body()[start_pos]);
  return avian::classpath::sockets::recv((JNIEnv*)t, s, buffer, count);
}

extern "C" JNIEXPORT jint JNICALL
    Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e,
                                                 jclass,
                                                 jstring name)
{
  if(!name) {
    throwNew(e, "java/lang/NullPointerException", 0);
    return 0;
  }

  const char* chars = e->GetStringUTFChars(name, 0);
  if (chars) {
#ifdef PLATFORM_WINDOWS
    hostent* host = gethostbyname(chars);
    e->ReleaseStringUTFChars(name, chars);
    if (host) {
      return ntohl(reinterpret_cast<in_addr*>(host->h_addr_list[0])->s_addr);
    } else {
      throwNew(e, "java/net/UnknownHostException", 0);
      return 0;
    }
#else
    addrinfo hints;
    memset(&hints, 0, sizeof(addrinfo));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;

    addrinfo* result;
    int r = getaddrinfo(chars, 0, &hints, &result);
    e->ReleaseStringUTFChars(name, chars);

    if (r != 0) {
      throwNew(e, "java/net/UnknownHostException", 0);
      return 0;
    } else {
      int address = ntohl(
          reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr);

      freeaddrinfo(result);
      return address;
    }
#endif
  } else {
    throwNew(e, "java/lang/OutOfMemoryError", 0);
    return 0;
  }
}
<|endoftext|>


<commit_before>/**************************************************************************
 *
 * Copyright 2007-2011 VMware, Inc.
 * All Rights Reserved.
 *
 * 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 <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "os.hpp"
#include "os_thread.hpp"
#include "os_string.hpp"
#include "trace_file.hpp"
#include "trace_writer.hpp"
#include "trace_format.hpp"

namespace trace {

static const char *memcpy_args[3] = {"dest", "src", "n"};
const FunctionSig memcpy_sig = {0, "memcpy", 3, memcpy_args};

static const char *malloc_args[1] = {"size"};
const FunctionSig malloc_sig = {1, "malloc", 1, malloc_args};

static const char *free_args[1] = {"ptr"};
const FunctionSig free_sig = {2, "free", 1, free_args};

static const char *realloc_args[2] = {"ptr", "size"};
const FunctionSig realloc_sig = {3, "realloc", 2, realloc_args};

static void exceptionCallback(void)
{
    localWriter.flush();
}

LocalWriter::LocalWriter() :
    acquired(0)
{
    // Install the signal handlers as early as possible, to prevent
    // interfering with the application's signal handling.
    os::setExceptionCallback(exceptionCallback);
}

LocalWriter::~LocalWriter()
{
    os::resetExceptionCallback();
}

void
LocalWriter::open(void) {
    os::String szFileName;

    const char *lpFileName;

    lpFileName = getenv("TRACE_FILE");
    if (!lpFileName) {
        static unsigned dwCounter = 0;

        os::String process = os::getProcessName();
#ifdef _WIN32
        process.trimExtension();
#endif
        process.trimDirectory();

        os::String prefix = os::getCurrentDir();
        prefix.join(process);

        for (;;) {
            FILE *file;

            if (dwCounter)
                szFileName = os::String::format("%s.%u.trace", prefix.str(), dwCounter);
            else
                szFileName = os::String::format("%s.trace", prefix.str());

            lpFileName = szFileName;
            file = fopen(lpFileName, "rb");
            if (file == NULL)
                break;

            fclose(file);

            ++dwCounter;
        }
    }

    os::log("apitrace: tracing to %s\n", lpFileName);

    if (!Writer::open(lpFileName)) {
        os::log("apitrace: error: failed to open %s\n", lpFileName);
        os::abort();
    }

#if 0
    // For debugging the exception handler
    *((int *)0) = 0;
#endif
}

static unsigned next_thread_id = 0;
static os::thread_specific_ptr<unsigned> thread_id_specific_ptr;

unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
    os::acquireMutex();
    ++acquired;

    if (!m_file->isOpened()) {
        open();
    }

    unsigned *thread_id_ptr = thread_id_specific_ptr.get();
    unsigned thread_id;
    if (thread_id_ptr) {
        thread_id = *thread_id_ptr;
    } else {
        thread_id = next_thread_id++;
        thread_id_ptr = new unsigned;
        *thread_id_ptr = thread_id;
        thread_id_specific_ptr.reset(thread_id_ptr);
    }

    return Writer::beginEnter(sig, thread_id);
}

void LocalWriter::endEnter(void) {
    Writer::endEnter();
    --acquired;
    os::releaseMutex();
}

void LocalWriter::beginLeave(unsigned call) {
    os::acquireMutex();
    ++acquired;
    Writer::beginLeave(call);
}

void LocalWriter::endLeave(void) {
    Writer::endLeave();
    --acquired;
    os::releaseMutex();
}

void LocalWriter::flush(void) {
    /*
     * Do nothing if the mutex is already acquired (e.g., if a segfault happen
     * while writing the file) to prevent dead-lock.
     */

    if (!acquired) {
        os::acquireMutex();
        if (m_file->isOpened()) {
            os::log("apitrace: flushing trace due to an exception\n");
            m_file->flush();
        }
        os::releaseMutex();
    }
}

LocalWriter localWriter;

} /* namespace trace */

<commit_msg>More helpful messages on exceptions inside apitrace code.<commit_after>/**************************************************************************
 *
 * Copyright 2007-2011 VMware, Inc.
 * All Rights Reserved.
 *
 * 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 <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "os.hpp"
#include "os_thread.hpp"
#include "os_string.hpp"
#include "trace_file.hpp"
#include "trace_writer.hpp"
#include "trace_format.hpp"

namespace trace {

static const char *memcpy_args[3] = {"dest", "src", "n"};
const FunctionSig memcpy_sig = {0, "memcpy", 3, memcpy_args};

static const char *malloc_args[1] = {"size"};
const FunctionSig malloc_sig = {1, "malloc", 1, malloc_args};

static const char *free_args[1] = {"ptr"};
const FunctionSig free_sig = {2, "free", 1, free_args};

static const char *realloc_args[2] = {"ptr", "size"};
const FunctionSig realloc_sig = {3, "realloc", 2, realloc_args};

static void exceptionCallback(void)
{
    localWriter.flush();
}

LocalWriter::LocalWriter() :
    acquired(0)
{
    // Install the signal handlers as early as possible, to prevent
    // interfering with the application's signal handling.
    os::setExceptionCallback(exceptionCallback);
}

LocalWriter::~LocalWriter()
{
    os::resetExceptionCallback();
}

void
LocalWriter::open(void) {
    os::String szFileName;

    const char *lpFileName;

    lpFileName = getenv("TRACE_FILE");
    if (!lpFileName) {
        static unsigned dwCounter = 0;

        os::String process = os::getProcessName();
#ifdef _WIN32
        process.trimExtension();
#endif
        process.trimDirectory();

        os::String prefix = os::getCurrentDir();
        prefix.join(process);

        for (;;) {
            FILE *file;

            if (dwCounter)
                szFileName = os::String::format("%s.%u.trace", prefix.str(), dwCounter);
            else
                szFileName = os::String::format("%s.trace", prefix.str());

            lpFileName = szFileName;
            file = fopen(lpFileName, "rb");
            if (file == NULL)
                break;

            fclose(file);

            ++dwCounter;
        }
    }

    os::log("apitrace: tracing to %s\n", lpFileName);

    if (!Writer::open(lpFileName)) {
        os::log("apitrace: error: failed to open %s\n", lpFileName);
        os::abort();
    }

#if 0
    // For debugging the exception handler
    *((int *)0) = 0;
#endif
}

static unsigned next_thread_id = 0;
static os::thread_specific_ptr<unsigned> thread_id_specific_ptr;

unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
    os::acquireMutex();
    ++acquired;

    if (!m_file->isOpened()) {
        open();
    }

    unsigned *thread_id_ptr = thread_id_specific_ptr.get();
    unsigned thread_id;
    if (thread_id_ptr) {
        thread_id = *thread_id_ptr;
    } else {
        thread_id = next_thread_id++;
        thread_id_ptr = new unsigned;
        *thread_id_ptr = thread_id;
        thread_id_specific_ptr.reset(thread_id_ptr);
    }

    return Writer::beginEnter(sig, thread_id);
}

void LocalWriter::endEnter(void) {
    Writer::endEnter();
    --acquired;
    os::releaseMutex();
}

void LocalWriter::beginLeave(unsigned call) {
    os::acquireMutex();
    ++acquired;
    Writer::beginLeave(call);
}

void LocalWriter::endLeave(void) {
    Writer::endLeave();
    --acquired;
    os::releaseMutex();
}

void LocalWriter::flush(void) {
    /*
     * Do nothing if the mutex is already acquired (e.g., if a segfault happen
     * while writing the file) to prevent dead-lock.
     */

    os::acquireMutex();
    if (acquired) {
        os::log("apitrace: ignoring exception while tracing\n");
    } else {
        ++acquired;
        if (m_file->isOpened()) {
            os::log("apitrace: flushing trace due to an exception\n");
            m_file->flush();
        }
        --acquired;
    }
    os::releaseMutex();
}

LocalWriter localWriter;

} /* namespace trace */

<|endoftext|>


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

BlueBerry Platform

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#ifdef __MINGW32__
// We need to inlclude winbase.h here in order to declare
// atomic intrinsics like InterlockedIncrement correctly.
// Otherwhise, they would be declared wrong within qatomic_windows.h .
#include <windows.h>
#endif

#include "berryHelpSearchView.h"

#include "berryHelpPluginActivator.h"
#include "berryQHelpEngineWrapper.h"
#include "berryHelpEditorInput.h"
#include "berryHelpEditor.h"

#include <QLayout>
#include <QMenu>
#include <QEvent>
#include <QMouseEvent>
#include <QTextBrowser>
#include <QClipboard>
#include <QHelpSearchQueryWidget>
#include <QHelpSearchResultWidget>
#include <QApplication>

namespace berry {

HelpSearchView::HelpSearchView()
  : m_ZoomCount(0)
  , m_Parent(0)
  , m_SearchEngine(HelpPluginActivator::getInstance()->getQHelpEngine().searchEngine())
  , m_ResultWidget(0)
  , m_QueryWidget(0)
{
}

HelpSearchView::~HelpSearchView()
{
  // prevent deletion of the widget
  m_ResultWidget->setParent(0);
}

void HelpSearchView::CreateQtPartControl(QWidget* parent)
{
  if (m_ResultWidget == 0)
  {
    m_Parent = parent;

    QVBoxLayout* vLayout = new QVBoxLayout(parent);

    // This will be lead to strange behavior when using multiple instances of this view
    // because the QHelpSearchResultWidget instance is shared. The new view will
    // reparent the widget.
    m_ResultWidget = m_SearchEngine->resultWidget();
    m_QueryWidget = new QHelpSearchQueryWidget();

    vLayout->addWidget(m_QueryWidget);
    vLayout->addWidget(m_ResultWidget);

    connect(m_QueryWidget, SIGNAL(search()), this, SLOT(search()));
    connect(m_ResultWidget, SIGNAL(requestShowLink(QUrl)), this,
            SLOT(requestShowLink(QUrl)));

    connect(m_SearchEngine, SIGNAL(searchingStarted()), this,
            SLOT(searchingStarted()));
    connect(m_SearchEngine, SIGNAL(searchingFinished(int)), this,
            SLOT(searchingFinished(int)));

    QTextBrowser* browser = qFindChild<QTextBrowser*>(m_ResultWidget);
    if (browser) // Will be null if QtHelp was configured not to use CLucene.
    {
      browser->viewport()->installEventFilter(this);
      browser->setContextMenuPolicy(Qt::CustomContextMenu);
      connect(browser, SIGNAL(customContextMenuRequested(QPoint)),
              this, SLOT(showContextMenu(QPoint)));
    }
  }
}

void HelpSearchView::SetFocus()
{
  if (!(m_ResultWidget->hasFocus()))
  {
    m_QueryWidget->setFocus();
  }
}

void HelpSearchView::zoomIn()
{
  QTextBrowser* browser = qFindChild<QTextBrowser*>(m_ResultWidget);
  if (browser && m_ZoomCount != 10)
  {
    m_ZoomCount++;
    browser->zoomIn();
  }
}

void HelpSearchView::zoomOut()
{
  QTextBrowser* browser = qFindChild<QTextBrowser*>(m_ResultWidget);
  if (browser && m_ZoomCount != -5)
  {
    m_ZoomCount--;
    browser->zoomOut();
  }
}

void HelpSearchView::resetZoom()
{
  if (m_ZoomCount == 0)
    return;

  QTextBrowser* browser = qFindChild<QTextBrowser*>(m_ResultWidget);
  if (browser)
  {
    browser->zoomOut(m_ZoomCount);
    m_ZoomCount = 0;
  }
}

void HelpSearchView::search() const
{
  QList<QHelpSearchQuery> query = m_QueryWidget->query();
  m_SearchEngine->search(query);
}

void HelpSearchView::searchingStarted()
{
  m_Parent->setCursor(QCursor(Qt::WaitCursor));
}

void HelpSearchView::searchingFinished(int hits)
{
  Q_UNUSED(hits)
  m_Parent->unsetCursor();
  //qApp->restoreOverrideCursor();
}

void HelpSearchView::requestShowLink(const QUrl &link)
{
  HelpPluginActivator::linkActivated(this->GetSite()->GetPage(), link);
}

bool HelpSearchView::eventFilter(QObject* o, QEvent *e)
{
  QTextBrowser* browser = qFindChild<QTextBrowser*>(m_ResultWidget);
  if (browser && o == browser->viewport()
      && e->type() == QEvent::MouseButtonRelease)
  {
    QMouseEvent* me = static_cast<QMouseEvent*>(e);
    QUrl link = m_ResultWidget->linkAt(me->pos());
    if (!link.isEmpty() || link.isValid())
    {
      bool controlPressed = me->modifiers() & Qt::ControlModifier;
      if((me->button() == Qt::LeftButton && controlPressed)
         || (me->button() == Qt::MidButton))
      {
        IEditorInput::Pointer input(new HelpEditorInput(link));
        this->GetSite()->GetPage()->OpenEditor(input, HelpEditor::EDITOR_ID);
      }
    }
  }
  return QObject::eventFilter(o,e);
}

void HelpSearchView::showContextMenu(const QPoint& point)
{
  QMenu menu;

  QTextBrowser* browser = qFindChild<QTextBrowser*>(m_ResultWidget);
  if (!browser)
    return;

//  QPoint point = browser->mapFromGlobal(pos);
//  if (!browser->rect().contains(point, true))
//    return;

  QUrl link = browser->anchorAt(point);

  QKeySequence keySeq(QKeySequence::Copy);
  QAction *copyAction = menu.addAction(tr("&Copy") + QLatin1String("\t") +
                                       keySeq.toString(QKeySequence::NativeText));
  copyAction->setEnabled(QTextCursor(browser->textCursor()).hasSelection());

  QAction *copyAnchorAction = menu.addAction(tr("Copy &Link Location"));
  copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid());

  keySeq = QKeySequence(Qt::CTRL);
  QAction *newTabAction = menu.addAction(tr("Open Link in New Tab") +
                                         QLatin1String("\t") + keySeq.toString(QKeySequence::NativeText) +
                                         QLatin1String("LMB"));
  newTabAction->setEnabled(!link.isEmpty() && link.isValid());

  menu.addSeparator();

  keySeq = QKeySequence::SelectAll;
  QAction *selectAllAction = menu.addAction(tr("Select All") +
                                            QLatin1String("\t") + keySeq.toString(QKeySequence::NativeText));

  QAction *usedAction = menu.exec(browser->mapToGlobal(point));
  if (usedAction == copyAction)
  {
    QTextCursor cursor = browser->textCursor();
    if (!cursor.isNull() && cursor.hasSelection())
    {
      QString selectedText = cursor.selectedText();
      QMimeData *data = new QMimeData();
      data->setText(selectedText);
      QApplication::clipboard()->setMimeData(data);
    }
  }
  else if (usedAction == copyAnchorAction)
  {
    QApplication::clipboard()->setText(link.toString());
  }
  else if (usedAction == newTabAction)
  {
    IEditorInput::Pointer input(new HelpEditorInput(link));
    this->GetSite()->GetPage()->OpenEditor(input, HelpEditor::EDITOR_ID);
  }
  else if (usedAction == selectAllAction)
  {
    browser->selectAll();
  }
}

}
<commit_msg>Replaced qFindChild macros with equivalent QObject::findChild method calls.<commit_after>/*===================================================================

BlueBerry Platform

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#ifdef __MINGW32__
// We need to inlclude winbase.h here in order to declare
// atomic intrinsics like InterlockedIncrement correctly.
// Otherwhise, they would be declared wrong within qatomic_windows.h .
#include <windows.h>
#endif

#include "berryHelpSearchView.h"

#include "berryHelpPluginActivator.h"
#include "berryQHelpEngineWrapper.h"
#include "berryHelpEditorInput.h"
#include "berryHelpEditor.h"

#include <QLayout>
#include <QMenu>
#include <QEvent>
#include <QMouseEvent>
#include <QMimeData>
#include <QTextBrowser>
#include <QClipboard>
#include <QHelpSearchQueryWidget>
#include <QHelpSearchResultWidget>
#include <QApplication>

namespace berry {

HelpSearchView::HelpSearchView()
  : m_ZoomCount(0)
  , m_Parent(0)
  , m_SearchEngine(HelpPluginActivator::getInstance()->getQHelpEngine().searchEngine())
  , m_ResultWidget(0)
  , m_QueryWidget(0)
{
}

HelpSearchView::~HelpSearchView()
{
  // prevent deletion of the widget
  m_ResultWidget->setParent(0);
}

void HelpSearchView::CreateQtPartControl(QWidget* parent)
{
  if (m_ResultWidget == 0)
  {
    m_Parent = parent;

    QVBoxLayout* vLayout = new QVBoxLayout(parent);

    // This will be lead to strange behavior when using multiple instances of this view
    // because the QHelpSearchResultWidget instance is shared. The new view will
    // reparent the widget.
    m_ResultWidget = m_SearchEngine->resultWidget();
    m_QueryWidget = new QHelpSearchQueryWidget();

    vLayout->addWidget(m_QueryWidget);
    vLayout->addWidget(m_ResultWidget);

    connect(m_QueryWidget, SIGNAL(search()), this, SLOT(search()));
    connect(m_ResultWidget, SIGNAL(requestShowLink(QUrl)), this,
            SLOT(requestShowLink(QUrl)));

    connect(m_SearchEngine, SIGNAL(searchingStarted()), this,
            SLOT(searchingStarted()));
    connect(m_SearchEngine, SIGNAL(searchingFinished(int)), this,
            SLOT(searchingFinished(int)));

    QTextBrowser* browser = m_ResultWidget->findChild<QTextBrowser*>();
    if (browser) // Will be null if QtHelp was configured not to use CLucene.
    {
      browser->viewport()->installEventFilter(this);
      browser->setContextMenuPolicy(Qt::CustomContextMenu);
      connect(browser, SIGNAL(customContextMenuRequested(QPoint)),
              this, SLOT(showContextMenu(QPoint)));
    }
  }
}

void HelpSearchView::SetFocus()
{
  if (!(m_ResultWidget->hasFocus()))
  {
    m_QueryWidget->setFocus();
  }
}

void HelpSearchView::zoomIn()
{
  QTextBrowser* browser = m_ResultWidget->findChild<QTextBrowser*>();
  if (browser && m_ZoomCount != 10)
  {
    m_ZoomCount++;
    browser->zoomIn();
  }
}

void HelpSearchView::zoomOut()
{
  QTextBrowser* browser = m_ResultWidget->findChild<QTextBrowser*>();
  if (browser && m_ZoomCount != -5)
  {
    m_ZoomCount--;
    browser->zoomOut();
  }
}

void HelpSearchView::resetZoom()
{
  if (m_ZoomCount == 0)
    return;

  QTextBrowser* browser = m_ResultWidget->findChild<QTextBrowser*>();
  if (browser)
  {
    browser->zoomOut(m_ZoomCount);
    m_ZoomCount = 0;
  }
}

void HelpSearchView::search() const
{
  QList<QHelpSearchQuery> query = m_QueryWidget->query();
  m_SearchEngine->search(query);
}

void HelpSearchView::searchingStarted()
{
  m_Parent->setCursor(QCursor(Qt::WaitCursor));
}

void HelpSearchView::searchingFinished(int hits)
{
  Q_UNUSED(hits)
  m_Parent->unsetCursor();
  //qApp->restoreOverrideCursor();
}

void HelpSearchView::requestShowLink(const QUrl &link)
{
  HelpPluginActivator::linkActivated(this->GetSite()->GetPage(), link);
}

bool HelpSearchView::eventFilter(QObject* o, QEvent *e)
{
  QTextBrowser* browser = m_ResultWidget->findChild<QTextBrowser*>();
  if (browser && o == browser->viewport()
      && e->type() == QEvent::MouseButtonRelease)
  {
    QMouseEvent* me = static_cast<QMouseEvent*>(e);
    QUrl link = m_ResultWidget->linkAt(me->pos());
    if (!link.isEmpty() || link.isValid())
    {
      bool controlPressed = me->modifiers() & Qt::ControlModifier;
      if((me->button() == Qt::LeftButton && controlPressed)
         || (me->button() == Qt::MidButton))
      {
        IEditorInput::Pointer input(new HelpEditorInput(link));
        this->GetSite()->GetPage()->OpenEditor(input, HelpEditor::EDITOR_ID);
      }
    }
  }
  return QObject::eventFilter(o,e);
}

void HelpSearchView::showContextMenu(const QPoint& point)
{
  QMenu menu;

  QTextBrowser* browser = m_ResultWidget->findChild<QTextBrowser*>();
  if (!browser)
    return;

//  QPoint point = browser->mapFromGlobal(pos);
//  if (!browser->rect().contains(point, true))
//    return;

  QUrl link = browser->anchorAt(point);

  QKeySequence keySeq(QKeySequence::Copy);
  QAction *copyAction = menu.addAction(tr("&Copy") + QLatin1String("\t") +
                                       keySeq.toString(QKeySequence::NativeText));
  copyAction->setEnabled(QTextCursor(browser->textCursor()).hasSelection());

  QAction *copyAnchorAction = menu.addAction(tr("Copy &Link Location"));
  copyAnchorAction->setEnabled(!link.isEmpty() && link.isValid());

  keySeq = QKeySequence(Qt::CTRL);
  QAction *newTabAction = menu.addAction(tr("Open Link in New Tab") +
                                         QLatin1String("\t") + keySeq.toString(QKeySequence::NativeText) +
                                         QLatin1String("LMB"));
  newTabAction->setEnabled(!link.isEmpty() && link.isValid());

  menu.addSeparator();

  keySeq = QKeySequence::SelectAll;
  QAction *selectAllAction = menu.addAction(tr("Select All") +
                                            QLatin1String("\t") + keySeq.toString(QKeySequence::NativeText));

  QAction *usedAction = menu.exec(browser->mapToGlobal(point));
  if (usedAction == copyAction)
  {
    QTextCursor cursor = browser->textCursor();
    if (!cursor.isNull() && cursor.hasSelection())
    {
      QString selectedText = cursor.selectedText();
      QMimeData *data = new QMimeData();
      data->setText(selectedText);
      QApplication::clipboard()->setMimeData(data);
    }
  }
  else if (usedAction == copyAnchorAction)
  {
    QApplication::clipboard()->setText(link.toString());
  }
  else if (usedAction == newTabAction)
  {
    IEditorInput::Pointer input(new HelpEditorInput(link));
    this->GetSite()->GetPage()->OpenEditor(input, HelpEditor::EDITOR_ID);
  }
  else if (usedAction == selectAllAction)
  {
    browser->selectAll();
  }
}

}
<|endoftext|>