<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "snippet.h"

#include <coreplugin/id.h>

#include <QLatin1Char>
#include <QLatin1String>
#include <QTextDocument>

using namespace TextEditor;

const char NOMANGLER_ID[] = "TextEditor::NoMangler";
const char UCMANGLER_ID[] = "TextEditor::UppercaseMangler";
const char LCMANGLER_ID[] = "TextEditor::LowercaseMangler";
const char TCMANGLER_ID[] = "TextEditor::TitlecaseMangler";

Q_DECLARE_METATYPE(QList<int>)

// --------------------------------------------------------------------
// Manglers:
// --------------------------------------------------------------------

class UppercaseMangler : public NameMangler
{
public:
    Core::Id id() const { return UCMANGLER_ID; }
    QString mangle(const QString &unmangled) const { return unmangled.toUpper(); }
};

class LowercaseMangler : public NameMangler
{
public:
    Core::Id id() const { return LCMANGLER_ID; }
    QString mangle(const QString &unmangled) const { return unmangled.toLower(); }
};

class TitlecaseMangler : public NameMangler
{
public:
    Core::Id id() const { return TCMANGLER_ID; }
    QString mangle(const QString &unmangled) const
    {
        QString result = unmangled;
        if (!result.isEmpty())
            result[0] = unmangled.at(0).toTitleCase();
        return result;
    }
};

// --------------------------------------------------------------------
// Snippet:
// --------------------------------------------------------------------

const QChar Snippet::kVariableDelimiter(QLatin1Char('$'));

Snippet::Snippet(const QString &groupId, const QString &id) :
    m_isRemoved(false), m_isModified(false), m_groupId(groupId), m_id(id)
{}

Snippet::~Snippet()
{}

const QString &Snippet::id() const
{
    return m_id;
}

const QString &Snippet::groupId() const
{
    return m_groupId;
}

bool Snippet::isBuiltIn() const
{
    return !m_id.isEmpty();
}

void Snippet::setTrigger(const QString &trigger)
{
    m_trigger = trigger;
}

const QString &Snippet::trigger() const
{
    return m_trigger;
}

void Snippet::setContent(const QString &content)
{
    m_content = content;
}

const QString &Snippet::content() const
{
    return m_content;
}

void Snippet::setComplement(const QString &complement)
{
    m_complement = complement;
}

const QString &Snippet::complement() const
{
    return m_complement;
}

void Snippet::setIsRemoved(bool removed)
{
    m_isRemoved = removed;
}

bool Snippet::isRemoved() const
{
    return m_isRemoved;
}

void Snippet::setIsModified(bool modified)
{
    m_isModified = modified;
}

bool Snippet::isModified() const
{
    return m_isModified;
}

QString Snippet::generateTip() const
{
    static const QLatin1Char kNewLine('\n');
    static const QLatin1Char kSpace(' ');
    static const QLatin1String kBr("
");
    static const QLatin1String kNbsp(" ");
    static const QLatin1String kNoBr("<nobr>");
    static const QLatin1String kOpenBold("");
    static const QLatin1String kCloseBold("");
    static const QLatin1String kEllipsis("...");

    QString escapedContent(Qt::escape(m_content));
    escapedContent.replace(kNewLine, kBr);
    escapedContent.replace(kSpace, kNbsp);

    QString tip(kNoBr);
    int count = 0;
    for (int i = 0; i < escapedContent.count(); ++i) {
        if (escapedContent.at(i) != kVariableDelimiter) {
            tip += escapedContent.at(i);
            continue;
        }
        if (++count % 2) {
            tip += kOpenBold;
        } else {
            if (escapedContent.at(i-1) == kVariableDelimiter)
                tip += kEllipsis;
            tip += kCloseBold;
        }
    }

    return tip;
}

Snippet::ParsedSnippet Snippet::parse(const QString &snippet)
{
    static UppercaseMangler ucMangler;
    static LowercaseMangler lcMangler;
    static TitlecaseMangler tcMangler;

    Snippet::ParsedSnippet result;
    result.success = true;

    const int count = snippet.count();
    bool success = true;
    int start = -1;
    NameMangler *mangler = 0;

    result.text.reserve(count);

    for (int i = 0; i < count; ++i) {
        QChar current = snippet.at(i);
        QChar next = (i + 1) < count ? snippet.at(i + 1) : QChar();

        if (current == Snippet::kVariableDelimiter) {
            if (start < 0) {
                // start delimiter:
                start = result.text.count();
            } else {
                int length = result.text.count() - start;
                result.ranges << ParsedSnippet::Range(start, length, mangler);
                mangler = 0;
                start = -1;
            }
            continue;
        }

        if (mangler) {
            success = false;
            break;
        }

        if (current == QLatin1Char(':')) {
            if (start >= 0) {
                if (mangler != 0) {
                    success = false;
                    break;
                }
                if (next == QLatin1Char('l')) {
                    mangler = &lcMangler;
                } else if (next == QLatin1Char('u')) {
                    mangler = &ucMangler;
                } else if (next == QLatin1Char('c')) {
                    mangler = &tcMangler;
                } else {
                    success = false;
                    break;
                }
            }
            ++i;
            continue;
        }

        if (current == QLatin1Char('\\')) {
            if (next.isNull()) {
                success = false;
                break;
            }
            result.text.append(next);
            ++i;
            continue;
        }

        result.text.append(current);
    }

    if (start >= 0)
        success = false;

    result.success = success;

    if (!success) {
        result.ranges.clear();
        result.text = snippet;
    }

    return result;
}

#ifdef WITH_TESTS
#   include <QTest>

#   include "texteditorplugin.h"

void Internal::TextEditorPlugin::testSnippetParsing_data()
{
    QTest::addColumn<QString>("input");
    QTest::addColumn<QString>("text");
    QTest::addColumn<bool>("success");
    QTest::addColumn<QList<int> >("ranges_start");
    QTest::addColumn<QList<int> >("ranges_length");
    QTest::addColumn<QList<Core::Id> >("ranges_mangler");

    QTest::newRow("no input")
            << QString() << QString() << true
            << (QList<int>()) << (QList<int>()) << (QList<Core::Id>());
    QTest::newRow("empty input")
            << QString::fromLatin1("") << QString::fromLatin1("") << true
            << (QList<int>()) << (QList<int>()) << (QList<Core::Id>());

    QTest::newRow("simple identifier")
            << QString::fromLatin1("$tESt$") << QString::fromLatin1("tESt") << true
            << (QList<int>() << 0) << (QList<int>() << 4)
            << (QList<Core::Id>() << NOMANGLER_ID);
    QTest::newRow("simple identifier with lc")
            << QString::fromLatin1("$tESt:l$") << QString::fromLatin1("tESt") << true
            << (QList<int>() << 0) << (QList<int>() << 4)
            << (QList<Core::Id>() << LCMANGLER_ID);
    QTest::newRow("simple identifier with uc")
            << QString::fromLatin1("$tESt:u$") << QString::fromLatin1("tESt") << true
            << (QList<int>() << 0) << (QList<int>() << 4)
            << (QList<Core::Id>() << UCMANGLER_ID);
    QTest::newRow("simple identifier with tc")
            << QString::fromLatin1("$tESt:c$") << QString::fromLatin1("tESt") << true
            << (QList<int>() << 0) << (QList<int>() << 4)
            << (QList<Core::Id>() << TCMANGLER_ID);

    QTest::newRow("escaped string")
            << QString::fromLatin1("\\$test\\$") << QString::fromLatin1("$test$") << true
            << (QList<int>()) << (QList<int>())
            << (QList<Core::Id>());
    QTest::newRow("escaped escape")
            << QString::fromLatin1("\\\\$test\\\\$") << QString::fromLatin1("\\test\\") << true
            << (QList<int>() << 1) << (QList<int>() << 5)
            << (QList<Core::Id>() << NOMANGLER_ID);

    QTest::newRow("Q_PROPERTY")
            << QString::fromLatin1("Q_PROPERTY($type$ $name$ READ $name$ WRITE set$name:c$ NOTIFY $name$Changed)")
            << QString::fromLatin1("Q_PROPERTY(type name READ name WRITE setname NOTIFY nameChanged)") << true
            << (QList<int>() << 11 << 16 << 26 << 40 << 52)
            << (QList<int>() << 4 << 4 << 4 << 4 << 4)
            << (QList<Core::Id>() << NOMANGLER_ID << NOMANGLER_ID << NOMANGLER_ID << TCMANGLER_ID << NOMANGLER_ID);

    QTest::newRow("broken escape")
            << QString::fromLatin1("\\\\$test\\\\$\\") << QString::fromLatin1("\\\\$test\\\\$\\") << false
            << (QList<int>()) << (QList<int>())
            << (QList<Core::Id>());
    QTest::newRow("open identifier")
            << QString::fromLatin1("$test") << QString::fromLatin1("$test") << false
            << (QList<int>()) << (QList<int>())
            << (QList<Core::Id>());
    QTest::newRow("wrong mangler")
            << QString::fromLatin1("$test:X$") << QString::fromLatin1("$test:X$") << false
            << (QList<int>()) << (QList<int>())
            << (QList<Core::Id>());
}

void Internal::TextEditorPlugin::testSnippetParsing()
{
    QFETCH(QString, input);
    QFETCH(QString, text);
    QFETCH(bool, success);
    QFETCH(QList<int>, ranges_start);
    QFETCH(QList<int>, ranges_length);
    QFETCH(QList<Core::Id>, ranges_mangler);
    Q_ASSERT(ranges_start.count() == ranges_length.count()); // sanity check for the test data
    Q_ASSERT(ranges_start.count() == ranges_mangler.count()); // sanity check for the test data

    Snippet::ParsedSnippet result = Snippet::parse(input);

    QCOMPARE(result.text, text);
    QCOMPARE(result.success, success);
    QCOMPARE(result.ranges.count(), ranges_start.count());
    for (int i = 0; i < ranges_start.count(); ++i) {
        QCOMPARE(result.ranges.at(i).start, ranges_start.at(i));
        QCOMPARE(result.ranges.at(i).length, ranges_length.at(i));
        Core::Id id = NOMANGLER_ID;
        if (result.ranges.at(i).mangler)
            id = result.ranges.at(i).mangler->id();
        QCOMPARE(id, ranges_mangler.at(i));
    }
}
#endif

<commit_msg>Snippet: Fix snippets with : in them<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "snippet.h"

#include <coreplugin/id.h>

#include <QLatin1Char>
#include <QLatin1String>
#include <QTextDocument>

using namespace TextEditor;

const char NOMANGLER_ID[] = "TextEditor::NoMangler";
const char UCMANGLER_ID[] = "TextEditor::UppercaseMangler";
const char LCMANGLER_ID[] = "TextEditor::LowercaseMangler";
const char TCMANGLER_ID[] = "TextEditor::TitlecaseMangler";

Q_DECLARE_METATYPE(QList<int>)

// --------------------------------------------------------------------
// Manglers:
// --------------------------------------------------------------------

class UppercaseMangler : public NameMangler
{
public:
    Core::Id id() const { return UCMANGLER_ID; }
    QString mangle(const QString &unmangled) const { return unmangled.toUpper(); }
};

class LowercaseMangler : public NameMangler
{
public:
    Core::Id id() const { return LCMANGLER_ID; }
    QString mangle(const QString &unmangled) const { return unmangled.toLower(); }
};

class TitlecaseMangler : public NameMangler
{
public:
    Core::Id id() const { return TCMANGLER_ID; }
    QString mangle(const QString &unmangled) const
    {
        QString result = unmangled;
        if (!result.isEmpty())
            result[0] = unmangled.at(0).toTitleCase();
        return result;
    }
};

// --------------------------------------------------------------------
// Snippet:
// --------------------------------------------------------------------

const QChar Snippet::kVariableDelimiter(QLatin1Char('$'));

Snippet::Snippet(const QString &groupId, const QString &id) :
    m_isRemoved(false), m_isModified(false), m_groupId(groupId), m_id(id)
{}

Snippet::~Snippet()
{}

const QString &Snippet::id() const
{
    return m_id;
}

const QString &Snippet::groupId() const
{
    return m_groupId;
}

bool Snippet::isBuiltIn() const
{
    return !m_id.isEmpty();
}

void Snippet::setTrigger(const QString &trigger)
{
    m_trigger = trigger;
}

const QString &Snippet::trigger() const
{
    return m_trigger;
}

void Snippet::setContent(const QString &content)
{
    m_content = content;
}

const QString &Snippet::content() const
{
    return m_content;
}

void Snippet::setComplement(const QString &complement)
{
    m_complement = complement;
}

const QString &Snippet::complement() const
{
    return m_complement;
}

void Snippet::setIsRemoved(bool removed)
{
    m_isRemoved = removed;
}

bool Snippet::isRemoved() const
{
    return m_isRemoved;
}

void Snippet::setIsModified(bool modified)
{
    m_isModified = modified;
}

bool Snippet::isModified() const
{
    return m_isModified;
}

QString Snippet::generateTip() const
{
    static const QLatin1Char kNewLine('\n');
    static const QLatin1Char kSpace(' ');
    static const QLatin1String kBr("
");
    static const QLatin1String kNbsp(" ");
    static const QLatin1String kNoBr("<nobr>");
    static const QLatin1String kOpenBold("");
    static const QLatin1String kCloseBold("");
    static const QLatin1String kEllipsis("...");

    QString escapedContent(Qt::escape(m_content));
    escapedContent.replace(kNewLine, kBr);
    escapedContent.replace(kSpace, kNbsp);

    QString tip(kNoBr);
    int count = 0;
    for (int i = 0; i < escapedContent.count(); ++i) {
        if (escapedContent.at(i) != kVariableDelimiter) {
            tip += escapedContent.at(i);
            continue;
        }
        if (++count % 2) {
            tip += kOpenBold;
        } else {
            if (escapedContent.at(i-1) == kVariableDelimiter)
                tip += kEllipsis;
            tip += kCloseBold;
        }
    }

    return tip;
}

Snippet::ParsedSnippet Snippet::parse(const QString &snippet)
{
    static UppercaseMangler ucMangler;
    static LowercaseMangler lcMangler;
    static TitlecaseMangler tcMangler;

    Snippet::ParsedSnippet result;
    result.success = true;

    const int count = snippet.count();
    bool success = true;
    int start = -1;
    NameMangler *mangler = 0;

    result.text.reserve(count);

    for (int i = 0; i < count; ++i) {
        QChar current = snippet.at(i);
        QChar next = (i + 1) < count ? snippet.at(i + 1) : QChar();

        if (current == Snippet::kVariableDelimiter) {
            if (start < 0) {
                // start delimiter:
                start = result.text.count();
            } else {
                int length = result.text.count() - start;
                result.ranges << ParsedSnippet::Range(start, length, mangler);
                mangler = 0;
                start = -1;
            }
            continue;
        }

        if (mangler) {
            success = false;
            break;
        }

        if (current == QLatin1Char(':') && start >= 0) {
            if (mangler != 0) {
                success = false;
                break;
            }
            if (next == QLatin1Char('l')) {
                mangler = &lcMangler;
            } else if (next == QLatin1Char('u')) {
                mangler = &ucMangler;
            } else if (next == QLatin1Char('c')) {
                mangler = &tcMangler;
            } else {
                success = false;
                break;
            }
            ++i;
            continue;
        }

        if (current == QLatin1Char('\\')) {
            if (next.isNull()) {
                success = false;
                break;
            }
            result.text.append(next);
            ++i;
            continue;
        }

        result.text.append(current);
    }

    if (start >= 0)
        success = false;

    result.success = success;

    if (!success) {
        result.ranges.clear();
        result.text = snippet;
    }

    return result;
}

#ifdef WITH_TESTS
#   include <QTest>

#   include "texteditorplugin.h"

void Internal::TextEditorPlugin::testSnippetParsing_data()
{
    QTest::addColumn<QString>("input");
    QTest::addColumn<QString>("text");
    QTest::addColumn<bool>("success");
    QTest::addColumn<QList<int> >("ranges_start");
    QTest::addColumn<QList<int> >("ranges_length");
    QTest::addColumn<QList<Core::Id> >("ranges_mangler");

    QTest::newRow("no input")
            << QString() << QString() << true
            << (QList<int>()) << (QList<int>()) << (QList<Core::Id>());
    QTest::newRow("empty input")
            << QString::fromLatin1("") << QString::fromLatin1("") << true
            << (QList<int>()) << (QList<int>()) << (QList<Core::Id>());

    QTest::newRow("simple identifier")
            << QString::fromLatin1("$tESt$") << QString::fromLatin1("tESt") << true
            << (QList<int>() << 0) << (QList<int>() << 4)
            << (QList<Core::Id>() << NOMANGLER_ID);
    QTest::newRow("simple identifier with lc")
            << QString::fromLatin1("$tESt:l$") << QString::fromLatin1("tESt") << true
            << (QList<int>() << 0) << (QList<int>() << 4)
            << (QList<Core::Id>() << LCMANGLER_ID);
    QTest::newRow("simple identifier with uc")
            << QString::fromLatin1("$tESt:u$") << QString::fromLatin1("tESt") << true
            << (QList<int>() << 0) << (QList<int>() << 4)
            << (QList<Core::Id>() << UCMANGLER_ID);
    QTest::newRow("simple identifier with tc")
            << QString::fromLatin1("$tESt:c$") << QString::fromLatin1("tESt") << true
            << (QList<int>() << 0) << (QList<int>() << 4)
            << (QList<Core::Id>() << TCMANGLER_ID);

    QTest::newRow("escaped string")
            << QString::fromLatin1("\\$test\\$") << QString::fromLatin1("$test$") << true
            << (QList<int>()) << (QList<int>())
            << (QList<Core::Id>());
    QTest::newRow("escaped escape")
            << QString::fromLatin1("\\\\$test\\\\$") << QString::fromLatin1("\\test\\") << true
            << (QList<int>() << 1) << (QList<int>() << 5)
            << (QList<Core::Id>() << NOMANGLER_ID);

    QTest::newRow("Q_PROPERTY")
            << QString::fromLatin1("Q_PROPERTY($type$ $name$ READ $name$ WRITE set$name:c$ NOTIFY $name$Changed)")
            << QString::fromLatin1("Q_PROPERTY(type name READ name WRITE setname NOTIFY nameChanged)") << true
            << (QList<int>() << 11 << 16 << 26 << 40 << 52)
            << (QList<int>() << 4 << 4 << 4 << 4 << 4)
            << (QList<Core::Id>() << NOMANGLER_ID << NOMANGLER_ID << NOMANGLER_ID << TCMANGLER_ID << NOMANGLER_ID);

    QTest::newRow("broken escape")
            << QString::fromLatin1("\\\\$test\\\\$\\") << QString::fromLatin1("\\\\$test\\\\$\\") << false
            << (QList<int>()) << (QList<int>())
            << (QList<Core::Id>());
    QTest::newRow("open identifier")
            << QString::fromLatin1("$test") << QString::fromLatin1("$test") << false
            << (QList<int>()) << (QList<int>())
            << (QList<Core::Id>());
    QTest::newRow("wrong mangler")
            << QString::fromLatin1("$test:X$") << QString::fromLatin1("$test:X$") << false
            << (QList<int>()) << (QList<int>())
            << (QList<Core::Id>());

    QTest::newRow("multiline with :")
            << QString::fromLatin1("class $name$\n"
                                   "{\n"
                                   "public:\n"
                                   "    $name$() {}\n"
                                   "};")
            << QString::fromLatin1("class name\n"
                                   "{\n"
                                   "public:\n"
                                   "    name() {}\n"
                                   "};")
            << true
            << (QList<int>() << 6 << 25)
            << (QList<int>() << 4 << 4)
            << (QList<Core::Id>() << NOMANGLER_ID << NOMANGLER_ID);
}

void Internal::TextEditorPlugin::testSnippetParsing()
{
    QFETCH(QString, input);
    QFETCH(QString, text);
    QFETCH(bool, success);
    QFETCH(QList<int>, ranges_start);
    QFETCH(QList<int>, ranges_length);
    QFETCH(QList<Core::Id>, ranges_mangler);
    Q_ASSERT(ranges_start.count() == ranges_length.count()); // sanity check for the test data
    Q_ASSERT(ranges_start.count() == ranges_mangler.count()); // sanity check for the test data

    Snippet::ParsedSnippet result = Snippet::parse(input);

    QCOMPARE(result.text, text);
    QCOMPARE(result.success, success);
    QCOMPARE(result.ranges.count(), ranges_start.count());
    for (int i = 0; i < ranges_start.count(); ++i) {
        QCOMPARE(result.ranges.at(i).start, ranges_start.at(i));
        QCOMPARE(result.ranges.at(i).length, ranges_length.at(i));
        Core::Id id = NOMANGLER_ID;
        if (result.ranges.at(i).mangler)
            id = result.ranges.at(i).mangler->id();
        QCOMPARE(id, ranges_mangler.at(i));
    }
}
#endif

<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "updateinfoplugin.h"
#include "updateinfobutton.h"

#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>

#include <qtconcurrentrun.h>

#include <QtCore/QtPlugin>
#include <QtCore/QProcess>
#include <QtCore/QTimer>
#include <QtCore/QTimerEvent>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QThread>
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtXml/QDomDocument>
#include <QtGui/QMessageBox>
#include <QtGui/QMenu>
#include <QtCore/QFutureWatcher>

namespace {
    static const quint32 OneMinute = 60000;
}

namespace UpdateInfo {
namespace Internal {

class UpdateInfoPluginPrivate
{
public:
    UpdateInfoPluginPrivate()
        : startUpdaterAction(0),
          currentTimerId(0),
          progressUpdateInfoButton(0),
          checkUpdateInfoWatcher(0)
    {}
    ~UpdateInfoPluginPrivate()
    {
    }

    QAction *startUpdaterAction;
    QString updaterProgram;
    QString updaterCheckOnlyArgument;
    QString updaterRunUiArgument;
    int currentTimerId;
    QFuture<QDomDocument> lastCheckUpdateInfoTask;
    QPointer<Core::FutureProgress> updateInfoProgress;
    UpdateInfoButton *progressUpdateInfoButton;
    QFutureWatcher<QDomDocument> *checkUpdateInfoWatcher;
};

UpdateInfoPlugin::UpdateInfoPlugin()
    : d(new UpdateInfoPluginPrivate)
{
}

UpdateInfoPlugin::~UpdateInfoPlugin()
{
    delete d;
}

void UpdateInfoPlugin::startCheckTimer(uint milliseconds)
{
    if (d->currentTimerId != 0) {
        stopCurrentCheckTimer();
    }
    d->currentTimerId = startTimer(milliseconds);
}

void UpdateInfoPlugin::stopCurrentCheckTimer()
{
    killTimer(d->currentTimerId);
}

/*! Initializes the plugin. Returns true on success.
    Plugins want to register objects with the plugin manager here.

    \a errorMessage can be used to pass an error message to the plugin system,
       if there was any.
*/
bool UpdateInfoPlugin::initialize(const QStringList & /* arguments */, QString *errorMessage)
{
    d->checkUpdateInfoWatcher = new QFutureWatcher<QDomDocument>(this);
    connect(d->checkUpdateInfoWatcher, SIGNAL(finished()), this, SLOT(reactOnUpdaterOutput()));

    QSettings *settings = Core::ICore::instance()->settings();
    d->updaterProgram = settings->value(QLatin1String("Updater/Application")).toString();
    d->updaterCheckOnlyArgument = settings->value(QLatin1String("Updater/CheckOnlyArgument")).toString();
    d->updaterRunUiArgument = settings->value(QLatin1String("Updater/RunUiArgument")).toString();

    if (d->updaterProgram.isEmpty()) {
        *errorMessage = tr("Could not determine location of maintenance tool. Please check "
                           "your installation if you did not enable this plugin manually.");
        return false;
    }

    if (!QFile::exists(d->updaterProgram)) {
        *errorMessage = tr("Could not find maintenance tool at '%1'. Check your installation.")
                .arg(d->updaterProgram);
        return false;
    }

    Core::ICore* const core = Core::ICore::instance();
    Core::ActionManager* const actionManager = core->actionManager();
    Core::ActionContainer* const helpActionContainer = actionManager->actionContainer(Core::Constants::M_HELP);
    helpActionContainer->menu()->addAction(tr("Start Updater"), this, SLOT(startUpdaterUiApplication()));

    //wait some time before we want to have the first check
    startCheckTimer(OneMinute / 10);

    return true;
}

QDomDocument UpdateInfoPlugin::checkForUpdates()
{
    if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
        qWarning() << Q_FUNC_INFO << " Was not designed to run in main/gui thread -> it is using updaterProcess.waitForFinished()";
    }

    //starting
    QProcess updaterProcess;

    updaterProcess.start(d->updaterProgram,
                         QStringList() << d->updaterCheckOnlyArgument);
    updaterProcess.waitForFinished();

    //process return value
    if (updaterProcess.exitStatus() == QProcess::CrashExit) {
        qWarning() << "Get update info application crashed.";
        //return; //maybe there is some output
    }
    QString updaterOutput = updaterProcess.readAllStandardOutput();
    QDomDocument updatesDomDocument;
    updatesDomDocument.setContent(updaterOutput);

    return updatesDomDocument;
}

void UpdateInfoPlugin::reactOnUpdaterOutput()
{
    QDomDocument updatesDomDocument = d->checkUpdateInfoWatcher->result();

    if (updatesDomDocument.isNull() ||
        !updatesDomDocument.firstChildElement().hasChildNodes())
    { // no updates are available
        startCheckTimer(60 * OneMinute);
    } else {
        //added the current almost finished task to the progressmanager
        d->updateInfoProgress = Core::ICore::instance()->progressManager()->addTask(
                d->lastCheckUpdateInfoTask, tr("Update"), QLatin1String("Update.GetInfo"), Core::ProgressManager::KeepOnFinish);

        d->updateInfoProgress->setKeepOnFinish(Core::FutureProgress::KeepOnFinish);

        d->progressUpdateInfoButton = new UpdateInfoButton();
        //the old widget is deleted inside this function
        //and the current widget becomes a child of updateInfoProgress
        d->updateInfoProgress->setWidget(d->progressUpdateInfoButton);

        //d->progressUpdateInfoButton->setText(tr("Update")); //we have this information over the progressbar
        connect(d->progressUpdateInfoButton, SIGNAL(released()),
                this, SLOT(startUpdaterUiApplication()));
    }
}

void UpdateInfoPlugin::startUpdaterUiApplication()
{
    QProcess::startDetached(d->updaterProgram, QStringList() << d->updaterRunUiArgument);
    if (!d->updateInfoProgress.isNull()) {
        d->updateInfoProgress->setKeepOnFinish(Core::FutureProgress::HideOnFinish); //this is fading out the last updateinfo
    }
    startCheckTimer(OneMinute);
}

void UpdateInfoPlugin::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == d->currentTimerId && !d->lastCheckUpdateInfoTask.isRunning())
    {
        stopCurrentCheckTimer();
        d->lastCheckUpdateInfoTask = QtConcurrent::run(this, &UpdateInfoPlugin::checkForUpdates);
        d->checkUpdateInfoWatcher->setFuture(d->lastCheckUpdateInfoTask);
    }
}

void UpdateInfoPlugin::extensionsInitialized()
{
}

} //namespace Internal
} //namespace UpdateInfo

Q_EXPORT_PLUGIN(UpdateInfo::Internal::UpdateInfoPlugin)
<commit_msg>Don't call killTimer() on dead timers.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "updateinfoplugin.h"
#include "updateinfobutton.h"

#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>

#include <qtconcurrentrun.h>

#include <QtCore/QtPlugin>
#include <QtCore/QProcess>
#include <QtCore/QTimer>
#include <QtCore/QTimerEvent>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QThread>
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtXml/QDomDocument>
#include <QtGui/QMessageBox>
#include <QtGui/QMenu>
#include <QtCore/QFutureWatcher>

namespace {
    static const quint32 OneMinute = 60000;
}

namespace UpdateInfo {
namespace Internal {

class UpdateInfoPluginPrivate
{
public:
    UpdateInfoPluginPrivate()
        : startUpdaterAction(0),
          currentTimerId(0),
          progressUpdateInfoButton(0),
          checkUpdateInfoWatcher(0)
    {}
    ~UpdateInfoPluginPrivate()
    {
    }

    QAction *startUpdaterAction;
    QString updaterProgram;
    QString updaterCheckOnlyArgument;
    QString updaterRunUiArgument;
    int currentTimerId;
    QFuture<QDomDocument> lastCheckUpdateInfoTask;
    QPointer<Core::FutureProgress> updateInfoProgress;
    UpdateInfoButton *progressUpdateInfoButton;
    QFutureWatcher<QDomDocument> *checkUpdateInfoWatcher;
};

UpdateInfoPlugin::UpdateInfoPlugin()
    : d(new UpdateInfoPluginPrivate)
{
}

UpdateInfoPlugin::~UpdateInfoPlugin()
{
    delete d;
}

void UpdateInfoPlugin::startCheckTimer(uint milliseconds)
{
    if (d->currentTimerId != 0) {
        stopCurrentCheckTimer();
    }
    d->currentTimerId = startTimer(milliseconds);
}

void UpdateInfoPlugin::stopCurrentCheckTimer()
{
    killTimer(d->currentTimerId);
    d->currentTimerId = 0;
}

/*! Initializes the plugin. Returns true on success.
    Plugins want to register objects with the plugin manager here.

    \a errorMessage can be used to pass an error message to the plugin system,
       if there was any.
*/
bool UpdateInfoPlugin::initialize(const QStringList & /* arguments */, QString *errorMessage)
{
    d->checkUpdateInfoWatcher = new QFutureWatcher<QDomDocument>(this);
    connect(d->checkUpdateInfoWatcher, SIGNAL(finished()), this, SLOT(reactOnUpdaterOutput()));

    QSettings *settings = Core::ICore::instance()->settings();
    d->updaterProgram = settings->value(QLatin1String("Updater/Application")).toString();
    d->updaterCheckOnlyArgument = settings->value(QLatin1String("Updater/CheckOnlyArgument")).toString();
    d->updaterRunUiArgument = settings->value(QLatin1String("Updater/RunUiArgument")).toString();

    if (d->updaterProgram.isEmpty()) {
        *errorMessage = tr("Could not determine location of maintenance tool. Please check "
                           "your installation if you did not enable this plugin manually.");
        return false;
    }

    if (!QFile::exists(d->updaterProgram)) {
        *errorMessage = tr("Could not find maintenance tool at '%1'. Check your installation.")
                .arg(d->updaterProgram);
        return false;
    }

    Core::ICore* const core = Core::ICore::instance();
    Core::ActionManager* const actionManager = core->actionManager();
    Core::ActionContainer* const helpActionContainer = actionManager->actionContainer(Core::Constants::M_HELP);
    helpActionContainer->menu()->addAction(tr("Start Updater"), this, SLOT(startUpdaterUiApplication()));

    //wait some time before we want to have the first check
    startCheckTimer(OneMinute / 10);

    return true;
}

QDomDocument UpdateInfoPlugin::checkForUpdates()
{
    if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
        qWarning() << Q_FUNC_INFO << " Was not designed to run in main/gui thread -> it is using updaterProcess.waitForFinished()";
    }

    //starting
    QProcess updaterProcess;

    updaterProcess.start(d->updaterProgram,
                         QStringList() << d->updaterCheckOnlyArgument);
    updaterProcess.waitForFinished();

    //process return value
    if (updaterProcess.exitStatus() == QProcess::CrashExit) {
        qWarning() << "Get update info application crashed.";
        //return; //maybe there is some output
    }
    QString updaterOutput = updaterProcess.readAllStandardOutput();
    QDomDocument updatesDomDocument;
    updatesDomDocument.setContent(updaterOutput);

    return updatesDomDocument;
}

void UpdateInfoPlugin::reactOnUpdaterOutput()
{
    QDomDocument updatesDomDocument = d->checkUpdateInfoWatcher->result();

    if (updatesDomDocument.isNull() ||
        !updatesDomDocument.firstChildElement().hasChildNodes())
    { // no updates are available
        startCheckTimer(60 * OneMinute);
    } else {
        //added the current almost finished task to the progressmanager
        d->updateInfoProgress = Core::ICore::instance()->progressManager()->addTask(
                d->lastCheckUpdateInfoTask, tr("Update"), QLatin1String("Update.GetInfo"), Core::ProgressManager::KeepOnFinish);

        d->updateInfoProgress->setKeepOnFinish(Core::FutureProgress::KeepOnFinish);

        d->progressUpdateInfoButton = new UpdateInfoButton();
        //the old widget is deleted inside this function
        //and the current widget becomes a child of updateInfoProgress
        d->updateInfoProgress->setWidget(d->progressUpdateInfoButton);

        //d->progressUpdateInfoButton->setText(tr("Update")); //we have this information over the progressbar
        connect(d->progressUpdateInfoButton, SIGNAL(released()),
                this, SLOT(startUpdaterUiApplication()));
    }
}

void UpdateInfoPlugin::startUpdaterUiApplication()
{
    QProcess::startDetached(d->updaterProgram, QStringList() << d->updaterRunUiArgument);
    if (!d->updateInfoProgress.isNull()) {
        d->updateInfoProgress->setKeepOnFinish(Core::FutureProgress::HideOnFinish); //this is fading out the last updateinfo
    }
    startCheckTimer(OneMinute);
}

void UpdateInfoPlugin::timerEvent(QTimerEvent *event)
{
    if (event->timerId() == d->currentTimerId && !d->lastCheckUpdateInfoTask.isRunning())
    {
        stopCurrentCheckTimer();
        d->lastCheckUpdateInfoTask = QtConcurrent::run(this, &UpdateInfoPlugin::checkForUpdates);
        d->checkUpdateInfoWatcher->setFuture(d->lastCheckUpdateInfoTask);
    }
}

void UpdateInfoPlugin::extensionsInitialized()
{
}

} //namespace Internal
} //namespace UpdateInfo

Q_EXPORT_PLUGIN(UpdateInfo::Internal::UpdateInfoPlugin)
<|endoftext|>


<commit_before>// rbOOmit: An implementation of the Certified Reduced Basis method.
// Copyright (C) 2009, 2010 David J. Knezevic

// This file is part of rbOOmit.

// rbOOmit 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.

// rbOOmit 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.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "libmesh/derived_rb_construction.h"
#include "libmesh/derived_rb_evaluation.h"

#include "libmesh/libmesh_logging.h"
#include "libmesh/equation_systems.h"

namespace libMesh
{

template <class Base>
DerivedRBConstruction<Base>::DerivedRBConstruction (EquationSystems& es,
		                                    const std::string& name,
		                                    const unsigned int number)
  : Base(es, name, number)
{
  // We do not want to compute the output dual norms in
  // a derived system, we just copy them over from the
  // primary system
  Base::output_dual_innerprods_computed = true;
}

template <class Base>
std::string DerivedRBConstruction<Base>::system_type () const
{
  return "DerivedRBConstruction";
}

template <class Base>
Real DerivedRBConstruction<Base>::train_reduced_basis (const std::string& directory_name,
                                                       const bool resize_rb_eval_data)
{
  Real training_greedy_error = Base::train_reduced_basis(directory_name,
                                                         resize_rb_eval_data);

  generate_residual_terms_wrt_truth();

  return training_greedy_error;
}

template<class Base>
void DerivedRBConstruction<Base>::set_uber_current_parameters()
{
  EquationSystems& es = this->get_equation_systems();
  RBConstruction& uber_system = es.get_system<RBConstruction>(uber_system_name);

  uber_system.set_parameters( Base::get_parameters() );
}

template <class Base>
void DerivedRBConstruction<Base>::load_basis_function(unsigned int i)
{
  START_LOG("load_basis_function()", "DerivedRBConstruction");

  EquationSystems& es = Base::get_equation_systems();
  RBConstruction& uber_system = es.get_system<RBConstruction>(uber_system_name);

  DenseVector<Number> bf = get_derived_basis_function(i);

  for(unsigned int j=0; j<uber_system.get_rb_evaluation().get_n_basis_functions(); j++)
  {
    Base::solution->add(bf(j), uber_system.get_rb_evaluation().get_basis_function(j));
  }

  STOP_LOG("load_basis_function()", "DerivedRBConstruction");
}

// explicit instantiations
template class DerivedRBConstruction<RBConstruction>;

}
<commit_msg>Changes in derived_rb_construction.C for -Wshadow.<commit_after>// rbOOmit: An implementation of the Certified Reduced Basis method.
// Copyright (C) 2009, 2010 David J. Knezevic

// This file is part of rbOOmit.

// rbOOmit 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.

// rbOOmit 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.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include "libmesh/derived_rb_construction.h"
#include "libmesh/derived_rb_evaluation.h"

#include "libmesh/libmesh_logging.h"
#include "libmesh/equation_systems.h"

namespace libMesh
{

template <class Base>
DerivedRBConstruction<Base>::DerivedRBConstruction (EquationSystems& es,
		                                    const std::string& name_in,
		                                    const unsigned int number_in)
  : Base(es, name_in, number_in)
{
  // We do not want to compute the output dual norms in
  // a derived system, we just copy them over from the
  // primary system
  Base::output_dual_innerprods_computed = true;
}

template <class Base>
std::string DerivedRBConstruction<Base>::system_type () const
{
  return "DerivedRBConstruction";
}

template <class Base>
Real DerivedRBConstruction<Base>::train_reduced_basis (const std::string& directory_name,
                                                       const bool resize_rb_eval_data)
{
  Real training_greedy_error = Base::train_reduced_basis(directory_name,
                                                         resize_rb_eval_data);

  generate_residual_terms_wrt_truth();

  return training_greedy_error;
}

template<class Base>
void DerivedRBConstruction<Base>::set_uber_current_parameters()
{
  EquationSystems& es = this->get_equation_systems();
  RBConstruction& uber_system = es.get_system<RBConstruction>(uber_system_name);

  uber_system.set_parameters( Base::get_parameters() );
}

template <class Base>
void DerivedRBConstruction<Base>::load_basis_function(unsigned int i)
{
  START_LOG("load_basis_function()", "DerivedRBConstruction");

  EquationSystems& es = Base::get_equation_systems();
  RBConstruction& uber_system = es.get_system<RBConstruction>(uber_system_name);

  DenseVector<Number> bf = get_derived_basis_function(i);

  for(unsigned int j=0; j<uber_system.get_rb_evaluation().get_n_basis_functions(); j++)
  {
    Base::solution->add(bf(j), uber_system.get_rb_evaluation().get_basis_function(j));
  }

  STOP_LOG("load_basis_function()", "DerivedRBConstruction");
}

// explicit instantiations
template class DerivedRBConstruction<RBConstruction>;

}
<|endoftext|>


<commit_before>#include <algorithm>
#include <cmath>
#include <functional>
#include <iterator>

#include <QCoreApplication>
#include <QFile>
#include <QHash>
#include <QSet>
#include <QSharedPointer>
#include <QString>
#include <QStringList>
#include <QTextStream>
#include <QVector>

/*
 * WARNING: this is just a proof of concept, containing a lot of duplicate
 * code and assumptions. Rewrite for serious use :p.
 */

typedef QSet<int> IndexSet;
typedef QHash<QString, QSharedPointer<IndexSet> > PositionHash;

inline QSharedPointer<IndexSet> defaultSet()
{
  return QSharedPointer<IndexSet>(new IndexSet);
}

struct Positions {
  PositionHash wordPositions;
  PositionHash tagPositions;
};

struct Unigram {
  Unigram () {}
  Unigram(QString const &newType, QString const &newUnigram) :
      type(newType), unigram(newUnigram) {}
  QString type;
  QString unigram;
};

inline bool operator==(Unigram const &u1, Unigram const &u2)
{
  return u1.type == u2.type && u1.unigram == u2.unigram;
}

inline uint qHash(Unigram const &unigram)
{
  uint h1 = qHash(unigram.type);
  uint h2 = qHash(unigram.unigram);
  return ((h1 << 16) | (h1 >> 16)) ^ h2;
}

template <typename T>
QSharedPointer<QSet<T> > intersect_set(QSharedPointer<QSet<T> > a,
    QSharedPointer<QSet<T> > b) {
  QSharedPointer<QSet<T> > small;
  QSharedPointer<QSet<T> > big;

  if (a->size() > b->size()) {
    big = a;
    small = b;
  } else {
    big = b;
    small = a;
  }

  QSharedPointer<QSet<T> > inter(new QSet<T>);
  for (typename QSet<T>::const_iterator iter = small->begin();
      iter != small->end();
      ++iter)
    if (big->contains(*iter))
      inter->insert(*iter);

  return inter;
}

typedef QPair<Unigram, Unigram> Bigram;

typedef QHash<Bigram, QSharedPointer<IndexSet> > BigramCache;

double expansionFactor(int badFreq) {
  return 1.0 + exp(-0.5 * static_cast<double>(badFreq));
}

bool readCorpus(QTextStream &corpusStream, Positions *positions) {
  int position = 0;
  QString line;

  while (true) {
    line = corpusStream.readLine();
    if (line.isNull())
      break;

    line = line.trimmed();

    QStringList lineParts = line.split(" ", QString::SkipEmptyParts);

    for (QStringList::const_iterator iter = lineParts.begin();
        iter != lineParts.end(); ++iter) {
      QString wordTag = *iter;

      int sepIndex = wordTag.lastIndexOf("/");
      QString word(wordTag.left(sepIndex));
      QString tag(wordTag.mid(sepIndex + 1));

      if (!positions->wordPositions.contains(word))
        positions->wordPositions[word] = defaultSet();
      positions->wordPositions[word]->insert(position);
      if (!positions->tagPositions.contains(tag))
        positions->tagPositions[tag] = defaultSet();
      positions->tagPositions[tag]->insert(position);

      ++position;
    }
  }

  return true;
}

double sequenceRatio(BigramCache *goodCache, BigramCache *badCache,
    Positions const &goodPositions, Positions const &badPositions,
    QVector<Unigram> seq)
{
  bool fromCache = false;

  QSharedPointer<IndexSet> goodIdx(new IndexSet);
  QSharedPointer<IndexSet> badIdx(new IndexSet);

  if (seq.size() > 1) {
      BigramCache::iterator badIter;
      BigramCache::iterator goodIter;
      Bigram bigram(seq[0], seq[1]);
      if ((badIter = badCache->find(bigram)) !=
          badCache->end() &&
          (goodIter = goodCache->find(bigram)) !=
           goodCache->end()) {
        badIdx = *badIter;
        goodIdx = *goodIter;
        seq = seq.mid(2);
        fromCache = true;
      }
  }

  for (int i = 0; i < seq.size(); ++i) {

    PositionHash const *goodHash = 0;
    PositionHash const *badHash = 0;

    if (seq[i].type == "w") {
      goodHash = &goodPositions.wordPositions;
      badHash = &badPositions.wordPositions;
    } else {
      goodHash = &goodPositions.tagPositions;
      badHash = &badPositions.tagPositions;
    }

    if (i == 0 && !fromCache) {
      goodIdx = goodHash->value(seq[i].unigram, defaultSet());
      badIdx = badHash->value(seq[i].unigram, defaultSet());
    } else {
      QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
      for (IndexSet::const_iterator iter = goodIdx->begin();
            iter != goodIdx->end(); ++iter)
        newGoodIdx->insert(*iter + 1);

      QSharedPointer<IndexSet> newBadIdx(new IndexSet);
      for (IndexSet::const_iterator iter = badIdx->begin();
            iter != badIdx->end(); ++iter)
        newBadIdx->insert(*iter + 1);

      goodIdx = intersect_set(newGoodIdx, goodHash->value(seq[i].unigram,
        defaultSet()));

      badIdx = intersect_set(newBadIdx, badHash->value(seq[i].unigram,
        defaultSet()));

      if (i == 1 && !fromCache && (goodIdx->size() > 5 || badIdx->size() > 5)) {
        Bigram bigram(seq[0], seq[1]);
        (*goodCache)[bigram] = goodIdx;
        (*badCache)[bigram] = badIdx;
      }
    }
  }

  if (badIdx->size() == 0)
    return 0.0;

  return static_cast<double>(badIdx->size())
    / static_cast<double>(goodIdx->size() + badIdx->size());
}

void expandCorpus(QTextStream *corpusStream, Positions const &goodPositions,
    Positions const &badPositions, QTextStream *sentStream,
    QTextStream *formStream)
{
  BigramCache goodBigramCache;
  BigramCache badBigramCache;

  int count = 0;

  QString line;
  while (true) {
    line = corpusStream->readLine();
    if (line.isNull())
      break;

    QStringList lineParts = line.split(" ", QString::SkipEmptyParts);

    QVector<Unigram> tags;
    QVector<Unigram> words;
    for (QStringList::const_iterator iter = lineParts.begin();
        iter != lineParts.end(); ++iter) {
      QString wordTag = *iter;

      int sepIndex = wordTag.lastIndexOf("/");
      QString word(wordTag.left(sepIndex));
      QString tag(wordTag.mid(sepIndex + 1));

      words.push_back(Unigram("w", word));
      tags.push_back(Unigram("t", tag));
    }

    for (int i = 0; i < words.size(); ++i) {
      // First word suspicion
      QSharedPointer<IndexSet> goodIdx =
        goodPositions.wordPositions.value(words[i].unigram, defaultSet());
      QSharedPointer<IndexSet> badIdx =
        badPositions.wordPositions.value(words[i].unigram, defaultSet());
      double susp = static_cast<double>(badIdx->size()) /
        static_cast<double>(badIdx->size() + goodIdx->size());

      QVector<Unigram> ngram;
      ngram.push_back(words[i]);

      for (int j = i + 1; j < lineParts.size(); ++j) {
        QSharedPointer<IndexSet> tagGoodIdx;
        QSharedPointer<IndexSet> tagBadIdx;

        bool fromCache = false;
        if (ngram.size() == 1) {
            BigramCache::const_iterator goodIter;
            BigramCache::const_iterator badIter;
            Bigram bigram(ngram[0], tags[j]);
            if ((goodIter = goodBigramCache.find(bigram)) !=
                  goodBigramCache.end() &&
                (badIter = badBigramCache.find(bigram)) !=
                  badBigramCache.end()) {
              tagGoodIdx = *goodIter;
              tagBadIdx = *badIter;
              fromCache = true;

              if (ngram.size() == 1 && ngram[0].unigram == "de" &&
                  tags[j].unigram == "N")
              {
                QTextStream err(stderr);
                err << "cached --> ok: " << tagGoodIdx->size() << " bad: " <<
                  tagBadIdx->size() << "\n";
              }
            }
        }

        if (!fromCache) {
          QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
          for (IndexSet::const_iterator iter = goodIdx->begin();
              iter != goodIdx->end(); ++iter)
            newGoodIdx->insert(*iter + 1);

          QSharedPointer<IndexSet> newBadIdx(new IndexSet);
          for (IndexSet::const_iterator iter = badIdx->begin();
              iter != badIdx->end(); ++iter)
            newBadIdx->insert(*iter + 1);

          tagGoodIdx = intersect_set(newGoodIdx,
              goodPositions.tagPositions.value(tags[j].unigram, defaultSet()));

          tagBadIdx = intersect_set(newBadIdx,
            badPositions.tagPositions.value(tags[j].unigram, defaultSet()));

          if (j - i == 1 && (tagGoodIdx->size() > 5 || tagBadIdx->size() > 5)) {
            Bigram bigram(ngram[0], tags[j]);
            goodBigramCache[bigram] = tagGoodIdx;
            badBigramCache[bigram] = tagBadIdx;
          }

          if (j == i + 1 && tags[j].unigram == "N") {
            QTextStream err(stderr);
            //err << "'N' --> ok: " <<
              //goodPositions.tagPositions.value(tags[j].unigram, defaultSet())->size()  <<
              //" bad: " << badPositions.tagPositions.value(tags[j].unigram, defaultSet())->size()  << "\n";
            if (ngram[0].unigram == "de")
              err << "intersect --> ok: " << tagGoodIdx->size() <<
                " bad: " << tagBadIdx->size() << "\n";
          }
        }

        double newTagSusp = 0.0;
        if (tagBadIdx->size() > 0)
          newTagSusp = static_cast<double>(tagBadIdx->size()) /
            static_cast<double>(tagBadIdx->size() + tagGoodIdx->size());

        double ef = expansionFactor(tagBadIdx->size());

        QVector<Unigram> secondGram = ngram.mid(1);
        secondGram.push_back(tags[j]);
        double susp2 = sequenceRatio(&goodBigramCache, &badBigramCache,
            goodPositions, badPositions, secondGram);

        if (newTagSusp > susp * ef && newTagSusp > susp2 * ef) {
          ngram.push_back(tags[j]);
          goodIdx = tagGoodIdx;
          badIdx = tagBadIdx;
          susp = newTagSusp;
          continue;
        }

        ////////////////////
        // Word expansion //
        ////////////////////

        QSharedPointer<IndexSet> wordGoodIdx;
        QSharedPointer<IndexSet> wordBadIdx;

        fromCache = false;
        if (ngram.size() == 1) {
            BigramCache::const_iterator goodIter;
            BigramCache::const_iterator badIter;
            Bigram bigram(ngram[0], words[j]);
            if ((goodIter = goodBigramCache.find(bigram)) !=
                  goodBigramCache.end() &&
                (badIter = badBigramCache.find(bigram)) !=
                badBigramCache.end()) {
              wordBadIdx = *badIter;
              wordGoodIdx = *goodIter;
              fromCache = true;
            }
        }

        if (!fromCache) {
          QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
          for (IndexSet::const_iterator iter = goodIdx->begin();
              iter != goodIdx->end(); ++iter)
            newGoodIdx->insert(*iter + 1);

          QSharedPointer<IndexSet> newBadIdx(new IndexSet);
          for (IndexSet::const_iterator iter = badIdx->begin();
              iter != badIdx->end(); ++iter)
            newBadIdx->insert(*iter + 1);

          wordGoodIdx = intersect_set(newGoodIdx,
            goodPositions.wordPositions.value(words[j].unigram, defaultSet()));

          wordBadIdx = intersect_set(newBadIdx,
            badPositions.wordPositions.value(words[j].unigram, defaultSet()));

          if (j - i == 1 && (wordGoodIdx->size() > 5 || wordBadIdx->size() > 5)) {
            Bigram bigram(ngram[0], words[j]);
            goodBigramCache[bigram] = wordGoodIdx;
            badBigramCache[bigram] = wordBadIdx;
          }
        }

        double newWordSusp = 0.0;
        if (wordBadIdx->size() > 0)
          newWordSusp = static_cast<double>(wordBadIdx->size()) /
            (wordBadIdx->size() + wordGoodIdx->size());

        ef = expansionFactor(wordBadIdx->size());

        secondGram = ngram.mid(1);
        secondGram.push_back(words[j]);
        susp2 = sequenceRatio(&goodBigramCache, &badBigramCache,
            goodPositions, badPositions, secondGram);

        if (newWordSusp > susp * ef && newWordSusp > susp2 * ef) {
          ngram.push_back(words[j]);
          goodIdx = wordGoodIdx;
          badIdx = wordBadIdx;
          susp = newWordSusp;
          continue;
        }

        break;
      }

      QStringList ngramFlat;
      for (QVector<Unigram>::const_iterator iter = ngram.begin();
          iter != ngram.end(); ++iter)
        ngramFlat.push_back(iter->unigram);
      QString ngramStr(ngramFlat.join("_"));

      //if (ngramFlat.size() == 2 && ngramFlat[0] == "de" && ngramFlat[1] == "N") {
      //  QTextStream err(stderr);
      //  err << "ok: " << goodIdx->size() << " bad: " << badIdx->size() << "\n";
      //}

      *sentStream << ngramStr << " ";
      *formStream << ngramStr << " " << susp << " " << goodIdx->size() <<
        " " << badIdx->size() << "\n";
    }

    count += 1;
    if (count % 100 == 0) {
      QTextStream out(stderr);
      out << ".";
     }

     *sentStream << "\n";
  }
}

int main(int argc, char *argv[]) {
  QCoreApplication app(argc, argv);

  if (argc != 5)
    return 1;

  QFile goodCorpus(argv[1]);
  goodCorpus.open(QFile::ReadOnly);
  QTextStream goodStream(&goodCorpus);

  QFile badCorpus(argv[2]);
  badCorpus.open(QFile::ReadOnly);
  QTextStream badStream(&badCorpus);

  QFile sents(argv[3]);
  sents.open(QFile::WriteOnly);
  QTextStream sentStream(&sents);

  QFile forms(argv[4]);
  forms.open(QFile::WriteOnly);
  QTextStream formStream(&forms);
  formStream.setRealNumberPrecision(6);
  formStream.setRealNumberNotation(QTextStream::FixedNotation);

  QTextStream err(stderr);
  err << "Constructing indextables..." << endl;
  Positions goodPositions;
  readCorpus(goodStream, &goodPositions);

  Positions badPositions;
  readCorpus(badStream, &badPositions);

  err << "Expanding..." << endl;
  badStream.seek(0);
  expandCorpus(&badStream, goodPositions, badPositions, &sentStream,
    &formStream);
}
<commit_msg>Remove debugging output.<commit_after>#include <algorithm>
#include <cmath>
#include <functional>
#include <iterator>

#include <QCoreApplication>
#include <QFile>
#include <QHash>
#include <QSet>
#include <QSharedPointer>
#include <QString>
#include <QStringList>
#include <QTextStream>
#include <QVector>

/*
 * WARNING: this is just a proof of concept, containing a lot of duplicate
 * code and assumptions. Rewrite for serious use :p.
 */

typedef QSet<int> IndexSet;
typedef QHash<QString, QSharedPointer<IndexSet> > PositionHash;

inline QSharedPointer<IndexSet> defaultSet()
{
  return QSharedPointer<IndexSet>(new IndexSet);
}

struct Positions {
  PositionHash wordPositions;
  PositionHash tagPositions;
};

struct Unigram {
  Unigram () {}
  Unigram(QString const &newType, QString const &newUnigram) :
      type(newType), unigram(newUnigram) {}
  QString type;
  QString unigram;
};

inline bool operator==(Unigram const &u1, Unigram const &u2)
{
  return u1.type == u2.type && u1.unigram == u2.unigram;
}

inline uint qHash(Unigram const &unigram)
{
  uint h1 = qHash(unigram.type);
  uint h2 = qHash(unigram.unigram);
  return ((h1 << 16) | (h1 >> 16)) ^ h2;
}

template <typename T>
QSharedPointer<QSet<T> > intersect_set(QSharedPointer<QSet<T> > a,
    QSharedPointer<QSet<T> > b) {
  QSharedPointer<QSet<T> > small;
  QSharedPointer<QSet<T> > big;

  if (a->size() > b->size()) {
    big = a;
    small = b;
  } else {
    big = b;
    small = a;
  }

  QSharedPointer<QSet<T> > inter(new QSet<T>);
  for (typename QSet<T>::const_iterator iter = small->begin();
      iter != small->end();
      ++iter)
    if (big->contains(*iter))
      inter->insert(*iter);

  return inter;
}

typedef QPair<Unigram, Unigram> Bigram;

typedef QHash<Bigram, QSharedPointer<IndexSet> > BigramCache;

double expansionFactor(int badFreq) {
  return 1.0 + exp(-0.5 * static_cast<double>(badFreq));
}

bool readCorpus(QTextStream &corpusStream, Positions *positions) {
  int position = 0;
  QString line;

  while (true) {
    line = corpusStream.readLine();
    if (line.isNull())
      break;

    line = line.trimmed();

    QStringList lineParts = line.split(" ", QString::SkipEmptyParts);

    for (QStringList::const_iterator iter = lineParts.begin();
        iter != lineParts.end(); ++iter) {
      QString wordTag = *iter;

      int sepIndex = wordTag.lastIndexOf("/");
      QString word(wordTag.left(sepIndex));
      QString tag(wordTag.mid(sepIndex + 1));

      if (!positions->wordPositions.contains(word))
        positions->wordPositions[word] = defaultSet();
      positions->wordPositions[word]->insert(position);
      if (!positions->tagPositions.contains(tag))
        positions->tagPositions[tag] = defaultSet();
      positions->tagPositions[tag]->insert(position);

      ++position;
    }
  }

  return true;
}

double sequenceRatio(BigramCache *goodCache, BigramCache *badCache,
    Positions const &goodPositions, Positions const &badPositions,
    QVector<Unigram> seq)
{
  bool fromCache = false;

  QSharedPointer<IndexSet> goodIdx(new IndexSet);
  QSharedPointer<IndexSet> badIdx(new IndexSet);

  if (seq.size() > 1) {
      BigramCache::iterator badIter;
      BigramCache::iterator goodIter;
      Bigram bigram(seq[0], seq[1]);
      if ((badIter = badCache->find(bigram)) !=
          badCache->end() &&
          (goodIter = goodCache->find(bigram)) !=
           goodCache->end()) {
        badIdx = *badIter;
        goodIdx = *goodIter;
        seq = seq.mid(2);
        fromCache = true;
      }
  }

  for (int i = 0; i < seq.size(); ++i) {

    PositionHash const *goodHash = 0;
    PositionHash const *badHash = 0;

    if (seq[i].type == "w") {
      goodHash = &goodPositions.wordPositions;
      badHash = &badPositions.wordPositions;
    } else {
      goodHash = &goodPositions.tagPositions;
      badHash = &badPositions.tagPositions;
    }

    if (i == 0 && !fromCache) {
      goodIdx = goodHash->value(seq[i].unigram, defaultSet());
      badIdx = badHash->value(seq[i].unigram, defaultSet());
    } else {
      QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
      for (IndexSet::const_iterator iter = goodIdx->begin();
            iter != goodIdx->end(); ++iter)
        newGoodIdx->insert(*iter + 1);

      QSharedPointer<IndexSet> newBadIdx(new IndexSet);
      for (IndexSet::const_iterator iter = badIdx->begin();
            iter != badIdx->end(); ++iter)
        newBadIdx->insert(*iter + 1);

      goodIdx = intersect_set(newGoodIdx, goodHash->value(seq[i].unigram,
        defaultSet()));

      badIdx = intersect_set(newBadIdx, badHash->value(seq[i].unigram,
        defaultSet()));

      if (i == 1 && !fromCache && (goodIdx->size() > 5 || badIdx->size() > 5)) {
        Bigram bigram(seq[0], seq[1]);
        (*goodCache)[bigram] = goodIdx;
        (*badCache)[bigram] = badIdx;
      }
    }
  }

  if (badIdx->size() == 0)
    return 0.0;

  return static_cast<double>(badIdx->size())
    / static_cast<double>(goodIdx->size() + badIdx->size());
}

void expandCorpus(QTextStream *corpusStream, Positions const &goodPositions,
    Positions const &badPositions, QTextStream *sentStream,
    QTextStream *formStream)
{
  BigramCache goodBigramCache;
  BigramCache badBigramCache;

  int count = 0;

  QString line;
  while (true) {
    line = corpusStream->readLine();
    if (line.isNull())
      break;

    QStringList lineParts = line.split(" ", QString::SkipEmptyParts);

    QVector<Unigram> tags;
    QVector<Unigram> words;
    for (QStringList::const_iterator iter = lineParts.begin();
        iter != lineParts.end(); ++iter) {
      QString wordTag = *iter;

      int sepIndex = wordTag.lastIndexOf("/");
      QString word(wordTag.left(sepIndex));
      QString tag(wordTag.mid(sepIndex + 1));

      words.push_back(Unigram("w", word));
      tags.push_back(Unigram("t", tag));
    }

    for (int i = 0; i < words.size(); ++i) {
      // First word suspicion
      QSharedPointer<IndexSet> goodIdx =
        goodPositions.wordPositions.value(words[i].unigram, defaultSet());
      QSharedPointer<IndexSet> badIdx =
        badPositions.wordPositions.value(words[i].unigram, defaultSet());
      double susp = static_cast<double>(badIdx->size()) /
        static_cast<double>(badIdx->size() + goodIdx->size());

      QVector<Unigram> ngram;
      ngram.push_back(words[i]);

      for (int j = i + 1; j < lineParts.size(); ++j) {
        QSharedPointer<IndexSet> tagGoodIdx;
        QSharedPointer<IndexSet> tagBadIdx;

        bool fromCache = false;
        if (ngram.size() == 1) {
            BigramCache::const_iterator goodIter;
            BigramCache::const_iterator badIter;
            Bigram bigram(ngram[0], tags[j]);
            if ((goodIter = goodBigramCache.find(bigram)) !=
                  goodBigramCache.end() &&
                (badIter = badBigramCache.find(bigram)) !=
                  badBigramCache.end()) {
              tagGoodIdx = *goodIter;
              tagBadIdx = *badIter;
              fromCache = true;
            }
        }

        if (!fromCache) {
          QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
          for (IndexSet::const_iterator iter = goodIdx->begin();
              iter != goodIdx->end(); ++iter)
            newGoodIdx->insert(*iter + 1);

          QSharedPointer<IndexSet> newBadIdx(new IndexSet);
          for (IndexSet::const_iterator iter = badIdx->begin();
              iter != badIdx->end(); ++iter)
            newBadIdx->insert(*iter + 1);

          tagGoodIdx = intersect_set(newGoodIdx,
              goodPositions.tagPositions.value(tags[j].unigram, defaultSet()));

          tagBadIdx = intersect_set(newBadIdx,
            badPositions.tagPositions.value(tags[j].unigram, defaultSet()));

          if (j - i == 1 && (tagGoodIdx->size() > 5 || tagBadIdx->size() > 5)) {
            Bigram bigram(ngram[0], tags[j]);
            goodBigramCache[bigram] = tagGoodIdx;
            badBigramCache[bigram] = tagBadIdx;
          }
        }

        double newTagSusp = 0.0;
        if (tagBadIdx->size() > 0)
          newTagSusp = static_cast<double>(tagBadIdx->size()) /
            static_cast<double>(tagBadIdx->size() + tagGoodIdx->size());

        double ef = expansionFactor(tagBadIdx->size());

        QVector<Unigram> secondGram = ngram.mid(1);
        secondGram.push_back(tags[j]);
        double susp2 = sequenceRatio(&goodBigramCache, &badBigramCache,
            goodPositions, badPositions, secondGram);

        if (newTagSusp > susp * ef && newTagSusp > susp2 * ef) {
          ngram.push_back(tags[j]);
          goodIdx = tagGoodIdx;
          badIdx = tagBadIdx;
          susp = newTagSusp;
          continue;
        }

        ////////////////////
        // Word expansion //
        ////////////////////

        QSharedPointer<IndexSet> wordGoodIdx;
        QSharedPointer<IndexSet> wordBadIdx;

        fromCache = false;
        if (ngram.size() == 1) {
            BigramCache::const_iterator goodIter;
            BigramCache::const_iterator badIter;
            Bigram bigram(ngram[0], words[j]);
            if ((goodIter = goodBigramCache.find(bigram)) !=
                  goodBigramCache.end() &&
                (badIter = badBigramCache.find(bigram)) !=
                badBigramCache.end()) {
              wordBadIdx = *badIter;
              wordGoodIdx = *goodIter;
              fromCache = true;
            }
        }

        if (!fromCache) {
          QSharedPointer<IndexSet> newGoodIdx(new IndexSet);
          for (IndexSet::const_iterator iter = goodIdx->begin();
              iter != goodIdx->end(); ++iter)
            newGoodIdx->insert(*iter + 1);

          QSharedPointer<IndexSet> newBadIdx(new IndexSet);
          for (IndexSet::const_iterator iter = badIdx->begin();
              iter != badIdx->end(); ++iter)
            newBadIdx->insert(*iter + 1);

          wordGoodIdx = intersect_set(newGoodIdx,
            goodPositions.wordPositions.value(words[j].unigram, defaultSet()));

          wordBadIdx = intersect_set(newBadIdx,
            badPositions.wordPositions.value(words[j].unigram, defaultSet()));

          if (j - i == 1 && (wordGoodIdx->size() > 5 || wordBadIdx->size() > 5)) {
            Bigram bigram(ngram[0], words[j]);
            goodBigramCache[bigram] = wordGoodIdx;
            badBigramCache[bigram] = wordBadIdx;
          }
        }

        double newWordSusp = 0.0;
        if (wordBadIdx->size() > 0)
          newWordSusp = static_cast<double>(wordBadIdx->size()) /
            (wordBadIdx->size() + wordGoodIdx->size());

        ef = expansionFactor(wordBadIdx->size());

        secondGram = ngram.mid(1);
        secondGram.push_back(words[j]);
        susp2 = sequenceRatio(&goodBigramCache, &badBigramCache,
            goodPositions, badPositions, secondGram);

        if (newWordSusp > susp * ef && newWordSusp > susp2 * ef) {
          ngram.push_back(words[j]);
          goodIdx = wordGoodIdx;
          badIdx = wordBadIdx;
          susp = newWordSusp;
          continue;
        }

        break;
      }

      QStringList ngramFlat;
      for (QVector<Unigram>::const_iterator iter = ngram.begin();
          iter != ngram.end(); ++iter)
        ngramFlat.push_back(iter->unigram);
      QString ngramStr(ngramFlat.join("_"));

      *sentStream << ngramStr << " ";
      *formStream << ngramStr << " " << susp << " " << goodIdx->size() <<
        " " << badIdx->size() << "\n";
    }

    count += 1;
    if (count % 100 == 0) {
      QTextStream out(stderr);
      out << ".";
     }

     *sentStream << "\n";
  }
}

int main(int argc, char *argv[]) {
  QCoreApplication app(argc, argv);

  if (argc != 5)
    return 1;

  QFile goodCorpus(argv[1]);
  goodCorpus.open(QFile::ReadOnly);
  QTextStream goodStream(&goodCorpus);

  QFile badCorpus(argv[2]);
  badCorpus.open(QFile::ReadOnly);
  QTextStream badStream(&badCorpus);

  QFile sents(argv[3]);
  sents.open(QFile::WriteOnly);
  QTextStream sentStream(&sents);

  QFile forms(argv[4]);
  forms.open(QFile::WriteOnly);
  QTextStream formStream(&forms);
  formStream.setRealNumberPrecision(6);
  formStream.setRealNumberNotation(QTextStream::FixedNotation);

  QTextStream err(stderr);
  err << "Constructing indextables..." << endl;
  Positions goodPositions;
  readCorpus(goodStream, &goodPositions);

  Positions badPositions;
  readCorpus(badStream, &badPositions);

  err << "Expanding..." << endl;
  badStream.seek(0);
  expandCorpus(&badStream, goodPositions, badPositions, &sentStream,
    &formStream);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite 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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qtest.h>
#include <QtScript>

//TESTED_FILES=

class tst_QScriptEngine : public QObject
{
    Q_OBJECT

public:
    tst_QScriptEngine();
    virtual ~tst_QScriptEngine();

public slots:
    void init();
    void cleanup();

private slots:
    void constructor();
    void evaluate_data();
    void evaluate();
    void evaluateProgram_data();
    void evaluateProgram();
    void connectAndDisconnect();
    void newObject();
    void newQObject();
    void newFunction();
    void newVariant();
    void collectGarbage();
    void pushAndPopContext();
    void toStringHandle();
    void castValueToQreal();
    void nativeCall();
};

tst_QScriptEngine::tst_QScriptEngine()
{
}

tst_QScriptEngine::~tst_QScriptEngine()
{
}

void tst_QScriptEngine::init()
{
}

void tst_QScriptEngine::cleanup()
{
}

void tst_QScriptEngine::constructor()
{
    QBENCHMARK {
        QScriptEngine engine;
        (void)engine.parent();
    }
}

void tst_QScriptEngine::evaluate_data()
{
    QTest::addColumn<QString>("code");
    QTest::newRow("empty script") << QString::fromLatin1("");
    QTest::newRow("number literal") << QString::fromLatin1("123");
    QTest::newRow("string literal") << QString::fromLatin1("'ciao'");
    QTest::newRow("regexp literal") << QString::fromLatin1("/foo/gim");
    QTest::newRow("null literal") << QString::fromLatin1("null");
    QTest::newRow("undefined literal") << QString::fromLatin1("undefined");
    QTest::newRow("null literal") << QString::fromLatin1("null");
    QTest::newRow("empty object literal") << QString::fromLatin1("{}");
    QTest::newRow("this") << QString::fromLatin1("this");
    QTest::newRow("object literal with one property") << QString::fromLatin1("{ foo: 123 }");
    QTest::newRow("object literal with two properties") << QString::fromLatin1("{ foo: 123, bar: 456 }");
    QTest::newRow("object literal with many properties") << QString::fromLatin1("{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 }");
    QTest::newRow("empty array literal") << QString::fromLatin1("[]");
    QTest::newRow("array literal with one element") << QString::fromLatin1("[1]");
    QTest::newRow("array literal with two elements") << QString::fromLatin1("[1,2]");
    QTest::newRow("array literal with many elements") << QString::fromLatin1("[1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1]");
    QTest::newRow("empty function definition") << QString::fromLatin1("function foo() { }");
    QTest::newRow("function definition") << QString::fromLatin1("function foo() { return 123; }");
    QTest::newRow("for loop with empty body (1000 iterations)") << QString::fromLatin1("for (i = 0; i < 1000; ++i) {}");
    QTest::newRow("for loop with empty body (10000 iterations)") << QString::fromLatin1("for (i = 0; i < 10000; ++i) {}");
    QTest::newRow("for loop with empty body (100000 iterations)") << QString::fromLatin1("for (i = 0; i < 100000; ++i) {}");
    QTest::newRow("for loop with empty body (1000000 iterations)") << QString::fromLatin1("for (i = 0; i < 1000000; ++i) {}");
    QTest::newRow("for loop (1000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 1000; ++i) { j += i; }; j");
    QTest::newRow("for loop (10000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 10000; ++i) { j += i; }; j");
    QTest::newRow("for loop (100000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 100000; ++i) { j += i; }; j");
    QTest::newRow("for loop (1000000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 1000000; ++i) { j += i; }; j");
    QTest::newRow("assignments") << QString::fromLatin1("a = 1; b = 2; c = 3; d = 4");
    QTest::newRow("while loop (1000 iterations)") << QString::fromLatin1("i = 0; while (i < 1000) { ++i; }; i");
    QTest::newRow("while loop (10000 iterations)") << QString::fromLatin1("i = 0; while (i < 10000) { ++i; }; i");
    QTest::newRow("while loop (100000 iterations)") << QString::fromLatin1("i = 0; while (i < 100000) { ++i; }; i");
    QTest::newRow("while loop (1000000 iterations)") << QString::fromLatin1("i = 0; while (i < 1000000) { ++i; }; i");
    QTest::newRow("function expression") << QString::fromLatin1("(function(a, b, c){ return a + b + c; })(1, 2, 3)");
}

void tst_QScriptEngine::evaluate()
{
    QFETCH(QString, code);
    QScriptEngine engine;

    QBENCHMARK {
        (void)engine.evaluate(code);
    }
}

void tst_QScriptEngine::connectAndDisconnect()
{
    QScriptEngine engine;
    QScriptValue fun = engine.evaluate("(function() { })");
    QBENCHMARK {
        qScriptConnect(&engine, SIGNAL(destroyed()), QScriptValue(), fun);
        qScriptDisconnect(&engine, SIGNAL(destroyed()), QScriptValue(), fun);
    }
}

void tst_QScriptEngine::evaluateProgram_data()
{
    evaluate_data();
}

void tst_QScriptEngine::evaluateProgram()
{
    QFETCH(QString, code);
    QScriptEngine engine;
    QScriptProgram program(code);

    QBENCHMARK {
        (void)engine.evaluate(program);
    }
}

void tst_QScriptEngine::newObject()
{
    QScriptEngine engine;
    QBENCHMARK {
        (void)engine.newObject();
    }
}

void tst_QScriptEngine::newQObject()
{
    QScriptEngine engine;
    QBENCHMARK {
        (void)engine.newQObject(QCoreApplication::instance());
    }
}

static QScriptValue testFunction(QScriptContext *, QScriptEngine *)
{
    return 0;
}

void tst_QScriptEngine::newFunction()
{
    QScriptEngine engine;
    QBENCHMARK {
        (void)engine.newFunction(testFunction);
    }
}

void tst_QScriptEngine::newVariant()
{
    QScriptEngine engine;
    QVariant var(123);
    QBENCHMARK {
        (void)engine.newVariant(var);
    }
}

void tst_QScriptEngine::collectGarbage()
{
    QScriptEngine engine;
    QBENCHMARK {
        engine.collectGarbage();
    }
}

void tst_QScriptEngine::pushAndPopContext()
{
    QScriptEngine engine;
    QBENCHMARK {
        (void)engine.pushContext();
        engine.popContext();
    }
}

void tst_QScriptEngine::toStringHandle()
{
    QScriptEngine engine;
    QString str = QString::fromLatin1("foobarbaz");
    QBENCHMARK {
        (void)engine.toStringHandle(str);
    }
}

void tst_QScriptEngine::castValueToQreal()
{
    QScriptEngine engine;
    QScriptValue val(123);
    QBENCHMARK {
        (void)qscriptvalue_cast<qreal>(val);
    }
}

static QScriptValue native_function(QScriptContext *, QScriptEngine *)
{
    return 42;
}

void tst_QScriptEngine::nativeCall()
{
    QScriptEngine eng;
    eng.globalObject().setProperty("fun", eng.newFunction(native_function));
    QBENCHMARK{
        eng.evaluate("var w = 0; for (i = 0; i < 100000; ++i) {\n"
                     "  w += fun() + fun(); w -= fun(); fun(); w -= fun(); }");
    }
}

QTEST_MAIN(tst_QScriptEngine)
#include "tst_qscriptengine.moc"
<commit_msg>Add benchmark for QtScript translation functions.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite 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 Technology Preview License Agreement accompanying
** this package.
**
** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qtest.h>
#include <QtScript>

//TESTED_FILES=

class tst_QScriptEngine : public QObject
{
    Q_OBJECT

public:
    tst_QScriptEngine();
    virtual ~tst_QScriptEngine();

public slots:
    void init();
    void cleanup();

private slots:
    void constructor();
    void evaluate_data();
    void evaluate();
    void evaluateProgram_data();
    void evaluateProgram();
    void connectAndDisconnect();
    void newObject();
    void newQObject();
    void newFunction();
    void newVariant();
    void collectGarbage();
    void pushAndPopContext();
    void toStringHandle();
    void castValueToQreal();
    void nativeCall();
    void translation_data();
    void translation();
};

tst_QScriptEngine::tst_QScriptEngine()
{
}

tst_QScriptEngine::~tst_QScriptEngine()
{
}

void tst_QScriptEngine::init()
{
}

void tst_QScriptEngine::cleanup()
{
}

void tst_QScriptEngine::constructor()
{
    QBENCHMARK {
        QScriptEngine engine;
        (void)engine.parent();
    }
}

void tst_QScriptEngine::evaluate_data()
{
    QTest::addColumn<QString>("code");
    QTest::newRow("empty script") << QString::fromLatin1("");
    QTest::newRow("number literal") << QString::fromLatin1("123");
    QTest::newRow("string literal") << QString::fromLatin1("'ciao'");
    QTest::newRow("regexp literal") << QString::fromLatin1("/foo/gim");
    QTest::newRow("null literal") << QString::fromLatin1("null");
    QTest::newRow("undefined literal") << QString::fromLatin1("undefined");
    QTest::newRow("null literal") << QString::fromLatin1("null");
    QTest::newRow("empty object literal") << QString::fromLatin1("{}");
    QTest::newRow("this") << QString::fromLatin1("this");
    QTest::newRow("object literal with one property") << QString::fromLatin1("{ foo: 123 }");
    QTest::newRow("object literal with two properties") << QString::fromLatin1("{ foo: 123, bar: 456 }");
    QTest::newRow("object literal with many properties") << QString::fromLatin1("{ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10 }");
    QTest::newRow("empty array literal") << QString::fromLatin1("[]");
    QTest::newRow("array literal with one element") << QString::fromLatin1("[1]");
    QTest::newRow("array literal with two elements") << QString::fromLatin1("[1,2]");
    QTest::newRow("array literal with many elements") << QString::fromLatin1("[1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1]");
    QTest::newRow("empty function definition") << QString::fromLatin1("function foo() { }");
    QTest::newRow("function definition") << QString::fromLatin1("function foo() { return 123; }");
    QTest::newRow("for loop with empty body (1000 iterations)") << QString::fromLatin1("for (i = 0; i < 1000; ++i) {}");
    QTest::newRow("for loop with empty body (10000 iterations)") << QString::fromLatin1("for (i = 0; i < 10000; ++i) {}");
    QTest::newRow("for loop with empty body (100000 iterations)") << QString::fromLatin1("for (i = 0; i < 100000; ++i) {}");
    QTest::newRow("for loop with empty body (1000000 iterations)") << QString::fromLatin1("for (i = 0; i < 1000000; ++i) {}");
    QTest::newRow("for loop (1000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 1000; ++i) { j += i; }; j");
    QTest::newRow("for loop (10000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 10000; ++i) { j += i; }; j");
    QTest::newRow("for loop (100000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 100000; ++i) { j += i; }; j");
    QTest::newRow("for loop (1000000 iterations)") << QString::fromLatin1("j = 0; for (i = 0; i < 1000000; ++i) { j += i; }; j");
    QTest::newRow("assignments") << QString::fromLatin1("a = 1; b = 2; c = 3; d = 4");
    QTest::newRow("while loop (1000 iterations)") << QString::fromLatin1("i = 0; while (i < 1000) { ++i; }; i");
    QTest::newRow("while loop (10000 iterations)") << QString::fromLatin1("i = 0; while (i < 10000) { ++i; }; i");
    QTest::newRow("while loop (100000 iterations)") << QString::fromLatin1("i = 0; while (i < 100000) { ++i; }; i");
    QTest::newRow("while loop (1000000 iterations)") << QString::fromLatin1("i = 0; while (i < 1000000) { ++i; }; i");
    QTest::newRow("function expression") << QString::fromLatin1("(function(a, b, c){ return a + b + c; })(1, 2, 3)");
}

void tst_QScriptEngine::evaluate()
{
    QFETCH(QString, code);
    QScriptEngine engine;

    QBENCHMARK {
        (void)engine.evaluate(code);
    }
}

void tst_QScriptEngine::connectAndDisconnect()
{
    QScriptEngine engine;
    QScriptValue fun = engine.evaluate("(function() { })");
    QBENCHMARK {
        qScriptConnect(&engine, SIGNAL(destroyed()), QScriptValue(), fun);
        qScriptDisconnect(&engine, SIGNAL(destroyed()), QScriptValue(), fun);
    }
}

void tst_QScriptEngine::evaluateProgram_data()
{
    evaluate_data();
}

void tst_QScriptEngine::evaluateProgram()
{
    QFETCH(QString, code);
    QScriptEngine engine;
    QScriptProgram program(code);

    QBENCHMARK {
        (void)engine.evaluate(program);
    }
}

void tst_QScriptEngine::newObject()
{
    QScriptEngine engine;
    QBENCHMARK {
        (void)engine.newObject();
    }
}

void tst_QScriptEngine::newQObject()
{
    QScriptEngine engine;
    QBENCHMARK {
        (void)engine.newQObject(QCoreApplication::instance());
    }
}

static QScriptValue testFunction(QScriptContext *, QScriptEngine *)
{
    return 0;
}

void tst_QScriptEngine::newFunction()
{
    QScriptEngine engine;
    QBENCHMARK {
        (void)engine.newFunction(testFunction);
    }
}

void tst_QScriptEngine::newVariant()
{
    QScriptEngine engine;
    QVariant var(123);
    QBENCHMARK {
        (void)engine.newVariant(var);
    }
}

void tst_QScriptEngine::collectGarbage()
{
    QScriptEngine engine;
    QBENCHMARK {
        engine.collectGarbage();
    }
}

void tst_QScriptEngine::pushAndPopContext()
{
    QScriptEngine engine;
    QBENCHMARK {
        (void)engine.pushContext();
        engine.popContext();
    }
}

void tst_QScriptEngine::toStringHandle()
{
    QScriptEngine engine;
    QString str = QString::fromLatin1("foobarbaz");
    QBENCHMARK {
        (void)engine.toStringHandle(str);
    }
}

void tst_QScriptEngine::castValueToQreal()
{
    QScriptEngine engine;
    QScriptValue val(123);
    QBENCHMARK {
        (void)qscriptvalue_cast<qreal>(val);
    }
}

static QScriptValue native_function(QScriptContext *, QScriptEngine *)
{
    return 42;
}

void tst_QScriptEngine::nativeCall()
{
    QScriptEngine eng;
    eng.globalObject().setProperty("fun", eng.newFunction(native_function));
    QBENCHMARK{
        eng.evaluate("var w = 0; for (i = 0; i < 100000; ++i) {\n"
                     "  w += fun() + fun(); w -= fun(); fun(); w -= fun(); }");
    }
}

void tst_QScriptEngine::translation_data()
{
    QTest::addColumn<QString>("text");
    QTest::newRow("no translation") << "\"hello world\"";
    QTest::newRow("qsTr") << "qsTr(\"hello world\")";
    QTest::newRow("qsTranslate") << "qsTranslate(\"\", \"hello world\")";
}

void tst_QScriptEngine::translation()
{
    QFETCH(QString, text);
    QScriptEngine engine;
    engine.installTranslatorFunctions();

    QBENCHMARK {
        (void)engine.evaluate(text);
    }
}

QTEST_MAIN(tst_QScriptEngine)
#include "tst_qscriptengine.moc"
<|endoftext|>


<commit_before>#include "qniteline.h"
#include "qnitefillnode.h"
#include "qniteaxes.h"
#include "qniteaxis.h"

#include <QDebug>

#include <QSGGeometry>
#include <QSGGeometryNode>
#include <QSGFlatColorMaterial>

#define SELECTION_TOLERANCE 25

QniteLine::QniteLine(QQuickItem *parent):
  QniteXYArtist(parent),
  m_fillNode{nullptr},
  m_fill{false},
  m_selected{false}
{
  setFlag(ItemHasContents, true);
}

QniteLine::~QniteLine()
{
}

void QniteLine::setFill(bool fill)
{
  if (m_fill != fill) {
    m_fill = fill;
    emit fillChanged();
  }
}

void QniteLine::setFillColor(QColor fillColor)
{
  if (m_fillColor != fillColor) {
    m_fillColor = fillColor;
    emit fillColorChanged();
  }
}

QSGNode* QniteLine::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*)
{
  QSGGeometryNode *node = 0;
  QSGGeometry *geometry = 0;

  // TODO: processdata should be triggered only when data changes
  processData();
  int dataSize = xMapped().size();

  // TODO: handle selection highlight in a proper way
  QSGFlatColorMaterial * material = new QSGFlatColorMaterial;
  if (selected()) {
    material->setColor(color().lighter(200));
  }
  else {
    material->setColor(color());
  }

  if (!oldNode) {
    node = new QSGGeometryNode;
    geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), dataSize);
    geometry->setLineWidth(2);
    geometry->setDrawingMode(GL_LINE_STRIP);
    node->setGeometry(geometry);
    node->setFlag(QSGNode::OwnsGeometry);
    node->setFlag(QSGNode::OwnsMaterial);
  } else {
    node = static_cast<QSGGeometryNode *>(oldNode);
    geometry = node->geometry();
    geometry->allocate(dataSize);
  }
  node->setMaterial(material);

  if (m_fill) {
    if (m_fillNode == nullptr) {
      m_fillNode = new QniteFillNode(QColor(m_fillColor));
      node->appendChildNode(m_fillNode);
    }

    qreal ya = axes()->leftAxis()->position();
    m_fillNode->updateGeometry(xMapped(), yMapped(), ya);
  }

  QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
  for(int i = 0; i < dataSize; ++i) {
    vertices[i].set(xMapped().at(i), yMapped().at(i));
  }

  node->markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial);
  return node;
}

/*!
  Temporary implementation of the selection logic for lines.

  TODO: fix the implementation
  TODO: can we assume data is alwayws already mapped at this point?
 */
bool QniteLine::select(QPoint p)
{
  bool accepted = false;

  // get the distance from the first point on the path
  int dataSize = xMapped().size();
  for(int i = 0; i < dataSize; ++i) {
    QPoint cp(xMapped().at(i), yMapped().at(i));
    QPoint d = p - cp;
    if (d.manhattanLength() < SELECTION_TOLERANCE) {
      m_selected = true;
      accepted = true;
      axes()->setOnTop(this);
      update();
      break;
    }
  }

  return accepted;
}

bool QniteLine::select(const QList<QPoint>& path)
{
  if (path.size()) {
    return select(path.first());
  }

  return false;
}

void QniteLine::clearSelection()
{
  m_selected = false;
  update();
}
<commit_msg>visual reparenting cleans node children, handle this for filled areas<commit_after>#include "qniteline.h"
#include "qnitefillnode.h"
#include "qniteaxes.h"
#include "qniteaxis.h"

#include <QDebug>

#include <QSGGeometry>
#include <QSGGeometryNode>
#include <QSGFlatColorMaterial>

#define SELECTION_TOLERANCE 25

QniteLine::QniteLine(QQuickItem *parent):
  QniteXYArtist(parent),
  m_fillNode{nullptr},
  m_fill{false},
  m_selected{false}
{
  setFlag(ItemHasContents, true);
}

QniteLine::~QniteLine()
{
}

void QniteLine::setFill(bool fill)
{
  if (m_fill != fill) {
    m_fill = fill;
    emit fillChanged();
  }
}

void QniteLine::setFillColor(QColor fillColor)
{
  if (m_fillColor != fillColor) {
    m_fillColor = fillColor;
    emit fillColorChanged();
  }
}

QSGNode* QniteLine::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*)
{
  QSGGeometryNode *node = 0;
  QSGGeometry *geometry = 0;

  // TODO: processdata should be triggered only when data changes
  processData();
  int dataSize = xMapped().size();

  // TODO: handle selection highlight in a proper way
  QSGFlatColorMaterial * material = new QSGFlatColorMaterial;
  if (selected()) {
    material->setColor(color().lighter(200));
  }
  else {
    material->setColor(color());
  }

  if (!oldNode) {
    node = new QSGGeometryNode;
    geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), dataSize);
    geometry->setLineWidth(2);
    geometry->setDrawingMode(GL_LINE_STRIP);
    node->setGeometry(geometry);
    node->setFlag(QSGNode::OwnsGeometry);
    node->setFlag(QSGNode::OwnsMaterial);
  } else {
    node = static_cast<QSGGeometryNode *>(oldNode);
    geometry = node->geometry();
    geometry->allocate(dataSize);
  }
  node->setMaterial(material);

  if (m_fill) {
    // handle dirty state caused by visual reparenting
    if ((m_fillNode==nullptr) || (node->childCount() == 0)) {
      m_fillNode = new QniteFillNode(QColor(m_fillColor));
      node->appendChildNode(m_fillNode);
    }

    qreal ya = axes()->leftAxis()->position();
    m_fillNode->updateGeometry(xMapped(), yMapped(), ya);
  }

  QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D();
  for(int i = 0; i < dataSize; ++i) {
    vertices[i].set(xMapped().at(i), yMapped().at(i));
  }

  node->markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial);
  return node;
}

/*!
  Temporary implementation of the selection logic for lines.

  TODO: fix the implementation
  TODO: can we assume data is alwayws already mapped at this point?
 */
bool QniteLine::select(QPoint p)
{
  bool accepted = false;

  // get the distance from the first point on the path
  int dataSize = xMapped().size();
  for(int i = 0; i < dataSize; ++i) {
    QPoint cp(xMapped().at(i), yMapped().at(i));
    QPoint d = p - cp;
    if (d.manhattanLength() < SELECTION_TOLERANCE) {
      m_selected = true;
      accepted = true;
      axes()->setOnTop(this);
      update();
      break;
    }
  }

  return accepted;
}

bool QniteLine::select(const QList<QPoint>& path)
{
  if (path.size()) {
    return select(path.first());
  }

  return false;
}

void QniteLine::clearSelection()
{
  m_selected = false;
  update();
}
<|endoftext|>