<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * A LibreOffice extension to send the menubar structure through DBusMenu
 *
 * Copyright 2011 Canonical, Ltd.
 * Authors:
 *     Alberto Ruiz <alberto.ruiz@codethink.co.uk>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the the GNU Lesser General Public License version 3, as published by the Free
 * Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
 * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE.  See the applicable
 * version of the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
 *
 */

#include "FrameJob.hxx"
#include "DesktopJob.hxx"
#include "FrameHelper.hxx"

#define OBJ_PATH_PREFIX "/com/canonical/menu/"

#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
#include <com/sun/star/awt/SystemDependentXWindow.hpp>
#include <com/sun/star/awt/XMenu.hpp>
#include <com/sun/star/awt/XMenuExtended.hpp>
#include <com/sun/star/awt/XMenuBar.hpp>
#include <com/sun/star/awt/XPopupMenu.hpp>
#include <com/sun/star/awt/XPopupMenuExtended.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/container/NoSuchElementException.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/frame/XDispatch.hpp>
#include <com/sun/star/frame/XDispatchHelper.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/frame/XFrameActionListener.hpp>
#include <com/sun/star/frame/XStatusListener.hpp>
#include <com/sun/star/frame/FrameAction.hpp>
#include <com/sun/star/lang/EventObject.hpp>
#include <com/sun/star/lang/SystemDependent.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/ui/XUIConfigurationManager.hpp>
#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIElementSettings.hpp>
#include <com/sun/star/ui/XUIElement.hpp>
#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/util/URL.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>

#include <iostream>
#include <fstream>

#include <gio/gio.h>
//#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/client.h>
#pragma GCC diagnostic error "-Wignored-qualifiers"
//#pragma GCC diagnostic pop

#include <rtl/process.h>
#include <osl/diagnose.h>

using rtl::OUString;
using rtl::OString;
using rtl::OUStringToOString;

using com::sun::star::awt::KeyEvent;
using com::sun::star::awt::SystemDependentXWindow;
using com::sun::star::awt::XMenu;
using com::sun::star::awt::XMenuExtended;
using com::sun::star::awt::XPopupMenu;
using com::sun::star::awt::XPopupMenuExtended;
using com::sun::star::awt::XMenuBar;
using com::sun::star::awt::XSystemDependentWindowPeer;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::Reference;
using com::sun::star::uno::WeakReference;
using com::sun::star::uno::Any;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Exception;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::XInterface;
using com::sun::star::lang::IllegalArgumentException;
using com::sun::star::lang::XMultiServiceFactory;
using com::sun::star::lang::SystemDependent::SYSTEM_XWINDOW;
using com::sun::star::lang::EventObject;
using com::sun::star::beans::NamedValue;
using com::sun::star::beans::PropertyValue;
using com::sun::star::beans::XPropertySet;
using com::sun::star::document::XEventBroadcaster;
using com::sun::star::frame::XFrame;
using com::sun::star::frame::XFrameActionListener;
using com::sun::star::frame::FrameActionEvent;
using com::sun::star::frame::XController;
using com::sun::star::frame::XLayoutManager;
using com::sun::star::frame::XModel;
using com::sun::star::frame::XModuleManager;
using com::sun::star::frame::XDispatch;
using com::sun::star::frame::XDispatchProvider;
using com::sun::star::frame::XDispatchHelper;
using com::sun::star::frame::XStatusListener;
using com::sun::star::frame::FeatureStateEvent;
using com::sun::star::ui::XUIElement;
using com::sun::star::ui::XUIElementSettings;
using com::sun::star::ui::XUIConfigurationManagerSupplier;
using com::sun::star::ui::XUIConfigurationManager;
using com::sun::star::ui::XModuleUIConfigurationManagerSupplier;
using com::sun::star::ui::XAcceleratorConfiguration;
using com::sun::star::util::URL;
using com::sun::star::util::XURLTransformer;
using com::sun::star::container::XIndexContainer;
using com::sun::star::container::XIndexAccess;
using com::sun::star::container::XNameAccess;
using com::sun::star::container::NoSuchElementException;

// This is a helper utility to transform an xid to a /com/canonical/menu/<XID>
// DBUS object path
OString
xid_to_object_path (unsigned long xid)
{

    GString *xid_str = g_string_new ("");
    g_string_printf (xid_str, "%d", (guint32)xid);
    OString object_path = OUStringToOString (OUString::createFromAscii (OBJ_PATH_PREFIX).concat (OUString::createFromAscii(xid_str->str)),
                                             RTL_TEXTENCODING_ASCII_US);
    g_string_free (xid_str, TRUE);
    return object_path;
}

//-------------------------- GObject callbacks -------------------------------//
//This is called when a registrar becomes available. It registers the hides the menubar.
static void
on_registrar_available (GDBusConnection * /*connection*/,
                        const gchar     * /*name*/,
                        const gchar     * /*name_owner*/,
                        gpointer         user_data)
{
    GError     *error = NULL;
    GDBusProxy *proxy;

    FrameHelper *helper = (FrameHelper*)user_data;
    unsigned long xid = helper->getXID();

    proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
                                           G_DBUS_PROXY_FLAGS_NONE,
                                           NULL,
                                           "com.canonical.AppMenu.Registrar",
                                           "/com/canonical/AppMenu/Registrar",
                                           "com.canonical.AppMenu.Registrar",
                                           NULL,
                                           &error);
    if (error)
    {
        g_warning ("Couldn't get /com/canonical/AppMenu/Registrar proxy");
        return;
    }

    //TODO: Check if window is registered already
    g_dbus_proxy_call_sync (proxy,
                            "RegisterWindow",
                            g_variant_new ("(uo)",
                                           (guint32)xid,
                                           xid_to_object_path (xid).getStr()),
                            G_DBUS_CALL_FLAGS_NONE,
                            -1,
                            NULL,
                            &error);

    if (error)
    {
        g_warning ("Couldn't call /com/canonical/AppMenu/Registrar.RegisterWindow");
        return;
    }

    //Hide menubar
    Reference < XFrame > xFrame  = helper->getFrame ();
    Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
    Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))),
                                                UNO_QUERY);
    xLayoutManager->hideElement (OUString(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar")));

    return;
}

//This is called when the registrar becomes unavailable. It shows the menubar.
static void
on_registrar_unavailable (GDBusConnection * /*connection*/,
                          const gchar     * /*name*/,
                          gpointer         user_data)
{
    //TODO: Unregister window?

    // Show menubar
    FrameHelper *helper = (FrameHelper*)user_data;
    Reference < XFrame > xFrame  = helper->getFrame ();
    Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
    Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))),
                                                UNO_QUERY);
    xLayoutManager->showElement (OUString(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar")));
    return;
}
// ------------------------------- FrameJob --------------------------------------------
Any SAL_CALL FrameJob::execute( const Sequence< NamedValue >& aArguments )
    throw ( IllegalArgumentException, Exception, RuntimeException )
{
    Sequence< NamedValue > lEnv;
    Reference< XModel >    xModel;
    sal_Int32              len    = aArguments.getLength();

    for (int i = 0; i<len; i++)
    {
        if (aArguments[i].Name.equalsAscii("Environment"))
        {
            aArguments[i].Value >>= lEnv;
            break;
        }
    }

    len = lEnv.getLength ();
    for (int i = 0; i<len; i++)
    {
        if (lEnv[i].Name.equalsAscii("Model"))
        {
            lEnv[i].Value >>= xModel;
        }
    }

    //If we didn't get the model we have to quit
    if (!xModel.is())
        return Any();

    Reference< XController > xController( xModel->getCurrentController(), UNO_QUERY);
    if (!xController.is())
        return Any();

    m_xFrame = Reference< XFrame > ( xController->getFrame(), UNO_QUERY);
    if (!m_xFrame.is ())
        return Any();

    exportMenus (m_xFrame);
    return Any();
}

// This function crates a DbusmenuServer and starts the watcher for the AppMenu Registrar bus name
void
FrameJob::exportMenus (Reference < XFrame > xFrame)
{
    //Set the xFrame for this object

    this->m_xFrame = xFrame;

    //Create dbusmenu server object path string
    DbusmenuServer *server = dbusmenu_server_new (xid_to_object_path(getXID (xFrame)).getStr());

    Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
    Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))),
                                                UNO_QUERY);
    if (!xLayoutManager.is())
    {
        g_object_unref (server);
        return;
    }

    Reference < XUIElement > menuBar(xLayoutManager->getElement (OUString(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar"))),
                                     UNO_QUERY);
    Reference < XPropertySet > menuPropSet (menuBar, UNO_QUERY);

    if (!menuPropSet.is())
    {
        g_object_unref (server);
        return;
    }

    Reference < XMenu > xMenu (menuPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("XMenuBar"))),
                               UNO_QUERY);

    if (!xMenu.is ())
    {
        g_object_unref (server);
        return;
    }

    //Create a new frame helper to close the server when needed
    FrameHelper *helper = new FrameHelper (m_xMSF, xFrame, server);
    xFrame->addFrameActionListener (Reference < XFrameActionListener > (helper));

    //Populate dbusmenu items and start the server
    DbusmenuMenuitem *root = getRootMenuitem (xMenu, (gpointer)helper);
    dbusmenu_server_set_root (server, root);

    //Listen to the availability of the registrar
    guint watcher = g_bus_watch_name (G_BUS_TYPE_SESSION,
                                      "com.canonical.AppMenu.Registrar",
                                      G_BUS_NAME_WATCHER_FLAGS_NONE,
                                      on_registrar_available,
                                      on_registrar_unavailable,
                                      helper,
                                      NULL);
    helper->setRegistrarWatcher (watcher);
}

//Gets the XID for a given XFrame
unsigned long
FrameJob::getXID (css::uno::Reference < css::frame::XFrame > xFrame)
{
    Reference< XSystemDependentWindowPeer > xWin( xFrame->getContainerWindow(), UNO_QUERY);

    if (!xWin.is())
        return 0;

    sal_Int8 processID[16];
    rtl_getGlobalProcessId( (sal_uInt8*)processID );
    Sequence <signed char> pidSeq (processID, 16);

    SystemDependentXWindow xWindow;
    xWin->getWindowHandle (pidSeq, SYSTEM_XWINDOW) >>= xWindow;

    return xWindow.WindowHandle;
}

// Builds a Dbusmenuitem structure from an XMenu object
DbusmenuMenuitem*
FrameJob::getRootMenuitem (Reference < XMenu > xMenu, gpointer helper)
{

    DbusmenuMenuitem *root = dbusmenu_menuitem_new_with_id (0);
    ((FrameHelper*)helper)->setRootItem(root);
    ((FrameHelper*)helper)->rebuildMenu (xMenu, root);

    return root;
}

// XJob
OUString FrameJob_getImplementationName ()
    throw (RuntimeException)
{
    return OUString ( RTL_CONSTASCII_USTRINGPARAM ( FRAMEJOB_IMPLEMENTATION_NAME ) );
}

sal_Bool SAL_CALL FrameJob_supportsService( const OUString& ServiceName )
    throw (RuntimeException)
{
    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( FRAMEJOB_SERVICE_NAME ) );
}

Sequence< OUString > SAL_CALL FrameJob_getSupportedServiceNames(  )
    throw (RuntimeException)
{
    Sequence < OUString > aRet(1);
    OUString* pArray = aRet.getArray();
    pArray[0] =  OUString ( RTL_CONSTASCII_USTRINGPARAM ( FRAMEJOB_SERVICE_NAME ) );
    return aRet;
}

Reference< XInterface > SAL_CALL FrameJob_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
    throw( Exception )
{
    return (cppu::OWeakObject*) new FrameJob(rSMgr);
}

// XServiceInfo
OUString SAL_CALL FrameJob::getImplementationName()
    throw (RuntimeException)
{
    return FrameJob_getImplementationName();
}

sal_Bool SAL_CALL FrameJob::supportsService( const OUString& rServiceName )
    throw (RuntimeException)
{
    return FrameJob_supportsService( rServiceName );
}

Sequence< OUString > SAL_CALL FrameJob::getSupportedServiceNames()
    throw (RuntimeException)
{
    return FrameJob_getSupportedServiceNames();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>cppcheck: C-style pointer casting<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * A LibreOffice extension to send the menubar structure through DBusMenu
 *
 * Copyright 2011 Canonical, Ltd.
 * Authors:
 *     Alberto Ruiz <alberto.ruiz@codethink.co.uk>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the the GNU Lesser General Public License version 3, as published by the Free
 * Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
 * SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR PURPOSE.  See the applicable
 * version of the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with this program. If not, see <http://www.gnu.org/licenses/>
 *
 */

#include "FrameJob.hxx"
#include "DesktopJob.hxx"
#include "FrameHelper.hxx"

#define OBJ_PATH_PREFIX "/com/canonical/menu/"

#include <com/sun/star/awt/XSystemDependentWindowPeer.hpp>
#include <com/sun/star/awt/SystemDependentXWindow.hpp>
#include <com/sun/star/awt/XMenu.hpp>
#include <com/sun/star/awt/XMenuExtended.hpp>
#include <com/sun/star/awt/XMenuBar.hpp>
#include <com/sun/star/awt/XPopupMenu.hpp>
#include <com/sun/star/awt/XPopupMenuExtended.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/container/NoSuchElementException.hpp>
#include <com/sun/star/container/XIndexAccess.hpp>
#include <com/sun/star/document/XEventBroadcaster.hpp>
#include <com/sun/star/frame/XController.hpp>
#include <com/sun/star/frame/XLayoutManager.hpp>
#include <com/sun/star/frame/XDispatch.hpp>
#include <com/sun/star/frame/XDispatchHelper.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/frame/XFrameActionListener.hpp>
#include <com/sun/star/frame/XStatusListener.hpp>
#include <com/sun/star/frame/FrameAction.hpp>
#include <com/sun/star/lang/EventObject.hpp>
#include <com/sun/star/lang/SystemDependent.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/ui/XUIConfigurationManager.hpp>
#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/ui/XUIElementSettings.hpp>
#include <com/sun/star/ui/XUIElement.hpp>
#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
#include <com/sun/star/util/URL.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>

#include <iostream>
#include <fstream>

#include <gio/gio.h>
//#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/client.h>
#pragma GCC diagnostic error "-Wignored-qualifiers"
//#pragma GCC diagnostic pop

#include <rtl/process.h>
#include <osl/diagnose.h>

using rtl::OUString;
using rtl::OString;
using rtl::OUStringToOString;

using com::sun::star::awt::KeyEvent;
using com::sun::star::awt::SystemDependentXWindow;
using com::sun::star::awt::XMenu;
using com::sun::star::awt::XMenuExtended;
using com::sun::star::awt::XPopupMenu;
using com::sun::star::awt::XPopupMenuExtended;
using com::sun::star::awt::XMenuBar;
using com::sun::star::awt::XSystemDependentWindowPeer;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::Reference;
using com::sun::star::uno::WeakReference;
using com::sun::star::uno::Any;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Exception;
using com::sun::star::uno::RuntimeException;
using com::sun::star::uno::XInterface;
using com::sun::star::lang::IllegalArgumentException;
using com::sun::star::lang::XMultiServiceFactory;
using com::sun::star::lang::SystemDependent::SYSTEM_XWINDOW;
using com::sun::star::lang::EventObject;
using com::sun::star::beans::NamedValue;
using com::sun::star::beans::PropertyValue;
using com::sun::star::beans::XPropertySet;
using com::sun::star::document::XEventBroadcaster;
using com::sun::star::frame::XFrame;
using com::sun::star::frame::XFrameActionListener;
using com::sun::star::frame::FrameActionEvent;
using com::sun::star::frame::XController;
using com::sun::star::frame::XLayoutManager;
using com::sun::star::frame::XModel;
using com::sun::star::frame::XModuleManager;
using com::sun::star::frame::XDispatch;
using com::sun::star::frame::XDispatchProvider;
using com::sun::star::frame::XDispatchHelper;
using com::sun::star::frame::XStatusListener;
using com::sun::star::frame::FeatureStateEvent;
using com::sun::star::ui::XUIElement;
using com::sun::star::ui::XUIElementSettings;
using com::sun::star::ui::XUIConfigurationManagerSupplier;
using com::sun::star::ui::XUIConfigurationManager;
using com::sun::star::ui::XModuleUIConfigurationManagerSupplier;
using com::sun::star::ui::XAcceleratorConfiguration;
using com::sun::star::util::URL;
using com::sun::star::util::XURLTransformer;
using com::sun::star::container::XIndexContainer;
using com::sun::star::container::XIndexAccess;
using com::sun::star::container::XNameAccess;
using com::sun::star::container::NoSuchElementException;

// This is a helper utility to transform an xid to a /com/canonical/menu/<XID>
// DBUS object path
OString
xid_to_object_path (unsigned long xid)
{

    GString *xid_str = g_string_new ("");
    g_string_printf (xid_str, "%d", (guint32)xid);
    OString object_path = OUStringToOString (OUString::createFromAscii (OBJ_PATH_PREFIX).concat (OUString::createFromAscii(xid_str->str)),
                                             RTL_TEXTENCODING_ASCII_US);
    g_string_free (xid_str, TRUE);
    return object_path;
}

//-------------------------- GObject callbacks -------------------------------//
//This is called when a registrar becomes available. It registers the hides the menubar.
static void
on_registrar_available (GDBusConnection * /*connection*/,
                        const gchar     * /*name*/,
                        const gchar     * /*name_owner*/,
                        gpointer         user_data)
{
    GError     *error = NULL;
    GDBusProxy *proxy;

    FrameHelper *helper = static_cast<FrameHelper*>(user_data);
    unsigned long xid = helper->getXID();

    proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
                                           G_DBUS_PROXY_FLAGS_NONE,
                                           NULL,
                                           "com.canonical.AppMenu.Registrar",
                                           "/com/canonical/AppMenu/Registrar",
                                           "com.canonical.AppMenu.Registrar",
                                           NULL,
                                           &error);
    if (error)
    {
        g_warning ("Couldn't get /com/canonical/AppMenu/Registrar proxy");
        return;
    }

    //TODO: Check if window is registered already
    g_dbus_proxy_call_sync (proxy,
                            "RegisterWindow",
                            g_variant_new ("(uo)",
                                           (guint32)xid,
                                           xid_to_object_path (xid).getStr()),
                            G_DBUS_CALL_FLAGS_NONE,
                            -1,
                            NULL,
                            &error);

    if (error)
    {
        g_warning ("Couldn't call /com/canonical/AppMenu/Registrar.RegisterWindow");
        return;
    }

    //Hide menubar
    Reference < XFrame > xFrame  = helper->getFrame ();
    Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
    Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))),
                                                UNO_QUERY);
    xLayoutManager->hideElement (OUString(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar")));

    return;
}

//This is called when the registrar becomes unavailable. It shows the menubar.
static void
on_registrar_unavailable (GDBusConnection * /*connection*/,
                          const gchar     * /*name*/,
                          gpointer         user_data)
{
    //TODO: Unregister window?

    // Show menubar
    FrameHelper *helper = static_cast<FrameHelper*>(user_data);
    Reference < XFrame > xFrame  = helper->getFrame ();
    Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
    Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))),
                                                UNO_QUERY);
    xLayoutManager->showElement (OUString(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar")));
    return;
}
// ------------------------------- FrameJob --------------------------------------------
Any SAL_CALL FrameJob::execute( const Sequence< NamedValue >& aArguments )
    throw ( IllegalArgumentException, Exception, RuntimeException )
{
    Sequence< NamedValue > lEnv;
    Reference< XModel >    xModel;
    sal_Int32              len    = aArguments.getLength();

    for (int i = 0; i<len; i++)
    {
        if (aArguments[i].Name.equalsAscii("Environment"))
        {
            aArguments[i].Value >>= lEnv;
            break;
        }
    }

    len = lEnv.getLength ();
    for (int i = 0; i<len; i++)
    {
        if (lEnv[i].Name.equalsAscii("Model"))
        {
            lEnv[i].Value >>= xModel;
        }
    }

    //If we didn't get the model we have to quit
    if (!xModel.is())
        return Any();

    Reference< XController > xController( xModel->getCurrentController(), UNO_QUERY);
    if (!xController.is())
        return Any();

    m_xFrame = Reference< XFrame > ( xController->getFrame(), UNO_QUERY);
    if (!m_xFrame.is ())
        return Any();

    exportMenus (m_xFrame);
    return Any();
}

// This function crates a DbusmenuServer and starts the watcher for the AppMenu Registrar bus name
void
FrameJob::exportMenus (Reference < XFrame > xFrame)
{
    //Set the xFrame for this object

    this->m_xFrame = xFrame;

    //Create dbusmenu server object path string
    DbusmenuServer *server = dbusmenu_server_new (xid_to_object_path(getXID (xFrame)).getStr());

    Reference< XPropertySet > frameProps (xFrame, UNO_QUERY);
    Reference < XLayoutManager > xLayoutManager(frameProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager"))),
                                                UNO_QUERY);
    if (!xLayoutManager.is())
    {
        g_object_unref (server);
        return;
    }

    Reference < XUIElement > menuBar(xLayoutManager->getElement (OUString(RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/menubar"))),
                                     UNO_QUERY);
    Reference < XPropertySet > menuPropSet (menuBar, UNO_QUERY);

    if (!menuPropSet.is())
    {
        g_object_unref (server);
        return;
    }

    Reference < XMenu > xMenu (menuPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("XMenuBar"))),
                               UNO_QUERY);

    if (!xMenu.is ())
    {
        g_object_unref (server);
        return;
    }

    //Create a new frame helper to close the server when needed
    FrameHelper *helper = new FrameHelper (m_xMSF, xFrame, server);
    xFrame->addFrameActionListener (Reference < XFrameActionListener > (helper));

    //Populate dbusmenu items and start the server
    DbusmenuMenuitem *root = getRootMenuitem (xMenu, (gpointer)helper);
    dbusmenu_server_set_root (server, root);

    //Listen to the availability of the registrar
    guint watcher = g_bus_watch_name (G_BUS_TYPE_SESSION,
                                      "com.canonical.AppMenu.Registrar",
                                      G_BUS_NAME_WATCHER_FLAGS_NONE,
                                      on_registrar_available,
                                      on_registrar_unavailable,
                                      helper,
                                      NULL);
    helper->setRegistrarWatcher (watcher);
}

//Gets the XID for a given XFrame
unsigned long
FrameJob::getXID (css::uno::Reference < css::frame::XFrame > xFrame)
{
    Reference< XSystemDependentWindowPeer > xWin( xFrame->getContainerWindow(), UNO_QUERY);

    if (!xWin.is())
        return 0;

    sal_Int8 processID[16];
    rtl_getGlobalProcessId( (sal_uInt8*)processID );
    Sequence <signed char> pidSeq (processID, 16);

    SystemDependentXWindow xWindow;
    xWin->getWindowHandle (pidSeq, SYSTEM_XWINDOW) >>= xWindow;

    return xWindow.WindowHandle;
}

// Builds a Dbusmenuitem structure from an XMenu object
DbusmenuMenuitem*
FrameJob::getRootMenuitem (Reference < XMenu > xMenu, gpointer helper)
{

    DbusmenuMenuitem *root = dbusmenu_menuitem_new_with_id (0);
    FrameHelper* fHelper = static_cast<FrameHelper*>(helper);
    fHelper->setRootItem(root);
    fHelper->rebuildMenu (xMenu, root);

    return root;
}

// XJob
OUString FrameJob_getImplementationName ()
    throw (RuntimeException)
{
    return OUString ( RTL_CONSTASCII_USTRINGPARAM ( FRAMEJOB_IMPLEMENTATION_NAME ) );
}

sal_Bool SAL_CALL FrameJob_supportsService( const OUString& ServiceName )
    throw (RuntimeException)
{
    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( FRAMEJOB_SERVICE_NAME ) );
}

Sequence< OUString > SAL_CALL FrameJob_getSupportedServiceNames(  )
    throw (RuntimeException)
{
    Sequence < OUString > aRet(1);
    OUString* pArray = aRet.getArray();
    pArray[0] =  OUString ( RTL_CONSTASCII_USTRINGPARAM ( FRAMEJOB_SERVICE_NAME ) );
    return aRet;
}

Reference< XInterface > SAL_CALL FrameJob_createInstance( const Reference< XMultiServiceFactory > & rSMgr)
    throw( Exception )
{
    return (cppu::OWeakObject*) new FrameJob(rSMgr);
}

// XServiceInfo
OUString SAL_CALL FrameJob::getImplementationName()
    throw (RuntimeException)
{
    return FrameJob_getImplementationName();
}

sal_Bool SAL_CALL FrameJob::supportsService( const OUString& rServiceName )
    throw (RuntimeException)
{
    return FrameJob_supportsService( rServiceName );
}

Sequence< OUString > SAL_CALL FrameJob::getSupportedServiceNames()
    throw (RuntimeException)
{
    return FrameJob_getSupportedServiceNames();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "SetupMeshAction.h"
#include "Parser.h"
#include "MooseMesh.h"
#include "MProblem.h"
#include "ActionWarehouse.h"

// libMesh includes
#include "exodusII_io.h"

const std::string SetupMeshAction::no_file_supplied("(no file supplied)");

template<>
InputParameters validParams<SetupMeshAction>()
{
  InputParameters params = validParams<Action>();
//  params.addParam<int>("dim", "DEPRECATED - Mesh dim can be determined from the file read.");
  params.addParam<std::string>("file", SetupMeshAction::no_file_supplied, "The name of the mesh file to read (required unless using dynamic generation)");
  params.addParam<bool>("second_order", false, "Turns on second order elements for the input mesh");
  params.addParam<std::string>("partitioner", "Specifies a mesh partitioner to use when splitting the mesh for a parallel computation");
  params.addParam<int>("uniform_refine", 0, "Specify the level of uniform refinement applied to the initial mesh");
  params.addParam<std::vector<std::string> >("displacements", "The variables corresponding to the x y z displacements of the mesh.  If this is provided then the displacements will be taken into account during the computation.");
  return params;
}

SetupMeshAction::SetupMeshAction(const std::string & name, InputParameters params) :
    Action(name, params)
{
}

MooseMesh *
SetupMeshAction::createMesh(bool save_exreader)
{
  /**
   * We will use the mesh object to read the file to cut down on
   * I/O conntention.  We still need to use the Exodus reader though
   * for copy_nodal_solutions
   */

  MooseMesh * mesh = NULL;

  if(save_exreader)
    mesh = _parser_handle._mesh;

  std::string mesh_file = getParam<std::string>("file");
  if (mesh_file != no_file_supplied)
  {
    Parser::checkFileReadable(mesh_file);
    mooseAssert(_parser_handle._mesh == NULL, "Mesh already exists, and you are trying to read another");
    mesh = new MooseMesh();

    if(save_exreader)
    {
      // FIXME: We need to support more input formats than Exodus - When we do we'll have to take care
      // to only perform the copy nodal variables action when using the Exodus reader
      _parser_handle._exreader = new ExodusII_IO(*mesh);

      Moose::setup_perf_log.push("Read Mesh","Setup");
      _parser_handle._exreader->read(mesh_file);
      Moose::setup_perf_log.pop("Read Mesh","Setup");
    }
    else
      ExodusII_IO(*mesh).read(mesh_file);
  }

  if (mesh != NULL)
  {

  // FIXME: second order
//  if (getParam<bool>("second_order"))
//    mesh->all_second_order(true);

  // FIXME: usage of partitioners
//  if (getParam<std::string>("partitioner") == "linear")
//    mesh->partitioner() = AutoPtr<Partitioner>(new LinearPartitioner);

    Moose::setup_perf_log.push("Prepare Mesh","Setup");
    mesh->prepare();
    Moose::setup_perf_log.pop("Prepare Mesh","Setup");

    Moose::setup_perf_log.push("Uniformly Refine Mesh","Setup");
    // uniformly refine mesh
    mesh->uniformlyRefine(getParam<int>("uniform_refine"));
    Moose::setup_perf_log.pop("Uniformly Refine Mesh","Setup");

    // FIXME: autosize problem
//  MeshRefinement mesh_refinement(*mesh);
//  if (!autoResizeProblem(mesh, mesh_refinement))
//    mesh_refinement.uniformly_refine(getParam<int>("uniform_refine"));

    Moose::setup_perf_log.push("Initial meshChanged()","Setup");
    mesh->meshChanged();
    Moose::setup_perf_log.pop("Initial meshChanged()","Setup");

    mesh->printInfo();
  }

  return mesh;
}

void
SetupMeshAction::act()
{
  // Create the mesh and save it off
  _parser_handle._mesh = createMesh(true);

  if (isParamValid("displacements"))
  {
    // Create the displaced mesh
    _parser_handle._displaced_mesh = createMesh(false);

    std::vector<std::string> displacements = getParam<std::vector<std::string> >("displacements");
    if (displacements.size() != _parser_handle._mesh->dimension())
      mooseError("Number of displacements and dimension of mesh MUST be the same!");
  }

  // There is no setup execution action satisfied, create the MProblem class by ourselves
  if (Moose::action_warehouse.actionBlocksWithActionBegin("setup_executioner") ==
      Moose::action_warehouse.actionBlocksWithActionEnd("setup_executioner"))
  {
    Moose::setup_perf_log.push("Create MProblem","Setup");
    _parser_handle._problem = new MProblem(*_parser_handle._mesh);
    Moose::setup_perf_log.pop("Create MProblem","Setup");
  }
}

<commit_msg>fix debug assert<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "SetupMeshAction.h"
#include "Parser.h"
#include "MooseMesh.h"
#include "MProblem.h"
#include "ActionWarehouse.h"

// libMesh includes
#include "exodusII_io.h"

const std::string SetupMeshAction::no_file_supplied("(no file supplied)");

template<>
InputParameters validParams<SetupMeshAction>()
{
  InputParameters params = validParams<Action>();
//  params.addParam<int>("dim", "DEPRECATED - Mesh dim can be determined from the file read.");
  params.addParam<std::string>("file", SetupMeshAction::no_file_supplied, "The name of the mesh file to read (required unless using dynamic generation)");
  params.addParam<bool>("second_order", false, "Turns on second order elements for the input mesh");
  params.addParam<std::string>("partitioner", "Specifies a mesh partitioner to use when splitting the mesh for a parallel computation");
  params.addParam<int>("uniform_refine", 0, "Specify the level of uniform refinement applied to the initial mesh");
  params.addParam<std::vector<std::string> >("displacements", "The variables corresponding to the x y z displacements of the mesh.  If this is provided then the displacements will be taken into account during the computation.");
  return params;
}

SetupMeshAction::SetupMeshAction(const std::string & name, InputParameters params) :
    Action(name, params)
{
}

MooseMesh *
SetupMeshAction::createMesh(bool save_exreader)
{
  /**
   * We will use the mesh object to read the file to cut down on
   * I/O conntention.  We still need to use the Exodus reader though
   * for copy_nodal_solutions
   */

  MooseMesh * mesh = NULL;

  if(save_exreader)
    mesh = _parser_handle._mesh;

  std::string mesh_file = getParam<std::string>("file");
  if (mesh_file != no_file_supplied)
  {
    Parser::checkFileReadable(mesh_file);
    mesh = new MooseMesh();

    if(save_exreader)
    {
      // FIXME: We need to support more input formats than Exodus - When we do we'll have to take care
      // to only perform the copy nodal variables action when using the Exodus reader
      _parser_handle._exreader = new ExodusII_IO(*mesh);

      Moose::setup_perf_log.push("Read Mesh","Setup");
      _parser_handle._exreader->read(mesh_file);
      Moose::setup_perf_log.pop("Read Mesh","Setup");
    }
    else
      ExodusII_IO(*mesh).read(mesh_file);
  }

  if (mesh != NULL)
  {

  // FIXME: second order
//  if (getParam<bool>("second_order"))
//    mesh->all_second_order(true);

  // FIXME: usage of partitioners
//  if (getParam<std::string>("partitioner") == "linear")
//    mesh->partitioner() = AutoPtr<Partitioner>(new LinearPartitioner);

    Moose::setup_perf_log.push("Prepare Mesh","Setup");
    mesh->prepare();
    Moose::setup_perf_log.pop("Prepare Mesh","Setup");

    Moose::setup_perf_log.push("Uniformly Refine Mesh","Setup");
    // uniformly refine mesh
    mesh->uniformlyRefine(getParam<int>("uniform_refine"));
    Moose::setup_perf_log.pop("Uniformly Refine Mesh","Setup");

    // FIXME: autosize problem
//  MeshRefinement mesh_refinement(*mesh);
//  if (!autoResizeProblem(mesh, mesh_refinement))
//    mesh_refinement.uniformly_refine(getParam<int>("uniform_refine"));

    Moose::setup_perf_log.push("Initial meshChanged()","Setup");
    mesh->meshChanged();
    Moose::setup_perf_log.pop("Initial meshChanged()","Setup");

    mesh->printInfo();
  }

  return mesh;
}

void
SetupMeshAction::act()
{
  mooseAssert(_parser_handle._mesh == NULL, "Mesh already exists, and you are trying to read another");

  // Create the mesh and save it off
  _parser_handle._mesh = createMesh(true);

  if (isParamValid("displacements"))
  {
    // Create the displaced mesh
    _parser_handle._displaced_mesh = createMesh(false);

    std::vector<std::string> displacements = getParam<std::vector<std::string> >("displacements");
    if (displacements.size() != _parser_handle._mesh->dimension())
      mooseError("Number of displacements and dimension of mesh MUST be the same!");
  }

  // There is no setup execution action satisfied, create the MProblem class by ourselves
  if (Moose::action_warehouse.actionBlocksWithActionBegin("setup_executioner") ==
      Moose::action_warehouse.actionBlocksWithActionEnd("setup_executioner"))
  {
    Moose::setup_perf_log.push("Create MProblem","Setup");
    _parser_handle._problem = new MProblem(*_parser_handle._mesh);
    Moose::setup_perf_log.pop("Create MProblem","Setup");
  }
}

<|endoftext|>


<commit_before>//==============================================================================
// Property editor widget
//==============================================================================

#include "propertyeditorwidget.h"

//==============================================================================

#include <float.h>

//==============================================================================

#include <QHeaderView>
#include <QKeyEvent>
#include <QStandardItem>

//==============================================================================

namespace OpenCOR {
namespace Core {

//==============================================================================

DoubleEditWidget::DoubleEditWidget(QWidget *pParent) :
    QLineEdit(pParent)
{
#ifdef Q_WS_MAC
    setAttribute(Qt::WA_MacShowFocusRect, 0);
    // Note: the above removes the focus border since it messes up the look of
    //       our editor
#endif
}

//==============================================================================

void DoubleEditWidget::keyPressEvent(QKeyEvent *pEvent)
{
    // Check some key combinations

    if (   !(pEvent->modifiers() & Qt::ShiftModifier)
        && !(pEvent->modifiers() & Qt::ControlModifier)
        && !(pEvent->modifiers() & Qt::AltModifier)
        && !(pEvent->modifiers() & Qt::MetaModifier)) {
        // None of the modifiers is selected

        if (pEvent->key() == Qt::Key_Up) {
            // The user wants to go to the previous property

            emit goToPreviousPropertyRequested();

            // Accept the event

            pEvent->accept();
        } else if (pEvent->key() == Qt::Key_Down) {
            // The user wants to go to the next property

            emit goToNextPropertyRequested();

            // Accept the event

            pEvent->accept();
        } else {
            // Default handling of the event

            QLineEdit::keyPressEvent(pEvent);
        }
    } else {
        // Default handling of the event

        QLineEdit::keyPressEvent(pEvent);
    }
}

//==============================================================================

QWidget * PropertyItemDelegate::createEditor(QWidget *pParent,
                                             const QStyleOptionViewItem &pOption,
                                             const QModelIndex &pIndex) const
{
    Q_UNUSED(pOption);
    Q_UNUSED(pIndex);

    // Create and return an editor for our double
    // Note: we don't allow the editing of a string, so...

    DoubleEditWidget *editor = new DoubleEditWidget(pParent);

    // Propagate a few signals

    connect(editor, SIGNAL(goToPreviousPropertyRequested()),
            this, SIGNAL(goToPreviousPropertyRequested()));
    connect(editor, SIGNAL(goToNextPropertyRequested()),
            this, SIGNAL(goToNextPropertyRequested()));

    // Let people know that there is a new editor

    emit openEditor(editor);

    // Return the editor

    return editor;
}

//==============================================================================

bool PropertyItemDelegate::eventFilter(QObject *pObject, QEvent *pEvent)
{
    // We want to handle key events ourselves, so...

    if(pEvent->type()==QEvent::KeyPress)
        return false;
    else
        return QStyledItemDelegate::eventFilter(pObject, pEvent);
}

//==============================================================================

PropertyItem::PropertyItem(const Type &pType, const QString &pValue,
                           const bool &pEditable) :
    QStandardItem(pValue),
    mType(pType)
{
    // Check whether the item should be editable

    if (!pEditable)
        setFlags(flags() & ~Qt::ItemIsEditable);
}

//==============================================================================

int PropertyItem::type() const
{
    // Return the property item's type

    return mType;
}

//==============================================================================

PropertyEditorWidget::PropertyEditorWidget(QWidget *pParent) :
    TreeViewWidget(pParent),
    mPropertyEditor(0),
    mPropertyRow(-1)
{
    // Create our item delegate and set it, after making sure that we handle a
    // few of its signals

    mPropertyItemDelegate = new PropertyItemDelegate();

    connect(mPropertyItemDelegate, SIGNAL(openEditor(QWidget *)),
            this, SLOT(editorOpened(QWidget *)));
    connect(mPropertyItemDelegate, SIGNAL(closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint)),
            this, SLOT(editorClosed()));

    connect(mPropertyItemDelegate, SIGNAL(goToPreviousPropertyRequested()),
            this, SLOT(goToPreviousProperty()));
    connect(mPropertyItemDelegate, SIGNAL(goToNextPropertyRequested()),
            this, SLOT(goToNextProperty()));

    setItemDelegate(mPropertyItemDelegate);

    // Further customise ourselves

    setSelectionMode(QAbstractItemView::SingleSelection);
}

//==============================================================================

void PropertyEditorWidget::setModel(QAbstractItemModel *pModel)
{
    // Stop tracking data changes in the old model

    disconnect(model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
               this, SLOT(updateHeight()));

    // Update our model

    TreeViewWidget::setModel(pModel);

    // Update our height following data changes

    connect(model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
            this, SLOT(updateHeight()));
}

//==============================================================================

void PropertyEditorWidget::resizeColumnsToContents()
{
    // Resize all our columns to their contents

    if (!model())
        // We don't have a model associated to us, so...

        return;

    // Resize our columns so that their contents fits perfectly

    for (int i = 0; i < model()->columnCount(); ++i)
        resizeColumnToContents(i);
}

//==============================================================================

PropertyItem * PropertyEditorWidget::newNonEditableString(const QString &pValue)
{
    // Create and return a non-editable item

    return new PropertyItem(PropertyItem::String, pValue, false);
}

//==============================================================================

PropertyItem * PropertyEditorWidget::newEditableDouble(const double &pValue)
{
    // Create and return an editable item

    return new PropertyItem(PropertyItem::Double, QString::number(pValue));
}

//==============================================================================

void PropertyEditorWidget::keyPressEvent(QKeyEvent *pEvent)
{
    // Check some key combinations

    if (   (pEvent->modifiers() & Qt::ControlModifier)
        && (pEvent->key() == Qt::Key_A)) {
        // The user wants to select everything which we don't want to allow,
        // so just accept the event...

        pEvent->accept();
    } else if (   (pEvent->key() == Qt::Key_Return)
               || (pEvent->key() == Qt::Key_Enter)) {
        // The user wants to start/stop editing the property

        if (mPropertyEditor)
            // We are currently editing the property, so stop editing it

            editProperty(-1);
        else
            // We are not currently editing the property, so start editing it
            // it
            // Note: we could use mPropertyRow, but if it was to be equal to -1
            //       we would have to use currentIndex().row(), so we might as
            //       well use the latter all the time...

            editProperty(currentIndex().row());

        // Accept the event

        pEvent->accept();
    } else if (pEvent->key() == Qt::Key_Escape) {
        // The user wants to cancel the editing of the property

        cancelPropertyEditing();

        // Accept the event

        pEvent->accept();
    } else if (   !(pEvent->modifiers() & Qt::ShiftModifier)
               && !(pEvent->modifiers() & Qt::ControlModifier)
               && !(pEvent->modifiers() & Qt::AltModifier)
               && !(pEvent->modifiers() & Qt::MetaModifier)) {
        // None of the modifiers is selected

        if (pEvent->key() == Qt::Key_Up) {
            // The user wants to go the previous property

            goToPreviousProperty();

            // Accept the event

            pEvent->accept();
        } else if (pEvent->key() == Qt::Key_Down) {
            // The user wants to go to the next property

            goToNextProperty();

            // Accept the event

            pEvent->accept();
        } else {
            // Default handling of the event

            TreeViewWidget::keyPressEvent(pEvent);
        }
    } else {
        // Default handling of the event

        TreeViewWidget::keyPressEvent(pEvent);
    }
}

//==============================================================================

void PropertyEditorWidget::mousePressEvent(QMouseEvent *pEvent)
{
    // Start/stop the editing of the property

    int propertyRow = indexAt(pEvent->pos()).row();

    if (mPropertyEditor) {
        // We are already editing a property, so either stop its editing or
        // start editing anoher property

        if (propertyRow != mPropertyRow)
            // We want to edit another property

            editProperty(propertyRow);
        else
            // We want to stop editing the property

            editProperty(-1);
    } else {
        // We are not currently editing a property, so start editing the current
        // one

        editProperty(propertyRow);
    }

    // Accept the event

    pEvent->accept();
}

//==============================================================================

void PropertyEditorWidget::mouseMoveEvent(QMouseEvent *pEvent)
{
    // Edit the property, but only if we want to edit a new one

    int propertyRow = indexAt(pEvent->pos()).row();

    if ((propertyRow != -1) && (propertyRow != mPropertyRow))
        editProperty(propertyRow);

    // Accept the event

    pEvent->accept();
}

//==============================================================================

void PropertyEditorWidget::updateHeight()
{
    // Update our height based on the number of rows

    int newHeight = header()->height();
    QAbstractItemModel *itemModel = model();

    for (int i = 0; i < itemModel->rowCount(); ++i)
        newHeight += rowHeight(itemModel->index(i, 0));

    setFixedHeight(newHeight);
}

//==============================================================================

void PropertyEditorWidget::editorOpened(QWidget *pEditor)
{
    // We are starting the editing of a property, so use its editor as our focus
    // proxy and make sure that it immediately gets the focus
    // Note: if we were not to immediately give the editor the focus, then the
    //       central widget would give the focus to the previously focused
    //       widget (see CentralWidget::updateGui()), so...

    setFocusProxy(pEditor);

    pEditor->setFocus();

    // Keep track of some information about the property

    mPropertyEditor = pEditor;
    mPropertyRow    = currentIndex().row();
}

//==============================================================================

void PropertyEditorWidget::editorClosed()
{
    // We have stopped editing a property, so reset our focus proxy and make
    // sure that we get the focus (see editorOpened() above for the reason)

    setFocusProxy(0);

    setFocus();

    // Reset some information about the property

    mPropertyEditor = 0;
}

//==============================================================================

void PropertyEditorWidget::editProperty(const int &pPropertyRow,
                                        const bool &pCommitData)
{
    // We want to edit a new property, so first stop the editing of the current
    // one, if any

    if (mPropertyEditor) {
        // A property is currently being edited, so commit its data and then
        // close its corresponding editor

        if (pCommitData)
            commitData(mPropertyEditor);

        closeEditor(mPropertyEditor,
                    pCommitData?
                        QAbstractItemDelegate::SubmitModelCache:
                        QAbstractItemDelegate::RevertModelCache);

        // Update our state
        // Note: this is very important otherwise our state will remain that of
        //       editing...

        setState(NoState);

        // Call editorClosed() to reset a few things

        editorClosed();
    }

    // Now that the editing of our old property has finished, we can start the
    // editing of our new property, if any

    if (pPropertyRow != -1) {
        // There is a new property to edit, so first select it

        selectItem(pPropertyRow);

        // Now, we can 'properly' edit the property's value
        // Note: the property's value's column is always 1...

        edit(model()->index(pPropertyRow, 1));
    }
}

//==============================================================================

void PropertyEditorWidget::cancelPropertyEditing()
{
    // The user wants to cancel the editing of the property

    editProperty(-1, false);
}

//==============================================================================

void PropertyEditorWidget::goToNeighbouringProperty(const int &pShift)
{
    // Go to the previous/next property

    int row = currentIndex().row()+pShift;

    if ((row >= 0) && (row < model()->rowCount()))
        // The previous/next property exists, so we can edit it

        editProperty(row);
}

//==============================================================================

void PropertyEditorWidget::goToPreviousProperty()
{
    // Go to the previous property

    goToNeighbouringProperty(-1);
}

//==============================================================================

void PropertyEditorWidget::goToNextProperty()
{
    // Go to the next property

    goToNeighbouringProperty(1);
}

//==============================================================================

}   // namespace Core
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>A minor fix for PropertyEditorWidget (#112).<commit_after>//==============================================================================
// Property editor widget
//==============================================================================

#include "propertyeditorwidget.h"

//==============================================================================

#include <float.h>

//==============================================================================

#include <QHeaderView>
#include <QKeyEvent>
#include <QStandardItem>

//==============================================================================

namespace OpenCOR {
namespace Core {

//==============================================================================

DoubleEditWidget::DoubleEditWidget(QWidget *pParent) :
    QLineEdit(pParent)
{
#ifdef Q_WS_MAC
    setAttribute(Qt::WA_MacShowFocusRect, 0);
    // Note: the above removes the focus border since it messes up the look of
    //       our editor
#endif
}

//==============================================================================

void DoubleEditWidget::keyPressEvent(QKeyEvent *pEvent)
{
    // Check some key combinations

    if (   !(pEvent->modifiers() & Qt::ShiftModifier)
        && !(pEvent->modifiers() & Qt::ControlModifier)
        && !(pEvent->modifiers() & Qt::AltModifier)
        && !(pEvent->modifiers() & Qt::MetaModifier)) {
        // None of the modifiers is selected

        if (pEvent->key() == Qt::Key_Up) {
            // The user wants to go to the previous property

            emit goToPreviousPropertyRequested();

            // Accept the event

            pEvent->accept();
        } else if (pEvent->key() == Qt::Key_Down) {
            // The user wants to go to the next property

            emit goToNextPropertyRequested();

            // Accept the event

            pEvent->accept();
        } else {
            // Default handling of the event

            QLineEdit::keyPressEvent(pEvent);
        }
    } else {
        // Default handling of the event

        QLineEdit::keyPressEvent(pEvent);
    }
}

//==============================================================================

QWidget * PropertyItemDelegate::createEditor(QWidget *pParent,
                                             const QStyleOptionViewItem &pOption,
                                             const QModelIndex &pIndex) const
{
    Q_UNUSED(pOption);
    Q_UNUSED(pIndex);

    // Create and return an editor for our double
    // Note: we don't allow the editing of a string, so...

    DoubleEditWidget *editor = new DoubleEditWidget(pParent);

    // Propagate a few signals

    connect(editor, SIGNAL(goToPreviousPropertyRequested()),
            this, SIGNAL(goToPreviousPropertyRequested()));
    connect(editor, SIGNAL(goToNextPropertyRequested()),
            this, SIGNAL(goToNextPropertyRequested()));

    // Let people know that there is a new editor

    emit openEditor(editor);

    // Return the editor

    return editor;
}

//==============================================================================

bool PropertyItemDelegate::eventFilter(QObject *pObject, QEvent *pEvent)
{
    // We want to handle key events ourselves, so...

    if(pEvent->type()==QEvent::KeyPress)
        return false;
    else
        return QStyledItemDelegate::eventFilter(pObject, pEvent);
}

//==============================================================================

PropertyItem::PropertyItem(const Type &pType, const QString &pValue,
                           const bool &pEditable) :
    QStandardItem(pValue),
    mType(pType)
{
    // Check whether the item should be editable

    if (!pEditable)
        setFlags(flags() & ~Qt::ItemIsEditable);
}

//==============================================================================

int PropertyItem::type() const
{
    // Return the property item's type

    return mType;
}

//==============================================================================

PropertyEditorWidget::PropertyEditorWidget(QWidget *pParent) :
    TreeViewWidget(pParent),
    mPropertyEditor(0),
    mPropertyRow(-1)
{
    // Create our item delegate and set it, after making sure that we handle a
    // few of its signals

    mPropertyItemDelegate = new PropertyItemDelegate();

    connect(mPropertyItemDelegate, SIGNAL(openEditor(QWidget *)),
            this, SLOT(editorOpened(QWidget *)));
    connect(mPropertyItemDelegate, SIGNAL(closeEditor(QWidget *, QAbstractItemDelegate::EndEditHint)),
            this, SLOT(editorClosed()));

    connect(mPropertyItemDelegate, SIGNAL(goToPreviousPropertyRequested()),
            this, SLOT(goToPreviousProperty()));
    connect(mPropertyItemDelegate, SIGNAL(goToNextPropertyRequested()),
            this, SLOT(goToNextProperty()));

    setItemDelegate(mPropertyItemDelegate);

    // Further customise ourselves

    setSelectionMode(QAbstractItemView::SingleSelection);
}

//==============================================================================

void PropertyEditorWidget::setModel(QAbstractItemModel *pModel)
{
    // Stop tracking data changes in the old model

    if (model())
        disconnect(model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
                   this, SLOT(updateHeight()));

    // Update our model

    TreeViewWidget::setModel(pModel);

    // Update our height following data changes

    connect(model(), SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
            this, SLOT(updateHeight()));
}

//==============================================================================

void PropertyEditorWidget::resizeColumnsToContents()
{
    // Resize all our columns to their contents

    if (!model())
        // We don't have a model associated to us, so...

        return;

    // Resize our columns so that their contents fits perfectly

    for (int i = 0; i < model()->columnCount(); ++i)
        resizeColumnToContents(i);
}

//==============================================================================

PropertyItem * PropertyEditorWidget::newNonEditableString(const QString &pValue)
{
    // Create and return a non-editable item

    return new PropertyItem(PropertyItem::String, pValue, false);
}

//==============================================================================

PropertyItem * PropertyEditorWidget::newEditableDouble(const double &pValue)
{
    // Create and return an editable item

    return new PropertyItem(PropertyItem::Double, QString::number(pValue));
}

//==============================================================================

void PropertyEditorWidget::keyPressEvent(QKeyEvent *pEvent)
{
    // Check some key combinations

    if (   (pEvent->modifiers() & Qt::ControlModifier)
        && (pEvent->key() == Qt::Key_A)) {
        // The user wants to select everything which we don't want to allow,
        // so just accept the event...

        pEvent->accept();
    } else if (   (pEvent->key() == Qt::Key_Return)
               || (pEvent->key() == Qt::Key_Enter)) {
        // The user wants to start/stop editing the property

        if (mPropertyEditor)
            // We are currently editing the property, so stop editing it

            editProperty(-1);
        else
            // We are not currently editing the property, so start editing it
            // it
            // Note: we could use mPropertyRow, but if it was to be equal to -1
            //       we would have to use currentIndex().row(), so we might as
            //       well use the latter all the time...

            editProperty(currentIndex().row());

        // Accept the event

        pEvent->accept();
    } else if (pEvent->key() == Qt::Key_Escape) {
        // The user wants to cancel the editing of the property

        cancelPropertyEditing();

        // Accept the event

        pEvent->accept();
    } else if (   !(pEvent->modifiers() & Qt::ShiftModifier)
               && !(pEvent->modifiers() & Qt::ControlModifier)
               && !(pEvent->modifiers() & Qt::AltModifier)
               && !(pEvent->modifiers() & Qt::MetaModifier)) {
        // None of the modifiers is selected

        if (pEvent->key() == Qt::Key_Up) {
            // The user wants to go the previous property

            goToPreviousProperty();

            // Accept the event

            pEvent->accept();
        } else if (pEvent->key() == Qt::Key_Down) {
            // The user wants to go to the next property

            goToNextProperty();

            // Accept the event

            pEvent->accept();
        } else {
            // Default handling of the event

            TreeViewWidget::keyPressEvent(pEvent);
        }
    } else {
        // Default handling of the event

        TreeViewWidget::keyPressEvent(pEvent);
    }
}

//==============================================================================

void PropertyEditorWidget::mousePressEvent(QMouseEvent *pEvent)
{
    // Start/stop the editing of the property

    int propertyRow = indexAt(pEvent->pos()).row();

    if (mPropertyEditor) {
        // We are already editing a property, so either stop its editing or
        // start editing anoher property

        if (propertyRow != mPropertyRow)
            // We want to edit another property

            editProperty(propertyRow);
        else
            // We want to stop editing the property

            editProperty(-1);
    } else {
        // We are not currently editing a property, so start editing the current
        // one

        editProperty(propertyRow);
    }

    // Accept the event

    pEvent->accept();
}

//==============================================================================

void PropertyEditorWidget::mouseMoveEvent(QMouseEvent *pEvent)
{
    // Edit the property, but only if we want to edit a new one

    int propertyRow = indexAt(pEvent->pos()).row();

    if ((propertyRow != -1) && (propertyRow != mPropertyRow))
        editProperty(propertyRow);

    // Accept the event

    pEvent->accept();
}

//==============================================================================

void PropertyEditorWidget::updateHeight()
{
    // Update our height based on the number of rows

    int newHeight = header()->height();
    QAbstractItemModel *itemModel = model();

    for (int i = 0; i < itemModel->rowCount(); ++i)
        newHeight += rowHeight(itemModel->index(i, 0));

    setFixedHeight(newHeight);
}

//==============================================================================

void PropertyEditorWidget::editorOpened(QWidget *pEditor)
{
    // We are starting the editing of a property, so use its editor as our focus
    // proxy and make sure that it immediately gets the focus
    // Note: if we were not to immediately give the editor the focus, then the
    //       central widget would give the focus to the previously focused
    //       widget (see CentralWidget::updateGui()), so...

    setFocusProxy(pEditor);

    pEditor->setFocus();

    // Keep track of some information about the property

    mPropertyEditor = pEditor;
    mPropertyRow    = currentIndex().row();
}

//==============================================================================

void PropertyEditorWidget::editorClosed()
{
    // We have stopped editing a property, so reset our focus proxy and make
    // sure that we get the focus (see editorOpened() above for the reason)

    setFocusProxy(0);

    setFocus();

    // Reset some information about the property

    mPropertyEditor = 0;
}

//==============================================================================

void PropertyEditorWidget::editProperty(const int &pPropertyRow,
                                        const bool &pCommitData)
{
    // We want to edit a new property, so first stop the editing of the current
    // one, if any

    if (mPropertyEditor) {
        // A property is currently being edited, so commit its data and then
        // close its corresponding editor

        if (pCommitData)
            commitData(mPropertyEditor);

        closeEditor(mPropertyEditor,
                    pCommitData?
                        QAbstractItemDelegate::SubmitModelCache:
                        QAbstractItemDelegate::RevertModelCache);

        // Update our state
        // Note: this is very important otherwise our state will remain that of
        //       editing...

        setState(NoState);

        // Call editorClosed() to reset a few things

        editorClosed();
    }

    // Now that the editing of our old property has finished, we can start the
    // editing of our new property, if any

    if (pPropertyRow != -1) {
        // There is a new property to edit, so first select it

        selectItem(pPropertyRow);

        // Now, we can 'properly' edit the property's value
        // Note: the property's value's column is always 1...

        edit(model()->index(pPropertyRow, 1));
    }
}

//==============================================================================

void PropertyEditorWidget::cancelPropertyEditing()
{
    // The user wants to cancel the editing of the property

    editProperty(-1, false);
}

//==============================================================================

void PropertyEditorWidget::goToNeighbouringProperty(const int &pShift)
{
    // Go to the previous/next property

    int row = currentIndex().row()+pShift;

    if ((row >= 0) && (row < model()->rowCount()))
        // The previous/next property exists, so we can edit it

        editProperty(row);
}

//==============================================================================

void PropertyEditorWidget::goToPreviousProperty()
{
    // Go to the previous property

    goToNeighbouringProperty(-1);
}

//==============================================================================

void PropertyEditorWidget::goToNextProperty()
{
    // Go to the next property

    goToNeighbouringProperty(1);
}

//==============================================================================

}   // namespace Core
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008 Torsten Rahn <tackat@kde.org>"
//

#include "MarbleGeoDataPlugin.h"

#include <QtCore/QDebug>
#include <QtGui/QColor>
#include <QtGui/QBrush>
#include <QtGui/QPen>
#include <QtGui/QPixmap>
#include <QtGui/QRadialGradient>

#include "MarbleDirs.h"
#include "MarbleDataFacade.h"
#include "MarbleGeoDataModel.h"
#include "GeoPainter.h"

#include "GeoDataCoordinates.h"
#include "GeoDataPolygon.h"
#include "GeoDataPlacemark.h"
#include "GeoDataFeature.h"
#include "GeoDataContainer.h"
#include "GeoDataDocument.h"
#include "GeoDataStyle.h"
#include "GeoDataStyleMap.h"
#include "GeoDataPolyStyle.h"
#include "GeoDataLineStyle.h"
#include "GeoDataParser.h"

namespace Marble
{

MarbleGeoDataPlugin::~MarbleGeoDataPlugin()
{
    delete( m_view );
}

QStringList MarbleGeoDataPlugin::backendTypes() const
{
    return QStringList( "geodata" );
}

QString MarbleGeoDataPlugin::renderPolicy() const
{
    return QString( "ALWAYS" );
}

QStringList MarbleGeoDataPlugin::renderPosition() const
{
    return QStringList( "ALWAYS_ON_TOP" );
}

QString MarbleGeoDataPlugin::name() const
{
    return tr( "GeoData Plugin" );
}

QString MarbleGeoDataPlugin::guiString() const
{
    return tr( "&GeoData Plugin" );
}

QString MarbleGeoDataPlugin::nameId() const
{
    return QString( "GeoData-plugin" );
}

QString MarbleGeoDataPlugin::description() const
{
    return tr( "This is a simple test plugin." );
}

QIcon MarbleGeoDataPlugin::icon () const
{
    return QIcon();
}

void MarbleGeoDataPlugin::initialize ()
{
    m_view = new MarbleGeoDataView();
}

bool MarbleGeoDataPlugin::isInitialized () const
{
    return true;
}
bool MarbleGeoDataPlugin::render( GeoPainter *painter, ViewportParams *viewport, const QString& renderPos, GeoSceneLayer * layer )
{
    if( !dataFacade()->renderModel() )
        return false;

    if( !m_view->model() ) m_view->setModel( dataFacade()->renderModel() );
    m_view->setGeoPainter( painter );
    return true;
}

}

Q_EXPORT_PLUGIN2( MarbleGeoDataPlugin, Marble::MarbleGeoDataPlugin )

#include "MarbleGeoDataPlugin.moc"
<commit_msg>some security testings<commit_after>//
// This file is part of the Marble Desktop Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008 Torsten Rahn <tackat@kde.org>"
//

#include "MarbleGeoDataPlugin.h"

#include <QtCore/QDebug>
#include <QtGui/QColor>
#include <QtGui/QBrush>
#include <QtGui/QPen>
#include <QtGui/QPixmap>
#include <QtGui/QRadialGradient>

#include "MarbleDirs.h"
#include "MarbleDataFacade.h"
#include "MarbleGeoDataModel.h"
#include "GeoPainter.h"

#include "GeoDataCoordinates.h"
#include "GeoDataPolygon.h"
#include "GeoDataPlacemark.h"
#include "GeoDataFeature.h"
#include "GeoDataContainer.h"
#include "GeoDataDocument.h"
#include "GeoDataStyle.h"
#include "GeoDataStyleMap.h"
#include "GeoDataPolyStyle.h"
#include "GeoDataLineStyle.h"
#include "GeoDataParser.h"

namespace Marble
{

MarbleGeoDataPlugin::~MarbleGeoDataPlugin()
{
    delete( m_view );
}

QStringList MarbleGeoDataPlugin::backendTypes() const
{
    return QStringList( "geodata" );
}

QString MarbleGeoDataPlugin::renderPolicy() const
{
    return QString( "ALWAYS" );
}

QStringList MarbleGeoDataPlugin::renderPosition() const
{
    return QStringList( "ALWAYS_ON_TOP" );
}

QString MarbleGeoDataPlugin::name() const
{
    return tr( "GeoData Plugin" );
}

QString MarbleGeoDataPlugin::guiString() const
{
    return tr( "&GeoData Plugin" );
}

QString MarbleGeoDataPlugin::nameId() const
{
    return QString( "GeoData-plugin" );
}

QString MarbleGeoDataPlugin::description() const
{
    return tr( "This is a simple test plugin." );
}

QIcon MarbleGeoDataPlugin::icon () const
{
    return QIcon();
}

void MarbleGeoDataPlugin::initialize ()
{
    m_view = new MarbleGeoDataView();
}

bool MarbleGeoDataPlugin::isInitialized () const
{
    return true;
}

bool MarbleGeoDataPlugin::render( GeoPainter *painter, ViewportParams *viewport, const QString& renderPos, GeoSceneLayer * layer )
{
    if( !dataFacade() || !dataFacade()->renderModel() )
        return false;

    if( !m_view->model() ) m_view->setModel( dataFacade()->renderModel() );
    m_view->setGeoPainter( painter );
    return true;
}

}

Q_EXPORT_PLUGIN2( MarbleGeoDataPlugin, Marble::MarbleGeoDataPlugin )

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


<commit_before>//==============================================================================
// IDA solver class
//==============================================================================

#include "idasolver.h"

//==============================================================================

#include "ida/ida.h"
#include "ida/ida_dense.h"
#include "ida/ida_impl.h"

//==============================================================================

namespace OpenCOR {
namespace IDASolver {

//==============================================================================

static const int SizeOfDouble = sizeof(double);

//==============================================================================

// Default IDA parameter values
// Note #1: a maximum step of 0 means that there is no maximum step as such and
//          that IDA can use whatever step it sees fit...
// Note #2: IDA's default maximum number of steps is 500 which ought to be big
//          enough in most cases...

static const double DefaultMaximumStep = 0;
static const int DefaultMaximumNumberOfSteps = 500;
static const double DefaultRelativeTolerance = 1e-7;
static const double DefaultAbsoluteTolerance = 1e-7;

//==============================================================================

int residualFunction(double pVoi, N_Vector pStates, N_Vector pRates,
                     N_Vector pResiduals, void *pUserData)
{
    // Compute the model

    IdaSolverUserData *userData = reinterpret_cast<IdaSolverUserData *>(pUserData);

    double *states    = N_VGetArrayPointer(pStates);
    double *rates     = N_VGetArrayPointer(pRates);
    double *residuals = N_VGetArrayPointer(pResiduals);

    userData->computeEssentialVariables(pVoi, userData->constants, rates,
                                        states, userData->algebraic,
                                        userData->condVar);

    userData->computeResiduals(pVoi, userData->constants, rates, states,
                               userData->algebraic, userData->condVar,
                               residuals);

    // Everything went fine, so...

    return 0;
}

//==============================================================================

int rootFindingFunction(double pVoi, N_Vector pStates, N_Vector pRates,
                        double *pRoots, void *pUserData)
{
    // Do the root finding

    IdaSolverUserData *userData = reinterpret_cast<IdaSolverUserData *>(pUserData);

    userData->computeRootInformation(pVoi, userData->constants,
                                     N_VGetArrayPointer(pRates),
                                     N_VGetArrayPointer(pStates),
                                     userData->algebraic, pRoots);

    // Everything went fine, so...

    return 0;
}

//==============================================================================

void errorHandler(int pErrorCode, const char *pModule, const char *pFunction,
                  char *pErrorMsg, void *pUserData)
{
    Q_UNUSED(pModule);
    Q_UNUSED(pFunction);

    if (pErrorCode != IDA_WARNING)
        // IDA really generated an error, so forward it to the IdaSolver object

        reinterpret_cast<IdaSolver *>(pUserData)->emitError(pErrorMsg);
}

//==============================================================================

IdaSolver::IdaSolver() :
    mSolver(0),
    mStatesVector(0),
    mRatesVector(0),
    mMaximumStep(DefaultMaximumStep),
    mMaximumNumberOfSteps(DefaultMaximumNumberOfSteps),
    mRelativeTolerance(DefaultRelativeTolerance),
    mAbsoluteTolerance(DefaultAbsoluteTolerance)
{
}

//==============================================================================

IdaSolver::~IdaSolver()
{
    // Delete some internal objects

    N_VDestroy_Serial(mStatesVector);
    N_VDestroy_Serial(mRatesVector);
    IDAFree(&mSolver);
}

//==============================================================================

void IdaSolver::initialize(const double &pVoiStart, const double &pVoiEnd,
                           const int &pStatesCount, const int &pCondVarCount,
                           double *pConstants, double *pRates, double *pStates,
                           double *pAlgebraic, double *pCondVar,
                           ComputeEssentialVariablesFunction pComputeEssentialVariables,
                           ComputeResidualsFunction pComputeResiduals,
                           ComputeRootInformationFunction pComputeRootInformation,
                           ComputeStateInformationFunction pComputeStateInformation)
{
    static const double VoiEpsilon = 1e-9;

    if (!mSolver) {
        // Initialise the ODE solver itself

        OpenCOR::CoreSolver::CoreDaeSolver::initialize(pVoiStart, pVoiEnd,
                                                       pStatesCount,
                                                       pCondVarCount,
                                                       pConstants, pRates,
                                                       pStates, pAlgebraic,
                                                       pCondVar,
                                                       pComputeEssentialVariables,
                                                       pComputeResiduals,
                                                       pComputeRootInformation,
                                                       pComputeStateInformation);

        // Retrieve some of the IDA properties

        mMaximumStep = mProperties.contains(MaximumStepProperty)?
                           mProperties.value(MaximumStepProperty).toDouble():
                           DefaultMaximumStep;

        mMaximumNumberOfSteps = mProperties.contains(MaximumNumberOfStepsProperty)?
                                    mProperties.value(MaximumNumberOfStepsProperty).toDouble():
                                    DefaultMaximumNumberOfSteps;

        mRelativeTolerance = mProperties.contains(RelativeToleranceProperty)?
                                 mProperties.value(RelativeToleranceProperty).toDouble():
                                 DefaultRelativeTolerance;
        mAbsoluteTolerance = mProperties.contains(AbsoluteToleranceProperty)?
                                 mProperties.value(AbsoluteToleranceProperty).toDouble():
                                 DefaultAbsoluteTolerance;

        // Create the IDA solver

        mSolver = IDACreate();

        // Use our own error handler

        IDASetErrHandlerFn(mSolver, errorHandler, this);

        // Create the states vector

        mStatesVector = N_VMake_Serial(pStatesCount, pStates);
        mRatesVector  = N_VMake_Serial(pStatesCount, pRates);

        // Initialise the IDA solver

        IDAInit(mSolver, residualFunction, pVoiStart,
                mStatesVector, mRatesVector);

        IDARootInit(mSolver, pCondVarCount, rootFindingFunction);
        //---GRY--- NEED TO CHECK THAT OUR IDA CODE WORKS AS EXPECTED BY TRYING
        //          IT OUT ON A MODEL WHICH NEEDS ROOT FINDING...

        // Set some user data

        mUserData.constants = pConstants;
        mUserData.algebraic = pAlgebraic;
        mUserData.condVar   = pCondVar;

        mUserData.computeResiduals          = pComputeResiduals;
        mUserData.computeEssentialVariables = pComputeEssentialVariables;
        mUserData.computeRootInformation    = pComputeRootInformation;

        IDASetUserData(mSolver, &mUserData);

        // Set the linear solver

        IDADense(mSolver, pStatesCount);

        // Set the maximum step

        IDASetMaxStep(mSolver, mMaximumStep);

        // Set the maximum number of steps

        IDASetMaxNumSteps(mSolver, mMaximumNumberOfSteps);

        // Set the relative and absolute tolerances

        IDASStolerances(mSolver, mRelativeTolerance, mAbsoluteTolerance);

        // Compute the model's initial conditions
        // Note: this requires retrieving the model's state information, setting
        //       the IDA object's id vector and then calling IDACalcIC()...

        double *id = new double[pStatesCount];

        pComputeStateInformation(id);

        N_Vector idVector = N_VMake_Serial(pStatesCount, id);

        IDASetId(mSolver, idVector);
        IDACalcIC(mSolver, IDA_YA_YDP_INIT,
                  pVoiStart+((pVoiEnd-pVoiStart > 0)?VoiEpsilon:-VoiEpsilon));

        N_VDestroy_Serial(idVector);
        delete[] id;
    } else {
        // Reinitialise the IDA object

        IDAReInit(mSolver, pVoiStart, mStatesVector, mRatesVector);

        // Recompute the model's new initial conditions

        IDACalcIC(mSolver, IDA_YA_YDP_INIT,
                  pVoiStart+((pVoiEnd-pVoiStart > 0)?VoiEpsilon:-VoiEpsilon));
    }
}

//==============================================================================

void IdaSolver::solve(double &pVoi, const double &pVoiEnd) const
{
    Q_ASSERT(mStatesCount > 0);
    Q_ASSERT(mCondVarCount >= 0);
    Q_ASSERT(mConstants);
    Q_ASSERT(mRates);
    Q_ASSERT(mStates);
    Q_ASSERT(mAlgebraic);
    Q_ASSERT(mCondVar);

    // Solve the model

    IDASolve(mSolver, pVoiEnd, &pVoi, mStatesVector, mRatesVector, IDA_NORMAL);
}

//==============================================================================

bool IdaSolver::isValidProperty(const QString &pName) const
{
    // Check whether the property name is known to us

    return    !pName.compare(MaximumStepProperty)
           || !pName.compare(MaximumNumberOfStepsProperty)
           || !pName.compare(RelativeToleranceProperty)
           || !pName.compare(AbsoluteToleranceProperty);
}

//==============================================================================

}   // namespace IDASolver
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Minor cleaning up for our DAE solver (#108).<commit_after>//==============================================================================
// IDA solver class
//==============================================================================

#include "idasolver.h"

//==============================================================================

#include "ida/ida.h"
#include "ida/ida_dense.h"
#include "ida/ida_impl.h"

//==============================================================================

namespace OpenCOR {
namespace IDASolver {

//==============================================================================

static const int SizeOfDouble = sizeof(double);

//==============================================================================

// Default IDA parameter values
// Note #1: a maximum step of 0 means that there is no maximum step as such and
//          that IDA can use whatever step it sees fit...
// Note #2: IDA's default maximum number of steps is 500 which ought to be big
//          enough in most cases...

static const double DefaultMaximumStep = 0;
static const int DefaultMaximumNumberOfSteps = 500;
static const double DefaultRelativeTolerance = 1e-7;
static const double DefaultAbsoluteTolerance = 1e-7;

//==============================================================================

int residualFunction(double pVoi, N_Vector pStates, N_Vector pRates,
                     N_Vector pResiduals, void *pUserData)
{
    // Compute the model

    IdaSolverUserData *userData = reinterpret_cast<IdaSolverUserData *>(pUserData);

    double *states    = N_VGetArrayPointer(pStates);
    double *rates     = N_VGetArrayPointer(pRates);
    double *residuals = N_VGetArrayPointer(pResiduals);

    userData->computeEssentialVariables(pVoi, userData->constants, rates,
                                        states, userData->algebraic,
                                        userData->condVar);

    userData->computeResiduals(pVoi, userData->constants, rates, states,
                               userData->algebraic, userData->condVar,
                               residuals);

    // Everything went fine, so...

    return 0;
}

//==============================================================================

int rootFindingFunction(double pVoi, N_Vector pStates, N_Vector pRates,
                        double *pRoots, void *pUserData)
{
    // Do the root finding

    IdaSolverUserData *userData = reinterpret_cast<IdaSolverUserData *>(pUserData);

    userData->computeRootInformation(pVoi, userData->constants,
                                     N_VGetArrayPointer(pRates),
                                     N_VGetArrayPointer(pStates),
                                     userData->algebraic, pRoots);

    // Everything went fine, so...

    return 0;
}

//==============================================================================

void errorHandler(int pErrorCode, const char *pModule, const char *pFunction,
                  char *pErrorMsg, void *pUserData)
{
    Q_UNUSED(pModule);
    Q_UNUSED(pFunction);

    if (pErrorCode != IDA_WARNING)
        // IDA really generated an error, so forward it to the IdaSolver object

        reinterpret_cast<IdaSolver *>(pUserData)->emitError(pErrorMsg);
}

//==============================================================================

IdaSolver::IdaSolver() :
    mSolver(0),
    mStatesVector(0),
    mRatesVector(0),
    mMaximumStep(DefaultMaximumStep),
    mMaximumNumberOfSteps(DefaultMaximumNumberOfSteps),
    mRelativeTolerance(DefaultRelativeTolerance),
    mAbsoluteTolerance(DefaultAbsoluteTolerance)
{
}

//==============================================================================

IdaSolver::~IdaSolver()
{
    // Delete some internal objects

    N_VDestroy_Serial(mStatesVector);
    N_VDestroy_Serial(mRatesVector);
    IDAFree(&mSolver);
}

//==============================================================================

void IdaSolver::initialize(const double &pVoiStart, const double &pVoiEnd,
                           const int &pStatesCount, const int &pCondVarCount,
                           double *pConstants, double *pRates, double *pStates,
                           double *pAlgebraic, double *pCondVar,
                           ComputeEssentialVariablesFunction pComputeEssentialVariables,
                           ComputeResidualsFunction pComputeResiduals,
                           ComputeRootInformationFunction pComputeRootInformation,
                           ComputeStateInformationFunction pComputeStateInformation)
{
    static const double VoiEpsilon = 1e-9;

    if (!mSolver) {
        // Initialise the ODE solver itself

        OpenCOR::CoreSolver::CoreDaeSolver::initialize(pVoiStart, pVoiEnd,
                                                       pStatesCount,
                                                       pCondVarCount,
                                                       pConstants, pRates,
                                                       pStates, pAlgebraic,
                                                       pCondVar,
                                                       pComputeEssentialVariables,
                                                       pComputeResiduals,
                                                       pComputeRootInformation,
                                                       pComputeStateInformation);

        // Retrieve some of the IDA properties

        mMaximumStep = mProperties.contains(MaximumStepProperty)?
                           mProperties.value(MaximumStepProperty).toDouble():
                           DefaultMaximumStep;

        mMaximumNumberOfSteps = mProperties.contains(MaximumNumberOfStepsProperty)?
                                    mProperties.value(MaximumNumberOfStepsProperty).toDouble():
                                    DefaultMaximumNumberOfSteps;

        mRelativeTolerance = mProperties.contains(RelativeToleranceProperty)?
                                 mProperties.value(RelativeToleranceProperty).toDouble():
                                 DefaultRelativeTolerance;
        mAbsoluteTolerance = mProperties.contains(AbsoluteToleranceProperty)?
                                 mProperties.value(AbsoluteToleranceProperty).toDouble():
                                 DefaultAbsoluteTolerance;

        // Create the IDA solver

        mSolver = IDACreate();

        // Use our own error handler

        IDASetErrHandlerFn(mSolver, errorHandler, this);

        // Create the states vector

        mStatesVector = N_VMake_Serial(pStatesCount, pStates);
        mRatesVector  = N_VMake_Serial(pStatesCount, pRates);

        // Initialise the IDA solver

        IDAInit(mSolver, residualFunction, pVoiStart,
                mStatesVector, mRatesVector);

        IDARootInit(mSolver, pCondVarCount, rootFindingFunction);
        //---GRY--- NEED TO CHECK THAT OUR IDA CODE WORKS AS EXPECTED BY TRYING
        //          IT OUT ON A MODEL WHICH NEEDS ROOT FINDING...

        // Set some user data

        mUserData.constants = pConstants;
        mUserData.algebraic = pAlgebraic;
        mUserData.condVar   = pCondVar;

        mUserData.computeResiduals          = pComputeResiduals;
        mUserData.computeEssentialVariables = pComputeEssentialVariables;
        mUserData.computeRootInformation    = pComputeRootInformation;

        IDASetUserData(mSolver, &mUserData);

        // Set the linear solver

        IDADense(mSolver, pStatesCount);

        // Set the maximum step

        IDASetMaxStep(mSolver, mMaximumStep);

        // Set the maximum number of steps

        IDASetMaxNumSteps(mSolver, mMaximumNumberOfSteps);

        // Set the relative and absolute tolerances

        IDASStolerances(mSolver, mRelativeTolerance, mAbsoluteTolerance);

        // Compute the model's initial conditions
        // Note: this requires retrieving the model's state information, setting
        //       the IDA object's id vector and then calling IDACalcIC()...

        double *id = new double[pStatesCount];

        pComputeStateInformation(id);

        N_Vector idVector = N_VMake_Serial(pStatesCount, id);

        IDASetId(mSolver, idVector);
        IDACalcIC(mSolver, IDA_YA_YDP_INIT,
                  pVoiStart+((pVoiEnd-pVoiStart > 0)?VoiEpsilon:-VoiEpsilon));

        N_VDestroy_Serial(idVector);
        delete[] id;
    } else {
        // Reinitialise the IDA object

        IDAReInit(mSolver, pVoiStart, mStatesVector, mRatesVector);

        // Compute the model's new initial conditions

        IDACalcIC(mSolver, IDA_YA_YDP_INIT,
                  pVoiStart+((pVoiEnd-pVoiStart > 0)?VoiEpsilon:-VoiEpsilon));
    }
}

//==============================================================================

void IdaSolver::solve(double &pVoi, const double &pVoiEnd) const
{
    Q_ASSERT(mStatesCount > 0);
    Q_ASSERT(mCondVarCount >= 0);
    Q_ASSERT(mConstants);
    Q_ASSERT(mRates);
    Q_ASSERT(mStates);
    Q_ASSERT(mAlgebraic);
    Q_ASSERT(mCondVar);

    // Solve the model

    IDASolve(mSolver, pVoiEnd, &pVoi, mStatesVector, mRatesVector, IDA_NORMAL);
}

//==============================================================================

bool IdaSolver::isValidProperty(const QString &pName) const
{
    // Check whether the property name is known to us

    return    !pName.compare(MaximumStepProperty)
           || !pName.compare(MaximumNumberOfStepsProperty)
           || !pName.compare(RelativeToleranceProperty)
           || !pName.compare(AbsoluteToleranceProperty);
}

//==============================================================================

}   // namespace IDASolver
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>