<commit_before>#include "Utility/String.h"

#include <string>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cctype>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <cmath>

namespace
{
    const auto whitespace = std::string{" \t\n\r"};
}

std::vector<std::string> String::split(const std::string& s, const std::string& delim, const size_t count) noexcept
{
    if(delim.empty())
    {
        return split(remove_extra_whitespace(s), " ", count);
    }

    if(s.empty())
    {
        return {};
    }

    std::vector<std::string> result;
    size_t start_index = 0;
    size_t end_index = 0;
    size_t split_count = 0;
    while(end_index < s.size() && split_count < count)
    {
        end_index = s.find(delim, start_index);
        result.push_back(s.substr(start_index, end_index - start_index));
        start_index = std::min(end_index, s.size()) + delim.size();
        ++split_count;
    }

    if(start_index <= s.size())
    {
        result.push_back(s.substr(start_index));
    }

    return result;
}

bool String::starts_with(const std::string& s, const std::string& beginning) noexcept
{
    return std::mismatch(beginning.begin(), beginning.end(), s.begin(), s.end()).first == beginning.end();
}

std::string String::trim_outer_whitespace(const std::string& s) noexcept
{
    const auto text_start = s.find_first_not_of(whitespace);
    if(text_start == std::string::npos)
    {
        return {};
    }

    const auto text_end = s.find_last_not_of(whitespace);
    return s.substr(text_start, text_end - text_start + 1);
}

std::string String::remove_extra_whitespace(const std::string& s) noexcept
{
    std::string s2 = trim_outer_whitespace(s);
    std::replace_if(s2.begin(), s2.end(), [](auto c) { return String::contains(whitespace, c); }, ' ');
    std::string result;
    std::copy_if(s2.begin(), s2.end(), std::back_inserter(result),
                 [&result](auto c)
                 {
                     return c != ' ' || result.back() != ' ';
                 });

    return result;
}

std::string String::strip_comments(const std::string& str, const std::string& comment) noexcept
{
    return trim_outer_whitespace(str.substr(0, str.find(comment)));
}

std::string String::strip_block_comment(const std::string& str, const std::string& start, const std::string& end)
{
    const auto start_comment_index = str.find(start);
    const auto end_comment_index = str.find(end);

    if(start_comment_index == std::string::npos && end_comment_index == std::string::npos)
    {
        return trim_outer_whitespace(str);
    }

    if(start_comment_index == std::string::npos || end_comment_index == std::string::npos)
    {
        throw std::invalid_argument("\"" + str + "\" is missing a comment delimiter: " + start + end);
    }

    if(start_comment_index >= end_comment_index)
    {
        throw std::invalid_argument("\"" + str + "\" contains bad comment delimiters: " + start + end);
    }

    try
    {
        const auto first_part = str.substr(0, start_comment_index);
        const auto last_part = str.substr(end_comment_index + end.size());
        return strip_block_comment(trim_outer_whitespace(first_part) + " " + trim_outer_whitespace(last_part), start, end);
    }
    catch(const std::invalid_argument& e)
    {
        throw std::invalid_argument(e.what() + std::string("\nOriginal line: ") + str);
    }
}

std::string String::strip_nested_block_comments(const std::string& str, const std::string& start, const std::string& end)
{
    if(contains(start, end) || contains(end, start))
    {
        throw std::invalid_argument("Delimiters cannot share substrings: " + start + "," + end + ".");
    }

    const auto error_message = "Invalid nesting of delimiters " + start + "," + end + ": " + str;
    std::string result;
    auto depth = 0;
    size_t index = 0;
    while(index < str.size())
    {
        auto start_index = str.find(start, index);
        auto end_index = str.find(end, index);
        if(start_index < end_index)
        {
            if(depth == 0)
            {
                result += str.substr(index, start_index - index);
            }
            ++depth;
            index = start_index + start.size();
        }
        else if(end_index < start_index)
        {
            if(depth == 0)
            {
                throw std::invalid_argument(error_message);
            }
            --depth;
            index = end_index + end.size();
        }
        else // start_index == end_index == std::string::npos
        {
            result += str.substr(index);
            break;
        }
    }

    if(depth != 0)
    {
        throw std::invalid_argument(error_message);
    }

    return result;
}

std::string String::remove_pgn_comments(const std::string& line)
{
    const auto index = line.find_first_of(";({");
    const auto delimiter = index < std::string::npos ? line[index] : '\0';

    switch(delimiter)
    {
        case ';' : return remove_pgn_comments(strip_comments(line, ";"));
        case '(' : return remove_pgn_comments(strip_nested_block_comments(line, "(", ")"));
        case '{' : return remove_pgn_comments(strip_block_comment(line, "{", "}"));
        default  : return remove_extra_whitespace(line);
    }
}

std::string String::extract_delimited_text(const std::string& str, const std::string& start, const std::string& end)
{
    const auto start_split = split(str, start, 1);
    if(start_split.size() != 2)
    {
        throw std::invalid_argument("Starting delimiter not found in \"" + str + "\": " + start + " " + end);
    }
    const auto start_of_inside = start_split[1];
    const auto inside_split = split(start_of_inside, end, 1);
    if(inside_split.size() != 2)
    {
        throw std::invalid_argument("Ending delimiter not found in \"" + str + "\": " + start + " " + end);
    }
    return inside_split[0];
}

char String::tolower(const char letter) noexcept
{
    return char(std::tolower(letter));
}

char String::toupper(const char letter) noexcept
{
    return char(std::toupper(letter));
}

std::string String::lowercase(std::string s) noexcept
{
    std::transform(s.begin(), s.end(), s.begin(), String::tolower);
    return s;
}

std::string String::round_to_decimals(const double x, const size_t decimal_places) noexcept
{
    auto result = std::ostringstream();
    result << std::fixed << std::setprecision(int(decimal_places)) << x;
    return result.str();
}

std::string String::date_and_time_format(const std::chrono::system_clock::time_point& point_in_time,
                                         const std::string& format) noexcept
{
    const auto time_c = std::chrono::system_clock::to_time_t(point_in_time);
    std::tm time_out;
#ifdef _WIN32
    localtime_s(&time_out, &time_c);
#elif defined(__linux__)
    localtime_r(&time_c, &time_out);
#endif
    auto ss = std::ostringstream{};
    ss << std::put_time(&time_out, format.c_str());
    return ss.str();
}

std::string String::add_to_file_name(const std::string& original_file_name, const std::string& addition) noexcept
{
    const auto dot_index = std::min(original_file_name.find_last_of('.'), original_file_name.size());
    return original_file_name.substr(0, dot_index) + addition + original_file_name.substr(dot_index);
}
<commit_msg>Simplify String::remove_extra_whitespace()<commit_after>#include "Utility/String.h"

#include <string>
#include <vector>
#include <stdexcept>
#include <algorithm>
#include <cctype>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <cmath>

namespace
{
    const auto whitespace = std::string{" \t\n\r"};
}

std::vector<std::string> String::split(const std::string& s, const std::string& delim, const size_t count) noexcept
{
    if(delim.empty())
    {
        return split(remove_extra_whitespace(s), " ", count);
    }

    if(s.empty())
    {
        return {};
    }

    std::vector<std::string> result;
    size_t start_index = 0;
    size_t end_index = 0;
    size_t split_count = 0;
    while(end_index < s.size() && split_count < count)
    {
        end_index = s.find(delim, start_index);
        result.push_back(s.substr(start_index, end_index - start_index));
        start_index = std::min(end_index, s.size()) + delim.size();
        ++split_count;
    }

    if(start_index <= s.size())
    {
        result.push_back(s.substr(start_index));
    }

    return result;
}

bool String::starts_with(const std::string& s, const std::string& beginning) noexcept
{
    return std::mismatch(beginning.begin(), beginning.end(), s.begin(), s.end()).first == beginning.end();
}

std::string String::trim_outer_whitespace(const std::string& s) noexcept
{
    const auto text_start = s.find_first_not_of(whitespace);
    if(text_start == std::string::npos)
    {
        return {};
    }

    const auto text_end = s.find_last_not_of(whitespace);
    return s.substr(text_start, text_end - text_start + 1);
}

std::string String::remove_extra_whitespace(const std::string& s) noexcept
{
    std::string result;
    std::copy_if(s.begin(), s.end(), std::back_inserter(result),
                 [&result](auto c)
                 {
                     return ! isspace(c) || ( ! result.empty() && ! std::isspace(result.back()));
                 });

    return trim_outer_whitespace(result);
}

std::string String::strip_comments(const std::string& str, const std::string& comment) noexcept
{
    return trim_outer_whitespace(str.substr(0, str.find(comment)));
}

std::string String::strip_block_comment(const std::string& str, const std::string& start, const std::string& end)
{
    const auto start_comment_index = str.find(start);
    const auto end_comment_index = str.find(end);

    if(start_comment_index == std::string::npos && end_comment_index == std::string::npos)
    {
        return trim_outer_whitespace(str);
    }

    if(start_comment_index == std::string::npos || end_comment_index == std::string::npos)
    {
        throw std::invalid_argument("\"" + str + "\" is missing a comment delimiter: " + start + end);
    }

    if(start_comment_index >= end_comment_index)
    {
        throw std::invalid_argument("\"" + str + "\" contains bad comment delimiters: " + start + end);
    }

    try
    {
        const auto first_part = str.substr(0, start_comment_index);
        const auto last_part = str.substr(end_comment_index + end.size());
        return strip_block_comment(trim_outer_whitespace(first_part) + " " + trim_outer_whitespace(last_part), start, end);
    }
    catch(const std::invalid_argument& e)
    {
        throw std::invalid_argument(e.what() + std::string("\nOriginal line: ") + str);
    }
}

std::string String::strip_nested_block_comments(const std::string& str, const std::string& start, const std::string& end)
{
    if(contains(start, end) || contains(end, start))
    {
        throw std::invalid_argument("Delimiters cannot share substrings: " + start + "," + end + ".");
    }

    const auto error_message = "Invalid nesting of delimiters " + start + "," + end + ": " + str;
    std::string result;
    auto depth = 0;
    size_t index = 0;
    while(index < str.size())
    {
        auto start_index = str.find(start, index);
        auto end_index = str.find(end, index);
        if(start_index < end_index)
        {
            if(depth == 0)
            {
                result += str.substr(index, start_index - index);
            }
            ++depth;
            index = start_index + start.size();
        }
        else if(end_index < start_index)
        {
            if(depth == 0)
            {
                throw std::invalid_argument(error_message);
            }
            --depth;
            index = end_index + end.size();
        }
        else // start_index == end_index == std::string::npos
        {
            result += str.substr(index);
            break;
        }
    }

    if(depth != 0)
    {
        throw std::invalid_argument(error_message);
    }

    return result;
}

std::string String::remove_pgn_comments(const std::string& line)
{
    const auto index = line.find_first_of(";({");
    const auto delimiter = index < std::string::npos ? line[index] : '\0';

    switch(delimiter)
    {
        case ';' : return remove_pgn_comments(strip_comments(line, ";"));
        case '(' : return remove_pgn_comments(strip_nested_block_comments(line, "(", ")"));
        case '{' : return remove_pgn_comments(strip_block_comment(line, "{", "}"));
        default  : return remove_extra_whitespace(line);
    }
}

std::string String::extract_delimited_text(const std::string& str, const std::string& start, const std::string& end)
{
    const auto start_split = split(str, start, 1);
    if(start_split.size() != 2)
    {
        throw std::invalid_argument("Starting delimiter not found in \"" + str + "\": " + start + " " + end);
    }
    const auto start_of_inside = start_split[1];
    const auto inside_split = split(start_of_inside, end, 1);
    if(inside_split.size() != 2)
    {
        throw std::invalid_argument("Ending delimiter not found in \"" + str + "\": " + start + " " + end);
    }
    return inside_split[0];
}

char String::tolower(const char letter) noexcept
{
    return char(std::tolower(letter));
}

char String::toupper(const char letter) noexcept
{
    return char(std::toupper(letter));
}

std::string String::lowercase(std::string s) noexcept
{
    std::transform(s.begin(), s.end(), s.begin(), String::tolower);
    return s;
}

std::string String::round_to_decimals(const double x, const size_t decimal_places) noexcept
{
    auto result = std::ostringstream();
    result << std::fixed << std::setprecision(int(decimal_places)) << x;
    return result.str();
}

std::string String::date_and_time_format(const std::chrono::system_clock::time_point& point_in_time,
                                         const std::string& format) noexcept
{
    const auto time_c = std::chrono::system_clock::to_time_t(point_in_time);
    std::tm time_out;
#ifdef _WIN32
    localtime_s(&time_out, &time_c);
#elif defined(__linux__)
    localtime_r(&time_c, &time_out);
#endif
    auto ss = std::ostringstream{};
    ss << std::put_time(&time_out, format.c_str());
    return ss.str();
}

std::string String::add_to_file_name(const std::string& original_file_name, const std::string& addition) noexcept
{
    const auto dot_index = std::min(original_file_name.find_last_of('.'), original_file_name.size());
    return original_file_name.substr(0, dot_index) + addition + original_file_name.substr(dot_index);
}
<|endoftext|>


<commit_before><commit_msg>add NFCTaskModule.cpp<commit_after>#include "NFCTaskModule.h"

bool NFCTaskModule::Init()
{
    return true;
}

bool NFCTaskModule::Shut()
{
    return true;
}

bool NFCTaskModule::Execute( const float fLasFrametime, const float fStartedTime )
{
    return true;
}

bool NFCTaskModule::AfterInit()
{
    return true;
}

int NFCTaskModule::AddTask( const NFIDENTID& self, const std::string& strTask )
{
    // ҪضʱֹͣϵͳĿ
    return 0;
}

int NFCTaskModule::RemoveTask( const NFIDENTID& self, const std::string& strTask )
{
    return 0;
}<|endoftext|>


<commit_before>#include "accountmanager.hpp"
#include "common.hpp"

#include <pajlada/settings/setting.hpp>

namespace chatterino {

namespace {

inline QString getEnvString(const char *target)
{
    char *val = std::getenv(target);
    if (val == nullptr) {
        return QString();
    }

    return QString(val);
}

}  // namespace

AccountManager::AccountManager()
    : twitchAnonymousUser("justinfan64537", "", "")
{
    QString envUsername = getEnvString("CHATTERINO2_USERNAME");
    QString envOauthToken = getEnvString("CHATTERINO2_OAUTH");

    if (!envUsername.isEmpty() && !envOauthToken.isEmpty()) {
        this->addTwitchUser(twitch::TwitchUser(envUsername, envOauthToken, ""));
    }

    pajlada::Settings::Setting<std::string>::set(
        "/accounts/current/roomID", "11148817", pajlada::Settings::SettingOption::DoNotWriteToJSON);
}

void AccountManager::load()
{
    auto keys = pajlada::Settings::SettingManager::getObjectKeys("/accounts");

    for (const auto &uid : keys) {
        if (uid == "current") {
            continue;
        }

        std::string username =
            pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/username");
        std::string userID =
            pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/userID");
        std::string clientID =
            pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/clientID");
        std::string oauthToken =
            pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/oauthToken");

        if (username.empty() || userID.empty() || clientID.empty() || oauthToken.empty()) {
            continue;
        }

        twitch::TwitchUser user(qS(username), qS(oauthToken), qS(clientID));

        this->addTwitchUser(user);
    }
}

twitch::TwitchUser &AccountManager::getTwitchAnon()
{
    return this->twitchAnonymousUser;
}

twitch::TwitchUser &AccountManager::getTwitchUser()
{
    std::lock_guard<std::mutex> lock(this->twitchUsersMutex);

    if (this->twitchUsers.size() == 0) {
        return this->getTwitchAnon();
    }

    return this->twitchUsers.front();
}

std::vector<twitch::TwitchUser> AccountManager::getTwitchUsers()
{
    std::lock_guard<std::mutex> lock(this->twitchUsersMutex);

    return std::vector<twitch::TwitchUser>(this->twitchUsers);
}

bool AccountManager::removeTwitchUser(const QString &userName)
{
    std::lock_guard<std::mutex> lock(this->twitchUsersMutex);

    for (auto it = this->twitchUsers.begin(); it != this->twitchUsers.end(); it++) {
        if ((*it).getUserName() == userName) {
            this->twitchUsers.erase(it);
            return true;
        }
    }

    return false;
}

void AccountManager::addTwitchUser(const twitch::TwitchUser &user)
{
    std::lock_guard<std::mutex> lock(this->twitchUsersMutex);

    this->twitchUsers.push_back(user);
}

}  // namespace chatterino
<commit_msg>Remove ability to log in with env variables<commit_after>#include "accountmanager.hpp"
#include "common.hpp"

#include <pajlada/settings/setting.hpp>

namespace chatterino {

namespace {

inline QString getEnvString(const char *target)
{
    char *val = std::getenv(target);
    if (val == nullptr) {
        return QString();
    }

    return QString(val);
}

}  // namespace

AccountManager::AccountManager()
    : twitchAnonymousUser("justinfan64537", "", "")
{
}

void AccountManager::load()
{
    auto keys = pajlada::Settings::SettingManager::getObjectKeys("/accounts");

    for (const auto &uid : keys) {
        if (uid == "current") {
            continue;
        }

        std::string username =
            pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/username");
        std::string userID =
            pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/userID");
        std::string clientID =
            pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/clientID");
        std::string oauthToken =
            pajlada::Settings::Setting<std::string>::get("/accounts/" + uid + "/oauthToken");

        if (username.empty() || userID.empty() || clientID.empty() || oauthToken.empty()) {
            continue;
        }

        twitch::TwitchUser user(qS(username), qS(oauthToken), qS(clientID));

        this->addTwitchUser(user);

        printf("Adding user %s(%s)\n", username.c_str(), userID.c_str());
    }
}

twitch::TwitchUser &AccountManager::getTwitchAnon()
{
    return this->twitchAnonymousUser;
}

twitch::TwitchUser &AccountManager::getTwitchUser()
{
    std::lock_guard<std::mutex> lock(this->twitchUsersMutex);

    if (this->twitchUsers.size() == 0) {
        return this->getTwitchAnon();
    }

    return this->twitchUsers.front();
}

std::vector<twitch::TwitchUser> AccountManager::getTwitchUsers()
{
    std::lock_guard<std::mutex> lock(this->twitchUsersMutex);

    return std::vector<twitch::TwitchUser>(this->twitchUsers);
}

bool AccountManager::removeTwitchUser(const QString &userName)
{
    std::lock_guard<std::mutex> lock(this->twitchUsersMutex);

    for (auto it = this->twitchUsers.begin(); it != this->twitchUsers.end(); it++) {
        if ((*it).getUserName() == userName) {
            this->twitchUsers.erase(it);
            return true;
        }
    }

    return false;
}

void AccountManager::addTwitchUser(const twitch::TwitchUser &user)
{
    std::lock_guard<std::mutex> lock(this->twitchUsersMutex);

    this->twitchUsers.push_back(user);
}

}  // namespace chatterino
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Assistant of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qhelpsearchquerywidget.h"

#include <QtCore/QDebug>

#include <QtCore/QObject>
#include <QtCore/QStringList>

#include <QtGui/QLabel>
#include <QtGui/QLayout>
#include <QtGui/QLineEdit>
#include <QtGui/QFocusEvent>
#include <QtGui/QPushButton>
#include <QtGui/QToolButton>

QT_BEGIN_NAMESPACE

class QHelpSearchQueryWidgetPrivate : public QObject
{
    Q_OBJECT

private:
    QHelpSearchQueryWidgetPrivate()
        : QObject()
    {
        searchButton = 0;
        advancedSearchWidget = 0;
        showHideAdvancedSearchButton = 0;
        defaultQuery = 0;
        exactQuery = 0;
        similarQuery = 0;
        withoutQuery = 0;
        allQuery = 0;
        atLeastQuery = 0;
    }

    ~QHelpSearchQueryWidgetPrivate()
    {
        // nothing todo
    }

    QString escapeString(const QString &text)
    {
        QString retValue = text;
        const QString escape(QLatin1String("\\"));
        QStringList escapableCharsList;
        escapableCharsList << QLatin1String("\\") << QLatin1String("+")
            << QLatin1String("-") << QLatin1String("!") << QLatin1String("(")
            << QLatin1String(")") << QLatin1String(":") << QLatin1String("^")
            << QLatin1String("[") << QLatin1String("]") << QLatin1String("{")
            << QLatin1String("}") << QLatin1String("~");

        // make sure we won't end up with an empty string
        foreach (const QString escapeChar, escapableCharsList) {
            if (retValue.contains(escapeChar))
                retValue.replace(escapeChar, QLatin1String(""));
        }
        if (retValue.trimmed().isEmpty())
            return retValue;

        retValue = text; // now realy escape the string...
        foreach (const QString escapeChar, escapableCharsList) {
            if (retValue.contains(escapeChar))
                retValue.replace(escapeChar, escape + escapeChar);
        }
        return retValue;
    }

    QStringList buildTermList(const QString query)
    {
        bool s = false;
        QString phrase;
        QStringList wordList;
        QString searchTerm = query;

        for (int i = 0; i < searchTerm.length(); ++i) {
            if (searchTerm[i] == QLatin1Char('\"') && !s) {
                s = true;
                phrase = searchTerm[i];
                continue;
            }
            if (searchTerm[i] != QLatin1Char('\"') && s)
                phrase += searchTerm[i];
            if (searchTerm[i] == QLatin1Char('\"') && s) {
                s = false;
                phrase += searchTerm[i];
                wordList.append(phrase);
                searchTerm.remove(phrase);
            }
        }
        if (s)
            searchTerm.replace(phrase, phrase.mid(1));

        const QRegExp exp(QLatin1String("\\s+"));
        wordList += searchTerm.split(exp, QString::SkipEmptyParts);
        return wordList;
    }

private slots:
    void showHideAdvancedSearch()
    {
        bool hidden = advancedSearchWidget->isHidden();
        if (hidden) {
            advancedSearchWidget->show();
            showHideAdvancedSearchButton->setText((QLatin1String("-")));
        } else {
            advancedSearchWidget->hide();
            showHideAdvancedSearchButton->setText((QLatin1String("+")));
        }

        defaultQuery->setEnabled(!hidden);
    }

private:
    friend class QHelpSearchQueryWidget;

    QPushButton *searchButton;
    QWidget* advancedSearchWidget;
    QToolButton *showHideAdvancedSearchButton;
    QLineEdit *defaultQuery;
    QLineEdit *exactQuery;
    QLineEdit *similarQuery;
    QLineEdit *withoutQuery;
    QLineEdit *allQuery;
    QLineEdit *atLeastQuery;
};

#include "qhelpsearchquerywidget.moc"

/*!
    \class QHelpSearchQueryWidget
    \since 4.4
    \inmodule QtHelp
    \brief The QHelpSearchQueryWidget class provides a simple line edit or
    an advanced widget to enable the user to input a search term in a
    standardized input mask.
*/

/*!
    \fn void QHelpSearchQueryWidget::search()

    This signal is emitted when a the user has the search button invoked.
    After reciving the signal you can ask the QHelpSearchQueryWidget for the build list
    of QHelpSearchQuery's that you may pass to the QHelpSearchEngine's search() function.
*/

/*!
    Constructs a new search query widget with the given \a parent.
*/
QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent)
    : QWidget(parent)
{
    d = new QHelpSearchQueryWidgetPrivate();

    QVBoxLayout *vLayout = new QVBoxLayout(this);
    vLayout->setMargin(0);

    QHBoxLayout* hBoxLayout = new QHBoxLayout();
    QLabel *label = new QLabel(tr("Search for:"), this);
    d->defaultQuery = new QLineEdit(this);
    d->searchButton = new QPushButton(tr("Search"), this);
    hBoxLayout->addWidget(label);
    hBoxLayout->addWidget(d->defaultQuery);
    hBoxLayout->addWidget(d->searchButton);

    vLayout->addLayout(hBoxLayout);

    connect(d->searchButton, SIGNAL(clicked()), this, SIGNAL(search()));
    connect(d->defaultQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));

#if defined(QT_CLUCENE_SUPPORT)
    hBoxLayout = new QHBoxLayout();
    d->showHideAdvancedSearchButton = new QToolButton(this);
    d->showHideAdvancedSearchButton->setText(QLatin1String("+"));
    d->showHideAdvancedSearchButton->setMinimumSize(25, 20);

    label = new QLabel(tr("Advanced search"), this);
    QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
    sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth());
    label->setSizePolicy(sizePolicy);

    QFrame* hLine = new QFrame(this);
    hLine->setFrameStyle(QFrame::HLine);
    hBoxLayout->addWidget(d->showHideAdvancedSearchButton);
    hBoxLayout->addWidget(label);
    hBoxLayout->addWidget(hLine);

    vLayout->addLayout(hBoxLayout);

    // setup advanced search layout
    d->advancedSearchWidget = new QWidget(this);
    QGridLayout *gLayout = new QGridLayout(d->advancedSearchWidget);
    gLayout->setMargin(0);

    label = new QLabel(tr("words similar to:"), this);
    gLayout->addWidget(label, 0, 0);
    d->similarQuery = new QLineEdit(this);
    gLayout->addWidget(d->similarQuery, 0, 1);

    label = new QLabel(tr("without the words:"), this);
    gLayout->addWidget(label, 1, 0);
    d->withoutQuery = new QLineEdit(this);
    gLayout->addWidget(d->withoutQuery, 1, 1);

    label = new QLabel(tr("with exact phrase:"), this);
    gLayout->addWidget(label, 2, 0);
    d->exactQuery = new QLineEdit(this);
    gLayout->addWidget(d->exactQuery, 2, 1);

    label = new QLabel(tr("with all of the words:"), this);
    gLayout->addWidget(label, 3, 0);
    d->allQuery = new QLineEdit(this);
    gLayout->addWidget(d->allQuery, 3, 1);

    label = new QLabel(tr("with at least one of the words:"), this);
    gLayout->addWidget(label, 4, 0);
    d->atLeastQuery = new QLineEdit(this);
    gLayout->addWidget(d->atLeastQuery, 4, 1);

    vLayout->addWidget(d->advancedSearchWidget);
    d->advancedSearchWidget->hide();

    connect(d->exactQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->similarQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->withoutQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->allQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->atLeastQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->showHideAdvancedSearchButton, SIGNAL(clicked()),
        d, SLOT(showHideAdvancedSearch()));
#endif
}

/*!
    Destroys the search query widget.
*/
QHelpSearchQueryWidget::~QHelpSearchQueryWidget()
{
    delete d;
}

/*!
    Returns a list of querys to use in combination with the search engines
    search(QList<QHelpSearchQuery> &query) function.
*/
QList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const
{
#if !defined(QT_CLUCENE_SUPPORT)
    QList<QHelpSearchQuery> queryList;
    queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
        QStringList(d->defaultQuery->text())));

    return queryList;
#else
    QList<QHelpSearchQuery> queryList;
    if (d->defaultQuery->isEnabled()) {
        queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
            d->buildTermList(d->escapeString(d->defaultQuery->text()))));
    } else {
        const QRegExp exp(QLatin1String("\\s+"));
        QStringList lst = d->similarQuery->text().split(exp, QString::SkipEmptyParts);
        if (!lst.isEmpty()) {
            QStringList fuzzy;
            foreach (const QString term, lst)
                fuzzy += d->buildTermList(d->escapeString(term));
            queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY, fuzzy));
        }

        lst = d->withoutQuery->text().split(exp, QString::SkipEmptyParts);
        if (!lst.isEmpty()) {
            QStringList without;
            foreach (const QString term, lst)
                without.append(d->escapeString(term));
            queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT, without));
        }

        if (!d->exactQuery->text().isEmpty()) {
            QString phrase = d->exactQuery->text().remove(QLatin1Char('\"'));
            phrase = d->escapeString(phrase.simplified());
            queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE, QStringList(phrase)));
        }

        lst = d->allQuery->text().split(exp, QString::SkipEmptyParts);
        if (!lst.isEmpty()) {
            QStringList all;
            foreach (const QString term, lst)
                all.append(d->escapeString(term));
            queryList.append(QHelpSearchQuery(QHelpSearchQuery::ALL, all));
        }

        lst = d->atLeastQuery->text().split(exp, QString::SkipEmptyParts);
        if (!lst.isEmpty()) {
            QStringList atLeast;
            foreach (const QString term, lst)
                atLeast += d->buildTermList(d->escapeString(term));
            queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST, atLeast));
        }
    }
    return queryList;
#endif
}

/*! \reimp
*/
void QHelpSearchQueryWidget::focusInEvent(QFocusEvent *focusEvent)
{
    if (focusEvent->reason() != Qt::MouseFocusReason) {
        d->defaultQuery->selectAll();
        d->defaultQuery->setFocus();
    }
}

QT_END_NAMESPACE
<commit_msg>Assistant: Added search history.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Assistant of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** 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.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qhelpsearchquerywidget.h"

#include <QtCore/QDebug>

#include <QtCore/QAbstractListModel>
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <QtCore/QtGlobal>

#include <QtGui/QCompleter>
#include <QtGui/QLabel>
#include <QtGui/QLayout>
#include <QtGui/QLineEdit>
#include <QtGui/QFocusEvent>
#include <QtGui/QPushButton>
#include <QtGui/QToolButton>

QT_BEGIN_NAMESPACE

class QHelpSearchQueryWidgetPrivate : public QObject
{
    Q_OBJECT

private:
    struct QueryHistory {
        explicit QueryHistory() : curQuery(-1) {}
        QList<QList<QHelpSearchQuery> > queries;
        int curQuery;
    };

    class CompleterModel : public QAbstractListModel
    {
    public:
        explicit CompleterModel(QObject *parent)
          : QAbstractListModel(parent) {}

        int rowCount(const QModelIndex &parent = QModelIndex()) const
        {
            return parent.isValid() ? 0 : termList.size();
        }

        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const
        {
            if (!index.isValid() || index.row() >= termList.count()||
                (role != Qt::EditRole && role != Qt::DisplayRole))
                return QVariant();
            return termList.at(index.row());
        }

        void addTerm(const QString &term)
        {
            if (!termList.contains(term)) {
                termList.append(term);
                reset();
            }
        }

    private:
        QStringList termList;
    };

    QHelpSearchQueryWidgetPrivate()
        : QObject(), simpleSearch(true),
          searchCompleter(new CompleterModel(this), this)
    {
        searchButton = 0;
        advancedSearchWidget = 0;
        showHideAdvancedSearchButton = 0;
        defaultQuery = 0;
        exactQuery = 0;
        similarQuery = 0;
        withoutQuery = 0;
        allQuery = 0;
        atLeastQuery = 0;
    }

    ~QHelpSearchQueryWidgetPrivate()
    {
        // nothing todo
    }

    QString escapeString(const QString &text)
    {
        QString retValue = text;
        const QString escape(QLatin1String("\\"));
        QStringList escapableCharsList;
        escapableCharsList << QLatin1String("\\") << QLatin1String("+")
            << QLatin1String("-") << QLatin1String("!") << QLatin1String("(")
            << QLatin1String(")") << QLatin1String(":") << QLatin1String("^")
            << QLatin1String("[") << QLatin1String("]") << QLatin1String("{")
            << QLatin1String("}") << QLatin1String("~");

        // make sure we won't end up with an empty string
        foreach (const QString escapeChar, escapableCharsList) {
            if (retValue.contains(escapeChar))
                retValue.replace(escapeChar, QLatin1String(""));
        }
        if (retValue.trimmed().isEmpty())
            return retValue;

        retValue = text; // now realy escape the string...
        foreach (const QString escapeChar, escapableCharsList) {
            if (retValue.contains(escapeChar))
                retValue.replace(escapeChar, escape + escapeChar);
        }
        return retValue;
    }

    QStringList buildTermList(const QString query)
    {
        bool s = false;
        QString phrase;
        QStringList wordList;
        QString searchTerm = query;

        for (int i = 0; i < searchTerm.length(); ++i) {
            if (searchTerm[i] == QLatin1Char('\"') && !s) {
                s = true;
                phrase = searchTerm[i];
                continue;
            }
            if (searchTerm[i] != QLatin1Char('\"') && s)
                phrase += searchTerm[i];
            if (searchTerm[i] == QLatin1Char('\"') && s) {
                s = false;
                phrase += searchTerm[i];
                wordList.append(phrase);
                searchTerm.remove(phrase);
            }
        }
        if (s)
            searchTerm.replace(phrase, phrase.mid(1));

        const QRegExp exp(QLatin1String("\\s+"));
        wordList += searchTerm.split(exp, QString::SkipEmptyParts);
        return wordList;
    }

    void saveQuery(const QList<QHelpSearchQuery> &query, QueryHistory &queryHist)
    {
        // We only add the query to the list if it is different from the last one.
        bool insert = false;
        if (queryHist.queries.empty())
            insert = true;
        else {
            const QList<QHelpSearchQuery> &lastQuery = queryHist.queries.last();
            if (lastQuery.size() != query.size()) {
                insert = true;
            } else {
                for (int i = 0; i < query.size(); ++i) {
                    if (query.at(i).fieldName != lastQuery.at(i).fieldName
                        || query.at(i).wordList != lastQuery.at(i).wordList) {
                        insert = true;
                        break;
                    }
                }
            }
        }
        if (insert) {
            queryHist.queries.append(query);
            foreach (const QHelpSearchQuery &queryPart, query) {
                static_cast<CompleterModel *>(searchCompleter.model())->
                        addTerm(queryPart.wordList.join(" "));
            }
        }
    }

    void nextOrPrevQuery(int maxOrMinIndex, int addend,
                         QToolButton *thisButton, QToolButton *otherButton)
    {
        QueryHistory *queryHist;
        QList<QLineEdit *> lineEdits;
        if (simpleSearch) {
            queryHist = &simpleQueries;
            lineEdits << defaultQuery;
        } else {
            queryHist = &complexQueries;
            lineEdits << allQuery << atLeastQuery << similarQuery
                    << withoutQuery << exactQuery;
        }
        foreach (QLineEdit *lineEdit, lineEdits)
            lineEdit->clear();

        // Otherwise, the respective button would be disabled.
        Q_ASSERT(queryHist->curQuery != maxOrMinIndex);

        queryHist->curQuery += addend;
        const QList<QHelpSearchQuery> &query =
                queryHist->queries.at(queryHist->curQuery);
        foreach (const QHelpSearchQuery &queryPart, query) {
            QLineEdit *lineEdit;
            switch (queryPart.fieldName) {
            case QHelpSearchQuery::DEFAULT:
                lineEdit = defaultQuery;
                break;
            case QHelpSearchQuery::ALL:
                lineEdit = allQuery;
                break;
            case QHelpSearchQuery::ATLEAST:
                lineEdit = atLeastQuery;
                break;
            case QHelpSearchQuery::FUZZY:
                lineEdit = similarQuery;
                break;
            case QHelpSearchQuery::WITHOUT:
                lineEdit = withoutQuery;
                break;
            case QHelpSearchQuery::PHRASE:
                lineEdit = exactQuery;
                break;
            default:
                Q_ASSERT(0);
            }
            lineEdit->setText(queryPart.wordList.join(" "));
        }

        if (queryHist->curQuery == maxOrMinIndex)
            thisButton->setEnabled(false);
        otherButton->setEnabled(true);
    }

    void enableOrDisableToolButtons()
    {
        const QueryHistory &queryHist =
                simpleSearch ? simpleQueries : complexQueries;
        prevQueryButton->setEnabled(queryHist.curQuery > 0);
        nextQueryButton->setEnabled(queryHist.curQuery <
                                    queryHist.queries.size() - 1);
    }

private slots:
    void showHideAdvancedSearch()
    {
        if (simpleSearch) {
            advancedSearchWidget->show();
            showHideAdvancedSearchButton->setText((QLatin1String("-")));
        } else {
            advancedSearchWidget->hide();
            showHideAdvancedSearchButton->setText((QLatin1String("+")));
        }

        simpleSearch = !simpleSearch;
        defaultQuery->setEnabled(simpleSearch);
        enableOrDisableToolButtons();
    }

    void searchRequested()
    {
        QList<QHelpSearchQuery> queryList;
#if !defined(QT_CLUCENE_SUPPORT)
        queryList.append(QHelSearchQuery(QHelpSearchQuery::DEFAULT,
                                          QStringList(defaultQuery->text())));

#else
        if (defaultQuery->isEnabled()) {
            queryList.append(QHelpSearchQuery(QHelpSearchQuery::DEFAULT,
                                              buildTermList(escapeString(defaultQuery->text()))));
        } else {
            const QRegExp exp(QLatin1String("\\s+"));
            QStringList lst = similarQuery->text().split(exp, QString::SkipEmptyParts);
            if (!lst.isEmpty()) {
                QStringList fuzzy;
                foreach (const QString term, lst)
                    fuzzy += buildTermList(escapeString(term));
                queryList.append(QHelpSearchQuery(QHelpSearchQuery::FUZZY, fuzzy));
            }

            lst = withoutQuery->text().split(exp, QString::SkipEmptyParts);
            if (!lst.isEmpty()) {
                QStringList without;
                foreach (const QString term, lst)
                    without.append(escapeString(term));
                queryList.append(QHelpSearchQuery(QHelpSearchQuery::WITHOUT, without));
            }

            if (!exactQuery->text().isEmpty()) {
                QString phrase = exactQuery->text().remove(QLatin1Char('\"'));
                phrase = escapeString(phrase.simplified());
                queryList.append(QHelpSearchQuery(QHelpSearchQuery::PHRASE, QStringList(phrase)));
            }

            lst = allQuery->text().split(exp, QString::SkipEmptyParts);
            if (!lst.isEmpty()) {
                QStringList all;
                foreach (const QString term, lst)
                    all.append(escapeString(term));
                queryList.append(QHelpSearchQuery(QHelpSearchQuery::ALL, all));
            }

            lst = atLeastQuery->text().split(exp, QString::SkipEmptyParts);
            if (!lst.isEmpty()) {
                QStringList atLeast;
                foreach (const QString term, lst)
                    atLeast += buildTermList(escapeString(term));
                queryList.append(QHelpSearchQuery(QHelpSearchQuery::ATLEAST, atLeast));
            }
        }
#endif
        QueryHistory &queryHist = simpleSearch ? simpleQueries : complexQueries;
        saveQuery(queryList, queryHist);
        queryHist.curQuery = queryHist.queries.size() - 1;
        if (queryHist.curQuery > 0)
            prevQueryButton->setEnabled(true);
        nextQueryButton->setEnabled(false);
    }

    void nextQuery()
    {
        nextOrPrevQuery((simpleSearch ? simpleQueries : complexQueries).queries.size() - 1,
                        1, nextQueryButton, prevQueryButton);
    }

    void prevQuery()
    {
        nextOrPrevQuery(0, -1, prevQueryButton, nextQueryButton);
    }

private:
    friend class QHelpSearchQueryWidget;

    bool simpleSearch;
    QPushButton *searchButton;
    QWidget* advancedSearchWidget;
    QToolButton *showHideAdvancedSearchButton;
    QLineEdit *defaultQuery;
    QLineEdit *exactQuery;
    QLineEdit *similarQuery;
    QLineEdit *withoutQuery;
    QLineEdit *allQuery;
    QLineEdit *atLeastQuery;
    QToolButton *nextQueryButton;
    QToolButton *prevQueryButton;
    QueryHistory simpleQueries;
    QueryHistory complexQueries;
    QCompleter searchCompleter;
};

#include "qhelpsearchquerywidget.moc"

/*!
    \class QHelpSearchQueryWidget
    \since 4.4
    \inmodule QtHelp
    \brief The QHelpSearchQueryWidget class provides a simple line edit or
    an advanced widget to enable the user to input a search term in a
    standardized input mask.
*/

/*!
    \fn void QHelpSearchQueryWidget::search()

    This signal is emitted when a the user has the search button invoked.
    After reciving the signal you can ask the QHelpSearchQueryWidget for the build list
    of QHelpSearchQuery's that you may pass to the QHelpSearchEngine's search() function.
*/

/*!
    Constructs a new search query widget with the given \a parent.
*/
QHelpSearchQueryWidget::QHelpSearchQueryWidget(QWidget *parent)
    : QWidget(parent)
{
    d = new QHelpSearchQueryWidgetPrivate();

    QVBoxLayout *vLayout = new QVBoxLayout(this);
    vLayout->setMargin(0);

    QHBoxLayout* hBoxLayout = new QHBoxLayout();
    QLabel *label = new QLabel(tr("Search for:"), this);
    d->defaultQuery = new QLineEdit(this);
    d->defaultQuery->setCompleter(&d->searchCompleter);
    d->prevQueryButton = new QToolButton(this);
    d->prevQueryButton->setArrowType(Qt::LeftArrow);
    d->prevQueryButton->setToolTip(tr("Previous search"));
    d->prevQueryButton->setEnabled(false);
    d->nextQueryButton = new QToolButton(this);
    d->nextQueryButton->setArrowType(Qt::RightArrow);
    d->nextQueryButton->setToolTip(tr("Next search"));
    d->nextQueryButton->setEnabled(false);
    d->searchButton = new QPushButton(tr("Search"), this);
    hBoxLayout->addWidget(label);
    hBoxLayout->addWidget(d->defaultQuery);
    hBoxLayout->addWidget(d->prevQueryButton);
    hBoxLayout->addWidget(d->nextQueryButton);
    hBoxLayout->addWidget(d->searchButton);

    vLayout->addLayout(hBoxLayout);

    connect(d->prevQueryButton, SIGNAL(clicked()), d, SLOT(prevQuery()));
    connect(d->nextQueryButton, SIGNAL(clicked()), d, SLOT(nextQuery()));
    connect(d->searchButton, SIGNAL(clicked()), this, SIGNAL(search()));
    connect(d->defaultQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));

#if defined(QT_CLUCENE_SUPPORT)
    hBoxLayout = new QHBoxLayout();
    d->showHideAdvancedSearchButton = new QToolButton(this);
    d->showHideAdvancedSearchButton->setText(QLatin1String("+"));
    d->showHideAdvancedSearchButton->setMinimumSize(25, 20);

    label = new QLabel(tr("Advanced search"), this);
    QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
    sizePolicy.setHeightForWidth(label->sizePolicy().hasHeightForWidth());
    label->setSizePolicy(sizePolicy);

    QFrame* hLine = new QFrame(this);
    hLine->setFrameStyle(QFrame::HLine);
    hBoxLayout->addWidget(d->showHideAdvancedSearchButton);
    hBoxLayout->addWidget(label);
    hBoxLayout->addWidget(hLine);

    vLayout->addLayout(hBoxLayout);

    // setup advanced search layout
    d->advancedSearchWidget = new QWidget(this);
    QGridLayout *gLayout = new QGridLayout(d->advancedSearchWidget);
    gLayout->setMargin(0);

    label = new QLabel(tr("words similar to:"), this);
    gLayout->addWidget(label, 0, 0);
    d->similarQuery = new QLineEdit(this);
    d->similarQuery->setCompleter(&d->searchCompleter);
    gLayout->addWidget(d->similarQuery, 0, 1);

    label = new QLabel(tr("without the words:"), this);
    gLayout->addWidget(label, 1, 0);
    d->withoutQuery = new QLineEdit(this);
    d->withoutQuery->setCompleter(&d->searchCompleter);
    gLayout->addWidget(d->withoutQuery, 1, 1);

    label = new QLabel(tr("with exact phrase:"), this);
    gLayout->addWidget(label, 2, 0);
    d->exactQuery = new QLineEdit(this);
    d->exactQuery->setCompleter(&d->searchCompleter);
    gLayout->addWidget(d->exactQuery, 2, 1);

    label = new QLabel(tr("with all of the words:"), this);
    gLayout->addWidget(label, 3, 0);
    d->allQuery = new QLineEdit(this);
    d->allQuery->setCompleter(&d->searchCompleter);
    gLayout->addWidget(d->allQuery, 3, 1);

    label = new QLabel(tr("with at least one of the words:"), this);
    gLayout->addWidget(label, 4, 0);
    d->atLeastQuery = new QLineEdit(this);
    d->atLeastQuery->setCompleter(&d->searchCompleter);
    gLayout->addWidget(d->atLeastQuery, 4, 1);

    vLayout->addWidget(d->advancedSearchWidget);
    d->advancedSearchWidget->hide();

    connect(d->exactQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->similarQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->withoutQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->allQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->atLeastQuery, SIGNAL(returnPressed()), this, SIGNAL(search()));
    connect(d->showHideAdvancedSearchButton, SIGNAL(clicked()),
        d, SLOT(showHideAdvancedSearch()));
#endif
    connect(this, SIGNAL(search()), d, SLOT(searchRequested()));
}

/*!
    Destroys the search query widget.
*/
QHelpSearchQueryWidget::~QHelpSearchQueryWidget()
{
    delete d;
}

/*!
    Returns a list of querys to use in combination with the search engines
    search(QList<QHelpSearchQuery> &query) function.
*/
QList<QHelpSearchQuery> QHelpSearchQueryWidget::query() const
{
    const QHelpSearchQueryWidgetPrivate::QueryHistory &queryHist =
        d->simpleSearch ? d->simpleQueries : d->complexQueries;
    return queryHist.queries.isEmpty() ?
        QList<QHelpSearchQuery>() : queryHist.queries.last();
}

/*! \reimp
*/
void QHelpSearchQueryWidget::focusInEvent(QFocusEvent *focusEvent)
{
    if (focusEvent->reason() != Qt::MouseFocusReason) {
        d->defaultQuery->selectAll();
        d->defaultQuery->setFocus();
    }
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/bluetooth/bluetooth_adapter_factory.h"

#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/chromeos_switches.h"
#include "device/bluetooth/bluetooth_adapter.h"

#if defined(OS_CHROMEOS)
#include "device/bluetooth/bluetooth_adapter_chromeos.h"
#include "device/bluetooth/bluetooth_adapter_chromeos_experimental.h"
#elif defined(OS_WIN)
#include "device/bluetooth/bluetooth_adapter_win.h"
#elif defined(OS_MACOSX)
#include "device/bluetooth/bluetooth_adapter_mac.h"
#endif

namespace {

using device::BluetoothAdapter;
using device::BluetoothAdapterFactory;

// Shared default adapter instance, we don't want to keep this class around
// if nobody is using it so use a WeakPtr and create the object when needed;
// since Google C++ Style (and clang's static analyzer) forbids us having
// exit-time destructors we use a leaky lazy instance for it.
base::LazyInstance<base::WeakPtr<device::BluetoothAdapter> >::Leaky
    default_adapter = LAZY_INSTANCE_INITIALIZER;

typedef std::vector<BluetoothAdapterFactory::AdapterCallback>
    AdapterCallbackList;

// List of adapter callbacks to be called once the adapter is initialized.
// Since Google C++ Style (and clang's static analyzer) forbids us having
// exit-time destructors we use a lazy instance for it.
base::LazyInstance<AdapterCallbackList> adapter_callbacks =
    LAZY_INSTANCE_INITIALIZER;

void RunAdapterCallbacks() {
  CHECK(default_adapter.Get().get());
  scoped_refptr<BluetoothAdapter> adapter(default_adapter.Get());
  for (std::vector<BluetoothAdapterFactory::AdapterCallback>::const_iterator
           iter = adapter_callbacks.Get().begin();
       iter != adapter_callbacks.Get().end();
       ++iter) {
    iter->Run(adapter);
  }
  adapter_callbacks.Get().clear();
}

}  // namespace

namespace device {

// static
bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() {
#if defined(OS_CHROMEOS)
  return true;
#elif defined(OS_WIN)
  return true;
#elif defined(OS_MACOSX)
  return true;
#endif
  return false;
}

// static
void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) {
  if (!default_adapter.Get().get()) {
#if defined(OS_CHROMEOS)
    if (CommandLine::ForCurrentProcess()->HasSwitch(
        chromeos::switches::kEnableExperimentalBluetooth)) {
      chromeos::BluetoothAdapterChromeOSExperimental* new_adapter =
          new chromeos::BluetoothAdapterChromeOSExperimental;
      new_adapter->TrackDefaultAdapter();
      default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
    } else {
      chromeos::BluetoothAdapterChromeOS* new_adapter =
          new chromeos::BluetoothAdapterChromeOS;
      new_adapter->TrackDefaultAdapter();
      default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
    }
#elif defined(OS_WIN)
    BluetoothAdapterWin* new_adapter = new BluetoothAdapterWin(
        base::Bind(&RunAdapterCallbacks));
    new_adapter->TrackDefaultAdapter();
    default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
#elif defined(OS_MACOSX)
    BluetoothAdapterMac* new_adapter = new BluetoothAdapterMac();
    new_adapter->TrackDefaultAdapter();
    default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
#endif
  }

  if (default_adapter.Get()->IsInitialized()) {
    callback.Run(scoped_refptr<BluetoothAdapter>(default_adapter.Get()));
  } else {
    adapter_callbacks.Get().push_back(callback);
  }
}

// static
scoped_refptr<BluetoothAdapter> BluetoothAdapterFactory::MaybeGetAdapter() {
  return scoped_refptr<BluetoothAdapter>(default_adapter.Get());
}

}  // namespace device
<commit_msg>Restricts BluetoothAdapterMac to OSX 10.7 or later.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "device/bluetooth/bluetooth_adapter_factory.h"

#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/chromeos_switches.h"
#include "device/bluetooth/bluetooth_adapter.h"

#if defined(OS_CHROMEOS)
#include "device/bluetooth/bluetooth_adapter_chromeos.h"
#include "device/bluetooth/bluetooth_adapter_chromeos_experimental.h"
#elif defined(OS_WIN)
#include "device/bluetooth/bluetooth_adapter_win.h"
#elif defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#include "device/bluetooth/bluetooth_adapter_mac.h"
#endif

namespace {

using device::BluetoothAdapter;
using device::BluetoothAdapterFactory;

// Shared default adapter instance, we don't want to keep this class around
// if nobody is using it so use a WeakPtr and create the object when needed;
// since Google C++ Style (and clang's static analyzer) forbids us having
// exit-time destructors we use a leaky lazy instance for it.
base::LazyInstance<base::WeakPtr<device::BluetoothAdapter> >::Leaky
    default_adapter = LAZY_INSTANCE_INITIALIZER;

typedef std::vector<BluetoothAdapterFactory::AdapterCallback>
    AdapterCallbackList;

// List of adapter callbacks to be called once the adapter is initialized.
// Since Google C++ Style (and clang's static analyzer) forbids us having
// exit-time destructors we use a lazy instance for it.
base::LazyInstance<AdapterCallbackList> adapter_callbacks =
    LAZY_INSTANCE_INITIALIZER;

void RunAdapterCallbacks() {
  CHECK(default_adapter.Get().get());
  scoped_refptr<BluetoothAdapter> adapter(default_adapter.Get());
  for (std::vector<BluetoothAdapterFactory::AdapterCallback>::const_iterator
           iter = adapter_callbacks.Get().begin();
       iter != adapter_callbacks.Get().end();
       ++iter) {
    iter->Run(adapter);
  }
  adapter_callbacks.Get().clear();
}

}  // namespace

namespace device {

// static
bool BluetoothAdapterFactory::IsBluetoothAdapterAvailable() {
#if defined(OS_CHROMEOS)
  return true;
#elif defined(OS_WIN)
  return true;
#elif defined(OS_MACOSX)
  return base::mac::IsOSLionOrLater();
#endif
  return false;
}

// static
void BluetoothAdapterFactory::GetAdapter(const AdapterCallback& callback) {
  if (!default_adapter.Get().get()) {
#if defined(OS_CHROMEOS)
    if (CommandLine::ForCurrentProcess()->HasSwitch(
        chromeos::switches::kEnableExperimentalBluetooth)) {
      chromeos::BluetoothAdapterChromeOSExperimental* new_adapter =
          new chromeos::BluetoothAdapterChromeOSExperimental;
      new_adapter->TrackDefaultAdapter();
      default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
    } else {
      chromeos::BluetoothAdapterChromeOS* new_adapter =
          new chromeos::BluetoothAdapterChromeOS;
      new_adapter->TrackDefaultAdapter();
      default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
    }
#elif defined(OS_WIN)
    BluetoothAdapterWin* new_adapter = new BluetoothAdapterWin(
        base::Bind(&RunAdapterCallbacks));
    new_adapter->TrackDefaultAdapter();
    default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
#elif defined(OS_MACOSX)
    BluetoothAdapterMac* new_adapter = new BluetoothAdapterMac();
    new_adapter->TrackDefaultAdapter();
    default_adapter.Get() = new_adapter->weak_ptr_factory_.GetWeakPtr();
#endif
  }

  if (default_adapter.Get()->IsInitialized()) {
    callback.Run(scoped_refptr<BluetoothAdapter>(default_adapter.Get()));
  } else {
    adapter_callbacks.Get().push_back(callback);
  }
}

// static
scoped_refptr<BluetoothAdapter> BluetoothAdapterFactory::MaybeGetAdapter() {
  return scoped_refptr<BluetoothAdapter>(default_adapter.Get());
}

}  // namespace device
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Andreas Sandberg
 */

#include "debug/VIOPci.hh"
#include "dev/virtio/pci.hh"
#include "mem/packet_access.hh"
#include "params/PciVirtIO.hh"

PciVirtIO::PciVirtIO(const Params *params)
    : PciDevice(params), queueNotify(0), interruptDeliveryPending(false),
      vio(*params->vio), callbackKick(this)
{
    // Override the subsystem ID with the device ID from VirtIO
    config.subsystemID = htole(vio.deviceId);
    BARSize[0] = BAR0_SIZE_BASE + vio.configSize;

    vio.registerKickCallback(&callbackKick);
}

PciVirtIO::~PciVirtIO()
{
}

Tick
PciVirtIO::read(PacketPtr pkt)
{
    const unsigned M5_VAR_USED size(pkt->getSize());
    int bar;
    Addr offset;
    if (!getBAR(pkt->getAddr(), bar, offset))
        panic("Invalid PCI memory access to unmapped memory.\n");
    assert(bar == 0);

    DPRINTF(VIOPci, "Reading offset 0x%x [len: %i]\n", offset, size);

    // Forward device configuration writes to the device VirtIO model
    if (offset >= OFF_VIO_DEVICE) {
        vio.readConfig(pkt, offset - OFF_VIO_DEVICE);
        return 0;
    }

    pkt->makeResponse();

    switch(offset) {
      case OFF_DEVICE_FEATURES:
        DPRINTF(VIOPci, "   DEVICE_FEATURES request\n");
        assert(size == sizeof(uint32_t));
        pkt->set<uint32_t>(vio.deviceFeatures);
        break;

      case OFF_GUEST_FEATURES:
        DPRINTF(VIOPci, "   GUEST_FEATURES request\n");
        assert(size == sizeof(uint32_t));
        pkt->set<uint32_t>(vio.getGuestFeatures());
        break;

      case OFF_QUEUE_ADDRESS:
        DPRINTF(VIOPci, "   QUEUE_ADDRESS request\n");
        assert(size == sizeof(uint32_t));
        pkt->set<uint32_t>(vio.getQueueAddress());
        break;

      case OFF_QUEUE_SIZE:
        DPRINTF(VIOPci, "   QUEUE_SIZE request\n");
        assert(size == sizeof(uint16_t));
        pkt->set<uint16_t>(vio.getQueueSize());
        break;

      case OFF_QUEUE_SELECT:
        DPRINTF(VIOPci, "   QUEUE_SELECT\n");
        assert(size == sizeof(uint16_t));
        pkt->set<uint16_t>(vio.getQueueSelect());
        break;

      case OFF_QUEUE_NOTIFY:
        DPRINTF(VIOPci, "   QUEUE_NOTIFY request\n");
        assert(size == sizeof(uint16_t));
        pkt->set<uint16_t>(queueNotify);
        break;

      case OFF_DEVICE_STATUS:
        DPRINTF(VIOPci, "   DEVICE_STATUS request\n");
        assert(size == sizeof(uint8_t));
        pkt->set<uint8_t>(vio.getDeviceStatus());
        break;

      case OFF_ISR_STATUS: {
          DPRINTF(VIOPci, "   ISR_STATUS\n");
          assert(size == sizeof(uint8_t));
          uint8_t isr_status(interruptDeliveryPending ? 1 : 0);
          interruptDeliveryPending = false;
          pkt->set<uint8_t>(isr_status);
      } break;

      default:
        panic("Unhandled read offset (0x%x)\n", offset);
    }

    return 0;
}

Tick
PciVirtIO::write(PacketPtr pkt)
{
    const unsigned M5_VAR_USED size(pkt->getSize());
    int bar;
    Addr offset;
    if (!getBAR(pkt->getAddr(), bar, offset))
        panic("Invalid PCI memory access to unmapped memory.\n");
    assert(bar == 0);

    DPRINTF(VIOPci, "Writing offset 0x%x [len: %i]\n", offset, size);

    // Forward device configuration writes to the device VirtIO model
    if (offset >= OFF_VIO_DEVICE) {
        vio.writeConfig(pkt, offset - OFF_VIO_DEVICE);
        return 0;
    }

    pkt->makeResponse();

    switch(offset) {
      case OFF_DEVICE_FEATURES:
        warn("Guest tried to write device features.");
        break;

      case OFF_GUEST_FEATURES:
        DPRINTF(VIOPci, "   WRITE GUEST_FEATURES request\n");
        assert(size == sizeof(uint32_t));
        vio.setGuestFeatures(pkt->get<uint32_t>());
        break;

      case OFF_QUEUE_ADDRESS:
        DPRINTF(VIOPci, "   WRITE QUEUE_ADDRESS\n");
        assert(size == sizeof(uint32_t));
        vio.setQueueAddress(pkt->get<uint32_t>());
        break;

      case OFF_QUEUE_SIZE:
        panic("Guest tried to write queue size.");
        break;

      case OFF_QUEUE_SELECT:
        DPRINTF(VIOPci, "   WRITE QUEUE_SELECT\n");
        assert(size == sizeof(uint16_t));
        vio.setQueueSelect(pkt->get<uint16_t>());
        break;

      case OFF_QUEUE_NOTIFY:
        DPRINTF(VIOPci, "   WRITE QUEUE_NOTIFY\n");
        assert(size == sizeof(uint16_t));
        queueNotify = pkt->get<uint16_t>();
        vio.onNotify(queueNotify);
        break;

      case OFF_DEVICE_STATUS: {
          assert(size == sizeof(uint8_t));
          uint8_t status(pkt->get<uint8_t>());
          DPRINTF(VIOPci, "VirtIO set status: 0x%x\n", status);
          vio.setDeviceStatus(status);
      } break;

      case OFF_ISR_STATUS:
        warn("Guest tried to write ISR status.");
        break;

      default:
        panic("Unhandled read offset (0x%x)\n", offset);
    }

    return 0;
}

void
PciVirtIO::kick()
{
    DPRINTF(VIOPci, "kick(): Sending interrupt...\n");
    interruptDeliveryPending = true;
    intrPost();
}

PciVirtIO *
PciVirtIOParams::create()
{
    return new PciVirtIO(this);
}
<commit_msg>dev: Correctly clear interrupts in VirtIO PCI<commit_after>/*
 * Copyright (c) 2014 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Andreas Sandberg
 */

#include "debug/VIOPci.hh"
#include "dev/virtio/pci.hh"
#include "mem/packet_access.hh"
#include "params/PciVirtIO.hh"

PciVirtIO::PciVirtIO(const Params *params)
    : PciDevice(params), queueNotify(0), interruptDeliveryPending(false),
      vio(*params->vio), callbackKick(this)
{
    // Override the subsystem ID with the device ID from VirtIO
    config.subsystemID = htole(vio.deviceId);
    BARSize[0] = BAR0_SIZE_BASE + vio.configSize;

    vio.registerKickCallback(&callbackKick);
}

PciVirtIO::~PciVirtIO()
{
}

Tick
PciVirtIO::read(PacketPtr pkt)
{
    const unsigned M5_VAR_USED size(pkt->getSize());
    int bar;
    Addr offset;
    if (!getBAR(pkt->getAddr(), bar, offset))
        panic("Invalid PCI memory access to unmapped memory.\n");
    assert(bar == 0);

    DPRINTF(VIOPci, "Reading offset 0x%x [len: %i]\n", offset, size);

    // Forward device configuration writes to the device VirtIO model
    if (offset >= OFF_VIO_DEVICE) {
        vio.readConfig(pkt, offset - OFF_VIO_DEVICE);
        return 0;
    }

    pkt->makeResponse();

    switch(offset) {
      case OFF_DEVICE_FEATURES:
        DPRINTF(VIOPci, "   DEVICE_FEATURES request\n");
        assert(size == sizeof(uint32_t));
        pkt->set<uint32_t>(vio.deviceFeatures);
        break;

      case OFF_GUEST_FEATURES:
        DPRINTF(VIOPci, "   GUEST_FEATURES request\n");
        assert(size == sizeof(uint32_t));
        pkt->set<uint32_t>(vio.getGuestFeatures());
        break;

      case OFF_QUEUE_ADDRESS:
        DPRINTF(VIOPci, "   QUEUE_ADDRESS request\n");
        assert(size == sizeof(uint32_t));
        pkt->set<uint32_t>(vio.getQueueAddress());
        break;

      case OFF_QUEUE_SIZE:
        DPRINTF(VIOPci, "   QUEUE_SIZE request\n");
        assert(size == sizeof(uint16_t));
        pkt->set<uint16_t>(vio.getQueueSize());
        break;

      case OFF_QUEUE_SELECT:
        DPRINTF(VIOPci, "   QUEUE_SELECT\n");
        assert(size == sizeof(uint16_t));
        pkt->set<uint16_t>(vio.getQueueSelect());
        break;

      case OFF_QUEUE_NOTIFY:
        DPRINTF(VIOPci, "   QUEUE_NOTIFY request\n");
        assert(size == sizeof(uint16_t));
        pkt->set<uint16_t>(queueNotify);
        break;

      case OFF_DEVICE_STATUS:
        DPRINTF(VIOPci, "   DEVICE_STATUS request\n");
        assert(size == sizeof(uint8_t));
        pkt->set<uint8_t>(vio.getDeviceStatus());
        break;

      case OFF_ISR_STATUS: {
          DPRINTF(VIOPci, "   ISR_STATUS\n");
          assert(size == sizeof(uint8_t));
          const uint8_t isr_status(interruptDeliveryPending ? 1 : 0);
          if (interruptDeliveryPending) {
              interruptDeliveryPending = false;
              intrClear();
          }
          pkt->set<uint8_t>(isr_status);
      } break;

      default:
        panic("Unhandled read offset (0x%x)\n", offset);
    }

    return 0;
}

Tick
PciVirtIO::write(PacketPtr pkt)
{
    const unsigned M5_VAR_USED size(pkt->getSize());
    int bar;
    Addr offset;
    if (!getBAR(pkt->getAddr(), bar, offset))
        panic("Invalid PCI memory access to unmapped memory.\n");
    assert(bar == 0);

    DPRINTF(VIOPci, "Writing offset 0x%x [len: %i]\n", offset, size);

    // Forward device configuration writes to the device VirtIO model
    if (offset >= OFF_VIO_DEVICE) {
        vio.writeConfig(pkt, offset - OFF_VIO_DEVICE);
        return 0;
    }

    pkt->makeResponse();

    switch(offset) {
      case OFF_DEVICE_FEATURES:
        warn("Guest tried to write device features.");
        break;

      case OFF_GUEST_FEATURES:
        DPRINTF(VIOPci, "   WRITE GUEST_FEATURES request\n");
        assert(size == sizeof(uint32_t));
        vio.setGuestFeatures(pkt->get<uint32_t>());
        break;

      case OFF_QUEUE_ADDRESS:
        DPRINTF(VIOPci, "   WRITE QUEUE_ADDRESS\n");
        assert(size == sizeof(uint32_t));
        vio.setQueueAddress(pkt->get<uint32_t>());
        break;

      case OFF_QUEUE_SIZE:
        panic("Guest tried to write queue size.");
        break;

      case OFF_QUEUE_SELECT:
        DPRINTF(VIOPci, "   WRITE QUEUE_SELECT\n");
        assert(size == sizeof(uint16_t));
        vio.setQueueSelect(pkt->get<uint16_t>());
        break;

      case OFF_QUEUE_NOTIFY:
        DPRINTF(VIOPci, "   WRITE QUEUE_NOTIFY\n");
        assert(size == sizeof(uint16_t));
        queueNotify = pkt->get<uint16_t>();
        vio.onNotify(queueNotify);
        break;

      case OFF_DEVICE_STATUS: {
          assert(size == sizeof(uint8_t));
          uint8_t status(pkt->get<uint8_t>());
          DPRINTF(VIOPci, "VirtIO set status: 0x%x\n", status);
          vio.setDeviceStatus(status);
      } break;

      case OFF_ISR_STATUS:
        warn("Guest tried to write ISR status.");
        break;

      default:
        panic("Unhandled read offset (0x%x)\n", offset);
    }

    return 0;
}

void
PciVirtIO::kick()
{
    DPRINTF(VIOPci, "kick(): Sending interrupt...\n");
    interruptDeliveryPending = true;
    intrPost();
}

PciVirtIO *
PciVirtIOParams::create()
{
    return new PciVirtIO(this);
}
<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/

/* rev for v2.3 by JGG */

#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include <stdio.h>
#include <assert.h>
#include "../rtstuff/Instrument.h"
#include "../rtstuff/rtdefs.h"

#define INCHANS_DISCREPANCY_WARNING "\
The bus config for this instrument specifies %d input channels, \n\
but its input source has %d channels. Setting input channels to %d..."

/* ----------------------------------------------------------- rtsetinput --- */
/* Instruments call this to set their input file pointer (like setnote in cmix).
   Returns 0 if ok, -1 if error.
*/
int
rtsetinput(float start_time, Instrument *inst)
{
   int   auxin_count = inst->bus_config->auxin_count;
   int   in_count = inst->bus_config->in_count;
   char  *inst_name = NULL;      // FIXME: need this for better msgs

   if (auxin_count == 0 && in_count == 0)
      die(inst_name, "This instrument requires input from either an in bus "
                      "or an aux bus.\nChange this with bus_config().");

   if (auxin_count > 0) {
      if (start_time != 0.0)
         die(inst_name, "Input start must be 0 when reading from an aux bus.");
   }

   if (in_count > 0) {
      int src_chans;
      int index = get_last_input_index();

      if (index < 0 || inputFileTable[index].fd < 1)
         die(inst_name, "No input source open for this instrument!");

      /* File or audio device was opened in rtinput(). Here we store the
         index into the inputFileTable for the file or device.
      */
      inst->fdIndex = index;

      /* Fill in relevant data members of instrument class. */
      inst->inputsr = inputFileTable[index].srate;

      src_chans = inputFileTable[index].chans;

      if (inst->inputchans != src_chans) {
         warn(inst_name, INCHANS_DISCREPANCY_WARNING, inst->inputchans,
                                                      src_chans, src_chans);
         inst->inputchans = src_chans;
      }

      if (inputFileTable[index].is_audio_dev) {
         if (start_time != 0.0)
            die(inst_name, "Input start must be 0 when reading from the "
                           "real-time audio device.");
      }
      else {
         int datum_size, inskip;

         inst->sfile_on = 1;

         inskip = (int) (start_time * inst->inputsr);

         /* sndlib always uses 2 for datum size, even if the actual size is
            different. However, we don't use sndlib to read float files, so
            their datum size is the real thing.
         */
         if (inputFileTable[index].is_float_format)
            datum_size = sizeof(float);
         else
            datum_size = 2;

         /* Offset is measured from the header size determined in rtinput(). */
         inst->fileOffset = inputFileTable[index].data_location
                            + (inskip * inst->inputchans * datum_size);

         if (start_time >= inputFileTable[index].dur)
            warn(inst_name, "Attempt to read past end of input file: %s",
                                             inputFileTable[index].filename);
      }

      /* Increment the reference count for this file. */
      inputFileTable[index].refcount++;
   }

   return 0;
}

<commit_msg>Comment out INCHANS_DISCREPANCY_WARNING. Match inst->inputchans to file chans only when file is a sound file   (and not when it represents a real-time audio fd). Other minor cleanups.<commit_after>/* RTcmix  - Copyright (C) 2000  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/

/* rev for v2.3 by JGG */

#include <globals.h>
#include <prototypes.h>
#include <ugens.h>
#include <stdio.h>
#include <assert.h>
#include "../rtstuff/Instrument.h"
#include "../rtstuff/rtdefs.h"

#define INCHANS_DISCREPANCY_WARNING "\
The bus config for this instrument specifies %d input channels, \n\
but its input source has %d channels. Setting input channels to %d..."

/* ----------------------------------------------------------- rtsetinput --- */
/* Instruments call this to set their input file pointer (like setnote in cmix).
   Returns 0 if ok, -1 if error.
*/
int
rtsetinput(float start_time, Instrument *inst)
{
   int   auxin_count = inst->bus_config->auxin_count;
   int   in_count = inst->bus_config->in_count;
   char  *inst_name = NULL;      // FIXME: need this for better msgs

   if (auxin_count == 0 && in_count == 0)
      die(inst_name, "This instrument requires input from either an in bus "
                      "or an aux bus.\nChange this with bus_config().");

   if (auxin_count > 0) {
      if (start_time != 0.0)
         die(inst_name, "Input start must be 0 when reading from an aux bus.");
   }

   if (in_count > 0) {
      int src_chans;
      int index = get_last_input_index();

      if (index < 0 || inputFileTable[index].fd < 1)
         die(inst_name, "No input source open for this instrument!");

      /* File or audio device was opened in rtinput(). Here we store the
         index into the inputFileTable for the file or device.
      */
      inst->fdIndex = index;

      /* Fill in relevant data members of instrument class. */
      inst->inputsr = inputFileTable[index].srate;

      src_chans = inputFileTable[index].chans;

      if (inputFileTable[index].is_audio_dev) {
         if (start_time != 0.0)
            die(inst_name, "Input start must be 0 when reading from the "
                           "real-time audio device.");
      }
      else {
         int datum_size, inskip_frames;

         if (inst->inputchans != src_chans) {
#ifdef NOMORE // pointless ifdef IGNORE_BUS_COUNT_FOR_FILE_INPUT in rtgetin.C
            advise(inst_name, INCHANS_DISCREPANCY_WARNING, inst->inputchans,
                                                        src_chans, src_chans);
#endif
            inst->inputchans = src_chans;
         }

         inst->sfile_on = 1;

         inskip_frames = (int) (start_time * inst->inputsr);

         /* sndlib always uses 2 for datum size, even if the actual size is
            different. However, we don't use sndlib to read float files, so
            their datum size is the real thing.
         */
         if (inputFileTable[index].is_float_format)
            datum_size = sizeof(float);
         else
            datum_size = 2;

         /* Offset is measured from the header size determined in rtinput(). */
         inst->fileOffset = inputFileTable[index].data_location
                            + (inskip_frames * inst->inputchans * datum_size);

         if (start_time >= inputFileTable[index].dur)
            warn(inst_name, "Attempt to read past end of input file: %s",
                                             inputFileTable[index].filename);
      }

      /* Increment the reference count for this file. */
      inputFileTable[index].refcount++;
   }

   return 0;
}

<|endoftext|>


<commit_before>// Copyright (c) 2011-2012 Steinwurf ApS
// All Rights Reserved

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Steinwurf ApS nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.

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

#include "endian_buffer.hpp"

#include "convert_endian.h"

#include <cassert>

namespace sak
{
    endian_buffer::endian_buffer(uint8_t* buffer, uint32_t size)
        : m_buffer(buffer),
          m_position(0),
          m_size(size)
    {
        assert(m_buffer != 0);
        assert(m_position == 0);
        assert(m_size);
    }

    void endian_buffer::write_u8(uint8_t v)
    {
        uint8_t* write_position = m_buffer+m_position;
        m_position += sizeof(uint8_t);
        assert(m_position <= m_size);
        big_endian::put<uint8_t>(v, write_position);
    }

    void endian_buffer::write_u16(uint16_t v)
    {
        uint8_t* write_position = m_buffer+m_position;
        m_position += sizeof(uint16_t);
        assert(m_position <= m_size);
        big_endian::put<uint16_t>(v, write_position);

    }

    void endian_buffer::write_u32(uint32_t v)
    {
        uint8_t* write_position = m_buffer+m_position;
        m_position += sizeof(uint32_t);
        assert(m_position <= m_size);
        big_endian::put<uint32_t>(v, write_position);

    }

    void endian_buffer::write_u64(uint64_t v)
    {
        uint8_t* write_position = m_buffer+m_position;
        m_position += sizeof(uint64_t);
        assert(m_position <= m_size);
        big_endian::put<uint64_t>(v, write_position);

    }

    uint8_t endian_buffer::read_u8()
    {
        m_position -= sizeof(uint8_t);
        return big_endian::get<uint8_t>(m_buffer + m_position);
    }

    uint16_t endian_buffer::read_u16()
    {
        m_position -= sizeof(uint16_t);
        return big_endian::get<uint16_t>(m_buffer +  m_position);
    }

    uint32_t endian_buffer::read_u32()
    {
        m_position -= sizeof(uint32_t);
        return big_endian::get<uint32_t>(m_buffer + m_position);
    }

    uint64_t endian_buffer::read_u64()
    {
        m_position -= sizeof(uint64_t);
        return big_endian::get<uint64_t>(m_buffer + m_position);
    }

    uint32_t endian_buffer::size() const
    {
        return m_size;
    }

    uint32_t endian_buffer::position() const
    {
        return m_position;
    }
}
<commit_msg>removed unneeded assert<commit_after>// Copyright (c) 2011-2012 Steinwurf ApS
// All Rights Reserved

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//     * Neither the name of Steinwurf ApS nor the
//       names of its contributors may be used to endorse or promote products
//       derived from this software without specific prior written permission.

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

#include "endian_buffer.hpp"

#include "convert_endian.h"

#include <cassert>

namespace sak
{
    endian_buffer::endian_buffer(uint8_t* buffer, uint32_t size)
        : m_buffer(buffer),
          m_position(0),
          m_size(size)
    {
        assert(m_buffer != 0);
        assert(m_size);
    }

    void endian_buffer::write_u8(uint8_t v)
    {
        uint8_t* write_position = m_buffer+m_position;
        m_position += sizeof(uint8_t);
        assert(m_position <= m_size);
        big_endian::put<uint8_t>(v, write_position);
    }

    void endian_buffer::write_u16(uint16_t v)
    {
        uint8_t* write_position = m_buffer+m_position;
        m_position += sizeof(uint16_t);
        assert(m_position <= m_size);
        big_endian::put<uint16_t>(v, write_position);

    }

    void endian_buffer::write_u32(uint32_t v)
    {
        uint8_t* write_position = m_buffer+m_position;
        m_position += sizeof(uint32_t);
        assert(m_position <= m_size);
        big_endian::put<uint32_t>(v, write_position);

    }

    void endian_buffer::write_u64(uint64_t v)
    {
        uint8_t* write_position = m_buffer+m_position;
        m_position += sizeof(uint64_t);
        assert(m_position <= m_size);
        big_endian::put<uint64_t>(v, write_position);

    }

    uint8_t endian_buffer::read_u8()
    {
        m_position -= sizeof(uint8_t);
        return big_endian::get<uint8_t>(m_buffer + m_position);
    }

    uint16_t endian_buffer::read_u16()
    {
        m_position -= sizeof(uint16_t);
        return big_endian::get<uint16_t>(m_buffer +  m_position);
    }

    uint32_t endian_buffer::read_u32()
    {
        m_position -= sizeof(uint32_t);
        return big_endian::get<uint32_t>(m_buffer + m_position);
    }

    uint64_t endian_buffer::read_u64()
    {
        m_position -= sizeof(uint64_t);
        return big_endian::get<uint64_t>(m_buffer + m_position);
    }

    uint32_t endian_buffer::size() const
    {
        return m_size;
    }

    uint32_t endian_buffer::position() const
    {
        return m_position;
    }
}
<|endoftext|>