Commit ee6c693a authored by Yuchen Deng's avatar Yuchen Deng Committed by Eike Ziller
Browse files

Add execute filter for locator



Change-Id: If6533851a7207e8cf93db7176497a69bb77893c0
Reviewed-by: default avatarEike Ziller <eike.ziller@nokia.com>
parent 297b444d
/**************************************************************************
**
** 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 "executefilter.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <coreplugin/variablemanager.h>
#include <QtGui/QMessageBox>
using namespace Core;
using namespace Locator;
using namespace Locator::Internal;
ExecuteFilter::ExecuteFilter()
{
setShortcutString(QString(QLatin1Char('!')));
setIncludedByDefault(false);
m_process = new Utils::QtcProcess(this);
m_process->setEnvironment(Utils::Environment::systemEnvironment());
connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)), this,
SLOT(finished(int, QProcess::ExitStatus)));
connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(readStandardOutput()));
connect(m_process, SIGNAL(readyReadStandardError()), this, SLOT(readStandardError()));
m_runTimer.setSingleShot(true);
connect(&m_runTimer, SIGNAL(timeout()), this, SLOT(runHeadCommand()));
}
QList<FilterEntry> ExecuteFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future,
const QString &entry)
{
QList<FilterEntry> value;
if (!entry.isEmpty()) // avoid empty entry
value.append(FilterEntry(this, entry, QVariant()));
QList<FilterEntry> others;
foreach (const QString& i, m_commandHistory) {
if (future.isCanceled())
break;
if (i == entry) // avoid repeated entry
continue;
if (i.startsWith(entry))
value.append(FilterEntry(this, i, QVariant()));
else
others.append(FilterEntry(this, i, QVariant()));
}
value.append(others);
return value;
}
void ExecuteFilter::accept(FilterEntry selection) const
{
ExecuteFilter *p = const_cast<ExecuteFilter *>(this);
const QString value = selection.displayName.trimmed();
const int index = m_commandHistory.indexOf(value);
if (index != -1 && index != 0)
p->m_commandHistory.removeAt(index);
if (index != 0)
p->m_commandHistory.prepend(value);
VariableManager *vm = Core::VariableManager::instance();
bool found;
QString workingDirectory = vm->value(QLatin1String("CurrentDocument:Path"), &found);
if (!found || workingDirectory.isEmpty())
workingDirectory = vm->value(QLatin1String("CurrentProject:Path"), &found);
ExecuteData d;
d.workingDirectory = workingDirectory;
const int pos = value.indexOf(QLatin1Char(' '));
if (pos == -1) {
d.executable = value;
} else {
d.executable = value.left(pos);
d.arguments = value.right(value.length() - pos - 1);
}
if (m_process->state() != QProcess::NotRunning) {
const QString info(tr("Previous command is still running ('%1').\nDo you want to kill it?")
.arg(p->headCommand()));
int r = QMessageBox::question(0, tr("Kill previous process?"), info,
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
QMessageBox::Yes);
if (r == QMessageBox::Yes)
m_process->kill();
if (r != QMessageBox::Cancel)
p->m_taskQueue.enqueue(d);
return;
}
p->m_taskQueue.enqueue(d);
p->runHeadCommand();
}
void ExecuteFilter::finished(int exitCode, QProcess::ExitStatus status)
{
QString log = QString("'%1' ").arg(headCommand());
if (status == QProcess::NormalExit && exitCode == 0)
ICore::instance()->messageManager()->printToOutputPane(log + tr("finished"), true);
else
ICore::instance()->messageManager()->printToOutputPane(log + tr("failed"), true);
m_taskQueue.dequeue();
if (!m_taskQueue.isEmpty())
m_runTimer.start(500);
}
void ExecuteFilter::readStandardOutput()
{
QByteArray data = m_process->readAllStandardOutput();
ICore::instance()->messageManager()->printToOutputPane(data, true);
}
void ExecuteFilter::readStandardError()
{
QByteArray data = m_process->readAllStandardError();
ICore::instance()->messageManager()->printToOutputPane(data, true);
}
void ExecuteFilter::runHeadCommand()
{
if (!m_taskQueue.isEmpty()) {
const ExecuteData &d = m_taskQueue.head();
const QString fullPath = Utils::Environment::systemEnvironment().searchInPath(d.executable);
if (fullPath.isEmpty()) {
const QString log = tr("Could not find executable for '%1'").arg(d.executable);
ICore::instance()->messageManager()->printToOutputPane(log, true);
m_taskQueue.dequeue();
runHeadCommand();
return;
}
QString log(tr("Starting command '%1'").arg(headCommand()));
ICore::instance()->messageManager()->printToOutputPane(log, true);
m_process->setWorkingDirectory(d.workingDirectory);
m_process->setCommand(fullPath, d.arguments);
m_process->start();
}
}
QString ExecuteFilter::headCommand() const
{
if (m_taskQueue.isEmpty())
return QString();
const ExecuteData &data = m_taskQueue.head();
if (data.arguments.isEmpty())
return data.executable;
else
return data.executable + QLatin1Char(' ') + data.arguments;
}
/**************************************************************************
**
** 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.
**
**************************************************************************/
#ifndef EXECUTEFILTER_H
#define EXECUTEFILTER_H
#include "ilocatorfilter.h"
#include <utils/qtcprocess.h>
#include <QtCore/QQueue>
#include <QtCore/QStringList>
#include <QtCore/QTimer>
namespace Locator {
namespace Internal {
class ExecuteFilter : public Locator::ILocatorFilter
{
Q_OBJECT
struct ExecuteData
{
QString executable;
QString arguments;
QString workingDirectory;
};
public:
ExecuteFilter();
QString displayName() const { return tr("Execute Custom Commands"); }
QString id() const { return "Execute custom commands"; }
Locator::ILocatorFilter::Priority priority() const { return Locator::ILocatorFilter::Medium; }
QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future,
const QString &entry);
void accept(Locator::FilterEntry selection) const;
void refresh(QFutureInterface<void> &) {}
private slots:
void finished(int exitCode, QProcess::ExitStatus status);
void readStandardOutput();
void readStandardError();
void runHeadCommand();
private:
QString headCommand() const;
private:
QQueue<ExecuteData> m_taskQueue;
QStringList m_commandHistory;
Utils::QtcProcess *m_process;
QTimer m_runTimer;
};
} // namespace Internal
} // namespace Locator
#endif // EXECUTEFILTER_H
......@@ -15,7 +15,8 @@ HEADERS += locatorplugin.h \
directoryfilter.h \
locatormanager.h \
basefilefilter.h \
locator_global.h
locator_global.h \
executefilter.h
SOURCES += locatorplugin.cpp \
commandlocator.cpp \
locatorwidget.cpp \
......@@ -26,7 +27,8 @@ SOURCES += locatorplugin.cpp \
directoryfilter.cpp \
locatormanager.cpp \
basefilefilter.cpp \
ilocatorfilter.cpp
ilocatorfilter.cpp \
executefilter.cpp
FORMS += settingspage.ui \
filesystemfilter.ui \
......
......@@ -93,9 +93,11 @@ LocatorPlugin::~LocatorPlugin()
{
removeObject(m_openDocumentsFilter);
removeObject(m_fileSystemFilter);
removeObject(m_executeFilter);
removeObject(m_settingsPage);
delete m_openDocumentsFilter;
delete m_fileSystemFilter;
delete m_executeFilter;
delete m_settingsPage;
qDeleteAll(m_customFilters);
}
......@@ -133,6 +135,9 @@ bool LocatorPlugin::initialize(const QStringList &, QString *)
m_fileSystemFilter = new FileSystemFilter(core->editorManager(), m_locatorWidget);
addObject(m_fileSystemFilter);
m_executeFilter = new ExecuteFilter();
addObject(m_executeFilter);
addAutoReleasedObject(new LocatorFiltersFilter(this, m_locatorWidget));
connect(core, SIGNAL(coreOpened()), this, SLOT(startSettingsLoad()));
......
......@@ -35,6 +35,7 @@
#include "ilocatorfilter.h"
#include "directoryfilter.h"
#include "executefilter.h"
#include <extensionsystem/iplugin.h>
#include <coreplugin/actionmanager/command.h>
......@@ -95,6 +96,7 @@ private:
QTimer m_refreshTimer;
OpenDocumentsFilter *m_openDocumentsFilter;
FileSystemFilter *m_fileSystemFilter;
ExecuteFilter *m_executeFilter;
QFutureWatcher<void> m_loadWatcher;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment