<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "editortoolbar.h"

#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/minisplitter.h>
#include <coreplugin/sidebar.h>

#include <coreplugin/editormanager/editorview.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/openeditorsmodel.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>

#include <utils/parameteraction.h>
#include <utils/qtcassert.h>
#include <utils/styledbar.h>

#include <QtCore/QSettings>
#include <QtCore/QEvent>
#include <QtCore/QDir>
#include <QtGui/QApplication>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QScrollArea>
#include <QtGui/QTabWidget>
#include <QtGui/QToolButton>
#include <QtGui/QMenu>
#include <QtGui/QClipboard>
#include <QtGui/QLabel>
#include <QtGui/QToolBar>

Q_DECLARE_METATYPE(Core::IEditor*)

enum {
    debug = false
};

namespace Core {

/*!
  Mimic the look of the text editor toolbar as defined in e.g. EditorView::EditorView
  */
EditorToolBar::EditorToolBar(QWidget *parent) :
        Utils::StyledBar(parent),
        m_editorList(new QComboBox(this)),
        m_closeButton(new QToolButton),
        m_lockButton(new QToolButton),

        m_goBackAction(new QAction(QIcon(QLatin1String(":/help/images/previous.png")), EditorManager::tr("Go Back"), parent)),
        m_goForwardAction(new QAction(QIcon(QLatin1String(":/help/images/next.png")), EditorManager::tr("Go Forward"), parent)),

        m_activeToolBar(0),
        m_toolBarPlaceholder(new QWidget),
        m_defaultToolBar(new QWidget(this)),
        m_isStandalone(false)
{
    QHBoxLayout *toolBarLayout = new QHBoxLayout(this);
    toolBarLayout->setMargin(0);
    toolBarLayout->setSpacing(0);
    toolBarLayout->addWidget(m_defaultToolBar);
    m_toolBarPlaceholder->setLayout(toolBarLayout);
    m_toolBarPlaceholder->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);

    m_defaultToolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    m_activeToolBar = m_defaultToolBar;

    m_editorsListModel = EditorManager::instance()->openedEditorsModel();
    connect(m_goBackAction, SIGNAL(triggered()), this, SIGNAL(goBackClicked()));
    connect(m_goForwardAction, SIGNAL(triggered()), this, SIGNAL(goForwardClicked()));

    m_editorList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    m_editorList->setMinimumContentsLength(20);
    m_editorList->setModel(m_editorsListModel);
    m_editorList->setMaxVisibleItems(40);
    m_editorList->setContextMenuPolicy(Qt::CustomContextMenu);

    m_lockButton->setAutoRaise(true);
    m_lockButton->setProperty("type", QLatin1String("dockbutton"));
    m_lockButton->setVisible(false);

    m_closeButton->setAutoRaise(true);
    m_closeButton->setIcon(QIcon(":/core/images/closebutton.png"));
    m_closeButton->setProperty("type", QLatin1String("dockbutton"));
    m_closeButton->setEnabled(false);

    m_toolBarPlaceholder->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);

    m_backButton = new QToolButton(this);
    m_backButton->setDefaultAction(m_goBackAction);

    m_forwardButton= new QToolButton(this);
    m_forwardButton->setDefaultAction(m_goForwardAction);

    QHBoxLayout *toplayout = new QHBoxLayout(this);
    toplayout->setSpacing(0);
    toplayout->setMargin(0);
    toplayout->addWidget(m_backButton);
    toplayout->addWidget(m_forwardButton);
    toplayout->addWidget(m_editorList);
    toplayout->addWidget(m_toolBarPlaceholder, 1); // Custom toolbar stretches
    toplayout->addWidget(m_lockButton);
    toplayout->addWidget(m_closeButton);

    setLayout(toplayout);

    // this signal is disconnected for standalone toolbars and replaced with
    // a private slot connection
    connect(m_editorList, SIGNAL(activated(int)), this, SIGNAL(listSelectionActivated(int)));

    connect(m_editorList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(listContextMenu(QPoint)));
    connect(m_lockButton, SIGNAL(clicked()), this, SLOT(makeEditorWritable()));
    connect(m_closeButton, SIGNAL(clicked()), this, SLOT(closeView()), Qt::QueuedConnection);

    ActionManager *am = ICore::instance()->actionManager();
    connect(am->command(Constants::CLOSE), SIGNAL(keySequenceChanged()),
            this, SLOT(updateActionShortcuts()));
    connect(am->command(Constants::GO_BACK), SIGNAL(keySequenceChanged()),
            this, SLOT(updateActionShortcuts()));
    connect(am->command(Constants::GO_FORWARD), SIGNAL(keySequenceChanged()),
            this, SLOT(updateActionShortcuts()));

}

void EditorToolBar::removeToolbarForEditor(IEditor *editor)
{
    QTC_ASSERT(editor, return)
    disconnect(editor, SIGNAL(changed()), this, SLOT(checkEditorStatus()));

    QWidget *toolBar = editor->toolBar();
    if (toolBar != 0) {
        if (m_activeToolBar == toolBar) {
            m_activeToolBar = m_defaultToolBar;
            m_activeToolBar->setVisible(true);
        }
        m_toolBarPlaceholder->layout()->removeWidget(toolBar);
        toolBar->setVisible(false);
        toolBar->setParent(0);
    }
}

void EditorToolBar::closeView()
{
    if (!currentEditor())
        return;

    if (m_isStandalone) {
        EditorManager *em = ICore::instance()->editorManager();
        if (IEditor *editor = currentEditor()) {
            em->closeEditor(editor);
        }
    }
    emit closeClicked();
}

void EditorToolBar::addEditor(IEditor *editor)
{
    QTC_ASSERT(editor, return)
    connect(editor, SIGNAL(changed()), this, SLOT(checkEditorStatus()));
    QWidget *toolBar = editor->toolBar();

    if (toolBar && !m_isStandalone)
        addCenterToolBar(toolBar);

    updateEditorStatus(editor);
}

void EditorToolBar::addCenterToolBar(QWidget *toolBar)
{
    QTC_ASSERT(toolBar, return)
    toolBar->setVisible(false); // will be made visible in setCurrentEditor
    m_toolBarPlaceholder->layout()->addWidget(toolBar);

    updateToolBar(toolBar);
}

void EditorToolBar::updateToolBar(QWidget *toolBar)
{
    if (!toolBar)
        toolBar = m_defaultToolBar;
    if (m_activeToolBar == toolBar)
        return;
    toolBar->setVisible(true);
    m_activeToolBar->setVisible(false);
    m_activeToolBar = toolBar;
}

void EditorToolBar::setToolbarCreationFlags(ToolbarCreationFlags flags)
{
    m_isStandalone = flags & FlagsStandalone;
    if (m_isStandalone) {
        EditorManager *em = EditorManager::instance();
        connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)), SLOT(updateEditorListSelection(Core::IEditor*)));

        disconnect(m_editorList, SIGNAL(activated(int)), this, SIGNAL(listSelectionActivated(int)));
        connect(m_editorList, SIGNAL(activated(int)), this, SLOT(changeActiveEditor(int)));
    }
}

void EditorToolBar::setCurrentEditor(IEditor *editor)
{
    QTC_ASSERT(editor, return)
    m_editorList->setCurrentIndex(m_editorsListModel->indexOf(editor).row());

    // If we never added the toolbar from the editor,  we will never change
    // the editor, so there's no need to update the toolbar either.
    if (!m_isStandalone)
        updateToolBar(editor->toolBar());

    updateEditorStatus(editor);
}

void EditorToolBar::updateEditorListSelection(IEditor *newSelection)
{
    if (newSelection)
        m_editorList->setCurrentIndex(m_editorsListModel->indexOf(newSelection).row());
}

void EditorToolBar::changeActiveEditor(int row)
{
    EditorManager *em = ICore::instance()->editorManager();
    QAbstractItemModel *model = m_editorList->model();
    const QModelIndex modelIndex = model->index(row, 0);
    IEditor *editor = model->data(modelIndex, Qt::UserRole).value<IEditor*>();

    if (editor) {
        if (editor != em->currentEditor())
            em->activateEditor(editor, EditorManager::NoModeSwitch);
    } else {
        //em->activateEditor(model->index(index, 0), this);
        QString fileName = model->data(modelIndex, Qt::UserRole + 1).toString();
        QByteArray kind = model->data(modelIndex, Qt::UserRole + 2).toByteArray();
        editor = em->openEditor(fileName, kind, EditorManager::NoModeSwitch);
    }
    if (editor) {
        m_editorList->setCurrentIndex(m_editorsListModel->indexOf(editor).row());
    }
}

void EditorToolBar::listContextMenu(QPoint pos)
{
    QModelIndex index = m_editorsListModel->index(m_editorList->currentIndex(), 0);
    QString fileName = m_editorsListModel->data(index, Qt::UserRole + 1).toString();
    if (fileName.isEmpty())
        return;
    QMenu menu;
    menu.addAction(tr("Copy full path to clipboard"));
    if (menu.exec(m_editorList->mapToGlobal(pos))) {
        QApplication::clipboard()->setText(fileName);
    }
}

void EditorToolBar::makeEditorWritable()
{
    if (currentEditor())
        ICore::instance()->editorManager()->makeEditorWritable(currentEditor());
}

void EditorToolBar::setCanGoBack(bool canGoBack)
{
    m_goBackAction->setEnabled(canGoBack);
}

void EditorToolBar::setCanGoForward(bool canGoForward)
{
    m_goForwardAction->setEnabled(canGoForward);
}

void EditorToolBar::updateActionShortcuts()
{
    ActionManager *am = ICore::instance()->actionManager();
    m_closeButton->setToolTip(am->command(Constants::CLOSE)->stringWithAppendedShortcut(EditorManager::tr("Close")));
    m_goBackAction->setToolTip(am->command(Constants::GO_BACK)->action()->toolTip());
    m_goForwardAction->setToolTip(am->command(Constants::GO_FORWARD)->action()->toolTip());
}

IEditor *EditorToolBar::currentEditor() const
{
    return ICore::instance()->editorManager()->currentEditor();
}

void EditorToolBar::checkEditorStatus()
{
    IEditor *editor = qobject_cast<IEditor *>(sender());
    IEditor *current = currentEditor();

    if (current == editor)
        updateEditorStatus(editor);
}

void EditorToolBar::updateEditorStatus(IEditor *editor)
{
    m_lockButton->setVisible(editor != 0);
    m_closeButton->setEnabled(editor != 0);

    if (!editor || !editor->file()) {
        m_editorList->setToolTip(QString());
        return;
    }

    m_editorList->setCurrentIndex(m_editorsListModel->indexOf(editor).row());

    if (editor->file()->isReadOnly()) {
        m_lockButton->setIcon(QIcon(m_editorsListModel->lockedIcon()));
        m_lockButton->setEnabled(!editor->file()->fileName().isEmpty());
        m_lockButton->setToolTip(tr("Make writable"));
    } else {
        m_lockButton->setIcon(QIcon(m_editorsListModel->unlockedIcon()));
        m_lockButton->setEnabled(false);
        m_lockButton->setToolTip(tr("File is writable"));
    }
    if (editor == currentEditor())
        m_editorList->setToolTip(
                currentEditor()->file()->fileName().isEmpty()
                ? currentEditor()->displayName()
                    : QDir::toNativeSeparators(editor->file()->fileName())
                    );

}

void EditorToolBar::setNavigationVisible(bool isVisible)
{
    m_goBackAction->setVisible(isVisible);
    m_goForwardAction->setVisible(isVisible);
    m_backButton->setVisible(isVisible);
    m_forwardButton->setVisible(isVisible);
}

} // Core
<commit_msg>Copying path with native separators to clipboard.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "editortoolbar.h"

#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icore.h>
#include <coreplugin/minisplitter.h>
#include <coreplugin/sidebar.h>

#include <coreplugin/editormanager/editorview.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/openeditorsmodel.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>

#include <utils/parameteraction.h>
#include <utils/qtcassert.h>
#include <utils/styledbar.h>

#include <QtCore/QSettings>
#include <QtCore/QEvent>
#include <QtCore/QDir>
#include <QtGui/QApplication>
#include <QtGui/QPlainTextEdit>
#include <QtGui/QVBoxLayout>
#include <QtGui/QScrollArea>
#include <QtGui/QTabWidget>
#include <QtGui/QToolButton>
#include <QtGui/QMenu>
#include <QtGui/QClipboard>
#include <QtGui/QLabel>
#include <QtGui/QToolBar>

Q_DECLARE_METATYPE(Core::IEditor*)

enum {
    debug = false
};

namespace Core {

/*!
  Mimic the look of the text editor toolbar as defined in e.g. EditorView::EditorView
  */
EditorToolBar::EditorToolBar(QWidget *parent) :
        Utils::StyledBar(parent),
        m_editorList(new QComboBox(this)),
        m_closeButton(new QToolButton),
        m_lockButton(new QToolButton),

        m_goBackAction(new QAction(QIcon(QLatin1String(":/help/images/previous.png")), EditorManager::tr("Go Back"), parent)),
        m_goForwardAction(new QAction(QIcon(QLatin1String(":/help/images/next.png")), EditorManager::tr("Go Forward"), parent)),

        m_activeToolBar(0),
        m_toolBarPlaceholder(new QWidget),
        m_defaultToolBar(new QWidget(this)),
        m_isStandalone(false)
{
    QHBoxLayout *toolBarLayout = new QHBoxLayout(this);
    toolBarLayout->setMargin(0);
    toolBarLayout->setSpacing(0);
    toolBarLayout->addWidget(m_defaultToolBar);
    m_toolBarPlaceholder->setLayout(toolBarLayout);
    m_toolBarPlaceholder->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);

    m_defaultToolBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    m_activeToolBar = m_defaultToolBar;

    m_editorsListModel = EditorManager::instance()->openedEditorsModel();
    connect(m_goBackAction, SIGNAL(triggered()), this, SIGNAL(goBackClicked()));
    connect(m_goForwardAction, SIGNAL(triggered()), this, SIGNAL(goForwardClicked()));

    m_editorList->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    m_editorList->setMinimumContentsLength(20);
    m_editorList->setModel(m_editorsListModel);
    m_editorList->setMaxVisibleItems(40);
    m_editorList->setContextMenuPolicy(Qt::CustomContextMenu);

    m_lockButton->setAutoRaise(true);
    m_lockButton->setProperty("type", QLatin1String("dockbutton"));
    m_lockButton->setVisible(false);

    m_closeButton->setAutoRaise(true);
    m_closeButton->setIcon(QIcon(":/core/images/closebutton.png"));
    m_closeButton->setProperty("type", QLatin1String("dockbutton"));
    m_closeButton->setEnabled(false);

    m_toolBarPlaceholder->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);

    m_backButton = new QToolButton(this);
    m_backButton->setDefaultAction(m_goBackAction);

    m_forwardButton= new QToolButton(this);
    m_forwardButton->setDefaultAction(m_goForwardAction);

    QHBoxLayout *toplayout = new QHBoxLayout(this);
    toplayout->setSpacing(0);
    toplayout->setMargin(0);
    toplayout->addWidget(m_backButton);
    toplayout->addWidget(m_forwardButton);
    toplayout->addWidget(m_editorList);
    toplayout->addWidget(m_toolBarPlaceholder, 1); // Custom toolbar stretches
    toplayout->addWidget(m_lockButton);
    toplayout->addWidget(m_closeButton);

    setLayout(toplayout);

    // this signal is disconnected for standalone toolbars and replaced with
    // a private slot connection
    connect(m_editorList, SIGNAL(activated(int)), this, SIGNAL(listSelectionActivated(int)));

    connect(m_editorList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(listContextMenu(QPoint)));
    connect(m_lockButton, SIGNAL(clicked()), this, SLOT(makeEditorWritable()));
    connect(m_closeButton, SIGNAL(clicked()), this, SLOT(closeView()), Qt::QueuedConnection);

    ActionManager *am = ICore::instance()->actionManager();
    connect(am->command(Constants::CLOSE), SIGNAL(keySequenceChanged()),
            this, SLOT(updateActionShortcuts()));
    connect(am->command(Constants::GO_BACK), SIGNAL(keySequenceChanged()),
            this, SLOT(updateActionShortcuts()));
    connect(am->command(Constants::GO_FORWARD), SIGNAL(keySequenceChanged()),
            this, SLOT(updateActionShortcuts()));

}

void EditorToolBar::removeToolbarForEditor(IEditor *editor)
{
    QTC_ASSERT(editor, return)
    disconnect(editor, SIGNAL(changed()), this, SLOT(checkEditorStatus()));

    QWidget *toolBar = editor->toolBar();
    if (toolBar != 0) {
        if (m_activeToolBar == toolBar) {
            m_activeToolBar = m_defaultToolBar;
            m_activeToolBar->setVisible(true);
        }
        m_toolBarPlaceholder->layout()->removeWidget(toolBar);
        toolBar->setVisible(false);
        toolBar->setParent(0);
    }
}

void EditorToolBar::closeView()
{
    if (!currentEditor())
        return;

    if (m_isStandalone) {
        EditorManager *em = ICore::instance()->editorManager();
        if (IEditor *editor = currentEditor()) {
            em->closeEditor(editor);
        }
    }
    emit closeClicked();
}

void EditorToolBar::addEditor(IEditor *editor)
{
    QTC_ASSERT(editor, return)
    connect(editor, SIGNAL(changed()), this, SLOT(checkEditorStatus()));
    QWidget *toolBar = editor->toolBar();

    if (toolBar && !m_isStandalone)
        addCenterToolBar(toolBar);

    updateEditorStatus(editor);
}

void EditorToolBar::addCenterToolBar(QWidget *toolBar)
{
    QTC_ASSERT(toolBar, return)
    toolBar->setVisible(false); // will be made visible in setCurrentEditor
    m_toolBarPlaceholder->layout()->addWidget(toolBar);

    updateToolBar(toolBar);
}

void EditorToolBar::updateToolBar(QWidget *toolBar)
{
    if (!toolBar)
        toolBar = m_defaultToolBar;
    if (m_activeToolBar == toolBar)
        return;
    toolBar->setVisible(true);
    m_activeToolBar->setVisible(false);
    m_activeToolBar = toolBar;
}

void EditorToolBar::setToolbarCreationFlags(ToolbarCreationFlags flags)
{
    m_isStandalone = flags & FlagsStandalone;
    if (m_isStandalone) {
        EditorManager *em = EditorManager::instance();
        connect(em, SIGNAL(currentEditorChanged(Core::IEditor*)), SLOT(updateEditorListSelection(Core::IEditor*)));

        disconnect(m_editorList, SIGNAL(activated(int)), this, SIGNAL(listSelectionActivated(int)));
        connect(m_editorList, SIGNAL(activated(int)), this, SLOT(changeActiveEditor(int)));
    }
}

void EditorToolBar::setCurrentEditor(IEditor *editor)
{
    QTC_ASSERT(editor, return)
    m_editorList->setCurrentIndex(m_editorsListModel->indexOf(editor).row());

    // If we never added the toolbar from the editor,  we will never change
    // the editor, so there's no need to update the toolbar either.
    if (!m_isStandalone)
        updateToolBar(editor->toolBar());

    updateEditorStatus(editor);
}

void EditorToolBar::updateEditorListSelection(IEditor *newSelection)
{
    if (newSelection)
        m_editorList->setCurrentIndex(m_editorsListModel->indexOf(newSelection).row());
}

void EditorToolBar::changeActiveEditor(int row)
{
    EditorManager *em = ICore::instance()->editorManager();
    QAbstractItemModel *model = m_editorList->model();
    const QModelIndex modelIndex = model->index(row, 0);
    IEditor *editor = model->data(modelIndex, Qt::UserRole).value<IEditor*>();

    if (editor) {
        if (editor != em->currentEditor())
            em->activateEditor(editor, EditorManager::NoModeSwitch);
    } else {
        //em->activateEditor(model->index(index, 0), this);
        QString fileName = model->data(modelIndex, Qt::UserRole + 1).toString();
        QByteArray kind = model->data(modelIndex, Qt::UserRole + 2).toByteArray();
        editor = em->openEditor(fileName, kind, EditorManager::NoModeSwitch);
    }
    if (editor) {
        m_editorList->setCurrentIndex(m_editorsListModel->indexOf(editor).row());
    }
}

void EditorToolBar::listContextMenu(QPoint pos)
{
    QModelIndex index = m_editorsListModel->index(m_editorList->currentIndex(), 0);
    QString fileName = m_editorsListModel->data(index, Qt::UserRole + 1).toString();
    if (fileName.isEmpty())
        return;
    QMenu menu;
    menu.addAction(tr("Copy full path to clipboard"));
    if (menu.exec(m_editorList->mapToGlobal(pos))) {
        QApplication::clipboard()->setText(QDir::toNativeSeparators(fileName));
    }
}

void EditorToolBar::makeEditorWritable()
{
    if (currentEditor())
        ICore::instance()->editorManager()->makeEditorWritable(currentEditor());
}

void EditorToolBar::setCanGoBack(bool canGoBack)
{
    m_goBackAction->setEnabled(canGoBack);
}

void EditorToolBar::setCanGoForward(bool canGoForward)
{
    m_goForwardAction->setEnabled(canGoForward);
}

void EditorToolBar::updateActionShortcuts()
{
    ActionManager *am = ICore::instance()->actionManager();
    m_closeButton->setToolTip(am->command(Constants::CLOSE)->stringWithAppendedShortcut(EditorManager::tr("Close")));
    m_goBackAction->setToolTip(am->command(Constants::GO_BACK)->action()->toolTip());
    m_goForwardAction->setToolTip(am->command(Constants::GO_FORWARD)->action()->toolTip());
}

IEditor *EditorToolBar::currentEditor() const
{
    return ICore::instance()->editorManager()->currentEditor();
}

void EditorToolBar::checkEditorStatus()
{
    IEditor *editor = qobject_cast<IEditor *>(sender());
    IEditor *current = currentEditor();

    if (current == editor)
        updateEditorStatus(editor);
}

void EditorToolBar::updateEditorStatus(IEditor *editor)
{
    m_lockButton->setVisible(editor != 0);
    m_closeButton->setEnabled(editor != 0);

    if (!editor || !editor->file()) {
        m_editorList->setToolTip(QString());
        return;
    }

    m_editorList->setCurrentIndex(m_editorsListModel->indexOf(editor).row());

    if (editor->file()->isReadOnly()) {
        m_lockButton->setIcon(QIcon(m_editorsListModel->lockedIcon()));
        m_lockButton->setEnabled(!editor->file()->fileName().isEmpty());
        m_lockButton->setToolTip(tr("Make writable"));
    } else {
        m_lockButton->setIcon(QIcon(m_editorsListModel->unlockedIcon()));
        m_lockButton->setEnabled(false);
        m_lockButton->setToolTip(tr("File is writable"));
    }
    if (editor == currentEditor())
        m_editorList->setToolTip(
                currentEditor()->file()->fileName().isEmpty()
                ? currentEditor()->displayName()
                    : QDir::toNativeSeparators(editor->file()->fileName())
                    );

}

void EditorToolBar::setNavigationVisible(bool isVisible)
{
    m_goBackAction->setVisible(isVisible);
    m_goForwardAction->setVisible(isVisible);
    m_backButton->setVisible(isVisible);
    m_forwardButton->setVisible(isVisible);
}

} // Core
<|endoftext|>


<commit_before>#ifndef BULL_GRAPHICS_LIGHT_DIRECTIONALLIGHT_HPP
#define BULL_GRAPHICS_LIGHT_DIRECTIONALLIGHT_HPP

#include <Bull/Graphics/Light/AbstractLight.hpp>
#include <Bull/Math/Vector/Vector3.hpp>

namespace Bull
{
    class BULL_GRAPHICS_API DirectionalLight : public AbstractLight
    {
    public:

        /*! \brief Default constructor
         *
         */
        DirectionalLight();

        /*! \brief Constructor
         *
         * \param direction The direction of the DirectionalLight
         * \param color     The Color of the DirectionalLight
         *
         */
        explicit DirectionalLight(const Vector3F& direction, const Color& color = Color::White);

        /*! \brief Set the direction of the DirectionalLight
         *
         * \param direction The direction
         *
         */
        void setDirection(const Vector3F& direction);

        /*! \brief Get the direction of the DirectionalLight
         *
         * \return The direction
         *
         */
        const Vector3F& getDirection() const;

    private:

        Vector3F m_direction;
    };
}

#endif // BULL_GRAPHICS_LIGHT_DIRECTIONALLIGHT_HPP
<commit_msg>[Graphics/Light] Fix some typo<commit_after>#ifndef BULL_GRAPHICS_LIGHT_DIRECTIONALLIGHT_HPP
#define BULL_GRAPHICS_LIGHT_DIRECTIONALLIGHT_HPP

#include <Bull/Graphics/Light/AbstractLight.hpp>

#include <Bull/Math/Vector/Vector3.hpp>

namespace Bull
{
    class BULL_GRAPHICS_API DirectionalLight : public AbstractLight
    {
    public:

        /*! \brief Default constructor
         *
         */
        DirectionalLight();

        /*! \brief Constructor
         *
         * \param direction The direction of the DirectionalLight
         * \param color     The Color of the DirectionalLight
         *
         */
        explicit DirectionalLight(const Vector3F& direction, const Color& color = Color::White);

        /*! \brief Set the direction of the DirectionalLight
         *
         * \param direction The direction
         *
         */
        void setDirection(const Vector3F& direction);

        /*! \brief Get the direction of the DirectionalLight
         *
         * \return The direction
         *
         */
        const Vector3F& getDirection() const;

    private:

        Vector3F m_direction;
    };
}

#endif // BULL_GRAPHICS_LIGHT_DIRECTIONALLIGHT_HPP
<|endoftext|>


<commit_before>/*
   Copyright (c) 2009-2014, Jack Poulson
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
#pragma once
#ifndef EL_HERMITIANUNIFORMSPECTRUM_HPP
#define EL_HERMITIANUNIFORMSPECTRUM_HPP

#include "./Diagonal.hpp"
#include "./Haar.hpp"
#include "./Uniform.hpp"

namespace El {

// Draw the spectrum from the specified half-open interval on the real line,
// then rotate with a Haar matrix

template<typename F>
inline void
MakeHermitianUniformSpectrum( Matrix<F>& A, Base<F> lower=0, Base<F> upper=1 )
{
    DEBUG_ONLY(CallStackEntry cse("MakeHermitianUniformSpectrum"))
    if( A.Height() != A.Width() )
        LogicError("Cannot make a non-square matrix Hermitian");
    typedef Base<F> Real;
    const bool isComplex = IsComplex<F>::val;

    // Form d and D
    const Int n = A.Height();
    std::vector<F> d( n );
    for( Int j=0; j<n; ++j )
        d[j] = SampleUniform<Real>( lower, upper );
    Diagonal( A, d );

    // Apply a Haar matrix from both sides
    Matrix<F> Q, t;
    Matrix<Real> s;
    ImplicitHaar( Q, t, s, n );
    qr::ApplyQ( LEFT, NORMAL, Q, t, s, A );
    qr::ApplyQ( RIGHT, ADJOINT, Q, t, s, A );

    if( isComplex )
    {
        const Int height = A.Height();
        for( Int j=0; j<height; ++j )
            A.SetImagPart( j, j, Real(0) );
    }
}

template<typename F,Dist U,Dist V>
inline void
MakeHermitianUniformSpectrum
( DistMatrix<F,U,V>& A, Base<F> lower=0, Base<F> upper=1 )
{
    DEBUG_ONLY(CallStackEntry cse("MakeHermitianUniformSpectrum"))
    if( A.Height() != A.Width() )
        LogicError("Cannot make a non-square matrix Hermitian");
    const Grid& grid = A.Grid();
    typedef Base<F> Real;
    const bool isComplex = IsComplex<F>::val;
    const bool standardDist = ( U == MC && V == MR );

    // Form d and D
    const Int n = A.Height();
    std::vector<F> d( n );
    if( grid.Rank() == 0 )
        for( Int j=0; j<n; ++j )
            d[j] = SampleUniform<Real>( lower, upper );
    mpi::Broadcast( d.data(), n, 0, grid.Comm() );
    DistMatrix<F> ABackup( grid );
    if( standardDist )
        Diagonal( A, d );
    else
    {
        ABackup.AlignWith( A );
        Diagonal( ABackup, d );
    }

    // Apply a Haar matrix from both sides
    DistMatrix<F> Q(grid);
    DistMatrix<F,MD,STAR> t(grid);
    DistMatrix<Real,MD,STAR> s(grid);
    ImplicitHaar( Q, t, s, n );

    // Copy the result into the correct distribution
    if( standardDist )
    {
        qr::ApplyQ( LEFT, NORMAL, Q, t, s, A );
        qr::ApplyQ( RIGHT, ADJOINT, Q, t, s, A );
    }
    else
    {
        qr::ApplyQ( LEFT, NORMAL, Q, t, s, ABackup );
        qr::ApplyQ( RIGHT, ADJOINT, Q, t, s, ABackup );
        A = ABackup;
    }

    // Force the diagonal to be real-valued
    if( isComplex )
    {
        const Int localHeight = A.LocalHeight();
        const Int localWidth = A.LocalWidth();
        for( Int jLoc=0; jLoc<localWidth; ++jLoc )
        {
            const Int j = A.GlobalCol(jLoc);
            for( Int iLoc=0; iLoc<localHeight; ++iLoc )
            {
                const Int i = A.GlobalRow(iLoc);
                if( i == j )
                    A.SetLocalImagPart( iLoc, jLoc, Real(0) );
            }
        }
    }
}

template<typename F>
inline void
HermitianUniformSpectrum
( Matrix<F>& A, Int n, Base<F> lower=0, Base<F> upper=1 )
{
    DEBUG_ONLY(CallStackEntry cse("HermitianUniformSpectrum"))
    A.Resize( n, n );
    MakeHermitianUniformSpectrum( A, lower, upper );
}

template<typename F,Dist U,Dist V>
inline void
HermitianUniformSpectrum
( DistMatrix<F,U,V>& A, Int n, Base<F> lower=0, Base<F> upper=1 )
{
    DEBUG_ONLY(CallStackEntry cse("HermitianUniformSpectrum"))
    A.Resize( n, n );
    MakeHermitianUniformSpectrum( A, lower, upper );
}

} // namespace El

#endif // ifndef EL_HERMITIANUNIFORMSPECTRUM_HPP
<commit_msg>Resolving one more include issue<commit_after>/*
   Copyright (c) 2009-2014, Jack Poulson
   All rights reserved.

   This file is part of Elemental and is under the BSD 2-Clause License,
   which can be found in the LICENSE file in the root directory, or at
   http://opensource.org/licenses/BSD-2-Clause
*/
#pragma once
#ifndef EL_HERMITIANUNIFORMSPECTRUM_HPP
#define EL_HERMITIANUNIFORMSPECTRUM_HPP

#include "./Diagonal.hpp"
#include "./Haar.hpp"

namespace El {

// Draw the spectrum from the specified half-open interval on the real line,
// then rotate with a Haar matrix

template<typename F>
inline void
MakeHermitianUniformSpectrum( Matrix<F>& A, Base<F> lower=0, Base<F> upper=1 )
{
    DEBUG_ONLY(CallStackEntry cse("MakeHermitianUniformSpectrum"))
    if( A.Height() != A.Width() )
        LogicError("Cannot make a non-square matrix Hermitian");
    typedef Base<F> Real;
    const bool isComplex = IsComplex<F>::val;

    // Form d and D
    const Int n = A.Height();
    std::vector<F> d( n );
    for( Int j=0; j<n; ++j )
        d[j] = SampleUniform<Real>( lower, upper );
    Diagonal( A, d );

    // Apply a Haar matrix from both sides
    Matrix<F> Q, t;
    Matrix<Real> s;
    ImplicitHaar( Q, t, s, n );
    qr::ApplyQ( LEFT, NORMAL, Q, t, s, A );
    qr::ApplyQ( RIGHT, ADJOINT, Q, t, s, A );

    if( isComplex )
    {
        const Int height = A.Height();
        for( Int j=0; j<height; ++j )
            A.SetImagPart( j, j, Real(0) );
    }
}

template<typename F,Dist U,Dist V>
inline void
MakeHermitianUniformSpectrum
( DistMatrix<F,U,V>& A, Base<F> lower=0, Base<F> upper=1 )
{
    DEBUG_ONLY(CallStackEntry cse("MakeHermitianUniformSpectrum"))
    if( A.Height() != A.Width() )
        LogicError("Cannot make a non-square matrix Hermitian");
    const Grid& grid = A.Grid();
    typedef Base<F> Real;
    const bool isComplex = IsComplex<F>::val;
    const bool standardDist = ( U == MC && V == MR );

    // Form d and D
    const Int n = A.Height();
    std::vector<F> d( n );
    if( grid.Rank() == 0 )
        for( Int j=0; j<n; ++j )
            d[j] = SampleUniform<Real>( lower, upper );
    mpi::Broadcast( d.data(), n, 0, grid.Comm() );
    DistMatrix<F> ABackup( grid );
    if( standardDist )
        Diagonal( A, d );
    else
    {
        ABackup.AlignWith( A );
        Diagonal( ABackup, d );
    }

    // Apply a Haar matrix from both sides
    DistMatrix<F> Q(grid);
    DistMatrix<F,MD,STAR> t(grid);
    DistMatrix<Real,MD,STAR> s(grid);
    ImplicitHaar( Q, t, s, n );

    // Copy the result into the correct distribution
    if( standardDist )
    {
        qr::ApplyQ( LEFT, NORMAL, Q, t, s, A );
        qr::ApplyQ( RIGHT, ADJOINT, Q, t, s, A );
    }
    else
    {
        qr::ApplyQ( LEFT, NORMAL, Q, t, s, ABackup );
        qr::ApplyQ( RIGHT, ADJOINT, Q, t, s, ABackup );
        A = ABackup;
    }

    // Force the diagonal to be real-valued
    if( isComplex )
    {
        const Int localHeight = A.LocalHeight();
        const Int localWidth = A.LocalWidth();
        for( Int jLoc=0; jLoc<localWidth; ++jLoc )
        {
            const Int j = A.GlobalCol(jLoc);
            for( Int iLoc=0; iLoc<localHeight; ++iLoc )
            {
                const Int i = A.GlobalRow(iLoc);
                if( i == j )
                    A.SetLocalImagPart( iLoc, jLoc, Real(0) );
            }
        }
    }
}

template<typename F>
inline void
HermitianUniformSpectrum
( Matrix<F>& A, Int n, Base<F> lower=0, Base<F> upper=1 )
{
    DEBUG_ONLY(CallStackEntry cse("HermitianUniformSpectrum"))
    A.Resize( n, n );
    MakeHermitianUniformSpectrum( A, lower, upper );
}

template<typename F,Dist U,Dist V>
inline void
HermitianUniformSpectrum
( DistMatrix<F,U,V>& A, Int n, Base<F> lower=0, Base<F> upper=1 )
{
    DEBUG_ONLY(CallStackEntry cse("HermitianUniformSpectrum"))
    A.Resize( n, n );
    MakeHermitianUniformSpectrum( A, lower, upper );
}

} // namespace El

#endif // ifndef EL_HERMITIANUNIFORMSPECTRUM_HPP
<|endoftext|>


<commit_before>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_DEPTHRENDERTECHNIQUE_HPP
#define NAZARA_DEPTHRENDERTECHNIQUE_HPP

#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/DepthRenderQueue.hpp>
#include <Nazara/Graphics/Light.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>

namespace Nz
{
	class NAZARA_GRAPHICS_API DepthRenderTechnique : public AbstractRenderTechnique
	{
		public:
			DepthRenderTechnique();
			~DepthRenderTechnique() = default;

			void Clear(const SceneData& sceneData) const override;
			bool Draw(const SceneData& sceneData) const override;

			AbstractRenderQueue* GetRenderQueue() override;
			RenderTechniqueType GetType() const override;

			static bool Initialize();
			static void Uninitialize();

		private:
			struct ShaderUniforms;

			void DrawBasicSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
			void DrawBillboards(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
			void DrawOpaqueModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
			const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
			void OnShaderInvalidated(const Shader* shader) const;

			struct LightIndex
			{
				LightType type;
				float score;
				unsigned int index;
			};

			struct ShaderUniforms
			{
				NazaraSlot(Shader, OnShaderUniformInvalidated, shaderUniformInvalidatedSlot);
				NazaraSlot(Shader, OnShaderRelease, shaderReleaseSlot);

				// Autre uniformes
				int eyePosition;
				int sceneAmbient;
				int textureOverlay;
			};

			mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
			Buffer m_vertexBuffer;
			mutable DepthRenderQueue m_renderQueue;
			VertexBuffer m_billboardPointBuffer;
			VertexBuffer m_spriteBuffer;

			static IndexBuffer s_quadIndexBuffer;
			static VertexBuffer s_quadVertexBuffer;
			static VertexDeclaration s_billboardInstanceDeclaration;
			static VertexDeclaration s_billboardVertexDeclaration;
	};
}

#include <Nazara/Graphics/dEPTHRenderTechnique.inl>

#endif // NAZARA_DEPTHRENDERTECHNIQUE_HPP
<commit_msg>Graphics/DepthRenderTechnique: Fix typo in include name<commit_after>// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Graphics module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#pragma once

#ifndef NAZARA_DEPTHRENDERTECHNIQUE_HPP
#define NAZARA_DEPTHRENDERTECHNIQUE_HPP

#include <Nazara/Prerequesites.hpp>
#include <Nazara/Graphics/AbstractRenderTechnique.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/DepthRenderQueue.hpp>
#include <Nazara/Graphics/Light.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Utility/IndexBuffer.hpp>
#include <Nazara/Utility/VertexBuffer.hpp>

namespace Nz
{
	class NAZARA_GRAPHICS_API DepthRenderTechnique : public AbstractRenderTechnique
	{
		public:
			DepthRenderTechnique();
			~DepthRenderTechnique() = default;

			void Clear(const SceneData& sceneData) const override;
			bool Draw(const SceneData& sceneData) const override;

			AbstractRenderQueue* GetRenderQueue() override;
			RenderTechniqueType GetType() const override;

			static bool Initialize();
			static void Uninitialize();

		private:
			struct ShaderUniforms;

			void DrawBasicSprites(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
			void DrawBillboards(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
			void DrawOpaqueModels(const SceneData& sceneData, ForwardRenderQueue::Layer& layer) const;
			const ShaderUniforms* GetShaderUniforms(const Shader* shader) const;
			void OnShaderInvalidated(const Shader* shader) const;

			struct LightIndex
			{
				LightType type;
				float score;
				unsigned int index;
			};

			struct ShaderUniforms
			{
				NazaraSlot(Shader, OnShaderUniformInvalidated, shaderUniformInvalidatedSlot);
				NazaraSlot(Shader, OnShaderRelease, shaderReleaseSlot);

				// Autre uniformes
				int eyePosition;
				int sceneAmbient;
				int textureOverlay;
			};

			mutable std::unordered_map<const Shader*, ShaderUniforms> m_shaderUniforms;
			Buffer m_vertexBuffer;
			mutable DepthRenderQueue m_renderQueue;
			VertexBuffer m_billboardPointBuffer;
			VertexBuffer m_spriteBuffer;

			static IndexBuffer s_quadIndexBuffer;
			static VertexBuffer s_quadVertexBuffer;
			static VertexDeclaration s_billboardInstanceDeclaration;
			static VertexDeclaration s_billboardVertexDeclaration;
	};
}

#include <Nazara/Graphics/DepthRenderTechnique.inl>

#endif // NAZARA_DEPTHRENDERTECHNIQUE_HPP
<|endoftext|>


<commit_before>#pragma once
#include <type_traits>
#include "string_literal.hpp"

namespace named_types {

template <class Char> unsigned long long constexpr const_hash(Char const *input) {
  return *input ?  static_cast<unsigned long long>(*input) + 33 * const_hash(input + 1) : 5381;
}

template <class Char, size_t Size> unsigned long long constexpr array_const_hash(Char const (&input)[Size]) {
  return const_hash<Char>(input);
}

template <class T, T ... chars> struct string_literal {
  static const char data[sizeof ... (chars) + 1u];
  static const size_t data_size = sizeof ... (chars);
  static const unsigned long long hash_value = array_const_hash<T, sizeof ... (chars) + 1>({chars..., '\0'});

  constexpr string_literal() = default;
  constexpr char const* str() const { return data; }
  constexpr size_t size() const { return sizeof ... (chars); }
  constexpr char operator[] (size_t index) const { return data[index]; }
};

template <class T, T ... chars> const char string_literal<T,chars...>::data[sizeof ... (chars) + 1u] = {chars..., '\0'};
}  // namespace string_literal
<commit_msg>Preparing string_literal hash for MSVC.<commit_after>#pragma once
#include <type_traits>
#include "string_literal.hpp"

namespace named_types {

template <class Char> unsigned long long constexpr const_hash(Char const *input) {
  return *input ?  static_cast<unsigned long long>(*input) + 33 * const_hash(input + 1) : 5381;
}

#ifdef __GNUG__
template <class Char, size_t Size> unsigned long long constexpr array_const_hash(Char const (&input)[Size]) {
  return const_hash<Char>(input);
}
#else
// MSVC does not support arrays in constexpr
unsigned long long constexpr array_const_hash() {
  return 5381llu;
}

template <class Head, class ... Tail> unsigned long long constexpr array_const_hash(Head current,  Tail ... tail) {
  return 0u == current ? static_cast<unsigned long long>(current) + 33llu * array_const_hash(tail...) : 5381llu;
}
#endif

template <class T, T ... chars> struct string_literal {
  static const char data[sizeof ... (chars) + 1u];
  static const size_t data_size = sizeof ... (chars);
# ifdef __GNUG__
  static const unsigned long long hash_value = array_const_hash<T, sizeof ... (chars) + 1>({chars..., '\0'});
# else
  static const unsigned long long hash_value = array_const_hash(chars...);
# endif

  constexpr string_literal() = default;
  constexpr char const* str() const { return data; }
  constexpr size_t size() const { return sizeof ... (chars); }
  constexpr char operator[] (size_t index) const { return data[index]; }
};

template <class T, T ... chars> const char string_literal<T,chars...>::data[sizeof ... (chars) + 1u] = {chars..., '\0'};
}  // namespace string_literal
<|endoftext|>


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

/**
 * @file motor_ramp.cpp
 * Application to test motor ramp up.
 *
 * @author Andreas Antener <andreas@uaventure.com>
 * @author Roman Bapst <bapstroman@gmail.com>
 */

#include <px4_config.h>
#include <px4_defines.h>
#include <px4_tasks.h>
#include <px4_posix.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <poll.h>

#include <arch/board/board.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_pwm_output.h>
#include <platforms/px4_defines.h>

#include "systemlib/systemlib.h"
#include "systemlib/err.h"

static bool _thread_should_exit = false;		/**< motor_ramp exit flag */
static bool _thread_running = false;		/**< motor_ramp status flag */
static int _motor_ramp_task;				/**< Handle of motor_ramp task / thread */
static float _ramp_time;
static int _min_pwm;
static bool _sine_output = false;

enum RampState {
	RAMP_INIT,
	RAMP_MIN,
	RAMP_RAMP,
	RAMP_WAIT
};

/**
 * motor_ramp management function.
 */
extern "C" __EXPORT int motor_ramp_main(int argc, char *argv[]);

/**
 * Mainloop of motor_ramp.
 */
int motor_ramp_thread_main(int argc, char *argv[]);

bool min_pwm_valid(unsigned pwm_value);

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value);

int set_out(int fd, unsigned long max_channels, float output);

int prepare(int fd, unsigned long *max_channels);

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		PX4_ERR("%s", reason);
	}

	PX4_WARN("\n\nWARNING: motors will ramp up to full speed!\n\n"
		 "Usage: motor_ramp <min_pwm> <ramp_time> <-s>\n"
		 "Setting option <-s> will enable sinus output with period <ramp_time>\n\n"
		 "Example:\n"
		 "nsh> sdlog2 on\n"
		 "nsh> mc_att_control stop\n"
		 "nsh> motor_ramp 1100 0.5\n");
}

/**
 * The motor_ramp app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int motor_ramp_main(int argc, char *argv[])
{
	if (argc < 3) {
		usage("missing parameters");
		return 1;
	}

	if (_thread_running) {
		PX4_WARN("motor_ramp already running\n");
		/* this is not an error */
		return 0;
	}

	_min_pwm = atoi(argv[1]);

	if (!min_pwm_valid(_min_pwm)) {
		usage("min pwm not in range");
		return 1;
	}

	_ramp_time = atof(argv[2]);

	// check if we should apply sine ouput instead of ramp
	if (argc > 3) {
		if (strcmp(argv[3], "-s") == 0) {
			_sine_output = true;
		}

	} else {
		_sine_output = false;
	}

	if (!(_ramp_time > 0)) {
		usage("ramp time must be greater than 0");
		return 1;
	}

	_thread_should_exit = false;
	_motor_ramp_task = px4_task_spawn_cmd("motor_ramp",
					      SCHED_DEFAULT,
					      SCHED_PRIORITY_DEFAULT + 40,
					      2000,
					      motor_ramp_thread_main,
					      (argv) ? (char *const *)&argv[2] : (char *const *)NULL);
	return 0;

	usage("unrecognized command");
	return 1;
}

bool min_pwm_valid(unsigned pwm_value)
{
	return pwm_value > 900 && pwm_value < 1300;
}

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value)
{
	int ret;

	struct pwm_output_values pwm_values;
	memset(&pwm_values, 0, sizeof(pwm_values));

	pwm_values.channel_count = max_channels;

	for (int i = 0; i < max_channels; i++) {
		pwm_values.values[i] = pwm_value;
	}

	ret = px4_ioctl(fd, PWM_SERVO_SET_MIN_PWM, (long unsigned int)&pwm_values);

	if (ret != OK) {
		PX4_ERR("failed setting min values");
		return 1;
	}

	return 0;
}

int set_out(int fd, unsigned long max_channels, float output)
{
	int ret;
	int pwm = (2000 - _min_pwm) * output + _min_pwm;

	for (unsigned i = 0; i < max_channels; i++) {

		ret = ioctl(fd, PWM_SERVO_SET(i), pwm);

		if (ret != OK) {
			PX4_ERR("PWM_SERVO_SET(%d), value: %d", i, pwm);
			return 1;
		}
	}

	return 0;
}

int prepare(int fd, unsigned long *max_channels)
{
	/* make sure no other source is publishing control values now */
	struct actuator_controls_s actuators;
	int act_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);

	/* clear changed flag */
	orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, act_sub, &actuators);

	/* wait 50 ms */
	usleep(50000);

	/* now expect nothing changed on that topic */
	bool orb_updated;
	orb_check(act_sub, &orb_updated);

	if (orb_updated) {
		PX4_ERR("ABORTING! Attitude control still active. Please ensure to shut down all controllers:\n"
			"\tmc_att_control stop\n"
			"\tfw_att_control stop\n");
		return 1;
	}

	/* get number of channels available on the device */
	if (px4_ioctl(fd, PWM_SERVO_GET_COUNT, (unsigned long)max_channels) != OK) {
		PX4_ERR("PWM_SERVO_GET_COUNT");
		return 1;
	}

	/* tell IO/FMU that its ok to disable its safety with the switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_ARM_OK, 0) != OK) {
		PX4_ERR("PWM_SERVO_SET_ARM_OK");
		return 1;
	}

	/* tell IO/FMU that the system is armed (it will output values if safety is off) */
	if (px4_ioctl(fd, PWM_SERVO_ARM, 0) != OK) {
		PX4_ERR("PWM_SERVO_ARM");
		return 1;
	}

	/* tell IO to switch off safety without using the safety switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_OFF, 0) != OK) {
		PX4_ERR("PWM_SERVO_SET_FORCE_SAFETY_OFF");
		return 1;
	}

	return 0;
}

int motor_ramp_thread_main(int argc, char *argv[])
{
	_thread_running = true;

	char *dev = PWM_OUTPUT0_DEVICE_PATH;
	unsigned long max_channels = 0;

	int fd = px4_open(dev, 0);

	if (fd < 0) {
		PX4_ERR("can't open %s", dev);
	}

	if (prepare(fd, &max_channels) != OK) {
		_thread_should_exit = true;
	}

	set_out(fd, max_channels, 0.0f);

	float dt = 0.01f; // prevent division with 0
	float timer = 0.0f;
	hrt_abstime start = 0;
	hrt_abstime last_run = 0;

	enum RampState ramp_state = RAMP_INIT;
	float output = 0.0f;

	while (!_thread_should_exit) {

		if (last_run > 0) {
			dt = hrt_elapsed_time(&last_run) * 1e-6;

		} else {
			start = hrt_absolute_time();
		}

		last_run = hrt_absolute_time();
		timer = hrt_elapsed_time(&start) * 1e-6;

		switch (ramp_state) {
		case RAMP_INIT: {
				PX4_WARN("setting pwm min: %d", _min_pwm);
				set_min_pwm(fd, max_channels, _min_pwm);
				ramp_state = RAMP_MIN;
				break;
			}

		case RAMP_MIN: {
				if (timer > 3.0f) {
					PX4_WARN("starting %s: %.2f sec", _sine_output ? "sine" : "ramp", (double)_ramp_time);
					start = hrt_absolute_time();
					ramp_state = RAMP_RAMP;
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_RAMP: {
				if (!_sine_output) {
					output += dt / _ramp_time;

				} else {
					// sine outpout with period T = _ramp_time and magnitude between [0,1]
					// phase shift makes sure that it starts at zero when timer is zero
					output = 0.5f * (1.0f + sinf(M_TWOPI_F * timer / _ramp_time - M_PI_2_F));
				}

				if ((output > 1.0f && !_sine_output) || (timer > 3.0f * _ramp_time && _sine_output)) {
					// for ramp mode we set output to 1, for sine mode we just leave it as is
					output = _sine_output ? output : 1.0f;
					start = hrt_absolute_time();
					ramp_state = RAMP_WAIT;
					PX4_WARN("%s finished, waiting", _sine_output ? "sine" : "ramp");
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_WAIT: {
				if (timer > 1.0f) {
					_thread_should_exit = true;
					break;
				}

				set_out(fd, max_channels, output);
				break;
			}
		}

		// rate limit
		usleep(2000);
	}

	if (fd >= 0) {
		/* disarm */
		ioctl(fd, PWM_SERVO_DISARM, 0);

		px4_close(fd);
	}

	_thread_running = false;

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

/**
 * @file motor_ramp.cpp
 * Application to test motor ramp up.
 *
 * @author Andreas Antener <andreas@uaventure.com>
 * @author Roman Bapst <bapstroman@gmail.com>
 */

#include <px4_config.h>
#include <px4_defines.h>
#include <px4_tasks.h>
#include <px4_posix.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <poll.h>

#include <arch/board/board.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_pwm_output.h>
#include <platforms/px4_defines.h>

#include "systemlib/systemlib.h"
#include "systemlib/err.h"

enum RampState {
	RAMP_INIT,
	RAMP_MIN,
	RAMP_RAMP,
	RAMP_WAIT
};

enum Mode {
	RAMP,
	SINE,
	SQUARE
};

static bool _thread_should_exit = false;		/**< motor_ramp exit flag */
static bool _thread_running = false;		/**< motor_ramp status flag */
static int _motor_ramp_task;				/**< Handle of motor_ramp task / thread */
static float _ramp_time;
static int _min_pwm;
static int _max_pwm;
static Mode _mode;
static char *_mode_c;

/**
 * motor_ramp management function.
 */
extern "C" __EXPORT int motor_ramp_main(int argc, char *argv[]);

/**
 * Mainloop of motor_ramp.
 */
int motor_ramp_thread_main(int argc, char *argv[]);

bool min_pwm_valid(unsigned pwm_value);

bool max_pwm_valid(unsigned pwm_value);

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value);

int set_out(int fd, unsigned long max_channels, float output);

int prepare(int fd, unsigned long *max_channels);

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		PX4_ERR("%s", reason);
	}

	PX4_WARN("\n\nWARNING: motors will ramp up to full speed!\n\n"
		 "Usage: motor_ramp <mode> <min_pwm> <time> [<max_pwm>]\n"
		 "<mode> can be one of (ramp|sine|square)\n\n"
		 "Example:\n"
		 "sdlog2 on\n"
		 "mc_att_control stop\n"
		 "motor_ramp sine 1100 0.5\n");
}

/**
 * The motor_ramp app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int motor_ramp_main(int argc, char *argv[])
{
	if (argc < 4) {
		usage("missing parameters");
		return 1;
	}

	if (_thread_running) {
		PX4_WARN("motor_ramp already running\n");
		/* this is not an error */
		return 0;
	}

	if (!strcmp(argv[1], "ramp")) {
		_mode = RAMP;

	} else if (!strcmp(argv[1], "sine")) {
		_mode = SINE;

	} else if (!strcmp(argv[1], "square")) {
		_mode = SQUARE;

	} else {
		usage("selected mode not valid");
		return 1;
	}

	_mode_c = argv[1];

	_min_pwm = atoi(argv[2]);

	if (!min_pwm_valid(_min_pwm)) {
		usage("min PWM not in range");
		return 1;
	}

	_ramp_time = atof(argv[3]);

	if (argc > 4) {
		_max_pwm = atoi(argv[4]);

		if (!max_pwm_valid(_max_pwm)) {
			usage("max PWM not in range");
			return 1;
		}

	} else {
		_max_pwm = 2000;
	}

	if (!(_ramp_time > 0)) {
		usage("ramp time must be greater than 0");
		return 1;
	}

	_thread_should_exit = false;
	_motor_ramp_task = px4_task_spawn_cmd("motor_ramp",
					      SCHED_DEFAULT,
					      SCHED_PRIORITY_DEFAULT + 40,
					      2000,
					      motor_ramp_thread_main,
					      (argv) ? (char *const *)&argv[2] : (char *const *)NULL);
	return 0;

	usage("unrecognized command");
	return 1;
}

bool min_pwm_valid(unsigned pwm_value)
{
	return pwm_value >= 900 && pwm_value <= 1500;
}

bool max_pwm_valid(unsigned pwm_value)
{
	return pwm_value <= 2100 && pwm_value > _min_pwm;
}

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value)
{
	int ret;

	struct pwm_output_values pwm_values;
	memset(&pwm_values, 0, sizeof(pwm_values));

	pwm_values.channel_count = max_channels;

	for (int i = 0; i < max_channels; i++) {
		pwm_values.values[i] = pwm_value;
	}

	ret = px4_ioctl(fd, PWM_SERVO_SET_MIN_PWM, (long unsigned int)&pwm_values);

	if (ret != OK) {
		PX4_ERR("failed setting min values");
		return 1;
	}

	return 0;
}

int set_out(int fd, unsigned long max_channels, float output)
{
	int ret;
	int pwm = (_max_pwm - _min_pwm) * output + _min_pwm;

	for (unsigned i = 0; i < max_channels; i++) {

		ret = ioctl(fd, PWM_SERVO_SET(i), pwm);

		if (ret != OK) {
			PX4_ERR("PWM_SERVO_SET(%d), value: %d", i, pwm);
			return 1;
		}
	}

	return 0;
}

int prepare(int fd, unsigned long *max_channels)
{
	/* make sure no other source is publishing control values now */
	struct actuator_controls_s actuators;
	int act_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);

	/* clear changed flag */
	orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, act_sub, &actuators);

	/* wait 50 ms */
	usleep(50000);

	/* now expect nothing changed on that topic */
	bool orb_updated;
	orb_check(act_sub, &orb_updated);

	if (orb_updated) {
		PX4_ERR("ABORTING! Attitude control still active. Please ensure to shut down all controllers:\n"
			"\tmc_att_control stop\n"
			"\tfw_att_control stop\n");
		return 1;
	}

	/* get number of channels available on the device */
	if (px4_ioctl(fd, PWM_SERVO_GET_COUNT, (unsigned long)max_channels) != OK) {
		PX4_ERR("PWM_SERVO_GET_COUNT");
		return 1;
	}

	/* tell IO/FMU that its ok to disable its safety with the switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_ARM_OK, 0) != OK) {
		PX4_ERR("PWM_SERVO_SET_ARM_OK");
		return 1;
	}

	/* tell IO/FMU that the system is armed (it will output values if safety is off) */
	if (px4_ioctl(fd, PWM_SERVO_ARM, 0) != OK) {
		PX4_ERR("PWM_SERVO_ARM");
		return 1;
	}

	/* tell IO to switch off safety without using the safety switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_OFF, 0) != OK) {
		PX4_ERR("PWM_SERVO_SET_FORCE_SAFETY_OFF");
		return 1;
	}

	return 0;
}

int motor_ramp_thread_main(int argc, char *argv[])
{
	_thread_running = true;

	char *dev = PWM_OUTPUT0_DEVICE_PATH;
	unsigned long max_channels = 0;

	int fd = px4_open(dev, 0);

	if (fd < 0) {
		PX4_ERR("can't open %s", dev);
	}

	if (prepare(fd, &max_channels) != OK) {
		_thread_should_exit = true;
	}

	set_out(fd, max_channels, 0.0f);

	float dt = 0.001f; // prevent division with 0
	float timer = 0.0f;
	hrt_abstime start = 0;
	hrt_abstime last_run = 0;

	enum RampState ramp_state = RAMP_INIT;
	float output = 0.0f;

	while (!_thread_should_exit) {

		if (last_run > 0) {
			dt = hrt_elapsed_time(&last_run) * 1e-6;

		} else {
			start = hrt_absolute_time();
		}

		last_run = hrt_absolute_time();
		timer = hrt_elapsed_time(&start) * 1e-6;

		switch (ramp_state) {
		case RAMP_INIT: {
				PX4_WARN("setting pwm min: %d", _min_pwm);
				set_min_pwm(fd, max_channels, _min_pwm);
				ramp_state = RAMP_MIN;
				break;
			}

		case RAMP_MIN: {
				if (timer > 3.0f) {
					PX4_WARN("starting %s: %.2f sec", _mode_c, (double)_ramp_time);
					start = hrt_absolute_time();
					ramp_state = RAMP_RAMP;
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_RAMP: {
				if (_mode == RAMP) {
					output += dt / _ramp_time;

				} else if (_mode == SINE) {
					// sine outpout with period T = _ramp_time and magnitude between [0,1]
					// phase shift makes sure that it starts at zero when timer is zero
					output = 0.5f * (1.0f + sinf(M_TWOPI_F * timer / _ramp_time - M_PI_2_F));

				} else if (_mode == SQUARE) {
					output = fmodf(timer, _ramp_time) > (_ramp_time * 0.5f) ? 1.0f : 0.0f;
				}

				if ((output > 1.0f && _mode == RAMP) || (timer > 3.0f * _ramp_time)) {
					// for ramp mode we set output to 1, for others we just leave it as is
					output = _mode != RAMP ? output : 1.0f;
					start = hrt_absolute_time();
					ramp_state = RAMP_WAIT;
					PX4_WARN("%s finished, waiting", _mode_c);
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_WAIT: {
				if (timer > 1.0f) {
					_thread_should_exit = true;
					break;
				}

				set_out(fd, max_channels, output);
				break;
			}
		}

		// rate limit
		usleep(2000);
	}

	if (fd >= 0) {
		/* disarm */
		ioctl(fd, PWM_SERVO_DISARM, 0);

		px4_close(fd);
	}

	_thread_running = false;

	return 0;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>

#include <tiramisu/debug.h>
#include <Halide.h>

using namespace Halide;
using namespace Halide::Internal;

using std::string;
using std::map;
using std::vector;

namespace tiramisu
{

namespace
{

string stmt_to_string(const string &str, const Stmt &s)
{
    std::ostringstream stream;
    stream << str << s << "\n";
    return stream.str();
}

} // anonymous namespace

Module lower_halide_pipeline(const string &pipeline_name,
                             const Target &t,
                             const vector<Argument> &args,
                             const Internal::LoweredFunc::LinkageType linkage_type,
                             Stmt s)
{
    Module result_module(pipeline_name, t);

    // TODO(tiramisu): Compute the env (function DAG). This is needed for
    // the sliding window and storage folding passes.
    map<string, Function> env;

    if (ENABLE_DEBUG)
    {
        std::cout << "Lower halide pipeline...\n" << s << "\n";
        std::flush(std::cout);
    }

    DEBUG(3, tiramisu::str_dump("Performing sliding window optimization...\n"));
    s = sliding_window(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after sliding window:\n", s)));

    DEBUG(3, tiramisu::str_dump("Removing code that depends on undef values...\n"));
    s = remove_undef(s);
    DEBUG(4, tiramisu::str_dump(
              stmt_to_string("Lowering after removing code that depends on undef values:\n", s)));

    // This uniquifies the variable names, so we're good to simplify
    // after this point. This lets later passes assume syntactic
    // equivalence means semantic equivalence.
    DEBUG(3, tiramisu::str_dump("Uniquifying variable names...\n"));
    s = uniquify_variable_names(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after uniquifying variable names:\n", s)));

    DEBUG(3, tiramisu::str_dump("Simplifying...\n")); // without removing dead lets, because storage flattening needs the strides
    s = simplify(s, false);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after simplification:\n", s)));

    DEBUG(3, tiramisu::str_dump("Performing storage folding optimization...\n"));
    s = storage_folding(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after storage folding:\n", s)));

    DEBUG(3, tiramisu::str_dump("Simplifying...\n")); // without removing dead lets, because storage flattening needs the strides
    s = simplify(s, false);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after simplification:\n", s)));

/*    DEBUG(3, tiramisu::str_dump("Injecting prefetches...\n"));
    s = inject_prefetch(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting prefetches:\n", s)));
*/
    DEBUG(3, tiramisu::str_dump("Destructuring tuple-valued realizations...\n"));
    s = split_tuples(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after destructuring tuple-valued realizations:\n", s)));
    DEBUG(3, tiramisu::str_dump("\n\n"));

    // TODO(tiramisu): This pass is important to figure out all the buffer symbols.
    // Maybe we should put it somewhere else instead of here.
    DEBUG(3, tiramisu::str_dump("Unpacking buffer arguments...\n"));
    s = unpack_buffers(s);
    DEBUG(0, tiramisu::str_dump(stmt_to_string("Lowering after unpacking buffer arguments:\n", s)));

    if (t.has_gpu_feature() ||
        t.has_feature(Target::OpenGLCompute) ||
        t.has_feature(Target::OpenGL) ||
        (t.arch != Target::Hexagon && (t.features_any_of({Target::HVX_64, Target::HVX_128})))) {
        DEBUG(3, tiramisu::str_dump("Selecting a GPU API for GPU loops...\n"));
        s = select_gpu_api(s, t);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after selecting a GPU API:\n", s)));

        DEBUG(3, tiramisu::str_dump("Injecting host <-> dev buffer copies...\n"));
        s = inject_host_dev_buffer_copies(s, t);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting host <-> dev buffer copies:\n",
                                    s)));
    }

    if (t.has_feature(Target::OpenGL))
    {
        DEBUG(3, tiramisu::str_dump("Injecting OpenGL texture intrinsics...\n"));
        s = inject_opengl_intrinsics(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after OpenGL intrinsics:\n", s)));
    }

    if (t.has_gpu_feature() ||
            t.has_feature(Target::OpenGLCompute))
    {
        DEBUG(3, tiramisu::str_dump("Injecting per-block gpu synchronization...\n"));
        s = fuse_gpu_thread_loops(s);
        DEBUG(4, tiramisu::str_dump(
                  stmt_to_string("Lowering after injecting per-block gpu synchronization:\n", s)));
    }

    DEBUG(3, tiramisu::str_dump("Simplifying...\n"));
    s = simplify(s);
    s = unify_duplicate_lets(s);
    s = remove_trivial_for_loops(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after second simplifcation:\n", s)));

    DEBUG(3, tiramisu::str_dump("Reduce prefetch dimension...\n"));
    s = reduce_prefetch_dimension(s, t);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after reduce prefetch dimension:\n", s)));

    DEBUG(3, tiramisu::str_dump("Unrolling...\n"));
    s = unroll_loops(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after unrolling:\n", s)));

    DEBUG(3, tiramisu::str_dump("Vectorizing...\n"));
    s = vectorize_loops(s, t);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after vectorizing:\n", s)));

    DEBUG(3, tiramisu::str_dump("Detecting vector interleavings...\n"));
    s = rewrite_interleavings(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after rewriting vector interleavings:\n", s)));

    DEBUG(3, tiramisu::str_dump("Partitioning loops to simplify boundary conditions...\n"));
    s = partition_loops(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after partitioning loops:\n", s)));

    DEBUG(3, tiramisu::str_dump("Trimming loops to the region over which they do something...\n"));
    s = trim_no_ops(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after loop trimming:\n", s)));

    DEBUG(3, tiramisu::str_dump("Injecting early frees...\n"));
    s = inject_early_frees(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting early frees:\n", s)));

    if (t.has_feature(Target::FuzzFloatStores))
    {
        DEBUG(3, tiramisu::str_dump("Fuzzing floating point stores...\n"));
        s = fuzz_float_stores(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after fuzzing floating point stores:\n", s)));
    }

    //DEBUG(3, tiramisu::str_dump("Simplifying...\n"));
    //s = common_subexpression_elimination(s);

    if (t.has_feature(Target::OpenGL))
    {
        DEBUG(3, tiramisu::str_dump("Detecting varying attributes...\n"));
        s = find_linear_expressions(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after detecting varying attributes:\n", s)));

        DEBUG(3, tiramisu::str_dump("Moving varying attribute expressions out of the shader...\n"));
        s = setup_gpu_vertex_buffer(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after removing varying attributes:\n", s)));
    }

    s = remove_dead_allocations(s);
    s = remove_trivial_for_loops(s);
    s = simplify(s);
    // s = loop_invariant_code_motion(s);
    if (ENABLE_DEBUG)
    {
        std::cout << "Lowering after final simplification:\n" << s << "\n";
        std::flush(std::cout);
    }

    DEBUG(3, tiramisu::str_dump("Splitting off Hexagon offload...\n"));
//    s = inject_hexagon_rpc(s, t, result_module);
//    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after splitting off Hexagon offload:\n", s)));

    vector<Argument> public_args = args;

    // We're about to drop the environment and outputs vector, which
    // contain the only strong refs to Functions that may still be
    // pointed to by the IR. So make those refs strong.
    class StrengthenRefs : public IRMutator {
        using IRMutator::visit;
        void visit(const Call *c) {
            IRMutator::visit(c);
            c = expr.as<Call>();
            //internal_assert(c);
            if (c->func.defined()) {
                FunctionPtr ptr = c->func;
                ptr.strengthen();
                expr = Call::make(c->type, c->name, c->args, c->call_type,
                                  ptr, c->value_index,
                                  c->image, c->param);
            }
        }
    };
    s = StrengthenRefs().mutate(s);

    LoweredFunc main_func(pipeline_name, public_args, s, linkage_type);

    result_module.append(main_func);

    // Append a wrapper for this pipeline that accepts old buffer_ts
    // and upgrades them. It will use the same name, so it will
    // require C++ linkage. We don't need it when jitting.
    if (!t.has_feature(Target::JIT)) {
        add_legacy_wrapper(result_module, main_func);
    }

    // Also append any wrappers for extern stages that expect the old buffer_t
    wrap_legacy_extern_stages(result_module);

    return result_module;
}

}
<commit_msg>Disable trim_no_ops to avoid a bug in dibaryon<commit_after>#include <algorithm>
#include <iostream>

#include <tiramisu/debug.h>
#include <Halide.h>

using namespace Halide;
using namespace Halide::Internal;

using std::string;
using std::map;
using std::vector;

namespace tiramisu
{

namespace
{

string stmt_to_string(const string &str, const Stmt &s)
{
    std::ostringstream stream;
    stream << str << s << "\n";
    return stream.str();
}

} // anonymous namespace

Module lower_halide_pipeline(const string &pipeline_name,
                             const Target &t,
                             const vector<Argument> &args,
                             const Internal::LoweredFunc::LinkageType linkage_type,
                             Stmt s)
{
    Module result_module(pipeline_name, t);

    // TODO(tiramisu): Compute the env (function DAG). This is needed for
    // the sliding window and storage folding passes.
    map<string, Function> env;

    if (ENABLE_DEBUG)
    {
        std::cout << "Lower halide pipeline...\n" << s << "\n";
        std::flush(std::cout);
    }

    DEBUG(3, tiramisu::str_dump("Performing sliding window optimization...\n"));
    s = sliding_window(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after sliding window:\n", s)));

    DEBUG(3, tiramisu::str_dump("Removing code that depends on undef values...\n"));
    s = remove_undef(s);
    DEBUG(4, tiramisu::str_dump(
              stmt_to_string("Lowering after removing code that depends on undef values:\n", s)));

    // This uniquifies the variable names, so we're good to simplify
    // after this point. This lets later passes assume syntactic
    // equivalence means semantic equivalence.
    DEBUG(3, tiramisu::str_dump("Uniquifying variable names...\n"));
    s = uniquify_variable_names(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after uniquifying variable names:\n", s)));

    DEBUG(3, tiramisu::str_dump("Simplifying...\n")); // without removing dead lets, because storage flattening needs the strides
    s = simplify(s, false);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after simplification:\n", s)));

    DEBUG(3, tiramisu::str_dump("Performing storage folding optimization...\n"));
    s = storage_folding(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after storage folding:\n", s)));

    DEBUG(3, tiramisu::str_dump("Simplifying...\n")); // without removing dead lets, because storage flattening needs the strides
    s = simplify(s, false);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after simplification:\n", s)));

/*    DEBUG(3, tiramisu::str_dump("Injecting prefetches...\n"));
    s = inject_prefetch(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting prefetches:\n", s)));
*/
    DEBUG(3, tiramisu::str_dump("Destructuring tuple-valued realizations...\n"));
    s = split_tuples(s, env);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after destructuring tuple-valued realizations:\n", s)));
    DEBUG(3, tiramisu::str_dump("\n\n"));

    // TODO(tiramisu): This pass is important to figure out all the buffer symbols.
    // Maybe we should put it somewhere else instead of here.
    DEBUG(3, tiramisu::str_dump("Unpacking buffer arguments...\n"));
    s = unpack_buffers(s);
    DEBUG(0, tiramisu::str_dump(stmt_to_string("Lowering after unpacking buffer arguments:\n", s)));

    if (t.has_gpu_feature() ||
        t.has_feature(Target::OpenGLCompute) ||
        t.has_feature(Target::OpenGL) ||
        (t.arch != Target::Hexagon && (t.features_any_of({Target::HVX_64, Target::HVX_128})))) {
        DEBUG(3, tiramisu::str_dump("Selecting a GPU API for GPU loops...\n"));
        s = select_gpu_api(s, t);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after selecting a GPU API:\n", s)));

        DEBUG(3, tiramisu::str_dump("Injecting host <-> dev buffer copies...\n"));
        s = inject_host_dev_buffer_copies(s, t);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting host <-> dev buffer copies:\n",
                                    s)));
    }

    if (t.has_feature(Target::OpenGL))
    {
        DEBUG(3, tiramisu::str_dump("Injecting OpenGL texture intrinsics...\n"));
        s = inject_opengl_intrinsics(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after OpenGL intrinsics:\n", s)));
    }

    if (t.has_gpu_feature() ||
            t.has_feature(Target::OpenGLCompute))
    {
        DEBUG(3, tiramisu::str_dump("Injecting per-block gpu synchronization...\n"));
        s = fuse_gpu_thread_loops(s);
        DEBUG(4, tiramisu::str_dump(
                  stmt_to_string("Lowering after injecting per-block gpu synchronization:\n", s)));
    }

    DEBUG(3, tiramisu::str_dump("Simplifying...\n"));
    s = simplify(s);
    s = unify_duplicate_lets(s);
    s = remove_trivial_for_loops(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after second simplifcation:\n", s)));

    DEBUG(3, tiramisu::str_dump("Reduce prefetch dimension...\n"));
    s = reduce_prefetch_dimension(s, t);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after reduce prefetch dimension:\n", s)));

    DEBUG(3, tiramisu::str_dump("Unrolling...\n"));
    s = unroll_loops(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after unrolling:\n", s)));

    DEBUG(3, tiramisu::str_dump("Vectorizing...\n"));
    s = vectorize_loops(s, t);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after vectorizing:\n", s)));

    DEBUG(3, tiramisu::str_dump("Detecting vector interleavings...\n"));
    s = rewrite_interleavings(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after rewriting vector interleavings:\n", s)));

    DEBUG(3, tiramisu::str_dump("Partitioning loops to simplify boundary conditions...\n"));
    s = partition_loops(s);
    s = simplify(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after partitioning loops:\n", s)));

//    DEBUG(3, tiramisu::str_dump("Trimming loops to the region over which they do something...\n"));
//    s = trim_no_ops(s);
//    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after loop trimming:\n", s)));

    DEBUG(3, tiramisu::str_dump("Injecting early frees...\n"));
    s = inject_early_frees(s);
    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after injecting early frees:\n", s)));

    if (t.has_feature(Target::FuzzFloatStores))
    {
        DEBUG(3, tiramisu::str_dump("Fuzzing floating point stores...\n"));
        s = fuzz_float_stores(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after fuzzing floating point stores:\n", s)));
    }

    //DEBUG(3, tiramisu::str_dump("Simplifying...\n"));
    //s = common_subexpression_elimination(s);

    if (t.has_feature(Target::OpenGL))
    {
        DEBUG(3, tiramisu::str_dump("Detecting varying attributes...\n"));
        s = find_linear_expressions(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after detecting varying attributes:\n", s)));

        DEBUG(3, tiramisu::str_dump("Moving varying attribute expressions out of the shader...\n"));
        s = setup_gpu_vertex_buffer(s);
        DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after removing varying attributes:\n", s)));
    }

    s = remove_dead_allocations(s);
    s = remove_trivial_for_loops(s);
    s = simplify(s);
    // s = loop_invariant_code_motion(s);
    if (ENABLE_DEBUG)
    {
        std::cout << "Lowering after final simplification:\n" << s << "\n";
        std::flush(std::cout);
    }

    DEBUG(3, tiramisu::str_dump("Splitting off Hexagon offload...\n"));
//    s = inject_hexagon_rpc(s, t, result_module);
//    DEBUG(4, tiramisu::str_dump(stmt_to_string("Lowering after splitting off Hexagon offload:\n", s)));

    vector<Argument> public_args = args;

    // We're about to drop the environment and outputs vector, which
    // contain the only strong refs to Functions that may still be
    // pointed to by the IR. So make those refs strong.
    class StrengthenRefs : public IRMutator {
        using IRMutator::visit;
        void visit(const Call *c) {
            IRMutator::visit(c);
            c = expr.as<Call>();
            //internal_assert(c);
            if (c->func.defined()) {
                FunctionPtr ptr = c->func;
                ptr.strengthen();
                expr = Call::make(c->type, c->name, c->args, c->call_type,
                                  ptr, c->value_index,
                                  c->image, c->param);
            }
        }
    };
    s = StrengthenRefs().mutate(s);

    LoweredFunc main_func(pipeline_name, public_args, s, linkage_type);

    result_module.append(main_func);

    // Append a wrapper for this pipeline that accepts old buffer_ts
    // and upgrades them. It will use the same name, so it will
    // require C++ linkage. We don't need it when jitting.
    if (!t.has_feature(Target::JIT)) {
        add_legacy_wrapper(result_module, main_func);
    }

    // Also append any wrappers for extern stages that expect the old buffer_t
    wrap_legacy_extern_stages(result_module);

    return result_module;
}

}
<|endoftext|>