<commit_before>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you under
the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

*******************************************************************************/

//==============================================================================
// Core CLI utilities
//==============================================================================

QString shortVersion(QCoreApplication *pApp);
QString version(QCoreApplication *pApp);

QString CORE_EXPORT osName();

QString CORE_EXPORT copyright();

QString CORE_EXPORT formatMessage(const QString &pMessage,
                                  const bool &pLowerCase = true,
                                  const bool &pDotDotDot = false);

QByteArray CORE_EXPORT resourceAsByteArray(const QString &pResource);

QString CORE_EXPORT temporaryFileName(const QString &pExtension = ".tmp");

bool CORE_EXPORT writeResourceToFile(const QString &pFileName,
                                     const QString &pResource);

bool CORE_EXPORT readTextFromFile(const QString &pFileName, QString &pText);
bool CORE_EXPORT writeTextToFile(const QString &pFileName,
                                 const QString &pText);

bool CORE_EXPORT readTextFromUrl(const QString &pUrl, QString &pText,
                                 QString *pErrorMessage = 0);

QString CORE_EXPORT eolString();

QString CORE_EXPORT nonDiacriticString(const QString &pString);

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Oops, forgot to import/export Core::shortVersion() and Core::version() on Windows [ci skip].<commit_after>/*******************************************************************************

Licensed to the OpenCOR team under one or more contributor license agreements.
See the NOTICE.txt file distributed with this work for additional information
regarding copyright ownership. The OpenCOR team licenses this file to you under
the Apache License, Version 2.0 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.

*******************************************************************************/

//==============================================================================
// Core CLI utilities
//==============================================================================

QString CORE_EXPORT shortVersion(QCoreApplication *pApp);
QString CORE_EXPORT version(QCoreApplication *pApp);

QString CORE_EXPORT osName();

QString CORE_EXPORT copyright();

QString CORE_EXPORT formatMessage(const QString &pMessage,
                                  const bool &pLowerCase = true,
                                  const bool &pDotDotDot = false);

QByteArray CORE_EXPORT resourceAsByteArray(const QString &pResource);

QString CORE_EXPORT temporaryFileName(const QString &pExtension = ".tmp");

bool CORE_EXPORT writeResourceToFile(const QString &pFileName,
                                     const QString &pResource);

bool CORE_EXPORT readTextFromFile(const QString &pFileName, QString &pText);
bool CORE_EXPORT writeTextToFile(const QString &pFileName,
                                 const QString &pText);

bool CORE_EXPORT readTextFromUrl(const QString &pUrl, QString &pText,
                                 QString *pErrorMessage = 0);

QString CORE_EXPORT eolString();

QString CORE_EXPORT nonDiacriticString(const QString &pString);

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


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

#include "qmlnewprojectwizard.h"

#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
#include <projectexplorer/projectexplorer.h>

#include <utils/filenamevalidatinglineedit.h>
#include <utils/filewizardpage.h>
#include <utils/pathchooser.h>
#include <utils/projectintropage.h>

#include <QtCore/QDir>
#include <QtCore/QtDebug>

#include <QtGui/QDirModel>
#include <QtGui/QFormLayout>
#include <QtGui/QListView>
#include <QtGui/QTreeView>

using namespace QmlProjectManager::Internal;
using namespace Core::Utils;

namespace {

class DirModel : public QDirModel
{
public:
    DirModel(QObject *parent)
        : QDirModel(parent)
    { setFilter(QDir::Dirs | QDir::NoDotAndDotDot); }

    virtual ~DirModel()
    { }

public:
    virtual int columnCount(const QModelIndex &) const
    { return 1; }

    virtual Qt::ItemFlags flags(const QModelIndex &index) const
    { return QDirModel::flags(index) | Qt::ItemIsUserCheckable; }

    virtual QVariant data(const QModelIndex &index, int role) const
    {
        if (index.column() == 0 && role == Qt::CheckStateRole) {
            if (m_selectedPaths.contains(index))
                return Qt::Checked;

            return Qt::Unchecked;
        }

        return QDirModel::data(index, role);
    }

    virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
    {
        if (index.column() == 0 && role == Qt::CheckStateRole) {
            if (value.toBool())
                m_selectedPaths.insert(index);
            else
                m_selectedPaths.remove(index);

            return true;
        }

        return QDirModel::setData(index, value, role);
    }

    void clearSelectedPaths()
    { m_selectedPaths.clear(); }

    QSet<QString> selectedPaths() const
    {
        QSet<QString> paths;

        foreach (const QModelIndex &index, m_selectedPaths)
            paths.insert(filePath(index));

        return paths;
    }

private:
    QSet<QModelIndex> m_selectedPaths;
};

} // end of anonymous namespace

//////////////////////////////////////////////////////////////////////////////
// QmlNewProjectWizardDialog
//////////////////////////////////////////////////////////////////////////////

QmlNewProjectWizardDialog::QmlNewProjectWizardDialog(QWidget *parent)
    : QWizard(parent)
{
    setWindowTitle(tr("New QML Project"));

    m_introPage = new Core::Utils::ProjectIntroPage();
    m_introPage->setDescription(tr("This wizard generates a QML application project."));

    addPage(m_introPage);
}

QmlNewProjectWizardDialog::~QmlNewProjectWizardDialog()
{ }

QString QmlNewProjectWizardDialog::path() const
{
    return m_introPage->path();
}

void QmlNewProjectWizardDialog::setPath(const QString &path)
{
    m_introPage->setPath(path);
}

QString QmlNewProjectWizardDialog::projectName() const
{
    return m_introPage->name();
}

void QmlNewProjectWizardDialog::updateFilesView(const QModelIndex &current,
                                                 const QModelIndex &)
{
    if (! current.isValid())
        m_filesView->setModel(0);

    else {
        const QString selectedPath = m_dirModel->filePath(current);

        if (! m_filesView->model())
            m_filesView->setModel(m_filesModel);

        m_filesView->setRootIndex(m_filesModel->index(selectedPath));
    }
}

void QmlNewProjectWizardDialog::initializePage(int id)
{
    Q_UNUSED(id)
}

bool QmlNewProjectWizardDialog::validateCurrentPage()
{
    return QWizard::validateCurrentPage();
}

QmlNewProjectWizard::QmlNewProjectWizard()
    : Core::BaseFileWizard(parameters())
{ }

QmlNewProjectWizard::~QmlNewProjectWizard()
{ }

Core::BaseFileWizardParameters QmlNewProjectWizard::parameters()
{
    static Core::BaseFileWizardParameters parameters(ProjectWizard);
    parameters.setIcon(QIcon(":/wizards/images/console.png"));
    parameters.setName(tr("QML Application"));
    parameters.setDescription(tr("Creates a QML application."));
    parameters.setCategory(QLatin1String("Projects"));
    parameters.setTrCategory(tr("Projects"));
    return parameters;
}

QWizard *QmlNewProjectWizard::createWizardDialog(QWidget *parent,
                                                  const QString &defaultPath,
                                                  const WizardPageList &extensionPages) const
{
    QmlNewProjectWizardDialog *wizard = new QmlNewProjectWizardDialog(parent);
    setupWizard(wizard);

    wizard->setPath(defaultPath);

    foreach (QWizardPage *p, extensionPages)
        wizard->addPage(p);

    return wizard;
}

Core::GeneratedFiles QmlNewProjectWizard::generateFiles(const QWizard *w,
                                                     QString *errorMessage) const
{
    Q_UNUSED(errorMessage)

    const QmlNewProjectWizardDialog *wizard = qobject_cast<const QmlNewProjectWizardDialog *>(w);
    const QString projectName = wizard->projectName();
    const QString projectPath = wizard->path() + QLatin1Char('/') + projectName;

    const QString creatorFileName = Core::BaseFileWizard::buildFileName(projectPath,
                                                                        projectName,
                                                                        QLatin1String("qmlproject"));

    const QString mainFileName = Core::BaseFileWizard::buildFileName(projectPath,
                                                                     projectName,
                                                                     QLatin1String("qml"));

    QString contents;
    QTextStream out(&contents);
    out << "Text {" << endl
        << "    text: \"Hello, world!\"" << endl
        << "}" << endl;

    Core::GeneratedFile generatedMainFile(mainFileName);
    generatedMainFile.setContents(contents);

    Core::GeneratedFile generatedCreatorFile(creatorFileName);
    generatedCreatorFile.setContents(projectName + QLatin1String(".qml\n"));

    Core::GeneratedFiles files;
    files.append(generatedMainFile);
    files.append(generatedCreatorFile);

    return files;
}

bool QmlNewProjectWizard::postGenerateFiles(const Core::GeneratedFiles &l, QString *errorMessage)
{
    // Post-Generate: Open the project
    const QString proFileName = l.back().path();
    if (!ProjectExplorer::ProjectExplorerPlugin::instance()->openProject(proFileName)) {
        *errorMessage = tr("The project %1 could not be opened.").arg(proFileName);
        return false;
    }
    return true;
}

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

#include "qmlnewprojectwizard.h"

#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
#include <projectexplorer/projectexplorer.h>

#include <utils/filenamevalidatinglineedit.h>
#include <utils/filewizardpage.h>
#include <utils/pathchooser.h>
#include <utils/projectintropage.h>

#include <QtCore/QDir>
#include <QtCore/QtDebug>

#include <QtGui/QDirModel>
#include <QtGui/QFormLayout>
#include <QtGui/QListView>
#include <QtGui/QTreeView>

using namespace QmlProjectManager::Internal;
using namespace Core::Utils;

namespace {

class DirModel : public QDirModel
{
public:
    DirModel(QObject *parent)
        : QDirModel(parent)
    { setFilter(QDir::Dirs | QDir::NoDotAndDotDot); }

    virtual ~DirModel()
    { }

public:
    virtual int columnCount(const QModelIndex &) const
    { return 1; }

    virtual Qt::ItemFlags flags(const QModelIndex &index) const
    { return QDirModel::flags(index) | Qt::ItemIsUserCheckable; }

    virtual QVariant data(const QModelIndex &index, int role) const
    {
        if (index.column() == 0 && role == Qt::CheckStateRole) {
            if (m_selectedPaths.contains(index))
                return Qt::Checked;

            return Qt::Unchecked;
        }

        return QDirModel::data(index, role);
    }

    virtual bool setData(const QModelIndex &index, const QVariant &value, int role)
    {
        if (index.column() == 0 && role == Qt::CheckStateRole) {
            if (value.toBool())
                m_selectedPaths.insert(index);
            else
                m_selectedPaths.remove(index);

            return true;
        }

        return QDirModel::setData(index, value, role);
    }

    void clearSelectedPaths()
    { m_selectedPaths.clear(); }

    QSet<QString> selectedPaths() const
    {
        QSet<QString> paths;

        foreach (const QModelIndex &index, m_selectedPaths)
            paths.insert(filePath(index));

        return paths;
    }

private:
    QSet<QModelIndex> m_selectedPaths;
};

} // end of anonymous namespace

//////////////////////////////////////////////////////////////////////////////
// QmlNewProjectWizardDialog
//////////////////////////////////////////////////////////////////////////////

QmlNewProjectWizardDialog::QmlNewProjectWizardDialog(QWidget *parent)
    : QWizard(parent)
{
    setWindowTitle(tr("New QML Project"));

    m_introPage = new Core::Utils::ProjectIntroPage();
    m_introPage->setDescription(tr("This wizard generates a QML application project."));

    addPage(m_introPage);
}

QmlNewProjectWizardDialog::~QmlNewProjectWizardDialog()
{ }

QString QmlNewProjectWizardDialog::path() const
{
    return m_introPage->path();
}

void QmlNewProjectWizardDialog::setPath(const QString &path)
{
    m_introPage->setPath(path);
}

QString QmlNewProjectWizardDialog::projectName() const
{
    return m_introPage->name();
}

void QmlNewProjectWizardDialog::updateFilesView(const QModelIndex &current,
                                                 const QModelIndex &)
{
    if (! current.isValid())
        m_filesView->setModel(0);

    else {
        const QString selectedPath = m_dirModel->filePath(current);

        if (! m_filesView->model())
            m_filesView->setModel(m_filesModel);

        m_filesView->setRootIndex(m_filesModel->index(selectedPath));
    }
}

void QmlNewProjectWizardDialog::initializePage(int id)
{
    Q_UNUSED(id)
}

bool QmlNewProjectWizardDialog::validateCurrentPage()
{
    return QWizard::validateCurrentPage();
}

QmlNewProjectWizard::QmlNewProjectWizard()
    : Core::BaseFileWizard(parameters())
{ }

QmlNewProjectWizard::~QmlNewProjectWizard()
{ }

Core::BaseFileWizardParameters QmlNewProjectWizard::parameters()
{
    static Core::BaseFileWizardParameters parameters(ProjectWizard);
    parameters.setIcon(QIcon(":/wizards/images/console.png"));
    parameters.setName(tr("QML Application"));
    parameters.setDescription(tr("Creates a QML application."));
    parameters.setCategory(QLatin1String("Projects"));
    parameters.setTrCategory(tr("Projects"));
    return parameters;
}

QWizard *QmlNewProjectWizard::createWizardDialog(QWidget *parent,
                                                  const QString &defaultPath,
                                                  const WizardPageList &extensionPages) const
{
    QmlNewProjectWizardDialog *wizard = new QmlNewProjectWizardDialog(parent);
    setupWizard(wizard);

    wizard->setPath(defaultPath);

    foreach (QWizardPage *p, extensionPages)
        wizard->addPage(p);

    return wizard;
}

Core::GeneratedFiles QmlNewProjectWizard::generateFiles(const QWizard *w,
                                                     QString *errorMessage) const
{
    Q_UNUSED(errorMessage)

    const QmlNewProjectWizardDialog *wizard = qobject_cast<const QmlNewProjectWizardDialog *>(w);
    const QString projectName = wizard->projectName();
    const QString projectPath = wizard->path() + QLatin1Char('/') + projectName;

    const QString creatorFileName = Core::BaseFileWizard::buildFileName(projectPath,
                                                                        projectName,
                                                                        QLatin1String("qmlproject"));

    const QString mainFileName = Core::BaseFileWizard::buildFileName(projectPath,
                                                                     projectName,
                                                                     QLatin1String("qml"));

    QString contents;
    QTextStream out(&contents);

    out
        << "Rect {" << endl
        << "    width: 200" << endl
        << "    height: 200" << endl
        << "    color: \"white\"" << endl
        << "    Text {" << endl
        << "        text: \"Hello World\"" << endl
        << "        anchors.centeredIn: parent" << endl
        << "    }" << endl
        << "}" << endl;

    Core::GeneratedFile generatedMainFile(mainFileName);
    generatedMainFile.setContents(contents);

    Core::GeneratedFile generatedCreatorFile(creatorFileName);
    generatedCreatorFile.setContents(projectName + QLatin1String(".qml\n"));

    Core::GeneratedFiles files;
    files.append(generatedMainFile);
    files.append(generatedCreatorFile);

    return files;
}

bool QmlNewProjectWizard::postGenerateFiles(const Core::GeneratedFiles &l, QString *errorMessage)
{
    // Post-Generate: Open the project
    const QString proFileName = l.back().path();
    if (!ProjectExplorer::ProjectExplorerPlugin::instance()->openProject(proFileName)) {
        *errorMessage = tr("The project %1 could not be opened.").arg(proFileName);
        return false;
    }
    return true;
}

<|endoftext|>


<commit_before>#include "gui.h"
#include "../client/NetClient.h"
#include "chatwindow.h"
#include "logindialog.h"

Gui::Gui()
{

    mainWindow = new ChatWindow(this);
    loginWindow = new LoginDialog(mainWindow, this);
    mainWindow->show();
    loginWindow->setModal(true);
    loginWindow->show();
}

// --------------------------

void Gui::receiveMessage(QString from, QString to, QString message, QString servertime) {
    mainWindow->receiveMessage(from, to, message, servertime);
}

void Gui::connected(){
    loginWindow->connected();
}

void Gui::createClient(QString inName, QString inAddress){
    delete client;
    client = new NetClient(inName, inAddress, this);
    client->start();
}

void Gui::userNameTaken(){
    loginWindow->userNameTaken();
}

void Gui::noConnection(){
    loginWindow->noConnection();
}

void Gui::sendMessage(QString from, QString to, QString message){
    client->sendMessage(from,to,message);
}

void Gui::updateStruct(QVector<QString> treeStruct){
    mainWindow->updateStruct(treeStruct);
}

void Gui::getStruct(){
    mainWindow->updateStruct(client->getStruct());
}

void Gui::receiveHistory(QVector<QString> &historyVector){
    mainWindow->receiveHistory(historyVector);
}
<commit_msg>Changed getStruct.<commit_after>#include "gui.h"
#include "../client/NetClient.h"
#include "chatwindow.h"
#include "logindialog.h"

Gui::Gui()
{

    mainWindow = new ChatWindow(this);
    loginWindow = new LoginDialog(mainWindow, this);
    mainWindow->show();
    loginWindow->setModal(true);
    loginWindow->show();
}

// --------------------------

void Gui::receiveMessage(QString from, QString to, QString message, QString servertime) {
    mainWindow->receiveMessage(from, to, message, servertime);
}

void Gui::connected(){
    loginWindow->connected();
}

void Gui::createClient(QString inName, QString inAddress){
    delete client;
    client = new NetClient(inName, inAddress, this);
    client->start();
}

void Gui::userNameTaken(){
    loginWindow->userNameTaken();
}

void Gui::noConnection(){
    loginWindow->noConnection();
}

void Gui::sendMessage(QString from, QString to, QString message){
    client->sendMessage(from,to,message);
}

void Gui::updateStruct(QVector<QString> treeStruct){
    mainWindow->updateStruct(treeStruct);
}

void Gui::getStruct(){
    client->getStruct();
}

void Gui::receiveHistory(QVector<QString> &historyVector){
    mainWindow->receiveHistory(historyVector);
}
<|endoftext|>


<commit_before>//
// Created by Ivan Shynkarenka on 01.08.2016.
//

#include "benchmark/cppbenchmark.h"

#include "logging/config.h"
#include "logging/logger.h"

#include "threads/mpmc_ring_queue.h"

#include <functional>
#include <thread>
#include <vector>

using namespace CppLogging;

const uint64_t items_to_produce = 8000000;
const auto settings = CppBenchmark::Settings().ParamRange(8, 8, [](int from, int to, int& result) { int r = result; result *= 2; return r; });

template<typename T, uint64_t N>
void test(CppBenchmark::Context& context, const std::function<void()>& wait_strategy)
{
    const int producers_count = context.x();
    uint64_t crc = 0;

    // Create multiple producers / multiple consumers wait-free ring queue
    CppCommon::MPMCRingQueue<T> queue(N);

    // Start consumer thread
    auto consumer = std::thread([&queue, &wait_strategy, &crc]()
    {
        for (uint64_t i = 0; i < items_to_produce; ++i)
        {
			// Dequeue using the given waiting strategy
			T item;
			while (!queue.Dequeue(item))
				wait_strategy();

			// Consume the item
			crc += 1;
        }
    });

    // Start producer threads
    std::vector<std::thread> producers;
    for (int producer = 0; producer < producers_count; ++producer)
    {
        producers.push_back(std::thread([&queue, &wait_strategy, producer, producers_count]()
        {
            uint64_t items = (items_to_produce / producers_count);
            for (uint64_t i = 0; i < items; ++i)
            {
                // Enqueue using the given waiting strategy
				T record;
                while (!queue.Enqueue(std::forward<T>(record)))
                    wait_strategy();
            }
        }));
    }

    // Wait for the consumer thread
    consumer.join();

    // Wait for all producers threads
    for (auto& producer : producers)
        producer.join();

    // Update benchmark metrics
    context.metrics().AddIterations(items_to_produce - 1);
    context.metrics().AddItems(items_to_produce);
    context.metrics().AddBytes(items_to_produce * sizeof(T));
    context.metrics().SetCustom("Queue.capacity", N);
    context.metrics().SetCustom("CRC", crc);
}

BENCHMARK("Test", settings)
{
    test<Record, 4096>(context, []{ std::this_thread::yield(); });
}

BENCHMARK_MAIN()
<commit_msg>Update<commit_after>//
// Created by Ivan Shynkarenka on 01.08.2016.
//

#include "benchmark/cppbenchmark.h"

#include "logging/config.h"
#include "logging/logger.h"

#include "threads/mpmc_ring_queue.h"

#include <functional>
#include <thread>
#include <vector>

using namespace CppLogging;

const uint64_t items_to_produce = 8000000;
const auto settings = CppBenchmark::Settings().ParamRange(8, 8, [](int from, int to, int& result) { int r = result; result *= 2; return r; });

class RecordEx
{
public:
	//! Timestamp of the logging record
	uint64_t timestamp;
	//! Thread Id of the logging record
	uint64_t thread;
	//! Level of the logging record
	Level level;

	char logger[5];
	char message[16];

	RecordEx() noexcept
		: timestamp(CppCommon::Timestamp::utc()),
		thread(CppCommon::Thread::CurrentThreadId()),
		level(Level::INFO)
	{}
	RecordEx(const RecordEx&) noexcept = delete;
	RecordEx(RecordEx&& r) noexcept
	{
		timestamp = std::move(r.timestamp);
		thread = std::move(r.thread);
		level = std::move(r.level);
		std::strcpy(logger, r.logger);
		std::strcpy(message, r.message);
	}
	~RecordEx() noexcept = default;

	RecordEx& operator=(const RecordEx&) noexcept = delete;
	RecordEx& operator=(RecordEx&& r) noexcept
	{
		timestamp = std::move(r.timestamp);
		thread = std::move(r.thread);
		level = std::move(r.level);
		std::strcpy(logger, r.logger);
		std::strcpy(message, r.message);
		return *this;
	}
};

template<typename T, uint64_t N>
void test(CppBenchmark::Context& context, const std::function<void()>& wait_strategy)
{
    const int producers_count = context.x();
    uint64_t crc = 0;

    // Create multiple producers / multiple consumers wait-free ring queue
    CppCommon::MPMCRingQueue<T> queue(N);

    // Start consumer thread
    auto consumer = std::thread([&queue, &wait_strategy, &crc]()
    {
        for (uint64_t i = 0; i < items_to_produce; ++i)
        {
			// Dequeue using the given waiting strategy
			T item;
			while (!queue.Dequeue(item))
				wait_strategy();

			// Consume the item
			crc += 1;
        }
    });

    // Start producer threads
    std::vector<std::thread> producers;
    for (int producer = 0; producer < producers_count; ++producer)
    {
        producers.push_back(std::thread([&queue, &wait_strategy, producer, producers_count]()
        {
            uint64_t items = (items_to_produce / producers_count);
            for (uint64_t i = 0; i < items; ++i)
            {
                // Enqueue using the given waiting strategy
				T record;
				std::strcpy(record.logger, "Test");
				std::strcpy(record.message, "Test message");
                while (!queue.Enqueue(std::forward<T>(record)))
                    wait_strategy();
            }
        }));
    }

    // Wait for the consumer thread
    consumer.join();

    // Wait for all producers threads
    for (auto& producer : producers)
        producer.join();

    // Update benchmark metrics
    context.metrics().AddIterations(items_to_produce - 1);
    context.metrics().AddItems(items_to_produce);
    context.metrics().AddBytes(items_to_produce * sizeof(T));
    context.metrics().SetCustom("Queue.capacity", N);
    context.metrics().SetCustom("CRC", crc);
}

BENCHMARK("Test", settings)
{
    test<RecordEx, 1048576>(context, []{ std::this_thread::yield(); });
}

BENCHMARK_MAIN()
<|endoftext|>


<commit_before><commit_msg>reopen files if no_buffer mode changes<commit_after><|endoftext|>


<commit_before>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 */
#pragma once

#include <crossbow/byte_buffer.hpp>
#include <crossbow/enum_underlying.hpp>
#include <crossbow/infinio/BatchingMessageSocket.hpp>
#include <crossbow/infinio/Fiber.hpp>
#include <crossbow/logger.hpp>
#include <crossbow/string.hpp>

#include <sparsehash/dense_hash_map>

#include <cstdint>
#include <limits>
#include <queue>
#include <system_error>
#include <tuple>
#include <type_traits>

namespace crossbow {
namespace infinio {
namespace detail {

extern const std::error_code gEmptyErrorCode;

} // namespace detail

class Fiber;

/**
 * @brief Base class representing a pending RPC response
 */
class RpcResponse {
public:
    /**
     * @brief Suspend the fiber until notified by another context or an response was received
     *
     * Blocks until notify() or complete() are called.
     *
     * @return Whether an response was received
     */
    bool wait();

    /**
     * @brief Whether an response was received
     */
    bool done() const {
        return !mPending;
    }

    Fiber& fiber() {
        return mFiber;
    }

protected:
    RpcResponse(Fiber& fiber)
            : mFiber(fiber),
              mPending(true),
              mWaiting(false) {
    }

    virtual ~RpcResponse();

    /**
     * @brief Notifies the response fiber of any event
     *
     * Will resume the fiber if it is waiting.
     */
    void notify();

    /**
     * @brief Notifies the response fiber of its completion
     *
     * Will resume the fiber if it is waiting.
     */
    void complete();

private:
    friend class RpcClientSocket;

    /**
     * @brief Called when a response with the given message type was received
     *
     * @param messageType The type of the received message
     * @param message The response message
     */
    virtual void onResponse(uint32_t messageType, crossbow::buffer_reader& message) = 0;

    /**
     * @brief Called when the RPC was aborted due to an error
     */
    virtual void onAbort(std::error_code ec) = 0;

    Fiber& mFiber;

    bool mPending;
    bool mWaiting;
};

enum class RpcResponseState {
    UNSET,
    SET,
    ERROR,
};

/**
 * @brief Class holding a future RPC response
 */
template <typename Handler, typename Result>
class RpcResponseResult : public RpcResponse {
public:
    using ResultType = Result;

    RpcResponseResult(Fiber& fiber)
            : RpcResponse(fiber),
              mState(RpcResponseState::UNSET),
              mRetrieved(false) {
    }

    virtual ~RpcResponseResult();

    /**
     * @brief Suspend the fiber until the response was received
     *
     * @return Whether the response is valid (contains an error otherwise)
     */
    bool waitForResult();

    /**
     * @brief Retrieve the response of the request
     *
     * Blocks until the response has been received.
     *
     * The result can only be retrieved once. An exception is thrown if the result is invalid or was already retrieved.
     *
     * @exception std::system_error The result is invalid
     * @exception std::future_error The result was already retrieved
     * @return The result of the RPC request
     */
    ResultType get();

    /**
     * @brief The error code if the response completed with an error
     *
     * Blocks until the response has been received.
     */
    const std::error_code& error();

protected:
    template <typename... Args>
    void setResult(Args&&... args) {
        setInternalResult<ResultType, RpcResponseState::SET, Args...>(std::forward<Args>(args)...);
    }

    template <typename... Args>
    void setError(Args&&... args) {
        setInternalResult<std::error_code, RpcResponseState::ERROR, Args...>(std::forward<Args>(args)...);
    }

private:
    virtual void onResponse(uint32_t messageType, crossbow::buffer_reader& message) final override;

    virtual void onAbort(std::error_code ec) final override;

    template <typename T, RpcResponseState State, typename... Args>
    void setInternalResult(Args&&... args);

    /// The state of the result container
    RpcResponseState mState;

    /// Whether the result was retrieved
    bool mRetrieved;

#if defined(__GNUC__) && __GNUC__ < 5
    static constexpr size_t maxResultSize = (sizeof(ResultType) > sizeof(std::error_code) ? sizeof(ResultType)
            : sizeof(std::error_code));
    static constexpr size_t maxResultAlign = (alignof(ResultType) > alignof(std::error_code) ? alignof(ResultType)
            : alignof(std::error_code));

    /// Union containing either nothing, the result or an error code
    typename std::aligned_storage<maxResultSize, maxResultAlign>::type mResult;
#else
    /// Union containing either nothing, the result or an error code
    typename std::aligned_union<0, ResultType, std::error_code>::type mResult;
#endif
};

template <typename Handler, typename Result>
RpcResponseResult<Handler, Result>::~RpcResponseResult() {
    switch (mState) {
    case RpcResponseState::SET: {
        reinterpret_cast<ResultType*>(&mResult)->~ResultType();
    } break;
    case RpcResponseState::ERROR: {
        reinterpret_cast<std::error_code*>(&mResult)->~error_code();
    } break;
    default:
        break;
    }
}

template <typename Handler, typename Result>
bool RpcResponseResult<Handler, Result>::waitForResult() {
    while (!wait()) {
    }
    LOG_ASSERT(mState != RpcResponseState::UNSET, "State is still unset after completion");

    return (mState == RpcResponseState::SET);
}

template <typename Handler, typename Result>
typename RpcResponseResult<Handler, Result>::ResultType RpcResponseResult<Handler, Result>::get() {
    if (!waitForResult()) {
        throw std::system_error(*reinterpret_cast<const std::error_code*>(&mResult));
    }

    if (mRetrieved) {
        throw std::future_error(std::future_errc::future_already_retrieved);
    }

    mRetrieved = true;
    return std::move(*reinterpret_cast<ResultType*>(&mResult));
}

template <typename Handler, typename Result>
const std::error_code& RpcResponseResult<Handler, Result>::error() {
    if (waitForResult()) {
        return detail::gEmptyErrorCode;
    }

    return *reinterpret_cast<const std::error_code*>(&mResult);
}

template <typename Handler, typename Result>
void RpcResponseResult<Handler, Result>::onResponse(uint32_t messageType, crossbow::buffer_reader& message) {
    static_assert(std::is_same<typename std::underlying_type<decltype(Handler::MessageType)>::type,
                  uint32_t>::value, "Given message type is not of the correct type");

    LOG_ASSERT(!done(), "Response is already done");
    LOG_ASSERT(mState == RpcResponseState::UNSET, "Result is already set");

    if (messageType == std::numeric_limits<uint32_t>::max()) {
        setError(message.read<uint64_t>(), Handler::errorCategory());
        return;
    }

    if (messageType != crossbow::to_underlying(Handler::MessageType)) {
        setError(error::wrong_type);
        return;
    }

    static_cast<Handler*>(this)->processResponse(message);
    if (mState == RpcResponseState::UNSET) {
        LOG_ASSERT(!done(), "Response is already done");
        setError(std::future_errc::broken_promise);
    }
}

template <typename Handler, typename Result>
void RpcResponseResult<Handler, Result>::onAbort(std::error_code ec) {
    LOG_ASSERT(!done(), "Response is already done");
    LOG_ASSERT(mState == RpcResponseState::UNSET, "Result is already set");

    setError(ec);
}

template <typename Handler, typename Result>
template <typename T, RpcResponseState State, typename... Args>
void RpcResponseResult<Handler, Result>::setInternalResult(Args&&... args) {
    static_assert(State != RpcResponseState::UNSET, "Result must not be unset");
    if (done()) {
        throw std::future_error(std::future_errc::promise_already_satisfied);
    }

    new (&mResult) T(std::forward<Args>(args)...);

    mState = State;
    complete();
}

/**
 * @brief Socket base class implementing client side basic remote procedure calls functionality
 */
class RpcClientSocket : protected BatchingMessageSocket<RpcClientSocket> {
    using Base = BatchingMessageSocket<RpcClientSocket>;

public:
    RpcClientSocket(InfinibandSocket socket, size_t maxPendingResponses = std::numeric_limits<size_t>::max(),
        size_t maxBatchSize = std::numeric_limits<size_t>::max());

protected:
    /**
     * @brief Send the synchronous request to the remote host
     *
     * Blocks the request if the connection is not yet ready - either when not yet connected or the maximum number of
     * concurrent pending responses has been reached.
     *
     * The server is expected to process all requests in the order they arrived.
     *
     * @param response The handler object to invoke when receiving the response
     * @param messageType The message type of the request to send
     * @param length The length of the message to send
     * @param fun Function writing the request to the given buffer
     */
    template <typename Fun, typename Message>
    bool sendRequest(std::shared_ptr<RpcResponse> response, Message messageType, uint32_t length, Fun fun);

    /**
     * @brief Starts a new asynchronous request with the given user ID
     *
     * The ID must be unique for all currently running asynchronous requests.
     *
     * @param userId The user ID assigned to the asynchronous request
     * @param response The handler object to invoke when receiving a response
     */
    bool startAsyncRequest(uint32_t userId, std::shared_ptr<RpcResponse> response) {
        return mAsyncResponses.insert(std::make_pair(userId, std::move(response))).second;
    }

    /**
     * @brief Send a new asynchronous request to the remote host
     *
     * Blocks the request if the connection is not yet ready - either when not yet connected or the maximum number of
     * concurrent pending responses has been reached. The request must have been started before using startAsyncRequest.
     *
     * @param userId The user ID assigned to the asynchronous request
     * @param response The handler object to invoke when receiving the response
     * @param messageType The message type of the request to send
     * @param length The length of the message to send
     * @param fun Function writing the request to the given buffer
     */
    template <typename Fun, typename Message>
    bool sendAsyncRequest(uint32_t userId, std::shared_ptr<RpcResponse> response, Message messageType, uint32_t length,
            Fun fun);

    /**
     * @brief Completes the running asynchronous request
     *
     * @param userId The user ID assigned to the asynchronous request
     */
    void completeAsyncRequest(uint32_t userId) {
        mAsyncResponses.erase(userId);
    }

private:
    friend Base;

    void onSocketConnected(const crossbow::string& data);

    void onSocketDisconnected();

    void onMessage(MessageId messageId, uint32_t messageType, crossbow::buffer_reader& message);

    void onSyncResponse(uint32_t userId, uint32_t messageType, crossbow::buffer_reader& message);

    void onAsyncResponse(uint32_t userId, uint32_t messageType, crossbow::buffer_reader& message);

    /// Current user ID incremented for each request sent
    uint32_t mUserId;

    /// Maximum number of concurrent pending responses
    size_t mMaxPendingResponses;

    /// Queue containing pending synchronous responses in the order they were sent
    std::queue<std::tuple<uint32_t, std::shared_ptr<RpcResponse>>> mSyncResponses;

    /// Map containing asynchronous response not yet processed by the remote host
    google::dense_hash_map<uint32_t, std::shared_ptr<RpcResponse>> mAsyncResponses;

    /// Requests waiting for the connection to become ready
    ConditionVariable mWaitingRequests;
};

template <typename Fun, typename Message>
bool RpcClientSocket::sendRequest(std::shared_ptr<RpcResponse> response, Message messageType, uint32_t length,
        Fun fun) {
    static_assert(std::is_same<typename std::underlying_type<Message>::type, uint32_t>::value,
            "Given message type is not of the correct type");
    LOG_ASSERT(crossbow::to_underlying(messageType) != std::numeric_limits<uint32_t>::max(), "Invalid message type");

    mWaitingRequests.wait(response->fiber(), [this] () {
        return (state() != ConnectionState::CONNECTING) && (mSyncResponses.size() < mMaxPendingResponses);
    });

    if (!isConnected()) {
        response->onAbort(std::make_error_code(std::errc::connection_aborted));
        return false;
    }

    ++mUserId;

    MessageId messageId(mUserId, false);
    std::error_code ec;
    this->writeMessage(messageId, crossbow::to_underlying(messageType), length, std::move(fun), ec);
    if (ec) {
        response->onAbort(std::move(ec));
        return false;
    }

    mSyncResponses.emplace(mUserId, std::move(response));
    return true;
}

template <typename Fun, typename Message>
bool RpcClientSocket::sendAsyncRequest(uint32_t userId, std::shared_ptr<RpcResponse> response, Message messageType,
        uint32_t length, Fun fun) {
    static_assert(std::is_same<typename std::underlying_type<Message>::type, uint32_t>::value,
            "Given message type is not of the correct type");
    LOG_ASSERT(crossbow::to_underlying(messageType) != std::numeric_limits<uint32_t>::max(), "Invalid message type");

    mWaitingRequests.wait(response->fiber(), [this] () {
        return (state() != ConnectionState::CONNECTING);
    });

    if (!isConnected()) {
        response->onAbort(std::make_error_code(std::errc::connection_aborted));
        return false;
    }

    MessageId messageId(userId, true);
    std::error_code ec;
    this->writeMessage(messageId, crossbow::to_underlying(messageType), length, std::move(fun), ec);
    if (ec) {
        response->onAbort(std::move(ec));
        return false;
    }
    return true;
}

} // namespace infinio
} // namespace crossbow
<commit_msg>Add specialization for RpcResponseResult when Result is void<commit_after>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 */
#pragma once

#include <crossbow/byte_buffer.hpp>
#include <crossbow/enum_underlying.hpp>
#include <crossbow/infinio/BatchingMessageSocket.hpp>
#include <crossbow/infinio/Fiber.hpp>
#include <crossbow/logger.hpp>
#include <crossbow/string.hpp>

#include <sparsehash/dense_hash_map>

#include <cstdint>
#include <limits>
#include <queue>
#include <system_error>
#include <tuple>
#include <type_traits>

namespace crossbow {
namespace infinio {
namespace detail {

extern const std::error_code gEmptyErrorCode;

} // namespace detail

class Fiber;

/**
 * @brief Base class representing a pending RPC response
 */
class RpcResponse {
public:
    /**
     * @brief Suspend the fiber until notified by another context or an response was received
     *
     * Blocks until notify() or complete() are called.
     *
     * @return Whether an response was received
     */
    bool wait();

    /**
     * @brief Whether an response was received
     */
    bool done() const {
        return !mPending;
    }

    Fiber& fiber() {
        return mFiber;
    }

protected:
    RpcResponse(Fiber& fiber)
            : mFiber(fiber),
              mPending(true),
              mWaiting(false) {
    }

    virtual ~RpcResponse();

    /**
     * @brief Notifies the response fiber of any event
     *
     * Will resume the fiber if it is waiting.
     */
    void notify();

    /**
     * @brief Notifies the response fiber of its completion
     *
     * Will resume the fiber if it is waiting.
     */
    void complete();

private:
    friend class RpcClientSocket;

    /**
     * @brief Called when a response with the given message type was received
     *
     * @param messageType The type of the received message
     * @param message The response message
     */
    virtual void onResponse(uint32_t messageType, crossbow::buffer_reader& message) = 0;

    /**
     * @brief Called when the RPC was aborted due to an error
     */
    virtual void onAbort(std::error_code ec) = 0;

    Fiber& mFiber;

    bool mPending;
    bool mWaiting;
};

enum class RpcResponseState {
    UNSET,
    SET,
    ERROR,
};

/**
 * @brief Class holding a future RPC response
 */
template <typename Handler, typename Result>
class RpcResponseResult : public RpcResponse {
public:
    using ResultType = Result;

    RpcResponseResult(Fiber& fiber)
            : RpcResponse(fiber),
              mState(RpcResponseState::UNSET),
              mRetrieved(false) {
    }

    virtual ~RpcResponseResult();

    /**
     * @brief Suspend the fiber until the response was received
     *
     * @return Whether the response is valid (contains an error otherwise)
     */
    bool waitForResult();

    /**
     * @brief Retrieve the response of the request
     *
     * Blocks until the response has been received.
     *
     * The result can only be retrieved once. An exception is thrown if the result is invalid or was already retrieved.
     *
     * @exception std::system_error The result is invalid
     * @exception std::future_error The result was already retrieved
     * @return The result of the RPC request
     */
    ResultType get();

    /**
     * @brief The error code if the response completed with an error
     *
     * Blocks until the response has been received.
     */
    const std::error_code& error();

protected:
    template <typename... Args>
    void setResult(Args&&... args) {
        setInternalResult<ResultType, RpcResponseState::SET, Args...>(std::forward<Args>(args)...);
    }

    template <typename... Args>
    void setError(Args&&... args) {
        setInternalResult<std::error_code, RpcResponseState::ERROR, Args...>(std::forward<Args>(args)...);
    }

private:
    virtual void onResponse(uint32_t messageType, crossbow::buffer_reader& message) final override;

    virtual void onAbort(std::error_code ec) final override;

    template <typename T, RpcResponseState State, typename... Args>
    void setInternalResult(Args&&... args);

    /// The state of the result container
    RpcResponseState mState;

    /// Whether the result was retrieved
    bool mRetrieved;

#if defined(__GNUC__) && __GNUC__ < 5
    static constexpr size_t maxResultSize = (sizeof(ResultType) > sizeof(std::error_code) ? sizeof(ResultType)
            : sizeof(std::error_code));
    static constexpr size_t maxResultAlign = (alignof(ResultType) > alignof(std::error_code) ? alignof(ResultType)
            : alignof(std::error_code));

    /// Union containing either nothing, the result or an error code
    typename std::aligned_storage<maxResultSize, maxResultAlign>::type mResult;
#else
    /// Union containing either nothing, the result or an error code
    typename std::aligned_union<0, ResultType, std::error_code>::type mResult;
#endif
};

template <typename Handler, typename Result>
RpcResponseResult<Handler, Result>::~RpcResponseResult() {
    switch (mState) {
    case RpcResponseState::SET: {
        reinterpret_cast<ResultType*>(&mResult)->~ResultType();
    } break;
    case RpcResponseState::ERROR: {
        reinterpret_cast<std::error_code*>(&mResult)->~error_code();
    } break;
    default:
        break;
    }
}

template <typename Handler, typename Result>
bool RpcResponseResult<Handler, Result>::waitForResult() {
    while (!wait()) {
    }
    LOG_ASSERT(mState != RpcResponseState::UNSET, "State is still unset after completion");

    return (mState != RpcResponseState::ERROR);
}

template <typename Handler, typename Result>
typename RpcResponseResult<Handler, Result>::ResultType RpcResponseResult<Handler, Result>::get() {
    if (!waitForResult()) {
        throw std::system_error(*reinterpret_cast<const std::error_code*>(&mResult));
    }

    if (mRetrieved) {
        throw std::future_error(std::future_errc::future_already_retrieved);
    }

    mRetrieved = true;
    return std::move(*reinterpret_cast<ResultType*>(&mResult));
}

template <typename Handler, typename Result>
const std::error_code& RpcResponseResult<Handler, Result>::error() {
    if (waitForResult()) {
        return detail::gEmptyErrorCode;
    }

    return *reinterpret_cast<const std::error_code*>(&mResult);
}

template <typename Handler, typename Result>
void RpcResponseResult<Handler, Result>::onResponse(uint32_t messageType, crossbow::buffer_reader& message) {
    static_assert(std::is_same<typename std::underlying_type<decltype(Handler::MessageType)>::type,
                  uint32_t>::value, "Given message type is not of the correct type");

    LOG_ASSERT(!done(), "Response is already done");
    LOG_ASSERT(mState == RpcResponseState::UNSET, "Result is already set");

    if (messageType == std::numeric_limits<uint32_t>::max()) {
        setError(message.read<uint64_t>(), Handler::errorCategory());
        return;
    }

    if (messageType != crossbow::to_underlying(Handler::MessageType)) {
        setError(error::wrong_type);
        return;
    }

    static_cast<Handler*>(this)->processResponse(message);
    if (mState == RpcResponseState::UNSET) {
        LOG_ASSERT(!done(), "Response is already done");
        setError(std::future_errc::broken_promise);
    }
}

template <typename Handler, typename Result>
void RpcResponseResult<Handler, Result>::onAbort(std::error_code ec) {
    LOG_ASSERT(!done(), "Response is already done");
    LOG_ASSERT(mState == RpcResponseState::UNSET, "Result is already set");

    setError(ec);
}

template <typename Handler, typename Result>
template <typename T, RpcResponseState State, typename... Args>
void RpcResponseResult<Handler, Result>::setInternalResult(Args&&... args) {
    static_assert(State != RpcResponseState::UNSET, "Result must not be unset");
    if (done()) {
        throw std::future_error(std::future_errc::promise_already_satisfied);
    }

    new (&mResult) T(std::forward<Args>(args)...);

    mState = State;
    complete();
}

/**
 * @brief Class holding a future RPC response
 */
template <typename Handler>
class RpcResponseResult<Handler, void> : public RpcResponse {
public:
    RpcResponseResult<Handler, void>(Fiber& fiber)
            : RpcResponse(fiber) {
    }

    /**
     * @brief Suspend the fiber until the response was received
     *
     * @return Whether the response is valid (contains an error otherwise)
     */
    bool waitForResult();

    /**
     * @brief The error code if the response completed with an error
     *
     * Blocks until the response has been received.
     */
    const std::error_code& error();

protected:
    template <typename... Args>
    void setError(Args&&... args) {
        mError = std::error_code(std::forward<Args>(args)...);
    }

private:
    virtual void onResponse(uint32_t messageType, crossbow::buffer_reader& message) final override;

    virtual void onAbort(std::error_code ec) final override;

    /// The resulting error code (or empty if successful)
    std::error_code mError;
};

template <typename Handler>
bool RpcResponseResult<Handler, void>::waitForResult() {
    while (!wait()) {
    }

    return !mError;
}

template <typename Handler>
const std::error_code& RpcResponseResult<Handler, void>::error() {
    waitForResult();
    return mError;
}

template <typename Handler>
void RpcResponseResult<Handler, void>::onResponse(uint32_t messageType, crossbow::buffer_reader& message) {
    static_assert(std::is_same<typename std::underlying_type<decltype(Handler::MessageType)>::type,
                  uint32_t>::value, "Given message type is not of the correct type");

    LOG_ASSERT(!done(), "Response is already done");

    if (messageType == std::numeric_limits<uint32_t>::max()) {
        onAbort({message.read<uint64_t>(), Handler::errorCategory()});
        return;
    }

    if (messageType != crossbow::to_underlying(Handler::MessageType)) {
        onAbort(error::wrong_type);
        return;
    }

    static_cast<Handler*>(this)->processResponse(message);
    complete();
}

template <typename Handler>
void RpcResponseResult<Handler, void>::onAbort(std::error_code ec) {
    LOG_ASSERT(!done(), "Response is already done");

    mError = std::move(ec);
    complete();
}

/**
 * @brief Socket base class implementing client side basic remote procedure calls functionality
 */
class RpcClientSocket : protected BatchingMessageSocket<RpcClientSocket> {
    using Base = BatchingMessageSocket<RpcClientSocket>;

public:
    RpcClientSocket(InfinibandSocket socket, size_t maxPendingResponses = std::numeric_limits<size_t>::max(),
        size_t maxBatchSize = std::numeric_limits<size_t>::max());

protected:
    /**
     * @brief Send the synchronous request to the remote host
     *
     * Blocks the request if the connection is not yet ready - either when not yet connected or the maximum number of
     * concurrent pending responses has been reached.
     *
     * The server is expected to process all requests in the order they arrived.
     *
     * @param response The handler object to invoke when receiving the response
     * @param messageType The message type of the request to send
     * @param length The length of the message to send
     * @param fun Function writing the request to the given buffer
     */
    template <typename Fun, typename Message>
    bool sendRequest(std::shared_ptr<RpcResponse> response, Message messageType, uint32_t length, Fun fun);

    /**
     * @brief Starts a new asynchronous request with the given user ID
     *
     * The ID must be unique for all currently running asynchronous requests.
     *
     * @param userId The user ID assigned to the asynchronous request
     * @param response The handler object to invoke when receiving a response
     */
    bool startAsyncRequest(uint32_t userId, std::shared_ptr<RpcResponse> response) {
        return mAsyncResponses.insert(std::make_pair(userId, std::move(response))).second;
    }

    /**
     * @brief Send a new asynchronous request to the remote host
     *
     * Blocks the request if the connection is not yet ready - either when not yet connected or the maximum number of
     * concurrent pending responses has been reached. The request must have been started before using startAsyncRequest.
     *
     * @param userId The user ID assigned to the asynchronous request
     * @param response The handler object to invoke when receiving the response
     * @param messageType The message type of the request to send
     * @param length The length of the message to send
     * @param fun Function writing the request to the given buffer
     */
    template <typename Fun, typename Message>
    bool sendAsyncRequest(uint32_t userId, std::shared_ptr<RpcResponse> response, Message messageType, uint32_t length,
            Fun fun);

    /**
     * @brief Completes the running asynchronous request
     *
     * @param userId The user ID assigned to the asynchronous request
     */
    void completeAsyncRequest(uint32_t userId) {
        mAsyncResponses.erase(userId);
    }

private:
    friend Base;

    void onSocketConnected(const crossbow::string& data);

    void onSocketDisconnected();

    void onMessage(MessageId messageId, uint32_t messageType, crossbow::buffer_reader& message);

    void onSyncResponse(uint32_t userId, uint32_t messageType, crossbow::buffer_reader& message);

    void onAsyncResponse(uint32_t userId, uint32_t messageType, crossbow::buffer_reader& message);

    /// Current user ID incremented for each request sent
    uint32_t mUserId;

    /// Maximum number of concurrent pending responses
    size_t mMaxPendingResponses;

    /// Queue containing pending synchronous responses in the order they were sent
    std::queue<std::tuple<uint32_t, std::shared_ptr<RpcResponse>>> mSyncResponses;

    /// Map containing asynchronous response not yet processed by the remote host
    google::dense_hash_map<uint32_t, std::shared_ptr<RpcResponse>> mAsyncResponses;

    /// Requests waiting for the connection to become ready
    ConditionVariable mWaitingRequests;
};

template <typename Fun, typename Message>
bool RpcClientSocket::sendRequest(std::shared_ptr<RpcResponse> response, Message messageType, uint32_t length,
        Fun fun) {
    static_assert(std::is_same<typename std::underlying_type<Message>::type, uint32_t>::value,
            "Given message type is not of the correct type");
    LOG_ASSERT(crossbow::to_underlying(messageType) != std::numeric_limits<uint32_t>::max(), "Invalid message type");

    mWaitingRequests.wait(response->fiber(), [this] () {
        return (state() != ConnectionState::CONNECTING) && (mSyncResponses.size() < mMaxPendingResponses);
    });

    if (!isConnected()) {
        response->onAbort(std::make_error_code(std::errc::connection_aborted));
        return false;
    }

    ++mUserId;

    MessageId messageId(mUserId, false);
    std::error_code ec;
    this->writeMessage(messageId, crossbow::to_underlying(messageType), length, std::move(fun), ec);
    if (ec) {
        response->onAbort(std::move(ec));
        return false;
    }

    mSyncResponses.emplace(mUserId, std::move(response));
    return true;
}

template <typename Fun, typename Message>
bool RpcClientSocket::sendAsyncRequest(uint32_t userId, std::shared_ptr<RpcResponse> response, Message messageType,
        uint32_t length, Fun fun) {
    static_assert(std::is_same<typename std::underlying_type<Message>::type, uint32_t>::value,
            "Given message type is not of the correct type");
    LOG_ASSERT(crossbow::to_underlying(messageType) != std::numeric_limits<uint32_t>::max(), "Invalid message type");

    mWaitingRequests.wait(response->fiber(), [this] () {
        return (state() != ConnectionState::CONNECTING);
    });

    if (!isConnected()) {
        response->onAbort(std::make_error_code(std::errc::connection_aborted));
        return false;
    }

    MessageId messageId(userId, true);
    std::error_code ec;
    this->writeMessage(messageId, crossbow::to_underlying(messageType), length, std::move(fun), ec);
    if (ec) {
        response->onAbort(std::move(ec));
        return false;
    }
    return true;
}

} // namespace infinio
} // namespace crossbow
<|endoftext|>


<commit_before>/**************************************************************************
** This file is part of LiteIDE
**
** Copyright (c) 2011-2016 LiteIDE Team. All rights reserved.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** In addition, as a special exception,  that plugins developed for LiteIDE,
** are allowed to remain closed sourced and can be distributed under any license .
** These rights are included in the file LGPL_EXCEPTION.txt in this package.
**
**************************************************************************/
// Module: quickopenmanager.cpp
// Creator: visualfc <visualfc@gmail.com>

#include "quickopenmanager.h"
#include "quickopen_global.h"
#include "quickopenfiles.h"
#include "quickopeneditor.h"
#include "quickopenmimetype.h"
#include <QTreeView>
#include <QDebug>

//lite_memory_check_begin
#if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
     #define _CRTDBG_MAP_ALLOC
     #include <stdlib.h>
     #include <crtdbg.h>
     #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
     #define new DEBUG_NEW
#endif
//lite_memory_check_end

QuickOpenManager::QuickOpenManager(QObject *parent) : LiteApi::IQuickOpenManager(parent)
{

}

QuickOpenManager::~QuickOpenManager()
{

}

bool QuickOpenManager::initWithApp(IApplication *app)
{
    if (!IQuickOpenManager::initWithApp(app)) {
        return false;
    }

    m_liteApp->extension()->addObject("LiteApi.IQuickOpenManager",this);

    m_widget = new QuickOpenWidget(m_liteApp,m_liteApp->mainWindow());
    m_widget->editor()->setPlaceholderText(tr("Type '?' to get help on the actions you can take from here"));

    connect(m_widget->editor(),SIGNAL(textChanged(QString)),this,SLOT(filterChanged(QString)));
    connect(m_widget->editor(),SIGNAL(returnPressed()),this,SLOT(selected()));
    connect(m_widget->view(),SIGNAL(clicked(QModelIndex)),this,SLOT(selected()));
    connect(m_widget->view(),SIGNAL(activated(QModelIndex)),this,SLOT(selected()));
    connect(m_widget,SIGNAL(hidePopup()),this,SLOT(hideQuickOpen()));
    connect(m_widget,SIGNAL(indexChanage(QModelIndex)),this,SLOT(indexChanage(QModelIndex)));

    m_quickOpenFiles = new QuickOpenFiles(app,this);

    //setCurrentFilter(m_quickOpenFiles);
    m_filterMap.insert("",m_quickOpenFiles);
    m_filterMap.insert("~",new QuickOpenEditor(m_liteApp,this));

    this->registerQuickOpenMimeType("@");
    m_quickOpenAct = new QAction(tr("Quick Open"),this);
    m_quickOpenAct->setData("");

    m_quickOpenEditAct = new QAction(tr("Quick Open Editor"),this);
    m_quickOpenEditAct->setData("~");

    m_quickOpenSymbolAct = new QAction(tr("Quick Open Symbol"),this);
    m_quickOpenSymbolAct->setData("@");

    m_liteApp->actionManager()->setViewMenuSeparator("sep/quickopen",true);

    LiteApi::IActionContext *context = m_liteApp->actionManager()->getActionContext(m_liteApp,"App");
    context->regAction(m_quickOpenAct,"QuickOpen","CTRL+P");
    context->regAction(m_quickOpenEditAct,"QuickOpenEditor","CTRL+ALT+P");
    context->regAction(m_quickOpenSymbolAct,"QuickOpenSymbol","CTRL+ALT+O");

    m_liteApp->actionManager()->insertViewMenuAction(m_quickOpenAct,"sep/quickopen");
    m_liteApp->actionManager()->insertViewMenuAction(m_quickOpenEditAct,"sep/quickopen");
    m_liteApp->actionManager()->insertViewMenuAction(m_quickOpenSymbolAct,"sep/quickopen");

    connect(m_quickOpenAct,SIGNAL(triggered(bool)),this,SLOT(quickOpen()));
    connect(m_quickOpenEditAct,SIGNAL(triggered(bool)),this,SLOT(quickOpen()));
    connect(m_quickOpenSymbolAct,SIGNAL(triggered(bool)),this,SLOT(quickOpen()));

    return true;
}

void QuickOpenManager::addFilter(const QString &sym, IQuickOpen *filter)
{
    if (filter == 0) {
        return;
    }
    if (sym.isEmpty()) {
        m_liteApp->appendLog("QuickOpen",QString("warning, skip empty symbol, id=%1").arg(filter->id()),true);
        return;
    }
    m_filterMap.insert(sym,filter);
}

void QuickOpenManager::removeFilter(IQuickOpen *filter)
{
    QMutableMapIterator<QString,IQuickOpen*> i(m_filterMap);
    while (i.hasNext()) {
        i.next();
        if (i.value() == filter) {
            m_filterMap.remove(i.key());
            break;
        }
    }
}

QList<IQuickOpen *> QuickOpenManager::filterList() const
{
    return m_filterMap.values();
}

QMap<QString, IQuickOpen *> QuickOpenManager::filterMap() const
{
    return m_filterMap;
}

void QuickOpenManager::setCurrentFilter(IQuickOpen *filter)
{
    if (filter) {
        filter->activate();
    }
    if (m_currentFilter == filter) {
        return;
    }
    m_currentFilter = filter;
    if (m_currentFilter) {
        m_sym = m_filterMap.key(filter);
        m_widget->setModel(m_currentFilter->model());
    }
}

IQuickOpen *QuickOpenManager::currentFilter() const
{
    return m_currentFilter;
}

QModelIndex QuickOpenManager::currentIndex() const
{
    return m_widget->view()->currentIndex();
}

void QuickOpenManager::showById(const QString &id)
{
    IQuickOpen *i = findById(id);
    if (i) {
        setCurrentFilter(i);
        showQuickOpen();
    }
}

void QuickOpenManager::showBySymbol(const QString &sym)
{
    IQuickOpen *i = findBySymbol(sym);
    if (i == 0) {
        i = m_quickOpenFiles;
    }
    if (i) {
        setCurrentFilter(i);
        showQuickOpen();
    }
}

IQuickOpen *QuickOpenManager::findById(const QString &id)
{
    QMutableMapIterator<QString,IQuickOpen*> i(m_filterMap);
    while (i.hasNext()) {
        i.next();
        if (i.value()->id() == id) {
            return i.value();
        }
    }
    if (id == m_quickOpenFiles->id()) {
        return m_quickOpenFiles;
    }
    return 0;
}

IQuickOpen *QuickOpenManager::findBySymbol(const QString &sym)
{
    QMutableMapIterator<QString,IQuickOpen*> i(m_filterMap);
    while (i.hasNext()) {
        i.next();
        if (i.key() == sym) {
            return i.value();
        }
    }
    return 0;
}

QTreeView *QuickOpenManager::modelView() const
{
    return m_widget->view();
}

IQuickOpenMimeType *QuickOpenManager::registerQuickOpenMimeType(const QString &sym)
{
    IQuickOpenMimeType *symbol = m_quickOpenSymbolMap[sym];
    if (!symbol) {
        symbol = new QuickOpenMimeType(m_liteApp,this);
        this->addFilter(sym,symbol);
    }
    return symbol;
}

void QuickOpenManager::quickOpen()
{
    m_updateMap.clear();
    QString sym;
    QAction *act = (QAction*)sender();
    if (act) {
        sym = act->data().toString();
    }
    showBySymbol(sym);
}

void QuickOpenManager::quickOpenEditor()
{
    showById("quickopen/editor");
}

void QuickOpenManager::updateModel()
{
    if (!m_currentFilter) {
        return;
    }
    if (m_updateMap.value(m_currentFilter)) {
        return;
    }
    m_updateMap.insert(m_currentFilter,true);
    m_currentFilter->updateModel();
    m_widget->view()->resizeColumnToContents(0);
}

void QuickOpenManager::showQuickOpen()
{
    updateModel();
    m_widget->editor()->setText(m_sym);
    m_widget->showView();
}

void QuickOpenManager::hideQuickOpen()
{
    m_widget->close();
    m_updateMap.clear();
    m_currentFilter = 0;
    m_sym.clear();
}

void QuickOpenManager::filterChanged(const QString &text)
{
    IQuickOpen *quick = 0;
    if (!text.isEmpty()) {
        QMapIterator<QString,IQuickOpen*> i(m_filterMap);
        QString mimeType;
        LiteApi::IEditor *cur = m_liteApp->editorManager()->currentEditor();
        if (cur) {
            mimeType = cur->mimeType();
        }
        while (i.hasNext()) {
            i.next();
            if (i.key().isEmpty()) {
                continue;
            }
            if (text.startsWith(i.key())) {
                quick = i.value();
                break;
            }
        }
    }
    if (quick == 0)  {
        quick = m_quickOpenFiles;
    }
    if (quick != m_currentFilter) {
        this->setCurrentFilter(quick);
        updateModel();
    }
    if (m_currentFilter) {
        QModelIndex index = m_currentFilter->filterChanged(text.mid(m_sym.size()));
        m_widget->view()->setCurrentIndex(index);
        m_widget->view()->scrollTo(index);
    }
}

void QuickOpenManager::indexChanage(const QModelIndex &index)
{
    if (m_currentFilter) {
        m_currentFilter->indexChanged(index);
    }
}

void QuickOpenManager::selected()
{
    if (!m_currentFilter) {
        return;
    }
    QString text = m_widget->editor()->text();
    QModelIndex index = m_widget->view()->currentIndex();
    if (!m_currentFilter->selected(text.mid(m_sym.size()),index)) {
        return;
    }
    this->hideQuickOpen();
}

<commit_msg>quickopen symbol shortcut ctrl+shift+o<commit_after>/**************************************************************************
** This file is part of LiteIDE
**
** Copyright (c) 2011-2016 LiteIDE Team. All rights reserved.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** In addition, as a special exception,  that plugins developed for LiteIDE,
** are allowed to remain closed sourced and can be distributed under any license .
** These rights are included in the file LGPL_EXCEPTION.txt in this package.
**
**************************************************************************/
// Module: quickopenmanager.cpp
// Creator: visualfc <visualfc@gmail.com>

#include "quickopenmanager.h"
#include "quickopen_global.h"
#include "quickopenfiles.h"
#include "quickopeneditor.h"
#include "quickopenmimetype.h"
#include <QTreeView>
#include <QDebug>

//lite_memory_check_begin
#if defined(WIN32) && defined(_MSC_VER) &&  defined(_DEBUG)
     #define _CRTDBG_MAP_ALLOC
     #include <stdlib.h>
     #include <crtdbg.h>
     #define DEBUG_NEW new( _NORMAL_BLOCK, __FILE__, __LINE__ )
     #define new DEBUG_NEW
#endif
//lite_memory_check_end

QuickOpenManager::QuickOpenManager(QObject *parent) : LiteApi::IQuickOpenManager(parent)
{

}

QuickOpenManager::~QuickOpenManager()
{

}

bool QuickOpenManager::initWithApp(IApplication *app)
{
    if (!IQuickOpenManager::initWithApp(app)) {
        return false;
    }

    m_liteApp->extension()->addObject("LiteApi.IQuickOpenManager",this);

    m_widget = new QuickOpenWidget(m_liteApp,m_liteApp->mainWindow());
    m_widget->editor()->setPlaceholderText(tr("Type '?' to get help on the actions you can take from here"));

    connect(m_widget->editor(),SIGNAL(textChanged(QString)),this,SLOT(filterChanged(QString)));
    connect(m_widget->editor(),SIGNAL(returnPressed()),this,SLOT(selected()));
    connect(m_widget->view(),SIGNAL(clicked(QModelIndex)),this,SLOT(selected()));
    connect(m_widget->view(),SIGNAL(activated(QModelIndex)),this,SLOT(selected()));
    connect(m_widget,SIGNAL(hidePopup()),this,SLOT(hideQuickOpen()));
    connect(m_widget,SIGNAL(indexChanage(QModelIndex)),this,SLOT(indexChanage(QModelIndex)));

    m_quickOpenFiles = new QuickOpenFiles(app,this);

    //setCurrentFilter(m_quickOpenFiles);
    m_filterMap.insert("",m_quickOpenFiles);
    m_filterMap.insert("~",new QuickOpenEditor(m_liteApp,this));

    this->registerQuickOpenMimeType("@");
    m_quickOpenAct = new QAction(tr("Quick Open"),this);
    m_quickOpenAct->setData("");

    m_quickOpenEditAct = new QAction(tr("Quick Open Editor"),this);
    m_quickOpenEditAct->setData("~");

    m_quickOpenSymbolAct = new QAction(tr("Quick Open Symbol"),this);
    m_quickOpenSymbolAct->setData("@");

    m_liteApp->actionManager()->setViewMenuSeparator("sep/quickopen",true);

    LiteApi::IActionContext *context = m_liteApp->actionManager()->getActionContext(m_liteApp,"App");
    context->regAction(m_quickOpenAct,"QuickOpen","CTRL+P");
    context->regAction(m_quickOpenEditAct,"QuickOpenEditor","CTRL+ALT+P");
    context->regAction(m_quickOpenSymbolAct,"QuickOpenSymbol","CTRL+SHIFT+O");

    m_liteApp->actionManager()->insertViewMenuAction(m_quickOpenAct,"sep/quickopen");
    m_liteApp->actionManager()->insertViewMenuAction(m_quickOpenEditAct,"sep/quickopen");
    m_liteApp->actionManager()->insertViewMenuAction(m_quickOpenSymbolAct,"sep/quickopen");

    connect(m_quickOpenAct,SIGNAL(triggered(bool)),this,SLOT(quickOpen()));
    connect(m_quickOpenEditAct,SIGNAL(triggered(bool)),this,SLOT(quickOpen()));
    connect(m_quickOpenSymbolAct,SIGNAL(triggered(bool)),this,SLOT(quickOpen()));

    return true;
}

void QuickOpenManager::addFilter(const QString &sym, IQuickOpen *filter)
{
    if (filter == 0) {
        return;
    }
    if (sym.isEmpty()) {
        m_liteApp->appendLog("QuickOpen",QString("warning, skip empty symbol, id=%1").arg(filter->id()),true);
        return;
    }
    m_filterMap.insert(sym,filter);
}

void QuickOpenManager::removeFilter(IQuickOpen *filter)
{
    QMutableMapIterator<QString,IQuickOpen*> i(m_filterMap);
    while (i.hasNext()) {
        i.next();
        if (i.value() == filter) {
            m_filterMap.remove(i.key());
            break;
        }
    }
}

QList<IQuickOpen *> QuickOpenManager::filterList() const
{
    return m_filterMap.values();
}

QMap<QString, IQuickOpen *> QuickOpenManager::filterMap() const
{
    return m_filterMap;
}

void QuickOpenManager::setCurrentFilter(IQuickOpen *filter)
{
    if (filter) {
        filter->activate();
    }
    if (m_currentFilter == filter) {
        return;
    }
    m_currentFilter = filter;
    if (m_currentFilter) {
        m_sym = m_filterMap.key(filter);
        m_widget->setModel(m_currentFilter->model());
    }
}

IQuickOpen *QuickOpenManager::currentFilter() const
{
    return m_currentFilter;
}

QModelIndex QuickOpenManager::currentIndex() const
{
    return m_widget->view()->currentIndex();
}

void QuickOpenManager::showById(const QString &id)
{
    IQuickOpen *i = findById(id);
    if (i) {
        setCurrentFilter(i);
        showQuickOpen();
    }
}

void QuickOpenManager::showBySymbol(const QString &sym)
{
    IQuickOpen *i = findBySymbol(sym);
    if (i == 0) {
        i = m_quickOpenFiles;
    }
    if (i) {
        setCurrentFilter(i);
        showQuickOpen();
    }
}

IQuickOpen *QuickOpenManager::findById(const QString &id)
{
    QMutableMapIterator<QString,IQuickOpen*> i(m_filterMap);
    while (i.hasNext()) {
        i.next();
        if (i.value()->id() == id) {
            return i.value();
        }
    }
    if (id == m_quickOpenFiles->id()) {
        return m_quickOpenFiles;
    }
    return 0;
}

IQuickOpen *QuickOpenManager::findBySymbol(const QString &sym)
{
    QMutableMapIterator<QString,IQuickOpen*> i(m_filterMap);
    while (i.hasNext()) {
        i.next();
        if (i.key() == sym) {
            return i.value();
        }
    }
    return 0;
}

QTreeView *QuickOpenManager::modelView() const
{
    return m_widget->view();
}

IQuickOpenMimeType *QuickOpenManager::registerQuickOpenMimeType(const QString &sym)
{
    IQuickOpenMimeType *symbol = m_quickOpenSymbolMap[sym];
    if (!symbol) {
        symbol = new QuickOpenMimeType(m_liteApp,this);
        this->addFilter(sym,symbol);
    }
    return symbol;
}

void QuickOpenManager::quickOpen()
{
    m_updateMap.clear();
    QString sym;
    QAction *act = (QAction*)sender();
    if (act) {
        sym = act->data().toString();
    }
    showBySymbol(sym);
}

void QuickOpenManager::quickOpenEditor()
{
    showById("quickopen/editor");
}

void QuickOpenManager::updateModel()
{
    if (!m_currentFilter) {
        return;
    }
    if (m_updateMap.value(m_currentFilter)) {
        return;
    }
    m_updateMap.insert(m_currentFilter,true);
    m_currentFilter->updateModel();
    m_widget->view()->resizeColumnToContents(0);
}

void QuickOpenManager::showQuickOpen()
{
    updateModel();
    m_widget->editor()->setText(m_sym);
    m_widget->showView();
}

void QuickOpenManager::hideQuickOpen()
{
    m_widget->close();
    m_updateMap.clear();
    m_currentFilter = 0;
    m_sym.clear();
}

void QuickOpenManager::filterChanged(const QString &text)
{
    IQuickOpen *quick = 0;
    if (!text.isEmpty()) {
        QMapIterator<QString,IQuickOpen*> i(m_filterMap);
        QString mimeType;
        LiteApi::IEditor *cur = m_liteApp->editorManager()->currentEditor();
        if (cur) {
            mimeType = cur->mimeType();
        }
        while (i.hasNext()) {
            i.next();
            if (i.key().isEmpty()) {
                continue;
            }
            if (text.startsWith(i.key())) {
                quick = i.value();
                break;
            }
        }
    }
    if (quick == 0)  {
        quick = m_quickOpenFiles;
    }
    if (quick != m_currentFilter) {
        this->setCurrentFilter(quick);
        updateModel();
    }
    if (m_currentFilter) {
        QModelIndex index = m_currentFilter->filterChanged(text.mid(m_sym.size()));
        m_widget->view()->setCurrentIndex(index);
        m_widget->view()->scrollTo(index);
    }
}

void QuickOpenManager::indexChanage(const QModelIndex &index)
{
    if (m_currentFilter) {
        m_currentFilter->indexChanged(index);
    }
}

void QuickOpenManager::selected()
{
    if (!m_currentFilter) {
        return;
    }
    QString text = m_widget->editor()->text();
    QModelIndex index = m_widget->view()->currentIndex();
    if (!m_currentFilter->selected(text.mid(m_sym.size()),index)) {
        return;
    }
    this->hideQuickOpen();
}

<|endoftext|>


<commit_before>#include "QPulseAudioDeviceChooser.hpp"
#include <QSettings>
#include <QtDebug>

void QPulseAudioDeviceChooser::writeSettings()
{

	QSettings settings ( "projectM", "qprojectM-pulseaudio" );
	settings.setValue ( "tryFirstAvailablePlaybackMonitor",
	                    this->tryFirstPlayBackMonitorCheckBox->checkState() == Qt::Checked );
	//settings.setValue ("pulseAudioSourceDevice", this->listView.data(
}

void QPulseAudioDeviceChooser::readSettings()
{

	QSettings settings ( "projectM", "qprojectM-pulseaudio" );

	bool tryFirst = settings.value
	                ( "tryFirstAvailablePlaybackMonitor", true ).toBool() ;

	this->tryFirstPlayBackMonitorCheckBox->setCheckState
	( tryFirst ? Qt::Checked : Qt::Unchecked );

	if ( tryFirst )
	{
		this->devicesListView->setEnabled(false);
	} else {
		this->devicesListView->setEnabled(true);
	}

}

void QPulseAudioDeviceChooser::updateDevicesListViewLock(int state) {
		devicesListView->setEnabled(state != Qt::Checked);

}

QPulseAudioDeviceChooser::QPulseAudioDeviceChooser ( QPulseAudioThread * qpulseAudioThread, QWidget * parent = 0, Qt::WindowFlags f ) : QDialog ( parent, f ), _qpulseAudioDeviceModel ( qpulseAudioThread->devices(), this ), _qpulseAudioThread ( qpulseAudioThread )
{

	setupUi ( this );
	readSettings();
	qDebug() << "setting model";
	this->devicesListView->setModel ( &_qpulseAudioDeviceModel );

// void QAbstractItemView::selectionChanged ( const QItemSelection & selected, const QItemSelection & deselected )   [virtual protected slot]

	connect ( tryFirstPlayBackMonitorCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateDevicesListViewLock(int)));

	/// @bug wrong! should be based on HASH index, not display index
	connect ( devicesListView, SIGNAL ( doubleClicked ( const QModelIndex& ) ), _qpulseAudioThread, SLOT ( connectDevice ( const QModelIndex& ) ) );
	//connect(buttonBox, SIGNAL(accepted()), _qpulseAudioThread, SLOT(connectDevice(device));
}

void QPulseAudioDeviceChooser::open()
{

	this->show();

}

<commit_msg>nonexistant bug fixed<commit_after>#include "QPulseAudioDeviceChooser.hpp"
#include <QSettings>
#include <QtDebug>

void QPulseAudioDeviceChooser::writeSettings()
{

	QSettings settings ( "projectM", "qprojectM-pulseaudio" );
	settings.setValue ( "tryFirstAvailablePlaybackMonitor",
	                    this->tryFirstPlayBackMonitorCheckBox->checkState() == Qt::Checked );
	//settings.setValue ("pulseAudioSourceDevice", this->listView.data(
}

void QPulseAudioDeviceChooser::readSettings()
{

	QSettings settings ( "projectM", "qprojectM-pulseaudio" );

	bool tryFirst = settings.value
	                ( "tryFirstAvailablePlaybackMonitor", true ).toBool() ;

	this->tryFirstPlayBackMonitorCheckBox->setCheckState
	( tryFirst ? Qt::Checked : Qt::Unchecked );

	if ( tryFirst )
	{
		this->devicesListView->setEnabled(false);
	} else {
		this->devicesListView->setEnabled(true);
	}

}

void QPulseAudioDeviceChooser::updateDevicesListViewLock(int state) {
		devicesListView->setEnabled(state != Qt::Checked);

}

QPulseAudioDeviceChooser::QPulseAudioDeviceChooser ( QPulseAudioThread * qpulseAudioThread, QWidget * parent = 0, Qt::WindowFlags f ) : QDialog ( parent, f ), _qpulseAudioDeviceModel ( qpulseAudioThread->devices(), this ), _qpulseAudioThread ( qpulseAudioThread )
{

	setupUi ( this );
	readSettings();
	this->devicesListView->setModel ( &_qpulseAudioDeviceModel );

	connect ( tryFirstPlayBackMonitorCheckBox, SIGNAL(stateChanged(int)), this, SLOT(updateDevicesListViewLock(int)));

	/// @bug wrong! should be based on HASH index, not display index
	/// @bug wait! it's ok because we are piping the text, not the device index to the connect method!
	connect ( devicesListView, SIGNAL ( doubleClicked ( const QModelIndex& ) ), _qpulseAudioThread, SLOT ( connectDevice ( const QModelIndex& ) ) );

}

void QPulseAudioDeviceChooser::open()
{

	this->show();

}

<|endoftext|>


<commit_before><commit_msg>Add a call to the module init (in main)<commit_after><|endoftext|>