<commit_before>/** @file
    @brief OSVR server driver for OpenVR

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// 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.

// Internal Includes
#include "ServerDriver_OSVR.h"

#include "OSVRTrackedHMD.h"         // for OSVRTrackedHMD
#include "OSVRTrackingReference.h"  // for OSVRTrackingReference
#include "platform_fixes.h"         // strcasecmp
#include "make_unique.h"            // for std::make_unique
#include "Logging.h"                // for OSVR_LOG, Logging

// Library/third-party includes
#include <openvr_driver.h>          // for everything in vr namespace

#include <osvr/ClientKit/Context.h> // for osvr::clientkit::ClientContext
#include <osvr/Util/PlatformConfig.h>

// Standard includes
#include <vector>                   // for std::vector
#include <cstring>                  // for std::strcmp
#include <string>                   // for std::string
#include <chrono>
#include <thread>
#include <atomic>

namespace {

static std::thread client_update_thread;
static std::atomic<bool> client_update_thread_quit;
static std::atomic<int> client_update_thread_ms_wait;
static void client_update_thread_work(osvr::clientkit::ClientContext ctx)
{
    while (!client_update_thread_quit.load()) {
        ctx.update();
        std::this_thread::sleep_for(std::chrono::milliseconds(client_update_thread_ms_wait.load()));
    }
    client_update_thread_quit = false;
}

} // anonymous namespace

vr::EVRInitError ServerDriver_OSVR::Init(vr::IVRDriverContext* driver_context)
{
    VR_INIT_SERVER_DRIVER_CONTEXT(driver_context);

    Logging::instance().setDriverLog(vr::VRDriverLog());

    settings_ = std::make_unique<Settings>();
    standbyWaitPeriod_ = settings_->getSetting<int>("standbyWaitPeriod", 100);
    activeWaitPeriod_ = settings_->getSetting<int>("activeWaitPeriod", 1);
    OSVR_LOG(debug) << "Standby wait period is " << standbyWaitPeriod_ << " ms.";
    OSVR_LOG(debug) << "Active wait period is " << activeWaitPeriod_ << " ms.";

    context_ = std::make_unique<osvr::clientkit::ClientContext>("org.osvr.SteamVR");

    trackedDevices_.emplace_back(std::make_unique<OSVRTrackedHMD>(*(context_.get())));
    trackedDevices_.emplace_back(std::make_unique<OSVRTrackingReference>(*(context_.get())));

    for (auto& tracked_device : trackedDevices_) {
        vr::VRServerDriverHost()->TrackedDeviceAdded(tracked_device->getId(), tracked_device->getDeviceClass(), tracked_device.get());
    }

    client_update_thread_quit.store(false);
    client_update_thread_ms_wait.store(activeWaitPeriod_);
    client_update_thread = std::thread(client_update_thread_work, context_->get());

    return vr::VRInitError_None;
}

void ServerDriver_OSVR::Cleanup()
{
    client_update_thread_quit.store(true);
    if (client_update_thread.joinable()) {
        client_update_thread.join();
    }

    trackedDevices_.clear();
    context_.reset();
    VR_CLEANUP_SERVER_DRIVER_CONTEXT();
}

const char* const* ServerDriver_OSVR::GetInterfaceVersions()
{
    return vr::k_InterfaceVersions;
}

void ServerDriver_OSVR::RunFrame()
{
    // do nothing
}

bool ServerDriver_OSVR::ShouldBlockStandbyMode()
{
    return false;
}

void ServerDriver_OSVR::EnterStandby()
{
    OSVR_LOG(debug) << "Entering standby mode...";
    client_update_thread_ms_wait.store(standbyWaitPeriod_);
}

void ServerDriver_OSVR::LeaveStandby()
{
    OSVR_LOG(debug) << "Leaving standby mode...";
    client_update_thread_ms_wait.store(activeWaitPeriod_);
}

<commit_msg>Pass ref to client context to update loop thread.<commit_after>/** @file
    @brief OSVR server driver for OpenVR

    @date 2015

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2015 Sensics, Inc.
//
// 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.

// Internal Includes
#include "ServerDriver_OSVR.h"

#include "OSVRTrackedHMD.h"         // for OSVRTrackedHMD
#include "OSVRTrackingReference.h"  // for OSVRTrackingReference
#include "platform_fixes.h"         // strcasecmp
#include "make_unique.h"            // for std::make_unique
#include "Logging.h"                // for OSVR_LOG, Logging

// Library/third-party includes
#include <openvr_driver.h>          // for everything in vr namespace

#include <osvr/ClientKit/Context.h> // for osvr::clientkit::ClientContext
#include <osvr/Util/PlatformConfig.h>

// Standard includes
#include <vector>                   // for std::vector
#include <cstring>                  // for std::strcmp
#include <string>                   // for std::string
#include <chrono>
#include <thread>
#include <atomic>

namespace {

static std::thread client_update_thread;
static std::atomic<bool> client_update_thread_quit;
static std::atomic<int> client_update_thread_ms_wait;
static void client_update_thread_work(osvr::clientkit::ClientContext& ctx)
{
    while (!client_update_thread_quit.load()) {
        ctx.update();
        std::this_thread::sleep_for(std::chrono::milliseconds(client_update_thread_ms_wait.load()));
    }
    client_update_thread_quit = false;
}

} // anonymous namespace

vr::EVRInitError ServerDriver_OSVR::Init(vr::IVRDriverContext* driver_context)
{
    VR_INIT_SERVER_DRIVER_CONTEXT(driver_context);

    Logging::instance().setDriverLog(vr::VRDriverLog());

    settings_ = std::make_unique<Settings>();
    standbyWaitPeriod_ = settings_->getSetting<int>("standbyWaitPeriod", 100);
    activeWaitPeriod_ = settings_->getSetting<int>("activeWaitPeriod", 1);
    OSVR_LOG(debug) << "Standby wait period is " << standbyWaitPeriod_ << " ms.";
    OSVR_LOG(debug) << "Active wait period is " << activeWaitPeriod_ << " ms.";

    context_ = std::make_unique<osvr::clientkit::ClientContext>("org.osvr.SteamVR");

    trackedDevices_.emplace_back(std::make_unique<OSVRTrackedHMD>(*(context_.get())));
    trackedDevices_.emplace_back(std::make_unique<OSVRTrackingReference>(*(context_.get())));

    for (auto& tracked_device : trackedDevices_) {
        vr::VRServerDriverHost()->TrackedDeviceAdded(tracked_device->getId(), tracked_device->getDeviceClass(), tracked_device.get());
    }

    client_update_thread_quit.store(false);
    client_update_thread_ms_wait.store(activeWaitPeriod_);
    client_update_thread = std::thread(client_update_thread_work, std::ref(*context_));

    return vr::VRInitError_None;
}

void ServerDriver_OSVR::Cleanup()
{
    client_update_thread_quit.store(true);
    if (client_update_thread.joinable()) {
        client_update_thread.join();
    }

    trackedDevices_.clear();
    context_.reset();
    VR_CLEANUP_SERVER_DRIVER_CONTEXT();
}

const char* const* ServerDriver_OSVR::GetInterfaceVersions()
{
    return vr::k_InterfaceVersions;
}

void ServerDriver_OSVR::RunFrame()
{
    // do nothing
}

bool ServerDriver_OSVR::ShouldBlockStandbyMode()
{
    return false;
}

void ServerDriver_OSVR::EnterStandby()
{
    OSVR_LOG(debug) << "Entering standby mode...";
    client_update_thread_ms_wait.store(standbyWaitPeriod_);
}

void ServerDriver_OSVR::LeaveStandby()
{
    OSVR_LOG(debug) << "Leaving standby mode...";
    client_update_thread_ms_wait.store(activeWaitPeriod_);
}

<|endoftext|>


<commit_before>#include "ArgParse.h"

using namespace std;

ArgParse::ArgParse(int argc, char* argv[])
{
    for(int a=1;a<argc;++a){
        if(argv[a][0]=='-'){
            string in(argv[a]),trig,val;
            trig=in.substr(1,in.find('=')-1);
            if(in.find('=')==string::npos) {
                val='1';//true
            } else {
                val=in.substr(in.find('=')+1);
            }
            m_streams[trig]=val;
        } else {
            ifstream fin(argv[a]);
            string in,trig,val;
            while(getline(fin,in)) {
                if(in.size()==0 || in[0]=='#') continue;
                trig=in.substr(0,in.find('='));
                if(in.find('=')==string::npos) {
                    val='1';
                } else {
                    val=in.substr(in.find('=')+1);
                }
                m_streams[trig]=val;
            }
        }
    }
}

double ArgParse::d(const string& str) const
{
    return stod(m_streams.at(str));
}

int ArgParse::i(const string& str) const
{
    return stoi(m_streams.at(str));
}

bool ArgParse::b(const string& str) const
{
    return stoi(m_streams.at(str));
}
 string ArgParse::s(const string& str) const
{
    return m_streams.at(str);
}
<commit_msg>bug fixes<commit_after>#include "ArgParse.h"
#include <stdexcept>

using namespace std;

ArgParse::ArgParse(int argc, char* argv[])
{
    for(int a=1;a<argc;++a){
        if(argv[a][0]=='-'){
            string in(argv[a]),trig,val;
            trig=in.substr(1,in.find('=')-1);
            if(in.find('=')==string::npos) {
                val='1';//true
            } else {
                val=in.substr(in.find('=')+1);
            }
            m_streams[trig]=val;
        } else {
            ifstream fin(argv[a]);
            string in,trig,val;
            while(getline(fin,in)) {
                if(in.size()==0 || in[0]=='#') continue;
                trig=in.substr(0,in.find('='));
                if(in.find('=')==string::npos) {
                    val='1';
                } else {
                    val=in.substr(in.find('=')+1);
                }
                m_streams[trig]=val;
            }
        }
    }
}

double ArgParse::d(const string& str) const
{
    double out;
    try {
        out=stod(m_streams.at(str));
        return out;
    } catch(out_of_range err) {
        cerr<<"No member \""<<str<<"\" found in arguments"<<endl;
        throw err;
    }
}

int ArgParse::i(const string& str) const
{
    int out;
    try {
        out=stoi(m_streams.at(str));
        return out;
    } catch (out_of_range err) {
        cerr<<"No member \""<<str<<"\" found in arguments"<<endl;
        throw err;
    }
}

bool ArgParse::b(const string& str) const
{
    bool out;
    try {
        out=stoi(m_streams.at(str));
        return out;
    } catch (out_of_range err) {
        cerr<<"No member \""<<str<<"\" found in arguments"<<endl;
        throw err;
    }
}
 string ArgParse::s(const string& str) const
{
    string out;
    try {
        out=m_streams.at(str);
        return out;
    } catch (out_of_range err) {
        cerr<<"No member \""<<str<<"\" found in arguments"<<endl;
        throw err;
    }
}
<|endoftext|>


<commit_before>#include "timeentryeditorwidget.h"
#include "ui_timeentryeditorwidget.h"

#include <QMessageBox>

#include "toggl_api.h"

TimeEntryEditorWidget::TimeEntryEditorWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TimeEntryEditorWidget),
    guid(""),
    timeEntryAutocompleteNeedsUpdate(false),
    projectAutocompleteNeedsUpdate(false),
    workspaceSelectNeedsUpdate(false),
    clientSelectNeedsUpdate(false)
{
    ui->setupUi(this);

    setVisible(false);

    ui->addNewProject->setText("Add new project");

    connect(TogglApi::instance, SIGNAL(displayLogin(bool,uint64_t)),
            this, SLOT(displayLogin(bool,uint64_t)));

    connect(TogglApi::instance, SIGNAL(displayTimeEntryList(bool,QVector<TimeEntryView*>)),
            this, SLOT(displayTimeEntryList(bool,QVector<TimeEntryView*>)));

    connect(TogglApi::instance, SIGNAL(displayTimeEntryEditor(bool,TimeEntryView*,QString)),
            this, SLOT(displayTimeEntryEditor(bool,TimeEntryView*,QString)));

    connect(TogglApi::instance, SIGNAL(displayTags(QVector<GenericView*>)),
            this, SLOT(displayTags(QVector<GenericView*>)));

    connect(TogglApi::instance, SIGNAL(displayWorkspaceSelect(QVector<GenericView*>)),
            this, SLOT(displayWorkspaceSelect(QVector<GenericView*>)));

    connect(TogglApi::instance, SIGNAL(displayProjectAutocomplete(QVector<AutocompleteView*>)),
            this, SLOT(displayProjectAutocomplete(QVector<AutocompleteView*>)));

    connect(TogglApi::instance, SIGNAL(displayTimeEntryAutocomplete(QVector<AutocompleteView*>)),
            this, SLOT(displayTimeEntryAutocomplete(QVector<AutocompleteView*>)));

    connect(TogglApi::instance, SIGNAL(displayClientSelect(QVector<GenericView*>)),
            this, SLOT(displayClientSelect(QVector<GenericView*>)));
}

TimeEntryEditorWidget::~TimeEntryEditorWidget()
{
    delete ui;
}

void TimeEntryEditorWidget::displayTags(
    QVector<GenericView*> tags)
{

}

void TimeEntryEditorWidget::displayClientSelect(
    QVector<GenericView *> list)
{
    clientSelectUpdate = list;
    clientSelectNeedsUpdate = true;
    if (ui->newProjectClient->hasFocus())
    {
        return;
    }

    u_int64_t workspaceID = 0;
    QVariant data = ui->newProjectWorkspace->currentData();
    if (data.canConvert<GenericView *>())
    {
        GenericView *view = data.value<GenericView *>();
        workspaceID = view->ID;
    }
    ui->newProjectClient->clear();
    ui->newProjectClient->addItem("");
    foreach(GenericView *view, clientSelectUpdate)
    {
        if (workspaceID && workspaceID != view->WID)
        {
            continue;
        }
        ui->newProjectClient->addItem(view->Name, QVariant::fromValue(view));
    }
    clientSelectNeedsUpdate = false;
}

void TimeEntryEditorWidget::displayTimeEntryAutocomplete(
    QVector<AutocompleteView *> list)
{
    timeEntryAutocompleteUpdate = list;
    timeEntryAutocompleteNeedsUpdate = true;
    if (ui->description->hasFocus())
    {
        return;
    }
    ui->description->clear();
    ui->description->addItem("");
    foreach(AutocompleteView *view, timeEntryAutocompleteUpdate)
    {
        ui->description->addItem(view->Text, QVariant::fromValue(view));
    }
    timeEntryAutocompleteNeedsUpdate = false;
}

void TimeEntryEditorWidget::displayProjectAutocomplete(
    QVector<AutocompleteView *> list)
{
    projectAutocompleteUpdate = list;
    projectAutocompleteNeedsUpdate = true;
    if (ui->project->hasFocus())
    {
        return;
    }
    ui->project->clear();
    ui->project->addItem("");
    foreach(AutocompleteView *view, projectAutocompleteUpdate)
    {
        ui->project->addItem(view->Text, QVariant::fromValue(view));
    }
    projectAutocompleteNeedsUpdate = false;
}

void TimeEntryEditorWidget::displayWorkspaceSelect(
    QVector<GenericView *> list)
{
    workspaceSelectUpdate = list;
    workspaceSelectNeedsUpdate = true;
    if (ui->newProjectWorkspace->hasFocus())
    {
        return;
    }
    ui->newProjectWorkspace->clear();
    foreach(GenericView *view, workspaceSelectUpdate)
    {
        ui->newProjectWorkspace->addItem(view->Name, QVariant::fromValue(view));
    }
    workspaceSelectNeedsUpdate = false;
}

void TimeEntryEditorWidget::displayLogin(
    const bool open,
    const uint64_t user_id)
{
    if (open || !user_id)
    {
        setVisible(false);
    }
}

void TimeEntryEditorWidget::displayTimeEntryList(
    const bool open,
    QVector<TimeEntryView *> list)
{
    if (open)
    {
        setVisible(false);
    }
}

void TimeEntryEditorWidget::displayTimeEntryEditor(
    const bool open,
    TimeEntryView *view,
    const QString focused_field_name)
{
    if (open)
    {
        ui->timeDetails->setVisible(false);
        ui->timeOverview->setVisible(true);

        ui->newProject->setVisible(false);
        ui->addNewProject->setVisible(true);

        setVisible(true);
    }

    guid = view->GUID;

    ui->description->setEditText(view->Description);
    ui->project->setEditText(view->ProjectAndTaskLabel);
    ui->start->setText(view->StartTimeString);
    ui->stop->setText(view->EndTimeString);
    ui->dateEdit->setDateTime(QDateTime::fromTime_t(view->Started));
    ui->duration->setText(view->Duration);
    ui->billable->setChecked(view->Billable);
    ui->timeOverview->setText("" + view->timeOverview() + "");

    ui->lastUpdate->setVisible(view->UpdatedAt);
    ui->lastUpdate->setText(view->lastUpdate());
}

void TimeEntryEditorWidget::on_doneButton_clicked()
{
    TogglApi::instance->viewTimeEntryList();
}

void TimeEntryEditorWidget::on_deleteButton_clicked()
{
    if (QMessageBox::Ok == QMessageBox(QMessageBox::Question,
                                        "Delete this time entry?",
                                        "Deleted time entries cannot be restored.",
                                        QMessageBox::Ok|QMessageBox::Cancel).exec())
    {
        TogglApi::instance->deleteTimeEntry(guid);
    }
}

void TimeEntryEditorWidget::on_addNewProject_linkActivated(const QString &link)
{
    ui->addNewProject->setVisible(false);
    ui->newProject->setVisible(true);
    ui->newProjectName->setFocus();
}

void TimeEntryEditorWidget::on_timeOverview_linkActivated(const QString &link)
{
    ui->timeOverview->setVisible(false);
    ui->timeDetails->setVisible(true);
    ui->duration->setFocus();
}

void TimeEntryEditorWidget::on_newProjectWorkspace_currentIndexChanged(int index)
{
    displayClientSelect(clientSelectUpdate);
}
<commit_msg>Dont overwrite user changes (linux)<commit_after>#include "timeentryeditorwidget.h"
#include "ui_timeentryeditorwidget.h"

#include <QMessageBox>

#include "toggl_api.h"

TimeEntryEditorWidget::TimeEntryEditorWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TimeEntryEditorWidget),
    guid(""),
    timeEntryAutocompleteNeedsUpdate(false),
    projectAutocompleteNeedsUpdate(false),
    workspaceSelectNeedsUpdate(false),
    clientSelectNeedsUpdate(false)
{
    ui->setupUi(this);

    setVisible(false);

    ui->addNewProject->setText("Add new project");

    connect(TogglApi::instance, SIGNAL(displayLogin(bool,uint64_t)),
            this, SLOT(displayLogin(bool,uint64_t)));

    connect(TogglApi::instance, SIGNAL(displayTimeEntryList(bool,QVector<TimeEntryView*>)),
            this, SLOT(displayTimeEntryList(bool,QVector<TimeEntryView*>)));

    connect(TogglApi::instance, SIGNAL(displayTimeEntryEditor(bool,TimeEntryView*,QString)),
            this, SLOT(displayTimeEntryEditor(bool,TimeEntryView*,QString)));

    connect(TogglApi::instance, SIGNAL(displayTags(QVector<GenericView*>)),
            this, SLOT(displayTags(QVector<GenericView*>)));

    connect(TogglApi::instance, SIGNAL(displayWorkspaceSelect(QVector<GenericView*>)),
            this, SLOT(displayWorkspaceSelect(QVector<GenericView*>)));

    connect(TogglApi::instance, SIGNAL(displayProjectAutocomplete(QVector<AutocompleteView*>)),
            this, SLOT(displayProjectAutocomplete(QVector<AutocompleteView*>)));

    connect(TogglApi::instance, SIGNAL(displayTimeEntryAutocomplete(QVector<AutocompleteView*>)),
            this, SLOT(displayTimeEntryAutocomplete(QVector<AutocompleteView*>)));

    connect(TogglApi::instance, SIGNAL(displayClientSelect(QVector<GenericView*>)),
            this, SLOT(displayClientSelect(QVector<GenericView*>)));
}

TimeEntryEditorWidget::~TimeEntryEditorWidget()
{
    delete ui;
}

void TimeEntryEditorWidget::displayTags(
    QVector<GenericView*> tags)
{

}

void TimeEntryEditorWidget::displayClientSelect(
    QVector<GenericView *> list)
{
    clientSelectUpdate = list;
    clientSelectNeedsUpdate = true;
    if (ui->newProjectClient->hasFocus())
    {
        return;
    }

    u_int64_t workspaceID = 0;
    QVariant data = ui->newProjectWorkspace->currentData();
    if (data.canConvert<GenericView *>())
    {
        GenericView *view = data.value<GenericView *>();
        workspaceID = view->ID;
    }
    ui->newProjectClient->clear();
    ui->newProjectClient->addItem("");
    foreach(GenericView *view, clientSelectUpdate)
    {
        if (workspaceID && workspaceID != view->WID)
        {
            continue;
        }
        ui->newProjectClient->addItem(view->Name, QVariant::fromValue(view));
    }
    clientSelectNeedsUpdate = false;
}

void TimeEntryEditorWidget::displayTimeEntryAutocomplete(
    QVector<AutocompleteView *> list)
{
    timeEntryAutocompleteUpdate = list;
    timeEntryAutocompleteNeedsUpdate = true;
    if (ui->description->hasFocus())
    {
        return;
    }
    ui->description->clear();
    ui->description->addItem("");
    foreach(AutocompleteView *view, timeEntryAutocompleteUpdate)
    {
        ui->description->addItem(view->Text, QVariant::fromValue(view));
    }
    timeEntryAutocompleteNeedsUpdate = false;
}

void TimeEntryEditorWidget::displayProjectAutocomplete(
    QVector<AutocompleteView *> list)
{
    projectAutocompleteUpdate = list;
    projectAutocompleteNeedsUpdate = true;
    if (ui->project->hasFocus())
    {
        return;
    }
    ui->project->clear();
    ui->project->addItem("");
    foreach(AutocompleteView *view, projectAutocompleteUpdate)
    {
        ui->project->addItem(view->Text, QVariant::fromValue(view));
    }
    projectAutocompleteNeedsUpdate = false;
}

void TimeEntryEditorWidget::displayWorkspaceSelect(
    QVector<GenericView *> list)
{
    workspaceSelectUpdate = list;
    workspaceSelectNeedsUpdate = true;
    if (ui->newProjectWorkspace->hasFocus())
    {
        return;
    }
    ui->newProjectWorkspace->clear();
    foreach(GenericView *view, workspaceSelectUpdate)
    {
        ui->newProjectWorkspace->addItem(view->Name, QVariant::fromValue(view));
    }
    workspaceSelectNeedsUpdate = false;
}

void TimeEntryEditorWidget::displayLogin(
    const bool open,
    const uint64_t user_id)
{
    if (open || !user_id)
    {
        setVisible(false);
    }
}

void TimeEntryEditorWidget::displayTimeEntryList(
    const bool open,
    QVector<TimeEntryView *> list)
{
    if (open)
    {
        setVisible(false);
    }
}

void TimeEntryEditorWidget::displayTimeEntryEditor(
    const bool open,
    TimeEntryView *view,
    const QString focused_field_name)
{
    if (open)
    {
        ui->timeDetails->setVisible(false);
        ui->timeOverview->setVisible(true);

        ui->newProject->setVisible(false);
        ui->addNewProject->setVisible(true);

        setVisible(true);
    }

    guid = view->GUID;

    if (!ui->description->hasFocus())
    {
        ui->description->setEditText(view->Description);
    }
    if (!ui->project->hasFocus())
    {
        ui->project->setEditText(view->ProjectAndTaskLabel);
    }
    if (!ui->start->hasFocus())
    {
        ui->start->setText(view->StartTimeString);
    }
    if (!ui->stop->hasFocus())
    {
        ui->stop->setText(view->EndTimeString);
    }
    if (!ui->dateEdit->hasFocus())
    {
        ui->dateEdit->setDateTime(QDateTime::fromTime_t(view->Started));
    }
    if (!ui->duration->hasFocus())
    {
        ui->duration->setText(view->Duration);
    }
    ui->billable->setChecked(view->Billable);
    ui->timeOverview->setText("" + view->timeOverview() + "");

    ui->lastUpdate->setVisible(view->UpdatedAt);
    ui->lastUpdate->setText(view->lastUpdate());
}

void TimeEntryEditorWidget::on_doneButton_clicked()
{
    TogglApi::instance->viewTimeEntryList();
}

void TimeEntryEditorWidget::on_deleteButton_clicked()
{
    if (QMessageBox::Ok == QMessageBox(QMessageBox::Question,
                                        "Delete this time entry?",
                                        "Deleted time entries cannot be restored.",
                                        QMessageBox::Ok|QMessageBox::Cancel).exec())
    {
        TogglApi::instance->deleteTimeEntry(guid);
    }
}

void TimeEntryEditorWidget::on_addNewProject_linkActivated(const QString &link)
{
    ui->addNewProject->setVisible(false);
    ui->newProject->setVisible(true);
    ui->newProjectName->setFocus();
}

void TimeEntryEditorWidget::on_timeOverview_linkActivated(const QString &link)
{
    ui->timeOverview->setVisible(false);
    ui->timeDetails->setVisible(true);
    ui->duration->setFocus();
}

void TimeEntryEditorWidget::on_newProjectWorkspace_currentIndexChanged(int index)
{
    displayClientSelect(clientSelectUpdate);
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2017, Vlad Meșco
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "control.h"
#include "logger.h"
#include "string_utils.h"

#include <algorithm>
#include <cassert>
#include <cstdio>

#define FIND_WHAT(id, then) \
    auto found = FindWhat(id); \
    if(found == model_->whats.end()) then;

#define DIRTY() do{\
    model_->dirty = true; \
}while(0)

auto Control::FindWhat(evData id) -> decltype(model_->whats)::iterator
{
    LOGGER(l);
    auto found = std::find_if(model_->whats.begin(), model_->whats.end(), [id](WhatEntry& e) -> bool {
                return e.name == id;
            });
    if(found == model_->whats.end())
    {
        l(L"Failed to find %ls...", id.c_str());
    }
    return found;
}

void Control::SetWhosName(evData oldName, std::wstring name)
{
    LOGGER(l);
    auto found = std::find_if(model_->whos.begin(), model_->whos.end(), [oldName](WhoEntry& e) -> bool {
                return e.name == oldName;
            });
    if(found == model_->whos.end())
    {
        l(L"Failed to find %ls...", oldName.c_str());
        return;
    }
    found->name = name;
    DIRTY();
    Event e = {
        Event::WHO,
        Event::NAME_CHANGED,
        oldName,
        name.c_str(),
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

void Control::SetWhosParam(Control::evData id, std::wstring key, std::wstring value)
{
    LOGGER(l);
    auto foundEntry = std::find_if(model_->whos.begin(), model_->whos.end(), [id](WhoEntry& e) -> bool {
                return e.name == id;
            });
    if(foundEntry == model_->whos.end()) {
        l(L"Failed to find %ls...", id.c_str());
        return;
    }
    auto&& params = foundEntry->params;

    auto found = std::find_if(params.begin(), params.end(), [key](WhoEntry::Params::reference p) -> bool {
                return p.first == key;
            });
    if(found == params.end()) {
        params.emplace_back(key, value);
    } else {
        found->second = value;
    }

    DIRTY();
    Event e = {
        Event::WHO,
        Event::CHANGED,
        id,
        key,
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

void Control::SetWhosSchema(Control::evData id, Schema const* schema)
{
    LOGGER(l);
    auto foundEntry = std::find_if(model_->whos.begin(), model_->whos.end(), [id](WhoEntry& e) -> bool {
                return e.name == id;
            });
    if(foundEntry == model_->whos.end()) {
        l(L"Failed to find %ls...", id.c_str());
        return;
    }

    foundEntry->schema = schema;

    DIRTY();
    Event e = {
        Event::WHO,
        Event::CHANGED,
        id,
        L" schema",
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

void Control::SetWhatsName(Control::evData id, std::wstring name)
{
    LOGGER(l);
    auto found = std::find_if(model_->whats.begin(), model_->whats.end(), [id](WhatEntry& e) -> bool {
                return e.name == id;
            });
    if(found == model_->whats.end())
    {
        l(L"Failed to find %ls...", id.c_str());
        return;
    }
    found->name = name;
    DIRTY();
    Event e = {
        Event::WHAT,
        Event::NAME_CHANGED,
        id,
        name.c_str(),
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

void Control::SetWhatsBpm(Control::evData id, std::wstring bpm)
{
    LOGGER(l);
    FIND_WHAT(id, return);
    found->bpm = bpm;
    DIRTY();
    Event e = {
        Event::WHAT,
        Event::CHANGED,
        id,
        L"bpm",
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

Event::Source Control::InsertColumnPrivate(evData id, column_p_t before, wchar_t c)
{
    LOGGER(l);
    if(id.empty()
            || id == L"OUTPUT")
    {
        Column col;
        auto size = model_->whats.size();
        model_->output.insert(before, column_t(size, c));
        DIRTY();
        return Event::OUTPUT;
    }

    FIND_WHAT(id, return Event::WHAT);
    auto size = model_->whos.size();
    found->columns.insert(before, column_t(size, c));
    DIRTY();
    return Event::WHAT;
}

void Control::InsertColumn(evData id, column_p_t before, wchar_t c)
{
    LOGGER(l);
    auto source = InsertColumnPrivate(id, before, c);
    if(source == Event::GLOBAL) return;
    Event e = {
        source,
        Event::CHANGED,
        id,
        L"",
        source_
    };
    Fire(&e);
}

void Control::Fire(Event* ev)
{
    LOGGER(l);
    std::for_each(model_->views.begin(), model_->views.end(), [&ev](View* v) {
                v->OnEvent(ev);
            });
}

void Control::SetCell(evData what, column_p_t before, int row, wchar_t c)
{
    LOGGER(l);
    if(what.empty()
            || what == L"OUTPUT")
    {
        if(before == model_->output.end())
        {
            (void) InsertColumnPrivate(what, before, ' ');
            auto pos = model_->output.end();
            std::advance(pos, -1);
            return SetCell(what, pos, row, c);
        }
        auto pos = before->begin();
        std::advance(pos, row);
        *pos = c;
        DIRTY();
        Event e  = {
            Event::OUTPUT,
            Event::CHANGED,
            what,
            L"",
            source_
        };
        Fire(&e);
        return;
    }

    FIND_WHAT(what, return);
    if(before == found->columns.end())
    {
        (void) InsertColumnPrivate(what, before, (c != ' ') ? '.' : ' ');
        auto pos = found->columns.end();
        std::advance(pos, -1);
        return SetCell(what, pos, row, c);
    }
    auto pos = before->begin();
    std::advance(pos, row);
    *pos = c;
    DIRTY();
    Event e  = {
        Event::WHAT,
        Event::CHANGED,
        what,
        L"",
        source_
    };
    Fire(&e);
}

void Control::BlankCell(evData id, int col, int row)
{
    LOGGER(l);
    if(id.empty()
            || id == L"OUTPUT")
    {
        auto it = model_->output.begin();
        std::advance(it, col);
        auto& col = *it;
        if(row < 0 || row >= col.size())
        {
            l(L"my=%d is out of bounds\n", row);
            return;
        }
        auto cit = col.begin();
        std::advance(cit, row);
        auto& cell = *cit;
        cell = (cell == L' ')
            ? L' '
            : L'.'
            ;

        Event e = {
            Event::OUTPUT,
            Event::CHANGED,
            id,
            L"",
            source_
        };
        Fire(&e);

        return;
    } else {
        FIND_WHAT(id, return);
        WhatEntry& we = *found;
        auto it = we.columns.begin();
        std::advance(it, col);
        auto& col = *it;
        if(row < 0 || row >= col.size())
        {
            l(L"my=%d is out of bounds\n", row);
            return;
        }
        auto cit = col.begin();
        std::advance(cit, row);
        auto& cell = *cit;
        cell = (cell == L' ')
            ? L' '
            : L'.'
            ;

        Event e = {
            Event::WHAT,
            Event::CHANGED,
            id,
            L"",
            source_
        };
        Fire(&e);

        return;
    }
}
<commit_msg>mark document dirty on backspace<commit_after>/*
Copyright (c) 2017, Vlad Meșco
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "control.h"
#include "logger.h"
#include "string_utils.h"

#include <algorithm>
#include <cassert>
#include <cstdio>

#define FIND_WHAT(id, then) \
    auto found = FindWhat(id); \
    if(found == model_->whats.end()) then;

#define DIRTY() do{\
    model_->dirty = true; \
}while(0)

auto Control::FindWhat(evData id) -> decltype(model_->whats)::iterator
{
    LOGGER(l);
    auto found = std::find_if(model_->whats.begin(), model_->whats.end(), [id](WhatEntry& e) -> bool {
                return e.name == id;
            });
    if(found == model_->whats.end())
    {
        l(L"Failed to find %ls...", id.c_str());
    }
    return found;
}

void Control::SetWhosName(evData oldName, std::wstring name)
{
    LOGGER(l);
    auto found = std::find_if(model_->whos.begin(), model_->whos.end(), [oldName](WhoEntry& e) -> bool {
                return e.name == oldName;
            });
    if(found == model_->whos.end())
    {
        l(L"Failed to find %ls...", oldName.c_str());
        return;
    }
    found->name = name;
    DIRTY();
    Event e = {
        Event::WHO,
        Event::NAME_CHANGED,
        oldName,
        name.c_str(),
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

void Control::SetWhosParam(Control::evData id, std::wstring key, std::wstring value)
{
    LOGGER(l);
    auto foundEntry = std::find_if(model_->whos.begin(), model_->whos.end(), [id](WhoEntry& e) -> bool {
                return e.name == id;
            });
    if(foundEntry == model_->whos.end()) {
        l(L"Failed to find %ls...", id.c_str());
        return;
    }
    auto&& params = foundEntry->params;

    auto found = std::find_if(params.begin(), params.end(), [key](WhoEntry::Params::reference p) -> bool {
                return p.first == key;
            });
    if(found == params.end()) {
        params.emplace_back(key, value);
    } else {
        found->second = value;
    }

    DIRTY();
    Event e = {
        Event::WHO,
        Event::CHANGED,
        id,
        key,
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

void Control::SetWhosSchema(Control::evData id, Schema const* schema)
{
    LOGGER(l);
    auto foundEntry = std::find_if(model_->whos.begin(), model_->whos.end(), [id](WhoEntry& e) -> bool {
                return e.name == id;
            });
    if(foundEntry == model_->whos.end()) {
        l(L"Failed to find %ls...", id.c_str());
        return;
    }

    foundEntry->schema = schema;

    DIRTY();
    Event e = {
        Event::WHO,
        Event::CHANGED,
        id,
        L" schema",
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

void Control::SetWhatsName(Control::evData id, std::wstring name)
{
    LOGGER(l);
    auto found = std::find_if(model_->whats.begin(), model_->whats.end(), [id](WhatEntry& e) -> bool {
                return e.name == id;
            });
    if(found == model_->whats.end())
    {
        l(L"Failed to find %ls...", id.c_str());
        return;
    }
    found->name = name;
    DIRTY();
    Event e = {
        Event::WHAT,
        Event::NAME_CHANGED,
        id,
        name.c_str(),
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

void Control::SetWhatsBpm(Control::evData id, std::wstring bpm)
{
    LOGGER(l);
    FIND_WHAT(id, return);
    found->bpm = bpm;
    DIRTY();
    Event e = {
        Event::WHAT,
        Event::CHANGED,
        id,
        L"bpm",
        source_
    };
    std::for_each(model_->views.begin(), model_->views.end(), [&e](View* v) {
                v->OnEvent(&e);
            });
}

Event::Source Control::InsertColumnPrivate(evData id, column_p_t before, wchar_t c)
{
    LOGGER(l);
    if(id.empty()
            || id == L"OUTPUT")
    {
        Column col;
        auto size = model_->whats.size();
        model_->output.insert(before, column_t(size, c));
        DIRTY();
        return Event::OUTPUT;
    }

    FIND_WHAT(id, return Event::WHAT);
    auto size = model_->whos.size();
    found->columns.insert(before, column_t(size, c));
    DIRTY();
    return Event::WHAT;
}

void Control::InsertColumn(evData id, column_p_t before, wchar_t c)
{
    LOGGER(l);
    auto source = InsertColumnPrivate(id, before, c);
    if(source == Event::GLOBAL) return;
    Event e = {
        source,
        Event::CHANGED,
        id,
        L"",
        source_
    };
    Fire(&e);
}

void Control::Fire(Event* ev)
{
    LOGGER(l);
    std::for_each(model_->views.begin(), model_->views.end(), [&ev](View* v) {
                v->OnEvent(ev);
            });
}

void Control::SetCell(evData what, column_p_t before, int row, wchar_t c)
{
    LOGGER(l);
    if(what.empty()
            || what == L"OUTPUT")
    {
        if(before == model_->output.end())
        {
            (void) InsertColumnPrivate(what, before, ' ');
            auto pos = model_->output.end();
            std::advance(pos, -1);
            return SetCell(what, pos, row, c);
        }
        auto pos = before->begin();
        std::advance(pos, row);
        *pos = c;
        DIRTY();
        Event e  = {
            Event::OUTPUT,
            Event::CHANGED,
            what,
            L"",
            source_
        };
        Fire(&e);
        return;
    }

    FIND_WHAT(what, return);
    if(before == found->columns.end())
    {
        (void) InsertColumnPrivate(what, before, (c != ' ') ? '.' : ' ');
        auto pos = found->columns.end();
        std::advance(pos, -1);
        return SetCell(what, pos, row, c);
    }
    auto pos = before->begin();
    std::advance(pos, row);
    *pos = c;
    DIRTY();
    Event e  = {
        Event::WHAT,
        Event::CHANGED,
        what,
        L"",
        source_
    };
    Fire(&e);
}

void Control::BlankCell(evData id, int col, int row)
{
    LOGGER(l);
    if(id.empty()
            || id == L"OUTPUT")
    {
        auto it = model_->output.begin();
        std::advance(it, col);
        auto& col = *it;
        if(row < 0 || row >= col.size())
        {
            l(L"my=%d is out of bounds\n", row);
            return;
        }
        auto cit = col.begin();
        std::advance(cit, row);
        auto& cell = *cit;
        cell = (cell == L' ')
            ? L' '
            : L'.'
            ;
        DIRTY();

        Event e = {
            Event::OUTPUT,
            Event::CHANGED,
            id,
            L"",
            source_
        };
        Fire(&e);

        return;
    } else {
        FIND_WHAT(id, return);
        WhatEntry& we = *found;
        auto it = we.columns.begin();
        std::advance(it, col);
        auto& col = *it;
        if(row < 0 || row >= col.size())
        {
            l(L"my=%d is out of bounds\n", row);
            return;
        }
        auto cit = col.begin();
        std::advance(cit, row);
        auto& cell = *cit;
        cell = (cell == L' ')
            ? L' '
            : L'.'
            ;
        DIRTY();

        Event e = {
            Event::WHAT,
            Event::CHANGED,
            id,
            L"",
            source_
        };
        Fire(&e);

        return;
    }
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.14  2001/09/24 15:31:13  peiyongz
 * DTV Reorganization: inherit from AbstractStringValidator
 *
 * Revision 1.12  2001/08/21 18:42:53  peiyongz
 * Bugzilla# 2816: cleanUp() declared with external linkage and called
 *                          before defined as inline
 *
 * Revision 1.11  2001/06/20 17:56:09  peiyongz
 * support for "fixed" option on constrainning facets
 *
 * Revision 1.10  2001/05/29 19:49:36  tng
 * Schema: Constraint Checking Fix in datatypeValidators.  By Pei Yong Zhang.
 *
 * Revision 1.9  2001/05/28 21:11:18  tng
 * Schema: Various DatatypeValidator fix.  By Pei Yong Zhang
 *
 * Revision 1.8  2001/05/23 16:05:11  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.7  2001/05/23 15:45:25  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.6  2001/05/18 13:36:48  tng
 * Schema: Catch RegularExpression exception and NumberFormatException
 *
 * Revision 1.5  2001/05/18 13:23:51  tng
 * Schema: Exception messages in DatatypeValidator.  By Pei Yong Zhang.
 *
 * Revision 1.4  2001/05/16 14:33:40  tng
 * Schema Constraint checking fix.
 *
 * Revision 1.3  2001/05/11 17:17:28  tng
 * Schema: DatatypeValidator fixes.  By Pei Yong Zhang.
 *
 * Revision 1.2  2001/05/11 13:27:29  tng
 * Copyright update.
 *
 * Revision 1.1  2001/05/09 18:43:42  tng
 * Add StringDatatypeValidator and BooleanDatatypeValidator.  By Pei Yong Zhang.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <validators/datatype/StringDatatypeValidator.hpp>
#include <validators/schema/SchemaSymbols.hpp>
#include <validators/datatype/InvalidDatatypeFacetException.hpp>
#include <validators/datatype/InvalidDatatypeValueException.hpp>

static const int BUF_LEN = 64;
static XMLCh value1[BUF_LEN+1];
static XMLCh value2[BUF_LEN+1];

// ---------------------------------------------------------------------------
//  Constructors and Destructor
// ---------------------------------------------------------------------------
StringDatatypeValidator::StringDatatypeValidator()
:AbstractStringValidator(0, 0, 0, DatatypeValidator::String)
,fWhiteSpace(DatatypeValidator::PRESERVE)
{}

StringDatatypeValidator::~StringDatatypeValidator()
{}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , RefVectorOf<XMLCh>*           const enums
                        , const int                           finalSet)
:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::String)
,fWhiteSpace(DatatypeValidator::PRESERVE)
{
    init(baseValidator, facets, enums);
}

DatatypeValidator* StringDatatypeValidator::newInstance(
                                      RefHashTableOf<KVStringPair>* const facets
                                    , RefVectorOf<XMLCh>*           const enums
                                    , const int                           finalSet)
{
    return (DatatypeValidator*) new StringDatatypeValidator(this, facets, enums, finalSet);
}

short StringDatatypeValidator::getWSFacet() const
{
    return fWhiteSpace;
}

// ---------------------------------------------------------------------------
//  Utilities
// ---------------------------------------------------------------------------
void StringDatatypeValidator::assignAdditionalFacet(const XMLCh* const key
                                                  , const XMLCh* const value)
{
    if (XMLString::compareString(key, SchemaSymbols::fgELT_WHITESPACE)==0)
    {
        // whiteSpace = preserve | replace | collapse
        if (XMLString::compareString(value, SchemaSymbols::fgWS_PRESERVE) == 0)
            setWhiteSpace(DatatypeValidator::PRESERVE);
        else if (XMLString::compareString(value, SchemaSymbols::fgWS_REPLACE) == 0)
            setWhiteSpace(DatatypeValidator::REPLACE);
        else if (XMLString::compareString(value, SchemaSymbols::fgWS_COLLAPSE) == 0)
            setWhiteSpace(DatatypeValidator::COLLAPSE);
        else
            ThrowXML1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_WS, value);
        //("whiteSpace value '" + ws + "' must be one of 'preserve', 'replace', 'collapse'.");

        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
    else
    {
        ThrowXML1(InvalidDatatypeFacetException
                , XMLExcepts::FACET_Invalid_Tag
                , key);
    }
}

void StringDatatypeValidator::inheritAdditionalFacet()
{
    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    // inherit whitespace
    if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
        ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) == 0))
    {
        setWhiteSpace(getBaseValidator()->getWSFacet());
        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
}

void StringDatatypeValidator::checkAdditionalFacetConstraints() const
{

    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();
    short    thisWSFacet = getWSFacet();
    short    baseWSFacet = pBaseValidator->getWSFacet();

    // check 4.3.6.c1 error: whitespace
    if (((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0) &&
        ((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 ))
    {
        if ((baseWSFacet == DatatypeValidator::COLLAPSE) &&
            ((thisWSFacet == DatatypeValidator::PRESERVE) ||
             (thisWSFacet == DatatypeValidator::REPLACE)))
             ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_collapse);

        if ((baseWSFacet == DatatypeValidator::REPLACE) &&
            (thisWSFacet == DatatypeValidator::PRESERVE))
            ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_replace);

        if (((pBaseValidator->getFixed() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
            ( thisWSFacet != baseWSFacet))
        {
            ThrowXML2(InvalidDatatypeFacetException
                        , XMLExcepts::FACET_whitespace_base_fixed
                        , getWSstring(thisWSFacet)
                        , getWSstring(baseWSFacet));
        }
    }

}

void StringDatatypeValidator::checkAdditionalFacet(const XMLCh* const content) const
{
    //
    // check WhiteSpace
    //
    if ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 )
    {
        if ( getWSFacet() == DatatypeValidator::REPLACE )
        {
            if (!XMLString::isWSReplaced(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_replaced, content);
        }
        else if ( getWSFacet() == DatatypeValidator::COLLAPSE )
        {
            if (!XMLString::isWSCollapsed(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_collapsed, content);
        }

    }
}

void StringDatatypeValidator::checkValueSpace(const XMLCh* const content)
{}

int StringDatatypeValidator::getLength(const XMLCh* const content) const
{
    return XMLString::stringLen(content);
}

/**
  * End of file StringDatatypeValidator.cpp
  */
<commit_msg>Check baseValidator in assignAdditinoalFacet() and inheritAdditionalFacet()<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 2001, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.15  2001/09/25 15:58:14  peiyongz
 * Check baseValidator in assignAdditinoalFacet() and inheritAdditionalFacet()
 *
 * Revision 1.14  2001/09/24 15:31:13  peiyongz
 * DTV Reorganization: inherit from AbstractStringValidator
 *
 * Revision 1.12  2001/08/21 18:42:53  peiyongz
 * Bugzilla# 2816: cleanUp() declared with external linkage and called
 *                          before defined as inline
 *
 * Revision 1.11  2001/06/20 17:56:09  peiyongz
 * support for "fixed" option on constrainning facets
 *
 * Revision 1.10  2001/05/29 19:49:36  tng
 * Schema: Constraint Checking Fix in datatypeValidators.  By Pei Yong Zhang.
 *
 * Revision 1.9  2001/05/28 21:11:18  tng
 * Schema: Various DatatypeValidator fix.  By Pei Yong Zhang
 *
 * Revision 1.8  2001/05/23 16:05:11  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.7  2001/05/23 15:45:25  tng
 * Schema: NormalizedString fix.  By Pei Yong Zhang.
 *
 * Revision 1.6  2001/05/18 13:36:48  tng
 * Schema: Catch RegularExpression exception and NumberFormatException
 *
 * Revision 1.5  2001/05/18 13:23:51  tng
 * Schema: Exception messages in DatatypeValidator.  By Pei Yong Zhang.
 *
 * Revision 1.4  2001/05/16 14:33:40  tng
 * Schema Constraint checking fix.
 *
 * Revision 1.3  2001/05/11 17:17:28  tng
 * Schema: DatatypeValidator fixes.  By Pei Yong Zhang.
 *
 * Revision 1.2  2001/05/11 13:27:29  tng
 * Copyright update.
 *
 * Revision 1.1  2001/05/09 18:43:42  tng
 * Add StringDatatypeValidator and BooleanDatatypeValidator.  By Pei Yong Zhang.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <validators/datatype/StringDatatypeValidator.hpp>
#include <validators/schema/SchemaSymbols.hpp>
#include <validators/datatype/InvalidDatatypeFacetException.hpp>
#include <validators/datatype/InvalidDatatypeValueException.hpp>

static const int BUF_LEN = 64;
static XMLCh value1[BUF_LEN+1];
static XMLCh value2[BUF_LEN+1];

// ---------------------------------------------------------------------------
//  Constructors and Destructor
// ---------------------------------------------------------------------------
StringDatatypeValidator::StringDatatypeValidator()
:AbstractStringValidator(0, 0, 0, DatatypeValidator::String)
,fWhiteSpace(DatatypeValidator::PRESERVE)
{}

StringDatatypeValidator::~StringDatatypeValidator()
{}

StringDatatypeValidator::StringDatatypeValidator(
                          DatatypeValidator*            const baseValidator
                        , RefHashTableOf<KVStringPair>* const facets
                        , RefVectorOf<XMLCh>*           const enums
                        , const int                           finalSet)
:AbstractStringValidator(baseValidator, facets, finalSet, DatatypeValidator::String)
,fWhiteSpace(DatatypeValidator::PRESERVE)
{
    init(baseValidator, facets, enums);
}

DatatypeValidator* StringDatatypeValidator::newInstance(
                                      RefHashTableOf<KVStringPair>* const facets
                                    , RefVectorOf<XMLCh>*           const enums
                                    , const int                           finalSet)
{
    return (DatatypeValidator*) new StringDatatypeValidator(this, facets, enums, finalSet);
}

short StringDatatypeValidator::getWSFacet() const
{
    return fWhiteSpace;
}

// ---------------------------------------------------------------------------
//  Utilities
// ---------------------------------------------------------------------------
void StringDatatypeValidator::assignAdditionalFacet(const XMLCh* const key
                                                  , const XMLCh* const value)
{
    if (XMLString::compareString(key, SchemaSymbols::fgELT_WHITESPACE)==0)
    {
        // whiteSpace = preserve | replace | collapse
        if (XMLString::compareString(value, SchemaSymbols::fgWS_PRESERVE) == 0)
            setWhiteSpace(DatatypeValidator::PRESERVE);
        else if (XMLString::compareString(value, SchemaSymbols::fgWS_REPLACE) == 0)
            setWhiteSpace(DatatypeValidator::REPLACE);
        else if (XMLString::compareString(value, SchemaSymbols::fgWS_COLLAPSE) == 0)
            setWhiteSpace(DatatypeValidator::COLLAPSE);
        else
            ThrowXML1(InvalidDatatypeFacetException, XMLExcepts::FACET_Invalid_WS, value);
        //("whiteSpace value '" + ws + "' must be one of 'preserve', 'replace', 'collapse'.");

        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
    else
    {
        ThrowXML1(InvalidDatatypeFacetException
                , XMLExcepts::FACET_Invalid_Tag
                , key);
    }
}

void StringDatatypeValidator::inheritAdditionalFacet()
{
    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    // inherit whitespace
    if (((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
        ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) == 0))
    {
        setWhiteSpace(getBaseValidator()->getWSFacet());
        setFacetsDefined(DatatypeValidator::FACET_WHITESPACE);
    }
}

void StringDatatypeValidator::checkAdditionalFacetConstraints() const
{

    StringDatatypeValidator *pBaseValidator = (StringDatatypeValidator*) getBaseValidator();

    if (!pBaseValidator)
        return;

    short    thisWSFacet = getWSFacet();
    short    baseWSFacet = pBaseValidator->getWSFacet();

    // check 4.3.6.c1 error: whitespace
    if (((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0) &&
        ((pBaseValidator->getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 ))
    {
        if ((baseWSFacet == DatatypeValidator::COLLAPSE) &&
            ((thisWSFacet == DatatypeValidator::PRESERVE) ||
             (thisWSFacet == DatatypeValidator::REPLACE)))
             ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_collapse);

        if ((baseWSFacet == DatatypeValidator::REPLACE) &&
            (thisWSFacet == DatatypeValidator::PRESERVE))
            ThrowXML(InvalidDatatypeFacetException, XMLExcepts::FACET_WS_replace);

        if (((pBaseValidator->getFixed() & DatatypeValidator::FACET_WHITESPACE) !=0) &&
            ( thisWSFacet != baseWSFacet))
        {
            ThrowXML2(InvalidDatatypeFacetException
                        , XMLExcepts::FACET_whitespace_base_fixed
                        , getWSstring(thisWSFacet)
                        , getWSstring(baseWSFacet));
        }
    }

}

void StringDatatypeValidator::checkAdditionalFacet(const XMLCh* const content) const
{
    //
    // check WhiteSpace
    //
    if ((getFacetsDefined() & DatatypeValidator::FACET_WHITESPACE) != 0 )
    {
        if ( getWSFacet() == DatatypeValidator::REPLACE )
        {
            if (!XMLString::isWSReplaced(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_replaced, content);
        }
        else if ( getWSFacet() == DatatypeValidator::COLLAPSE )
        {
            if (!XMLString::isWSCollapsed(content))
                ThrowXML1(InvalidDatatypeValueException, XMLExcepts::VALUE_WS_collapsed, content);
        }

    }
}

void StringDatatypeValidator::checkValueSpace(const XMLCh* const content)
{}

int StringDatatypeValidator::getLength(const XMLCh* const content) const
{
    return XMLString::stringLen(content);
}

/**
  * End of file StringDatatypeValidator.cpp
  */
<|endoftext|>


<commit_before>#include <sstream>
#include <set>
#include <memory>
#include <dlfcn.h>

#include "plugin-loader.hpp"
#include "output.hpp"
#include "../core/wm.hpp"
#include "core.hpp"
#include "debug.hpp"

namespace
{
    template<class A, class B> B union_cast(A object)
    {
        union {
            A x;
            B y;
        } helper;
        helper.x = object;
        return helper.y;
    }
}

static const std::string default_plugins = "viewport_impl move resize animate \
                                            switcher vswitch cube expo command \
                                            grid";

static void idle_reload(void *data)
{
    auto manager = (plugin_manager *) data;
    manager->reload_dynamic_plugins();
    manager->idle_reload_dynamic_plugins = NULL;
}

plugin_manager::plugin_manager(wayfire_output *o, wayfire_config *config)
{
    this->config = config;
    this->output = o;

    auto section = config->get_section("core");
    plugins_opt = section->get_option("plugins", "default");

    reload_dynamic_plugins();
    load_static_plugins();

    list_updated = [=] ()
    {
        /* reload when config reload has finished */
        idle_reload_dynamic_plugins =
            wl_event_loop_add_idle(core->ev_loop, idle_reload, this);
    };

    plugins_opt->updated.push_back(&list_updated);
}

plugin_manager::~plugin_manager()
{
    for (auto& p : loaded_plugins)
        destroy_plugin(p.second);

    loaded_plugins.clear();
    wl_event_source_remove(idle_reload_dynamic_plugins);

    plugins_opt->updated.erase(std::remove(plugins_opt->updated.begin(), plugins_opt->updated.end(),
                                           &list_updated), plugins_opt->updated.end());
}

void plugin_manager::init_plugin(wayfire_plugin& p)
{
    p->grab_interface = new wayfire_grab_interface_t(output);
    p->output = output;

    p->init(config);
}

void plugin_manager::destroy_plugin(wayfire_plugin& p)
{
    p->grab_interface->ungrab();
    output->deactivate_plugin(p->grab_interface);

    p->fini();
    delete p->grab_interface;

    /* we load the same plugins for each output, so we must dlclose() the handle
     * only when we remove the last output */
    if (core->get_num_outputs() < 1)
    {
        if (p->dynamic)
            dlclose(p->handle);
    }

    p.reset();
}

wayfire_plugin plugin_manager::load_plugin_from_file(std::string path)
{
    void *handle = dlopen(path.c_str(), RTLD_NOW);
    if(handle == NULL)
    {
        log_error("error loading plugin: %s", dlerror());
        return nullptr;
    }

    auto initptr = dlsym(handle, "newInstance");
    if(initptr == NULL)
    {
        log_error("%s: missing newInstance(). %s", path.c_str(), dlerror());
        return nullptr;
    }

    log_debug("loading plugin %s", path.c_str());
    get_plugin_instance_t init = union_cast<void*, get_plugin_instance_t> (initptr);

    auto ptr = wayfire_plugin(init());

    ptr->handle = handle;
    ptr->dynamic = true;

    return wayfire_plugin(init());
}

void plugin_manager::reload_dynamic_plugins()
{
    std::stringstream stream(plugins_opt->as_string());
    std::vector<std::string> next_plugins;

    std::string plugin;
    while(stream >> plugin)
    {
        if(plugin != "")
            next_plugins.push_back(plugin);
    }

    /* erase plugins that have been removed from the config */
    auto it = loaded_plugins.begin();
    while(it != loaded_plugins.end())
    {
        /* skip built-in(static) plugins */
        if (it->first.size() && it->first[0] == '_')
        {
            ++it;
            continue;
        }

        if (std::find(next_plugins.begin(), next_plugins.end(), it->first) == next_plugins.end())
        {
            log_debug("unload plugin %s", it->first.c_str());
            destroy_plugin(it->second);
            it = loaded_plugins.erase(it);
        } else
        {
            ++it;
        }
    }

    /* load new plugins */
    auto path = std::string(INSTALL_PREFIX "/lib/wayfire/");
    for (auto plugin : next_plugins)
    {
        if (loaded_plugins.count(plugin))
            continue;

        auto ptr = load_plugin_from_file(path + "lib" + plugin + ".so");
        if (ptr)
        {
            init_plugin(ptr);
            loaded_plugins[plugin] = std::move(ptr);
        }
    }
}

template<class T> static wayfire_plugin create_plugin()
{
    return std::unique_ptr<wayfire_plugin_t>(new T);
}

void plugin_manager::load_static_plugins()
{
    loaded_plugins["_exit"]         = create_plugin<wayfire_exit>();
    loaded_plugins["_focus"]        = create_plugin<wayfire_focus>();
    loaded_plugins["_close"]        = create_plugin<wayfire_close>();
    loaded_plugins["_focus_parent"] = create_plugin<wayfire_handle_focus_parent>();

    init_plugin(loaded_plugins["_exit"]);
    init_plugin(loaded_plugins["_focus"]);
    init_plugin(loaded_plugins["_close"]);
    init_plugin(loaded_plugins["_focus_parent"]);
}
<commit_msg>plugin-loader: add support for absolute plugin paths<commit_after>#include <sstream>
#include <set>
#include <memory>
#include <dlfcn.h>

#include "plugin-loader.hpp"
#include "output.hpp"
#include "../core/wm.hpp"
#include "core.hpp"
#include "debug.hpp"

namespace
{
    template<class A, class B> B union_cast(A object)
    {
        union {
            A x;
            B y;
        } helper;
        helper.x = object;
        return helper.y;
    }
}

static const std::string default_plugins = "viewport_impl move resize animate \
                                            switcher vswitch cube expo command \
                                            grid";

static void idle_reload(void *data)
{
    auto manager = (plugin_manager *) data;
    manager->reload_dynamic_plugins();
    manager->idle_reload_dynamic_plugins = NULL;
}

plugin_manager::plugin_manager(wayfire_output *o, wayfire_config *config)
{
    this->config = config;
    this->output = o;

    auto section = config->get_section("core");
    plugins_opt = section->get_option("plugins", "default");

    reload_dynamic_plugins();
    load_static_plugins();

    list_updated = [=] ()
    {
        /* reload when config reload has finished */
        idle_reload_dynamic_plugins =
            wl_event_loop_add_idle(core->ev_loop, idle_reload, this);
    };

    plugins_opt->updated.push_back(&list_updated);
}

plugin_manager::~plugin_manager()
{
    for (auto& p : loaded_plugins)
        destroy_plugin(p.second);

    loaded_plugins.clear();
    wl_event_source_remove(idle_reload_dynamic_plugins);

    plugins_opt->updated.erase(std::remove(plugins_opt->updated.begin(), plugins_opt->updated.end(),
                                           &list_updated), plugins_opt->updated.end());
}

void plugin_manager::init_plugin(wayfire_plugin& p)
{
    p->grab_interface = new wayfire_grab_interface_t(output);
    p->output = output;

    p->init(config);
}

void plugin_manager::destroy_plugin(wayfire_plugin& p)
{
    p->grab_interface->ungrab();
    output->deactivate_plugin(p->grab_interface);

    p->fini();
    delete p->grab_interface;

    /* we load the same plugins for each output, so we must dlclose() the handle
     * only when we remove the last output */
    if (core->get_num_outputs() < 1)
    {
        if (p->dynamic)
            dlclose(p->handle);
    }

    p.reset();
}

wayfire_plugin plugin_manager::load_plugin_from_file(std::string path)
{
    void *handle = dlopen(path.c_str(), RTLD_NOW);
    if(handle == NULL)
    {
        log_error("error loading plugin: %s", dlerror());
        return nullptr;
    }

    auto initptr = dlsym(handle, "newInstance");
    if(initptr == NULL)
    {
        log_error("%s: missing newInstance(). %s", path.c_str(), dlerror());
        return nullptr;
    }

    log_debug("loading plugin %s", path.c_str());
    get_plugin_instance_t init = union_cast<void*, get_plugin_instance_t> (initptr);

    auto ptr = wayfire_plugin(init());

    ptr->handle = handle;
    ptr->dynamic = true;

    return wayfire_plugin(init());
}

void plugin_manager::reload_dynamic_plugins()
{
    std::stringstream stream(plugins_opt->as_string());
    std::vector<std::string> next_plugins;

    std::string plugin;
    while(stream >> plugin)
    {
        if(plugin != "")
            next_plugins.push_back(plugin);
    }

    /* erase plugins that have been removed from the config */
    auto it = loaded_plugins.begin();
    while(it != loaded_plugins.end())
    {
        /* skip built-in(static) plugins */
        if (it->first.size() && it->first[0] == '_')
        {
            ++it;
            continue;
        }

        if (std::find(next_plugins.begin(), next_plugins.end(), it->first) == next_plugins.end())
        {
            log_debug("unload plugin %s", it->first.c_str());
            destroy_plugin(it->second);
            it = loaded_plugins.erase(it);
        } else
        {
            ++it;
        }
    }

    /* load new plugins */
    auto path = std::string(INSTALL_PREFIX "/lib/wayfire/");
    for (auto plugin : next_plugins)
    {
        if (!plugin.length())
            continue;

        std::string plugin_path;
        if (plugin.size() && plugin[0] == '/')
        {
            plugin_path = plugin;
        } else
        {
            plugin_path = path + "lib" + plugin + ".so";
        }

        if (loaded_plugins.count(plugin_path))
            continue;

        auto ptr = load_plugin_from_file(plugin_path);
        if (ptr)
        {
            init_plugin(ptr);
            loaded_plugins[plugin] = std::move(ptr);
        }
    }
}

template<class T> static wayfire_plugin create_plugin()
{
    return std::unique_ptr<wayfire_plugin_t>(new T);
}

void plugin_manager::load_static_plugins()
{
    loaded_plugins["_exit"]         = create_plugin<wayfire_exit>();
    loaded_plugins["_focus"]        = create_plugin<wayfire_focus>();
    loaded_plugins["_close"]        = create_plugin<wayfire_close>();
    loaded_plugins["_focus_parent"] = create_plugin<wayfire_handle_focus_parent>();

    init_plugin(loaded_plugins["_exit"]);
    init_plugin(loaded_plugins["_focus"]);
    init_plugin(loaded_plugins["_close"]);
    init_plugin(loaded_plugins["_focus_parent"]);
}
<|endoftext|>


<commit_before>#include "photoeffects.hpp"

using namespace cv;

int tint(InputArray src, OutputArray dst,
        const Vec3b &colorTint, float density)
{
    CV_Assert(src.type() == CV_8UC3);
    CV_Assert(density >= 0.0f || density <= 1.0f);
    dst.create(src.size(), CV_8UC3);
    Mat image = src.getMat(), outputImage = dst.getMat();
    float negDen = 1 - density;
    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++)
        {
            Vec3b colorDest = image.at<Vec3b>(i, j);
            colorDest = colorTint * density + negDen * colorDest;
            outputImage.at<Vec3b>(i, j) = colorDest;
        }
    }
    outputImage.convertTo(dst, CV_8UC3);
    return 0;
}
<commit_msg>Update tint.cpp<commit_after>#include "photoeffects.hpp"

using namespace cv;

int tint(InputArray src, OutputArray dst,
        const Vec3b &colorTint, float density)
{
    CV_Assert(src.type() == CV_8UC3);
    CV_Assert(density >= 0.0f || density <= 1.0f);
    dst.create(src.size(), CV_8UC3);
    Mat image = src.getMat(), outputImage = dst.getMat();
    float negDen = 1 - density;
    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++)
        {
            Vec3b colorDest = image.at<Vec3b>(i, j);
            colorDest = colorTint * density + negDen * colorDest;
            outputImage.at<Vec3b>(i, j) = colorDest;
        }
    }
    return 0;
}
<|endoftext|>


<commit_before>#include "physics/forkable.hpp"

#include "geometry/named_quantities.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "quantities/si.hpp"

namespace principia {

using geometry::Instant;
using si::Second;
using ::testing::ElementsAre;

namespace physics {

class FakeTrajectory : public Forkable<FakeTrajectory,
                                       std::list<Instant>::const_iterator> {
 public:
  FakeTrajectory();

  void push_back(Instant const& time);

 protected:
  not_null<FakeTrajectory*> that() override;
  not_null<FakeTrajectory const*> that() const override;

  TimelineConstIterator timeline_begin() const override;
  TimelineConstIterator timeline_end() const override;
  TimelineConstIterator timeline_find(Instant const& time) const override;
  void timeline_insert(TimelineConstIterator begin,
                       TimelineConstIterator end) override;
  bool timeline_empty() const override;

 private:
  // Use list<> because we want the iterators to remain valid across operations.
  std::list<Instant> timeline_;

  template<typename Tr4jectory, typename TimelineConstIterator_>
  friend class Forkable;
  template<typename Tr4jectory, typename TimelineConstIterator_>
  friend class Forkable<Tr4jectory, TimelineConstIterator_>::Iterator;
};

FakeTrajectory::FakeTrajectory()
    : Forkable<FakeTrajectory,
               std::list<Instant>::const_iterator>() {}

void FakeTrajectory::push_back(Instant const& time) {
  timeline_.push_back(time);
}

not_null<FakeTrajectory*> FakeTrajectory::that() {
  return this;
}

not_null<FakeTrajectory const*> FakeTrajectory::that() const {
  return this;
}

FakeTrajectory::TimelineConstIterator FakeTrajectory::timeline_begin() const {
  return timeline_.begin();
}

FakeTrajectory::TimelineConstIterator FakeTrajectory::timeline_end() const {
  return timeline_.end();
}

FakeTrajectory::TimelineConstIterator FakeTrajectory::timeline_find(
    Instant const & time) const {
  // Stupid O(N) search.
  for (auto it = timeline_.begin(); it != timeline_.end(); ++it) {
    if (*it == time) {
      return it;
    }
  }
  return timeline_.end();
}

void FakeTrajectory::timeline_insert(TimelineConstIterator begin,
                                     TimelineConstIterator end) {
  CHECK(timeline_empty());
  timeline_.insert(timeline_.end(), begin, end);
}

bool FakeTrajectory::timeline_empty() const {
  return timeline_.empty();
}

class ForkableTest : public testing::Test {
 protected:
  ForkableTest() :
    t0_(),
    t1_(t0_ + 7 * Second),
    t2_(t0_ + 17 * Second),
    t3_(t0_ + 27 * Second),
    t4_(t0_ + 37 * Second) {}

  static std::vector<Instant> After(
      not_null<FakeTrajectory const*> const trajectory,
      Instant const& time) {
    std::vector<Instant> after;
    for (FakeTrajectory::Iterator it = trajectory->Find(time);
         it != trajectory->End();
         ++it) {
      after.push_back(*it.current());
    }
    return after;
  }

  static Instant const& LastTime(
      not_null<FakeTrajectory const*> const trajectory) {
    FakeTrajectory::Iterator it = trajectory->End();
    --it;
    return *it.current();
  }

  static std::vector<Instant> Times(
      not_null<FakeTrajectory const*> const trajectory) {
    std::vector<Instant> times;
    for (FakeTrajectory::Iterator it = trajectory->Begin();
         it != trajectory->End();
         ++it) {
      times.push_back(*it.current());
    }
    return times;
  }

  FakeTrajectory trajectory_;
  Instant t0_, t1_, t2_, t3_, t4_;
};

using ForkableDeathTest = ForkableTest;

TEST_F(ForkableDeathTest, ForkError) {
  EXPECT_DEATH({
    trajectory_.push_back(t1_);
    trajectory_.push_back(t3_);
    trajectory_.NewFork(t2_);
  }, "nonexistent time");
}

TEST_F(ForkableDeathTest, ForkSuccess) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);
  not_null<FakeTrajectory*> const fork = trajectory_.NewFork(t2_);
  fork->push_back(t4_);
  auto times = Times(&trajectory_);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));
  times = Times(fork);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_, t4_));
}

TEST_F(ForkableTest, ForkAtLast) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);
  not_null<FakeTrajectory*> const fork1 = trajectory_.NewFork(t3_);
  not_null<FakeTrajectory*> const fork2 = fork1->NewFork(LastTime(fork1));
  not_null<FakeTrajectory*> const fork3 = fork2->NewFork(LastTime(fork1));
  EXPECT_EQ(t3_, LastTime(&trajectory_));
  EXPECT_EQ(t3_, LastTime(fork1));

  auto times = Times(fork2);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));
  EXPECT_EQ(t3_, LastTime(fork2));
  EXPECT_EQ(t3_, *fork2->ForkTime());

  auto after = After(fork3, t3_);
  EXPECT_THAT(after, ElementsAre(t3_));

  after = After(fork2, t3_);
  EXPECT_THAT(after, ElementsAre(t3_));

  fork1->push_back(t4_);
  times = Times(fork2);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));

  after = After(fork1, t3_);
  EXPECT_THAT(after, ElementsAre(t3_, t4_));

  times = Times(fork3);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));

  fork2->push_back(t4_);
  after = After(fork2, t3_);
  EXPECT_THAT(after, ElementsAre(t3_, t4_));

  fork3->push_back(t4_);
  after = After(fork3, t3_);
  EXPECT_THAT(after, ElementsAre(t3_, t4_));

  after = After(fork3, t2_);
  EXPECT_THAT(after, ElementsAre(t2_, t3_, t4_));
}

TEST_F(ForkableDeathTest, DeleteForkError) {
  EXPECT_DEATH({
    trajectory_.push_back(t1_);
    FakeTrajectory* root = &trajectory_;
    trajectory_.DeleteFork(&root);
  }, "'fork_time'.* non NULL");
  EXPECT_DEATH({
    trajectory_.push_back(t1_);
    FakeTrajectory* fork1 = trajectory_.NewFork(t1_);
    fork1->push_back(t2_);
    FakeTrajectory* fork2 = fork1->NewFork(t2_);
    trajectory_.DeleteFork(&fork2);
  }, "not a child");
}

//TEST_F(ForkableDeathTest, DeleteForkSuccess) {
//  trajectory_.push_back(t1_);
//  trajectory_.push_back(t2_);
//  trajectory_.push_back(t3_);
//  not_null<FakeTrajectory*> const fork1 = trajectory_.NewFork(t2_);
//  FakeTrajectory* fork2 = trajectory_.NewFork(t2_);
//  fork1.push_back(t4_);
//  trajectory_.DeleteFork(&fork2);
//  EXPECT_EQ(nullptr, fork2);
//  std::map<Instant, Position<World>> positions =
//      trajectory_.Positions();
//  std::map<Instant, Velocity<World>> velocities =
//      trajectory_.Velocities();
//  std::list<Instant> times = trajectory_.Times();
//  EXPECT_THAT(positions, ElementsAre(testing::Pair(t1_, q1_),
//                                     testing::Pair(t2_, q2_),
//                                     testing::Pair(t3_, q3_)));
//  EXPECT_THAT(velocities, ElementsAre(testing::Pair(t1_, p1_),
//                                      testing::Pair(t2_, p2_),
//                                      testing::Pair(t3_, p3_)));
//  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));
//  EXPECT_THAT(fork1->body<MassiveBody>(), Eq(&massive_body_));
//  positions = fork1->Positions();
//  velocities = fork1->Velocities();
//  times = fork1->Times();
//  EXPECT_THAT(positions, ElementsAre(testing::Pair(t1_, q1_),
//                                     testing::Pair(t2_, q2_),
//                                     testing::Pair(t3_, q3_),
//                                     testing::Pair(t4_, q4_)));
//  EXPECT_THAT(velocities, ElementsAre(testing::Pair(t1_, p1_),
//                                      testing::Pair(t2_, p2_),
//                                      testing::Pair(t3_, p3_),
//                                      testing::Pair(t4_, p4_)));
//  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_, t4_));
//  EXPECT_THAT(fork1->body<MassiveBody>(), Eq(&massive_body_));
//  trajectory_.reset();
//}
//
TEST_F(ForkableDeathTest, IteratorDecrementError) {
  EXPECT_DEATH({
    auto it = trajectory_.End();
    --it;
  }, "parent_.*non NULL");
}

TEST_F(ForkableTest, IteratorDecrementNoForkSuccess) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);
  auto it = trajectory_.End();
  --it;
  EXPECT_EQ(t3_, *it.current());
  --it;
  EXPECT_EQ(t2_, *it.current());
  --it;
  EXPECT_EQ(t1_, *it.current());
}

TEST_F(ForkableTest, IteratorDecrementForkSuccess) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  auto fork = trajectory_.NewFork(t1_);
  trajectory_.push_back(t4_);
  fork->push_back(t3_);
  auto it = fork->End();
  --it;
  EXPECT_EQ(t3_, *it.current());
  --it;
  EXPECT_EQ(t2_, *it.current());
  --it;
  EXPECT_EQ(t1_, *it.current());
}

TEST_F(ForkableTest, Root) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);
  not_null<FakeTrajectory*> const fork = trajectory_.NewFork(t2_);
  EXPECT_TRUE(trajectory_.is_root());
  EXPECT_FALSE(fork->is_root());
  EXPECT_EQ(&trajectory_, trajectory_.root());
  EXPECT_EQ(&trajectory_, fork->root());
  EXPECT_EQ(nullptr, trajectory_.ForkTime());
  EXPECT_EQ(t2_, *fork->ForkTime());
}

TEST_F(ForkableTest, IteratorBeginSuccess) {
  auto it = trajectory_.Begin();
  EXPECT_EQ(it, trajectory_.End());

  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);

  it = trajectory_.Begin();
  EXPECT_NE(it, trajectory_.End());
  EXPECT_EQ(t1_, *it.current());
  ++it;
  EXPECT_EQ(t2_, *it.current());
  ++it;
  EXPECT_EQ(t3_, *it.current());
  ++it;
  EXPECT_EQ(it, trajectory_.End());

  not_null<FakeTrajectory*> const fork = trajectory_.NewFork(t2_);
  fork->push_back(t4_);

  it = fork->Begin();
  EXPECT_NE(it, trajectory_.End());
  EXPECT_EQ(t1_, *it.current());
  ++it;
  EXPECT_EQ(t2_, *it.current());
  ++it;
  EXPECT_EQ(t3_, *it.current());
  ++it;
  EXPECT_EQ(t4_, *it.current());
  ++it;
  EXPECT_EQ(it, trajectory_.End());
}

TEST_F(ForkableTest, IteratorFindSuccess) {
  auto it = trajectory_.Find(t0_);
  EXPECT_EQ(it, trajectory_.End());

  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);

  it = trajectory_.Find(t1_);
  EXPECT_NE(it, trajectory_.End());
  EXPECT_EQ(t1_, *it.current());
  it = trajectory_.Find(t2_);
  EXPECT_EQ(t2_, *it.current());
  it = trajectory_.Find(t4_);
  EXPECT_EQ(it, trajectory_.End());

  not_null<FakeTrajectory*> const fork = trajectory_.NewFork(t2_);
  fork->push_back(t4_);

  it = fork->Find(t1_);
  EXPECT_NE(it, trajectory_.End());
  EXPECT_EQ(t1_, *it.current());
  it = fork->Find(t2_);
  EXPECT_EQ(t2_, *it.current());
  it = fork->Find(t4_);
  EXPECT_EQ(t4_, *it.current());
  it = fork->Find(t4_ + 1 * Second);
  EXPECT_EQ(it, trajectory_.End());
}

}  // namespace physics
}  // namespace principia
<commit_msg>All tests passing.<commit_after>#include "physics/forkable.hpp"

#include "geometry/named_quantities.hpp"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "quantities/si.hpp"

namespace principia {

using geometry::Instant;
using si::Second;
using ::testing::ElementsAre;

namespace physics {

class FakeTrajectory : public Forkable<FakeTrajectory,
                                       std::list<Instant>::const_iterator> {
 public:
  FakeTrajectory();

  void push_back(Instant const& time);

 protected:
  not_null<FakeTrajectory*> that() override;
  not_null<FakeTrajectory const*> that() const override;

  TimelineConstIterator timeline_begin() const override;
  TimelineConstIterator timeline_end() const override;
  TimelineConstIterator timeline_find(Instant const& time) const override;
  void timeline_insert(TimelineConstIterator begin,
                       TimelineConstIterator end) override;
  bool timeline_empty() const override;

 private:
  // Use list<> because we want the iterators to remain valid across operations.
  std::list<Instant> timeline_;

  template<typename Tr4jectory, typename TimelineConstIterator_>
  friend class Forkable;
  template<typename Tr4jectory, typename TimelineConstIterator_>
  friend class Forkable<Tr4jectory, TimelineConstIterator_>::Iterator;
};

FakeTrajectory::FakeTrajectory()
    : Forkable<FakeTrajectory,
               std::list<Instant>::const_iterator>() {}

void FakeTrajectory::push_back(Instant const& time) {
  timeline_.push_back(time);
}

not_null<FakeTrajectory*> FakeTrajectory::that() {
  return this;
}

not_null<FakeTrajectory const*> FakeTrajectory::that() const {
  return this;
}

FakeTrajectory::TimelineConstIterator FakeTrajectory::timeline_begin() const {
  return timeline_.begin();
}

FakeTrajectory::TimelineConstIterator FakeTrajectory::timeline_end() const {
  return timeline_.end();
}

FakeTrajectory::TimelineConstIterator FakeTrajectory::timeline_find(
    Instant const & time) const {
  // Stupid O(N) search.
  for (auto it = timeline_.begin(); it != timeline_.end(); ++it) {
    if (*it == time) {
      return it;
    }
  }
  return timeline_.end();
}

void FakeTrajectory::timeline_insert(TimelineConstIterator begin,
                                     TimelineConstIterator end) {
  CHECK(timeline_empty());
  timeline_.insert(timeline_.end(), begin, end);
}

bool FakeTrajectory::timeline_empty() const {
  return timeline_.empty();
}

class ForkableTest : public testing::Test {
 protected:
  ForkableTest() :
    t0_(),
    t1_(t0_ + 7 * Second),
    t2_(t0_ + 17 * Second),
    t3_(t0_ + 27 * Second),
    t4_(t0_ + 37 * Second) {}

  static std::vector<Instant> After(
      not_null<FakeTrajectory const*> const trajectory,
      Instant const& time) {
    std::vector<Instant> after;
    for (FakeTrajectory::Iterator it = trajectory->Find(time);
         it != trajectory->End();
         ++it) {
      after.push_back(*it.current());
    }
    return after;
  }

  static Instant const& LastTime(
      not_null<FakeTrajectory const*> const trajectory) {
    FakeTrajectory::Iterator it = trajectory->End();
    --it;
    return *it.current();
  }

  static std::vector<Instant> Times(
      not_null<FakeTrajectory const*> const trajectory) {
    std::vector<Instant> times;
    for (FakeTrajectory::Iterator it = trajectory->Begin();
         it != trajectory->End();
         ++it) {
      times.push_back(*it.current());
    }
    return times;
  }

  FakeTrajectory trajectory_;
  Instant t0_, t1_, t2_, t3_, t4_;
};

using ForkableDeathTest = ForkableTest;

TEST_F(ForkableDeathTest, ForkError) {
  EXPECT_DEATH({
    trajectory_.push_back(t1_);
    trajectory_.push_back(t3_);
    trajectory_.NewFork(t2_);
  }, "nonexistent time");
}

TEST_F(ForkableDeathTest, ForkSuccess) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);
  not_null<FakeTrajectory*> const fork = trajectory_.NewFork(t2_);
  fork->push_back(t4_);
  auto times = Times(&trajectory_);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));
  times = Times(fork);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_, t4_));
}

TEST_F(ForkableTest, ForkAtLast) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);
  not_null<FakeTrajectory*> const fork1 = trajectory_.NewFork(t3_);
  not_null<FakeTrajectory*> const fork2 = fork1->NewFork(LastTime(fork1));
  not_null<FakeTrajectory*> const fork3 = fork2->NewFork(LastTime(fork1));
  EXPECT_EQ(t3_, LastTime(&trajectory_));
  EXPECT_EQ(t3_, LastTime(fork1));

  auto times = Times(fork2);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));
  EXPECT_EQ(t3_, LastTime(fork2));
  EXPECT_EQ(t3_, *fork2->ForkTime());

  auto after = After(fork3, t3_);
  EXPECT_THAT(after, ElementsAre(t3_));

  after = After(fork2, t3_);
  EXPECT_THAT(after, ElementsAre(t3_));

  fork1->push_back(t4_);
  times = Times(fork2);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));

  after = After(fork1, t3_);
  EXPECT_THAT(after, ElementsAre(t3_, t4_));

  times = Times(fork3);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));

  fork2->push_back(t4_);
  after = After(fork2, t3_);
  EXPECT_THAT(after, ElementsAre(t3_, t4_));

  fork3->push_back(t4_);
  after = After(fork3, t3_);
  EXPECT_THAT(after, ElementsAre(t3_, t4_));

  after = After(fork3, t2_);
  EXPECT_THAT(after, ElementsAre(t2_, t3_, t4_));
}

TEST_F(ForkableDeathTest, DeleteForkError) {
  EXPECT_DEATH({
    trajectory_.push_back(t1_);
    FakeTrajectory* root = &trajectory_;
    trajectory_.DeleteFork(&root);
  }, "'fork_time'.* non NULL");
  EXPECT_DEATH({
    trajectory_.push_back(t1_);
    FakeTrajectory* fork1 = trajectory_.NewFork(t1_);
    fork1->push_back(t2_);
    FakeTrajectory* fork2 = fork1->NewFork(t2_);
    trajectory_.DeleteFork(&fork2);
  }, "not a child");
}

TEST_F(ForkableTest, DeleteForkSuccess) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);
  not_null<FakeTrajectory*> const fork1 = trajectory_.NewFork(t2_);
  FakeTrajectory* fork2 = trajectory_.NewFork(t2_);
  fork1->push_back(t4_);
  trajectory_.DeleteFork(&fork2);
  EXPECT_EQ(nullptr, fork2);
  auto times = Times(&trajectory_);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_));
  times = Times(fork1);
  EXPECT_THAT(times, ElementsAre(t1_, t2_, t3_, t4_));
}

TEST_F(ForkableDeathTest, IteratorDecrementError) {
  EXPECT_DEATH({
    auto it = trajectory_.End();
    --it;
  }, "parent_.*non NULL");
}

TEST_F(ForkableTest, IteratorDecrementNoForkSuccess) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);
  auto it = trajectory_.End();
  --it;
  EXPECT_EQ(t3_, *it.current());
  --it;
  EXPECT_EQ(t2_, *it.current());
  --it;
  EXPECT_EQ(t1_, *it.current());
}

TEST_F(ForkableTest, IteratorDecrementForkSuccess) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  auto fork = trajectory_.NewFork(t1_);
  trajectory_.push_back(t4_);
  fork->push_back(t3_);
  auto it = fork->End();
  --it;
  EXPECT_EQ(t3_, *it.current());
  --it;
  EXPECT_EQ(t2_, *it.current());
  --it;
  EXPECT_EQ(t1_, *it.current());
}

TEST_F(ForkableTest, Root) {
  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);
  not_null<FakeTrajectory*> const fork = trajectory_.NewFork(t2_);
  EXPECT_TRUE(trajectory_.is_root());
  EXPECT_FALSE(fork->is_root());
  EXPECT_EQ(&trajectory_, trajectory_.root());
  EXPECT_EQ(&trajectory_, fork->root());
  EXPECT_EQ(nullptr, trajectory_.ForkTime());
  EXPECT_EQ(t2_, *fork->ForkTime());
}

TEST_F(ForkableTest, IteratorBeginSuccess) {
  auto it = trajectory_.Begin();
  EXPECT_EQ(it, trajectory_.End());

  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);

  it = trajectory_.Begin();
  EXPECT_NE(it, trajectory_.End());
  EXPECT_EQ(t1_, *it.current());
  ++it;
  EXPECT_EQ(t2_, *it.current());
  ++it;
  EXPECT_EQ(t3_, *it.current());
  ++it;
  EXPECT_EQ(it, trajectory_.End());

  not_null<FakeTrajectory*> const fork = trajectory_.NewFork(t2_);
  fork->push_back(t4_);

  it = fork->Begin();
  EXPECT_NE(it, trajectory_.End());
  EXPECT_EQ(t1_, *it.current());
  ++it;
  EXPECT_EQ(t2_, *it.current());
  ++it;
  EXPECT_EQ(t3_, *it.current());
  ++it;
  EXPECT_EQ(t4_, *it.current());
  ++it;
  EXPECT_EQ(it, trajectory_.End());
}

TEST_F(ForkableTest, IteratorFindSuccess) {
  auto it = trajectory_.Find(t0_);
  EXPECT_EQ(it, trajectory_.End());

  trajectory_.push_back(t1_);
  trajectory_.push_back(t2_);
  trajectory_.push_back(t3_);

  it = trajectory_.Find(t1_);
  EXPECT_NE(it, trajectory_.End());
  EXPECT_EQ(t1_, *it.current());
  it = trajectory_.Find(t2_);
  EXPECT_EQ(t2_, *it.current());
  it = trajectory_.Find(t4_);
  EXPECT_EQ(it, trajectory_.End());

  not_null<FakeTrajectory*> const fork = trajectory_.NewFork(t2_);
  fork->push_back(t4_);

  it = fork->Find(t1_);
  EXPECT_NE(it, trajectory_.End());
  EXPECT_EQ(t1_, *it.current());
  it = fork->Find(t2_);
  EXPECT_EQ(t2_, *it.current());
  it = fork->Find(t4_);
  EXPECT_EQ(t4_, *it.current());
  it = fork->Find(t4_ + 1 * Second);
  EXPECT_EQ(it, trajectory_.End());
}

}  // namespace physics
}  // namespace principia
<|endoftext|>


<commit_before>#include "ImageLoader.h"
#include "AssetManager.h"
#include "texture/texture.h"
#include "utility.h"
#include <map>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

namespace aten {
	static std::string g_base;

	void ImageLoader::setBasePath(const std::string& base)
	{
		g_base = removeTailPathSeparator(base);
	}

	texture* ImageLoader::load(const std::string& path)
	{
		std::string pathname;
		std::string extname;
		std::string filename;

		getStringsFromPath(
			path,
			pathname,
			extname,
			filename);

		auto tex = load(filename, path);

		return tex;
	}

	template <typename TYPE>
	static void read(
		TYPE* src,
		texture* tex,
		int width,
		int height,
		int channel,
		real norm)
	{
		int skipChannel = channel;
		channel = (channel > 3 ? 3 : channel);

#pragma omp parallel for
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				int idx = y * width + x;
				idx *= skipChannel;

				switch (channel) {
				case 3:
					(*tex)(x, y, 2) = src[idx + 2] * norm;
				case 2:
					(*tex)(x, y, 1) = src[idx + 1] * norm;
				case 1:
					(*tex)(x, y, 0) = src[idx + 0] * norm;
					break;
				}
			}
		}
	}

	texture* ImageLoader::load(const std::string& tag, const std::string& path)
	{
		std::string fullpath = path;
		if (!g_base.empty()) {
			fullpath = g_base + "/" + fullpath;
		}

		texture* tex = AssetManager::getTex(tag);

		if (tex) {
			AT_PRINTF("There is same tag texture. [%s]\n", tag.c_str());
			return tex;
		}

		real* dst = nullptr;
		int width = 0;
		int height = 0;
		int channels = 0;

		if (stbi_is_hdr(fullpath.c_str())) {
			auto src = stbi_loadf(fullpath.c_str(), &width, &height, &channels, 0);
			if (src) {
				tex = new texture(width, height, std::min(channels, 3), path.c_str());
				real norm = real(1);
				read<float>(src, tex, width, height, channels, norm);

				STBI_FREE(src);
			}
		}
		else {
			auto src = stbi_load(fullpath.c_str(), &width, &height, &channels, 0);
			if (src) {
				tex = new texture(width, height, std::min(channels, 3), path.c_str());
				real norm = real(1) / real(255);

				read<stbi_uc>(src, tex, width, height, channels, norm);

				STBI_FREE(src);
			}
		}

		if (tex) {
			AssetManager::registerTex(tag, tex);
		}
		else {
			AT_ASSERT(false);
			AT_PRINTF("Failed load texture. [%s]\n", fullpath.c_str());
			return nullptr;
		}

		return tex;
	}
}<commit_msg>It is enabled to load texture which has alpha.<commit_after>#include "ImageLoader.h"
#include "AssetManager.h"
#include "texture/texture.h"
#include "utility.h"
#include <map>

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

namespace aten {
	static std::string g_base;

	void ImageLoader::setBasePath(const std::string& base)
	{
		g_base = removeTailPathSeparator(base);
	}

	texture* ImageLoader::load(const std::string& path)
	{
		std::string pathname;
		std::string extname;
		std::string filename;

		getStringsFromPath(
			path,
			pathname,
			extname,
			filename);

		auto tex = load(filename, path);

		return tex;
	}

	template <typename TYPE>
	static void read(
		TYPE* src,
		texture* tex,
		int width,
		int height,
		int channel,
		real norm)
	{
		int skipChannel = channel;

#pragma omp parallel for
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++) {
				int idx = y * width + x;
				idx *= skipChannel;

				switch (channel) {
				case 4:
					(*tex)(x, y, 3) = src[idx + 3] * norm;
				case 3:
					(*tex)(x, y, 2) = src[idx + 2] * norm;
				case 2:
					(*tex)(x, y, 1) = src[idx + 1] * norm;
				case 1:
					(*tex)(x, y, 0) = src[idx + 0] * norm;
					break;
				}
			}
		}
	}

	texture* ImageLoader::load(const std::string& tag, const std::string& path)
	{
		std::string fullpath = path;
		if (!g_base.empty()) {
			fullpath = g_base + "/" + fullpath;
		}

		texture* tex = AssetManager::getTex(tag);

		if (tex) {
			AT_PRINTF("There is same tag texture. [%s]\n", tag.c_str());
			return tex;
		}

		real* dst = nullptr;
		int width = 0;
		int height = 0;
		int channels = 0;

		if (stbi_is_hdr(fullpath.c_str())) {
			auto src = stbi_loadf(fullpath.c_str(), &width, &height, &channels, 0);
			if (src) {
				tex = new texture(width, height, channels, path.c_str());
				real norm = real(1);
				read<float>(src, tex, width, height, channels, norm);

				STBI_FREE(src);
			}
		}
		else {
			auto src = stbi_load(fullpath.c_str(), &width, &height, &channels, 0);
			if (src) {
				tex = new texture(width, height, channels, path.c_str());
				real norm = real(1) / real(255);

				read<stbi_uc>(src, tex, width, height, channels, norm);

				STBI_FREE(src);
			}
		}

		if (tex) {
			AssetManager::registerTex(tag, tex);
		}
		else {
			AT_ASSERT(false);
			AT_PRINTF("Failed load texture. [%s]\n", fullpath.c_str());
			return nullptr;
		}

		return tex;
	}
}<|endoftext|>