<commit_before>#include "notelistmodel.h"
#include <QDebug>
#include "nodepath.h"
#include <QTimer>
#include <QMimeData>

NoteListModel::NoteListModel(QObject *parent)
    : QAbstractListModel(parent)
{
    connect(this, &NoteListModel::pinnedChanged,
            this, &NoteListModel::onPinnedChanged);
}

NoteListModel::~NoteListModel()
{

}

QModelIndex NoteListModel::addNote(const NodeData& note)
{
    if (!noteIsPinned(note)) {
        const int rowCnt = rowCount();
        beginInsertRows(QModelIndex(), rowCnt, rowCnt);
        m_noteList << note;
        endInsertRows();
        emit rowCountChanged();
        return createIndex(rowCnt, 0);
    } else {
        const int rowCnt = m_pinnedList.size();
        beginInsertRows(QModelIndex(), rowCnt, rowCnt);
        m_pinnedList << note;
        endInsertRows();
        emit rowCountChanged();
        return createIndex(rowCnt, 0);
    }
}

QModelIndex NoteListModel::insertNote(const NodeData &note, int row)
{
    if (noteIsPinned(note)) {
        if (row > m_pinnedList.size()) {
            row = m_pinnedList.size();
        } else if (row < 0) {
            row = 0;
        }
        beginInsertRows(QModelIndex(), row, row);
        m_pinnedList.insert(row, note);
        endInsertRows();
        emit rowCountChanged();
        return createIndex(row, 0);
    } else {
        if (row < m_pinnedList.size()) {
            row = m_pinnedList.size();
        } else if (row > (m_pinnedList.size() + m_noteList.size())) {
            row = m_pinnedList.size() + m_noteList.size();
        }
        beginInsertRows(QModelIndex(), row, row);
        m_noteList.insert(row - m_pinnedList.size(), note);
        endInsertRows();
        emit rowCountChanged();
        return createIndex(row, 0);
    }
}

NodeData NoteListModel::getNote(const QModelIndex& index) const
{
    auto row = index.row();
    if (row < m_pinnedList.size()) {
        return m_pinnedList.at(row);
    } else {
        row = row - m_pinnedList.size();
        return m_noteList.at(row);
    }
}

QModelIndex NoteListModel::getNoteIndex(int id) const
{
    for (int i = 0; i < m_pinnedList.size(); ++i) {
        if (m_pinnedList[i].id() == id) {
            return createIndex(i, 0);
        }
    }

    for (int i = 0; i < m_noteList.size(); ++i) {
        if (m_noteList[i].id() == id) {
            return createIndex(i + m_pinnedList.size(), 0);
        }
    }
    return QModelIndex{};
}

void NoteListModel::setListNote(const QVector<NodeData> notes, const ListViewInfo& inf)
{
    beginResetModel();
    m_pinnedList.clear();
    m_noteList.clear();
    m_listViewInfo = inf;
    if ((!m_listViewInfo.isInTag) && (m_listViewInfo.parentFolderId != SpecialNodeID::TrashFolder)) {
        for (const auto& note : QT_AS_CONST(notes)) {
            if (noteIsPinned(note)) {
                m_pinnedList.append(note);
            } else {
                m_noteList.append(note);
            }
        }
    } else {
        m_noteList = notes;
    }
    endResetModel();
    emit rowCountChanged();
}

void NoteListModel::removeNote(const QModelIndex &noteIndex)
{
    if (noteIndex.isValid()) {
        int row = noteIndex.row();
        beginRemoveRows(QModelIndex(), row, row);
        if (row < m_pinnedList.size()) {
            m_pinnedList.takeAt(row);
        } else {
            row = row - m_pinnedList.size();
            m_noteList.takeAt(row);
        }
        endRemoveRows();
        emit rowCountChanged();
    }
}

bool NoteListModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild)
{
    if(sourceRow < 0
            || sourceRow >= rowCount()
            || destinationChild <0
            || destinationChild >= rowCount()) {
        return false;
    }
    if (sourceRow < m_pinnedList.size() && destinationChild < m_pinnedList.size()) {
        if (beginMoveRows(sourceParent,sourceRow,sourceRow,destinationParent,destinationChild)) {
            vector_move(m_pinnedList, sourceRow, destinationChild);
            endMoveRows();
            emit rowCountChanged();
            return true;
        }
    }
    if (sourceRow >= m_pinnedList.size() && destinationChild >= m_pinnedList.size()) {
        sourceRow = sourceRow - m_pinnedList.size();
        destinationChild = destinationChild - m_pinnedList.size();
        if (beginMoveRows(sourceParent,sourceRow,sourceRow,destinationParent,destinationChild)) {
            vector_move(m_noteList, sourceRow, destinationChild);
            endMoveRows();
            emit rowCountChanged();
            return true;
        }
    }
    return false;
}

void NoteListModel::clearNotes()
{
    beginResetModel();
    m_pinnedList.clear();
    m_noteList.clear();
    endResetModel();
    emit rowCountChanged();
}

QVariant NoteListModel::data(const QModelIndex &index, int role) const
{
    if (index.row() < 0 || index.row() >= (m_noteList.count() + m_pinnedList.count())) {
        return QVariant();
    }
    auto row = index.row();
    NodeData note;
    if (row < m_pinnedList.size()) {
        note = m_pinnedList[row];
    } else {
        row = row - m_pinnedList.size();
        note = m_noteList[row];
    }
    if(role == NoteID){
        return note.id();
    }else if(role == NoteFullTitle){
        return note.fullTitle();
    }else if(role == NoteCreationDateTime){
        return note.creationDateTime();
    }else if(role == NoteLastModificationDateTime){
        return note.lastModificationdateTime();
    }else if(role == NoteDeletionDateTime){
        return note.deletionDateTime();
    }else if(role == NoteContent){
        return note.content();
    }else if(role == NoteScrollbarPos){
        return note.scrollBarPosition();
    }else if(role == NoteTagsList){
        return QVariant::fromValue(note.tagIds());
    }else if(role == NoteIsTemp){
        return note.isTempNote();
    }else if(role == NoteParentName){
        return note.parentName();
    } else if (role == NoteTagListScrollbarPos) {
        return note.tagListScrollBarPos();
    } else if (role == NoteIsPinned) {
        if (isInAllNote()) {
            return note.isPinnedNoteAN();
        } else {
            return note.isPinnedNote();
        }
    }

    return QVariant();
}

bool NoteListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.row() < 0 || index.row() >= (m_noteList.count() + m_pinnedList.count())) {
        return false;
    }

    auto getRef = [this] (int row) -> NodeData& {
        NodeData note;
        if (row < m_pinnedList.size()) {
            return m_pinnedList[row];
        } else {
            row = row - m_pinnedList.size();
            return m_noteList[row];
        }
    };
    NodeData& note = getRef(index.row());
    if(role == NoteID){
        note.setId(value.toInt());
    }else if(role == NoteFullTitle){
        note.setFullTitle(value.toString());
    }else if(role == NoteCreationDateTime){
        note.setCreationDateTime(value.toDateTime());
    }else if(role == NoteLastModificationDateTime){
        note.setLastModificationDateTime(value.toDateTime());
    }else if(role == NoteDeletionDateTime){
        note.setDeletionDateTime(value.toDateTime());
    }else if(role == NoteContent){
        note.setContent(value.toString());
    }else if(role == NoteScrollbarPos){
        note.setScrollBarPosition(value.toInt());
    }else if(role == NoteTagsList) {
        note.setTagIds(value.value<QSet<int>>());
    }else if(role == NoteIsTemp) {
        note.setIsTempNote(value.toBool());
    }else if(role == NoteParentName) {
        note.setParentName(value.toString());
    } else if (role == NoteTagListScrollbarPos) {
        note.setTagListScrollBarPos(value.toInt());
    } else if (role == NoteIsPinned) {
        bool isPinned = value.toBool();
        if (isInAllNote()) {
            note.setIsPinnedNoteAN(isPinned);
        } else {
            note.setIsPinnedNote(isPinned);
        }
        QTimer::singleShot(0, this, [this, index, isPinned] {
            emit pinnedChanged(index, isPinned);
        });
    } else {
        return false;
    }

    emit dataChanged(this->index(index.row()),
                     this->index(index.row()),
                     QVector<int>(1,role));
    return true;
}

Qt::ItemFlags NoteListModel::flags(const QModelIndex &index) const
{
    if (!index.isValid()) {
        return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
    }

    return QAbstractListModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
}

int NoteListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_noteList.size() + m_pinnedList.size();
}

void NoteListModel::sort(int column, Qt::SortOrder order)
{
    Q_UNUSED(column)
    Q_UNUSED(order)

    std::stable_sort(m_pinnedList.begin(), m_pinnedList.end(), [](const NodeData& lhs, const NodeData& rhs){
        return lhs.relativePosition() < rhs.relativePosition();
    });

    std::stable_sort(m_noteList.begin(), m_noteList.end(), [](const NodeData& lhs, const NodeData& rhs){
        return lhs.lastModificationdateTime() > rhs.lastModificationdateTime();
    });

    emit dataChanged(index(0), index(rowCount()-1));
}

void NoteListModel::setNoteData(const QModelIndex &index, const NodeData &note)
{
    if (!index.isValid()) {
        return;
    }
    auto row = index.row();
    if (row < m_pinnedList.size()) {
        m_pinnedList[row] = note;
    } else {
        row = row - m_pinnedList.size();
        m_noteList[row] = note;
    }
    emit dataChanged(this->index(index.row()),
                     this->index(index.row()));
}

void NoteListModel::onPinnedChanged(const QModelIndex &index, bool isPinned)
{
    int sourceRow = index.row();
    if (sourceRow < 0 || sourceRow >= rowCount()) {
        return;
    }
    auto sourceParent = index;

    if (isInAllNote()) {
        emit requestUpdatePinnedAN(index.data(NoteID).toInt(), isPinned);
    } else {
        emit requestUpdatePinned(index.data(NoteID).toInt(), isPinned);
    }
    if (isPinned && (sourceRow - m_pinnedList.size()) >= 0
            && (sourceRow - m_pinnedList.size()) < m_noteList.size()) {
        int destinationChild = 0;
        auto destinationParent = this->index(destinationChild);
        if (beginMoveRows(sourceParent,sourceRow,sourceRow,destinationParent,destinationChild)) {
            m_pinnedList.prepend(m_noteList.takeAt(sourceRow - m_pinnedList.size()));
            endMoveRows();
            emit rowCountChanged();
            updatePinnedRelativePosition();
        }
    }

    if ((!isPinned) && (sourceRow < m_pinnedList.size())) {
        int destinationChild = 0;
        auto lastMod = index.data(NoteCreationDateTime).toDateTime();
        for (destinationChild = 0; destinationChild < m_noteList.size(); ++destinationChild) {
            const auto& note = m_noteList[destinationChild];
            if (note.lastModificationdateTime() <= lastMod) {
                break;
            }
        }
        auto destc = destinationChild + m_pinnedList.size() - 1;
        auto destinationParent = this->index(destc);

        if (beginMoveRows(sourceParent,sourceRow,sourceRow,destinationParent,destc)) {
            m_noteList.insert(destinationChild, m_pinnedList.takeAt(sourceRow));
            endMoveRows();
            emit rowCountChanged();
            updatePinnedRelativePosition();
        }
    }
}

void NoteListModel::updatePinnedRelativePosition()
{
    for (int i = 0; i < m_pinnedList.size(); ++i) {
        if (!isInAllNote()) {
            emit requestUpdatePinnedRelPos(m_pinnedList[i].id(), i);
        } else {
            emit requestUpdatePinnedRelPosAN(m_pinnedList[i].id(), i);
        }
    }
}

bool NoteListModel::isInAllNote() const
{
    return (!m_listViewInfo.isInTag) && (m_listViewInfo.parentFolderId == SpecialNodeID::RootFolder);
}

bool NoteListModel::noteIsPinned(const NodeData &note) const
{
    if (isInAllNote()) {
        return note.isPinnedNoteAN();
    } else {
        return note.isPinnedNote();
    }
}

Qt::DropActions NoteListModel::supportedDropActions() const
{
    return Qt::MoveAction;
}

Qt::DropActions NoteListModel::supportedDragActions() const
{
    return Qt::MoveAction;
}

QStringList NoteListModel::mimeTypes() const
{
    return QStringList() << NOTE_MIME;
}

QMimeData *NoteListModel::mimeData(const QModelIndexList &indexes) const
{
    if (indexes.isEmpty()) {
        return nullptr;
    }
    QMimeData *mimeData = new QMimeData;
    const auto& current = indexes[0];
    mimeData->setData(NOTE_MIME, QString::number(
                          current.data(NoteListModel::NoteID).toInt()).toUtf8());
    return mimeData;
}

bool NoteListModel::dropMimeData(const QMimeData *mime,
                                 Qt::DropAction action,
                                 int row, int column,
                                 const QModelIndex &parent)
{
    Q_UNUSED(column);

    if (!(mime->hasFormat(NOTE_MIME) &&
          action == Qt::MoveAction)) {
        return false;
    }
    if (row == -1) {
        // valid index: drop onto item
        if (parent.isValid()) {
            row = parent.row();
        } else {
            // invalid index: append at bottom, after last toplevel
            row = rowCount(parent);
        }
    }
    if (row >= m_pinnedList.size()) {
        return false;
    }
    bool ok = false;
    auto nodeId = QString::fromUtf8(mime->data(NOTE_MIME)).toInt(&ok);
    if (ok) {
        beginResetModel();
        for (int i = 0; i < m_pinnedList.size(); ++i) {
            if (m_pinnedList[i].id() == nodeId) {
                vector_move(m_pinnedList, i, row);
                break;
            }
        }

        endResetModel();
        emit setCurrentIndex(getNoteIndex(nodeId));
        updatePinnedRelativePosition();
        return true;
    }

    return false;
}

QModelIndex NoteListModel::firstUnpinnedIndex() const
{
    if (!m_noteList.isEmpty()) {
        return createIndex(m_pinnedList.size(), 0);
    } else {
        return QModelIndex();
    }
}

bool NoteListModel::noteIsHaveTag(const QModelIndex index) const
{
    if (index.row() < 0 || index.row() >= (m_noteList.count() + m_pinnedList.count())) {
        return false;
    }
    auto row = index.row();
    NodeData note;
    if (row < m_pinnedList.size()) {
        note = m_pinnedList[row];
    } else {
        row = row - m_pinnedList.size();
        note = m_noteList[row];
    }
    return !note.tagIds().empty();
}
<commit_msg> 5. There is the problem of changes not being saved again here: If I change the pinned notes order and get out of the app and then restart the app again the changes are not saved.<commit_after>#include "notelistmodel.h"
#include <QDebug>
#include "nodepath.h"
#include <QTimer>
#include <QMimeData>

NoteListModel::NoteListModel(QObject *parent)
    : QAbstractListModel(parent)
{
    connect(this, &NoteListModel::pinnedChanged,
            this, &NoteListModel::onPinnedChanged);
}

NoteListModel::~NoteListModel()
{

}

QModelIndex NoteListModel::addNote(const NodeData& note)
{
    if (!noteIsPinned(note)) {
        const int rowCnt = rowCount();
        beginInsertRows(QModelIndex(), rowCnt, rowCnt);
        m_noteList << note;
        endInsertRows();
        emit rowCountChanged();
        return createIndex(rowCnt, 0);
    } else {
        const int rowCnt = m_pinnedList.size();
        beginInsertRows(QModelIndex(), rowCnt, rowCnt);
        m_pinnedList << note;
        endInsertRows();
        emit rowCountChanged();
        return createIndex(rowCnt, 0);
    }
}

QModelIndex NoteListModel::insertNote(const NodeData &note, int row)
{
    if (noteIsPinned(note)) {
        if (row > m_pinnedList.size()) {
            row = m_pinnedList.size();
        } else if (row < 0) {
            row = 0;
        }
        beginInsertRows(QModelIndex(), row, row);
        m_pinnedList.insert(row, note);
        endInsertRows();
        emit rowCountChanged();
        return createIndex(row, 0);
    } else {
        if (row < m_pinnedList.size()) {
            row = m_pinnedList.size();
        } else if (row > (m_pinnedList.size() + m_noteList.size())) {
            row = m_pinnedList.size() + m_noteList.size();
        }
        beginInsertRows(QModelIndex(), row, row);
        m_noteList.insert(row - m_pinnedList.size(), note);
        endInsertRows();
        emit rowCountChanged();
        return createIndex(row, 0);
    }
}

NodeData NoteListModel::getNote(const QModelIndex& index) const
{
    auto row = index.row();
    if (row < m_pinnedList.size()) {
        return m_pinnedList.at(row);
    } else {
        row = row - m_pinnedList.size();
        return m_noteList.at(row);
    }
}

QModelIndex NoteListModel::getNoteIndex(int id) const
{
    for (int i = 0; i < m_pinnedList.size(); ++i) {
        if (m_pinnedList[i].id() == id) {
            return createIndex(i, 0);
        }
    }

    for (int i = 0; i < m_noteList.size(); ++i) {
        if (m_noteList[i].id() == id) {
            return createIndex(i + m_pinnedList.size(), 0);
        }
    }
    return QModelIndex{};
}

void NoteListModel::setListNote(const QVector<NodeData> notes, const ListViewInfo& inf)
{
    beginResetModel();
    m_pinnedList.clear();
    m_noteList.clear();
    m_listViewInfo = inf;
    if ((!m_listViewInfo.isInTag) && (m_listViewInfo.parentFolderId != SpecialNodeID::TrashFolder)) {
        for (const auto& note : QT_AS_CONST(notes)) {
            if (noteIsPinned(note)) {
                m_pinnedList.append(note);
            } else {
                m_noteList.append(note);
            }
        }
    } else {
        m_noteList = notes;
    }
    sort(0, Qt::AscendingOrder);
    endResetModel();
    emit rowCountChanged();
}

void NoteListModel::removeNote(const QModelIndex &noteIndex)
{
    if (noteIndex.isValid()) {
        int row = noteIndex.row();
        beginRemoveRows(QModelIndex(), row, row);
        if (row < m_pinnedList.size()) {
            m_pinnedList.takeAt(row);
        } else {
            row = row - m_pinnedList.size();
            m_noteList.takeAt(row);
        }
        endRemoveRows();
        emit rowCountChanged();
    }
}

bool NoteListModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild)
{
    if(sourceRow < 0
            || sourceRow >= rowCount()
            || destinationChild <0
            || destinationChild >= rowCount()) {
        return false;
    }
    if (sourceRow < m_pinnedList.size() && destinationChild < m_pinnedList.size()) {
        if (beginMoveRows(sourceParent,sourceRow,sourceRow,destinationParent,destinationChild)) {
            vector_move(m_pinnedList, sourceRow, destinationChild);
            endMoveRows();
            emit rowCountChanged();
            return true;
        }
    }
    if (sourceRow >= m_pinnedList.size() && destinationChild >= m_pinnedList.size()) {
        sourceRow = sourceRow - m_pinnedList.size();
        destinationChild = destinationChild - m_pinnedList.size();
        if (beginMoveRows(sourceParent,sourceRow,sourceRow,destinationParent,destinationChild)) {
            vector_move(m_noteList, sourceRow, destinationChild);
            endMoveRows();
            emit rowCountChanged();
            return true;
        }
    }
    return false;
}

void NoteListModel::clearNotes()
{
    beginResetModel();
    m_pinnedList.clear();
    m_noteList.clear();
    endResetModel();
    emit rowCountChanged();
}

QVariant NoteListModel::data(const QModelIndex &index, int role) const
{
    if (index.row() < 0 || index.row() >= (m_noteList.count() + m_pinnedList.count())) {
        return QVariant();
    }
    auto row = index.row();
    NodeData note;
    if (row < m_pinnedList.size()) {
        note = m_pinnedList[row];
    } else {
        row = row - m_pinnedList.size();
        note = m_noteList[row];
    }
    if(role == NoteID){
        return note.id();
    }else if(role == NoteFullTitle){
        return note.fullTitle();
    }else if(role == NoteCreationDateTime){
        return note.creationDateTime();
    }else if(role == NoteLastModificationDateTime){
        return note.lastModificationdateTime();
    }else if(role == NoteDeletionDateTime){
        return note.deletionDateTime();
    }else if(role == NoteContent){
        return note.content();
    }else if(role == NoteScrollbarPos){
        return note.scrollBarPosition();
    }else if(role == NoteTagsList){
        return QVariant::fromValue(note.tagIds());
    }else if(role == NoteIsTemp){
        return note.isTempNote();
    }else if(role == NoteParentName){
        return note.parentName();
    } else if (role == NoteTagListScrollbarPos) {
        return note.tagListScrollBarPos();
    } else if (role == NoteIsPinned) {
        if (isInAllNote()) {
            return note.isPinnedNoteAN();
        } else {
            return note.isPinnedNote();
        }
    }

    return QVariant();
}

bool NoteListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.row() < 0 || index.row() >= (m_noteList.count() + m_pinnedList.count())) {
        return false;
    }

    auto getRef = [this] (int row) -> NodeData& {
        NodeData note;
        if (row < m_pinnedList.size()) {
            return m_pinnedList[row];
        } else {
            row = row - m_pinnedList.size();
            return m_noteList[row];
        }
    };
    NodeData& note = getRef(index.row());
    if(role == NoteID){
        note.setId(value.toInt());
    }else if(role == NoteFullTitle){
        note.setFullTitle(value.toString());
    }else if(role == NoteCreationDateTime){
        note.setCreationDateTime(value.toDateTime());
    }else if(role == NoteLastModificationDateTime){
        note.setLastModificationDateTime(value.toDateTime());
    }else if(role == NoteDeletionDateTime){
        note.setDeletionDateTime(value.toDateTime());
    }else if(role == NoteContent){
        note.setContent(value.toString());
    }else if(role == NoteScrollbarPos){
        note.setScrollBarPosition(value.toInt());
    }else if(role == NoteTagsList) {
        note.setTagIds(value.value<QSet<int>>());
    }else if(role == NoteIsTemp) {
        note.setIsTempNote(value.toBool());
    }else if(role == NoteParentName) {
        note.setParentName(value.toString());
    } else if (role == NoteTagListScrollbarPos) {
        note.setTagListScrollBarPos(value.toInt());
    } else if (role == NoteIsPinned) {
        bool isPinned = value.toBool();
        if (isInAllNote()) {
            note.setIsPinnedNoteAN(isPinned);
        } else {
            note.setIsPinnedNote(isPinned);
        }
        QTimer::singleShot(0, this, [this, index, isPinned] {
            emit pinnedChanged(index, isPinned);
        });
    } else {
        return false;
    }

    emit dataChanged(this->index(index.row()),
                     this->index(index.row()),
                     QVector<int>(1,role));
    return true;
}

Qt::ItemFlags NoteListModel::flags(const QModelIndex &index) const
{
    if (!index.isValid()) {
        return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
    }

    return QAbstractListModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
}

int NoteListModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_noteList.size() + m_pinnedList.size();
}

void NoteListModel::sort(int column, Qt::SortOrder order)
{
    Q_UNUSED(column)
    Q_UNUSED(order)

    std::stable_sort(m_pinnedList.begin(), m_pinnedList.end(), [this](const NodeData& lhs, const NodeData& rhs) {
        if (isInAllNote()) {
            return lhs.relativePosAN() < rhs.relativePosAN();
        } else {
            return lhs.relativePosition() < rhs.relativePosition();
        }
    });

    std::stable_sort(m_noteList.begin(), m_noteList.end(), [](const NodeData& lhs, const NodeData& rhs){
        return lhs.lastModificationdateTime() > rhs.lastModificationdateTime();
    });

    emit dataChanged(index(0), index(rowCount()-1));
}

void NoteListModel::setNoteData(const QModelIndex &index, const NodeData &note)
{
    if (!index.isValid()) {
        return;
    }
    auto row = index.row();
    if (row < m_pinnedList.size()) {
        m_pinnedList[row] = note;
    } else {
        row = row - m_pinnedList.size();
        m_noteList[row] = note;
    }
    emit dataChanged(this->index(index.row()),
                     this->index(index.row()));
}

void NoteListModel::onPinnedChanged(const QModelIndex &index, bool isPinned)
{
    int sourceRow = index.row();
    if (sourceRow < 0 || sourceRow >= rowCount()) {
        return;
    }
    auto sourceParent = index;

    if (isInAllNote()) {
        emit requestUpdatePinnedAN(index.data(NoteID).toInt(), isPinned);
    } else {
        emit requestUpdatePinned(index.data(NoteID).toInt(), isPinned);
    }
    if (isPinned && (sourceRow - m_pinnedList.size()) >= 0
            && (sourceRow - m_pinnedList.size()) < m_noteList.size()) {
        int destinationChild = 0;
        auto destinationParent = this->index(destinationChild);
        if (beginMoveRows(sourceParent,sourceRow,sourceRow,destinationParent,destinationChild)) {
            m_pinnedList.prepend(m_noteList.takeAt(sourceRow - m_pinnedList.size()));
            endMoveRows();
            emit rowCountChanged();
            updatePinnedRelativePosition();
        }
    }

    if ((!isPinned) && (sourceRow < m_pinnedList.size())) {
        int destinationChild = 0;
        auto lastMod = index.data(NoteCreationDateTime).toDateTime();
        for (destinationChild = 0; destinationChild < m_noteList.size(); ++destinationChild) {
            const auto& note = m_noteList[destinationChild];
            if (note.lastModificationdateTime() <= lastMod) {
                break;
            }
        }
        auto destc = destinationChild + m_pinnedList.size() - 1;
        auto destinationParent = this->index(destc);

        if (beginMoveRows(sourceParent,sourceRow,sourceRow,destinationParent,destc)) {
            m_noteList.insert(destinationChild, m_pinnedList.takeAt(sourceRow));
            endMoveRows();
            emit rowCountChanged();
            updatePinnedRelativePosition();
        }
    }
}

void NoteListModel::updatePinnedRelativePosition()
{
    for (int i = 0; i < m_pinnedList.size(); ++i) {
        if (!isInAllNote()) {
            emit requestUpdatePinnedRelPos(m_pinnedList[i].id(), i);
        } else {
            emit requestUpdatePinnedRelPosAN(m_pinnedList[i].id(), i);
        }
    }
}

bool NoteListModel::isInAllNote() const
{
    return (!m_listViewInfo.isInTag) && (m_listViewInfo.parentFolderId == SpecialNodeID::RootFolder);
}

bool NoteListModel::noteIsPinned(const NodeData &note) const
{
    if (isInAllNote()) {
        return note.isPinnedNoteAN();
    } else {
        return note.isPinnedNote();
    }
}

Qt::DropActions NoteListModel::supportedDropActions() const
{
    return Qt::MoveAction;
}

Qt::DropActions NoteListModel::supportedDragActions() const
{
    return Qt::MoveAction;
}

QStringList NoteListModel::mimeTypes() const
{
    return QStringList() << NOTE_MIME;
}

QMimeData *NoteListModel::mimeData(const QModelIndexList &indexes) const
{
    if (indexes.isEmpty()) {
        return nullptr;
    }
    QMimeData *mimeData = new QMimeData;
    const auto& current = indexes[0];
    mimeData->setData(NOTE_MIME, QString::number(
                          current.data(NoteListModel::NoteID).toInt()).toUtf8());
    return mimeData;
}

bool NoteListModel::dropMimeData(const QMimeData *mime,
                                 Qt::DropAction action,
                                 int row, int column,
                                 const QModelIndex &parent)
{
    Q_UNUSED(column);

    if (!(mime->hasFormat(NOTE_MIME) &&
          action == Qt::MoveAction)) {
        return false;
    }
    if (row == -1) {
        // valid index: drop onto item
        if (parent.isValid()) {
            row = parent.row();
        } else {
            // invalid index: append at bottom, after last toplevel
            row = rowCount(parent);
        }
    }
    if (row >= m_pinnedList.size()) {
        return false;
    }
    bool ok = false;
    auto nodeId = QString::fromUtf8(mime->data(NOTE_MIME)).toInt(&ok);
    if (ok) {
        beginResetModel();
        for (int i = 0; i < m_pinnedList.size(); ++i) {
            if (m_pinnedList[i].id() == nodeId) {
                vector_move(m_pinnedList, i, row);
                break;
            }
        }

        endResetModel();
        emit setCurrentIndex(getNoteIndex(nodeId));
        updatePinnedRelativePosition();
        return true;
    }

    return false;
}

QModelIndex NoteListModel::firstUnpinnedIndex() const
{
    if (!m_noteList.isEmpty()) {
        return createIndex(m_pinnedList.size(), 0);
    } else {
        return QModelIndex();
    }
}

bool NoteListModel::noteIsHaveTag(const QModelIndex index) const
{
    if (index.row() < 0 || index.row() >= (m_noteList.count() + m_pinnedList.count())) {
        return false;
    }
    auto row = index.row();
    NodeData note;
    if (row < m_pinnedList.size()) {
        note = m_pinnedList[row];
    } else {
        row = row - m_pinnedList.size();
        note = m_noteList[row];
    }
    return !note.tagIds().empty();
}
<|endoftext|>


<commit_before>// Copyright (C) [2012, 2013] [AB2 Technologies] [Austin Beam, Alan Bullick]
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

// MSP430 TLC5925 library

#include "tlc5925.h"

// Logical AND with existing channel data written to the TLC
void inline tlc5925::andWrite(uint16_t channel_data)
{
  write((pres_channel_data & channel_data));
}

// Scans through all TLC5925 channels from high to low beginning with the
// specified channel for the specified number of scans
void tlc5925::channelScanDown(uint16_t scan_quantity)
{
  uint8_t i;
  uint16_t next_ch = start_ch;

  for (scan_quantity; scan_quantity > 0; scan_quantity--)
  {
    for (i=(TLC5925_NUM_CHANNELS + 1); i>0; i--)
    {
      write(next_ch);
      next_ch = rlc(next_ch);
      clk->delayMS(anim_delay);
    }
  }
}

// Scans through all TLC5925 channels from low to high beginning with the
// specified channel for the specified number of scans
void tlc5925::channelScanUp(uint16_t scan_quantity)
{
  uint8_t i;
  uint16_t next_ch = start_ch;

  for (scan_quantity; scan_quantity > 0; scan_quantity--)
  {
    for (i=(TLC5925_NUM_CHANNELS + 1); i>0; i--)
    {
      write(next_ch);
      next_ch = rrc(next_ch);
      clk->delayMS(anim_delay);
    }
  }
}

// Clear the TLC5925 by writing zeros
void tlc5925::clear(void)
{
  tlc_spi.risingEdge();
  tlc_spi.write(0);
  tlc_spi.write(0);
  latch();
}

// Retrieve the instance start_ch value
tlc5925_ch_t inline tlc5925::getStartCh(void)
{
  return (start_ch);
}

// Pulses the provided channel data for the specified pulse quantity
void tlc5925::flash(uint16_t pulse_quantity, uint16_t channel_data)
{
  outputDisable();
  write(channel_data);
  for (pulse_quantity; pulse_quantity>0; pulse_quantity--)
  {
    outputEnable();
    clk->delayMS(anim_delay);
    outputDisable();
    clk->delayMS(anim_delay);
  }
}

// Toggles TLC5925 latch bit high
void inline tlc5925::latch(void)
{
  pinPulse(le);
}

// Logical OR with existing channel data written to the TLC
void inline tlc5925::orWrite(uint16_t channel_data)
{
  write((pres_channel_data | channel_data));
}

// Sets TLC5925 output enable bit high (active low)
void tlc5925::outputDisable(void)
{
  if (oe != MSP_PIN_SIZE)
    pinOn(oe);
  else
    clear();
}

// Sets TLC5925 output enable bit low (active low)
void inline tlc5925::outputEnable(void)
{
  if (oe != MSP_PIN_SIZE)
    pinOff(oe);
  else
    write(pres_channel_data);
}

// Re-configure start channel
void inline tlc5925::setStartCh(tlc5925_ch_t ch)
{
  set(start_ch, ch);
}

// Rotates the specified TLC5925 channel data up (left shift with carry) the
// channels
void tlc5925::shiftDown(uint16_t shift_quantity, uint16_t channel_data)
{
  for (shift_quantity; shift_quantity>0; shift_quantity--)
  {
    write(channel_data);
    channel_data = rlc(channel_data);
    clk->delayMS(anim_delay);
  }
}

// Rotates the specified TLC5925 channel data up (right shift with carry) the
// channels
void tlc5925::shiftUp(uint16_t shift_quantity , uint16_t channel_data)
{
  for (shift_quantity; shift_quantity>0; shift_quantity--)
  {
    write(channel_data);
    channel_data = rrc(channel_data);
    clk->delayMS(anim_delay);
  }
}

// Writes channel data to TLC5925
void tlc5925::write(uint16_t channel_data)
{
  pres_channel_data = channel_data;

  tlc_spi.risingEdge();
  if (oe != MSP_PIN_SIZE)
    outputDisable();
  tlc_spi.write((pres_channel_data >> 8) & 0xFF);
  tlc_spi.write(pres_channel_data & 0xFF);
  latch();
  if (oe != MSP_PIN_SIZE)
    outputEnable();
}

<commit_msg>msp/tlc5925: Removed empty expression from loops<commit_after>// Copyright (C) [2012, 2013] [AB2 Technologies] [Austin Beam, Alan Bullick]
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

// MSP430 TLC5925 library

#include "tlc5925.h"

// Logical AND with existing channel data written to the TLC
void inline tlc5925::andWrite(uint16_t channel_data)
{
  write((pres_channel_data & channel_data));
}

// Scans through all TLC5925 channels from high to low beginning with the
// specified channel for the specified number of scans
void tlc5925::channelScanDown(uint16_t scan_quantity)
{
  uint8_t i;
  uint16_t next_ch = start_ch;

  for ( ; scan_quantity > 0; scan_quantity--)
  {
    for (i=(TLC5925_NUM_CHANNELS + 1); i>0; i--)
    {
      write(next_ch);
      next_ch = rlc(next_ch);
      clk->delayMS(anim_delay);
    }
  }
}

// Scans through all TLC5925 channels from low to high beginning with the
// specified channel for the specified number of scans
void tlc5925::channelScanUp(uint16_t scan_quantity)
{
  uint8_t i;
  uint16_t next_ch = start_ch;

  for ( ; scan_quantity > 0; scan_quantity--)
  {
    for (i=(TLC5925_NUM_CHANNELS + 1); i>0; i--)
    {
      write(next_ch);
      next_ch = rrc(next_ch);
      clk->delayMS(anim_delay);
    }
  }
}

// Clear the TLC5925 by writing zeros
void tlc5925::clear(void)
{
  tlc_spi.risingEdge();
  tlc_spi.write(0);
  tlc_spi.write(0);
  latch();
}

// Retrieve the instance start_ch value
tlc5925_ch_t inline tlc5925::getStartCh(void)
{
  return (start_ch);
}

// Pulses the provided channel data for the specified pulse quantity
void tlc5925::flash(uint16_t pulse_quantity, uint16_t channel_data)
{
  outputDisable();
  write(channel_data);
  for ( ; pulse_quantity>0; pulse_quantity--)
  {
    outputEnable();
    clk->delayMS(anim_delay);
    outputDisable();
    clk->delayMS(anim_delay);
  }
}

// Toggles TLC5925 latch bit high
void inline tlc5925::latch(void)
{
  pinPulse(le);
}

// Logical OR with existing channel data written to the TLC
void inline tlc5925::orWrite(uint16_t channel_data)
{
  write((pres_channel_data | channel_data));
}

// Sets TLC5925 output enable bit high (active low)
void tlc5925::outputDisable(void)
{
  if (oe != MSP_PIN_SIZE)
    pinOn(oe);
  else
    clear();
}

// Sets TLC5925 output enable bit low (active low)
void inline tlc5925::outputEnable(void)
{
  if (oe != MSP_PIN_SIZE)
    pinOff(oe);
  else
    write(pres_channel_data);
}

// Re-configure start channel
void inline tlc5925::setStartCh(tlc5925_ch_t ch)
{
  set(start_ch, ch);
}

// Rotates the specified TLC5925 channel data up (left shift with carry) the
// channels
void tlc5925::shiftDown(uint16_t shift_quantity, uint16_t channel_data)
{
  for ( ; shift_quantity>0; shift_quantity--)
  {
    write(channel_data);
    channel_data = rlc(channel_data);
    clk->delayMS(anim_delay);
  }
}

// Rotates the specified TLC5925 channel data up (right shift with carry) the
// channels
void tlc5925::shiftUp(uint16_t shift_quantity , uint16_t channel_data)
{
  for ( ; shift_quantity>0; shift_quantity--)
  {
    write(channel_data);
    channel_data = rrc(channel_data);
    clk->delayMS(anim_delay);
  }
}

// Writes channel data to TLC5925
void tlc5925::write(uint16_t channel_data)
{
  pres_channel_data = channel_data;

  tlc_spi.risingEdge();
  if (oe != MSP_PIN_SIZE)
    outputDisable();
  tlc_spi.write((pres_channel_data >> 8) & 0xFF);
  tlc_spi.write(pres_channel_data & 0xFF);
  latch();
  if (oe != MSP_PIN_SIZE)
    outputEnable();
}

<|endoftext|>


<commit_before>// musicPlayer.hpp
// 26. April 2017
// Created by:
// 		Bryan Burkhardt (bmburkhardt@alaska.edu)
// 		Alexander Eckert (aeckert@alaska.edu)
// 		Jeremiah Jacobson (jjjacobson2@alaska.edu)
// 		Jarye Maurphy (@alaska.edu)
// 		Cameron Showalter (@alaska.edu)
//
// Header for MusicPlayer class

#ifndef MUSICPLAYER_HPP
#define MUSICPLAYER_HPP

#include <vector>
#include <memory>

#include "textureManager.hpp"

// define version numbers
// set in CMakeLists.txt file
#define myproject_VERSION_MAJOR 0
#define myproject_VERSION_MINOR 1

// define window size
#define WINDOW_WIDTH 700
#define WINDOW_HEIGHT 300

class MusicPlayer {
public:
<<<<<<< Updated upstream
	sf::RenderWindow window;
	TextureManager texmgr;

	std::vector<sf::Sprite> spriteVec;

	sf::SoundBuffer buffer;
	sf::Music music;

	sf::Font font;
	sf::Text prevSong;
	sf::Text currentSong;
	sf::Text nextSong;
	sf::Text next2Song;
	sf::Text next3Song;
	sf::Text next4Song;

	sf::Sprite musicPlayerBG;
	sf::Sprite playPauseButton;
	sf::Sprite prevButton;
	sf::Sprite nextButton;
	sf::Sprite muteButton;
	sf::Sprite decreaseVolumeButton;
	sf::Sprite increaseVolumeButton;

=======
>>>>>>> Stashed changes
	void playerLoop();

	MusicPlayer();
	~MusicPlayer() = default;

	void draw();
	void update();
<<<<<<< Updated upstream
	void handleInput();
	bool clickInSprite(sf::Sprite s, int x , int y);

	/****** Functionality Functions ******/
	void callPlayPause();
	void callNextSong();
	void callPrevSong();
	void callIncreaseVolume();
	void callDecreaseVolume();
	void callMuteUnmute();

	/****** Update Functions ******/
	void mouseOverHighlight();
	void displayPlaylist();

private:
	void loadTextures();

	std::vector<std::string> songList_;
	unsigned int songListIndex_ = 0;

	unsigned int volSave_;
	bool isMuted_;

	std::unique_ptr<MusicPlayer> musicPlayer;
=======

private:

	/****** Update Functions ******/
	void mouseOverHighlight();
	void displayPlaylist();
	std::unique_ptr<GUI> gui;
	Music music;
>>>>>>> Stashed changes
};

#endif // #ifndef MUSICPLAYER_HPP
<commit_msg>fix some merge stuff<commit_after>// musicPlayer.hpp
// 26. April 2017
// Created by:
// 		Bryan Burkhardt (bmburkhardt@alaska.edu)
// 		Alexander Eckert (aeckert@alaska.edu)
// 		Jeremiah Jacobson (jjjacobson2@alaska.edu)
// 		Jarye Maurphy (@alaska.edu)
// 		Cameron Showalter (@alaska.edu)
//
// Header for MusicPlayer class

#ifndef MUSICPLAYER_HPP
#define MUSICPLAYER_HPP

#include <vector>
#include <memory>

#include "GUI.hpp"

// define version numbers
// set in CMakeLists.txt file
#define myproject_VERSION_MAJOR 0
#define myproject_VERSION_MINOR 1

class MusicPlayer {
public:
	void playerLoop();

	MusicPlayer();
	~MusicPlayer() = default;

	void update();
	void handleInput();

private:

	/****** Update Functions ******/
	void mouseOverHighlight();
	void displayPlaylist();
	std::unique_ptr<GUI> gui;
	std::unique_ptr<Music> music;
};

#endif // #ifndef MUSICPLAYER_HPP
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This is a small program that tries to connect to the X server.  It
// continually retries until it connects or 5 seconds pass.  If it fails
// to connect to the X server after 5 seconds, it returns an error code
// of -1.
//
// This is to help verify that the X server is available before we start
// start running tests on the build bots.

#include <errno.h>
#include <stdio.h>
#include <time.h>
#include <X11/Xlib.h>

#if defined(TOUCH_UI) || defined(USE_AURA)
#include <X11/extensions/XInput2.h>
#endif

void Sleep(int duration_ms) {
  struct timespec sleep_time, remaining;

  // Contains the portion of duration_ms >= 1 sec.
  sleep_time.tv_sec = duration_ms / 1000;
  duration_ms -= sleep_time.tv_sec * 1000;

  // Contains the portion of duration_ms < 1 sec.
  sleep_time.tv_nsec = duration_ms * 1000 * 1000;  // nanoseconds.

  while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
    sleep_time = remaining;
}

int main(int argc, char* argv[]) {
  int kNumTries = 50;
  Display* display = NULL;
  for (int i = 0; i < kNumTries; ++i) {
    display = XOpenDisplay(NULL);
    if (display)
      break;
    Sleep(100);
  }

  if (!display) {
    fprintf(stderr, "Failed to connect to %s\n", XDisplayName(NULL));
    return -1;
  }

#if defined(TOUCH_UI) || defined(USE_AURA)
  // Check for XInput2
  int opcode, event, err;
  if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &err)) {
    fprintf(stderr,
        "Failed to get XInputExtension on %s.\n", XDisplayName(NULL));
    return -1;
  }

  int major = 2, minor = 0;
  if (XIQueryVersion(display, &major, &minor) == BadRequest) {
    fprintf(stderr,
        "Server does not have XInput2 on %s.\n", XDisplayName(NULL));
    return -1;
  }

  // Ask for the list of devices. This can cause some Xvfb to crash.
  int count = 0;
  XIDeviceInfo* devices = XIQueryDevice(display, XIAllDevices, &count);
  if (devices)
    XIFreeDeviceInfo(devices);
#endif

  return 0;
}
<commit_msg>xdisplaycheck: Remove obsolete check.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This is a small program that tries to connect to the X server.  It
// continually retries until it connects or 5 seconds pass.  If it fails
// to connect to the X server after 5 seconds, it returns an error code
// of -1.
//
// This is to help verify that the X server is available before we start
// start running tests on the build bots.

#include <errno.h>
#include <stdio.h>
#include <time.h>
#include <X11/Xlib.h>

#if defined(USE_AURA)
#include <X11/extensions/XInput2.h>
#endif

void Sleep(int duration_ms) {
  struct timespec sleep_time, remaining;

  // Contains the portion of duration_ms >= 1 sec.
  sleep_time.tv_sec = duration_ms / 1000;
  duration_ms -= sleep_time.tv_sec * 1000;

  // Contains the portion of duration_ms < 1 sec.
  sleep_time.tv_nsec = duration_ms * 1000 * 1000;  // nanoseconds.

  while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
    sleep_time = remaining;
}

int main(int argc, char* argv[]) {
  int kNumTries = 50;
  Display* display = NULL;
  for (int i = 0; i < kNumTries; ++i) {
    display = XOpenDisplay(NULL);
    if (display)
      break;
    Sleep(100);
  }

  if (!display) {
    fprintf(stderr, "Failed to connect to %s\n", XDisplayName(NULL));
    return -1;
  }

#if defined(USE_AURA)
  // Check for XInput2
  int opcode, event, err;
  if (!XQueryExtension(display, "XInputExtension", &opcode, &event, &err)) {
    fprintf(stderr,
        "Failed to get XInputExtension on %s.\n", XDisplayName(NULL));
    return -1;
  }

  int major = 2, minor = 0;
  if (XIQueryVersion(display, &major, &minor) == BadRequest) {
    fprintf(stderr,
        "Server does not have XInput2 on %s.\n", XDisplayName(NULL));
    return -1;
  }

  // Ask for the list of devices. This can cause some Xvfb to crash.
  int count = 0;
  XIDeviceInfo* devices = XIQueryDevice(display, XIAllDevices, &count);
  if (devices)
    XIFreeDeviceInfo(devices);
#endif

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: svcommstream.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-07 19:18:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <tools/stream.hxx>

#include "commtypes.hxx"
#include "icommstream.hxx"

class SvCommStream : public ICommStream
{
protected:
    SvStream* pStream;
public:

    SvCommStream( SvStream* pIO );
    ~SvCommStream();

    ICommStream&        operator>>( USHORT& rUShort );
    ICommStream&        operator>>( ULONG& rULong );
    ICommStream&        operator>>( unsigned char& rChar );

    ICommStream&        operator<<( USHORT nUShort );
    ICommStream&        operator<<( ULONG nULong );
    ICommStream&        operator<<( unsigned char nChar );

    ULONG           Read( void* pData, ULONG nSize );
    ULONG           Write( const void* pData, ULONG nSize );

    BOOL            IsEof() const;
    ULONG           SeekRel( long nPos );
};
<commit_msg>INTEGRATION: CWS sixtyfour05 (1.2.30); FILE MERGED 2006/04/13 10:31:52 cmc 1.2.30.1: #i63183# automation 64bit fixes<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: svcommstream.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2006-04-19 13:57:39 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <tools/stream.hxx>

#include "commtypes.hxx"
#include "icommstream.hxx"

class SvCommStream : public ICommStream
{
protected:
    SvStream* pStream;
public:

    SvCommStream( SvStream* pIO );
    ~SvCommStream();

    ICommStream&        operator>>( comm_USHORT& rUShort );
    ICommStream&        operator>>( comm_ULONG& rULong );
    ICommStream&        operator>>( comm_BOOL& rChar );

    ICommStream&        operator<<( comm_USHORT nUShort );
    ICommStream&        operator<<( comm_ULONG nULong );
    ICommStream&        operator<<( comm_BOOL nChar );

    comm_ULONG      Read( void* pData, comm_ULONG nSize );
    comm_ULONG      Write( const void* pData, comm_ULONG nSize );

    comm_BOOL       IsEof() const;
    comm_ULONG      SeekRel( long nPos );
};
<|endoftext|>


<commit_before>// Wheels - various C++ utilities
//
// Written in 2013 by Martinho Fernandes <martinho.fernandes@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all copyright and related
// and neighboring rights to this software to the public domain worldwide. This software is
// distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>

// Meta-programming facilities

#ifndef WHEELS_META_HPP
#define WHEELS_META_HPP

#include <wheels/meta/invoke.h++>
#include <wheels/meta/id.h++>
#include <wheels/meta/alias.h++>
#include <wheels/meta/not_deducible.h++>

#include <wheels/meta/constant.h++>
#include <wheels/meta/int.h++>
#include <wheels/meta/bool.h++>

#include <wheels/meta/void.h++>

#include <wheels/meta/if.h++>
#include <wheels/meta/invoke_if.h++>

#include <wheels/meta/enable_if.h++>
#include <wheels/meta/is_computable.h++>

#include <wheels/meta/depend_on.h++>

#include <wheels/meta/add_const.h++>
#include <wheels/meta/remove_const.h++>
#include <wheels/meta/add_volatile.h++>
#include <wheels/meta/remove_volatile.h++>
#include <wheels/meta/add_cv.h++>
#include <wheels/meta/remove_cv.h++>

#include <wheels/meta/add_lvalue_reference.h++>
#include <wheels/meta/add_rvalue_reference.h++>
#include <wheels/meta/remove_reference.h++>

#include <wheels/meta/decay.h++>
#include <wheels/meta/unqual.h++>
#include <wheels/meta/is_unqualified.h++>

#include <wheels/meta/qualifying_value_category_of.h++>
#include <wheels/meta/qualifying_const_of.h++>
#include <wheels/meta/qualifying_volatile_of.h++>
#include <wheels/meta/qualifying_cv_of.h++>
#include <wheels/meta/qualifying.h++>

#include <wheels/meta/add_pointer.h++>
#include <wheels/meta/remove_pointer.h++>

#include <wheels/meta/remove_extent.h++>
#include <wheels/meta/remove_all_extents.h++>

#include <wheels/meta/make_signed.h++>
#include <wheels/meta/make_unsigned.h++>

#include <wheels/meta/underlying_type.h++>
#include <wheels/meta/common_type.h++>

#include <wheels/meta/is_related.h++>

#include <wheels/meta/is_deduced.h++>

#include <wheels/meta/class_of.h++>
#include <wheels/meta/member_of.h++>

#endif // WHEELS_META_HPP

<commit_msg>Add missing #includes<commit_after>// Wheels - various C++ utilities
//
// Written in 2013 by Martinho Fernandes <martinho.fernandes@gmail.com>
//
// To the extent possible under law, the author(s) have dedicated all copyright and related
// and neighboring rights to this software to the public domain worldwide. This software is
// distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>

// Meta-programming facilities

#ifndef WHEELS_META_HPP
#define WHEELS_META_HPP

#include <wheels/meta/invoke.h++>
#include <wheels/meta/id.h++>
#include <wheels/meta/alias.h++>
#include <wheels/meta/not_deducible.h++>

#include <wheels/meta/constant.h++>
#include <wheels/meta/int.h++>
#include <wheels/meta/bool.h++>

#include <wheels/meta/not.h++>
#include <wheels/meta/any.h++>
#include <wheels/meta/all.h++>

#include <wheels/meta/void.h++>

#include <wheels/meta/if.h++>
#include <wheels/meta/invoke_if.h++>

#include <wheels/meta/enable_if.h++>
#include <wheels/meta/is_computable.h++>

#include <wheels/meta/depend_on.h++>
#include <wheels/meta/trait_of.h++>

#include <wheels/meta/add_const.h++>
#include <wheels/meta/remove_const.h++>
#include <wheels/meta/add_volatile.h++>
#include <wheels/meta/remove_volatile.h++>
#include <wheels/meta/add_cv.h++>
#include <wheels/meta/remove_cv.h++>

#include <wheels/meta/add_lvalue_reference.h++>
#include <wheels/meta/add_rvalue_reference.h++>
#include <wheels/meta/remove_reference.h++>

#include <wheels/meta/decay.h++>
#include <wheels/meta/unqual.h++>
#include <wheels/meta/is_unqualified.h++>

#include <wheels/meta/qualifying_value_category_of.h++>
#include <wheels/meta/qualifying_const_of.h++>
#include <wheels/meta/qualifying_volatile_of.h++>
#include <wheels/meta/qualifying_cv_of.h++>
#include <wheels/meta/qualifying.h++>

#include <wheels/meta/add_pointer.h++>
#include <wheels/meta/remove_pointer.h++>

#include <wheels/meta/remove_extent.h++>
#include <wheels/meta/remove_all_extents.h++>

#include <wheels/meta/make_signed.h++>
#include <wheels/meta/make_unsigned.h++>

#include <wheels/meta/underlying_type.h++>
#include <wheels/meta/common_type.h++>

#include <wheels/meta/is_related.h++>

#include <wheels/meta/is_deduced.h++>

#include <wheels/meta/class_of.h++>
#include <wheels/meta/member_of.h++>

#endif // WHEELS_META_HPP

<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osgSim/Sector>
#include <osg/Vec2>

using namespace osgSim;

//
// Elevation Range
//

void AzimRange::setAzimuthRange(float minAzimuth,float maxAzimuth,float fadeAngle)
{
    // clamp the azimuth range.
    const float twoPI = 2.0f*(float)osg::PI;
    while(minAzimuth>maxAzimuth) minAzimuth -= twoPI;

    // compute the centerline
    float centerAzim = (minAzimuth+maxAzimuth)*0.5f;
    _cosAzim = cos(centerAzim);
    _sinAzim = sin(centerAzim);

    // compute the half angle range of the sector.
    float angle = (maxAzimuth-minAzimuth)*0.5f;
    _cosAngle = cos(angle);

    // clamp the fade angle to valid values.
    fadeAngle = osg::clampAbove(fadeAngle,0.0f);
    if (angle+fadeAngle>osg::PI) _cosFadeAngle = -1.0f;
    else _cosFadeAngle = cos(angle+fadeAngle);

}

void AzimRange::getAzimuthRange(float& minAzimuth, float& maxAzimuth, float& fadeAngle) const
{
    float centerAzim = atan2(_sinAzim, _cosAzim);
    float angle = acos(_cosAngle);
    minAzimuth = centerAzim - angle;
    maxAzimuth = centerAzim + angle;
    if (_cosFadeAngle == -1.0f) {
        fadeAngle = 2.0f * osg::PI;
    } else {
        fadeAngle = acos(_cosFadeAngle) - angle;
    }
}

//
// Elevation Range
//
void ElevationRange::setElevationRange(float minElevation,float maxElevation,float fadeAngle)
{
    if (minElevation>maxElevation)
    {
        // need to swap angle pair.
        float tmp = minElevation;
        minElevation = maxElevation;
        maxElevation = tmp;
    }

    minElevation = osg::clampTo(minElevation,(float)-osg::PI_2,(float)osg::PI_2);
    maxElevation = osg::clampTo(maxElevation,(float)-osg::PI_2,(float)osg::PI_2);
    fadeAngle = osg::clampTo(fadeAngle,0.0f,(float)osg::PI_2);

    _cosMinElevation = cos(osg::PI_2-minElevation);
    _cosMaxElevation = cos(osg::PI_2-maxElevation);

    float minFadeAngle = osg::PI_2-minElevation+fadeAngle;
    if (minFadeAngle>=osg::PI) _cosMinFadeElevation = -1.0f;
    else _cosMinFadeElevation = cos(minFadeAngle);

    float maxFadeAngle = osg::PI_2-maxElevation-fadeAngle;
    if (maxFadeAngle<=0.0f) _cosMaxFadeElevation = 1.0f;
    else _cosMaxFadeElevation = cos(maxFadeAngle);

}

float ElevationRange::getMinElevation() const
{
    return osg::PI_2-acos(_cosMinElevation);
}

float ElevationRange::getMaxElevation() const
{
    return osg::PI_2-acos(_cosMaxElevation);
}

float ElevationRange::getFadeAngle() const
{
    float fadeAngle = 0.0;

    // Take the appropriate (unclipped) elevation angle to calculate the fade angle
    if (_cosMinFadeElevation != -1.0f) {
        float minFadeAngle = acos(_cosMinFadeElevation);
        float minElevation = osg::PI_2 - acos(_cosMinElevation);
        fadeAngle = minFadeAngle + minElevation - osg::PI_2;

    } else if (_cosMaxFadeElevation != 1.0f) {
        float maxFadeAngle = acos(_cosMaxFadeElevation);
        float maxElevation = osg::PI_2 - acos(_cosMaxElevation);
        fadeAngle = osg::PI_2 - maxFadeAngle - maxElevation;
    }

    return fadeAngle;
}

//
// ElevationSector
//
AzimSector::AzimSector(float minAzimuth,float maxAzimuth,float fadeAngle):
    Sector(),
    AzimRange()
{
    setAzimuthRange(minAzimuth,maxAzimuth,fadeAngle);
}

float AzimSector::operator() (const osg::Vec3& eyeLocal) const
{
    return azimSector(eyeLocal);
}

//
// ElevationSector
//
ElevationSector::ElevationSector(float minElevation,float maxElevation,float fadeAngle):
    Sector(),
    ElevationRange()
{
    setElevationRange(minElevation,maxElevation,fadeAngle);
}

float ElevationSector::operator() (const osg::Vec3& eyeLocal) const
{
    return elevationSector(eyeLocal);
}

//
// AzimElevationSector
//
AzimElevationSector::AzimElevationSector(float minAzimuth,float maxAzimuth,float minElevation,float maxElevation,float fadeAngle):
    Sector(),
    AzimRange(),
    ElevationRange()
{
    setAzimuthRange(minAzimuth,maxAzimuth,fadeAngle);
    setElevationRange(minElevation,maxElevation,fadeAngle);
}

float AzimElevationSector::operator() (const osg::Vec3& eyeLocal) const
{
    float azimIntensity = azimSector(eyeLocal);
    if (azimIntensity==0.0) return 0.0; // out of sector.
    float elevIntensity = elevationSector(eyeLocal);
    if (elevIntensity==0.0) return 0.0; // out of sector.
    if (azimIntensity<=elevIntensity) return azimIntensity;
    return elevIntensity;
}

//
// ConeSector
//
ConeSector::ConeSector(const osg::Vec3& axis,float angle,float fadeangle):
            Sector()
{
    setAxis(axis);
    setAngle(angle,fadeangle);
}

void ConeSector::setAxis(const osg::Vec3& axis)
{
    _axis = axis;
    _axis.normalize();
}

const osg::Vec3& ConeSector::getAxis() const
{
    return _axis;
}

void ConeSector::setAngle(float angle,float fadeangle)
{
    _cosAngle = cos(angle);
    _cosAngleFade = cos(angle+fadeangle);
}

float ConeSector::getAngle() const
{
    return acos(_cosAngle);
}

float ConeSector::getFadeAngle() const
{
    return acos(_cosAngleFade)-acos(_cosAngle);
}

float ConeSector::operator() (const osg::Vec3& eyeLocal) const
{
    float dotproduct = eyeLocal*_axis;
    float length = eyeLocal.length();
    if (dotproduct>_cosAngle*length) return 1.0f; // fully in sector
    if (dotproduct<_cosAngleFade*length) return 0.0f; // out of sector
    return (dotproduct-_cosAngleFade*length)/((_cosAngle-_cosAngleFade)*length);
}

//
// DirectionalSector
//
DirectionalSector::DirectionalSector(const osg::Vec3& direction,float horizLobeAngle, float vertLobeAngle, float lobeRollAngle, float fadeAngle):
            Sector()
{
    setDirection(direction);
    setHorizLobeAngle(horizLobeAngle);
    setVertLobeAngle(vertLobeAngle);
    setLobeRollAngle(lobeRollAngle);
    setFadeAngle(fadeAngle);
}

void DirectionalSector::computeMatrix()
{
  double heading = atan2(_direction[0], _direction[1]);
  double pitch   = atan2(_direction[2], sqrt(_direction[0]*_direction[0] + _direction[1]*_direction[1]));
  double roll    = _rollAngle;

  _local_to_LP.setRotate(osg::Quat(heading,osg::Vec3d(0.0, 0.0, -1.0)));
  _local_to_LP.preMultRotate(osg::Quat(pitch, osg::Vec3d(1.0, 0.0, 0.0)));
  _local_to_LP.preMultRotate(osg::Quat(roll, osg::Vec3d(0.0, 1.0, 0.0)));
}

void DirectionalSector::setDirection(const osg::Vec3& direction)
{
   _direction = direction ;
   computeMatrix() ;
}

const osg::Vec3& DirectionalSector::getDirection() const
{
    return _direction;
}

void DirectionalSector::setHorizLobeAngle(float angle)
{
    _cosHorizAngle = cos(angle*0.5);
}

float DirectionalSector::getHorizLobeAngle() const
{
    return acos(_cosHorizAngle)*2.0;
}

void DirectionalSector::setVertLobeAngle(float angle)
{
    _cosVertAngle = cos(angle*0.5);
}

float DirectionalSector::getVertLobeAngle() const
{
    return acos(_cosVertAngle)*2.0;
}

void DirectionalSector::setLobeRollAngle(float angle)
{
    _rollAngle = angle ;
    computeMatrix() ;
}

float DirectionalSector::getLobeRollAngle() const
{
    return _rollAngle ;
}

void DirectionalSector::setFadeAngle(float angle)
{
    float ang = acos(_cosHorizAngle)+angle ;
    if ( ang > osg::PI ) _cosHorizFadeAngle = -1.0 ;
    else _cosHorizFadeAngle = cos(ang);

    ang = acos(_cosVertAngle)+angle ;
    if ( ang > osg::PI ) _cosVertFadeAngle = -1.0 ;
    else _cosVertFadeAngle = cos(ang);
}

float DirectionalSector::getFadeAngle() const
{
    return acos(_cosHorizFadeAngle)-acos(_cosHorizAngle);
}

float DirectionalSector::operator() (const osg::Vec3& eyeLocal) const
{
   float elev_intensity, azim_intensity ;

   // Tranform eyeLocal into the LightPoint frame
   osg::Vec3 EPlp = _local_to_LP * eyeLocal ;

   /*fprintf(stderr, "    eyeLocal = %f, %f, %f\n", eyeLocal[0], eyeLocal[1], eyeLocal[2]) ;
   fprintf(stderr, "    EPlp     = %f, %f, %f\n", EPlp[0], EPlp[1], EPlp[2]) ;*/

   // Elevation check
     // Project EPlp into LP YZ plane and dot with LPy
   osg::Vec2 EPyz(EPlp[1], EPlp[2]) ;
   EPyz.normalize() ;
   /*fprintf(stderr, "    EPyz.normalize() = %f, %f\n", EPyz[0], EPyz[1]) ;
   fprintf(stderr, "        _cosVertFadeAngle = %f\n", _cosVertFadeAngle) ;
   fprintf(stderr, "        _cosVertAngle     = %f\n", _cosVertAngle) ;*/
      // cosElev = EPyz* LPy = EPyz[0]
   if ( EPyz[0] < _cosVertFadeAngle ) {
      // Completely outside elevation range
      //fprintf(stderr, "   >> outside el range\n") ;
      return(0.0f) ;
   }
   if ( EPyz[0] < _cosVertAngle ) {
      // In the fade range
      //fprintf(stderr, "   >> inside el fade range\n") ;
      elev_intensity = (_cosVertAngle-EPyz[0])/(_cosVertAngle-_cosVertFadeAngle) ;
   } else {
      // Fully in elevation range
      elev_intensity = 1.0 ;
      //fprintf(stderr, "   >> fully inside el range\n") ;
   }
   // Elevation check passed

   // Azimuth check
     // Project EPlp into LP XY plane and dot with LPy
   osg::Vec2 EPxy(EPlp[0], EPlp[1]) ;
   EPxy.normalize() ;
   /*fprintf(stderr, "    EPxy.normalize() = %f, %f\n", EPxy[0], EPxy[1]) ;
   fprintf(stderr, "        _cosHorizFadeAngle = %f\n", _cosHorizFadeAngle) ;
   fprintf(stderr, "        _cosHorizAngle     = %f\n", _cosHorizAngle) ;*/
      // cosAzim = EPxy * LPy = EPxy[1]
      // if cosElev < 0.0, then need to negate EP for azimuth check
   if ( EPyz[0] < 0.0 ) EPxy.set(-EPxy[0], -EPxy[1]) ;
   if ( EPxy[1] < _cosHorizFadeAngle ) {
      // Completely outside azimuth range
      //fprintf(stderr, "   >> outside az range\n") ;
      return(0.0f) ;
   }
   if ( EPxy[1] < _cosHorizAngle ) {
      // In fade range
      //fprintf(stderr, "   >> inside az fade range\n") ;
      azim_intensity = (_cosHorizAngle-EPxy[1])/(_cosHorizAngle-_cosHorizFadeAngle) ;
   } else {
      // Fully in azimuth range
      //fprintf(stderr, "   >> fully inside az range\n") ;
      azim_intensity = 1.0 ;
   }
   // Azimuth check passed

   // We're good! Return full intensity
   //fprintf(stderr, "   %%%% Returing intensity = %f\n", elev_intensity * azim_intensity) ;
   return elev_intensity * azim_intensity ;
}
<commit_msg>From Lionel Lagarde, "this correction makes the intensity interpolated in the correct direction when the angle is between _cosFadeAngle and _cosAngle."<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
*/

#include <osgSim/Sector>
#include <osg/Vec2>

using namespace osgSim;

//
// Elevation Range
//

void AzimRange::setAzimuthRange(float minAzimuth,float maxAzimuth,float fadeAngle)
{
    // clamp the azimuth range.
    const float twoPI = 2.0f*(float)osg::PI;
    while(minAzimuth>maxAzimuth) minAzimuth -= twoPI;

    // compute the centerline
    float centerAzim = (minAzimuth+maxAzimuth)*0.5f;
    _cosAzim = cos(centerAzim);
    _sinAzim = sin(centerAzim);

    // compute the half angle range of the sector.
    float angle = (maxAzimuth-minAzimuth)*0.5f;
    _cosAngle = cos(angle);

    // clamp the fade angle to valid values.
    fadeAngle = osg::clampAbove(fadeAngle,0.0f);
    if (angle+fadeAngle>osg::PI) _cosFadeAngle = -1.0f;
    else _cosFadeAngle = cos(angle+fadeAngle);

}

void AzimRange::getAzimuthRange(float& minAzimuth, float& maxAzimuth, float& fadeAngle) const
{
    float centerAzim = atan2(_sinAzim, _cosAzim);
    float angle = acos(_cosAngle);
    minAzimuth = centerAzim - angle;
    maxAzimuth = centerAzim + angle;
    if (_cosFadeAngle == -1.0f) {
        fadeAngle = 2.0f * osg::PI;
    } else {
        fadeAngle = acos(_cosFadeAngle) - angle;
    }
}

//
// Elevation Range
//
void ElevationRange::setElevationRange(float minElevation,float maxElevation,float fadeAngle)
{
    if (minElevation>maxElevation)
    {
        // need to swap angle pair.
        float tmp = minElevation;
        minElevation = maxElevation;
        maxElevation = tmp;
    }

    minElevation = osg::clampTo(minElevation,(float)-osg::PI_2,(float)osg::PI_2);
    maxElevation = osg::clampTo(maxElevation,(float)-osg::PI_2,(float)osg::PI_2);
    fadeAngle = osg::clampTo(fadeAngle,0.0f,(float)osg::PI_2);

    _cosMinElevation = cos(osg::PI_2-minElevation);
    _cosMaxElevation = cos(osg::PI_2-maxElevation);

    float minFadeAngle = osg::PI_2-minElevation+fadeAngle;
    if (minFadeAngle>=osg::PI) _cosMinFadeElevation = -1.0f;
    else _cosMinFadeElevation = cos(minFadeAngle);

    float maxFadeAngle = osg::PI_2-maxElevation-fadeAngle;
    if (maxFadeAngle<=0.0f) _cosMaxFadeElevation = 1.0f;
    else _cosMaxFadeElevation = cos(maxFadeAngle);

}

float ElevationRange::getMinElevation() const
{
    return osg::PI_2-acos(_cosMinElevation);
}

float ElevationRange::getMaxElevation() const
{
    return osg::PI_2-acos(_cosMaxElevation);
}

float ElevationRange::getFadeAngle() const
{
    float fadeAngle = 0.0;

    // Take the appropriate (unclipped) elevation angle to calculate the fade angle
    if (_cosMinFadeElevation != -1.0f) {
        float minFadeAngle = acos(_cosMinFadeElevation);
        float minElevation = osg::PI_2 - acos(_cosMinElevation);
        fadeAngle = minFadeAngle + minElevation - osg::PI_2;

    } else if (_cosMaxFadeElevation != 1.0f) {
        float maxFadeAngle = acos(_cosMaxFadeElevation);
        float maxElevation = osg::PI_2 - acos(_cosMaxElevation);
        fadeAngle = osg::PI_2 - maxFadeAngle - maxElevation;
    }

    return fadeAngle;
}

//
// ElevationSector
//
AzimSector::AzimSector(float minAzimuth,float maxAzimuth,float fadeAngle):
    Sector(),
    AzimRange()
{
    setAzimuthRange(minAzimuth,maxAzimuth,fadeAngle);
}

float AzimSector::operator() (const osg::Vec3& eyeLocal) const
{
    return azimSector(eyeLocal);
}

//
// ElevationSector
//
ElevationSector::ElevationSector(float minElevation,float maxElevation,float fadeAngle):
    Sector(),
    ElevationRange()
{
    setElevationRange(minElevation,maxElevation,fadeAngle);
}

float ElevationSector::operator() (const osg::Vec3& eyeLocal) const
{
    return elevationSector(eyeLocal);
}

//
// AzimElevationSector
//
AzimElevationSector::AzimElevationSector(float minAzimuth,float maxAzimuth,float minElevation,float maxElevation,float fadeAngle):
    Sector(),
    AzimRange(),
    ElevationRange()
{
    setAzimuthRange(minAzimuth,maxAzimuth,fadeAngle);
    setElevationRange(minElevation,maxElevation,fadeAngle);
}

float AzimElevationSector::operator() (const osg::Vec3& eyeLocal) const
{
    float azimIntensity = azimSector(eyeLocal);
    if (azimIntensity==0.0) return 0.0; // out of sector.
    float elevIntensity = elevationSector(eyeLocal);
    if (elevIntensity==0.0) return 0.0; // out of sector.
    if (azimIntensity<=elevIntensity) return azimIntensity;
    return elevIntensity;
}

//
// ConeSector
//
ConeSector::ConeSector(const osg::Vec3& axis,float angle,float fadeangle):
            Sector()
{
    setAxis(axis);
    setAngle(angle,fadeangle);
}

void ConeSector::setAxis(const osg::Vec3& axis)
{
    _axis = axis;
    _axis.normalize();
}

const osg::Vec3& ConeSector::getAxis() const
{
    return _axis;
}

void ConeSector::setAngle(float angle,float fadeangle)
{
    _cosAngle = cos(angle);
    _cosAngleFade = cos(angle+fadeangle);
}

float ConeSector::getAngle() const
{
    return acos(_cosAngle);
}

float ConeSector::getFadeAngle() const
{
    return acos(_cosAngleFade)-acos(_cosAngle);
}

float ConeSector::operator() (const osg::Vec3& eyeLocal) const
{
    float dotproduct = eyeLocal*_axis;
    float length = eyeLocal.length();
    if (dotproduct>_cosAngle*length) return 1.0f; // fully in sector
    if (dotproduct<_cosAngleFade*length) return 0.0f; // out of sector
    return (dotproduct-_cosAngleFade*length)/((_cosAngle-_cosAngleFade)*length);
}

//
// DirectionalSector
//
DirectionalSector::DirectionalSector(const osg::Vec3& direction,float horizLobeAngle, float vertLobeAngle, float lobeRollAngle, float fadeAngle):
            Sector()
{
    setDirection(direction);
    setHorizLobeAngle(horizLobeAngle);
    setVertLobeAngle(vertLobeAngle);
    setLobeRollAngle(lobeRollAngle);
    setFadeAngle(fadeAngle);
}

void DirectionalSector::computeMatrix()
{
  double heading = atan2(_direction[0], _direction[1]);
  double pitch   = atan2(_direction[2], sqrt(_direction[0]*_direction[0] + _direction[1]*_direction[1]));
  double roll    = _rollAngle;

  _local_to_LP.setRotate(osg::Quat(heading,osg::Vec3d(0.0, 0.0, -1.0)));
  _local_to_LP.preMultRotate(osg::Quat(pitch, osg::Vec3d(1.0, 0.0, 0.0)));
  _local_to_LP.preMultRotate(osg::Quat(roll, osg::Vec3d(0.0, 1.0, 0.0)));
}

void DirectionalSector::setDirection(const osg::Vec3& direction)
{
   _direction = direction ;
   computeMatrix() ;
}

const osg::Vec3& DirectionalSector::getDirection() const
{
    return _direction;
}

void DirectionalSector::setHorizLobeAngle(float angle)
{
    _cosHorizAngle = cos(angle*0.5);
}

float DirectionalSector::getHorizLobeAngle() const
{
    return acos(_cosHorizAngle)*2.0;
}

void DirectionalSector::setVertLobeAngle(float angle)
{
    _cosVertAngle = cos(angle*0.5);
}

float DirectionalSector::getVertLobeAngle() const
{
    return acos(_cosVertAngle)*2.0;
}

void DirectionalSector::setLobeRollAngle(float angle)
{
    _rollAngle = angle ;
    computeMatrix() ;
}

float DirectionalSector::getLobeRollAngle() const
{
    return _rollAngle ;
}

void DirectionalSector::setFadeAngle(float angle)
{
    float ang = acos(_cosHorizAngle)+angle ;
    if ( ang > osg::PI ) _cosHorizFadeAngle = -1.0 ;
    else _cosHorizFadeAngle = cos(ang);

    ang = acos(_cosVertAngle)+angle ;
    if ( ang > osg::PI ) _cosVertFadeAngle = -1.0 ;
    else _cosVertFadeAngle = cos(ang);
}

float DirectionalSector::getFadeAngle() const
{
    return acos(_cosHorizFadeAngle)-acos(_cosHorizAngle);
}

float DirectionalSector::operator() (const osg::Vec3& eyeLocal) const
{
   float elev_intensity, azim_intensity ;

   // Tranform eyeLocal into the LightPoint frame
   osg::Vec3 EPlp = _local_to_LP * eyeLocal ;

   /*fprintf(stderr, "    eyeLocal = %f, %f, %f\n", eyeLocal[0], eyeLocal[1], eyeLocal[2]) ;
   fprintf(stderr, "    EPlp     = %f, %f, %f\n", EPlp[0], EPlp[1], EPlp[2]) ;*/

   // Elevation check
     // Project EPlp into LP YZ plane and dot with LPy
   osg::Vec2 EPyz(EPlp[1], EPlp[2]) ;
   EPyz.normalize() ;
   /*fprintf(stderr, "    EPyz.normalize() = %f, %f\n", EPyz[0], EPyz[1]) ;
   fprintf(stderr, "        _cosVertFadeAngle = %f\n", _cosVertFadeAngle) ;
   fprintf(stderr, "        _cosVertAngle     = %f\n", _cosVertAngle) ;*/
      // cosElev = EPyz* LPy = EPyz[0]
   if ( EPyz[0] < _cosVertFadeAngle ) {
      // Completely outside elevation range
      //fprintf(stderr, "   >> outside el range\n") ;
      return(0.0f) ;
   }
   if ( EPyz[0] < _cosVertAngle ) {
      // In the fade range
      //fprintf(stderr, "   >> inside el fade range\n") ;
      elev_intensity = (EPyz[0]-_cosVertFadeAngle)/(_cosVertAngle-_cosVertFadeAngle) ;
   } else {
      // Fully in elevation range
      elev_intensity = 1.0 ;
      //fprintf(stderr, "   >> fully inside el range\n") ;
   }
   // Elevation check passed

   // Azimuth check
     // Project EPlp into LP XY plane and dot with LPy
   osg::Vec2 EPxy(EPlp[0], EPlp[1]) ;
   EPxy.normalize() ;
   /*fprintf(stderr, "    EPxy.normalize() = %f, %f\n", EPxy[0], EPxy[1]) ;
   fprintf(stderr, "        _cosHorizFadeAngle = %f\n", _cosHorizFadeAngle) ;
   fprintf(stderr, "        _cosHorizAngle     = %f\n", _cosHorizAngle) ;*/
      // cosAzim = EPxy * LPy = EPxy[1]
      // if cosElev < 0.0, then need to negate EP for azimuth check
   if ( EPyz[0] < 0.0 ) EPxy.set(-EPxy[0], -EPxy[1]) ;
   if ( EPxy[1] < _cosHorizFadeAngle ) {
      // Completely outside azimuth range
      //fprintf(stderr, "   >> outside az range\n") ;
      return(0.0f) ;
   }
   if ( EPxy[1] < _cosHorizAngle ) {
      // In fade range
      //fprintf(stderr, "   >> inside az fade range\n") ;
      azim_intensity = (EPxy[1]-_cosHorizFadeAngle)/(_cosHorizAngle-_cosHorizFadeAngle) ;
   } else {
      // Fully in azimuth range
      //fprintf(stderr, "   >> fully inside az range\n") ;
      azim_intensity = 1.0 ;
   }
   // Azimuth check passed

   // We're good! Return full intensity
   //fprintf(stderr, "   %%%% Returing intensity = %f\n", elev_intensity * azim_intensity) ;
   return elev_intensity * azim_intensity ;
}
<|endoftext|>