summaryrefslogtreecommitdiffstats
path: root/examples/xmlpatterns/filetree/mainwindow.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Update copyright year to 2011.Jason McDonald2011-01-111-1/+1
| | | | | Reviewed-by: Trust Me (cherry picked from commit ac5c099cc3c5b8c7eec7a49fdeb8a21037230350)
* QString usage cleanupsOswald Buddenhagen2010-09-011-1/+1
| | | | | - tr() already returns a QString, duh - use multi-arg arg() (heh)
* Doc: Updated example license to three clause BSD license.David Boddie2010-05-191-27/+26
| | | | | Reviewed-by: Trust Me Requested-by: Legal
* Update copyright year to 2010Jason McDonald2010-01-061-1/+1
| | | | Reviewed-by: Trust Me
* Update license headers again.Jason McDonald2009-09-091-4/+4
| | | | Reviewed-by: Trust Me
* Update tech preview license header.Jason McDonald2009-08-311-13/+13
| | | | Reviewed-by: Trust Me
* Update license headers.Jason McDonald2009-08-111-1/+1
| | | | Reviewed-by: Trust Me
* Update license headers as requested by the marketing department.Jason McDonald2009-06-161-2/+2
| | | | Reviewed-by: Trust Me
* Long live Qt 4.5!Lars Knoll2009-03-231-0/+166
href='#n197'>197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtSCriptTools module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qscriptcompletiontask_p.h"
#include "qscriptcompletiontaskinterface_p_p.h"
#include "qscriptdebuggerconsole_p.h"
#include "qscriptdebuggerconsolecommand_p.h"
#include "qscriptdebuggerconsolecommandmanager_p.h"
#include "qscriptdebuggercommandschedulerjob_p.h"
#include "qscriptdebuggercommandschedulerfrontend_p.h"
#include "qscriptdebuggerjobschedulerinterface_p.h"
#include "qscriptdebuggerresponse_p.h"

#include "private/qobject_p.h"

#include <QtCore/qset.h>
#include <QtCore/qdebug.h>

QT_BEGIN_NAMESPACE

class QScriptCompletionTaskPrivate
    : public QScriptCompletionTaskInterfacePrivate
{
    Q_DECLARE_PUBLIC(QScriptCompletionTask)
public:
    QScriptCompletionTaskPrivate();
    ~QScriptCompletionTaskPrivate();

    void completeScriptExpression();
    void emitFinished();

    QString contents;
    int cursorPosition;
    int frameIndex;
    QScriptDebuggerCommandSchedulerInterface *commandScheduler;
    QScriptDebuggerJobSchedulerInterface *jobScheduler;
    QScriptDebuggerConsole *console;
};

QScriptCompletionTaskPrivate::QScriptCompletionTaskPrivate()
    : cursorPosition(0), frameIndex(0), commandScheduler(0),
      jobScheduler(0), console(0)
{
}

QScriptCompletionTaskPrivate::~QScriptCompletionTaskPrivate()
{
}

class QScriptCompleteExpressionJob : public QScriptDebuggerCommandSchedulerJob
{
public:
    QScriptCompleteExpressionJob(int frameIndex, const QStringList &path,
                                 QScriptCompletionTaskPrivate *task,
                                 QScriptDebuggerCommandSchedulerInterface *scheduler)
        : QScriptDebuggerCommandSchedulerJob(scheduler),
          m_frameIndex(frameIndex), m_path(path), m_task(task)
        {}

    void start()
    {
        QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
        frontend.scheduleGetCompletions(m_frameIndex, m_path);
    }
    void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
    {
        m_task->results = response.result().toStringList();
        m_task->emitFinished();
        finish();
    }

private:
    int m_frameIndex;
    QStringList m_path;
    QScriptCompletionTaskPrivate *m_task;
};

namespace {

static bool isIdentChar(const QChar &ch)
{
    static QChar underscore = QLatin1Char('_');
    return ch.isLetter() || (ch == underscore);
}

static bool isPrefixOf(const QString &prefix, const QString &what)
{
    return ((what.length() > prefix.length())
            && what.startsWith(prefix));
}

} // namespace

class QScriptCompleteScriptsJob : public QScriptDebuggerCommandSchedulerJob
{
public:
    QScriptCompleteScriptsJob(const QString &prefix, QScriptCompletionTaskPrivate *task,
                              QScriptDebuggerCommandSchedulerInterface *scheduler)
        : QScriptDebuggerCommandSchedulerJob(scheduler),
          m_prefix(prefix), m_task(task)
        {}

    void start()
    {
        QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
        frontend.scheduleGetScripts();
    }
    void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
    {
        QScriptScriptMap scripts = response.resultAsScripts();
        QScriptScriptMap::const_iterator it;
        for (it = scripts.constBegin(); it != scripts.constEnd(); ++it) {
            QString fileName = it.value().fileName();
            if (isPrefixOf(m_prefix, fileName))
                m_task->results.append(fileName);
        }
        m_task->emitFinished();
        finish();
    }
private:
    QString m_prefix;
    QScriptCompletionTaskPrivate *m_task;
};

void QScriptCompletionTaskPrivate::completeScriptExpression()
{
    int pos = cursorPosition;
    if ((pos > 0) && contents.at(pos-1).isNumber()) {
        // completion of numbers is pointless
        emitFinished();
        return;
    }

    while ((pos > 0) && isIdentChar(contents.at(pos-1)))
        --pos;
    int pos2 = cursorPosition - 1;
    while ((pos2+1 < contents.size()) && isIdentChar(contents.at(pos2+1)))
        ++pos2;
    QString ident = contents.mid(pos, pos2 - pos + 1);
    position = pos;

    QStringList path;
    path.append(ident);
    while ((pos > 0) && (contents.at(pos-1) == QLatin1Char('.'))) {
        --pos;
        pos2 = pos;
        while ((pos > 0) && isIdentChar(contents.at(pos-1)))
            --pos;
        path.prepend(contents.mid(pos, pos2 - pos));
    }

    length = path.last().length();
    type = QScriptCompletionTask::ScriptIdentifierCompletion;

    QScriptDebuggerJob *job = new QScriptCompleteExpressionJob(frameIndex, path, this, commandScheduler);
    jobScheduler->scheduleJob(job);
}

void QScriptCompletionTaskPrivate::emitFinished()
{
    emit q_func()->finished();
}

QScriptCompletionTask::QScriptCompletionTask(
    const QString &contents, int cursorPosition, int frameIndex,
    QScriptDebuggerCommandSchedulerInterface *commandScheduler,
    QScriptDebuggerJobSchedulerInterface *jobScheduler,
    QScriptDebuggerConsole *console,
    QObject *parent)
    : QScriptCompletionTaskInterface(
        *new QScriptCompletionTaskPrivate, parent)
{
    Q_D(QScriptCompletionTask);
    d->contents = contents;
    d->cursorPosition = cursorPosition;
    if ((frameIndex == -1) && console)
        d->frameIndex = console->currentFrameIndex();
    else
        d->frameIndex = frameIndex;
    d->commandScheduler = commandScheduler;
    d->jobScheduler = jobScheduler;
    d->console = console;
}

QScriptCompletionTask::~QScriptCompletionTask()
{
}

void QScriptCompletionTask::start()
{
    Q_D(QScriptCompletionTask);
    d->type = NoCompletion;
    // see if we're typing a command
    // ### don't hardcode the command prefix
    QRegExp cmdRx(QString::fromLatin1("^\\s*\\.([a-zA-Z]*)"));
    int cmdIndex = cmdRx.indexIn(d->contents);
    if ((cmdIndex != -1) && d->console) {
        int len = cmdRx.matchedLength();
        QString prefix = cmdRx.capturedTexts().at(1);
        if ((d->cursorPosition >= cmdIndex) && (d->cursorPosition <= (cmdIndex+len))) {
            // editing command --> get command completions
            d->results = d->console->commandManager()->completions(prefix);
            d->position = cmdRx.pos(1);
            d->length = prefix.length();
            d->type = CommandNameCompletion;
            d->appendix = QString::fromLatin1(" ");
            emit finished();
        } else {
            QScriptDebuggerConsoleCommand *cmd = d->console->commandManager()->findCommand(prefix);
            if (!cmd) {
                emit finished();
                return;
            }
            // editing an argument
            int argNum = 0;
            QString arg;
            int pos = cmdIndex + len;
            while (pos < d->contents.size()) {
                while ((pos < d->contents.size()) && d->contents.at(pos).isSpace())
                    ++pos;
                if (pos < d->contents.size()) {
                    int pos2 = pos + 1;
                    while ((pos2 < d->contents.size()) && !d->contents.at(pos2).isSpace())
                        ++pos2;
                    if ((d->cursorPosition >= pos) && (d->cursorPosition <= pos2)) {
                        arg = d->contents.mid(pos, pos2 - pos);
                        break;
                    }
                    pos = pos2;
                    ++argNum;
                }
            }
            QString argType = cmd->argumentTypes().value(argNum);
            if (!argType.isEmpty()) {
                if (argType == QLatin1String("command-or-group-name")) {
                    d->results = d->console->commandManager()->completions(arg);
                } else if (argType == QLatin1String("script-filename")) {
                    d->position = pos;
                    d->length = arg.length();
                    d->type = CommandArgumentCompletion;
                    QScriptDebuggerJob *job = new QScriptCompleteScriptsJob(arg, d, d->commandScheduler);
                    d->jobScheduler->scheduleJob(job);
                } else if (argType == QLatin1String("subcommand-name")) {
                    for (int i = 0; i < cmd->subCommands().size(); ++i) {
                        QString name = cmd->subCommands().at(i);
                        if (isPrefixOf(arg, name))
                            d->results.append(name);
                    }
                    qStableSort(d->results);
                } else if (argType == QLatin1String("script")) {
                    d->completeScriptExpression();
                } else {
                    emit finished();
                }
                if ((d->type == NoCompletion) && !d->results.isEmpty()) {
                    d->position = pos;
                    d->length = arg.length();
                    d->type = CommandArgumentCompletion;
                    emit finished();
                }
            }
        }
    } else {
        // assume it's an eval expression
        d->completeScriptExpression();
    }
}

QT_END_NAMESPACE