<commit_before>/**
 * \file
 * <!--
 * Copyright 2015 Develer S.r.l. (http://www.develer.com/)
 * -->
 *
 * \brief main cutecom-ng window
 *
 * \author Aurelien Rainone <aurelien@develer.org>
 */

#include <algorithm>
#include <iterator>

#include <QUiLoader>
#include <QLineEdit>
#include <QPropertyAnimation>
#include <QShortcut>

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "connectdialog.h"
#include "sessionmanager.h"
#include "outputmanager.h"
#include "searchhighlighter.h"

/// line ending char appended to the commands sent to the serial port
const QString LINE_ENDING = "\n";

/// maximum count of document blocks for the bootom output
const int MAX_OUTPUT_LINES = 100;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    search_widget(0),
    search_input(0)
{
    ui->setupUi(this);

    // create session and output managers
    output_mgr = new OutputManager(this);
    session_mgr = new SessionManager(this);
    connect_dlg = new ConnectDialog(this);

    // show connection dialog
    connect(ui->connectButton, &QAbstractButton::clicked, connect_dlg, &ConnectDialog::show);

    // handle reception of new data from serial port
    connect(session_mgr, &SessionManager::dataReceived, this, &MainWindow::handleDataReceived);

    // get data formatted for display and show it in output view
    connect(output_mgr, &OutputManager::dataConverted, this, &MainWindow::addDataToView);

    // get data formatted for display and show it in output view
    connect(ui->inputBox, &HistoryComboBox::lineEntered, this, &MainWindow::handleNewInput);

    // clear output manager buffer at session start
    connect(session_mgr, &SessionManager::sessionStarted, output_mgr, &OutputManager::clear);

    // clear both output text at session start
    connect(session_mgr, &SessionManager::sessionStarted, ui->mainOutput, &QPlainTextEdit::clear);
    connect(session_mgr, &SessionManager::sessionStarted, ui->bottomOutput, &QPlainTextEdit::clear);

    // clear both output text when 'clear' is clicked
    connect(ui->clearButton, &QToolButton::clicked, ui->mainOutput, &QPlainTextEdit::clear);
    connect(ui->clearButton, &QToolButton::clicked, ui->bottomOutput, &QPlainTextEdit::clear);

    // call openSession when user accepts/closes connection dialog
    connect(connect_dlg, &ConnectDialog::openDeviceClicked, session_mgr, &SessionManager::openSession);

    connect(ui->splitOutputBtn, &QToolButton::clicked, this, &MainWindow::toggleOutputSplitter);

    // additional configuration for bottom output
    ui->bottomOutput->hide();
    ui->bottomOutput->document()->setMaximumBlockCount(MAX_OUTPUT_LINES);
    ui->bottomOutput->viewport()->installEventFilter(this);

    // load search widget and hide it
    QUiLoader loader;
    QFile file(":/searchwidget.ui");
    file.open(QFile::ReadOnly);
    search_widget = loader.load(&file, ui->mainOutput);
    Q_ASSERT_X(search_widget, "MainWindow::MainWindow", "error while loading searchwidget.ui");

    search_input = search_widget->findChild<QLineEdit*>("searchInput");
    Q_ASSERT_X(search_input, "MainWindow::MainWindow", "didn't find searchInput");

    search_prev_button = search_widget->findChild<QToolButton*>("previousButton");
    search_next_button = search_widget->findChild<QToolButton*>("nextButton");
    Q_ASSERT_X(search_prev_button, "MainWindow::MainWindow", "didn't find previousButton");
    Q_ASSERT_X(search_next_button, "MainWindow::MainWindow", "didn't find nextButton");

    file.close();
    search_widget->hide();

    // create the search results highlighter for main output
    SearchHighlighter *search_highlighter_main = new SearchHighlighter(ui->mainOutput->document());
    connect(search_input, &QLineEdit::textChanged, search_highlighter_main, &SearchHighlighter::setSearchString);

    // search result highlighter (without search cursor) for bottom output
    SearchHighlighter *search_highlighter_bottom = new SearchHighlighter(ui->bottomOutput->document(), false);
    connect(search_input, &QLineEdit::textChanged, search_highlighter_bottom, &SearchHighlighter::setSearchString);

    // connect search-related signals/slots
    connect(search_prev_button, &QToolButton::clicked, search_highlighter_main, &SearchHighlighter::previousOccurence);
    connect(search_next_button, &QToolButton::clicked, search_highlighter_main, &SearchHighlighter::nextOccurence);
    connect(search_highlighter_main, &SearchHighlighter::cursorPosChanged, this, &MainWindow::handleCursosPosChanged);
    connect(search_highlighter_main, &SearchHighlighter::totalOccurencesChanged, this, &MainWindow::handleTotalOccurencesChanged);
    connect(ui->searchButton, &QToolButton::toggled, this, &MainWindow::showSearchWidget);

    search_input->installEventFilter(this);
    ui->mainOutput->viewport()->installEventFilter(this);
    installEventFilter(this);
}

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

void MainWindow::handleNewInput(QString entry)
{
    // if session is not open, this also keeps user input
    if (session_mgr->isSessionOpen())
    {
        entry.append(LINE_ENDING);
        session_mgr->sendToSerial(entry.toLocal8Bit());
        ui->inputBox->clearEditText();
    }
}

void MainWindow::addDataToView(const QString & textdata)
{
    // problem : QTextEdit interprets a '\r' as a new line, so if a buffer ending
    //           with '\r\n' happens to be cut in the middle, there will be 1 extra
    //           line jump in the QTextEdit. To prevent we remove ending '\r' and
    //           prepend them to the next received buffer

    // flag indicating that the previously received buffer ended with CR
    static bool prev_ends_with_CR = false;

    QString newdata;
    if (prev_ends_with_CR)
    {
        // CR was removed at the previous buffer, so now we prepend it
        newdata.append('\r');
        prev_ends_with_CR = false;
    }

    if (textdata.length() > 0)
    {
        QString::const_iterator end_cit = textdata.cend();
        if (textdata.endsWith('\r'))
        {
            // if buffer ends with CR, we don't copy it
            end_cit--;
            prev_ends_with_CR = true;
        }
        std::copy(textdata.begin(), end_cit, std::back_inserter(newdata));
    }

    // record end cursor position before adding text
    QTextCursor prev_end_cursor(ui->mainOutput->document());
    prev_end_cursor.movePosition(QTextCursor::End);

    if (ui->bottomOutput->isVisible())
    {
        // append text to the top output and stay at current position
        QTextCursor cursor(ui->mainOutput->document());
        cursor.movePosition(QTextCursor::End);
        cursor.insertText(newdata);
    }
    else
    {
        // append text to the top output and scroll down
        ui->mainOutput->moveCursor(QTextCursor::End);
        ui->mainOutput->insertPlainText(newdata);
    }

    // append text to bottom output and scroll
    ui->bottomOutput->moveCursor(QTextCursor::End);
    ui->bottomOutput->insertPlainText(newdata);
}

void MainWindow::handleDataReceived(const QByteArray &data)
{
    (*output_mgr) << data;
}

void MainWindow::toggleOutputSplitter()
{
    ui->bottomOutput->setVisible(!ui->bottomOutput->isVisible());
}

bool MainWindow::eventFilter(QObject *target, QEvent *event)
{
    if (target == ui->mainOutput->viewport())
    {
        if (event->type() == QEvent::Resize)
        {
            // re position search widget when main output inner size changes
            // this takes into account existence of vertical scrollbar
            QResizeEvent *resizeEvent = static_cast<QResizeEvent*>(event);
            search_widget->move(resizeEvent->size().width() - search_widget->width(), 0);
        }
        else if (event->type() == QEvent::Wheel)
        {
            // allow mouse wheel usage only in 'browsing mode'
            if (!ui->bottomOutput->isVisible())
                return true;
        }
    }
    else
    {
        if (event->type() == QEvent::KeyPress)
        {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            if (ui->searchButton->isChecked())
            {
                // hide search widget on Escape key press
                if (keyEvent->key() == Qt::Key_Escape)
                    emit ui->searchButton->toggle();
            }
            else
            {
                // show search widget on Ctrl-F
                if (keyEvent->key() == Qt::Key_F && keyEvent->modifiers() == Qt::ControlModifier)
                    emit ui->searchButton->toggle();
            }
            if (target == search_input)
            {
                if (keyEvent->key() == Qt::Key_Return)
                {
                    if (keyEvent->modifiers() == Qt::ShiftModifier)
                        emit search_prev_button->click();
                    else
                        emit search_next_button->click();
                }
            }

        }
    }

    // base class behaviour
    return QMainWindow::eventFilter(target, event);
}

void MainWindow::showSearchWidget(bool show)
{
    // record which widget had focus before showing search widget, in order
    // to return focus to it when search widget is hidden
    static QWidget *prevFocus = 0;

    QPropertyAnimation *animation = new QPropertyAnimation(search_widget, "pos");
    animation->setDuration(150);

    // place search widget at the rightmost position of mainoutput viewport
    QPoint showed_pos(ui->mainOutput->viewport()->width() - search_widget->width(), 0);
    QPoint hidden_pos(ui->mainOutput->viewport()->width() - search_widget->width(), -search_widget->height());
    animation->setStartValue(show ? hidden_pos : showed_pos);
    animation->setEndValue(show ? showed_pos : hidden_pos);

    if (show)
    {
        prevFocus = QApplication::focusWidget();
        search_widget->setVisible(show);
        search_input->setFocus();
    }
    else
    {
        connect(animation, &QPropertyAnimation::destroyed, search_widget, &QWidget::hide);
        prevFocus->setFocus();
    }
    animation->start(QAbstractAnimation::DeleteWhenStopped);
}

void MainWindow::handleCursosPosChanged(int pos)
{
    // only in browsing mode
    if (ui->bottomOutput->isVisible())
    {
        // move cursor
        QTextCursor text_cursor = ui->mainOutput->textCursor();
        text_cursor.setPosition(pos);

        // ensure search result cursor is visible
        ui->mainOutput->ensureCursorVisible();
        ui->mainOutput->setTextCursor(text_cursor);
    }
}

void MainWindow::handleTotalOccurencesChanged(int total_occurences)
{
    if (total_occurences == 0)
        search_input->setStyleSheet("QLineEdit{background-color: red;}");
    else
        search_input->setStyleSheet("");
}
<commit_msg>remove unnecessary emit<commit_after>/**
 * \file
 * <!--
 * Copyright 2015 Develer S.r.l. (http://www.develer.com/)
 * -->
 *
 * \brief main cutecom-ng window
 *
 * \author Aurelien Rainone <aurelien@develer.org>
 */

#include <algorithm>
#include <iterator>

#include <QUiLoader>
#include <QLineEdit>
#include <QPropertyAnimation>
#include <QShortcut>

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "connectdialog.h"
#include "sessionmanager.h"
#include "outputmanager.h"
#include "searchhighlighter.h"

/// line ending char appended to the commands sent to the serial port
const QString LINE_ENDING = "\n";

/// maximum count of document blocks for the bootom output
const int MAX_OUTPUT_LINES = 100;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    search_widget(0),
    search_input(0)
{
    ui->setupUi(this);

    // create session and output managers
    output_mgr = new OutputManager(this);
    session_mgr = new SessionManager(this);
    connect_dlg = new ConnectDialog(this);

    // show connection dialog
    connect(ui->connectButton, &QAbstractButton::clicked, connect_dlg, &ConnectDialog::show);

    // handle reception of new data from serial port
    connect(session_mgr, &SessionManager::dataReceived, this, &MainWindow::handleDataReceived);

    // get data formatted for display and show it in output view
    connect(output_mgr, &OutputManager::dataConverted, this, &MainWindow::addDataToView);

    // get data formatted for display and show it in output view
    connect(ui->inputBox, &HistoryComboBox::lineEntered, this, &MainWindow::handleNewInput);

    // clear output manager buffer at session start
    connect(session_mgr, &SessionManager::sessionStarted, output_mgr, &OutputManager::clear);

    // clear both output text at session start
    connect(session_mgr, &SessionManager::sessionStarted, ui->mainOutput, &QPlainTextEdit::clear);
    connect(session_mgr, &SessionManager::sessionStarted, ui->bottomOutput, &QPlainTextEdit::clear);

    // clear both output text when 'clear' is clicked
    connect(ui->clearButton, &QToolButton::clicked, ui->mainOutput, &QPlainTextEdit::clear);
    connect(ui->clearButton, &QToolButton::clicked, ui->bottomOutput, &QPlainTextEdit::clear);

    // call openSession when user accepts/closes connection dialog
    connect(connect_dlg, &ConnectDialog::openDeviceClicked, session_mgr, &SessionManager::openSession);

    connect(ui->splitOutputBtn, &QToolButton::clicked, this, &MainWindow::toggleOutputSplitter);

    // additional configuration for bottom output
    ui->bottomOutput->hide();
    ui->bottomOutput->document()->setMaximumBlockCount(MAX_OUTPUT_LINES);
    ui->bottomOutput->viewport()->installEventFilter(this);

    // load search widget and hide it
    QUiLoader loader;
    QFile file(":/searchwidget.ui");
    file.open(QFile::ReadOnly);
    search_widget = loader.load(&file, ui->mainOutput);
    Q_ASSERT_X(search_widget, "MainWindow::MainWindow", "error while loading searchwidget.ui");

    search_input = search_widget->findChild<QLineEdit*>("searchInput");
    Q_ASSERT_X(search_input, "MainWindow::MainWindow", "didn't find searchInput");

    search_prev_button = search_widget->findChild<QToolButton*>("previousButton");
    search_next_button = search_widget->findChild<QToolButton*>("nextButton");
    Q_ASSERT_X(search_prev_button, "MainWindow::MainWindow", "didn't find previousButton");
    Q_ASSERT_X(search_next_button, "MainWindow::MainWindow", "didn't find nextButton");

    file.close();
    search_widget->hide();

    // create the search results highlighter for main output
    SearchHighlighter *search_highlighter_main = new SearchHighlighter(ui->mainOutput->document());
    connect(search_input, &QLineEdit::textChanged, search_highlighter_main, &SearchHighlighter::setSearchString);

    // search result highlighter (without search cursor) for bottom output
    SearchHighlighter *search_highlighter_bottom = new SearchHighlighter(ui->bottomOutput->document(), false);
    connect(search_input, &QLineEdit::textChanged, search_highlighter_bottom, &SearchHighlighter::setSearchString);

    // connect search-related signals/slots
    connect(search_prev_button, &QToolButton::clicked, search_highlighter_main, &SearchHighlighter::previousOccurence);
    connect(search_next_button, &QToolButton::clicked, search_highlighter_main, &SearchHighlighter::nextOccurence);
    connect(search_highlighter_main, &SearchHighlighter::cursorPosChanged, this, &MainWindow::handleCursosPosChanged);
    connect(search_highlighter_main, &SearchHighlighter::totalOccurencesChanged, this, &MainWindow::handleTotalOccurencesChanged);
    connect(ui->searchButton, &QToolButton::toggled, this, &MainWindow::showSearchWidget);

    search_input->installEventFilter(this);
    ui->mainOutput->viewport()->installEventFilter(this);
    installEventFilter(this);
}

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

void MainWindow::handleNewInput(QString entry)
{
    // if session is not open, this also keeps user input
    if (session_mgr->isSessionOpen())
    {
        entry.append(LINE_ENDING);
        session_mgr->sendToSerial(entry.toLocal8Bit());
        ui->inputBox->clearEditText();
    }
}

void MainWindow::addDataToView(const QString & textdata)
{
    // problem : QTextEdit interprets a '\r' as a new line, so if a buffer ending
    //           with '\r\n' happens to be cut in the middle, there will be 1 extra
    //           line jump in the QTextEdit. To prevent we remove ending '\r' and
    //           prepend them to the next received buffer

    // flag indicating that the previously received buffer ended with CR
    static bool prev_ends_with_CR = false;

    QString newdata;
    if (prev_ends_with_CR)
    {
        // CR was removed at the previous buffer, so now we prepend it
        newdata.append('\r');
        prev_ends_with_CR = false;
    }

    if (textdata.length() > 0)
    {
        QString::const_iterator end_cit = textdata.cend();
        if (textdata.endsWith('\r'))
        {
            // if buffer ends with CR, we don't copy it
            end_cit--;
            prev_ends_with_CR = true;
        }
        std::copy(textdata.begin(), end_cit, std::back_inserter(newdata));
    }

    // record end cursor position before adding text
    QTextCursor prev_end_cursor(ui->mainOutput->document());
    prev_end_cursor.movePosition(QTextCursor::End);

    if (ui->bottomOutput->isVisible())
    {
        // append text to the top output and stay at current position
        QTextCursor cursor(ui->mainOutput->document());
        cursor.movePosition(QTextCursor::End);
        cursor.insertText(newdata);
    }
    else
    {
        // append text to the top output and scroll down
        ui->mainOutput->moveCursor(QTextCursor::End);
        ui->mainOutput->insertPlainText(newdata);
    }

    // append text to bottom output and scroll
    ui->bottomOutput->moveCursor(QTextCursor::End);
    ui->bottomOutput->insertPlainText(newdata);
}

void MainWindow::handleDataReceived(const QByteArray &data)
{
    (*output_mgr) << data;
}

void MainWindow::toggleOutputSplitter()
{
    ui->bottomOutput->setVisible(!ui->bottomOutput->isVisible());
}

bool MainWindow::eventFilter(QObject *target, QEvent *event)
{
    if (target == ui->mainOutput->viewport())
    {
        if (event->type() == QEvent::Resize)
        {
            // re position search widget when main output inner size changes
            // this takes into account existence of vertical scrollbar
            QResizeEvent *resizeEvent = static_cast<QResizeEvent*>(event);
            search_widget->move(resizeEvent->size().width() - search_widget->width(), 0);
        }
        else if (event->type() == QEvent::Wheel)
        {
            // allow mouse wheel usage only in 'browsing mode'
            if (!ui->bottomOutput->isVisible())
                return true;
        }
    }
    else
    {
        if (event->type() == QEvent::KeyPress)
        {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            if (ui->searchButton->isChecked())
            {
                // hide search widget on Escape key press
                if (keyEvent->key() == Qt::Key_Escape)
                    ui->searchButton->toggle();
            }
            else
            {
                // show search widget on Ctrl-F
                if (keyEvent->key() == Qt::Key_F && keyEvent->modifiers() == Qt::ControlModifier)
                    ui->searchButton->toggle();
            }
            if (target == search_input)
            {
                if (keyEvent->key() == Qt::Key_Return)
                {
                    if (keyEvent->modifiers() == Qt::ShiftModifier)
                        search_prev_button->click();
                    else
                        search_next_button->click();
                }
            }

        }
    }

    // base class behaviour
    return QMainWindow::eventFilter(target, event);
}

void MainWindow::showSearchWidget(bool show)
{
    // record which widget had focus before showing search widget, in order
    // to return focus to it when search widget is hidden
    static QWidget *prevFocus = 0;

    QPropertyAnimation *animation = new QPropertyAnimation(search_widget, "pos");
    animation->setDuration(150);

    // place search widget at the rightmost position of mainoutput viewport
    QPoint showed_pos(ui->mainOutput->viewport()->width() - search_widget->width(), 0);
    QPoint hidden_pos(ui->mainOutput->viewport()->width() - search_widget->width(), -search_widget->height());
    animation->setStartValue(show ? hidden_pos : showed_pos);
    animation->setEndValue(show ? showed_pos : hidden_pos);

    if (show)
    {
        prevFocus = QApplication::focusWidget();
        search_widget->setVisible(show);
        search_input->setFocus();
    }
    else
    {
        connect(animation, &QPropertyAnimation::destroyed, search_widget, &QWidget::hide);
        prevFocus->setFocus();
    }
    animation->start(QAbstractAnimation::DeleteWhenStopped);
}

void MainWindow::handleCursosPosChanged(int pos)
{
    // only in browsing mode
    if (ui->bottomOutput->isVisible())
    {
        // move cursor
        QTextCursor text_cursor = ui->mainOutput->textCursor();
        text_cursor.setPosition(pos);

        // ensure search result cursor is visible
        ui->mainOutput->ensureCursorVisible();
        ui->mainOutput->setTextCursor(text_cursor);
    }
}

void MainWindow::handleTotalOccurencesChanged(int total_occurences)
{
    if (total_occurences == 0)
        search_input->setStyleSheet("QLineEdit{background-color: red;}");
    else
        search_input->setStyleSheet("");
}
<|endoftext|>


<commit_before>#include <QMessageBox>
#include <QImage>
#include <QScreen>
#include <QClipboard>
#include <QImageWriter>
#include <QImageReader>
#include <QDir>
#include <QStandardPaths>
#include <QStyle>
#include <QTime>
#include <QGuiApplication>
#include <QApplication>
#include <QLabel>
#include <QSharedPointer>
#include <QListWidget>
#include <QBitmap>
#include <QMenu>
#include <QDesktopWidget>
#include <QDebug>

#include "awesomeservice.h"
#include "mainwindow.h"
#include "rsview.h"
#include "dock/colorswidget.h"
#include "dock/accentwidget.h"
#include "fullscreenselectiondialog.h"
#include "assistant/cvsnapassistant.h"
#include "accent/selectionaccentpainter.h"
#include "accent/rectangleaccentpainter.h"
#include "accent/cinemaaccentpainter.h"
#include "accent/hatchingaccentpainter.h"
#include "widgetutils.h"
#include "cv/cvmodelbuilder.h"

static const QColor RegionColor = Qt::red;
static const QColor ShaderColor = QColor::fromRgba(0x50a0a0a0);

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , _modelBuilder(new CvModelBuilder(this))
{
    connect(_modelBuilder, &CvModelBuilder::signalBuildCompleted, this, &MainWindow::slotBuildCompleted);

    setupUi();
    enableDisableUi();
}

void MainWindow::slotActionScreenshot()
{
    hide();
    delay(300);

    QScreen *screen = QGuiApplication::primaryScreen();
    _currentImage = screen->grabWindow(QApplication::desktop()->winId()).toImage();

    FullscreenSelectionDialog dialog(this, _currentImage, createDefaultAccentPainter());
    if (dialog.exec() == QDialog::Accepted) {
        updateImage(dialog.getRegionContext(), dialog.usedHighlightedRegion());

        _statusbar->showMessage(tr("A screen region is captured."));
    }

    show();
}

void MainWindow::slotActionPaste()
{
    QClipboard *clipboard = QApplication::clipboard();
    QImage image = clipboard->image();
    if (image.isNull()) {
        _statusbar->showMessage(tr("Clipboard has no image."));
    }
    else {
        updateImage(image);
    }
}

void MainWindow::slotActionCopy()
{
    QClipboard *clipboard = QApplication::clipboard();
    clipboard->setImage(_currentImage);

    _statusbar->showMessage(tr("Copied to the clipboard."));
}

void MainWindow::slotActionSave()
{
    QFileDialog dialog(this, tr("Save Image As"));
    initializeImageFileDialog(dialog, QFileDialog::AcceptSave);

    while (dialog.exec() == QDialog::Accepted && !saveImage(dialog.selectedFiles().first())) {}
}

void MainWindow::slotActionOpen()
{
    QFileDialog dialog(this, tr("Open Image"));
    initializeImageFileDialog(dialog, QFileDialog::AcceptOpen);

    while (dialog.exec() == QDialog::Accepted && !openImage(dialog.selectedFiles().first())) {}
}

void MainWindow::slotActionCrop()
{
    QRect cropRegion = _rsview->highlightedRegion();
    if (cropRegion.isEmpty() ||
        cropRegion.size() == QSize(1,1)) {
        QMessageBox::warning(this, tr("No region selected"), tr("Please use mouse to select a region to crop."));
        return;
    }

    QSize size = cropRegion.size();
    updateImage(_currentImage.copy(cropRegion));

    _statusbar->showMessage(tr("Image cropped. New size: %1x%2").arg(size.width()).arg(size.height()));
}

void MainWindow::slotSelectionStarted()
{
    if (_colorsDock->isVisible()) {
        _colorsWidget->setSelectedColor();
    }
}

void MainWindow::slotMouseMove(const QPoint &pos)
{
    if (_colorsDock->isVisible()) {
        QColor color(_currentImage.pixel(pos));
        _colorsWidget->setCurrentColor(color);
    }
}

void MainWindow::slotAccentChanged()
{
    _rsview->setAccentPainter(createAccentPainter());
    update();
}

void MainWindow::slotAccentApplied()
{
    QPixmap pm = QPixmap::fromImage(_currentImage);
    QPainter painter(&pm);

    QSharedPointer<AccentPainter> accent = createAccentPainter();
    accent->paint(&painter, pm.rect(), _rsview->highlightedRegion());

    updateImage(pm.toImage());

    _statusbar->showMessage(tr("Selected accent applied."));
}

void MainWindow::slotBuildCompleted(QSharedPointer<CvModel> model)
{
    QSharedPointer<SnapAssistant> assistant(new CvSnapAssistant(model));
    _rsview->setSnapAssistant(assistant);
    _rsview->setCursor(Qt::CrossCursor);

    setCursor(Qt::ArrowCursor);

    enableDisableUi();
    show();
}

void MainWindow::handleDockWidgetVisibityChange(QDockWidget *dockWidget)
{
    if (dockWidget->isVisible()) {
        if (_colorsDock == dockWidget) {
            _accentDock->setVisible(false);
        }
        else {
            _colorsDock->setVisible(false);
            slotAccentChanged();
        }
    }
    else {
        if (dockWidget == _accentDock) {
            _rsview->setAccentPainter(createDefaultAccentPainter());
        }
    }
}

QSharedPointer<AccentPainter> MainWindow::createDefaultAccentPainter()
{
    return QSharedPointer<AccentPainter>(new SelectionAccentPainter(RegionColor, ShaderColor));
}

QSharedPointer<AccentPainter> MainWindow::createAccentPainter()
{
    QColor color = _accentWidget->accentColor();
    AccentPainter* accent = NULL;

    switch (_accentWidget->accentMode()) {
    case AccentWidget::Rectangle:
        accent = new RectangleAccentPainter(color, 3);
        break;
    case AccentWidget::Cinema:
        accent = new CinemaAccentPainter(color);
        break;
    case AccentWidget::Hatching:
        accent = new HatchingAccentPainter(color);
        break;
    default:
        qFatal("Unknown AccentMode");
    }

    return QSharedPointer<AccentPainter>(accent);
}

bool MainWindow::saveImage(const QString &fileName)
{
    QImageWriter writer(fileName);
    if (!writer.write(_currentImage)) {
        QMessageBox::information(this, QGuiApplication::applicationDisplayName(),
                                 tr("Cannot save %1: %2")
                                 .arg(QDir::toNativeSeparators(fileName)), writer.errorString());
        return false;
    }

    const QString message = tr("Saved \"%1\"").arg(QDir::toNativeSeparators(fileName));
    _statusbar->showMessage(message);

    return true;
}

bool MainWindow::openImage(const QString &fileName)
{
    QImageReader reader(fileName);
    QImage image = reader.read();
    if (image.isNull()) {
        return false;
    }

    const QString message = tr("Opened \"%1\"").arg(QDir::toNativeSeparators(fileName));
    _statusbar->showMessage(message);

    updateImage(image);
    return true;
}

void MainWindow::initializeImageFileDialog(QFileDialog &dialog, QFileDialog::AcceptMode acceptMode)
{
    static bool firstDialog = true;

    if (firstDialog) {
        firstDialog = false;
        const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
        dialog.setDirectory(picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.last());
    }

    QStringList mimeTypeFilters;
    const QByteArrayList supportedMimeTypes = acceptMode == QFileDialog::AcceptOpen
        ? QImageReader::supportedMimeTypes() : QImageWriter::supportedMimeTypes();
    foreach (const QByteArray &mimeTypeName, supportedMimeTypes)
        mimeTypeFilters.append(mimeTypeName);
    mimeTypeFilters.sort();
    dialog.setMimeTypeFilters(mimeTypeFilters);
    dialog.selectMimeTypeFilter("image/png");
    if (acceptMode == QFileDialog::AcceptSave) {
        dialog.setDefaultSuffix("png");
    }
}

void MainWindow::delay(int millisecondsToWait)
{
    QTime dieTime = QTime::currentTime().addMSecs(millisecondsToWait);
    while( QTime::currentTime() < dieTime ) {
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
    }
}

void MainWindow::updateImage(const QImage& image)
{
    setCursor(Qt::WaitCursor);

    if (image.format() != QImage::Format_RGBA8888) {
       _currentImage = image.convertToFormat(QImage::Format_RGBA8888);
    } else {
        _currentImage = image;
    }

    _rsview->setImage(_currentImage);
    _modelBuilder->buildAsync(_currentImage, CvModelBuilderOptions());
}

void MainWindow::updateImage(const QSharedPointer<RegionContext>& regionContext, bool bHighlightedRegion)
{
    setCursor(Qt::WaitCursor);

    QRect selectedRegion = regionContext->selectedRegion();
    QRect highlightedRegion = regionContext->highlightedRegion();
    if (selectedRegion.isEmpty() && highlightedRegion.isEmpty()) {
        return;
    }

    QRect cropRegion = (bHighlightedRegion) ? highlightedRegion : selectedRegion;

    QImage image = _currentImage.copy(cropRegion);
    if (image.format() != QImage::Format_RGBA8888) {
        _currentImage = image.convertToFormat(QImage::Format_RGBA8888);
    } else {
        _currentImage = image;
    }
    _rsview->setImage(_currentImage);

    if (!bHighlightedRegion) {
        // Moves the highlightedRegion
        highlightedRegion.translate(-selectedRegion.topLeft());

        QSharedPointer<RegionContext>& viewRegionContext = _rsview->getRegionContext();
        viewRegionContext->setSelectedRegion(image.rect());
        viewRegionContext->setHighlightedRegion(highlightedRegion);
        update();
    }

    _colorsWidget->clearColors();
    _modelBuilder->buildAsync(_currentImage, CvModelBuilderOptions());
}

void MainWindow::enableDisableUi()
{
    bool hasImage = !_currentImage.isNull();
    bool skipFirst = true;

    foreach (QAction* action, _toolbar->actions()) {
        if (skipFirst) {
            skipFirst = false;
            continue;
        }
        action->setEnabled(hasImage);
    }
}

void MainWindow::setupUi()
{
    // awesome font
    AwesomeService::create(this);
    _awesome = AwesomeService::awesome();

    // geometry & title
    setWindowTitle(tr("REVERSCREEN"));
    setMinimumSize(QSize(400, 300));

    // font
    QFont font;
    font.setFamily(QStringLiteral("Calibri"));
    font.setPointSize(10);
    setFont(font);

    setUnifiedTitleAndToolBarOnMac(true);

    // toolbar
    _toolbar = new QToolBar(this);
    _toolbar->setFont(font);
    _toolbar->setMovable(false);
    _toolbar->setFloatable(false);
    _toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    addToolBar(Qt::TopToolBarArea, _toolbar);

    // statusbar
    _statusbar = new QStatusBar(this);
    _statusbar->setFont(font);
    setStatusBar(_statusbar);
    _statusbar->showMessage(tr("Ready."));

    // actions
    _actionPaste = new QAction(_awesome->icon(fa::paste), tr("Paste from clipboard"), this);
    _actionPaste->setShortcut(QKeySequence("Ctrl+V"));
    _actionOpen = new QAction(_awesome->icon(fa::filepictureo), tr("Open image file..."), this);
    _actionOpen->setShortcut(QKeySequence("Ctrl+O"));
    _actionCopy = new QAction(_awesome->icon(fa::copy), tr("Copy"), this);
    _actionCopy->setShortcut(QKeySequence("Ctrl+C"));
    _actionSave = new QAction(_awesome->icon(fa::save), tr("Save..."), this);
    _actionSave->setShortcut(QKeySequence("Ctrl+S"));
    _actionCrop = new QAction(_awesome->icon(fa::crop), tr("Crop"), this);
    _actionCrop->setShortcut(QKeySequence("Ctrl+X"));

    connect(_actionPaste, &QAction::triggered, this, &MainWindow::slotActionPaste);
    connect(_actionOpen, &QAction::triggered, this, &MainWindow::slotActionOpen);
    connect(_actionCopy, &QAction::triggered, this, &MainWindow::slotActionCopy);
    connect(_actionSave, &QAction::triggered, this, &MainWindow::slotActionSave);
    connect(_actionCrop, &QAction::triggered, this, &MainWindow::slotActionCrop);

    // central widget
    _scrollArea = new QScrollArea(this);
    _scrollArea->setBackgroundRole(QPalette::BrightText);
    _scrollArea->setAlignment(Qt::AlignCenter);
    _scrollArea->setFrameStyle(QFrame::NoFrame);

    _scrollArea->viewport()->installEventFilter(this);

    _rsview = new RsView(_scrollArea, false);
    _rsview->setAccentPainter(createDefaultAccentPainter());
    connect(_rsview, &RsView::signalSelectionStarted, this, &MainWindow::slotSelectionStarted);
    connect(_rsview, &RsView::signalMouseMove, this, &MainWindow::slotMouseMove);

    _scrollArea->setWidget(_rsview);

    setCentralWidget(_scrollArea);

    // docked widgets
    _colorsDock = new QDockWidget(tr("Colors"), this);
    _colorsWidget = new ColorsWidget(_colorsDock);
    setupDockWidget(_colorsDock, _awesome->icon(fa::eyedropper), _colorsWidget);

    _accentDock = new QDockWidget(tr("Accent"), this);
    _accentWidget = new AccentWidget(_accentDock);
    connect(_accentWidget, &AccentWidget::signalAccentChanged, this, &MainWindow::slotAccentChanged);
    connect(_accentWidget, &AccentWidget::signalAccentApplied, this, &MainWindow::slotAccentApplied);
    setupDockWidget(_accentDock, _awesome->icon(fa::lightbulbo), _accentWidget);

    // combo actions
    QMenu *newMenu = new QMenu(tr("Screenshot"));
    newMenu->menuAction()->setIcon(_awesome->icon(fa::cameraretro));
    newMenu->menuAction()->setShortcut(QKeySequence("Ctrl+N"));
    connect(newMenu->menuAction(), &QAction::triggered, this, &MainWindow::slotActionScreenshot);
    newMenu->addAction(_actionPaste);
    newMenu->addAction(_actionOpen);

    // toolbar
    _toolbar->addAction(newMenu->menuAction());
    _toolbar->addAction(_actionCopy);
    _toolbar->addAction(_actionSave);
    _toolbar->insertSeparator(0);
    _toolbar->addAction(_actionCrop);
    _toolbar->addAction(_colorsDock->toggleViewAction());
    // _toolbar->addAction(_accentDock->toggleViewAction());

    WidgetUtils::centerWindow(this);
}

void MainWindow::setupDockWidget(QDockWidget *dockWidget, QIcon icon, QWidget *contentWidget)
{
    dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
    dockWidget->setVisible(false);
    dockWidget->setWidget(contentWidget);
    dockWidget->toggleViewAction()->setIcon(icon);

    addDockWidget(Qt::RightDockWidgetArea, dockWidget);
    connect(dockWidget, &QDockWidget::visibilityChanged, this, [this, dockWidget]() { handleDockWidgetVisibityChange(dockWidget); });
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == _scrollArea->viewport()){
        if (event->type() == QEvent::Wheel) {
            QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
            wheelEvent->ignore();
            return true;
        }
    }
    return QMainWindow::eventFilter(obj, event);
}
<commit_msg>Fixed Save/Open dialog accept mode<commit_after>#include <QMessageBox>
#include <QImage>
#include <QScreen>
#include <QClipboard>
#include <QImageWriter>
#include <QImageReader>
#include <QDir>
#include <QStandardPaths>
#include <QStyle>
#include <QTime>
#include <QGuiApplication>
#include <QApplication>
#include <QLabel>
#include <QSharedPointer>
#include <QListWidget>
#include <QBitmap>
#include <QMenu>
#include <QDesktopWidget>
#include <QDebug>

#include "awesomeservice.h"
#include "mainwindow.h"
#include "rsview.h"
#include "dock/colorswidget.h"
#include "dock/accentwidget.h"
#include "fullscreenselectiondialog.h"
#include "assistant/cvsnapassistant.h"
#include "accent/selectionaccentpainter.h"
#include "accent/rectangleaccentpainter.h"
#include "accent/cinemaaccentpainter.h"
#include "accent/hatchingaccentpainter.h"
#include "widgetutils.h"
#include "cv/cvmodelbuilder.h"

static const QColor RegionColor = Qt::red;
static const QColor ShaderColor = QColor::fromRgba(0x50a0a0a0);

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , _modelBuilder(new CvModelBuilder(this))
{
    connect(_modelBuilder, &CvModelBuilder::signalBuildCompleted, this, &MainWindow::slotBuildCompleted);

    setupUi();
    enableDisableUi();
}

void MainWindow::slotActionScreenshot()
{
    hide();
    delay(300);

    QScreen *screen = QGuiApplication::primaryScreen();
    _currentImage = screen->grabWindow(QApplication::desktop()->winId()).toImage();

    FullscreenSelectionDialog dialog(this, _currentImage, createDefaultAccentPainter());
    if (dialog.exec() == QDialog::Accepted) {
        updateImage(dialog.getRegionContext(), dialog.usedHighlightedRegion());

        _statusbar->showMessage(tr("A screen region is captured."));
    }

    show();
}

void MainWindow::slotActionPaste()
{
    QClipboard *clipboard = QApplication::clipboard();
    QImage image = clipboard->image();
    if (image.isNull()) {
        _statusbar->showMessage(tr("Clipboard has no image."));
    }
    else {
        updateImage(image);
    }
}

void MainWindow::slotActionCopy()
{
    QClipboard *clipboard = QApplication::clipboard();
    clipboard->setImage(_currentImage);

    _statusbar->showMessage(tr("Copied to the clipboard."));
}

void MainWindow::slotActionSave()
{
    QFileDialog dialog(this, tr("Save Image As"));
    initializeImageFileDialog(dialog, QFileDialog::AcceptSave);

    while (dialog.exec() == QDialog::Accepted && !saveImage(dialog.selectedFiles().first())) {}
}

void MainWindow::slotActionOpen()
{
    QFileDialog dialog(this, tr("Open Image"));
    initializeImageFileDialog(dialog, QFileDialog::AcceptOpen);

    while (dialog.exec() == QDialog::Accepted && !openImage(dialog.selectedFiles().first())) {}
}

void MainWindow::slotActionCrop()
{
    QRect cropRegion = _rsview->highlightedRegion();
    if (cropRegion.isEmpty() ||
        cropRegion.size() == QSize(1,1)) {
        QMessageBox::warning(this, tr("No region selected"), tr("Please use mouse to select a region to crop."));
        return;
    }

    QSize size = cropRegion.size();
    updateImage(_currentImage.copy(cropRegion));

    _statusbar->showMessage(tr("Image cropped. New size: %1x%2").arg(size.width()).arg(size.height()));
}

void MainWindow::slotSelectionStarted()
{
    if (_colorsDock->isVisible()) {
        _colorsWidget->setSelectedColor();
    }
}

void MainWindow::slotMouseMove(const QPoint &pos)
{
    if (_colorsDock->isVisible()) {
        QColor color(_currentImage.pixel(pos));
        _colorsWidget->setCurrentColor(color);
    }
}

void MainWindow::slotAccentChanged()
{
    _rsview->setAccentPainter(createAccentPainter());
    update();
}

void MainWindow::slotAccentApplied()
{
    QPixmap pm = QPixmap::fromImage(_currentImage);
    QPainter painter(&pm);

    QSharedPointer<AccentPainter> accent = createAccentPainter();
    accent->paint(&painter, pm.rect(), _rsview->highlightedRegion());

    updateImage(pm.toImage());

    _statusbar->showMessage(tr("Selected accent applied."));
}

void MainWindow::slotBuildCompleted(QSharedPointer<CvModel> model)
{
    QSharedPointer<SnapAssistant> assistant(new CvSnapAssistant(model));
    _rsview->setSnapAssistant(assistant);
    _rsview->setCursor(Qt::CrossCursor);

    setCursor(Qt::ArrowCursor);

    enableDisableUi();
    show();
}

void MainWindow::handleDockWidgetVisibityChange(QDockWidget *dockWidget)
{
    if (dockWidget->isVisible()) {
        if (_colorsDock == dockWidget) {
            _accentDock->setVisible(false);
        }
        else {
            _colorsDock->setVisible(false);
            slotAccentChanged();
        }
    }
    else {
        if (dockWidget == _accentDock) {
            _rsview->setAccentPainter(createDefaultAccentPainter());
        }
    }
}

QSharedPointer<AccentPainter> MainWindow::createDefaultAccentPainter()
{
    return QSharedPointer<AccentPainter>(new SelectionAccentPainter(RegionColor, ShaderColor));
}

QSharedPointer<AccentPainter> MainWindow::createAccentPainter()
{
    QColor color = _accentWidget->accentColor();
    AccentPainter* accent = NULL;

    switch (_accentWidget->accentMode()) {
    case AccentWidget::Rectangle:
        accent = new RectangleAccentPainter(color, 3);
        break;
    case AccentWidget::Cinema:
        accent = new CinemaAccentPainter(color);
        break;
    case AccentWidget::Hatching:
        accent = new HatchingAccentPainter(color);
        break;
    default:
        qFatal("Unknown AccentMode");
    }

    return QSharedPointer<AccentPainter>(accent);
}

bool MainWindow::saveImage(const QString &fileName)
{
    QImageWriter writer(fileName);
    if (!writer.write(_currentImage)) {
        QMessageBox::information(this, QGuiApplication::applicationDisplayName(),
                                 tr("Cannot save %1: %2")
                                 .arg(QDir::toNativeSeparators(fileName)), writer.errorString());
        return false;
    }

    const QString message = tr("Saved \"%1\"").arg(QDir::toNativeSeparators(fileName));
    _statusbar->showMessage(message);

    return true;
}

bool MainWindow::openImage(const QString &fileName)
{
    QImageReader reader(fileName);
    QImage image = reader.read();
    if (image.isNull()) {
        return false;
    }

    const QString message = tr("Opened \"%1\"").arg(QDir::toNativeSeparators(fileName));
    _statusbar->showMessage(message);

    updateImage(image);
    return true;
}

void MainWindow::initializeImageFileDialog(QFileDialog &dialog, QFileDialog::AcceptMode acceptMode)
{
    static bool firstDialog = true;

    if (firstDialog) {
        firstDialog = false;
        const QStringList picturesLocations = QStandardPaths::standardLocations(QStandardPaths::PicturesLocation);
        dialog.setDirectory(picturesLocations.isEmpty() ? QDir::currentPath() : picturesLocations.last());
    }

    QStringList mimeTypeFilters;
    const QByteArrayList supportedMimeTypes = acceptMode == QFileDialog::AcceptOpen
        ? QImageReader::supportedMimeTypes() : QImageWriter::supportedMimeTypes();
    foreach (const QByteArray &mimeTypeName, supportedMimeTypes)
        mimeTypeFilters.append(mimeTypeName);
    mimeTypeFilters.sort();
    dialog.setMimeTypeFilters(mimeTypeFilters);
    dialog.selectMimeTypeFilter("image/png");
    if (acceptMode == QFileDialog::AcceptSave) {
        dialog.setDefaultSuffix("png");
    }

    dialog.setAcceptMode(acceptMode);
}

void MainWindow::delay(int millisecondsToWait)
{
    QTime dieTime = QTime::currentTime().addMSecs(millisecondsToWait);
    while( QTime::currentTime() < dieTime ) {
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
    }
}

void MainWindow::updateImage(const QImage& image)
{
    setCursor(Qt::WaitCursor);

    if (image.format() != QImage::Format_RGBA8888) {
       _currentImage = image.convertToFormat(QImage::Format_RGBA8888);
    } else {
        _currentImage = image;
    }

    _rsview->setImage(_currentImage);
    _modelBuilder->buildAsync(_currentImage, CvModelBuilderOptions());
}

void MainWindow::updateImage(const QSharedPointer<RegionContext>& regionContext, bool bHighlightedRegion)
{
    setCursor(Qt::WaitCursor);

    QRect selectedRegion = regionContext->selectedRegion();
    QRect highlightedRegion = regionContext->highlightedRegion();
    if (selectedRegion.isEmpty() && highlightedRegion.isEmpty()) {
        return;
    }

    QRect cropRegion = (bHighlightedRegion) ? highlightedRegion : selectedRegion;

    QImage image = _currentImage.copy(cropRegion);
    if (image.format() != QImage::Format_RGBA8888) {
        _currentImage = image.convertToFormat(QImage::Format_RGBA8888);
    } else {
        _currentImage = image;
    }
    _rsview->setImage(_currentImage);

    if (!bHighlightedRegion) {
        // Moves the highlightedRegion
        highlightedRegion.translate(-selectedRegion.topLeft());

        QSharedPointer<RegionContext>& viewRegionContext = _rsview->getRegionContext();
        viewRegionContext->setSelectedRegion(image.rect());
        viewRegionContext->setHighlightedRegion(highlightedRegion);
        update();
    }

    _colorsWidget->clearColors();
    _modelBuilder->buildAsync(_currentImage, CvModelBuilderOptions());
}

void MainWindow::enableDisableUi()
{
    bool hasImage = !_currentImage.isNull();
    bool skipFirst = true;

    foreach (QAction* action, _toolbar->actions()) {
        if (skipFirst) {
            skipFirst = false;
            continue;
        }
        action->setEnabled(hasImage);
    }
}

void MainWindow::setupUi()
{
    // awesome font
    AwesomeService::create(this);
    _awesome = AwesomeService::awesome();

    // geometry & title
    setWindowTitle(tr("REVERSCREEN"));
    setMinimumSize(QSize(400, 300));

    // font
    QFont font;
    font.setFamily(QStringLiteral("Calibri"));
    font.setPointSize(10);
    setFont(font);

    setUnifiedTitleAndToolBarOnMac(true);

    // toolbar
    _toolbar = new QToolBar(this);
    _toolbar->setFont(font);
    _toolbar->setMovable(false);
    _toolbar->setFloatable(false);
    _toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    addToolBar(Qt::TopToolBarArea, _toolbar);

    // statusbar
    _statusbar = new QStatusBar(this);
    _statusbar->setFont(font);
    setStatusBar(_statusbar);
    _statusbar->showMessage(tr("Ready."));

    // actions
    _actionPaste = new QAction(_awesome->icon(fa::paste), tr("Paste from clipboard"), this);
    _actionPaste->setShortcut(QKeySequence("Ctrl+V"));
    _actionOpen = new QAction(_awesome->icon(fa::filepictureo), tr("Open image file..."), this);
    _actionOpen->setShortcut(QKeySequence("Ctrl+O"));
    _actionCopy = new QAction(_awesome->icon(fa::copy), tr("Copy"), this);
    _actionCopy->setShortcut(QKeySequence("Ctrl+C"));
    _actionSave = new QAction(_awesome->icon(fa::save), tr("Save..."), this);
    _actionSave->setShortcut(QKeySequence("Ctrl+S"));
    _actionCrop = new QAction(_awesome->icon(fa::crop), tr("Crop"), this);
    _actionCrop->setShortcut(QKeySequence("Ctrl+X"));

    connect(_actionPaste, &QAction::triggered, this, &MainWindow::slotActionPaste);
    connect(_actionOpen, &QAction::triggered, this, &MainWindow::slotActionOpen);
    connect(_actionCopy, &QAction::triggered, this, &MainWindow::slotActionCopy);
    connect(_actionSave, &QAction::triggered, this, &MainWindow::slotActionSave);
    connect(_actionCrop, &QAction::triggered, this, &MainWindow::slotActionCrop);

    // central widget
    _scrollArea = new QScrollArea(this);
    _scrollArea->setBackgroundRole(QPalette::BrightText);
    _scrollArea->setAlignment(Qt::AlignCenter);
    _scrollArea->setFrameStyle(QFrame::NoFrame);

    _scrollArea->viewport()->installEventFilter(this);

    _rsview = new RsView(_scrollArea, false);
    _rsview->setAccentPainter(createDefaultAccentPainter());
    connect(_rsview, &RsView::signalSelectionStarted, this, &MainWindow::slotSelectionStarted);
    connect(_rsview, &RsView::signalMouseMove, this, &MainWindow::slotMouseMove);

    _scrollArea->setWidget(_rsview);

    setCentralWidget(_scrollArea);

    // docked widgets
    _colorsDock = new QDockWidget(tr("Colors"), this);
    _colorsWidget = new ColorsWidget(_colorsDock);
    setupDockWidget(_colorsDock, _awesome->icon(fa::eyedropper), _colorsWidget);

    _accentDock = new QDockWidget(tr("Accent"), this);
    _accentWidget = new AccentWidget(_accentDock);
    connect(_accentWidget, &AccentWidget::signalAccentChanged, this, &MainWindow::slotAccentChanged);
    connect(_accentWidget, &AccentWidget::signalAccentApplied, this, &MainWindow::slotAccentApplied);
    setupDockWidget(_accentDock, _awesome->icon(fa::lightbulbo), _accentWidget);

    // combo actions
    QMenu *newMenu = new QMenu(tr("Screenshot"));
    newMenu->menuAction()->setIcon(_awesome->icon(fa::cameraretro));
    newMenu->menuAction()->setShortcut(QKeySequence("Ctrl+N"));
    connect(newMenu->menuAction(), &QAction::triggered, this, &MainWindow::slotActionScreenshot);
    newMenu->addAction(_actionPaste);
    newMenu->addAction(_actionOpen);

    // toolbar
    _toolbar->addAction(newMenu->menuAction());
    _toolbar->addAction(_actionCopy);
    _toolbar->addAction(_actionSave);
    _toolbar->insertSeparator(0);
    _toolbar->addAction(_actionCrop);
    _toolbar->addAction(_colorsDock->toggleViewAction());
    // _toolbar->addAction(_accentDock->toggleViewAction());

    WidgetUtils::centerWindow(this);
}

void MainWindow::setupDockWidget(QDockWidget *dockWidget, QIcon icon, QWidget *contentWidget)
{
    dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
    dockWidget->setVisible(false);
    dockWidget->setWidget(contentWidget);
    dockWidget->toggleViewAction()->setIcon(icon);

    addDockWidget(Qt::RightDockWidgetArea, dockWidget);
    connect(dockWidget, &QDockWidget::visibilityChanged, this, [this, dockWidget]() { handleDockWidgetVisibityChange(dockWidget); });
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == _scrollArea->viewport()){
        if (event->type() == QEvent::Wheel) {
            QWheelEvent *wheelEvent = static_cast<QWheelEvent*>(event);
            wheelEvent->ignore();
            return true;
        }
    }
    return QMainWindow::eventFilter(obj, event);
}
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    db_ = new SQLiteDB(":/dbschema.json", this);
    hp_ = new HashPool(db_,this);
    tp_ = new TagPool(db_,this);
    rp_ = new RankPool(db_, hp_,this);

    // ui::menu
    createActions();
    createMenus();

    // ui: File explorer
    FSmixDBmodel *fmixd_;
    fmixd_ = new FSmixDBmodel(hp_, rp_, this);
    fmixd_->setRootPath(QDir::rootPath());
    fmixd_->setFilter(QDir::Files);
    fmixd_->setNameFilters(QStringList()
                                 << "*.zip"
                                 << "*.cb?"
                                 << "*.rar");
    fmixd_->setNameFilterDisables(false);
//    fmixd_->setReadOnly(false);
    file_exp_widget_ = new FileExplorer(fmixd_, this);
    ui->topTabWidget->addTab(file_exp_widget_, "&Explorer");

    connect(this, SIGNAL(sigStatusMsg(QString, int)),
            ui->statusBar, SLOT(showMessage(QString,int)));

    // ui: tags
    FileTagsWidget *w = new FileTagsWidget(tp_,this);
    ui->centralWidget->layout()->addWidget(w);
    connect(file_exp_widget_, SIGNAL(sigFilePath(QString)),
            w, SLOT(setFileName(QString)));
    connect(file_exp_widget_, SIGNAL(sigFileNameSelected(bool)),
            w, SLOT(setVisible(bool)));

    // ui: Library ( DB ) View
    connect(db_, SIGNAL(sigOpened()), this, SLOT(loadDBTabs()));
    connect(db_, SIGNAL(sigOpened(bool)), closeAct, SLOT(setEnabled(bool)));
    connect(db_, SIGNAL(sigOpened(bool)), dbManAct, SLOT(setEnabled(bool)));
    connect(db_, SIGNAL(sigOpened(bool)), tags2DBAct, SLOT(setEnabled(bool)));
    connect(db_, SIGNAL(sigClosed()), this, SLOT(removeDBTabs()));
    connect(db_, SIGNAL(sigClosed(bool)), closeAct, SLOT(setDisabled(bool)));
    connect(db_, SIGNAL(sigClosed(bool)), dbManAct, SLOT(setDisabled(bool)));
    connect(db_, SIGNAL(sigClosed(bool)), tags2DBAct, SLOT(setDisabled(bool)));

    // auto open "~/mangalib.db"
    if( QFile::exists(QDir::homePath() + "/mangalib.db")){
        db_->open(QDir::homePath() + "/mangalib.db");
    }
}

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

void MainWindow::openDBfile(QString fn)
{
    if ( fn.isEmpty() ){
        QString selfilter = tr("DB Files (*.db)");
        fn = QFileDialog::getSaveFileName( this,
                                              tr("Choose DB file"),
                                              QDir::homePath(),
                                              tr("DB Files (*.db)"),
                                              &selfilter,
                                              QFileDialog::DontConfirmOverwrite );
    }

    if (!fn.isEmpty()){
        db_->open(fn);
    } else {
        emit sigStatusMsg(tr("no file selected."));
    }
}

void MainWindow::closeDBconnection()
{
    db_->closeDB();
}

void MainWindow::loadDBTabs()
{
    QStringList dbtables = db_->tables();
    QStringList tables, filter;
    filter << "file" << "tag" << "book" << "author";
    for (int i = 0; i < filter.size(); ++i){
        if (dbtables.contains(filter.at(i))){
            tables.append(filter.at(i));
        }
    }
    for( int i = 0; i < tables.size(); ++i){
        DBTableWidget* w = new DBTableWidget(tables.at(i),
                                               db_->conn(),
                                               ui->topTabWidget);

        QString tname = QString("( &") + QString::number(i+1) + " ) "
                        + tables.at(i);
        int tabIndex = ui->topTabWidget->addTab(w,tname);
        db_table_widgets_hash_.insert(w,tabIndex);
    }
}

void MainWindow::removeDBTabs()
{
    QHash<DBTableWidget*,int>::iterator iter;
    for (iter = db_table_widgets_hash_.begin(); iter != db_table_widgets_hash_.end(); ++iter){
        ui->topTabWidget->removeTab(iter.value());
        iter.key()->deleteLater();
    }
    db_table_widgets_hash_.clear();
}

void MainWindow::openDBManager()
{
    DBManager *w = new DBManager(db_, this);
    connect(w, SIGNAL(finished(int)), w, SLOT(deleteLater()));
    w->showMaximized();
}

void MainWindow::saveLocalFileInfo()
{
//    QSqlQuery q(db_);

}

void MainWindow::createActions()
{
    openAct = new QAction(tr("&Open Sqlite DB file"), this);
    openAct->setShortcuts(QKeySequence::Open);
    openAct->setStatusTip(tr("Choose and open a Sqlite DB file"));
    connect(openAct, SIGNAL(triggered()), this, SLOT(openDBfile()));

    closeAct = new QAction(tr("&Close DB connection"), this);
    closeAct->setShortcut(QKeySequence::Close);
    closeAct->setStatusTip(tr("Close current DB connection"));
    connect(closeAct, SIGNAL(triggered()), this, SLOT(closeDBconnection()));

    quitAct = new QAction(tr("&Quit"), this);
    quitAct->setShortcuts(QKeySequence::Quit);
    quitAct->setStatusTip(tr("Quit application"));
    connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));

    dbManAct = new QAction(tr("DB &Manager"), this);
    dbManAct->setStatusTip(tr("Open DB Manager"));
    connect(dbManAct, SIGNAL(triggered()), this, SLOT(openDBManager()));

    tags2DBAct = new QAction(tr("insert &Tags to DB tables"), this);
    tags2DBAct->setStatusTip(tr("insert Tags to DB tables, where tag type = table name."));
    connect(tags2DBAct, SIGNAL(triggered()), tp_, SLOT(insertTags2Table()));
}

void MainWindow::createMenus()
{
    DBMenu = menuBar()->addMenu(tr("&Database"));
    DBMenu->addAction(openAct);
    DBMenu->addAction(closeAct);
    DBMenu->addSeparator();
    DBMenu->addAction(dbManAct);
    DBMenu->addSeparator();
    DBMenu->addAction(tags2DBAct);
    DBMenu->addAction(quitAct);
}
<commit_msg>hide file tags widget on start up.<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    db_ = new SQLiteDB(":/dbschema.json", this);
    hp_ = new HashPool(db_,this);
    tp_ = new TagPool(db_,this);
    rp_ = new RankPool(db_, hp_,this);

    // ui::menu
    createActions();
    createMenus();

    // ui: File explorer
    FSmixDBmodel *fmixd_;
    fmixd_ = new FSmixDBmodel(hp_, rp_, this);
    fmixd_->setRootPath(QDir::rootPath());
    fmixd_->setFilter(QDir::Files);
    fmixd_->setNameFilters(QStringList()
                                 << "*.zip"
                                 << "*.cb?"
                                 << "*.rar");
    fmixd_->setNameFilterDisables(false);
//    fmixd_->setReadOnly(false);
    file_exp_widget_ = new FileExplorer(fmixd_, this);
    ui->topTabWidget->addTab(file_exp_widget_, "&Explorer");

    connect(this, SIGNAL(sigStatusMsg(QString, int)),
            ui->statusBar, SLOT(showMessage(QString,int)));

    // ui: tags
    FileTagsWidget *w = new FileTagsWidget(tp_,this);
    w->hide();
    ui->centralWidget->layout()->addWidget(w);
    connect(file_exp_widget_, SIGNAL(sigFilePath(QString)),
            w, SLOT(setFileName(QString)));
    connect(file_exp_widget_, SIGNAL(sigFileNameSelected(bool)),
            w, SLOT(setVisible(bool)));

    // ui: Library ( DB ) View
    connect(db_, SIGNAL(sigOpened()), this, SLOT(loadDBTabs()));
    connect(db_, SIGNAL(sigOpened(bool)), closeAct, SLOT(setEnabled(bool)));
    connect(db_, SIGNAL(sigOpened(bool)), dbManAct, SLOT(setEnabled(bool)));
    connect(db_, SIGNAL(sigOpened(bool)), tags2DBAct, SLOT(setEnabled(bool)));
    connect(db_, SIGNAL(sigClosed()), this, SLOT(removeDBTabs()));
    connect(db_, SIGNAL(sigClosed(bool)), closeAct, SLOT(setDisabled(bool)));
    connect(db_, SIGNAL(sigClosed(bool)), dbManAct, SLOT(setDisabled(bool)));
    connect(db_, SIGNAL(sigClosed(bool)), tags2DBAct, SLOT(setDisabled(bool)));

    // auto open "~/mangalib.db"
    if( QFile::exists(QDir::homePath() + "/mangalib.db")){
        db_->open(QDir::homePath() + "/mangalib.db");
    }
}

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

void MainWindow::openDBfile(QString fn)
{
    if ( fn.isEmpty() ){
        QString selfilter = tr("DB Files (*.db)");
        fn = QFileDialog::getSaveFileName( this,
                                              tr("Choose DB file"),
                                              QDir::homePath(),
                                              tr("DB Files (*.db)"),
                                              &selfilter,
                                              QFileDialog::DontConfirmOverwrite );
    }

    if (!fn.isEmpty()){
        db_->open(fn);
    } else {
        emit sigStatusMsg(tr("no file selected."));
    }
}

void MainWindow::closeDBconnection()
{
    db_->closeDB();
}

void MainWindow::loadDBTabs()
{
    QStringList dbtables = db_->tables();
    QStringList tables, filter;
    filter << "file" << "tag" << "book" << "author";
    for (int i = 0; i < filter.size(); ++i){
        if (dbtables.contains(filter.at(i))){
            tables.append(filter.at(i));
        }
    }
    for( int i = 0; i < tables.size(); ++i){
        DBTableWidget* w = new DBTableWidget(tables.at(i),
                                               db_->conn(),
                                               ui->topTabWidget);

        QString tname = QString("( &") + QString::number(i+1) + " ) "
                        + tables.at(i);
        int tabIndex = ui->topTabWidget->addTab(w,tname);
        db_table_widgets_hash_.insert(w,tabIndex);
    }
}

void MainWindow::removeDBTabs()
{
    QHash<DBTableWidget*,int>::iterator iter;
    for (iter = db_table_widgets_hash_.begin(); iter != db_table_widgets_hash_.end(); ++iter){
        ui->topTabWidget->removeTab(iter.value());
        iter.key()->deleteLater();
    }
    db_table_widgets_hash_.clear();
}

void MainWindow::openDBManager()
{
    DBManager *w = new DBManager(db_, this);
    connect(w, SIGNAL(finished(int)), w, SLOT(deleteLater()));
    w->showMaximized();
}

void MainWindow::saveLocalFileInfo()
{
//    QSqlQuery q(db_);

}

void MainWindow::createActions()
{
    openAct = new QAction(tr("&Open Sqlite DB file"), this);
    openAct->setShortcuts(QKeySequence::Open);
    openAct->setStatusTip(tr("Choose and open a Sqlite DB file"));
    connect(openAct, SIGNAL(triggered()), this, SLOT(openDBfile()));

    closeAct = new QAction(tr("&Close DB connection"), this);
    closeAct->setShortcut(QKeySequence::Close);
    closeAct->setStatusTip(tr("Close current DB connection"));
    connect(closeAct, SIGNAL(triggered()), this, SLOT(closeDBconnection()));

    quitAct = new QAction(tr("&Quit"), this);
    quitAct->setShortcuts(QKeySequence::Quit);
    quitAct->setStatusTip(tr("Quit application"));
    connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));

    dbManAct = new QAction(tr("DB &Manager"), this);
    dbManAct->setStatusTip(tr("Open DB Manager"));
    connect(dbManAct, SIGNAL(triggered()), this, SLOT(openDBManager()));

    tags2DBAct = new QAction(tr("insert &Tags to DB tables"), this);
    tags2DBAct->setStatusTip(tr("insert Tags to DB tables, where tag type = table name."));
    connect(tags2DBAct, SIGNAL(triggered()), tp_, SLOT(insertTags2Table()));
}

void MainWindow::createMenus()
{
    DBMenu = menuBar()->addMenu(tr("&Database"));
    DBMenu->addAction(openAct);
    DBMenu->addAction(closeAct);
    DBMenu->addSeparator();
    DBMenu->addAction(dbManAct);
    DBMenu->addSeparator();
    DBMenu->addAction(tags2DBAct);
    DBMenu->addAction(quitAct);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>

#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>

#define KwmDaemonPort 3020

int KwmcSockFD;

void Fatal(const std::string &err)
{
    std::cout << err << std::endl;
    exit(1);
}

std::string ReadFromSocket(int SockFD)
{
    std::string Message;
    char Cur;

    while(recv(SockFD, &Cur, 1, 0))
        Message += Cur;

    return Message;
}

void KwmcForwardMessageThroughSocket(std::string Msg)
{
    Msg += "\n";
    send(KwmcSockFD, Msg.c_str(), Msg.size(), 0);
    std::cout << ReadFromSocket(KwmcSockFD) << std::endl;
}

void KwmcConnectToDaemon()
{
    struct sockaddr_in srv_addr;
    struct hostent *server;

    if((KwmcSockFD = socket(PF_INET, SOCK_STREAM, 0)) == -1)
        Fatal("Could not create socket!");

    server = gethostbyname("localhost");
    srv_addr.sin_family = AF_INET;
    srv_addr.sin_port = htons(KwmDaemonPort);
    std::memcpy(&srv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
    std::memset(&srv_addr.sin_zero, '\0', 8);

    if(connect(KwmcSockFD, (struct sockaddr*) &srv_addr, sizeof(struct sockaddr)) == -1)
        Fatal("Connection failed! Make sure the YTD server is running...");
}

int main(int argc, char **argv)
{
    if(argc == 2)
    {
        KwmcConnectToDaemon();
        KwmcForwardMessageThroughSocket(argv[1]);
        close(KwmcSockFD);
    }
    else
    {
        std::cout << "Usage: kwmc <command>" << std::endl;
    }

    return 0;
}
<commit_msg>correct error message should be returned if connection fails<commit_after>#include <iostream>
#include <string>

#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>

#define KwmDaemonPort 3020

int KwmcSockFD;

void Fatal(const std::string &err)
{
    std::cout << err << std::endl;
    exit(1);
}

std::string ReadFromSocket(int SockFD)
{
    std::string Message;
    char Cur;

    while(recv(SockFD, &Cur, 1, 0))
        Message += Cur;

    return Message;
}

void KwmcForwardMessageThroughSocket(std::string Msg)
{
    Msg += "\n";
    send(KwmcSockFD, Msg.c_str(), Msg.size(), 0);
    std::cout << ReadFromSocket(KwmcSockFD) << std::endl;
}

void KwmcConnectToDaemon()
{
    struct sockaddr_in srv_addr;
    struct hostent *server;

    if((KwmcSockFD = socket(PF_INET, SOCK_STREAM, 0)) == -1)
        Fatal("Could not create socket!");

    server = gethostbyname("localhost");
    srv_addr.sin_family = AF_INET;
    srv_addr.sin_port = htons(KwmDaemonPort);
    std::memcpy(&srv_addr.sin_addr.s_addr, server->h_addr, server->h_length);
    std::memset(&srv_addr.sin_zero, '\0', 8);

    if(connect(KwmcSockFD, (struct sockaddr*) &srv_addr, sizeof(struct sockaddr)) == -1)
        Fatal("Connection failed! Make sure the Kwm daemon is running...");
}

int main(int argc, char **argv)
{
    if(argc == 2)
    {
        KwmcConnectToDaemon();
        KwmcForwardMessageThroughSocket(argv[1]);
        close(KwmcSockFD);
    }
    else
    {
        std::cout << "Usage: kwmc <command>" << std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include <vector>
#include <cmath>

#include "ingameelements/character.h"
#include "gamestate.h"
#include "ingameelements/movingentity.h"
#include "ingameelements/player.h"
#include "global_constants.h"
#include "engine.h"
#include "ingameelements/weapon.h"

Character::Character(uint64_t id_, Gamestate *state, EntityPtr owner_, CharacterChildParameters parameters) : MovingEntity(id_, state),
            owner(owner_), weapon(parameters.weapon), hp(parameters.maxhp), hpdir(-1), isflipped(false), runanim(parameters.characterfolder+"run/"),
            crouchanim(parameters.characterfolder+"crouchwalk/"), pressed_keys(), held_keys(), lastdirectionpressed(0)
{
    acceleration = 300;
    runpower = parameters.runpower;
    // friction factor per second of null movement; calculated directly from Gang Garrison 2
    // from pygg2
    friction = 0.01510305449388463132584804061124;
}

void Character::setinput(Gamestate *state, INPUT_CONTAINER pressed_keys_, INPUT_CONTAINER held_keys_, double mouse_x_, double mouse_y_)
{
    pressed_keys = pressed_keys_;
    held_keys = held_keys_;
    mouse_x = mouse_x_;
    mouse_y = mouse_y_;
    Weapon *w = state->get<Weapon>(weapon);
    w->setaim(mouse_x, mouse_y);
}

void Character::beginstep(Gamestate *state, double frametime)
{
    state->get<Weapon>(weapon)->beginstep(state, frametime);
}

void Character::midstep(Gamestate *state, double frametime)
{
    if (cangetinput(state))
    {
        double maxhspeed;
        if (crouchanim.active())
        {
            maxhspeed = 60.0;
        }
        else
        {
            maxhspeed = 153.0;
        }

        if (pressed_keys.LEFT)
        {
            lastdirectionpressed = LEFT;
        }
        else if (lastdirectionpressed == LEFT and not held_keys.LEFT)
        {
            lastdirectionpressed = RIGHT*held_keys.RIGHT;
        }
        if (pressed_keys.RIGHT)
        {
            lastdirectionpressed = RIGHT;
        }
        else if (lastdirectionpressed == RIGHT and not held_keys.RIGHT)
        {
            lastdirectionpressed = LEFT*held_keys.LEFT;
        }

        if (lastdirectionpressed == LEFT)
        {
            hspeed = std::max(hspeed - acceleration * runpower * frametime, -maxhspeed);
        }
        else if (lastdirectionpressed == RIGHT)
        {
            hspeed = std::min(hspeed + acceleration * runpower * frametime, maxhspeed);
        }

        if (pressed_keys.JUMP)
        {
            if (onground(state))
            {
                vspeed = -240.0;
            }
        }
        if (held_keys.CROUCH)
        {
            if (not crouchanim.active())
            {
                crouchanim.active(true);
                crouchanim.reset();
            }
        }
        else if (crouchanim.active())
        {
            // We're crouched and we'd like to uncrouch
            // Do so only if we have the room
            if (not state->currentmap->collides(getstandingcollisionrect(state)))
            {
                crouchanim.active(false);
            }
        }

        if (held_keys.RELOAD)
        {
            Weapon *w = state->get<Weapon>(weapon);
            w->reload(state, frametime);
        }
        // Shooting
        if (held_keys.PRIMARY_FIRE and state->engine->isserver)
        {
            Weapon *w = state->get<Weapon>(weapon);
            w->fireprimary(state, frametime);
        }
        if (held_keys.SECONDARY_FIRE and state->engine->isserver)
        {
            Weapon *w = state->get<Weapon>(weapon);
            w->firesecondary(state, frametime);
        }

        if (isflipped != (mouse_x < 0))
        {
            // Spinjumping (compensate for later gravity)
            vspeed -= 540.0*frametime*3.0/4.0;
            isflipped = (mouse_x < 0);
        }
    }

    damage(20*frametime);
    if (hp.total() <= 0)
    {
        hp = getmaxhp();
    }

    // Gravity
    vspeed += 540.0*frametime;

    // apply friction
    hspeed *= std::pow(friction, frametime);

    state->get<Weapon>(weapon)->midstep(state, frametime);
}

void Character::endstep(Gamestate *state, double frametime)
{
    MovingEntity::endstep(state, frametime);

    // Collision with wallmask
    if (state->currentmap->collides(getcollisionrect(state)))
    {
        // We collide, do collision handling
        double hs = hspeed*frametime, vs = vspeed*frametime;
        // Buffers for "undone" horizontal/vertical movement
        double xbuffer = 0.0, ybuffer = 0.0;
        int steps = std::ceil(std::fmax(std::abs(hs), std::abs(vs)));
        double xstep = hs/steps, ystep = vs/steps;
        // Pull us out of the wall
        for (int i=0; i<steps; ++i)
        {
            x -= xstep; y -= ystep;
            xbuffer += xstep; ybuffer += ystep;
            if (not state->currentmap->collides(getcollisionrect(state)))
            {
                break;
            }
        }
        // We're at the point where the character touched the wallmask for the first time
        // Now keep moving one unit in either direction until all possible movement is exhausted
        bool xblocked = false, yblocked = false;
        bool xfinished = false, yfinished = false;
        double oldxbuffer = xbuffer, oldybuffer = ybuffer;
        while (not xfinished or not yfinished)
        {
            oldxbuffer = xbuffer; oldybuffer = ybuffer;
            // Try first moving horizontally
            if (not xfinished)
            {
                if (not state->currentmap->collides(getcollisionrect(state).offset(xstep, 0)))
                {
                    x += xstep;
                    xbuffer -= xstep;
                    if (xbuffer == 0.0 or std::signbit(xbuffer) != std::signbit(oldxbuffer))
                    {
                        // We're done for this coordinate
                        xfinished = true;
                    }
                }
                else
                {
                    // There's the possibility we might have walked into a staircase
                    if (not state->currentmap->collides(getcollisionrect(state).offset(xstep, STAIRCASE_STEPSIZE)))
                    {
                        // Indeed we did. Move up
                        x += xstep;
                        y += STAIRCASE_STEPSIZE;
                        xbuffer -= xstep;
                        if (xbuffer == 0.0 or std::signbit(xbuffer) != std::signbit(oldxbuffer))
                        {
                            // We're done for this coordinate
                            xfinished = true;
                        }
                    }
                    else
                    {
                        // No more moving, we're blocked
                        xblocked = true;
                        xfinished = true;
                    }
                }
            }
            // Do the same vertically, but without stair code
            if (not yfinished)
            {
                if (not state->currentmap->collides(getcollisionrect(state).offset(0, ystep)))
                {
                    // We cam move through
                    y += ystep;
                    ybuffer -= ystep;
                    if (ybuffer == 0.0 or std::signbit(ybuffer) != std::signbit(oldybuffer))
                    {
                        // We're done for this coordinate
                        yfinished = true;
                    }
                }
                else
                {
                    // No more moving, we're blocked
                    yblocked = true;
                    yfinished = true;
                }
            }
        }
        // Set hspeed and vspeed to what they should be
        if (xblocked)
        {
            hspeed = 0;
        }
        if (yblocked)
        {
            vspeed = 0;
        }
        if (state->currentmap->collides(getcollisionrect(state)))
        {
            printf("\nError: Still in wallmask after collision handling.");
        }
    } // end collision with wallmask

    // Stick to stairs when going down
    if (std::fabs(vspeed*frametime) <= 3.0 and not std::signbit(vspeed*frametime) and not onground(state))
    {
        Rect r = getcollisionrect(state);
        int stepsize = (-STAIRCASE_STEPSIZE)*std::ceil(std::fabs(hspeed)*frametime/(-STAIRCASE_STEPSIZE));
        if (state->currentmap->collides(Rect(r.x, r.y+r.h+stepsize, r.w, 1)))
        {
            for (int i=0; i<stepsize; ++i)
            {
                ++y;
                if (onground(state))
                {
                    break;
                }
            }
        }
    }

    // Running animation
    if (onground(state))
    {
        if (isflipped)
        {
            runanim.update(state, -hspeed*frametime);
            crouchanim.update(state, -hspeed*frametime);
        }
        else
        {
            runanim.update(state, hspeed*frametime);
            crouchanim.update(state, hspeed*frametime);
        }
    }
    if (hspeed == 0.0)
    {
        bool run=runanim.active(), crouch=crouchanim.active();
        runanim.reset();
        runanim.active(run);
        crouchanim.reset();
        crouchanim.active(crouch);
    }

    state->get<Weapon>(weapon)->endstep(state, frametime);
}

bool Character::onground(Gamestate *state)
{
    Rect r = getcollisionrect(state);
    return state->currentmap->collides(Rect(r.x, r.y+r.h, r.w, 1));
}

void Character::interpolate(Entity *prev_entity, Entity *next_entity, double alpha)
{
    MovingEntity::interpolate(prev_entity, next_entity, alpha);

    Character *prev_e = static_cast<Character*>(prev_entity);
    Character *next_e = static_cast<Character*>(next_entity);

    if (alpha < 0.5)
    {
        held_keys = prev_e->held_keys;
        pressed_keys = prev_e->pressed_keys;
        crouchanim.active(prev_e->crouchanim.active());
    }
    else
    {
        held_keys = next_e->held_keys;
        pressed_keys = next_e->pressed_keys;
        crouchanim.active(prev_e->crouchanim.active());
    }
    mouse_x = prev_e->mouse_x + alpha*(next_e->mouse_x - prev_e->mouse_x);
    mouse_y = prev_e->mouse_y + alpha*(next_e->mouse_y - prev_e->mouse_y);
    runanim.interpolate(&(prev_e->runanim), &(next_e->runanim), alpha);
    hp.normal = prev_e->hp.normal + alpha*(next_e->hp.normal - prev_e->hp.normal);
    hp.armor = prev_e->hp.armor + alpha*(next_e->hp.armor - prev_e->hp.armor);
    hp.shields = prev_e->hp.shields + alpha*(next_e->hp.shields - prev_e->hp.shields);
}

void Character::serialize(Gamestate *state, WriteBuffer *buffer, bool fullupdate)
{
    MovingEntity::serialize(state, buffer, fullupdate);
    buffer->write<float>(hp.normal);
    buffer->write<float>(hp.armor);
    buffer->write<float>(hp.shields);
    pressed_keys.serialize(buffer);
    held_keys.serialize(buffer);
    buffer->write<float>(mouse_x);
    buffer->write<float>(mouse_y);
    Weapon *w = state->get<Weapon>(weapon);
    w->serialize(state, buffer, fullupdate);
}

void Character::deserialize(Gamestate *state, ReadBuffer *buffer, bool fullupdate)
{
    MovingEntity::deserialize(state, buffer, fullupdate);
    hp.normal = buffer->read<float>();
    hp.armor = buffer->read<float>();
    hp.shields = buffer->read<float>();
    pressed_keys.deserialize(buffer);
    held_keys.deserialize(buffer);
    mouse_x = buffer->read<float>();
    mouse_y = buffer->read<float>();
    Weapon *w = state->get<Weapon>(weapon);
    w->deserialize(state, buffer, fullupdate);
}

void Character::damage(double amount)
{
    if (hp.shields < amount)
    {
        amount -= hp.shields;
        hp.shields = 0;
        if (hp.armor > 0)
        {
            amount -= std::min(amount/2.0, 5.0);
        }
        if (hp.armor < amount)
        {
            amount -= hp.armor;
            hp.armor = 0;
            hp.normal = std::max(0.0, hp.normal-amount);
        }
        else
        {
            hp.armor -= amount;
        }
    }
    else
    {
        hp.shields -= amount;
    }
}

void Character::destroy(Gamestate *state)
{
    state->get<Weapon>(weapon)->destroy(state);
}
<commit_msg>Cosmetic improvement.<commit_after>#include <vector>
#include <cmath>

#include "ingameelements/character.h"
#include "gamestate.h"
#include "ingameelements/movingentity.h"
#include "ingameelements/player.h"
#include "global_constants.h"
#include "engine.h"
#include "ingameelements/weapon.h"

Character::Character(uint64_t id_, Gamestate *state, EntityPtr owner_, CharacterChildParameters parameters) : MovingEntity(id_, state),
            owner(owner_), weapon(parameters.weapon), hp(parameters.maxhp), hpdir(-1), isflipped(false), runanim(parameters.characterfolder+"run/"),
            crouchanim(parameters.characterfolder+"crouchwalk/"), pressed_keys(), held_keys(), lastdirectionpressed(0)
{
    acceleration = 300;
    runpower = parameters.runpower;
    // friction factor per second of null movement; calculated directly from Gang Garrison 2
    // from pygg2
    friction = 0.01510305449388463132584804061124;
}

void Character::setinput(Gamestate *state, INPUT_CONTAINER pressed_keys_, INPUT_CONTAINER held_keys_, double mouse_x_, double mouse_y_)
{
    pressed_keys = pressed_keys_;
    held_keys = held_keys_;
    mouse_x = mouse_x_;
    mouse_y = mouse_y_;
    Weapon *w = state->get<Weapon>(weapon);
    w->setaim(mouse_x, mouse_y);
}

void Character::beginstep(Gamestate *state, double frametime)
{
    state->get<Weapon>(weapon)->beginstep(state, frametime);
}

void Character::midstep(Gamestate *state, double frametime)
{
    if (cangetinput(state))
    {
        double maxhspeed;
        if (crouchanim.active())
        {
            maxhspeed = 60.0;
        }
        else
        {
            maxhspeed = 153.0;
        }

        if (pressed_keys.LEFT)
        {
            lastdirectionpressed = LEFT;
        }
        else if (lastdirectionpressed == LEFT and not held_keys.LEFT)
        {
            lastdirectionpressed = RIGHT*held_keys.RIGHT;
        }
        if (pressed_keys.RIGHT)
        {
            lastdirectionpressed = RIGHT;
        }
        else if (lastdirectionpressed == RIGHT and not held_keys.RIGHT)
        {
            lastdirectionpressed = LEFT*held_keys.LEFT;
        }

        if (lastdirectionpressed == LEFT)
        {
            hspeed = std::max(hspeed - acceleration * runpower * frametime, -maxhspeed);
        }
        else if (lastdirectionpressed == RIGHT)
        {
            hspeed = std::min(hspeed + acceleration * runpower * frametime, maxhspeed);
        }

        if (pressed_keys.JUMP)
        {
            if (onground(state))
            {
                vspeed = -240.0;
            }
        }
        if (held_keys.CROUCH)
        {
            if (not crouchanim.active())
            {
                crouchanim.active(true);
                crouchanim.reset();
            }
        }
        else if (crouchanim.active())
        {
            // We're crouched and we'd like to uncrouch
            // Do so only if we have the room
            if (not state->currentmap->collides(getstandingcollisionrect(state)))
            {
                crouchanim.active(false);
            }
        }

        if (held_keys.RELOAD)
        {
            Weapon *w = state->get<Weapon>(weapon);
            w->reload(state, frametime);
        }
        // Shooting
        if (held_keys.PRIMARY_FIRE and state->engine->isserver)
        {
            Weapon *w = state->get<Weapon>(weapon);
            w->fireprimary(state, frametime);
        }
        if (held_keys.SECONDARY_FIRE and state->engine->isserver)
        {
            Weapon *w = state->get<Weapon>(weapon);
            w->firesecondary(state, frametime);
        }

        if (isflipped != (mouse_x < 0))
        {
            // Spinjumping (compensate for later gravity)
            vspeed -= 540.0*frametime*3.0/4.0;
            isflipped = (mouse_x < 0);
        }
    }

    damage(20*frametime);
    if (hp.total() <= 0)
    {
        hp = getmaxhp();
    }

    // Gravity
    vspeed += 540.0*frametime;

    // apply friction
    hspeed *= std::pow(friction, frametime);

    state->get<Weapon>(weapon)->midstep(state, frametime);
}

void Character::endstep(Gamestate *state, double frametime)
{
    MovingEntity::endstep(state, frametime);

    // Collision with wallmask
    if (state->currentmap->collides(getcollisionrect(state)))
    {
        // We collide, do collision handling
        double hs = hspeed*frametime, vs = vspeed*frametime;
        // Buffers for "undone" horizontal/vertical movement
        double xbuffer = 0.0, ybuffer = 0.0;
        int steps = std::ceil(std::fmax(std::abs(hs), std::abs(vs)));
        double xstep = hs/steps, ystep = vs/steps;
        // Pull us out of the wall
        for (int i=0; i<steps; ++i)
        {
            x -= xstep; y -= ystep;
            xbuffer += xstep; ybuffer += ystep;
            if (not state->currentmap->collides(getcollisionrect(state)))
            {
                break;
            }
        }
        // We're at the point where the character touched the wallmask for the first time
        // Now keep moving one unit in either direction until all possible movement is exhausted
        bool xblocked = false, yblocked = false;
        bool xfinished = false, yfinished = false;
        double oldxbuffer = xbuffer, oldybuffer = ybuffer;
        while (not xfinished or not yfinished)
        {
            oldxbuffer = xbuffer; oldybuffer = ybuffer;
            // Try first moving horizontally
            if (not xfinished)
            {
                if (not state->currentmap->collides(getcollisionrect(state).offset(xstep, 0)))
                {
                    x += xstep;
                    xbuffer -= xstep;
                    if (xbuffer == 0.0 or std::signbit(xbuffer) != std::signbit(oldxbuffer))
                    {
                        // We're done for this coordinate
                        xfinished = true;
                    }
                }
                else
                {
                    // There's the possibility we might have walked into a staircase
                    if (not state->currentmap->collides(getcollisionrect(state).offset(xstep, STAIRCASE_STEPSIZE)))
                    {
                        // Indeed we did. Move up
                        x += xstep;
                        y += STAIRCASE_STEPSIZE;
                        xbuffer -= xstep;
                        if (xbuffer == 0.0 or std::signbit(xbuffer) != std::signbit(oldxbuffer))
                        {
                            // We're done for this coordinate
                            xfinished = true;
                        }
                    }
                    else
                    {
                        // No more moving, we're blocked
                        xblocked = true;
                        xfinished = true;
                    }
                }
            }
            // Do the same vertically, but without stair code
            if (not yfinished)
            {
                if (not state->currentmap->collides(getcollisionrect(state).offset(0, ystep)))
                {
                    // We cam move through
                    y += ystep;
                    ybuffer -= ystep;
                    if (ybuffer == 0.0 or std::signbit(ybuffer) != std::signbit(oldybuffer))
                    {
                        // We're done for this coordinate
                        yfinished = true;
                    }
                }
                else
                {
                    // No more moving, we're blocked
                    yblocked = true;
                    yfinished = true;
                }
            }
        }
        // Set hspeed and vspeed to what they should be
        if (xblocked)
        {
            hspeed = 0;
        }
        if (yblocked)
        {
            vspeed = 0;
        }
        if (state->currentmap->collides(getcollisionrect(state)))
        {
            printf("\nError: Still in wallmask after collision handling.");
        }
    } // end collision with wallmask

    // Stick to stairs when going down
    if (std::fabs(vspeed*frametime) <= 3.0 and not std::signbit(vspeed*frametime) and not onground(state))
    {
        Rect r = getcollisionrect(state);
        int stepsize = (-STAIRCASE_STEPSIZE)*std::ceil(std::fabs(hspeed)*frametime/(-STAIRCASE_STEPSIZE));
        if (state->currentmap->collides(Rect(r.x, r.y+r.h+stepsize, r.w, 1)))
        {
            for (int i=0; i<stepsize; ++i)
            {
                ++y;
                if (onground(state))
                {
                    break;
                }
            }
        }
    }

    // Running animation
    if (onground(state))
    {
        if (isflipped)
        {
            runanim.update(state, -hspeed*frametime);
            crouchanim.update(state, -hspeed*frametime);
        }
        else
        {
            runanim.update(state, hspeed*frametime);
            crouchanim.update(state, hspeed*frametime);
        }
    }
    if (hspeed == 0.0)
    {
        bool run=runanim.active(), crouch=crouchanim.active();
        runanim.reset();
        runanim.active(run);
        crouchanim.reset();
        crouchanim.active(crouch);
    }

    state->get<Weapon>(weapon)->endstep(state, frametime);
}

bool Character::onground(Gamestate *state)
{
    Rect r = getcollisionrect(state);
    return state->currentmap->collides(Rect(r.x, r.y+r.h, r.w, 1));
}

void Character::interpolate(Entity *prev_entity, Entity *next_entity, double alpha)
{
    MovingEntity::interpolate(prev_entity, next_entity, alpha);

    Character *prev_e = static_cast<Character*>(prev_entity);
    Character *next_e = static_cast<Character*>(next_entity);

    if (alpha < 0.5)
    {
        held_keys = prev_e->held_keys;
        pressed_keys = prev_e->pressed_keys;
        crouchanim.active(prev_e->crouchanim.active());
    }
    else
    {
        held_keys = next_e->held_keys;
        pressed_keys = next_e->pressed_keys;
        crouchanim.active(prev_e->crouchanim.active());
    }
    mouse_x = prev_e->mouse_x + alpha*(next_e->mouse_x - prev_e->mouse_x);
    mouse_y = prev_e->mouse_y + alpha*(next_e->mouse_y - prev_e->mouse_y);
    runanim.interpolate(&(prev_e->runanim), &(next_e->runanim), alpha);
    hp.normal = prev_e->hp.normal + alpha*(next_e->hp.normal - prev_e->hp.normal);
    hp.armor = prev_e->hp.armor + alpha*(next_e->hp.armor - prev_e->hp.armor);
    hp.shields = prev_e->hp.shields + alpha*(next_e->hp.shields - prev_e->hp.shields);
}

void Character::serialize(Gamestate *state, WriteBuffer *buffer, bool fullupdate)
{
    MovingEntity::serialize(state, buffer, fullupdate);

    buffer->write<float>(hp.normal);
    buffer->write<float>(hp.armor);
    buffer->write<float>(hp.shields);

    pressed_keys.serialize(buffer);
    held_keys.serialize(buffer);
    buffer->write<float>(mouse_x);
    buffer->write<float>(mouse_y);

    Weapon *w = state->get<Weapon>(weapon);
    w->serialize(state, buffer, fullupdate);
}

void Character::deserialize(Gamestate *state, ReadBuffer *buffer, bool fullupdate)
{
    MovingEntity::deserialize(state, buffer, fullupdate);

    hp.normal = buffer->read<float>();
    hp.armor = buffer->read<float>();
    hp.shields = buffer->read<float>();

    pressed_keys.deserialize(buffer);
    held_keys.deserialize(buffer);
    mouse_x = buffer->read<float>();
    mouse_y = buffer->read<float>();

    Weapon *w = state->get<Weapon>(weapon);
    w->deserialize(state, buffer, fullupdate);
}

void Character::damage(double amount)
{
    if (hp.shields < amount)
    {
        amount -= hp.shields;
        hp.shields = 0;
        if (hp.armor > 0)
        {
            amount -= std::min(amount/2.0, 5.0);
        }
        if (hp.armor < amount)
        {
            amount -= hp.armor;
            hp.armor = 0;
            hp.normal = std::max(0.0, hp.normal-amount);
        }
        else
        {
            hp.armor -= amount;
        }
    }
    else
    {
        hp.shields -= amount;
    }
}

void Character::destroy(Gamestate *state)
{
    state->get<Weapon>(weapon)->destroy(state);
}
<|endoftext|>


<commit_before>/**
 * File    : B.cpp
 * Author  : Kazune Takahashi
 * Created : 11/24/2018, 8:10:20 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, K;
ll a[1010];
ll sum[1010];
vector<ll> V;

int main()
{
  cin >> N >> K;
  for (auto i = 0; i < N; i++)
  {
    cin >> a[i];
  }
  sum[0] = 0;
  for (auto i = 0; i < N; i++)
  {
    sum[i + 1] = sum[i] + a[i];
  }
  for (auto i = 0; i <= N; i++)
  {
    for (auto j = 0; j < i; j++)
    {
      V.push_back(sum[i] - sum[j]);
    }
  }
  /*
  for (auto x : V)
  {
    cerr << x << endl;
  }
  */
  for (int i = 60 - 1; i >= 0; i--)
  {
    int cnt = 0;
    int L = V.size();
    for (auto j = 0; j < L; j++)
    {
      if ((V[j] >> i) & 1)
      {
        cnt++;
      }
    }
    if (cnt >= K)
    {
      cerr << "i = " << i << ", cnt = " << cnt << endl;
      auto it = V.begin();
      while (it != V.end())
      {
        if (((*it) >> 1) & 1)
        {
          it++;
        }
        else
        {
          cerr << "erased : " << *it << endl;
          it = V.erase(it);
        }
      }
    }
  }
  ll ans = V[0];
  for (auto i = 0; i < K; i++)
  {
    ans = ans & V[i];
  }
  cout << ans << endl;
}<commit_msg>tried B.cpp to 'B'<commit_after>/**
 * File    : B.cpp
 * Author  : Kazune Takahashi
 * Created : 11/24/2018, 8:10:20 PM
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

int N, K;
ll a[1010];
ll sum[1010];
vector<ll> V;

int main()
{
  cin >> N >> K;
  for (auto i = 0; i < N; i++)
  {
    cin >> a[i];
  }
  sum[0] = 0;
  for (auto i = 0; i < N; i++)
  {
    sum[i + 1] = sum[i] + a[i];
  }
  for (auto i = 0; i <= N; i++)
  {
    for (auto j = 0; j < i; j++)
    {
      V.push_back(sum[i] - sum[j]);
    }
  }
  /*
  for (auto x : V)
  {
    cerr << x << endl;
  }
  */
  for (int i = 60 - 1; i >= 0; i--)
  {
    int cnt = 0;
    int L = V.size();
    for (auto j = 0; j < L; j++)
    {
      if ((V[j] >> i) & 1)
      {
        cnt++;
      }
    }
    if (cnt >= K)
    {
      cerr << "i = " << i << ", cnt = " << cnt << endl;
      auto it = V.begin();
      while (it != V.end())
      {
        if (((*it) >> 1) & 1)
        {
          it++;
        }
        else
        {
          cerr << "erased : " << *it << endl;
          it = V.erase(it);
        }
      }
      cerr << "V.size() = " << V.size() << endl;
    }
  }
  ll ans = V[0];
  for (auto i = 0; i < K; i++)
  {
    ans = ans & V[i];
  }
  cout << ans << endl;
}<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2013 Soumyajit De
 */

#include <shogun/lib/config.h>
#include <shogun/lib/SGMatrix.h>
#include <shogun/lib/SGVector.h>
#include <shogun/mathematics/eigen3.h>
#include <shogun/mathematics/logdet/DenseMatrixOperator.h>
#include <gtest/gtest.h>

using namespace shogun;

#ifdef HAVE_EIGEN3
using namespace Eigen;

TEST(DenseMatrixOperator, apply)
{
	const index_t size=5;
	SGVector<float64_t> b1(size);
	b1.set_const(0.25);

	// float64_t, fixed matrix
	SGMatrix<float64_t> m1(size, size);
	m1.set_const(0.5);

	CDenseMatrixOperator<float64_t, float64_t> op11(m1);
	SGVector<float64_t> r1=op11.apply(b1);

	for (index_t i=0; i<r1.vlen; ++i)
	{
		EXPECT_NEAR(r1[i], 0.625, 1E-16);
	}

	// float64_t, identity matrix
	typedef Matrix<float64_t, size, size> MatrixSd;
	Map<MatrixSd> mapped1(m1.matrix, m1.num_rows, m1.num_cols);
	mapped1=MatrixSd::Identity();
	CDenseMatrixOperator<float64_t, float64_t> op12(m1);
	r1=op12.apply(b1);

	for (index_t i=0; i<r1.vlen; ++i)
	{
		EXPECT_NEAR(r1[i], 0.25, 1E-16);
	}

	SGVector<complex64_t> b2(size);
	b2.set_const(complex64_t(0.25, 1.0));

	// complex64_t, fixed matrix
	SGMatrix<complex64_t> m2(size, size);
	m2.set_const(complex64_t(0.5, 0.25));

	CDenseMatrixOperator<complex64_t, complex64_t> op21(m2);
	SGVector<complex64_t> r2=op21.apply(b2);

	for (index_t i=0; i<r2.vlen; ++i)
	{
		EXPECT_NEAR(r2[i].real(), -0.625, 1E-16);
		EXPECT_NEAR(r2[i].imag(), 2.8125, 1E-16);
	}

	// complex64_t, identity matrix
	typedef Matrix<complex64_t, size, size> MatrixScd;
	Map<MatrixScd> mapped2(m2.matrix, m2.num_rows, m2.num_cols);
	mapped2=MatrixScd::Identity();
	CDenseMatrixOperator<complex64_t, complex64_t> op22(m2);
	r2=op22.apply(b2);

	for (index_t i=0; i<r2.vlen; ++i)
	{
		EXPECT_NEAR(r2[i].real(), 0.25, 1E-16);
		EXPECT_NEAR(r2[i].imag(), 1.0, 1E-16);
	}
}

TEST(DenseMatrixOperator, shift_apply)
{
	const index_t size=5;
	SGVector<float64_t> b(size);
	b.set_const(0.25);

	// complex64_t, fixed matrix
	SGMatrix<complex64_t> m(size, size);
	m.set_const(complex64_t(0.5, 0.0));

	// shifting the diagonal via interface
	CDenseMatrixOperator<complex64_t, float64_t> op(m);
	SGVector<complex64_t> diag=op.get_diagonal();
	for (index_t i=0; i<diag.vlen; ++i)
		diag[i].imag()-=0.75;
	op.set_diagonal(diag);

	SGVector<complex64_t> r1=op.apply(b);
	Map<VectorXcd> map_r1(r1.vector, r1.vlen);

	// shifting the diagonal directly via matrix
	m.set_const(complex64_t(0.5, 0.0));
	for (index_t i=0; i<size; ++i)
		m(i,i).imag()-=0.75;

	SGVector<complex64_t> r2=op.apply(b);
	Map<VectorXcd> map_r2(r2.vector, r2.vlen);

	EXPECT_NEAR(map_r1.norm(), map_r2.norm(), 1E-15);
}

#endif // HAVE_EIGEN3
<commit_msg>fix c++11 compile error<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2013 Soumyajit De
 */

#include <shogun/lib/config.h>
#include <shogun/lib/SGMatrix.h>
#include <shogun/lib/SGVector.h>
#include <shogun/mathematics/eigen3.h>
#include <shogun/mathematics/logdet/DenseMatrixOperator.h>
#include <gtest/gtest.h>

using namespace shogun;

#ifdef HAVE_EIGEN3
using namespace Eigen;

TEST(DenseMatrixOperator, apply)
{
	const index_t size=5;
	SGVector<float64_t> b1(size);
	b1.set_const(0.25);

	// float64_t, fixed matrix
	SGMatrix<float64_t> m1(size, size);
	m1.set_const(0.5);

	CDenseMatrixOperator<float64_t, float64_t> op11(m1);
	SGVector<float64_t> r1=op11.apply(b1);

	for (index_t i=0; i<r1.vlen; ++i)
	{
		EXPECT_NEAR(r1[i], 0.625, 1E-16);
	}

	// float64_t, identity matrix
	typedef Matrix<float64_t, size, size> MatrixSd;
	Map<MatrixSd> mapped1(m1.matrix, m1.num_rows, m1.num_cols);
	mapped1=MatrixSd::Identity();
	CDenseMatrixOperator<float64_t, float64_t> op12(m1);
	r1=op12.apply(b1);

	for (index_t i=0; i<r1.vlen; ++i)
	{
		EXPECT_NEAR(r1[i], 0.25, 1E-16);
	}

	SGVector<complex64_t> b2(size);
	b2.set_const(complex64_t(0.25, 1.0));

	// complex64_t, fixed matrix
	SGMatrix<complex64_t> m2(size, size);
	m2.set_const(complex64_t(0.5, 0.25));

	CDenseMatrixOperator<complex64_t, complex64_t> op21(m2);
	SGVector<complex64_t> r2=op21.apply(b2);

	for (index_t i=0; i<r2.vlen; ++i)
	{
		EXPECT_NEAR(r2[i].real(), -0.625, 1E-16);
		EXPECT_NEAR(r2[i].imag(), 2.8125, 1E-16);
	}

	// complex64_t, identity matrix
	typedef Matrix<complex64_t, size, size> MatrixScd;
	Map<MatrixScd> mapped2(m2.matrix, m2.num_rows, m2.num_cols);
	mapped2=MatrixScd::Identity();
	CDenseMatrixOperator<complex64_t, complex64_t> op22(m2);
	r2=op22.apply(b2);

	for (index_t i=0; i<r2.vlen; ++i)
	{
		EXPECT_NEAR(r2[i].real(), 0.25, 1E-16);
		EXPECT_NEAR(r2[i].imag(), 1.0, 1E-16);
	}
}

TEST(DenseMatrixOperator, shift_apply)
{
	const index_t size=5;
	SGVector<float64_t> b(size);
	b.set_const(0.25);

	// complex64_t, fixed matrix
	SGMatrix<complex64_t> m(size, size);
	m.set_const(complex64_t(0.5, 0.0));

	// shifting the diagonal via interface
	CDenseMatrixOperator<complex64_t, float64_t> op(m);
	SGVector<complex64_t> diag=op.get_diagonal();
	for (index_t i=0; i<diag.vlen; ++i)
	{
#ifdef HAVE_CXX11
		diag[i].imag(diag[i].imag()-0.75);
#else
		diag[i].imag()-=0.75;
#endif
	}
	op.set_diagonal(diag);

	SGVector<complex64_t> r1=op.apply(b);
	Map<VectorXcd> map_r1(r1.vector, r1.vlen);

	// shifting the diagonal directly via matrix
	m.set_const(complex64_t(0.5, 0.0));
	for (index_t i=0; i<size; ++i)
	{
#ifdef HAVE_CXX11
		m(i,i).imag(m(i,i).imag()-0.75);
#else
		m(i,i).imag()-=0.75;
#endif
	}

	SGVector<complex64_t> r2=op.apply(b);
	Map<VectorXcd> map_r2(r2.vector, r2.vlen);

	EXPECT_NEAR(map_r1.norm(), map_r2.norm(), 1E-15);
}

#endif // HAVE_EIGEN3
<|endoftext|>