<commit_before>#include <QtGui>
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QButtonGroup>
#include <QDesktopServices>

#include "seafile-applet.h"
#include "account-mgr.h"
#include "utils/utils.h"
#include "utils/paint-utils.h"
#include "utils/file-utils.h"
#include "api/api-error.h"
#include "file-table.h"
#include "seaf-dirent.h"
#include "ui/loading-view.h"
#include "data-mgr.h"
#include "data-mgr.h"
#include "progress-dialog.h"
#include "tasks.h"
#include "ui/set-repo-password-dialog.h"

#include "file-browser-dialog.h"

namespace {

enum {
    INDEX_LOADING_VIEW = 0,
    INDEX_TABLE_VIEW,
    INDEX_LOADING_FAILED_VIEW
};

const char *kLoadingFaieldLabelName = "loadingFailedText";
const int kToolBarIconSize = 20;
const int kStatusBarIconSize = 24;
const int kStatusCodePasswordNeeded = 400;

} // namespace

FileBrowserDialog::FileBrowserDialog(const ServerRepo& repo, QWidget *parent)
    : QDialog(parent),
      repo_(repo)
{
    current_path_ = "/";
    // since root is special, the next step is unnecessary
    // current_lpath_.push_back("");

    const Account& account = seafApplet->accountManager()->currentAccount();
    data_mgr_ = new DataManager(account);

    setWindowTitle(tr("Cloud File Browser"));
    setWindowIcon(QIcon(":/images/seafile.png"));
    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

    createToolBar();
    createStatusBar();
    createLoadingFailedView();
    createFileTable();

    QVBoxLayout *vlayout = new QVBoxLayout;
    vlayout->setContentsMargins(0, 6, 0, 0);
    vlayout->setSpacing(0);
    setLayout(vlayout);

    stack_ = new QStackedWidget;
    stack_->insertWidget(INDEX_LOADING_VIEW, loading_view_);
    stack_->insertWidget(INDEX_TABLE_VIEW, table_view_);
    stack_->insertWidget(INDEX_LOADING_FAILED_VIEW, loading_failed_view_);

    vlayout->addWidget(toolbar_);
    vlayout->addWidget(stack_);
    vlayout->addWidget(status_bar_);

    connect(table_view_, SIGNAL(direntClicked(const SeafDirent&)),
            this, SLOT(onDirentClicked(const SeafDirent&)));

    connect(data_mgr_, SIGNAL(getDirentsSuccess(const QList<SeafDirent>&)),
            this, SLOT(onGetDirentsSuccess(const QList<SeafDirent>&)));
    connect(data_mgr_, SIGNAL(getDirentsFailed(const ApiError&)),
            this, SLOT(onGetDirentsFailed(const ApiError&)));

    QTimer::singleShot(0, this, SLOT(fetchDirents()));
}

FileBrowserDialog::~FileBrowserDialog()
{
    delete data_mgr_;
}

void FileBrowserDialog::createToolBar()
{
    toolbar_ = new QToolBar;

    const int w = ::getDPIScaledSize(kToolBarIconSize);
    toolbar_->setIconSize(QSize(w, w));

    toolbar_->setObjectName("topBar");
    toolbar_->setIconSize(QSize(w, w));

    backward_action_ = new QAction(tr("Back"), this);
    backward_action_->setIcon(getIconSet(":images/filebrowser/backward.png", kToolBarIconSize, kToolBarIconSize));
    backward_action_->setEnabled(false);
    toolbar_->addAction(backward_action_);
    connect(backward_action_, SIGNAL(triggered()), this, SLOT(goBackward()));

    forward_action_ = new QAction(tr("Forward"), this);
    forward_action_->setIcon(getIconSet(":images/filebrowser/forward.png", kToolBarIconSize, kToolBarIconSize));
    forward_action_->setEnabled(false);
    connect(forward_action_, SIGNAL(triggered()), this, SLOT(goForward()));
    toolbar_->addAction(forward_action_);

    gohome_action_ = new QAction(tr("Home"), this);
    gohome_action_->setIcon(getIconSet(":images/filebrowser/home.png", kToolBarIconSize, kToolBarIconSize));
    connect(gohome_action_, SIGNAL(triggered()), this, SLOT(goHome()));
    // toolbar_->addAction(gohome_action_);

    path_navigator_ = new QButtonGroup(this);
    connect(path_navigator_, SIGNAL(buttonClicked(int)),
            this, SLOT(onNavigatorClick(int)));

    // root is special
    QPushButton *path_navigator_root_ = new QPushButton(repo_.name);
    path_navigator_root_->setFlat(true);
    path_navigator_root_->setCursor(Qt::PointingHandCursor);
    connect(path_navigator_root_, SIGNAL(clicked()),
            this, SLOT(goHome()));
    toolbar_->addWidget(path_navigator_root_);
}

void FileBrowserDialog::createStatusBar()
{
    status_bar_ = new QToolBar;

    const int w = ::getDPIScaledSize(kStatusBarIconSize);
    status_bar_->setObjectName("statusBar");
    status_bar_->setIconSize(QSize(w, w));

    QWidget *spacer1 = new QWidget;
    spacer1->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
    status_bar_->addWidget(spacer1);

    upload_action_ = new QAction(this);
    upload_action_->setIcon(
        getIconSet(":images/filebrowser/upload.png", kStatusBarIconSize, kStatusBarIconSize));
    connect(upload_action_, SIGNAL(triggered()), this, SLOT(chooseFileToUpload()));
    status_bar_->addAction(upload_action_);
    if (repo_.readonly) {
        upload_action_->setEnabled(false);
        upload_action_->setToolTip(tr("You don't have permission to upload files to this library"));
    }

    details_label_ = new QLabel;
    details_label_->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
    details_label_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    details_label_->setFixedHeight(w);
    status_bar_->addWidget(details_label_);

    refresh_action_ = new QAction(this);
    refresh_action_->setIcon(
        getIconSet(":images/filebrowser/refresh.png", kStatusBarIconSize, kStatusBarIconSize));
    connect(refresh_action_, SIGNAL(triggered()), this, SLOT(forceRefresh()));
    status_bar_->addAction(refresh_action_);

    open_cache_dir_action_ = new QAction(this);
    open_cache_dir_action_->setIcon(
        getIconSet(":/images/filebrowser/open-folder.png", kStatusBarIconSize, kStatusBarIconSize));
    connect(open_cache_dir_action_, SIGNAL(triggered()), this, SLOT(openCacheFolder()));
    status_bar_->addAction(open_cache_dir_action_);

    QWidget *spacer2 = new QWidget;
    spacer2->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
    status_bar_->addWidget(spacer2);
}

void FileBrowserDialog::createFileTable()
{
    loading_view_ = new LoadingView;
    table_view_ = new FileTableView(repo_);
    table_model_ = new FileTableModel();
    table_view_->setModel(table_model_);

    connect(table_view_, SIGNAL(dropFile(const QString&)),
            this, SLOT(uploadFile(const QString&)));
}

void FileBrowserDialog::forceRefresh()
{
    fetchDirents(true);
}

void FileBrowserDialog::fetchDirents()
{
    fetchDirents(false);
}

void FileBrowserDialog::fetchDirents(bool force_refresh)
{
    if (repo_.encrypted && !data_mgr_->isRepoPasswordSet(repo_.id)) {
        SetRepoPasswordDialog password_dialog(repo_, this);
        if (password_dialog.exec() != QDialog::Accepted) {
            reject();
            return;
        } else {
            data_mgr_->setRepoPasswordSet(repo_.id);
        }
    }

    if (!force_refresh) {
        QList<SeafDirent> dirents;
        if (data_mgr_->getDirents(repo_.id, current_path_, &dirents)) {
            updateTable(dirents);
            return;
        }
    }

    showLoading();
    data_mgr_->getDirentsFromServer(repo_.id, current_path_);
}

void FileBrowserDialog::onGetDirentsSuccess(const QList<SeafDirent>& dirents)
{
    updateTable(dirents);
}

void FileBrowserDialog::onGetDirentsFailed(const ApiError& error)
{
    stack_->setCurrentIndex(INDEX_LOADING_FAILED_VIEW);
}

void FileBrowserDialog::createLoadingFailedView()
{
    loading_failed_view_ = new QWidget(this);

    QVBoxLayout *layout = new QVBoxLayout;
    loading_failed_view_->setLayout(layout);

    QLabel *label = new QLabel;
    label->setObjectName(kLoadingFaieldLabelName);
    QString link = QString("%1").arg(tr("retry"));
    QString label_text = tr("Failed to get files information
"
                            "Please %1").arg(link);
    label->setText(label_text);
    label->setAlignment(Qt::AlignCenter);

    connect(label, SIGNAL(linkActivated(const QString&)),
            this, SLOT(fetchDirents()));

    layout->addWidget(label);
}

void FileBrowserDialog::onDirentClicked(const SeafDirent& dirent)
{
    if (dirent.isDir()) {
        onDirClicked(dirent);
    } else {
        onFileClicked(dirent);
    }
}

void FileBrowserDialog::showLoading()
{
    forward_action_->setEnabled(false);
    backward_action_->setEnabled(false);
    upload_action_->setEnabled(false);
    gohome_action_->setEnabled(false);
    stack_->setCurrentIndex(INDEX_LOADING_VIEW);
}

void FileBrowserDialog::onDirClicked(const SeafDirent& dir)
{
    const QString& path = ::pathJoin(current_path_, dir.name);
    backward_history_.push(current_path_);
    forward_history_.clear();
    enterPath(path);
}

void FileBrowserDialog::enterPath(const QString& path)
{
    current_path_ = path;
    // use QUrl::toPercentEncoding if need
    fetchDirents();

    // current_path should be guaranteed safe to split!
    current_lpath_ = current_path_.split('/');
    // if the last element is empty (i.e. current_path_ ends with an extra "/"),
    // remove it
    if(current_lpath_.last().isEmpty())
        current_lpath_.pop_back();

    // remove all old buttons for navigator except the root
    QList<QAbstractButton *> buttons = path_navigator_->buttons();
    foreach(QAbstractButton *button, buttons)
    {
        path_navigator_->removeButton(button);
        delete button;
    }
    foreach(QLabel *label, path_navigator_separators_)
    {
        delete label;
    }
    path_navigator_separators_.clear();

    // add new buttons for navigator except the root
    for(int i = 1; i < current_lpath_.size(); i++) {
        QLabel *separator = new QLabel("/");
        path_navigator_separators_.push_back(separator);
        toolbar_->addWidget(separator);
        QPushButton* button = new QPushButton(current_lpath_[i]);
        button->setFlat(true);
        button->setCursor(Qt::PointingHandCursor);
        path_navigator_->addButton(button, i);
        toolbar_->addWidget(button);
    }
}

void FileBrowserDialog::onFileClicked(const SeafDirent& file)
{
    QString fpath = ::pathJoin(current_path_, file.name);

    QString cached_file = data_mgr_->getLocalCachedFile(repo_.id, fpath, file.id);
    if (!cached_file.isEmpty()) {
        openFile(cached_file);
        return;
    } else {
        downloadFile(fpath);
    }
}

void FileBrowserDialog::downloadFile(const QString& path)
{
    FileDownloadTask *task = data_mgr_->createDownloadTask(repo_.id, path);
    FileBrowserProgressDialog dialog(task, this);
    connect(task, SIGNAL(finished(bool)),
            this, SLOT(onDownloadFinished(bool)));
    task->start();
    dialog.exec();
}

void FileBrowserDialog::uploadFile(const QString& path)
{
    FileUploadTask *task = data_mgr_->createUploadTask(repo_.id, current_path_, path);
    FileBrowserProgressDialog dialog(task, this);
    connect(task, SIGNAL(finished(bool)),
            this, SLOT(onUploadFinished(bool)));
    task->start();
    dialog.exec();
}

void FileBrowserDialog::onDownloadFinished(bool success)
{
    FileNetworkTask *task = (FileNetworkTask *)sender();
    if (success) {
        openFile(task->localFilePath());
    } else {
        if (repo_.encrypted &&
            setPasswordAndRetry(task, &FileBrowserDialog::downloadFile)) {
            return;
        }

        QString msg = tr("Failed to download file: %1").arg(task->errorString());
        seafApplet->warningBox(msg, this);
    }
}

void FileBrowserDialog::onUploadFinished(bool success)
{
    FileNetworkTask *task = (FileNetworkTask *)sender();
    if (success) {
        forceRefresh();
    } else {
        if (repo_.encrypted &&
            setPasswordAndRetry(task, &FileBrowserDialog::uploadFile)) {
            return;
        }
        QString msg = tr("Failed to upload file: %1").arg(task->errorString());
        seafApplet->warningBox(msg, this);
    }
}

bool FileBrowserDialog::setPasswordAndRetry(FileNetworkTask *task,
                                            void (FileBrowserDialog::*func)(const QString&))
{
    if (task->httpErrorCode() == 400) {
        SetRepoPasswordDialog password_dialog(repo_, this);
        if (password_dialog.exec() == QDialog::Accepted) {
            (this->*func)(task->path());
            return true;
        }
    }

    return false;
}

void FileBrowserDialog::openFile(const QString& path)
{
    ::openInNativeExtension(path) || ::showInGraphicalShell(path);
}

void FileBrowserDialog::goForward()
{
    QString path = forward_history_.pop();
    backward_history_.push(current_path_);
    enterPath(path);
}

void FileBrowserDialog::goBackward()
{
    QString path = backward_history_.pop();
    forward_history_.push(current_path_);
    enterPath(path);
}

void FileBrowserDialog::goHome()
{
    if (current_path_ == "/") {
        return;
    }
    QString path = "/";
    backward_history_.push(current_path_);
    enterPath(path);
}

void FileBrowserDialog::updateTable(const QList<SeafDirent>& dirents)
{
    table_model_->setDirents(dirents);
    stack_->setCurrentIndex(INDEX_TABLE_VIEW);
    if (!forward_history_.empty()) {
        forward_action_->setEnabled(true);
    } else {
        forward_action_->setEnabled(false);
    }
    if (!backward_history_.empty()) {
        backward_action_->setEnabled(true);
    } else {
        backward_action_->setEnabled(false);
    }
    if (!repo_.readonly) {
        upload_action_->setEnabled(true);
    }
    gohome_action_->setEnabled(true);
}

void FileBrowserDialog::chooseFileToUpload()
{
    QString path = QFileDialog::getOpenFileName(this, tr("Select a file to upload"));
    if (!path.isEmpty()) {
        uploadFile(path);
    }
}

void FileBrowserDialog::openCacheFolder()
{
    QString folder = data_mgr_->getRepoCacheFolder(repo_.id);
    ::createDirIfNotExists(folder);
    QDesktopServices::openUrl(QUrl::fromLocalFile(folder));
}

void FileBrowserDialog::onNavigatorClick(int id)
{
    // root is safe, since it is handled by goHome not this function
    // i.e. id is never equal to 0

    // calculate the path
    QString path = "/";
    for(int i = 1; i <= id; i++)
      path += current_lpath_[i] + "/";

    enterPath(path);
}

<commit_msg>correct some typos<commit_after>#include <QtGui>
#include <QVBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QButtonGroup>
#include <QDesktopServices>

#include "seafile-applet.h"
#include "account-mgr.h"
#include "utils/utils.h"
#include "utils/paint-utils.h"
#include "utils/file-utils.h"
#include "api/api-error.h"
#include "file-table.h"
#include "seaf-dirent.h"
#include "ui/loading-view.h"
#include "data-mgr.h"
#include "data-mgr.h"
#include "progress-dialog.h"
#include "tasks.h"
#include "ui/set-repo-password-dialog.h"

#include "file-browser-dialog.h"

namespace {

enum {
    INDEX_LOADING_VIEW = 0,
    INDEX_TABLE_VIEW,
    INDEX_LOADING_FAILED_VIEW
};

const char *kLoadingFaieldLabelName = "loadingFailedText";
const int kToolBarIconSize = 20;
const int kStatusBarIconSize = 24;
const int kStatusCodePasswordNeeded = 400;

} // namespace

FileBrowserDialog::FileBrowserDialog(const ServerRepo& repo, QWidget *parent)
    : QDialog(parent),
      repo_(repo)
{
    current_path_ = "/";
    // since root is special, the next step is unnecessary
    // current_lpath_.push_back("");

    const Account& account = seafApplet->accountManager()->currentAccount();
    data_mgr_ = new DataManager(account);

    setWindowTitle(tr("Cloud File Browser"));
    setWindowIcon(QIcon(":/images/seafile.png"));
    setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

    createToolBar();
    createStatusBar();
    createLoadingFailedView();
    createFileTable();

    QVBoxLayout *vlayout = new QVBoxLayout;
    vlayout->setContentsMargins(0, 6, 0, 0);
    vlayout->setSpacing(0);
    setLayout(vlayout);

    stack_ = new QStackedWidget;
    stack_->insertWidget(INDEX_LOADING_VIEW, loading_view_);
    stack_->insertWidget(INDEX_TABLE_VIEW, table_view_);
    stack_->insertWidget(INDEX_LOADING_FAILED_VIEW, loading_failed_view_);

    vlayout->addWidget(toolbar_);
    vlayout->addWidget(stack_);
    vlayout->addWidget(status_bar_);

    connect(table_view_, SIGNAL(direntClicked(const SeafDirent&)),
            this, SLOT(onDirentClicked(const SeafDirent&)));

    connect(data_mgr_, SIGNAL(getDirentsSuccess(const QList<SeafDirent>&)),
            this, SLOT(onGetDirentsSuccess(const QList<SeafDirent>&)));
    connect(data_mgr_, SIGNAL(getDirentsFailed(const ApiError&)),
            this, SLOT(onGetDirentsFailed(const ApiError&)));

    QTimer::singleShot(0, this, SLOT(fetchDirents()));
}

FileBrowserDialog::~FileBrowserDialog()
{
    delete data_mgr_;
}

void FileBrowserDialog::createToolBar()
{
    toolbar_ = new QToolBar;

    const int w = ::getDPIScaledSize(kToolBarIconSize);
    toolbar_->setIconSize(QSize(w, w));

    toolbar_->setObjectName("topBar");
    toolbar_->setIconSize(QSize(w, w));

    backward_action_ = new QAction(tr("Back"), this);
    backward_action_->setIcon(getIconSet(":/images/filebrowser/backward.png", kToolBarIconSize, kToolBarIconSize));
    backward_action_->setEnabled(false);
    toolbar_->addAction(backward_action_);
    connect(backward_action_, SIGNAL(triggered()), this, SLOT(goBackward()));

    forward_action_ = new QAction(tr("Forward"), this);
    forward_action_->setIcon(getIconSet(":/images/filebrowser/forward.png", kToolBarIconSize, kToolBarIconSize));
    forward_action_->setEnabled(false);
    connect(forward_action_, SIGNAL(triggered()), this, SLOT(goForward()));
    toolbar_->addAction(forward_action_);

    gohome_action_ = new QAction(tr("Home"), this);
    gohome_action_->setIcon(getIconSet(":images/filebrowser/home.png", kToolBarIconSize, kToolBarIconSize));
    connect(gohome_action_, SIGNAL(triggered()), this, SLOT(goHome()));
    // toolbar_->addAction(gohome_action_);

    path_navigator_ = new QButtonGroup(this);
    connect(path_navigator_, SIGNAL(buttonClicked(int)),
            this, SLOT(onNavigatorClick(int)));

    // root is special
    QPushButton *path_navigator_root_ = new QPushButton(repo_.name);
    path_navigator_root_->setFlat(true);
    path_navigator_root_->setCursor(Qt::PointingHandCursor);
    connect(path_navigator_root_, SIGNAL(clicked()),
            this, SLOT(goHome()));
    toolbar_->addWidget(path_navigator_root_);
}

void FileBrowserDialog::createStatusBar()
{
    status_bar_ = new QToolBar;

    const int w = ::getDPIScaledSize(kStatusBarIconSize);
    status_bar_->setObjectName("statusBar");
    status_bar_->setIconSize(QSize(w, w));

    QWidget *spacer1 = new QWidget;
    spacer1->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
    status_bar_->addWidget(spacer1);

    upload_action_ = new QAction(this);
    upload_action_->setIcon(
        getIconSet(":/images/filebrowser/upload.png", kStatusBarIconSize, kStatusBarIconSize));
    connect(upload_action_, SIGNAL(triggered()), this, SLOT(chooseFileToUpload()));
    status_bar_->addAction(upload_action_);
    if (repo_.readonly) {
        upload_action_->setEnabled(false);
        upload_action_->setToolTip(tr("You don't have permission to upload files to this library"));
    }

    details_label_ = new QLabel;
    details_label_->setAlignment(Qt::AlignCenter | Qt::AlignVCenter);
    details_label_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    details_label_->setFixedHeight(w);
    status_bar_->addWidget(details_label_);

    refresh_action_ = new QAction(this);
    refresh_action_->setIcon(
        getIconSet(":/images/filebrowser/refresh.png", kStatusBarIconSize, kStatusBarIconSize));
    connect(refresh_action_, SIGNAL(triggered()), this, SLOT(forceRefresh()));
    status_bar_->addAction(refresh_action_);

    open_cache_dir_action_ = new QAction(this);
    open_cache_dir_action_->setIcon(
        getIconSet(":/images/filebrowser/open-folder.png", kStatusBarIconSize, kStatusBarIconSize));
    connect(open_cache_dir_action_, SIGNAL(triggered()), this, SLOT(openCacheFolder()));
    status_bar_->addAction(open_cache_dir_action_);

    QWidget *spacer2 = new QWidget;
    spacer2->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
    status_bar_->addWidget(spacer2);
}

void FileBrowserDialog::createFileTable()
{
    loading_view_ = new LoadingView;
    table_view_ = new FileTableView(repo_);
    table_model_ = new FileTableModel();
    table_view_->setModel(table_model_);

    connect(table_view_, SIGNAL(dropFile(const QString&)),
            this, SLOT(uploadFile(const QString&)));
}

void FileBrowserDialog::forceRefresh()
{
    fetchDirents(true);
}

void FileBrowserDialog::fetchDirents()
{
    fetchDirents(false);
}

void FileBrowserDialog::fetchDirents(bool force_refresh)
{
    if (repo_.encrypted && !data_mgr_->isRepoPasswordSet(repo_.id)) {
        SetRepoPasswordDialog password_dialog(repo_, this);
        if (password_dialog.exec() != QDialog::Accepted) {
            reject();
            return;
        } else {
            data_mgr_->setRepoPasswordSet(repo_.id);
        }
    }

    if (!force_refresh) {
        QList<SeafDirent> dirents;
        if (data_mgr_->getDirents(repo_.id, current_path_, &dirents)) {
            updateTable(dirents);
            return;
        }
    }

    showLoading();
    data_mgr_->getDirentsFromServer(repo_.id, current_path_);
}

void FileBrowserDialog::onGetDirentsSuccess(const QList<SeafDirent>& dirents)
{
    updateTable(dirents);
}

void FileBrowserDialog::onGetDirentsFailed(const ApiError& error)
{
    stack_->setCurrentIndex(INDEX_LOADING_FAILED_VIEW);
}

void FileBrowserDialog::createLoadingFailedView()
{
    loading_failed_view_ = new QWidget(this);

    QVBoxLayout *layout = new QVBoxLayout;
    loading_failed_view_->setLayout(layout);

    QLabel *label = new QLabel;
    label->setObjectName(kLoadingFaieldLabelName);
    QString link = QString("%1").arg(tr("retry"));
    QString label_text = tr("Failed to get files information
"
                            "Please %1").arg(link);
    label->setText(label_text);
    label->setAlignment(Qt::AlignCenter);

    connect(label, SIGNAL(linkActivated(const QString&)),
            this, SLOT(fetchDirents()));

    layout->addWidget(label);
}

void FileBrowserDialog::onDirentClicked(const SeafDirent& dirent)
{
    if (dirent.isDir()) {
        onDirClicked(dirent);
    } else {
        onFileClicked(dirent);
    }
}

void FileBrowserDialog::showLoading()
{
    forward_action_->setEnabled(false);
    backward_action_->setEnabled(false);
    upload_action_->setEnabled(false);
    gohome_action_->setEnabled(false);
    stack_->setCurrentIndex(INDEX_LOADING_VIEW);
}

void FileBrowserDialog::onDirClicked(const SeafDirent& dir)
{
    const QString& path = ::pathJoin(current_path_, dir.name);
    backward_history_.push(current_path_);
    forward_history_.clear();
    enterPath(path);
}

void FileBrowserDialog::enterPath(const QString& path)
{
    current_path_ = path;
    // use QUrl::toPercentEncoding if need
    fetchDirents();

    // current_path should be guaranteed safe to split!
    current_lpath_ = current_path_.split('/');
    // if the last element is empty (i.e. current_path_ ends with an extra "/"),
    // remove it
    if(current_lpath_.last().isEmpty())
        current_lpath_.pop_back();

    // remove all old buttons for navigator except the root
    QList<QAbstractButton *> buttons = path_navigator_->buttons();
    foreach(QAbstractButton *button, buttons)
    {
        path_navigator_->removeButton(button);
        delete button;
    }
    foreach(QLabel *label, path_navigator_separators_)
    {
        delete label;
    }
    path_navigator_separators_.clear();

    // add new buttons for navigator except the root
    for(int i = 1; i < current_lpath_.size(); i++) {
        QLabel *separator = new QLabel("/");
        path_navigator_separators_.push_back(separator);
        toolbar_->addWidget(separator);
        QPushButton* button = new QPushButton(current_lpath_[i]);
        button->setFlat(true);
        button->setCursor(Qt::PointingHandCursor);
        path_navigator_->addButton(button, i);
        toolbar_->addWidget(button);
    }
}

void FileBrowserDialog::onFileClicked(const SeafDirent& file)
{
    QString fpath = ::pathJoin(current_path_, file.name);

    QString cached_file = data_mgr_->getLocalCachedFile(repo_.id, fpath, file.id);
    if (!cached_file.isEmpty()) {
        openFile(cached_file);
        return;
    } else {
        downloadFile(fpath);
    }
}

void FileBrowserDialog::downloadFile(const QString& path)
{
    FileDownloadTask *task = data_mgr_->createDownloadTask(repo_.id, path);
    FileBrowserProgressDialog dialog(task, this);
    connect(task, SIGNAL(finished(bool)),
            this, SLOT(onDownloadFinished(bool)));
    task->start();
    dialog.exec();
}

void FileBrowserDialog::uploadFile(const QString& path)
{
    FileUploadTask *task = data_mgr_->createUploadTask(repo_.id, current_path_, path);
    FileBrowserProgressDialog dialog(task, this);
    connect(task, SIGNAL(finished(bool)),
            this, SLOT(onUploadFinished(bool)));
    task->start();
    dialog.exec();
}

void FileBrowserDialog::onDownloadFinished(bool success)
{
    FileNetworkTask *task = (FileNetworkTask *)sender();
    if (success) {
        openFile(task->localFilePath());
    } else {
        if (repo_.encrypted &&
            setPasswordAndRetry(task, &FileBrowserDialog::downloadFile)) {
            return;
        }

        QString msg = tr("Failed to download file: %1").arg(task->errorString());
        seafApplet->warningBox(msg, this);
    }
}

void FileBrowserDialog::onUploadFinished(bool success)
{
    FileNetworkTask *task = (FileNetworkTask *)sender();
    if (success) {
        forceRefresh();
    } else {
        if (repo_.encrypted &&
            setPasswordAndRetry(task, &FileBrowserDialog::uploadFile)) {
            return;
        }
        QString msg = tr("Failed to upload file: %1").arg(task->errorString());
        seafApplet->warningBox(msg, this);
    }
}

bool FileBrowserDialog::setPasswordAndRetry(FileNetworkTask *task,
                                            void (FileBrowserDialog::*func)(const QString&))
{
    if (task->httpErrorCode() == 400) {
        SetRepoPasswordDialog password_dialog(repo_, this);
        if (password_dialog.exec() == QDialog::Accepted) {
            (this->*func)(task->path());
            return true;
        }
    }

    return false;
}

void FileBrowserDialog::openFile(const QString& path)
{
    ::openInNativeExtension(path) || ::showInGraphicalShell(path);
}

void FileBrowserDialog::goForward()
{
    QString path = forward_history_.pop();
    backward_history_.push(current_path_);
    enterPath(path);
}

void FileBrowserDialog::goBackward()
{
    QString path = backward_history_.pop();
    forward_history_.push(current_path_);
    enterPath(path);
}

void FileBrowserDialog::goHome()
{
    if (current_path_ == "/") {
        return;
    }
    QString path = "/";
    backward_history_.push(current_path_);
    enterPath(path);
}

void FileBrowserDialog::updateTable(const QList<SeafDirent>& dirents)
{
    table_model_->setDirents(dirents);
    stack_->setCurrentIndex(INDEX_TABLE_VIEW);
    if (!forward_history_.empty()) {
        forward_action_->setEnabled(true);
    } else {
        forward_action_->setEnabled(false);
    }
    if (!backward_history_.empty()) {
        backward_action_->setEnabled(true);
    } else {
        backward_action_->setEnabled(false);
    }
    if (!repo_.readonly) {
        upload_action_->setEnabled(true);
    }
    gohome_action_->setEnabled(true);
}

void FileBrowserDialog::chooseFileToUpload()
{
    QString path = QFileDialog::getOpenFileName(this, tr("Select a file to upload"));
    if (!path.isEmpty()) {
        uploadFile(path);
    }
}

void FileBrowserDialog::openCacheFolder()
{
    QString folder = data_mgr_->getRepoCacheFolder(repo_.id);
    ::createDirIfNotExists(folder);
    QDesktopServices::openUrl(QUrl::fromLocalFile(folder));
}

void FileBrowserDialog::onNavigatorClick(int id)
{
    // root is safe, since it is handled by goHome not this function
    // i.e. id is never equal to 0

    // calculate the path
    QString path = "/";
    for(int i = 1; i <= id; i++)
      path += current_lpath_[i] + "/";

    enterPath(path);
}

<|endoftext|>


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

// VTK includes
#include <vtksys/CommandLineArguments.hxx>
#include <vtksys/SystemTools.hxx>
#include "vtkDoubleArray.h"
#include "vtkNew.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkXMLPolyDataReader.h"
#include "vtkXMLPolyDataWriter.h"

#include "Helper.h"
#include "ReconstructionData.h"

#include <iostream>
#include <string>
#include <numeric>

//-----------------------------------------------------------------------------
// READ ARGUMENTS
//-----------------------------------------------------------------------------
std::string g_inputPath = "";
std::string g_outputPath = "";
std::string g_globalKRTDFilePath = "";
std::string g_globalVTIFilePath = "";
bool verbose = false;

//-----------------------------------------------------------------------------
// FUNCTIONS
//-----------------------------------------------------------------------------
bool ReadArguments(int argc, char ** argv);
void ShowInformation(std::string message);
void ShowFilledParameters();

//-----------------------------------------------------------------------------
/* Main function */
int main(int argc, char ** argv)
{
  if (!ReadArguments(argc, argv))
  {
    return EXIT_FAILURE;
  }

  ShowInformation("** Read input...");
  vtkNew<vtkXMLPolyDataReader> reader;
  reader->SetFileName(g_inputPath.c_str());
  reader->Update();

  ShowInformation("** Extract vti and krtd file path...");
  std::vector<std::string> vtiList = help::ExtractAllFilePath(g_globalVTIFilePath.c_str());
  std::vector<std::string> krtdList = help::ExtractAllFilePath(g_globalKRTDFilePath.c_str());
  if (krtdList.size() < vtiList.size())
    {
    std::cerr << "Error, no enough krtd file for each vti file" << std::endl;
    return EXIT_FAILURE;
    }

  int nbDepthMap = (int)vtiList.size();

  ShowInformation("** Read krtd and vti...");
  std::vector<ReconstructionData*> dataList;
  for (int id = 0; id < nbDepthMap; id++)
    {
    std::cout << "\r" << id * 100 / nbDepthMap << " %" << std::flush;
    ReconstructionData* data = new ReconstructionData(vtiList[id], krtdList[id]);
    dataList.push_back(data);
    }

  std::cout << "\r" << "100 %" << std::flush << std::endl << std::endl;
  ShowInformation("** Process coloration...");
  vtkPolyData* mesh = reader->GetOutput();
  vtkPoints* meshPointList = mesh->GetPoints();
  vtkIdType nbMeshPoint = meshPointList->GetNumberOfPoints();
  //vtkIdType nbMeshPoint = 3;
  int* depthMapDimensions = dataList[0]->GetDepthMapDimensions();

  std::vector<int> pointCount(nbMeshPoint);
  // Contains rgb values
  vtkUnsignedCharArray* meanValues = vtkUnsignedCharArray::New();
  meanValues->SetNumberOfComponents(3);
  meanValues->SetNumberOfTuples(nbMeshPoint);
  meanValues->FillComponent(0, 0);
  meanValues->FillComponent(1, 0);
  meanValues->FillComponent(2, 0);
  meanValues->SetName("meanColoration");

  vtkUnsignedCharArray* medianValues = vtkUnsignedCharArray::New();
  medianValues->SetNumberOfComponents(3);
  medianValues->SetNumberOfTuples(nbMeshPoint);
  medianValues->FillComponent(0, 0);
  medianValues->FillComponent(1, 0);
  medianValues->FillComponent(2, 0);
  medianValues->SetName("medianColoration");

  vtkDoubleArray* projectedDMValue = vtkDoubleArray::New();
  projectedDMValue->SetNumberOfComponents(1);
  projectedDMValue->SetNumberOfTuples(nbMeshPoint);
  projectedDMValue->FillComponent(0, 0);
  projectedDMValue->SetName("NbProjectedDepthMap");

  // Store each rgb value for each depth map
  std::vector<double> list0;
  std::vector<double> list1;
  std::vector<double> list2;

  for (vtkIdType id = 0; id < nbMeshPoint; id++)
    {
    std::cout << "\r" << id * 100 / nbMeshPoint << " %" << std::flush;

    list0.reserve(nbDepthMap);
    list1.reserve(nbDepthMap);
    list2.reserve(nbDepthMap);

    // Get mesh position from id
    double position[3];
    meshPointList->GetPoint(id, position);

    for (int idData = 0; idData < nbDepthMap; idData++)
      {
      ReconstructionData* data = dataList[idData];

      // Transform to pixel index
      int pixelPosition[2];
      help::WorldToDepthMap(data->GetMatrixTR(), data->Get4MatrixK(), position, pixelPosition);
      // Test if pixel is inside depth map
      if (pixelPosition[0] < 0 || pixelPosition[1] < 0 ||
        pixelPosition[0] >= depthMapDimensions[0] ||
        pixelPosition[1] >= depthMapDimensions[1])
        {
        continue;
        }

      double color[3];
      data->GetColorValue(pixelPosition, color);

      list0.push_back(color[0]);
      list1.push_back(color[1]);
      list2.push_back(color[2]);
      }

    // If we get elements
    if (list0.size() != 0)
      {
      double sum0 = std::accumulate(list0.begin(), list0.end(), 0);
      double sum1 = std::accumulate(list1.begin(), list1.end(), 0);
      double sum2 = std::accumulate(list2.begin(), list2.end(), 0);
      double nbVal = (double)list0.size();
      meanValues->SetTuple3(id, sum0 / (double)nbVal, sum1 / (double)nbVal, sum2 / (double)nbVal);
      double median0, median1, median2;
      help::ComputeMedian<double>(list0, median0);
      help::ComputeMedian<double>(list1, median1);
      help::ComputeMedian<double>(list2, median2);
      medianValues->SetTuple3(id, median0, median1, median2);
      projectedDMValue->SetTuple1(id, list0.size());
      }

    list0.clear();
    list1.clear();
    list2.clear();
    }

  mesh->GetPointData()->AddArray(meanValues);
  mesh->GetPointData()->AddArray(medianValues);
  mesh->GetPointData()->AddArray(projectedDMValue);

  std::cout << "\r" << "100 %" << std::flush << std::endl << std::endl;
  ShowInformation("** Write output image");
  vtkNew<vtkXMLPolyDataWriter> writer;
  writer->SetFileName(g_outputPath.c_str());
  writer->SetInputData(mesh);
  writer->Update();

  return EXIT_SUCCESS;
}

//-----------------------------------------------------------------------------
/* Read input argument and check if they are valid */
bool ReadArguments(int argc, char ** argv)
{
  bool help = false;

  vtksys::CommandLineArguments arg;
  arg.Initialize(argc, argv);
  typedef vtksys::CommandLineArguments argT;

  arg.AddArgument("--input", argT::SPACE_ARGUMENT, &g_inputPath, "(required) Path to a .vtp file");
  arg.AddArgument("--output", argT::SPACE_ARGUMENT, &g_outputPath, "(required) Path of the output file (.vtp)");
  arg.AddArgument("--krtd", argT::SPACE_ARGUMENT, &g_globalKRTDFilePath, "(required) Path to the file which contains all krtd path");
  arg.AddArgument("--vti", argT::SPACE_ARGUMENT, &g_globalVTIFilePath, "(required) Path to the file which contains all vti path");
  arg.AddBooleanArgument("--verbose", &verbose, "(optional) Use to display debug information");
  arg.AddBooleanArgument("--help", &help, "Print help message");

  int result = arg.Parse();
  if (!result || help)
    {
    std::cerr << arg.GetHelp();
    return false;
    }

  // Check arguments
  if (g_inputPath == "" || g_outputPath == "" || g_globalKRTDFilePath == "" || g_globalVTIFilePath == "")
    {
    std::cerr << "Missing arguments..." << std::endl;
    std::cerr << arg.GetHelp();
    return false;
    }

  return true;
}

//-----------------------------------------------------------------------------
/* Show information on console if we are on verbose mode */
void ShowInformation(std::string information)
{
  if (verbose)
  {
    std::cout << information << "\n" << std::endl;
  }
}

void ShowFilledParameters()
{
  if (!verbose)
    return;

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

// VTK includes
#include <vtksys/CommandLineArguments.hxx>
#include <vtksys/SystemTools.hxx>
#include "vtkDoubleArray.h"
#include "vtkNew.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkXMLPolyDataReader.h"
#include "vtkXMLPolyDataWriter.h"

#include "Helper.h"
#include "ReconstructionData.h"

#include <iostream>
#include <string>
#include <numeric>

//-----------------------------------------------------------------------------
// READ ARGUMENTS
//-----------------------------------------------------------------------------
std::string g_inputPath = "";
std::string g_outputPath = "";
std::string g_globalKRTDFilePath = "";
std::string g_globalVTIFilePath = "";
bool verbose = false;

//-----------------------------------------------------------------------------
// FUNCTIONS
//-----------------------------------------------------------------------------
bool ReadArguments(int argc, char ** argv);
void ShowInformation(std::string message);
void ShowFilledParameters();

//-----------------------------------------------------------------------------
/* Main function */
int main(int argc, char ** argv)
{
  if (!ReadArguments(argc, argv))
  {
    return EXIT_FAILURE;
  }

  ShowInformation("** Read input...");
  vtkNew<vtkXMLPolyDataReader> reader;
  reader->SetFileName(g_inputPath.c_str());
  reader->Update();

  ShowInformation("** Extract vti and krtd file path...");
  std::vector<std::string> vtiList = help::ExtractAllFilePath(g_globalVTIFilePath.c_str());
  std::vector<std::string> krtdList = help::ExtractAllFilePath(g_globalKRTDFilePath.c_str());
  if (krtdList.size() < vtiList.size())
    {
    std::cerr << "Error, no enough krtd file for each vti file" << std::endl;
    return EXIT_FAILURE;
    }

  int nbDepthMap = (int)vtiList.size();

  ShowInformation("** Read krtd and vti...");
  std::vector<ReconstructionData*> dataList;
  for (int id = 0; id < nbDepthMap; id++)
    {
    std::cout << "\r" << id * 100 / nbDepthMap << " %" << std::flush;
    ReconstructionData* data = new ReconstructionData(vtiList[id], krtdList[id]);
    dataList.push_back(data);
    }

  std::cout << "\r" << "100 %" << std::flush << std::endl << std::endl;
  vtkPolyData* mesh = reader->GetOutput();
  vtkPoints* meshPointList = mesh->GetPoints();
  vtkIdType nbMeshPoint = meshPointList->GetNumberOfPoints();
  //vtkIdType nbMeshPoint = 3;
  int* depthMapDimensions = dataList[0]->GetDepthMapDimensions();

  ShowInformation("** Process coloration for " + std::to_string(nbMeshPoint) + " points ...");

  std::vector<int> pointCount(nbMeshPoint);
  // Contains rgb values
  vtkUnsignedCharArray* meanValues = vtkUnsignedCharArray::New();
  meanValues->SetNumberOfComponents(3);
  meanValues->SetNumberOfTuples(nbMeshPoint);
  meanValues->FillComponent(0, 0);
  meanValues->FillComponent(1, 0);
  meanValues->FillComponent(2, 0);
  meanValues->SetName("meanColoration");

  vtkUnsignedCharArray* medianValues = vtkUnsignedCharArray::New();
  medianValues->SetNumberOfComponents(3);
  medianValues->SetNumberOfTuples(nbMeshPoint);
  medianValues->FillComponent(0, 0);
  medianValues->FillComponent(1, 0);
  medianValues->FillComponent(2, 0);
  medianValues->SetName("medianColoration");

  vtkDoubleArray* projectedDMValue = vtkDoubleArray::New();
  projectedDMValue->SetNumberOfComponents(1);
  projectedDMValue->SetNumberOfTuples(nbMeshPoint);
  projectedDMValue->FillComponent(0, 0);
  projectedDMValue->SetName("NbProjectedDepthMap");

  // Store each rgb value for each depth map
  std::vector<double> list0;
  std::vector<double> list1;
  std::vector<double> list2;

  for (vtkIdType id = 0; id < nbMeshPoint; id++)
    {
    std::cout << "\r" << id * 100 / nbMeshPoint << " %" << std::flush;

    list0.reserve(nbDepthMap);
    list1.reserve(nbDepthMap);
    list2.reserve(nbDepthMap);

    // Get mesh position from id
    double position[3];
    meshPointList->GetPoint(id, position);

    for (int idData = 0; idData < nbDepthMap; idData++)
      {
      ReconstructionData* data = dataList[idData];

      // Transform to pixel index
      int pixelPosition[2];
      help::WorldToDepthMap(data->GetMatrixTR(), data->Get4MatrixK(), position, pixelPosition);
      // Test if pixel is inside depth map
      if (pixelPosition[0] < 0 || pixelPosition[1] < 0 ||
        pixelPosition[0] >= depthMapDimensions[0] ||
        pixelPosition[1] >= depthMapDimensions[1])
        {
        continue;
        }

      double color[3];
      data->GetColorValue(pixelPosition, color);

      list0.push_back(color[0]);
      list1.push_back(color[1]);
      list2.push_back(color[2]);
      }

    // If we get elements
    if (list0.size() != 0)
      {
      double sum0 = std::accumulate(list0.begin(), list0.end(), 0);
      double sum1 = std::accumulate(list1.begin(), list1.end(), 0);
      double sum2 = std::accumulate(list2.begin(), list2.end(), 0);
      double nbVal = (double)list0.size();
      meanValues->SetTuple3(id, sum0 / (double)nbVal, sum1 / (double)nbVal, sum2 / (double)nbVal);
      double median0, median1, median2;
      help::ComputeMedian<double>(list0, median0);
      help::ComputeMedian<double>(list1, median1);
      help::ComputeMedian<double>(list2, median2);
      medianValues->SetTuple3(id, median0, median1, median2);
      projectedDMValue->SetTuple1(id, list0.size());
      }

    list0.clear();
    list1.clear();
    list2.clear();
    }

  mesh->GetPointData()->AddArray(meanValues);
  mesh->GetPointData()->AddArray(medianValues);
  mesh->GetPointData()->AddArray(projectedDMValue);

  std::cout << "\r" << "100 %" << std::flush << std::endl << std::endl;
  ShowInformation("** Write output image");
  vtkNew<vtkXMLPolyDataWriter> writer;
  writer->SetFileName(g_outputPath.c_str());
  writer->SetInputData(mesh);
  writer->Update();

  return EXIT_SUCCESS;
}

//-----------------------------------------------------------------------------
/* Read input argument and check if they are valid */
bool ReadArguments(int argc, char ** argv)
{
  bool help = false;

  vtksys::CommandLineArguments arg;
  arg.Initialize(argc, argv);
  typedef vtksys::CommandLineArguments argT;

  arg.AddArgument("--input", argT::SPACE_ARGUMENT, &g_inputPath, "(required) Path to a .vtp file");
  arg.AddArgument("--output", argT::SPACE_ARGUMENT, &g_outputPath, "(required) Path of the output file (.vtp)");
  arg.AddArgument("--krtd", argT::SPACE_ARGUMENT, &g_globalKRTDFilePath, "(required) Path to the file which contains all krtd path");
  arg.AddArgument("--vti", argT::SPACE_ARGUMENT, &g_globalVTIFilePath, "(required) Path to the file which contains all vti path");
  arg.AddBooleanArgument("--verbose", &verbose, "(optional) Use to display debug information");
  arg.AddBooleanArgument("--help", &help, "Print help message");

  int result = arg.Parse();
  if (!result || help)
    {
    std::cerr << arg.GetHelp();
    return false;
    }

  // Check arguments
  if (g_inputPath == "" || g_outputPath == "" || g_globalKRTDFilePath == "" || g_globalVTIFilePath == "")
    {
    std::cerr << "Missing arguments..." << std::endl;
    std::cerr << arg.GetHelp();
    return false;
    }

  return true;
}

//-----------------------------------------------------------------------------
/* Show information on console if we are on verbose mode */
void ShowInformation(std::string information)
{
  if (verbose)
  {
    std::cout << information << "\n" << std::endl;
  }
}

void ShowFilledParameters()
{
  if (!verbose)
    return;

}<|endoftext|>


<commit_before>#ifndef GCL_PATTERN_
# define GCL_PATTERN_

# include <iostream>
# include <queue>
# include <thread>
# include <future>
# include <chrono>

namespace GCL
{
	namespace Experimental
	{
		namespace Pattern
		{
			namespace Module
			{
				template <typename T_ToVisitType>
				struct Type
				{
					virtual void	Visit(T_ToVisitType &) = 0;
				};
				template <typename T_ToVisitType>
				struct ChainElementFilter
				{
					using T_ToVisitElement = typename T_ToVisitType::T_Element;

					virtual void	Visit(T_ToVisitElement &) = 0;
				};
			}
			// Todo : Runnable class with status : Starting, Started, Running, Stoping, Stopped
			template <typename T_ElementType>
			struct ControlCenter final
			{
				using T_Element = T_ElementType;
				using T_ThisType = ControlCenter<T_Element>;

				using T_FilterType = Module::ChainElementFilter<T_ThisType>;
				using T_FilterList = std::list<std::shared_ptr<T_FilterType>>;
				using T_ElementQueue = std::queue<T_Element>;

				static void	Push(T_Element && rEvent)
				{
					T_ThisType & instance = GetInstance();
					instance._mutex.lock();
					instance._cache.push(rEvent);
					instance._mutex.unlock();
					// notify ?
				}
				static inline T_ThisType & GetInstance(void)
				{
					static T_ThisType instance;
					return instance;
				}

				void Start(void)
				{
					_running = true;

					if (_thread != nullptr)
						throw std::runtime_error("Event::ControlCenter::Start : Already started");

					_thread.reset();

					struct CaptureAdapter
					{
						std::mutex & _mutex;
						T_ElementQueue &_cache;
						T_FilterList & _filters;
					} capture { _mutex, _cache, _filters };

					_thread = std::make_unique<std::thread>([&](CaptureAdapter & capture)
					{
						while (this->IsRunning())
						{
							if (capture._cache.empty())
								; // wait notification, condition_variable, etc ...
							else
							{
								capture._mutex.lock();
								T_ElementQueue::value_type elem = std::move(capture._cache.front());
								capture._cache.pop();
								capture._mutex.unlock();

								for (auto & filter : capture._filters)
									filter->Visit(elem);
								elem();
							}
						}
					}, capture);
				}
				void Stop(void)
				{
					_running = false;
					if (_thread != nullptr)
						_thread->join();
					_thread.reset();
				}
				inline bool	IsRunning(void) const
				{
					return _running;
				}
				inline const size_t Pending(void) const
				{
					return _cache.size();
				}

			protected:
				T_FilterList	_filters;
				T_ElementQueue	_cache;

				void ProcessElement(T_Element & elem)
				{
					for (auto & filter : _filters)
						filter->Visit(elem);
					elem();
				}

			private:
				std::unique_ptr<std::thread>	_thread;
				std::mutex						_mutex;
				volatile bool					_running = false;

				ControlCenter() = default;
				ControlCenter(const ControlCenter &) = default;
				ControlCenter(ControlCenter &&) = delete;
			};

			struct Test
			{
				struct Event final
				{
					explicit Event() = default;
					void operator()(void)
					{}
				};

				static bool	Proceed(void)
				{
					using ControlCenterType = ControlCenter<Test::Event>;

					static const long long qty = std::chrono::microseconds::period::den;
					for (long long i = 0; i < qty; ++i)
						ControlCenterType::Push(Event{});

					std::cout << "\t |- Racing ..." << std::endl;
					ControlCenterType::GetInstance().Start();
					std::this_thread::sleep_for(std::chrono::seconds(1));
					ControlCenterType::GetInstance().Stop();
					std::cout << "\t |- Processed elements : " << (qty - ControlCenterType::GetInstance().Pending()) << " in 1 second" << std::endl;
					return true;
				}
			};
		}
	}
}

#endif // GCL_PATTERN_<commit_msg>New test + condition variable on lock<commit_after>#ifndef GCL_PATTERN_
# define GCL_PATTERN_

# include <iostream>
# include <queue>
# include <thread>
# include <future>
# include <chrono>

namespace GCL
{
	namespace Experimental
	{
		namespace Pattern
		{
			namespace Module
			{
				template <typename T_ToVisitType>
				struct Type
				{
					virtual void	Visit(T_ToVisitType &) = 0;
				};
				template <typename T_ToVisitType>
				struct ChainElementFilter
				{
					using T_ToVisitElement = typename T_ToVisitType::T_Element;

					virtual void	Visit(T_ToVisitElement &) = 0;
				};
			}
			// Todo : Runnable class with status : Starting, Started, Running, Stoping, Stopped
			template <typename T_ElementType>
			struct ControlCenter final
			{
				using T_Element = T_ElementType;
				using T_ThisType = ControlCenter<T_Element>;

				using T_FilterType = Module::ChainElementFilter<T_ThisType>;
				using T_FilterList = std::list<std::shared_ptr<T_FilterType>>;
				using T_ElementQueue = std::queue<T_Element>;

				static void	Push(T_Element && rEvent)
				{
					T_ThisType & instance = GetInstance();
					{	// Critical section
						std::unique_lock<std::mutex> lock(instance._mutex);
						instance._cache.push(rEvent);
					}
					instance._cv.notify_one();
				}
				static inline T_ThisType & GetInstance(void)
				{
					static T_ThisType instance;
					return instance;
				}

				DEBUG_INSTRUCTION
				(static void inline EmergencyCacheFlush(void)
				{
					ControlCenter & instance = GetInstance();
					std::unique_lock<std::mutex> lock(instance._mutex);
					instance._cache.swap(T_ElementQueue());
				})

				void Start(void)
				{
					_running = true;

					if (_thread != nullptr)
						throw std::runtime_error("Event::ControlCenter::Start : Already started");

					_thread.reset();

					struct CaptureAdapter
					{
						std::mutex & _mutex;
						std::condition_variable & _cv;
						T_ElementQueue &_cache;
						T_FilterList & _filters;
					} capture { _mutex, _cv, _cache, _filters };

					_thread = std::make_unique<std::thread>([&](CaptureAdapter & capture)
					{
						T_ElementQueue::value_type elem;
						while (this->IsRunning())
						{
							while (capture._cache.empty())
							{
								std::unique_lock<std::mutex> lock(capture._mutex);
								capture._cv.wait(lock);
							}
							{	// Critical section
								std::unique_lock<std::mutex> lock(capture._mutex);
								elem = std::move(capture._cache.front());
								capture._cache.pop();
							}

							for (auto & filter : capture._filters)
								filter->Visit(elem);
							elem();
						}
					}, capture);
				}
				void Stop(void)
				{
					_running = false;
					if (_thread != nullptr)
						_thread->join();
					_thread.reset();
				}
				inline bool	IsRunning(void) const
				{
					return _running;
				}
				inline const size_t Pending(void) const
				{
					return _cache.size();
				}

			protected:
				T_FilterList	_filters;
				T_ElementQueue	_cache;

				void ProcessElement(T_Element & elem)
				{
					for (auto & filter : _filters)
						filter->Visit(elem);
					elem();
				}

			private:
				std::unique_ptr<std::thread>	_thread;
				std::mutex						_mutex;
				std::condition_variable			_cv;
				volatile bool					_running = false;

				ControlCenter() = default;
				ControlCenter(const ControlCenter &) = default;
				ControlCenter(ControlCenter &&) = delete;
			};

			struct Test
			{
				struct Event final
				{
					explicit Event() = default;
					void operator()(void)
					{}
				};

				static bool	Proceed(void)
				{
					using ControlCenterType = ControlCenter<Test::Event>;

					{	// Test 1 : consuming in 1 second
						static const long long qty = std::chrono::microseconds::period::den;
						std::cout << "\t |- Generating " << qty << " elements ..." << std::endl;
						for (long long i = 0; i < qty; ++i)
							ControlCenterType::Push(Event{});

						std::cout << "\t |- Racing ..." << std::endl;
						ControlCenterType::GetInstance().Start();
						std::this_thread::sleep_for(std::chrono::seconds(1));
						ControlCenterType::GetInstance().Stop();
						std::cout << "\t |- Processed elements : " << (qty - ControlCenterType::GetInstance().Pending()) << " in 1 second" << std::endl;
					}

					ControlCenterType::EmergencyCacheFlush();

					{	// Test 2 : Produce take more time than consuming
						std::cout << "\t |- Racing ..." << std::endl;
						ControlCenterType::GetInstance().Start();
						static const long long qty = std::chrono::milliseconds::period::den;
						for (long long i = 0; i < qty; ++i)
						{
							std::this_thread::sleep_for(std::chrono::milliseconds(1));
							ControlCenterType::Push(Event{});
						}
						ControlCenterType::GetInstance().Stop();
						std::cout << "\t |- Processed elements : " << (qty - ControlCenterType::GetInstance().Pending()) << " / " << qty << std::endl;
					}

					return true;
				}
			};
		}
	}
}

#endif // GCL_PATTERN_<|endoftext|>


<commit_before>//Copyright (c) 2015 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "StringTest.h"

#include <iomanip>
#include <sstream> // ostringstream
#include <../src/utils/intpoint.h>
#include <../src/utils/string.h>

namespace cura
{
    CPPUNIT_TEST_SUITE_REGISTRATION(StringTest);

void StringTest::setUp()
{
    //Do nothing.
}

void StringTest::tearDown()
{
    //Do nothing.
}

void StringTest::writeInt2mmTest10000Negative()
{
    writeInt2mmAssert(-10000);
}
void StringTest::writeInt2mmTest1000Negative()
{
    writeInt2mmAssert(-1000);
}
void StringTest::writeInt2mmTest100Negative()
{
    writeInt2mmAssert(-100);
}
void StringTest::writeInt2mmTest10Negative()
{
    writeInt2mmAssert(-10);
}
void StringTest::writeInt2mmTest1Negative()
{
    writeInt2mmAssert(-1);
}
void StringTest::writeInt2mmTest0()
{
    writeInt2mmAssert(0);
}
void StringTest::writeInt2mmTest1()
{
    writeInt2mmAssert(1);
}
void StringTest::writeInt2mmTest10()
{
    writeInt2mmAssert(10);
}
void StringTest::writeInt2mmTest100()
{
    writeInt2mmAssert(100);
}
void StringTest::writeInt2mmTest1000()
{
    writeInt2mmAssert(1000);
}
void StringTest::writeInt2mmTest10000()
{
    writeInt2mmAssert(10000);
}
void StringTest::writeInt2mmTest123456789()
{
    writeInt2mmAssert(123456789);
}
void StringTest::writeInt2mmTestMax()
{
    writeInt2mmAssert(std::numeric_limits<int32_t>::max() / 1001); // divide by 1001, because MM2INT first converts to int and then multiplies by 1000, which causes overflow for the highest integer.
}

void StringTest::writeInt2mmAssert(int64_t in)
{
    std::ostringstream ss;
    writeInt2mm(in, ss);

    ss.flush();
    std::string str = ss.str();
    if (!ss.good())
    {
        char buffer[200];
        sprintf(buffer, "The integer %ld was printed as '%s' which was a bad string!", in, str.c_str());
        CPPUNIT_ASSERT_MESSAGE(std::string(buffer), false);
    }
    int64_t out = MM2INT(strtod(str.c_str(), nullptr));

    char buffer[200];
    sprintf(buffer, "The integer %ld was printed as '%s' which was interpreted as %ld rather than %ld!", in, str.c_str(), out, in);
    CPPUNIT_ASSERT_MESSAGE(std::string(buffer), in == out);
}

void StringTest::writeDoubleToStreamTest10000Negative()
{
    writeDoubleToStreamAssert(-10.000);
}
void StringTest::writeDoubleToStreamTest1000Negative()
{
    writeDoubleToStreamAssert(-1.000);
}
void StringTest::writeDoubleToStreamTest100Negative()
{
    writeDoubleToStreamAssert(-.100);
}
void StringTest::writeDoubleToStreamTest10Negative()
{
    writeDoubleToStreamAssert(-.010);
}
void StringTest::writeDoubleToStreamTest1Negative()
{
    writeDoubleToStreamAssert(-.001);
}
void StringTest::writeDoubleToStreamTest0()
{
    writeDoubleToStreamAssert(0.000);
}
void StringTest::writeDoubleToStreamTest1()
{
    writeDoubleToStreamAssert(.001);
}
void StringTest::writeDoubleToStreamTest10()
{
    writeDoubleToStreamAssert(.010);
}
void StringTest::writeDoubleToStreamTest100()
{
    writeDoubleToStreamAssert(.100);
}
void StringTest::writeDoubleToStreamTest1000()
{
    writeDoubleToStreamAssert(1.000);
}
void StringTest::writeDoubleToStreamTest10000()
{
    writeDoubleToStreamAssert(10.000);
}
void StringTest::writeDoubleToStreamTest123456789()
{
    writeDoubleToStreamAssert(123456.789);
}

void StringTest::writeDoubleToStreamTestMin()
{
    writeDoubleToStreamAssert(std::numeric_limits<double>::min());
}
void StringTest::writeDoubleToStreamTestMax()
{
    writeDoubleToStreamAssert(std::numeric_limits<double>::max());
}
void StringTest::writeDoubleToStreamTestLowest()
{
    writeDoubleToStreamAssert(std::numeric_limits<double>::lowest());
}
void StringTest::writeDoubleToStreamTestLowestNeg()
{
    writeDoubleToStreamAssert(-std::numeric_limits<double>::lowest());
}
void StringTest::writeDoubleToStreamTestLow()
{
    writeDoubleToStreamAssert(0.00000001d);
}

void StringTest::writeDoubleToStreamAssert(double in, unsigned int precision)
{
    std::ostringstream ss;
    writeDoubleToStream(precision, in, ss);
    ss.flush();
    std::string str = ss.str();
    if (!ss.good())
    {
        char buffer[8000];
        sprintf(buffer, "The double %f was printed as '%s' which was a bad string!", in, str.c_str());
        CPPUNIT_ASSERT_MESSAGE(std::string(buffer), false);
    }
    double out = strtod(str.c_str(), nullptr);

    std::ostringstream in_ss;
    in_ss << std::fixed << std::setprecision(precision) << in;
    std::string in_str = in_ss.str();
    double in_reinterpreted = strtod(in_str.c_str(), nullptr);

    char buffer[8000];
    sprintf(buffer, "The double %f was printed as '%s' which was interpreted as %f rather than %f!", in, str.c_str(), out, in_reinterpreted);
    if (in_reinterpreted != out) std::cerr << buffer << "\n";
    CPPUNIT_ASSERT_MESSAGE(std::string(buffer), in_reinterpreted == out);
}

}<commit_msg>Stringtest: Making it 64bit-save<commit_after>//Copyright (c) 2015 Ultimaker B.V.
//CuraEngine is released under the terms of the AGPLv3 or higher.

#include "StringTest.h"

#include <iomanip>
#include <sstream> // ostringstream
#include <../src/utils/intpoint.h>
#include <../src/utils/string.h>

namespace cura
{
    CPPUNIT_TEST_SUITE_REGISTRATION(StringTest);

void StringTest::setUp()
{
    //Do nothing.
}

void StringTest::tearDown()
{
    //Do nothing.
}

void StringTest::writeInt2mmTest10000Negative()
{
    writeInt2mmAssert(-10000);
}
void StringTest::writeInt2mmTest1000Negative()
{
    writeInt2mmAssert(-1000);
}
void StringTest::writeInt2mmTest100Negative()
{
    writeInt2mmAssert(-100);
}
void StringTest::writeInt2mmTest10Negative()
{
    writeInt2mmAssert(-10);
}
void StringTest::writeInt2mmTest1Negative()
{
    writeInt2mmAssert(-1);
}
void StringTest::writeInt2mmTest0()
{
    writeInt2mmAssert(0);
}
void StringTest::writeInt2mmTest1()
{
    writeInt2mmAssert(1);
}
void StringTest::writeInt2mmTest10()
{
    writeInt2mmAssert(10);
}
void StringTest::writeInt2mmTest100()
{
    writeInt2mmAssert(100);
}
void StringTest::writeInt2mmTest1000()
{
    writeInt2mmAssert(1000);
}
void StringTest::writeInt2mmTest10000()
{
    writeInt2mmAssert(10000);
}
void StringTest::writeInt2mmTest123456789()
{
    writeInt2mmAssert(123456789);
}
void StringTest::writeInt2mmTestMax()
{
    writeInt2mmAssert(std::numeric_limits<int32_t>::max() / 1001); // divide by 1001, because MM2INT first converts to int and then multiplies by 1000, which causes overflow for the highest integer.
}

void StringTest::writeInt2mmAssert(int64_t in)
{
    std::ostringstream ss;
    writeInt2mm(in, ss);

    ss.flush();
    std::string str = ss.str();
    if (!ss.good())
    {
        char buffer[200];
        sprintf(buffer, "The integer %" PRId64 " was printed as '%s' which was a bad string!", in, str.c_str());
        CPPUNIT_ASSERT_MESSAGE(std::string(buffer), false);
    }
    int64_t out = MM2INT(strtod(str.c_str(), nullptr));

    char buffer[200];
    sprintf(buffer, "The integer %" PRId64 " was printed as '%s' which was interpreted as %" PRId64 " rather than %" PRId64 "!", in, str.c_str(), out, in);
    CPPUNIT_ASSERT_MESSAGE(std::string(buffer), in == out);
}

void StringTest::writeDoubleToStreamTest10000Negative()
{
    writeDoubleToStreamAssert(-10.000);
}
void StringTest::writeDoubleToStreamTest1000Negative()
{
    writeDoubleToStreamAssert(-1.000);
}
void StringTest::writeDoubleToStreamTest100Negative()
{
    writeDoubleToStreamAssert(-.100);
}
void StringTest::writeDoubleToStreamTest10Negative()
{
    writeDoubleToStreamAssert(-.010);
}
void StringTest::writeDoubleToStreamTest1Negative()
{
    writeDoubleToStreamAssert(-.001);
}
void StringTest::writeDoubleToStreamTest0()
{
    writeDoubleToStreamAssert(0.000);
}
void StringTest::writeDoubleToStreamTest1()
{
    writeDoubleToStreamAssert(.001);
}
void StringTest::writeDoubleToStreamTest10()
{
    writeDoubleToStreamAssert(.010);
}
void StringTest::writeDoubleToStreamTest100()
{
    writeDoubleToStreamAssert(.100);
}
void StringTest::writeDoubleToStreamTest1000()
{
    writeDoubleToStreamAssert(1.000);
}
void StringTest::writeDoubleToStreamTest10000()
{
    writeDoubleToStreamAssert(10.000);
}
void StringTest::writeDoubleToStreamTest123456789()
{
    writeDoubleToStreamAssert(123456.789);
}

void StringTest::writeDoubleToStreamTestMin()
{
    writeDoubleToStreamAssert(std::numeric_limits<double>::min());
}
void StringTest::writeDoubleToStreamTestMax()
{
    writeDoubleToStreamAssert(std::numeric_limits<double>::max());
}
void StringTest::writeDoubleToStreamTestLowest()
{
    writeDoubleToStreamAssert(std::numeric_limits<double>::lowest());
}
void StringTest::writeDoubleToStreamTestLowestNeg()
{
    writeDoubleToStreamAssert(-std::numeric_limits<double>::lowest());
}
void StringTest::writeDoubleToStreamTestLow()
{
    writeDoubleToStreamAssert(0.00000001d);
}

void StringTest::writeDoubleToStreamAssert(double in, unsigned int precision)
{
    std::ostringstream ss;
    writeDoubleToStream(precision, in, ss);
    ss.flush();
    std::string str = ss.str();
    if (!ss.good())
    {
        char buffer[8000];
        sprintf(buffer, "The double %f was printed as '%s' which was a bad string!", in, str.c_str());
        CPPUNIT_ASSERT_MESSAGE(std::string(buffer), false);
    }
    double out = strtod(str.c_str(), nullptr);

    std::ostringstream in_ss;
    in_ss << std::fixed << std::setprecision(precision) << in;
    std::string in_str = in_ss.str();
    double in_reinterpreted = strtod(in_str.c_str(), nullptr);

    char buffer[8000];
    sprintf(buffer, "The double %f was printed as '%s' which was interpreted as %f rather than %f!", in, str.c_str(), out, in_reinterpreted);
    if (in_reinterpreted != out) std::cerr << buffer << "\n";
    CPPUNIT_ASSERT_MESSAGE(std::string(buffer), in_reinterpreted == out);
}

}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef CONTEXT_H
#define CONTEXT_H

#include <string>
#include <map>
#include <vector>
#include <memory>

#include <unordered_map>
#include <unordered_set>

#include "Types.hpp"

#include "AssemblyFileWriter.hpp"

namespace eddic {

class Value;
class Variable;

typedef std::unordered_map<int, std::shared_ptr<Variable>> StoredVariables;
typedef std::unordered_map<std::string, int> VisibleVariables;

class Context {
    private:
        std::shared_ptr<Context> m_parent;

    protected:
        StoredVariables m_stored;
        VisibleVariables m_visibles;

        static int currentVariable;

    public:
        Context(std::shared_ptr<Context> parent);

        virtual std::shared_ptr<Variable> addVariable(const std::string& a, Type type) = 0;
        virtual bool exists(const std::string& a) const;
        virtual std::shared_ptr<Variable> getVariable(const std::string& variable) const;
        virtual std::shared_ptr<Variable> getVariable(int index) const;

        virtual void write(AssemblyFileWriter& writer);
        virtual void release(AssemblyFileWriter& writer);
        std::shared_ptr<Context> parent() const ;

        void storeVariable(int index, std::shared_ptr<Variable> variable);
};

} //end of eddic

#endif
<commit_msg>move constructors definitions to source<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#ifndef CONTEXT_H
#define CONTEXT_H

#include <string>
#include <map>
#include <vector>
#include <memory>

#include <unordered_map>
#include <unordered_set>

#include "Types.hpp"

#include "AssemblyFileWriter.hpp"

namespace eddic {

class Value;
class Variable;

class Context {
    private:
        std::shared_ptr<Context> m_parent;

    protected:
        typedef std::unordered_map<int, std::shared_ptr<Variable>> StoredVariables;
        typedef std::unordered_map<std::string, int> VisibleVariables;

        StoredVariables m_stored;
        VisibleVariables m_visibles;

        static int currentVariable;

    public:
        Context(std::shared_ptr<Context> parent);

        virtual std::shared_ptr<Variable> addVariable(const std::string& a, Type type) = 0;
        virtual bool exists(const std::string& a) const;
        virtual std::shared_ptr<Variable> getVariable(const std::string& variable) const;
        virtual std::shared_ptr<Variable> getVariable(int index) const;

        virtual void write(AssemblyFileWriter& writer);
        virtual void release(AssemblyFileWriter& writer);
        std::shared_ptr<Context> parent() const ;

        void storeVariable(int index, std::shared_ptr<Variable> variable);
};

} //end of eddic

#endif
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All rights reserved.
//
// 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.

#include "components/time_limit.h"
#include "fplbase/utilities.h"
#include "component_library/transform.h"

FPL_ENTITY_DEFINE_COMPONENT(fpl::zooshi::TimeLimitComponent,
                            fpl::zooshi::TimeLimitData)

namespace fpl {
namespace zooshi {

// Time (in ms) taken for objects to shrink away before they're actually
// removed.
const WorldTime kShrinkTime = 1000;

void TimeLimitComponent::AddFromRawData(entity::EntityRef& entity,
                                        const void* raw_data) {
  auto time_limit_def = static_cast<const TimeLimitDef*>(raw_data);
  TimeLimitData* time_limit_data = AddEntity(entity);
  // Time limit is specified in seconds in the data files.
  time_limit_data->time_limit = static_cast<entity::WorldTime>(
      time_limit_def->timelimit() * 1000);
}

void TimeLimitComponent::UpdateAllEntities(entity::WorldTime delta_time) {
  for (auto iter = component_data_.begin(); iter != component_data_.end();
       ++iter) {
    TimeLimitData* time_limit_data = Data<TimeLimitData>(iter->entity);
    time_limit_data->time_elapsed += delta_time;
    if (time_limit_data->time_elapsed >=
        time_limit_data->time_limit - kShrinkTime) {
      component_library::TransformData* transform_data =
          Data<component_library::TransformData>(iter->entity);
      if (transform_data) {
        float scale_factor = (time_limit_data->time_limit -
            time_limit_data->time_elapsed) / static_cast<float>(kShrinkTime);
        transform_data->scale = time_limit_data->original_scale * scale_factor;
      }
    }
    if (time_limit_data->time_elapsed >= time_limit_data->time_limit) {
      entity_manager_->DeleteEntity(iter->entity);
    }
  }
}

entity::ComponentInterface::RawDataUniquePtr TimeLimitComponent::ExportRawData(
    const entity::EntityRef& entity) const {
  const TimeLimitData* data = GetComponentData(entity);
  if (data == nullptr) return nullptr;

  flatbuffers::FlatBufferBuilder fbb;

  fbb.Finish(CreateTimeLimitDef(fbb, static_cast<float>(data->time_limit)));
  return fbb.ReleaseBufferPointer();
}

void TimeLimitComponent::InitEntity(entity::EntityRef& entity) {
  TimeLimitData* time_limit_data = Data<TimeLimitData>(entity);
  component_library::TransformData* transform_data =
      Data<component_library::TransformData>(entity);
  if (transform_data) {
    time_limit_data->original_scale = transform_data->scale;
  }
}

}  // zooshi
}  // fpl
<commit_msg>Fix for sushi fade-away after time change.<commit_after>// Copyright 2015 Google Inc. All rights reserved.
//
// 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.

#include "components/time_limit.h"
#include "fplbase/utilities.h"
#include "component_library/transform.h"

FPL_ENTITY_DEFINE_COMPONENT(fpl::zooshi::TimeLimitComponent,
                            fpl::zooshi::TimeLimitData)

namespace fpl {
namespace zooshi {

// Time (in ms) taken for objects to shrink away before they're actually
// removed.
const entity::WorldTime kShrinkTime = 1000;

void TimeLimitComponent::AddFromRawData(entity::EntityRef& entity,
                                        const void* raw_data) {
  auto time_limit_def = static_cast<const TimeLimitDef*>(raw_data);
  TimeLimitData* time_limit_data = AddEntity(entity);
  // Time limit is specified in seconds in the data files.
  time_limit_data->time_limit = static_cast<entity::WorldTime>(
      time_limit_def->timelimit() * 1000);
}

void TimeLimitComponent::UpdateAllEntities(entity::WorldTime delta_time) {
  for (auto iter = component_data_.begin(); iter != component_data_.end();
       ++iter) {
    TimeLimitData* time_limit_data = Data<TimeLimitData>(iter->entity);
    time_limit_data->time_elapsed += delta_time;
    if (time_limit_data->time_elapsed >=
        time_limit_data->time_limit - kShrinkTime) {
      component_library::TransformData* transform_data =
          Data<component_library::TransformData>(iter->entity);
      if (transform_data) {
        float scale_factor = (time_limit_data->time_limit -
            time_limit_data->time_elapsed) / static_cast<float>(kShrinkTime);
        transform_data->scale = time_limit_data->original_scale * scale_factor;
      }
    }
    if (time_limit_data->time_elapsed >= time_limit_data->time_limit) {
      entity_manager_->DeleteEntity(iter->entity);
    }
  }
}

entity::ComponentInterface::RawDataUniquePtr TimeLimitComponent::ExportRawData(
    const entity::EntityRef& entity) const {
  const TimeLimitData* data = GetComponentData(entity);
  if (data == nullptr) return nullptr;

  flatbuffers::FlatBufferBuilder fbb;

  fbb.Finish(CreateTimeLimitDef(fbb, static_cast<float>(data->time_limit)));
  return fbb.ReleaseBufferPointer();
}

void TimeLimitComponent::InitEntity(entity::EntityRef& entity) {
  TimeLimitData* time_limit_data = Data<TimeLimitData>(entity);
  component_library::TransformData* transform_data =
      Data<component_library::TransformData>(entity);
  if (transform_data) {
    time_limit_data->original_scale = transform_data->scale;
  }
}

}  // zooshi
}  // fpl
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DLL_RBM_INL
#define DLL_RBM_INL

#include "cpp_utils/assert.hpp"             //Assertions
#include "cpp_utils/stop_watch.hpp"         //Performance counter

#include "etl/etl.hpp"

#include "normal_rbm.hpp"
#include "checks.hpp"

namespace dll {

/*!
 * \brief Standard version of Restricted Boltzmann Machine
 *
 * This follows the definition of a RBM by Geoffrey Hinton.
 */
template<typename Desc>
struct rbm : public normal_rbm<rbm<Desc>, Desc> {
    typedef double weight;
    typedef double value_t;

    using desc = Desc;

    static constexpr const std::size_t num_visible = desc::num_visible;
    static constexpr const std::size_t num_hidden = desc::num_hidden;

    static constexpr const unit_type visible_unit = desc::visible_unit;
    static constexpr const unit_type hidden_unit = desc::hidden_unit;

    //Weights and biases
    etl::fast_matrix<weight, num_visible, num_hidden> w;    //!< Weights
    etl::fast_vector<weight, num_hidden> b;                 //!< Hidden biases
    etl::fast_vector<weight, num_visible> c;                //!< Visible biases

    //Reconstruction data
    etl::fast_vector<weight, num_visible> v1; //!< State of the visible units

    etl::fast_vector<weight, num_hidden> h1_a; //!< Activation probabilities of hidden units after first CD-step
    etl::fast_vector<weight, num_hidden> h1_s; //!< Sampled value of hidden units after first CD-step

    etl::fast_vector<weight, num_visible> v2_a; //!< Activation probabilities of visible units after first CD-step
    etl::fast_vector<weight, num_visible> v2_s; //!< Sampled value of visible units after first CD-step

    etl::fast_vector<weight, num_hidden> h2_a; //!< Activation probabilities of hidden units after last CD-step
    etl::fast_vector<weight, num_hidden> h2_s; //!< Sampled value of hidden units after last CD-step

    //No copying
    rbm(const rbm& rbm) = delete;
    rbm& operator=(const rbm& rbm) = delete;

    //No moving
    rbm(rbm&& rbm) = delete;
    rbm& operator=(rbm&& rbm) = delete;

    /*!
     * \brief Initialize a RBM with basic weights.
     *
     * The weights are initialized from a normal distribution of
     * zero-mean and 0.1 variance.
     */
    rbm() : normal_rbm<rbm<Desc>, Desc>(), b(0.0), c(0.0) {
        //Initialize the weights with a zero-mean and unit variance Gaussian distribution
        w = etl::normal_generator() * 0.1;
    }

    static constexpr std::size_t input_size(){
        return num_visible;
    }

    static constexpr std::size_t output_size(){
        return num_hidden;
    }

    void display() const {
        std::cout << "RBM: " << num_visible << " -> " << num_hidden << std::endl;
    }

    template<typename H1, typename H2, typename V>
    void activate_hidden(H1& h_a, H2& h_s, const V& v_a, const V& v_s) const {
        return activate_hidden(h_a, h_s, v_a, v_s, b, w);
    }

    template<typename H1, typename H2, typename V, typename B, typename W>
    static void activate_hidden(H1& h_a, H2& h_s, const V& v_a, const V&, const B& b, const W& w){
        using namespace etl;

        static fast_matrix<weight, 1, num_hidden> t;

        if(hidden_unit == unit_type::BINARY){
            h_a = sigmoid(b + auto_vmmul(v_a, w, t));
            h_s = bernoulli(h_a);
        } else if(hidden_unit == unit_type::EXP){
            h_a = exp(b + auto_vmmul(v_a, w, t));
            h_s = bernoulli(h_a);
        } else if(hidden_unit == unit_type::RELU){
            h_a = max(b + auto_vmmul(v_a, w, t), 0.0);
            h_s = logistic_noise(h_a);
        } else if(hidden_unit == unit_type::RELU6){
            h_a = min(max(b + auto_vmmul(v_a, w, t), 0.0), 6.0);
            h_s = ranged_noise(h_a, 6.0);
        } else if(hidden_unit == unit_type::RELU1){
            h_a = min(max(b + auto_vmmul(v_a, w, t), 0.0), 1.0);
            h_s = ranged_noise(h_a, 1.0);
        } else if(hidden_unit == unit_type::SOFTMAX){
            h_a = softmax(b + auto_vmmul(v_a, w, t));
            h_s = one_if_max(h_a);
        } else {
            cpp_unreachable("Invalid path");
        }

        nan_check_deep(h_a);
        nan_check_deep(h_s);
    }

    template<typename H, typename V>
    void activate_visible(const H&, const H& h_s, V& v_a, V& v_s) const {
        using namespace etl;

        static fast_matrix<weight, num_visible, 1> t;

        if(visible_unit == unit_type::BINARY){
            v_a = sigmoid(c + auto_vmmul(w, h_s, t));
            v_s = bernoulli(v_a);
        } else if(visible_unit == unit_type::GAUSSIAN){
            v_a = c + auto_vmmul(w, h_s, t);
            v_s = v_a;
        } else if(visible_unit == unit_type::RELU){
            v_a = max(c + auto_vmmul(w, h_s, t), 0.0);
            v_s = logistic_noise(v_a);
        } else {
            cpp_unreachable("Invalid path");
        }

        nan_check_deep(v_a);
        nan_check_deep(v_s);
    }

    template<typename Sample, typename Output>
        void activation_probabilities(const Sample& item_data, Output& result){
            etl::dyn_vector<weight> item(item_data);

            static etl::dyn_vector<weight> next_s(num_hidden);

            activate_hidden(result, next_s, item, item);
        }

    template<typename Sample>
        etl::dyn_vector<weight> activation_probabilities(const Sample& item_data){
            etl::dyn_vector<weight> result(output_size());

            activation_probabilities(item_data, result);

            return result;
        }
};

} //end of dbn namespace

#endif
<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef DLL_RBM_INL
#define DLL_RBM_INL

#include "cpp_utils/assert.hpp"             //Assertions
#include "cpp_utils/stop_watch.hpp"         //Performance counter

#include "etl/etl.hpp"

#include "normal_rbm.hpp"
#include "checks.hpp"

namespace dll {

/*!
 * \brief Standard version of Restricted Boltzmann Machine
 *
 * This follows the definition of a RBM by Geoffrey Hinton.
 */
template<typename Desc>
struct rbm : public normal_rbm<rbm<Desc>, Desc> {
    typedef double weight;
    typedef double value_t;

    using desc = Desc;

    static constexpr const std::size_t num_visible = desc::num_visible;
    static constexpr const std::size_t num_hidden = desc::num_hidden;

    static constexpr const unit_type visible_unit = desc::visible_unit;
    static constexpr const unit_type hidden_unit = desc::hidden_unit;

    //Weights and biases
    etl::fast_matrix<weight, num_visible, num_hidden> w;    //!< Weights
    etl::fast_vector<weight, num_hidden> b;                 //!< Hidden biases
    etl::fast_vector<weight, num_visible> c;                //!< Visible biases

    //Reconstruction data
    etl::fast_vector<weight, num_visible> v1; //!< State of the visible units

    etl::fast_vector<weight, num_hidden> h1_a; //!< Activation probabilities of hidden units after first CD-step
    etl::fast_vector<weight, num_hidden> h1_s; //!< Sampled value of hidden units after first CD-step

    etl::fast_vector<weight, num_visible> v2_a; //!< Activation probabilities of visible units after first CD-step
    etl::fast_vector<weight, num_visible> v2_s; //!< Sampled value of visible units after first CD-step

    etl::fast_vector<weight, num_hidden> h2_a; //!< Activation probabilities of hidden units after last CD-step
    etl::fast_vector<weight, num_hidden> h2_s; //!< Sampled value of hidden units after last CD-step

    //No copying
    rbm(const rbm& rbm) = delete;
    rbm& operator=(const rbm& rbm) = delete;

    //No moving
    rbm(rbm&& rbm) = delete;
    rbm& operator=(rbm&& rbm) = delete;

    /*!
     * \brief Initialize a RBM with basic weights.
     *
     * The weights are initialized from a normal distribution of
     * zero-mean and 0.1 variance.
     */
    rbm() : normal_rbm<rbm<Desc>, Desc>(), b(0.0), c(0.0) {
        //Initialize the weights with a zero-mean and unit variance Gaussian distribution
        w = etl::normal_generator() * 0.1;
    }

    static constexpr std::size_t input_size(){
        return num_visible;
    }

    static constexpr std::size_t output_size(){
        return num_hidden;
    }

    void display() const {
        std::cout << "RBM: " << num_visible << " -> " << num_hidden << std::endl;
    }

    template<typename H1, typename H2, typename V>
    void activate_hidden(H1& h_a, H2& h_s, const V& v_a, const V& v_s) const {
        return activate_hidden(h_a, h_s, v_a, v_s, b, w);
    }

    template<typename H1, typename H2, typename V, typename B, typename W>
    static void activate_hidden(H1& h_a, H2& h_s, const V& v_a, const V&, const B& b, const W& w){
        using namespace etl;

        static fast_matrix<weight, 1, num_hidden> t;

        if(hidden_unit == unit_type::BINARY){
            h_a = sigmoid(b + auto_vmmul(v_a, w, t));
            h_s = bernoulli(h_a);
        } else if(hidden_unit == unit_type::EXP){
            h_a = exp(b + auto_vmmul(v_a, w, t));
            h_s = bernoulli(h_a);
        } else if(hidden_unit == unit_type::RELU){
            h_a = max(b + auto_vmmul(v_a, w, t), 0.0);
            h_s = logistic_noise(h_a);
        } else if(hidden_unit == unit_type::RELU6){
            h_a = min(max(b + auto_vmmul(v_a, w, t), 0.0), 6.0);
            h_s = ranged_noise(h_a, 6.0);
        } else if(hidden_unit == unit_type::RELU1){
            h_a = min(max(b + auto_vmmul(v_a, w, t), 0.0), 1.0);
            h_s = ranged_noise(h_a, 1.0);
        } else if(hidden_unit == unit_type::SOFTMAX){
            h_a = softmax(b + auto_vmmul(v_a, w, t));
            h_s = one_if_max(h_a);
        } else {
            cpp_unreachable("Invalid path");
        }

        nan_check_deep(h_a);
        nan_check_deep(h_s);
    }

    template<typename H, typename V>
    void activate_visible(const H&, const H& h_s, V& v_a, V& v_s) const {
        using namespace etl;

        static fast_matrix<weight, num_visible, 1> t;

        if(visible_unit == unit_type::BINARY){
            v_a = sigmoid(c + auto_vmmul(w, h_s, t));
            v_s = bernoulli(v_a);
        } else if(visible_unit == unit_type::GAUSSIAN){
            v_a = c + auto_vmmul(w, h_s, t);
            v_s = v_a;
        } else if(visible_unit == unit_type::RELU){
            v_a = max(c + auto_vmmul(w, h_s, t), 0.0);
            v_s = logistic_noise(v_a);
        } else {
            cpp_unreachable("Invalid path");
        }

        nan_check_deep(v_a);
        nan_check_deep(v_s);
    }

    template<typename Sample, typename Output>
    void activation_probabilities(const Sample& item_data, Output& result){
        etl::dyn_vector<weight> item(item_data);

        static etl::dyn_vector<weight> next_s(num_hidden);

        activate_hidden(result, next_s, item, item);
    }

    template<typename Sample>
    etl::dyn_vector<weight> activation_probabilities(const Sample& item_data){
        etl::dyn_vector<weight> result(output_size());

        activation_probabilities(item_data, result);

        return result;
    }
};

} //end of dbn namespace

#endif
<|endoftext|>