diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.cpp b/src/plugins/coreplugin/actionmanager/actionmanager.cpp index 97b7bca13e78b431f2d3f3b10d4462c40d963485..67706afa2a5e69121d63abd039ab1161f3d22c45 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager.cpp +++ b/src/plugins/coreplugin/actionmanager/actionmanager.cpp @@ -166,7 +166,7 @@ namespace { */ /*! - \fn Command *ActionManager::registerAction(QAction *action, const QString &id, const Context &context) + \fn Command *ActionManager::registerAction(QAction *action, const QString &id, const Context &context, bool scriptable) \brief Makes an \a action known to the system under the specified string \a id. Returns a command object that represents the action in the application and is @@ -174,10 +174,12 @@ namespace { same \a id as long as the \a context is different. In this case a trigger of the actual action is forwarded to the registered QAction for the currently active context. + A scriptable action can be called from a script without the need for the user + to interact with it. */ /*! - \fn Command *ActionManager::registerShortcut(QShortcut *shortcut, const QString &id, const Context &context) + \fn Command *ActionManager::registerShortcut(QShortcut *shortcut, const QString &id, const Context &context, bool scriptable) \brief Makes a \a shortcut known to the system under the specified string \a id. Returns a command object that represents the shortcut in the application and is @@ -185,6 +187,8 @@ namespace { same \a id as long as the \a context is different. In this case a trigger of the actual shortcut is forwarded to the registered QShortcut for the currently active context. + A scriptable shortcut can be called from a script without the need for the user + to interact with it. */ /*! @@ -341,14 +345,15 @@ ActionContainer *ActionManagerPrivate::createMenuBar(const Id &id) return mbc; } -Command *ActionManagerPrivate::registerAction(QAction *action, const Id &id, const Context &context) +Command *ActionManagerPrivate::registerAction(QAction *action, const Id &id, const Context &context, bool scriptable) { Action *a = 0; Command *c = registerOverridableAction(action, id, false); a = static_cast<Action *>(c); if (a) - a->addOverrideAction(action, context); + a->addOverrideAction(action, context, scriptable); emit commandListChanged(); + emit commandAdded(id); return a; } @@ -417,7 +422,7 @@ void ActionManagerPrivate::unregisterAction(QAction *action, const Id &id) emit commandListChanged(); } -Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const Id &id, const Context &context) +Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const Id &id, const Context &context, bool scriptable) { Shortcut *sc = 0; int uid = UniqueIDManager::instance()->uniqueIdentifier(id); @@ -442,6 +447,7 @@ Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const Id &i shortcut->setObjectName(id); shortcut->setParent(m_mainWnd); sc->setShortcut(shortcut); + sc->setScriptable(scriptable); if (context.isEmpty()) sc->setContext(Context(0)); @@ -449,6 +455,7 @@ Command *ActionManagerPrivate::registerShortcut(QShortcut *shortcut, const Id &i sc->setContext(context); emit commandListChanged(); + emit commandAdded(id); return sc; } diff --git a/src/plugins/coreplugin/actionmanager/actionmanager.h b/src/plugins/coreplugin/actionmanager/actionmanager.h index 3242f7d7921d11ccb356a7eb3b35be324c5f6642..82a92e0ecd22b893a31a70c0822ecac7d2921e6f 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager.h +++ b/src/plugins/coreplugin/actionmanager/actionmanager.h @@ -62,8 +62,8 @@ public: virtual ActionContainer *createMenu(const Id &id) = 0; virtual ActionContainer *createMenuBar(const Id &id) = 0; - virtual Command *registerAction(QAction *action, const Id &id, const Context &context) = 0; - virtual Command *registerShortcut(QShortcut *shortcut, const Id &id, const Context &context) = 0; + virtual Command *registerAction(QAction *action, const Id &id, const Context &context, bool scriptable = false) = 0; + virtual Command *registerShortcut(QShortcut *shortcut, const Id &id, const Context &context, bool scriptable = false) = 0; virtual Command *command(const Id &id) const = 0; virtual ActionContainer *actionContainer(const Id &id) const = 0; @@ -74,6 +74,7 @@ public: signals: void commandListChanged(); + void commandAdded(const QString &id); }; } // namespace Core diff --git a/src/plugins/coreplugin/actionmanager/actionmanager_p.h b/src/plugins/coreplugin/actionmanager/actionmanager_p.h index 2f5186a82bd598fe79b5e4a2f569953dd507a807..a281f326fcd4c4046877368b6054f730df8866d2 100644 --- a/src/plugins/coreplugin/actionmanager/actionmanager_p.h +++ b/src/plugins/coreplugin/actionmanager/actionmanager_p.h @@ -89,9 +89,9 @@ public: ActionContainer *createMenuBar(const Id &id); Command *registerAction(QAction *action, const Id &id, - const Context &context); + const Context &context, bool scriptable=false); Command *registerShortcut(QShortcut *shortcut, const Id &id, - const Context &context); + const Context &context, bool scriptable=false); Core::Command *command(const Id &id) const; Core::ActionContainer *actionContainer(const Id &id) const; diff --git a/src/plugins/coreplugin/actionmanager/command.cpp b/src/plugins/coreplugin/actionmanager/command.cpp index bfb4c2be54cc2cf62cfbb325ce9f159977e6a686..c16004de2d6a7f9204b03a692a4acca6b9aeeda4 100644 --- a/src/plugins/coreplugin/actionmanager/command.cpp +++ b/src/plugins/coreplugin/actionmanager/command.cpp @@ -191,6 +191,19 @@ context. */ +/*! + \fn bool Command::isScriptable() const + Returns if the Command is scriptable. A scriptable command can be called + from a script without the need for the user to interact with it. +*/ + +/*! + \fn bool Command::isScriptable(const Context &) const + Returns if the Command is scriptable for the given context. + A scriptable command can be called from a script without the need for the user to + interact with it. +*/ + /*! \fn Command::~Command() \internal @@ -285,7 +298,7 @@ QString CommandPrivate::stringWithAppendedShortcut(const QString &str) const */ Shortcut::Shortcut(int id) - : CommandPrivate(id), m_shortcut(0) + : CommandPrivate(id), m_shortcut(0), m_scriptable(false) { } @@ -363,6 +376,21 @@ bool Shortcut::isActive() const return m_shortcut->isEnabled(); } +bool Shortcut::isScriptable() const +{ + return m_scriptable; +} + +bool Shortcut::isScriptable(const Core::Context &) const +{ + return m_scriptable; +} + +void Shortcut::setScriptable(bool value) +{ + m_scriptable = value; +} + // ---------- Action ------------ /*! @@ -485,7 +513,7 @@ static inline QString msgActionWarning(QAction *newAction, int k, QAction *oldAc return msg; } -void Action::addOverrideAction(QAction *action, const Core::Context &context) +void Action::addOverrideAction(QAction *action, const Core::Context &context, bool scriptable) { if (context.isEmpty()) { m_contextActionMap.insert(0, action); @@ -497,6 +525,7 @@ void Action::addOverrideAction(QAction *action, const Core::Context &context) m_contextActionMap.insert(k, action); } } + m_scriptableMap[action] = scriptable; } void Action::removeOverrideAction(QAction *action) @@ -558,3 +587,21 @@ bool Action::isEmpty() const return m_contextActionMap.isEmpty(); } +bool Action::isScriptable() const +{ + return m_scriptableMap.values().contains(true); +} + +bool Action::isScriptable(const Core::Context &context) const +{ + if (context == m_context && m_scriptableMap.contains(m_currentAction)) + return m_scriptableMap.value(m_currentAction); + + for (int i = 0; i < context.size(); ++i) { + if (QAction *a = m_contextActionMap.value(context.at(i), 0)) { + if (m_scriptableMap.contains(a) && m_scriptableMap.value(a)) + return true; + } + } + return false; +} diff --git a/src/plugins/coreplugin/actionmanager/command.h b/src/plugins/coreplugin/actionmanager/command.h index f3e2f1a99c6573b0655c48e733b937184010e4be..96d6ef654b652f74e8912b4cd8d6ba387249fb7d 100644 --- a/src/plugins/coreplugin/actionmanager/command.h +++ b/src/plugins/coreplugin/actionmanager/command.h @@ -85,6 +85,9 @@ public: virtual QString stringWithAppendedShortcut(const QString &str) const = 0; + virtual bool isScriptable() const = 0; + virtual bool isScriptable(const Context &) const = 0; + signals: void keySequenceChanged(); void activeStateChanged(); diff --git a/src/plugins/coreplugin/actionmanager/command_p.h b/src/plugins/coreplugin/actionmanager/command_p.h index 1922be731c8d0cc10fdef91779853ba258bb37c9..17b969a81aab8ad6d345f78fd3fb9d20675d0290 100644 --- a/src/plugins/coreplugin/actionmanager/command_p.h +++ b/src/plugins/coreplugin/actionmanager/command_p.h @@ -40,6 +40,7 @@ #include <QtCore/QList> #include <QtCore/QMultiMap> #include <QtCore/QPointer> +#include <QtCore/QMap> #include <QtGui/QKeySequence> namespace Core { @@ -109,9 +110,15 @@ public: bool setCurrentContext(const Context &context); bool isActive() const; + + bool isScriptable() const; + bool isScriptable(const Context &) const; + void setScriptable(bool value); + private: QShortcut *m_shortcut; QString m_defaultText; + bool m_scriptable; }; class Action : public CommandPrivate @@ -133,10 +140,13 @@ public: bool setCurrentContext(const Context &context); bool isActive() const; - void addOverrideAction(QAction *action, const Context &context); + void addOverrideAction(QAction *action, const Context &context, bool scriptable); void removeOverrideAction(QAction *action); bool isEmpty() const; + bool isScriptable() const; + bool isScriptable(const Context &context) const; + protected: void updateToolTipWithKeySequence(); @@ -152,6 +162,7 @@ private: QPointer<QAction> m_currentAction; QMap<int, QPointer<QAction> > m_contextActionMap; + QMap<QAction*, bool> m_scriptableMap; bool m_active; bool m_contextInitialized; }; diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index 3d12695e50c1a8f1933ea05b28b30aaaa3872bc6..90de435e5c3c9bea76d2a8ae52d8672a5bb8469e 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -311,7 +311,7 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) : mwindow->addAction(cmd, Constants::G_WINDOW_NAVIGATE); // Close Action - cmd = am->registerAction(m_d->m_closeCurrentEditorAction, Constants::CLOSE, editManagerContext); + cmd = am->registerAction(m_d->m_closeCurrentEditorAction, Constants::CLOSE, editManagerContext, true); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+W"))); cmd->setAttribute(Core::Command::CA_UpdateText); cmd->setDefaultText(m_d->m_closeCurrentEditorAction->text()); @@ -328,13 +328,13 @@ EditorManager::EditorManager(ICore *core, QWidget *parent) : #endif // Close All Action - cmd = am->registerAction(m_d->m_closeAllEditorsAction, Constants::CLOSEALL, editManagerContext); + cmd = am->registerAction(m_d->m_closeAllEditorsAction, Constants::CLOSEALL, editManagerContext, true); cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+W"))); mfile->addAction(cmd, Constants::G_FILE_CLOSE); connect(m_d->m_closeAllEditorsAction, SIGNAL(triggered()), this, SLOT(closeAllEditors())); // Close All Others Action - cmd = am->registerAction(m_d->m_closeOtherEditorsAction, Constants::CLOSEOTHERS, editManagerContext); + cmd = am->registerAction(m_d->m_closeOtherEditorsAction, Constants::CLOSEOTHERS, editManagerContext, true); mfile->addAction(cmd, Constants::G_FILE_CLOSE); cmd->setAttribute(Core::Command::CA_UpdateText); connect(m_d->m_closeOtherEditorsAction, SIGNAL(triggered()), this, SLOT(closeOtherEditors())); diff --git a/src/plugins/cppeditor/cppplugin.cpp b/src/plugins/cppeditor/cppplugin.cpp index 5ebaf47801e4a7b4772472de06881e46087a50a5..4935b912830a39b4e20560695faf426422c79180 100644 --- a/src/plugins/cppeditor/cppplugin.cpp +++ b/src/plugins/cppeditor/cppplugin.cpp @@ -254,7 +254,7 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess QAction *jumpToDefinition = new QAction(tr("Follow Symbol Under Cursor"), this); cmd = am->registerAction(jumpToDefinition, - Constants::JUMP_TO_DEFINITION, context); + Constants::JUMP_TO_DEFINITION, context, true); cmd->setDefaultKeySequence(QKeySequence(Qt::Key_F2)); connect(jumpToDefinition, SIGNAL(triggered()), this, SLOT(jumpToDefinition())); @@ -263,7 +263,7 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess QAction *switchDeclarationDefinition = new QAction(tr("Switch Between Method Declaration/Definition"), this); cmd = am->registerAction(switchDeclarationDefinition, - Constants::SWITCH_DECLARATION_DEFINITION, context); + Constants::SWITCH_DECLARATION_DEFINITION, context, true); cmd->setDefaultKeySequence(QKeySequence("Shift+F2")); connect(switchDeclarationDefinition, SIGNAL(triggered()), this, SLOT(switchDeclarationDefinition())); diff --git a/src/plugins/cpptools/cpptoolsplugin.cpp b/src/plugins/cpptools/cpptoolsplugin.cpp index 947675e624d7154d3cd6ee0353ec97e1cfd6c5df..fcfc4f5cdcad370f235e87048c7e3b5c01574f35 100644 --- a/src/plugins/cpptools/cpptoolsplugin.cpp +++ b/src/plugins/cpptools/cpptoolsplugin.cpp @@ -137,7 +137,7 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error) Core::Context context(CppEditor::Constants::C_CPPEDITOR); QAction *switchAction = new QAction(tr("Switch Header/Source"), this); - Core::Command *command = am->registerAction(switchAction, Constants::SWITCH_HEADER_SOURCE, context); + Core::Command *command = am->registerAction(switchAction, Constants::SWITCH_HEADER_SOURCE, context, true); command->setDefaultKeySequence(QKeySequence(Qt::Key_F4)); mcpptools->addAction(command); connect(switchAction, SIGNAL(triggered()), this, SLOT(switchHeaderSource())); diff --git a/src/plugins/macros/Macros.pluginspec.in b/src/plugins/macros/Macros.pluginspec.in new file mode 100644 index 0000000000000000000000000000000000000000..a7ca5bc8c7155cc7521e530ea5fc35d85138c5eb --- /dev/null +++ b/src/plugins/macros/Macros.pluginspec.in @@ -0,0 +1,22 @@ +<plugin name=\"Macros\" version=\"$$QTCREATOR_VERSION\" compatVersion=\"$$QTCREATOR_VERSION\"> + <vendor>Nokia Corporation</vendor> + <copyright>(C) 2010 Nicolas Arnaud-Cormos</copyright> + <license> +Commercial Usage + +Licensees holding valid Qt Commercial licenses may use this plugin in accordance with the Qt Commercial License Agreement provided with the Software or, alternatively, in accordance with the terms contained in a written agreement between you and Nokia. + +GNU Lesser General Public License Usage + +Alternatively, this plugin may be used under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation. 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. + </license> + <category>Qt Creator</category> + <description>Macros in text editors.</description> + <url>http://qt.nokia.com</url> + <dependencyList> + <dependency name=\"Core\" version=\"$$QTCREATOR_VERSION\"/> + <dependency name=\"Locator\" version=\"$$QTCREATOR_VERSION\"/> + <dependency name=\"Find\" version=\"$$QTCREATOR_VERSION\"/> + <dependency name=\"TextEditor\" version=\"$$QTCREATOR_VERSION\"/> + </dependencyList> +</plugin> diff --git a/src/plugins/macros/actionmacrohandler.cpp b/src/plugins/macros/actionmacrohandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..985f284d51f9bc7cd7049f6e8a82ac3e476bc7ee --- /dev/null +++ b/src/plugins/macros/actionmacrohandler.cpp @@ -0,0 +1,139 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "actionmacrohandler.h" +#include "macroevent.h" +#include "macro.h" + +#include <texteditor/texteditorconstants.h> + +#include <coreplugin/icore.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/command.h> +#include <coreplugin/coreconstants.h> +#include <coreplugin/uniqueidmanager.h> +#include <coreplugin/icontext.h> + +#include <QObject> +#include <QEvent> +#include <QAction> +#include <QSignalMapper> +#include <QShortcut> +#include <QtAlgorithms> +#include <QStringList> + +using namespace Macros; +using namespace Macros::Internal; + + +static const char EVENTNAME[] = "Action"; +static quint8 ACTIONNAME = 0; + +ActionMacroHandler::ActionMacroHandler(): + m_mapper(new QSignalMapper(this)) +{ + connect(m_mapper, SIGNAL(mapped(const QString &)), + this, SLOT(addActionEvent(const QString &))); + + const Core::ICore *core = Core::ICore::instance(); + const Core::ActionManager *am = core->actionManager(); + connect(am, SIGNAL(commandAdded(QString)), + this, SLOT(addCommand(QString))); + + // Register all existing scriptable actions + QList<Core::Command *> commands = am->commands(); + foreach (Core::Command *command, commands) { + if (command->isScriptable()) { + QString id = Core::UniqueIDManager::instance()->stringForUniqueIdentifier(command->id()); + registerCommand(id); + } + } +} + +bool ActionMacroHandler::canExecuteEvent(const MacroEvent ¯oEvent) +{ + return (macroEvent.id() == EVENTNAME); +} + +bool ActionMacroHandler::executeEvent(const MacroEvent ¯oEvent) +{ + const Core::ICore *core = Core::ICore::instance(); + const Core::ActionManager *am = core->actionManager(); + + QAction *action = am->command(macroEvent.value(ACTIONNAME).toString())->action(); + if (!action) + return false; + + action->trigger(); + return true; +} + +void ActionMacroHandler::addActionEvent(const QString &id) +{ + if (!isRecording()) + return; + + const Core::ICore *core = Core::ICore::instance(); + const Core::ActionManager *am = core->actionManager(); + const Core::Command *cmd = am->command(id); + if (cmd->isScriptable(cmd->context())) { + MacroEvent e; + e.setId(EVENTNAME); + e.setValue(ACTIONNAME, id); + addMacroEvent(e); + } +} + +void ActionMacroHandler::registerCommand(const QString &id) +{ + if (!m_commandIds.contains(id)) { + m_commandIds.insert(id); + const Core::ICore *core = Core::ICore::instance(); + const Core::ActionManager *am = core->actionManager(); + QAction* action = am->command(id)->action(); + if (action) { + connect(action, SIGNAL(triggered()), m_mapper, SLOT(map())); + m_mapper->setMapping(action, id); + return; + } + QShortcut* shortcut = am->command(id)->shortcut(); + if (shortcut) { + connect(shortcut, SIGNAL(activated()), m_mapper, SLOT(map())); + m_mapper->setMapping(shortcut, id); + } + } +} + +void ActionMacroHandler::addCommand(const QString &id) +{ + const Core::ICore *core = Core::ICore::instance(); + const Core::ActionManager *am = core->actionManager(); + if (am->command(id)->isScriptable()) + registerCommand(id); +} diff --git a/src/plugins/macros/actionmacrohandler.h b/src/plugins/macros/actionmacrohandler.h new file mode 100644 index 0000000000000000000000000000000000000000..29386767e6c516a4e8941ff711a662c1ac4a4d79 --- /dev/null +++ b/src/plugins/macros/actionmacrohandler.h @@ -0,0 +1,68 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_ACTIONEVENTHANDLER_H +#define MACROSPLUGIN_ACTIONEVENTHANDLER_H + +#include "imacrohandler.h" + +#include <QSet> + +class QAction; +class QSignalMapper; + +namespace Macros { +namespace Internal { + +class ActionMacroHandler : public IMacroHandler +{ + Q_OBJECT + +public: + ActionMacroHandler(); + + bool canExecuteEvent(const MacroEvent ¯oEvent); + bool executeEvent(const MacroEvent ¯oEvent); + +private: + void registerCommand(const QString &id); + +private slots: + void addCommand(const QString &id); + void addActionEvent(const QString &id); + +private: + QSet<QString> m_commandIds; + QSignalMapper *m_mapper; +}; + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_ACTIONEVENTHANDLER_H diff --git a/src/plugins/macros/findmacrohandler.cpp b/src/plugins/macros/findmacrohandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c1e920b8c793bf4939e96b19c9efcbdb02bcca57 --- /dev/null +++ b/src/plugins/macros/findmacrohandler.cpp @@ -0,0 +1,231 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "findmacrohandler.h" +#include "macroevent.h" +#include "macro.h" +#include "macrotextfind.h" + +#include <find/ifindsupport.h> + +#include <coreplugin/icore.h> +#include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/editormanager/ieditor.h> + +#include <aggregation/aggregate.h> + +using namespace Macros; +using namespace Macros::Internal; + +static const char EVENTNAME[] = "Find"; +static const quint8 TYPE = 0; +static const quint8 BEFORE = 1; +static const quint8 AFTER = 2; +static const quint8 FLAGS = 3; + +static const quint8 FINDINCREMENTAL = 0; +static const quint8 FINDSTEP = 1; +static const quint8 REPLACE = 2; +static const quint8 REPLACESTEP = 3; +static const quint8 REPLACEALL = 4; +static const quint8 RESET = 5; + + +FindMacroHandler::FindMacroHandler(): + IMacroHandler() +{ + const Core::EditorManager *editorManager = Core::EditorManager::instance(); + connect(editorManager, SIGNAL(currentEditorChanged(Core::IEditor*)), + this, SLOT(changeEditor(Core::IEditor*))); +} + +bool FindMacroHandler::canExecuteEvent(const MacroEvent ¯oEvent) +{ + return (macroEvent.id() == EVENTNAME); +} + +bool FindMacroHandler::executeEvent(const MacroEvent ¯oEvent) +{ + Core::IEditor *editor = Core::EditorManager::instance()->currentEditor(); + if (!editor) + return false; + + Aggregation::Aggregate *aggregate = Aggregation::Aggregate::parentAggregate(editor->widget()); + if (!aggregate) + return false; + + Find::IFindSupport *currentFind = aggregate->component<Find::IFindSupport>(); + if (!currentFind) + return false; + + switch (macroEvent.value(TYPE).toInt()) { + case FINDINCREMENTAL: + currentFind->findIncremental(macroEvent.value(BEFORE).toString(), + (Find::FindFlags)macroEvent.value(FLAGS).toInt()); + break; + case FINDSTEP: + currentFind->findStep(macroEvent.value(BEFORE).toString(), + (Find::FindFlags)macroEvent.value(FLAGS).toInt()); + break; + case REPLACE: + currentFind->replace(macroEvent.value(BEFORE).toString(), + macroEvent.value(AFTER).toString(), + (Find::FindFlags)macroEvent.value(FLAGS).toInt()); + case REPLACESTEP: + currentFind->replaceStep(macroEvent.value(BEFORE).toString(), + macroEvent.value(AFTER).toString(), + (Find::FindFlags)macroEvent.value(FLAGS).toInt()); + break; + case REPLACEALL: + currentFind->replaceAll(macroEvent.value(BEFORE).toString(), + macroEvent.value(AFTER).toString(), + (Find::FindFlags)macroEvent.value(FLAGS).toInt()); + break; + case RESET: + currentFind->resetIncrementalSearch(); + break; + } + return true; +} + +void FindMacroHandler::findIncremental(const QString &txt, Find::FindFlags findFlags) +{ + if (!isRecording()) + return; + MacroEvent e; + e.setId(EVENTNAME); + e.setValue(BEFORE, txt); + e.setValue(FLAGS, (int)findFlags); + e.setValue(TYPE, FINDINCREMENTAL); + addMacroEvent(e); +} + +void FindMacroHandler::findStep(const QString &txt, Find::FindFlags findFlags) +{ + if (!isRecording()) + return; + MacroEvent e; + e.setId(EVENTNAME); + e.setValue(BEFORE, txt); + e.setValue(FLAGS, (int)findFlags); + e.setValue(TYPE, FINDSTEP); + addMacroEvent(e); +} + +void FindMacroHandler::replace(const QString &before, const QString &after, Find::FindFlags findFlags) +{ + if (!isRecording()) + return; + MacroEvent e; + e.setId(EVENTNAME); + e.setValue(BEFORE, before); + e.setValue(AFTER, after); + e.setValue(FLAGS, (int)findFlags); + e.setValue(TYPE, REPLACE); + addMacroEvent(e); +} + +void FindMacroHandler::replaceStep(const QString &before, const QString &after, Find::FindFlags findFlags) +{ + if (!isRecording()) + return; + MacroEvent e; + e.setId(EVENTNAME); + e.setValue(BEFORE, before); + e.setValue(AFTER, after); + e.setValue(FLAGS, (int)findFlags); + e.setValue(TYPE, REPLACESTEP); + addMacroEvent(e); +} + +void FindMacroHandler::replaceAll(const QString &before, const QString &after, Find::FindFlags findFlags) +{ + if (!isRecording()) + return; + MacroEvent e; + e.setId(EVENTNAME); + e.setValue(BEFORE, before); + e.setValue(AFTER, after); + e.setValue(FLAGS, (int)findFlags); + e.setValue(TYPE, REPLACEALL); + addMacroEvent(e); +} + +void FindMacroHandler::resetIncrementalSearch() +{ + if (!isRecording()) + return; + MacroEvent e; + e.setId(EVENTNAME); + e.setValue(TYPE, RESET); + addMacroEvent(e); +} + + +void FindMacroHandler::changeEditor(Core::IEditor *editor) +{ + if (!isRecording() || !editor || !editor->widget()) + return; + + Aggregation::Aggregate *aggregate = Aggregation::Aggregate::parentAggregate(editor->widget()); + if (aggregate) { + Find::IFindSupport *currentFind = aggregate->component<Find::IFindSupport>(); + if (currentFind) { + MacroTextFind *macroFind = qobject_cast<MacroTextFind *>(currentFind); + if (macroFind) + return; + + aggregate->remove(currentFind); + macroFind = new MacroTextFind(currentFind); + aggregate->add(macroFind); + + // Connect all signals + connect(macroFind, SIGNAL(allReplaced(QString,QString,Find::FindFlags)), + this, SLOT(replaceAll(QString,QString,Find::FindFlags))); + connect(macroFind, SIGNAL(incrementalFound(QString,Find::FindFlags)), + this, SLOT(findIncremental(QString,Find::FindFlags))); + connect(macroFind, SIGNAL(incrementalSearchReseted()), + this, SLOT(resetIncrementalSearch())); + connect(macroFind, SIGNAL(replaced(QString,QString,Find::FindFlags)), + this, SLOT(replace(QString,QString,Find::FindFlags))); + connect(macroFind, SIGNAL(stepFound(QString,Find::FindFlags)), + this, SLOT(findStep(QString,Find::FindFlags))); + connect(macroFind, SIGNAL(stepReplaced(QString,QString,Find::FindFlags)), + this, SLOT(replaceStep(QString,QString,Find::FindFlags))); + } + } +} + +void FindMacroHandler::startRecording(Macros::Macro* macro) +{ + IMacroHandler::startRecording(macro); + const Core::EditorManager *editorManager = Core::EditorManager::instance(); + if (editorManager->currentEditor()) + changeEditor(editorManager->currentEditor()); +} diff --git a/src/plugins/macros/findmacrohandler.h b/src/plugins/macros/findmacrohandler.h new file mode 100644 index 0000000000000000000000000000000000000000..957a08af37e809396dddbb13aa0ffd37cfb6e88c --- /dev/null +++ b/src/plugins/macros/findmacrohandler.h @@ -0,0 +1,71 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_FINDEVENTHANDLER_H +#define MACROSPLUGIN_FINDEVENTHANDLER_H + +#include "imacrohandler.h" + +#include <find/textfindconstants.h> + +namespace Core { +class IEditor; +} + +namespace Macros { +namespace Internal { + +class FindMacroHandler : public IMacroHandler +{ + Q_OBJECT + +public: + FindMacroHandler(); + + void startRecording(Macros::Macro* macro); + + bool canExecuteEvent(const Macros::MacroEvent ¯oEvent); + bool executeEvent(const Macros::MacroEvent ¯oEvent); + +public slots: + void findIncremental(const QString &txt, Find::FindFlags findFlags); + void findStep(const QString &txt, Find::FindFlags findFlags); + void replace(const QString &before, const QString &after, Find::FindFlags findFlags); + void replaceStep(const QString &before, const QString &after, Find::FindFlags findFlags); + void replaceAll(const QString &before, const QString &after, Find::FindFlags findFlags); + void resetIncrementalSearch(); + +private slots: + void changeEditor(Core::IEditor *editor); +}; + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_FINDEVENTHANDLER_H diff --git a/src/plugins/macros/imacrohandler.cpp b/src/plugins/macros/imacrohandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5f6836971372231c716ba8b1247c5823de477bf --- /dev/null +++ b/src/plugins/macros/imacrohandler.cpp @@ -0,0 +1,124 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "imacrohandler.h" + +#include "macro.h" + +using namespace Macros; + +/*! + \class Macro::IEventHandler + \brief Base class for all macro event handlers. + + An event handler is used to handle a specific type of macro events. + They are used to create and replay macro events, use MacroManager::registerEventHandler + to add a new event handler. +*/ + +/*! + \fn void IEventHandler::startRecording(Macro* macro) + + This method is called when starting to record a macro, it can be used + to initialize some data. +*/ + +/*! + \fn void IEventHandler::endRecordingMacro(Macro* macro) + + This method is called after recording a macro, to cleanup everything. +*/ + +/*! + \fn bool IEventHandler::canExecuteEvent(const MacroEvent ¯oEvent) + + When replaying a macro, the manager iterate through all macro events + in the macro and call this method to know which handler to use. + If the method returns true, executeEvent is called. +*/ + +/*! + \fn bool IEventHandler::executeEvent(const MacroEvent ¯oEvent) + + This method execute a specific macro event, using the values stored in + the macro event. +*/ + +class IMacroHandler::IMacroHandlerPrivate +{ +public: + IMacroHandlerPrivate(); + + Macro *currentMacro; +}; + +IMacroHandler::IMacroHandlerPrivate::IMacroHandlerPrivate() : + currentMacro(0) +{ +} + + +// ---------- IMacroHandler ------------ + +IMacroHandler::IMacroHandler(): + d(new IMacroHandlerPrivate) +{ +} + +IMacroHandler::~IMacroHandler() +{ + delete d; +} + +void IMacroHandler::startRecording(Macro* macro) +{ + d->currentMacro = macro; +} + +void IMacroHandler::endRecordingMacro(Macro* macro) +{ + Q_UNUSED(macro) + d->currentMacro = 0; +} + +void IMacroHandler::addMacroEvent(const MacroEvent& event) +{ + if (d->currentMacro) + d->currentMacro->append(event); +} + +void IMacroHandler::setCurrentMacro(Macro *macro) +{ + d->currentMacro = macro; +} + +bool IMacroHandler::isRecording() const +{ + return d->currentMacro != 0; +} diff --git a/src/plugins/macros/imacrohandler.h b/src/plugins/macros/imacrohandler.h new file mode 100644 index 0000000000000000000000000000000000000000..81c65fdb00c70a4517643d5498234fef13c30acf --- /dev/null +++ b/src/plugins/macros/imacrohandler.h @@ -0,0 +1,70 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_IMACROHANDLER_H +#define MACROSPLUGIN_IMACROHANDLER_H + +#include "macros_global.h" +#include <QObject> + +namespace Macros { + +class Macro; +class MacroEvent; +class MacroManager; + +class MACROS_EXPORT IMacroHandler: public QObject +{ +public: + IMacroHandler(); + virtual ~IMacroHandler(); + + virtual void startRecording(Macro* macro); + virtual void endRecordingMacro(Macro* macro); + + virtual bool canExecuteEvent(const MacroEvent ¯oEvent) = 0; + virtual bool executeEvent(const MacroEvent ¯oEvent) = 0; + +protected: + void addMacroEvent(const MacroEvent& event); + + void setCurrentMacro(Macro *macro); + + bool isRecording() const; + +private: + friend class MacroManager; + + class IMacroHandlerPrivate; + IMacroHandlerPrivate *d; +}; + +} // namespace Macros + +#endif // MACROSPLUGIN_IMACROHANDLER_H diff --git a/src/plugins/macros/images/macro.png b/src/plugins/macros/images/macro.png new file mode 100644 index 0000000000000000000000000000000000000000..2246f308547dbfa82a4b016ad54d66c844b57f23 Binary files /dev/null and b/src/plugins/macros/images/macro.png differ diff --git a/src/plugins/macros/macro.cpp b/src/plugins/macros/macro.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d046381ae8c59b779803fc922a7c5ed78ba3edec --- /dev/null +++ b/src/plugins/macros/macro.cpp @@ -0,0 +1,203 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "macro.h" + +#include <coreplugin/coreconstants.h> + +#include <QFileInfo> + +using namespace Macros; + +/*! + \class Macros::Macro + + \brief Represents a macro, which is more or less a list of Macros::MacroEvent + + A macro is a list of events that can be replayed in Qt Creator. A macro has + an header consisting of the Qt Creator version where the macro was created + and a description. + The name of the macro is the filename without the extension. +*/ + +class Macro::MacroPrivate +{ +public: + MacroPrivate(); + + QString description; + QString version; + QString fileName; + QList<MacroEvent> events; + int shortcutId; +}; + +Macro::MacroPrivate::MacroPrivate() : + version(Core::Constants::IDE_VERSION_LONG), + shortcutId(-1) +{ +} + + + +// ---------- Macro ------------ + +Macro::Macro() : + d(new MacroPrivate) +{ +} + +Macro::Macro(const Macro &other): + d(new MacroPrivate) +{ + d->description = other.d->description; + d->version = other.d->version; + d->fileName = other.d->fileName; + d->events = other.d->events; + d->shortcutId = other.d->shortcutId; +} + +Macro::~Macro() +{ + delete d; +} + +Macro& Macro::operator=(const Macro &other) +{ + if (this == &other) + return *this; + d->description = other.d->description; + d->version = other.d->version; + d->fileName = other.d->fileName; + d->events = other.d->events; + d->shortcutId = other.d->shortcutId; + return *this; +} + +void Macro::load(QString fileName) +{ + if (d->events.count()) + return; // the macro is not empty + + // Take the current filename if the parameter is null + if (fileName.isNull()) + fileName = d->fileName; + else + d->fileName = fileName; + + // Load all the macroevents + QFile file(fileName); + if (file.open(QFile::ReadOnly)) { + QDataStream stream(&file); + stream >> d->version; + stream >> d->description; + while (!stream.atEnd()) { + MacroEvent macroEvent; + macroEvent.load(stream); + append(macroEvent); + } + } +} + +void Macro::loadHeader(const QString &fileName) +{ + d->fileName = fileName; + QFile file(fileName); + if (file.open(QFile::ReadOnly)) { + QDataStream stream(&file); + stream >> d->version; + stream >> d->description; + } +} + +void Macro::save(const QString &fileName) +{ + QFile file(fileName); + if (file.open(QFile::WriteOnly)) { + QDataStream stream(&file); + stream << d->version; + stream << d->description; + foreach (const MacroEvent &event, d->events) { + event.save(stream); + } + d->fileName = fileName; + } +} + +QString Macro::displayName() const +{ + QFileInfo fileInfo(d->fileName); + return fileInfo.baseName(); +} + +void Macro::append(const MacroEvent &event) +{ + d->events.append(event); +} + +const QString &Macro::description() const +{ + return d->description; +} + +void Macro::setDescription(const QString &text) +{ + d->description = text; +} + +const QString &Macro::version() const +{ + return d->version; +} + +const QString &Macro::fileName() const +{ + return d->fileName; +} + +const QList<MacroEvent> &Macro::events() const +{ + return d->events; +} + +void Macro::setShortcutId(int id) +{ + d->shortcutId = id; +} + +int Macro::shortcutId() const +{ + return d->shortcutId; +} + +bool Macro::isWritable() const +{ + QFileInfo fileInfo(d->fileName); + return fileInfo.exists() && fileInfo.isWritable(); +} diff --git a/src/plugins/macros/macro.h b/src/plugins/macros/macro.h new file mode 100644 index 0000000000000000000000000000000000000000..0a8bbbe35147d123cfd33fc31f1bedcdab817a16 --- /dev/null +++ b/src/plugins/macros/macro.h @@ -0,0 +1,75 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACRO_H +#define MACROSPLUGIN_MACRO_H + +#include <QList> +#include <QString> + +#include "macroevent.h" +#include "macros_global.h" + +namespace Macros { + +class MACROS_EXPORT Macro +{ +public: + Macro(); + Macro(const Macro& other); + ~Macro(); + Macro& operator=(const Macro& other); + + void load(QString fileName = QString::null); + void loadHeader(const QString &fileName); + void save(const QString &fileName); + + const QString &description() const; + void setDescription(const QString &text); + + const QString &version() const; + const QString &fileName() const; + QString displayName() const; + + void append(const MacroEvent &event); + const QList<MacroEvent> &events() const; + + void setShortcutId(int id); + int shortcutId() const; + + bool isWritable() const; + +private: + class MacroPrivate; + MacroPrivate* d; +}; + +} // namespace Macros + +#endif // MACROSPLUGIN_MACRO_H diff --git a/src/plugins/macros/macroevent.cpp b/src/plugins/macros/macroevent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..68916952a818631514de8c310ef3a45d413d8a1f --- /dev/null +++ b/src/plugins/macros/macroevent.cpp @@ -0,0 +1,135 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "macroevent.h" + +using namespace Macros; + +/*! + \class Macros::MacroEvent + \brief Represents an event in a macro + + An event stores informations so it can be replayed. An event can be: + \list + \o menu action + \o key event on an editor + \o find/replace usage + \o ... + \endlist + + The information are stored in a map of QVariants (using quint8 for keys). +*/ + +class MacroEvent::MacroEventPrivate +{ +public: + QByteArray id; + QMap<quint8, QVariant> values; +}; + + +// ---------- MacroEvent ------------ + +MacroEvent::MacroEvent(): + d(new MacroEventPrivate) +{ +} + +MacroEvent::MacroEvent(const MacroEvent &other): + d(new MacroEventPrivate) +{ + d->id = other.d->id; + d->values = other.d->values; +} + +MacroEvent::~MacroEvent() +{ + delete d; +} + +MacroEvent& MacroEvent::operator=(const MacroEvent &other) +{ + if (this == &other) + return *this; + d->id = other.d->id; + d->values = other.d->values; + return *this; +} + +QVariant MacroEvent::value(quint8 id) const +{ + if (d->values.contains(id)) + return d->values.value(id); + return QVariant(); +} + +void MacroEvent::setValue(quint8 id, const QVariant &value) +{ + d->values[id] = value; +} + +void MacroEvent::load(QDataStream &stream) +{ + stream >> d->id; + int count; + stream >> count; + quint8 id; + QVariant value; + for (int i = 0; i < count; ++i) { + stream >> id; + stream >> value; + d->values[id] = value; + } +} + +void MacroEvent::save(QDataStream &stream) const +{ + stream << d->id; + stream << d->values.count(); + QMapIterator<quint8, QVariant> i(d->values); + while (i.hasNext()) { + i.next(); + stream << i.key() << i.value(); + } +} + +const QByteArray & MacroEvent::id() const +{ + return d->id; +} + +void MacroEvent::setId(const char *id) +{ + d->id = id; +} + +QMap<quint8, QVariant> MacroEvent::values() const +{ + return d->values; +} diff --git a/src/plugins/macros/macroevent.h b/src/plugins/macros/macroevent.h new file mode 100644 index 0000000000000000000000000000000000000000..294e27fa37c1d310f4d0009da6e484d1b7fe849f --- /dev/null +++ b/src/plugins/macros/macroevent.h @@ -0,0 +1,67 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROEVENT_H +#define MACROSPLUGIN_MACROEVENT_H + +#include "macros_global.h" + +#include <QString> +#include <QVariant> +#include <QDataStream> + +namespace Macros { + +class MACROS_EXPORT MacroEvent +{ +public: + MacroEvent(); + MacroEvent(const MacroEvent &other); + virtual ~MacroEvent(); + MacroEvent& operator=(const MacroEvent &other); + + const QByteArray &id() const; + void setId(const char *id); + + QVariant value(quint8 id) const; + void setValue(quint8 id, const QVariant &value); + + QMap<quint8, QVariant> values() const; + + void load(QDataStream &stream); + void save(QDataStream &stream) const; + +private: + class MacroEventPrivate; + MacroEventPrivate* d; +}; + +} // namespace Macros + +#endif // MACROSPLUGIN_MACROEVENT_H diff --git a/src/plugins/macros/macrolocatorfilter.cpp b/src/plugins/macros/macrolocatorfilter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..78c46396770ab243ef216542f7c050c40bb1611a --- /dev/null +++ b/src/plugins/macros/macrolocatorfilter.cpp @@ -0,0 +1,88 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "macrolocatorfilter.h" +#include "macromanager.h" +#include "macro.h" + +#include <coreplugin/icore.h> +#include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/editormanager/ieditor.h> + +#include <QPixmap> + +using namespace Macros; +using namespace Macros::Internal; + +MacroLocatorFilter::MacroLocatorFilter(): + m_icon(QPixmap(":/macros/images/macro.png")) +{ + setShortcutString("rm"); +} + +MacroLocatorFilter::~MacroLocatorFilter() +{ +} + +QList<Locator::FilterEntry> MacroLocatorFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry) +{ + Q_UNUSED(future) + QList<Locator::FilterEntry> result; + + const QMap<QString, Macro*> ¯os = MacroManager::instance()->macros(); + QMapIterator<QString, Macro*> it(macros); + + while (it.hasNext()) { + it.next(); + QString name = it.key(); + + if (name.contains(entry)) { + QVariant id; + Locator::FilterEntry entry(this, it.key(), id, m_icon); + entry.extraInfo = it.value()->description(); + result.append(entry); + } + } + return result; +} + +void MacroLocatorFilter::accept(Locator::FilterEntry selection) const +{ + // Give the focus back to the editor + Core::IEditor *editor = Core::EditorManager::instance()->currentEditor(); + if (editor) + editor->widget()->setFocus(Qt::OtherFocusReason); + + MacroManager::instance()->executeMacro(selection.displayName); +} + +void MacroLocatorFilter::refresh(QFutureInterface<void> &future) +{ + Q_UNUSED(future) +} diff --git a/src/plugins/macros/macrolocatorfilter.h b/src/plugins/macros/macrolocatorfilter.h new file mode 100644 index 0000000000000000000000000000000000000000..d83bc2283359c97d62a89629be29a613920d05b6 --- /dev/null +++ b/src/plugins/macros/macrolocatorfilter.h @@ -0,0 +1,66 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROLOCATORFILTER_H +#define MACROSPLUGIN_MACROLOCATORFILTER_H + +#include <locator/ilocatorfilter.h> + +#include <QIcon> + +namespace Macros { + +class MacroManager; + +namespace Internal { + +class MacroLocatorFilter : public Locator::ILocatorFilter +{ + Q_OBJECT + +public: + MacroLocatorFilter(); + ~MacroLocatorFilter(); + + QString displayName() const { return tr("Macros"); } + QString id() const { return QLatin1String("Macros"); } + Priority priority() const { return Medium; } + + QList<Locator::FilterEntry> matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString &entry); + void accept(Locator::FilterEntry selection) const; + void refresh(QFutureInterface<void> &future); + +private: + QIcon m_icon; +}; + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_MACROLOCATORFILTER_H diff --git a/src/plugins/macros/macromanager.cpp b/src/plugins/macros/macromanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d4537a458e9758b75d83cb348f449e1ca7a3f1e --- /dev/null +++ b/src/plugins/macros/macromanager.cpp @@ -0,0 +1,502 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "macromanager.h" + +#include "macrosconstants.h" +#include "macro.h" +#include "macrosettings.h" +#include "imacrohandler.h" +#include "savedialog.h" +#include "actionmacrohandler.h" +#include "texteditormacrohandler.h" +#include "findmacrohandler.h" + +#include <texteditor/texteditorconstants.h> + +#include <coreplugin/coreconstants.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/actionmanager/command.h> +#include <coreplugin/icore.h> +#include <coreplugin/uniqueidmanager.h> +#include <coreplugin/icontext.h> +#include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/editormanager/ieditor.h> + +#include <QDir> +#include <QFile> +#include <QFileInfo> +#include <QShortcut> +#include <QKeySequence> +#include <QMainWindow> +#include <QSettings> +#include <QAction> +#include <QFileDialog> +#include <QMessageBox> +#include <QSignalMapper> +#include <QList> + +using namespace Macros; +using namespace Macros::Internal; + +/*! + \namespace Macros + \brief The Macros namespace contains support for macros in Qt Creator. +*/ + +/*! + + \class Macro::MacroManager + \brief Manager for macros. + + The MacroManager manage all macros, it loads them on startup, keep track of the + current macro and create new macros. + + There are two important methods in this class that can be used outside the Macros plugin: + \list + \o registerEventHandler: add a new event handler + \o registerAction: add a macro event when this action is triggered + \endlist + + This class is a singleton and can be accessed using the instance method. +*/ + +/*! + \fn void registerAction(QAction *action, const QString &id) + + Append this action to the list of actions registered in a macro. The id is + the action id passed to the ActionManager. +*/ + +class Macros::MacroManager::MacroManagerPrivate +{ +public: + MacroManagerPrivate(MacroManager *qq); + + MacroManager *q; + MacroSettings settings; + QMap<QString, Macro *> macros; + Macro *currentMacro; + bool isRecording; + + QList<IMacroHandler*> handlers; + + QSignalMapper *mapper; + QMap<int, QShortcut *> shortcuts; + int currentId; + + ActionMacroHandler *actionHandler; + TextEditorMacroHandler *textEditorHandler; + FindMacroHandler *findHandler; + + void init(); + void appendDirectory(const QString &directory); + void removeDirectory(const QString &directory); + void addMacro(Macro *macro); + void removeMacro(const QString &name); + void changeMacroDescription(Macro *macro, const QString &description); + + int addShortcut(Macro *macro, int id=-1); + void removeShortcut(Macro *macro); + + bool executeMacro(Macro *macro); + void showSaveDialog(); +}; + +MacroManager::MacroManagerPrivate::MacroManagerPrivate(MacroManager *qq): + q(qq), + currentMacro(0), + isRecording(false), + mapper(new QSignalMapper(qq)), + currentId(0) +{ + settings.fromSettings(Core::ICore::instance()->settings()); + + connect(mapper, SIGNAL(mapped(QString)), q, SLOT(executeMacro(QString))); + + // Load/unload macros + foreach (const QString &dir, settings.directories) + appendDirectory(dir); + + actionHandler = new ActionMacroHandler; + textEditorHandler = new TextEditorMacroHandler; + findHandler = new FindMacroHandler; +} + +void MacroManager::MacroManagerPrivate::appendDirectory(const QString &directory) +{ + macros.clear(); + QDir dir(directory); + QStringList filter; + filter << QString("*.")+Constants::M_EXTENSION; + QStringList files = dir.entryList(filter, QDir::Files); + + foreach (const QString &name, files) { + QString fileName = dir.absolutePath()+"/"+name; + Macro *macro = new Macro; + macro->loadHeader(fileName); + addMacro(macro); + + // Create shortcut + if (settings.shortcutIds.contains(macro->displayName())) { + int id = settings.shortcutIds.value(macro->displayName()).toInt(); + addShortcut(macro, id); + } + } +} + +void MacroManager::MacroManagerPrivate::removeDirectory(const QString &directory) +{ + QMapIterator<QString, Macro *> it(macros); + QDir dir(directory); + QStringList removeList; + while (it.hasNext()) { + it.next(); + QFileInfo fileInfo(it.value()->fileName()); + if (fileInfo.absoluteDir() == dir.absolutePath()) + removeList.append(it.key()); + } + foreach (const QString &name, removeList) + removeMacro(name); +} + +void MacroManager::MacroManagerPrivate::addMacro(Macro *macro) +{ + macros[macro->displayName()] = macro; +} + +void MacroManager::MacroManagerPrivate::removeMacro(const QString &name) +{ + if (!macros.contains(name)) + return; + Macro *macro = macros.take(name); + removeShortcut(macro); + delete macro; +} + +void MacroManager::MacroManagerPrivate::changeMacroDescription(Macro *macro, const QString &description) +{ + macro->load(); + macro->setDescription(description); + macro->save(macro->fileName()); +} + +int MacroManager::MacroManagerPrivate::addShortcut(Macro *macro, int id) +{ + if (id==-1) + id=currentId; + QShortcut *shortcut=0; + if (shortcuts.contains(id)) { + shortcut = shortcuts.value(id); + } else { + Core::Context context(TextEditor::Constants::C_TEXTEDITOR); + Core::ICore *core = Core::ICore::instance(); + Core::ActionManager *am = core->actionManager(); + shortcut = new QShortcut(core->mainWindow()); + connect(shortcut, SIGNAL(activated()), mapper, SLOT(map())); + const QString macroId = QLatin1String(Constants::SHORTCUT_MACRO) + QString("%1").arg(id, 2, 10, QLatin1Char('0')); + Core::Command *command = am->registerShortcut(shortcut, macroId, context); + + // Add a default shortcut for the 10 first shortcuts + if (id < 10) + command->setDefaultKeySequence(QKeySequence(QString(tr("Alt+R,Alt+%1").arg(id)))); + shortcuts[id] = shortcut; + } + // Update the current id (first id without shortcut) + while (shortcuts.contains(currentId)) + currentId++; + + // Assign the shortcut + macro->setShortcutId(id); + shortcut->setWhatsThis(macro->displayName()); + mapper->setMapping(shortcut, macro->displayName()); + return id; +} + +void MacroManager::MacroManagerPrivate::removeShortcut(Macro *macro) +{ + // Remove the old shortcut + if (macro->shortcutId() >= 0) { + QShortcut* shortcut = qobject_cast<QShortcut *>(mapper->mapping(macro->displayName())); + shortcut->setWhatsThis(""); + if (shortcut) + mapper->removeMappings(shortcut); + if (currentId > macro->shortcutId()) + currentId = macro->shortcutId(); + macro->setShortcutId(-1); + } +} + +bool MacroManager::MacroManagerPrivate::executeMacro(Macro *macro) +{ + macro->load(); + bool error = false; + foreach (const MacroEvent ¯oEvent, macro->events()) { + foreach (IMacroHandler *handler, handlers) { + if (handler->canExecuteEvent(macroEvent)) { + if (!handler->executeEvent(macroEvent)) + error = true; + break; + } + } + if (error) + break; + } + + if (error) { + QMessageBox::warning(Core::ICore::instance()->mainWindow(), + tr("Executing Macro"), + tr("An error occured while replaying the macro, execution stopped.")); + } + + // Set the focus back to the editor + // TODO: is it really needed?? + const Core::EditorManager *editorManager = Core::EditorManager::instance(); + if (editorManager->currentEditor()) + editorManager->currentEditor()->widget()->setFocus(Qt::OtherFocusReason); + + return !error; +} + +void MacroManager::MacroManagerPrivate::showSaveDialog() +{ + QMainWindow *mainWindow = Core::ICore::instance()->mainWindow(); + SaveDialog dialog(mainWindow); + if (dialog.exec()) { + bool changed = false; + if (settings.showSaveDialog == dialog.hideSaveDialog()) { + settings.showSaveDialog = !dialog.hideSaveDialog(); + changed = true; + } + + if (dialog.name().isEmpty()) + return; + + // Check if there's a default directory + // If not, ask a directory to the user + QString directory = settings.defaultDirectory; + QDir dir(directory); + if (directory.isEmpty() || !dir.exists()) { + directory = QFileDialog::getExistingDirectory( + mainWindow, + tr("Choose a default macro directory"), + QDir::homePath()); + if (directory.isNull()) + return; + settings.directories.append(directory); + settings.defaultDirectory= directory; + changed = true; + } + QString fileName = directory + '/' + dialog.name() + + '.' + Constants::M_EXTENSION; + currentMacro->setDescription(dialog.description()); + currentMacro->save(fileName); + addMacro(currentMacro); + + if (dialog.createShortcut()) + settings.shortcutIds[dialog.name()] = addShortcut(currentMacro); + + if (changed) + q->saveSettings(); + } +} + + +// ---------- MacroManager ------------ +MacroManager *MacroManager::m_instance = 0; + +MacroManager::MacroManager(QObject *parent) : + QObject(parent), + d(new MacroManagerPrivate(this)) +{ + registerMacroHandler(d->actionHandler); + registerMacroHandler(d->findHandler); + registerMacroHandler(d->textEditorHandler); + m_instance = this; +} + +MacroManager::~MacroManager() +{ + // Cleanup macro + QStringList macroList = d->macros.keys(); + foreach (const QString &name, macroList) + d->removeMacro(name); + + // Cleanup handlers + qDeleteAll(d->handlers); + + delete d; +} + +const MacroSettings &MacroManager::settings() const +{ + return d->settings; +} + +void MacroManager::startMacro() +{ + d->isRecording = true; + // Delete anonymous macro + if (d->currentMacro && d->currentMacro->displayName().isEmpty()) + delete d->currentMacro; + d->currentMacro = new Macro; + + Core::ActionManager *am = Core::ICore::instance()->actionManager(); + am->command(Constants::START_MACRO)->action()->setEnabled(false); + am->command(Constants::END_MACRO)->action()->setEnabled(true); + am->command(Constants::EXECUTE_LAST_MACRO)->action()->setEnabled(false); + foreach (IMacroHandler *handler, d->handlers) + handler->startRecording(d->currentMacro); + + QString endShortcut = am->command(Constants::END_MACRO)->defaultKeySequence().toString(); + QString executeShortcut = am->command(Constants::EXECUTE_LAST_MACRO)->defaultKeySequence().toString(); + QString help = tr("Macro mode. Type \"%1\" to stop recording and \"%2\" to execute it") + .arg(endShortcut).arg(executeShortcut); + Core::EditorManager::instance()->showEditorStatusBar( + QLatin1String(Constants::M_STATUS_BUFFER), + help, + tr("End Macro"), this, SLOT(endMacro())); +} + +void MacroManager::endMacro() +{ + Core::EditorManager::instance()->hideEditorStatusBar(QLatin1String(Constants::M_STATUS_BUFFER)); + + Core::ActionManager *am = Core::ICore::instance()->actionManager(); + am->command(Constants::START_MACRO)->action()->setEnabled(true); + am->command(Constants::END_MACRO)->action()->setEnabled(false); + am->command(Constants::EXECUTE_LAST_MACRO)->action()->setEnabled(true); + foreach (IMacroHandler *handler, d->handlers) + handler->endRecordingMacro(d->currentMacro); + + d->isRecording = false; + + if (d->currentMacro->events().count() && d->settings.showSaveDialog) + d->showSaveDialog(); +} + +void MacroManager::executeLastMacro() +{ + if (d->currentMacro) + d->executeMacro(d->currentMacro); +} + +bool MacroManager::executeMacro(const QString &name) +{ + // Don't execute macro while recording + if (d->isRecording || !d->macros.contains(name)) + return false; + + Macro *macro = d->macros.value(name); + if (!d->executeMacro(macro)) + return false; + + // Delete anonymous macro + if (d->currentMacro && d->currentMacro->displayName().isEmpty()) + delete d->currentMacro; + d->currentMacro = macro; + return true; +} + +void MacroManager::appendDirectory(const QString &directory) +{ + d->appendDirectory(directory); + d->settings.directories.append(directory); +} + +void MacroManager::removeDirectory(const QString &directory) +{ + d->removeDirectory(directory); + d->settings.directories.removeAll(directory); +} + +void MacroManager::setDefaultDirectory(const QString &directory) +{ + d->settings.defaultDirectory = directory; +} + +void MacroManager::showSaveDialog(bool value) +{ + d->settings.showSaveDialog = value; +} + +void MacroManager::deleteMacro(const QString &name) +{ + Macro *macro = d->macros.value(name); + if (macro) { + QString fileName = macro->fileName(); + d->removeMacro(name); + d->settings.shortcutIds.remove(name); + QFile::remove(fileName); + } +} + +const QMap<QString,Macro*> &MacroManager::macros() const +{ + return d->macros; +} + +void MacroManager::saveSettings() +{ + d->settings.toSettings(Core::ICore::instance()->settings()); +} + +void MacroManager::registerMacroHandler(IMacroHandler *handler) +{ + d->handlers.prepend(handler); +} + +MacroManager *MacroManager::instance() +{ + return m_instance; +} + +void MacroManager::changeMacro(const QString &name, const QString &description, bool shortcut) +{ + if (!d->macros.contains(name)) + return; + Macro *macro = d->macros.value(name); + + // Change description + if (macro->description() != description) + d->changeMacroDescription(macro, description); + + // Change shortcut + if ((macro->shortcutId()==-1 && !shortcut) + || (macro->shortcutId()>=0 && shortcut)) + return; + + if (shortcut) { + d->settings.shortcutIds[name] = d->addShortcut(macro); + } else { + d->removeShortcut(macro); + d->settings.shortcutIds.remove(name); + } +} diff --git a/src/plugins/macros/macromanager.h b/src/plugins/macros/macromanager.h new file mode 100644 index 0000000000000000000000000000000000000000..c5aa998e0c22cf057be07f65e4537ae553e94fd9 --- /dev/null +++ b/src/plugins/macros/macromanager.h @@ -0,0 +1,90 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROMANAGER_H +#define MACROSPLUGIN_MACROMANAGER_H + +#include <QObject> +#include <QMap> + +#include "macros_global.h" + +class QAction; + +namespace Macros { + +class Macro; +class IMacroHandler; + +namespace Internal { + class MacroSettings; + class MacroOptionsWidget; +} + +class MACROS_EXPORT MacroManager : public QObject +{ + Q_OBJECT +public: + explicit MacroManager(QObject *parent = 0); + ~MacroManager(); + + static MacroManager *instance(); + + const Internal::MacroSettings &settings() const; + const QMap<QString, Macro *> ¯os() const; + + void registerMacroHandler(IMacroHandler *handler); + +public slots: + void startMacro(); + void endMacro(); + void executeLastMacro(); + bool executeMacro(const QString &name); + +protected: + friend class Internal::MacroOptionsWidget; + + void deleteMacro(const QString &name); + void changeMacro(const QString &name, const QString &description, bool shortcut); + void appendDirectory(const QString &directory); + void removeDirectory(const QString &directory); + void setDefaultDirectory(const QString &directory); + void showSaveDialog(bool value); + void saveSettings(); + +private: + static MacroManager *m_instance; + + class MacroManagerPrivate; + MacroManagerPrivate* d; +}; + +} // namespace Macros + +#endif // MACROSPLUGIN_MACROMANAGER_H diff --git a/src/plugins/macros/macrooptionspage.cpp b/src/plugins/macros/macrooptionspage.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d1fef5d939b7ec27334d90d92722fcaf2da91e6 --- /dev/null +++ b/src/plugins/macros/macrooptionspage.cpp @@ -0,0 +1,97 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "macrooptionspage.h" + +#include "macromanager.h" +#include "macrosconstants.h" +#include "macrooptionswidget.h" + +#include <texteditor/texteditorconstants.h> + +#include <QCoreApplication> +#include <QWidget> +#include <QIcon> + +using namespace Macros; +using namespace Macros::Internal; + + +MacroOptionsPage::MacroOptionsPage(QObject *parent) + : Core::IOptionsPage(parent) +{ +} + +MacroOptionsPage::~MacroOptionsPage() +{ +} + +QString MacroOptionsPage::id() const +{ + return Constants::M_OPTIONS_PAGE; +} + +QString MacroOptionsPage::displayName() const +{ + return QCoreApplication::translate("Macro", Constants::M_OPTIONS_TR_PAGE); +} + +QString MacroOptionsPage::category() const +{ + return TextEditor::Constants::TEXT_EDITOR_SETTINGS_CATEGORY; +} + +QString MacroOptionsPage::displayCategory() const +{ + return QCoreApplication::translate("TextEditor", + TextEditor::Constants::TEXT_EDITOR_SETTINGS_TR_CATEGORY); +} + +QIcon MacroOptionsPage::categoryIcon() const +{ + return QIcon(); +} + +QWidget *MacroOptionsPage::createPage(QWidget *parent) +{ + m_widget = new MacroOptionsWidget(parent); + m_widget->setSettings(MacroManager::instance()->settings()); + return m_widget; +} + +void MacroOptionsPage::apply() +{ + if (m_widget) + m_widget->apply(); +} + +void MacroOptionsPage::finish() +{ + // Nothing to do +} diff --git a/src/plugins/macros/macrooptionspage.h b/src/plugins/macros/macrooptionspage.h new file mode 100644 index 0000000000000000000000000000000000000000..0f443da627e35eab7a85c448546be2e0cc194b32 --- /dev/null +++ b/src/plugins/macros/macrooptionspage.h @@ -0,0 +1,68 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROOPTIONSPAGE_H +#define MACROSPLUGIN_MACROOPTIONSPAGE_H + +#include "macros_global.h" + +#include <coreplugin/dialogs/ioptionspage.h> + +namespace Macros { +namespace Internal { + +class MacroOptionsWidget; + +class MACROS_EXPORT MacroOptionsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + MacroOptionsPage(QObject *parent = 0); + ~MacroOptionsPage(); + + // IOptionsPage implementation + QString id() const; + QString displayName() const; + QString category() const; + QString displayCategory() const; + QIcon categoryIcon() const; + QWidget *createPage(QWidget *parent); + + void apply(); + void finish(); + +private: + Internal::MacroOptionsWidget *m_widget; +}; + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_MACROOPTIONSPAGE_H diff --git a/src/plugins/macros/macrooptionswidget.cpp b/src/plugins/macros/macrooptionswidget.cpp new file mode 100644 index 0000000000000000000000000000000000000000..392b16206f2d90bb3275b9e07ccfd6c388139092 --- /dev/null +++ b/src/plugins/macros/macrooptionswidget.cpp @@ -0,0 +1,292 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "macrooptionswidget.h" +#include "ui_macrooptionswidget.h" +#include "macrosettings.h" +#include "macrosconstants.h" +#include "macromanager.h" +#include "macro.h" +#include "macrosconstants.h" + +#include <coreplugin/icore.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/command.h> +#include <coreplugin/uniqueidmanager.h> + +#include <QButtonGroup> +#include <QTreeWidget> +#include <QTreeWidgetItem> +#include <QCheckBox> +#include <QDir> +#include <QGroupBox> +#include <QHeaderView> +#include <QFileInfo> +#include <QRegExpValidator> +#include <QLineEdit> + +namespace { + int DIRECTORY = 1; + int MACRO = 2; + + int DEFAULT_ROLE = Qt::UserRole; + int NAME_ROLE = Qt::UserRole; + int WRITE_ROLE = Qt::UserRole+1; + int ID_ROLE = Qt::UserRole+2; +} + +using namespace Macros; +using namespace Macros::Internal; + + +MacroOptionsWidget::MacroOptionsWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::MacroOptionsWidget), + changingCurrent(false) +{ + ui->setupUi(this); + + connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), + this, SLOT(changeCurrentItem(QTreeWidgetItem*))); + connect(ui->removeButton, SIGNAL(clicked()), + this, SLOT(remove())); + connect(ui->defaultButton, SIGNAL(clicked()), + this, SLOT(setDefault())); + connect(ui->addButton, SIGNAL(clicked()), + this, SLOT(addDirectoy())); + connect(ui->description, SIGNAL(textChanged(QString)), + this, SLOT(changeDescription(QString))); + connect(ui->assignShortcut, SIGNAL(toggled(bool)), + this, SLOT(changeShortcut(bool))); + + ui->treeWidget->header()->setSortIndicator(0, Qt::AscendingOrder); +} + +MacroOptionsWidget::~MacroOptionsWidget() +{ + delete ui; +} + +void MacroOptionsWidget::setSettings(const MacroSettings &s) +{ + m_macroToRemove.clear(); + m_macroToChange.clear(); + m_directories.clear(); + ui->treeWidget->clear(); + + ui->showSaveDialog->setChecked(s.showSaveDialog); + + // Create the treeview + foreach (const QString &dir, s.directories) + appendDirectory(dir, s.defaultDirectory==dir); + m_directories = s.directories; +} + +void MacroOptionsWidget::appendDirectory(const QString &directory, bool isDefault) +{ + QDir dir(directory); + QTreeWidgetItem *dirItem = new QTreeWidgetItem(ui->treeWidget, DIRECTORY); + dirItem->setText(0, dir.absolutePath()); + dirItem->setData(0, DEFAULT_ROLE, isDefault); + dirItem->setFirstColumnSpanned(true); + if (isDefault) + dirItem->setIcon(0, QPixmap(":/extensionsystem/images/ok.png")); + + Core::ICore *core = Core::ICore::instance(); + Core::ActionManager *am = core->actionManager(); + QMapIterator<QString, Macro *> it(MacroManager::instance()->macros()); + while (it.hasNext()) { + it.next(); + QFileInfo fileInfo(it.value()->fileName()); + if (fileInfo.absoluteDir() == dir.absolutePath()) { + QTreeWidgetItem *macroItem = new QTreeWidgetItem(dirItem, MACRO); + macroItem->setText(0, it.value()->displayName()); + macroItem->setText(1, it.value()->description()); + macroItem->setData(0, NAME_ROLE, it.value()->displayName()); + macroItem->setData(0, WRITE_ROLE, it.value()->isWritable()); + macroItem->setData(0, ID_ROLE, it.value()->shortcutId()); + + if (it.value()->shortcutId() >= 0) { + QString textId = QString("%1").arg(it.value()->shortcutId(), 2, 10, QLatin1Char('0')); + QString commandId = QLatin1String(Constants::SHORTCUT_MACRO)+textId; + QString shortcut = am->command(commandId)->keySequence().toString(); + macroItem->setText(2, QString("%1 (%2)").arg(shortcut).arg(commandId)); + } + } + } +} + +void MacroOptionsWidget::addDirectoy() +{ + QString directory = ui->directoryPathChooser->path(); + appendDirectory(directory, ui->treeWidget->children().count()==0); +} + +void MacroOptionsWidget::changeCurrentItem(QTreeWidgetItem *current) +{ + changingCurrent = true; + if (!current) { + ui->removeButton->setEnabled(false); + ui->defaultButton->setEnabled(false); + ui->description->clear(); + ui->assignShortcut->setChecked(false); + ui->macroGroup->setEnabled(false); + } + else if (current->type() == DIRECTORY) { + bool isDefault = current->data(0, DEFAULT_ROLE).toBool(); + ui->removeButton->setEnabled(!isDefault); + ui->defaultButton->setEnabled(!isDefault); + ui->description->clear(); + ui->assignShortcut->setChecked(false); + ui->macroGroup->setEnabled(false); + } else { + ui->removeButton->setEnabled(true); + ui->defaultButton->setEnabled(false); + ui->description->setText(current->text(1)); + ui->description->setEnabled(current->data(0, WRITE_ROLE).toBool()); + ui->assignShortcut->setChecked(current->data(0, ID_ROLE).toInt() >= 0); + ui->macroGroup->setEnabled(true); + } + changingCurrent = false; +} + +void MacroOptionsWidget::remove() +{ + QTreeWidgetItem *current = ui->treeWidget->currentItem(); + if (current->type() == MACRO) + m_macroToRemove.append(current->text(0)); + delete current; +} + +void MacroOptionsWidget::setDefault() +{ + QTreeWidgetItem *current = ui->treeWidget->currentItem(); + if (!current || current->type() != DIRECTORY) + return; + + for (int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i) { + QTreeWidgetItem *item = ui->treeWidget->topLevelItem(i); + if (item->data(0, DEFAULT_ROLE).toBool()) { + item->setIcon(0, QPixmap()); + item->setData(0, DEFAULT_ROLE, false); + } + } + + current->setData(0, DEFAULT_ROLE, true); + current->setIcon(0, QPixmap(":/extensionsystem/images/ok.png")); +} + +void MacroOptionsWidget::apply() +{ + // Remove macro + foreach (const QString &name, m_macroToRemove) + MacroManager::instance()->deleteMacro(name); + + // Change macro + QMapIterator<QString, ChangeSet> it(m_macroToChange); + while (it.hasNext()) { + it.next(); + MacroManager::instance()->changeMacro(it.key(), it.value().description, + it.value().shortcut); + } + + // Get list of dir to append or remove + QStringList dirToAppend; + QStringList dirToRemove = m_directories; + for (int i = 0; i < ui->treeWidget->topLevelItemCount(); ++i) { + QTreeWidgetItem *item = ui->treeWidget->topLevelItem(i); + if (!m_directories.contains(item->text(0))) + dirToAppend.append(item->text(0)); + dirToRemove.removeAll(item->text(0)); + if (item->data(0, DEFAULT_ROLE).toBool()) + MacroManager::instance()->setDefaultDirectory(item->text(0)); + } + + // Append/remove directory + foreach (const QString &dir, dirToAppend) + MacroManager::instance()->appendDirectory(dir); + foreach (const QString &dir, dirToRemove) + MacroManager::instance()->removeDirectory(dir); + + MacroManager::instance()->showSaveDialog(ui->showSaveDialog->checkState()==Qt::Checked); + + MacroManager::instance()->saveSettings(); + + // Reinitialize the page + setSettings(MacroManager::instance()->settings()); +} + +void MacroOptionsWidget::changeData(QTreeWidgetItem *current, int column, QVariant value) +{ + QString macroName = current->data(0, NAME_ROLE).toString(); + if (!m_macroToChange.contains(macroName)) { + m_macroToChange[macroName].description = current->text(1); + m_macroToChange[macroName].shortcut = (current->data(0, ID_ROLE).toInt() >= 0); + } + + // Change the description + if (column == 1) { + m_macroToChange[macroName].description = value.toString(); + current->setText(1, value.toString()); + QFont font = current->font(1); + font.setItalic(true); + current->setFont(1, font); + } + // Change the shortcut + if (column == 2) { + bool shortcut = value.toBool(); + m_macroToChange[macroName].shortcut = shortcut; + QFont font = current->font(2); + if (current->data(0, ID_ROLE).toInt() >= 0) { + font.setStrikeOut(!shortcut); + font.setItalic(!shortcut); + } + else { + font.setItalic(shortcut); + current->setText(2, shortcut?tr("create shortcut"):""); + } + current->setFont(2, font); + } +} + +void MacroOptionsWidget::changeDescription(const QString &description) +{ + QTreeWidgetItem *current = ui->treeWidget->currentItem(); + if (changingCurrent || !current || current->type() == DIRECTORY) + return; + changeData(current, 1, description); +} + +void MacroOptionsWidget::changeShortcut(bool shortcut) +{ + QTreeWidgetItem *current = ui->treeWidget->currentItem(); + if (changingCurrent || !current || current->type() == DIRECTORY) + return; + changeData(current, 2, shortcut); +} diff --git a/src/plugins/macros/macrooptionswidget.h b/src/plugins/macros/macrooptionswidget.h new file mode 100644 index 0000000000000000000000000000000000000000..578accf7ea5f60f170b4adb7f1ffe806e6b619d8 --- /dev/null +++ b/src/plugins/macros/macrooptionswidget.h @@ -0,0 +1,90 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROOPTIONSWIDGET_H +#define MACROSPLUGIN_MACROOPTIONSWIDGET_H + +#include <QWidget> +#include <QPixmap> +#include <QMap> +#include <QStringList> + +class QTreeWidgetItem; + + +namespace Macros { +namespace Internal { + +class MacroSettings; + +namespace Ui { + class MacroOptionsWidget; +} + +class MacroOptionsWidget : public QWidget { + Q_OBJECT +public: + explicit MacroOptionsWidget(QWidget *parent = 0); + ~MacroOptionsWidget(); + + void setSettings(const MacroSettings &s); + + void apply(); + +private slots: + void addDirectoy(); + void remove(); + void setDefault(); + void changeCurrentItem(QTreeWidgetItem *current); + +private: + void appendDirectory(const QString &directory, bool isDefault = false); + void changeData(QTreeWidgetItem *current, int column, QVariant value); + +private slots: + void changeDescription(const QString &description); + void changeShortcut(bool shortcut); + +private: + Ui::MacroOptionsWidget *ui; + QStringList m_macroToRemove; + QStringList m_directories; + bool changingCurrent; + + struct ChangeSet { + QString description; + bool shortcut; + }; + QMap<QString, ChangeSet> m_macroToChange; +}; + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_MACROOPTIONSWIDGET_H diff --git a/src/plugins/macros/macrooptionswidget.ui b/src/plugins/macros/macrooptionswidget.ui new file mode 100644 index 0000000000000000000000000000000000000000..b918af69dff3930e6cbd0afca7342751092eafce --- /dev/null +++ b/src/plugins/macros/macrooptionswidget.ui @@ -0,0 +1,173 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Macros::Internal::MacroOptionsWidget</class> + <widget class="QWidget" name="Macros::Internal::MacroOptionsWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>464</width> + <height>473</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QGroupBox" name="directoryGroupBox"> + <property name="title"> + <string>Preferences</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Directory:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="Utils::PathChooser" name="directoryPathChooser" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QPushButton" name="addButton"> + <property name="text"> + <string>Add</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="3"> + <widget class="QTreeWidget" name="treeWidget"> + <property name="textElideMode"> + <enum>Qt::ElideLeft</enum> + </property> + <property name="uniformRowHeights"> + <bool>true</bool> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <property name="columnCount"> + <number>3</number> + </property> + <attribute name="headerShowSortIndicator" stdset="0"> + <bool>true</bool> + </attribute> + <attribute name="headerStretchLastSection"> + <bool>true</bool> + </attribute> + <column> + <property name="text"> + <string>Name</string> + </property> + </column> + <column> + <property name="text"> + <string>Description</string> + </property> + </column> + <column> + <property name="text"> + <string>Shortcut (Command)</string> + </property> + </column> + </widget> + </item> + <item row="3" column="0"> + <widget class="QPushButton" name="defaultButton"> + <property name="text"> + <string>Default Directory</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>213</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="3" column="2"> + <widget class="QPushButton" name="removeButton"> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item row="0" column="0" colspan="3"> + <widget class="QCheckBox" name="showSaveDialog"> + <property name="text"> + <string>Show the save dialog at the end of the macro</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="macroGroup"> + <property name="title"> + <string>Macro</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::ExpandingFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Description:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="description"/> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QCheckBox" name="assignShortcut"> + <property name="toolTip"> + <string>Add or remove a shortcut for this macro. +You can change the default shortcut in the +Environment:Keyboard page.</string> + </property> + <property name="text"> + <string>Assign a shortcut</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>Utils::PathChooser</class> + <extends>QWidget</extends> + <header location="global">utils/pathchooser.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/src/plugins/macros/macros.pri b/src/plugins/macros/macros.pri new file mode 100644 index 0000000000000000000000000000000000000000..e896cd943bc695419dbf41595c3e6f58d1c5a08e --- /dev/null +++ b/src/plugins/macros/macros.pri @@ -0,0 +1,3 @@ +include(macros_dependencies.pri) + +LIBS *= -l$$qtLibraryTarget(Macros) diff --git a/src/plugins/macros/macros.pro b/src/plugins/macros/macros.pro new file mode 100644 index 0000000000000000000000000000000000000000..aacc0b40eeca5fcceb8619017ffb7aca3dfe76aa --- /dev/null +++ b/src/plugins/macros/macros.pro @@ -0,0 +1,45 @@ +TEMPLATE = lib +TARGET = Macros + +DEFINES += MACROS_LIBRARY + +include(../../qtcreatorplugin.pri) +include(macros_dependencies.pri) + +HEADERS += macrosplugin.h \ + macros_global.h \ + macrosconstants.h \ + macrosettings.h \ + macro.h \ + macroevent.h \ + macromanager.h \ + macrooptionspage.h \ + macrooptionswidget.h \ + macrolocatorfilter.h \ + savedialog.h \ + macrotextfind.h \ + texteditormacrohandler.h \ + actionmacrohandler.h \ + findmacrohandler.h \ + imacrohandler.h + +SOURCES += macrosplugin.cpp \ + macrosettings.cpp \ + macro.cpp \ + macroevent.cpp \ + macromanager.cpp \ + macrooptionswidget.cpp \ + macrooptionspage.cpp \ + macrolocatorfilter.cpp \ + savedialog.cpp \ + macrotextfind.cpp \ + texteditormacrohandler.cpp \ + actionmacrohandler.cpp \ + findmacrohandler.cpp \ + imacrohandler.cpp + +RESOURCES += macros.qrc + +FORMS += \ + macrooptionswidget.ui \ + savedialog.ui diff --git a/src/plugins/macros/macros.qrc b/src/plugins/macros/macros.qrc new file mode 100644 index 0000000000000000000000000000000000000000..f82524e9e0aa1f358dc11b5abe160965e05b2263 --- /dev/null +++ b/src/plugins/macros/macros.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/macros"> + <file>images/macro.png</file> + </qresource> +</RCC> diff --git a/src/plugins/macros/macros_dependencies.pri b/src/plugins/macros/macros_dependencies.pri new file mode 100644 index 0000000000000000000000000000000000000000..48ed0123081f22e87a7500731239e588445c5a81 --- /dev/null +++ b/src/plugins/macros/macros_dependencies.pri @@ -0,0 +1,4 @@ +include(../../plugins/coreplugin/coreplugin.pri) +include(../../plugins/locator/locator.pri) +include(../../plugins/find/find.pri) +include(../../plugins/texteditor/texteditor.pri) diff --git a/src/plugins/macros/macros_global.h b/src/plugins/macros/macros_global.h new file mode 100644 index 0000000000000000000000000000000000000000..73841cda36dfe881435e171ef42531f3f6e6b9e7 --- /dev/null +++ b/src/plugins/macros/macros_global.h @@ -0,0 +1,41 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROS_GLOBAL_H +#define MACROSPLUGIN_MACROS_GLOBAL_H + +#include <QtCore/qglobal.h> + +#if defined(MACROS_LIBRARY) +# define MACROS_EXPORT Q_DECL_EXPORT +#else +# define MACROS_EXPORT Q_DECL_IMPORT +#endif + +#endif // MACROSPLUGIN_MACROS_GLOBAL_H diff --git a/src/plugins/macros/macrosconstants.h b/src/plugins/macros/macrosconstants.h new file mode 100644 index 0000000000000000000000000000000000000000..b1163bbca8c3d36b1af004ee7b3f34912816dc5c --- /dev/null +++ b/src/plugins/macros/macrosconstants.h @@ -0,0 +1,54 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROSCONSTANTS_H +#define MACROSPLUGIN_MACROSCONSTANTS_H + +namespace Macros { +namespace Constants { + +const char * const M_TOOLS_MACRO = "Macros.Tools.Menu"; + +const char * const START_MACRO = "Macros.StartMacro"; +const char * const END_MACRO = "Macros.EndMacro"; +const char * const EXECUTE_LAST_MACRO = "Macros.ExecuteLastMacro"; +const char * const SHORTCUT_MACRO = "Macros.Shortcut-"; + +const char * const M_OPTIONS_PAGE = "Macros"; +const char * const M_OPTIONS_TR_PAGE = "Macros"; + +const char * const M_STATUS_BUFFER = "Macros.Status"; +const char * const M_INFO_BUFFER = "Macros.Info"; + +const char * const M_EXTENSION = "mac"; + +} // namespace Constants +} // namespace Macros + +#endif // MACROSPLUGIN_MACROSCONSTANTS_H diff --git a/src/plugins/macros/macrosettings.cpp b/src/plugins/macros/macrosettings.cpp new file mode 100644 index 0000000000000000000000000000000000000000..315f7c1d8cc49d28ee482456b1e3c3690d4f4cea --- /dev/null +++ b/src/plugins/macros/macrosettings.cpp @@ -0,0 +1,74 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "macrosettings.h" + +#include <QSettings> + +using namespace Macros::Internal; + +static const char GROUP[] = "Macro"; +static const char DEFAULT_DIRECTORY[] = "DefaultDirectory"; +static const char SHOW_SAVE_DIALOG[] = "ShowSaveDialog"; +static const char DIRECTORIES[] = "Directories"; +static const char SHORTCUTIDS[] = "ShortcutIds"; + + +MacroSettings::MacroSettings(): + showSaveDialog(false) +{ +} + +void MacroSettings::toSettings(QSettings *s) const +{ + s->beginGroup(QLatin1String(GROUP)); + s->setValue(QLatin1String(DEFAULT_DIRECTORY), defaultDirectory); + s->setValue(QLatin1String(SHOW_SAVE_DIALOG), showSaveDialog); + s->setValue(QLatin1String(DIRECTORIES), directories); + s->setValue(QLatin1String(SHORTCUTIDS), shortcutIds); + s->endGroup(); +} + +void MacroSettings::fromSettings(QSettings *s) +{ + s->beginGroup(QLatin1String(GROUP)); + defaultDirectory = s->value(QLatin1String(DEFAULT_DIRECTORY), QString("")).toString(); + showSaveDialog = s->value(QLatin1String(SHOW_SAVE_DIALOG), false).toBool(); + directories = s->value(QLatin1String(DIRECTORIES)).toStringList(); + shortcutIds = s->value(QLatin1String(SHORTCUTIDS)).toMap(); + s->endGroup(); +} + +bool MacroSettings::equals(const MacroSettings &ms) const +{ + return defaultDirectory == ms.defaultDirectory && + shortcutIds == ms.shortcutIds && + directories == ms.directories && + showSaveDialog == ms.showSaveDialog; +} diff --git a/src/plugins/macros/macrosettings.h b/src/plugins/macros/macrosettings.h new file mode 100644 index 0000000000000000000000000000000000000000..214bf6c0b680df309688ced8f46cc5ce00e85a1d --- /dev/null +++ b/src/plugins/macros/macrosettings.h @@ -0,0 +1,65 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROSETTINGS_H +#define MACROSPLUGIN_MACROSETTINGS_H + +#include <QString> +#include <QStringList> +#include <QMap> +#include <QVariant> + +class QSettings; + +namespace Macros { +namespace Internal { + +class MacroSettings +{ +public: + MacroSettings(); + + void toSettings(QSettings *s) const; + void fromSettings(QSettings *s); + + bool equals(const MacroSettings &ms) const; + + QString defaultDirectory; + QStringList directories; + QMap<QString, QVariant> shortcutIds; + bool showSaveDialog; +}; + +inline bool operator==(const MacroSettings &m1, const MacroSettings &m2) { return m1.equals(m2); } +inline bool operator!=(const MacroSettings &m1, const MacroSettings &m2) { return !m1.equals(m2); } + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_MACROSETTINGS_H diff --git a/src/plugins/macros/macrosplugin.cpp b/src/plugins/macros/macrosplugin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c6ec45fc9606072d5dcdaab6ccb7f5ea1e0bea52 --- /dev/null +++ b/src/plugins/macros/macrosplugin.cpp @@ -0,0 +1,114 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "macrosplugin.h" + +#include "macrosconstants.h" +#include "macromanager.h" +#include "macrooptionspage.h" +#include "macrolocatorfilter.h" + +#include <texteditor/texteditorconstants.h> + +#include <coreplugin/coreconstants.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/actioncontainer.h> +#include <coreplugin/actionmanager/command.h> +#include <coreplugin/icore.h> +#include <coreplugin/uniqueidmanager.h> +#include <coreplugin/icontext.h> + +#include <QtPlugin> +#include <QAction> +#include <QKeySequence> +#include <QSettings> +#include <QMenu> + +using namespace Macros; +using namespace Macros::Internal; + + +MacrosPlugin::MacrosPlugin() +{ +} + +MacrosPlugin::~MacrosPlugin() +{ +} + +bool MacrosPlugin::initialize(const QStringList &arguments, QString *error_message) +{ + Q_UNUSED(arguments); + Q_UNUSED(error_message); + + addAutoReleasedObject(new MacroOptionsPage); + addAutoReleasedObject(new MacroLocatorFilter); + + Core::ICore *core = Core::ICore::instance(); + Core::ActionManager *am = core->actionManager(); + + Core::Context globalcontext(Core::Constants::C_GLOBAL); + Core::Context textContext(TextEditor::Constants::C_TEXTEDITOR); + m_macroManager = new MacroManager(this); + + // Menus + Core::ActionContainer *mtools = am->actionContainer(Core::Constants::M_TOOLS); + Core::ActionContainer *mmacrotools = am->createMenu(Constants::M_TOOLS_MACRO); + QMenu *menu = mmacrotools->menu(); + menu->setTitle(tr("&Macros")); + menu->setEnabled(true); + mtools->addMenu(mmacrotools); + + QAction *startMacro = new QAction(tr("Start Macro"), this); + Core::Command *command = am->registerAction(startMacro, Constants::START_MACRO, textContext); + command->setDefaultKeySequence(QKeySequence(tr("Alt+("))); + mmacrotools->addAction(command); + connect(startMacro, SIGNAL(triggered()), m_macroManager, SLOT(startMacro())); + + QAction *endMacro = new QAction(tr("End Macro"), this); + endMacro->setEnabled(false); + command = am->registerAction(endMacro, Constants::END_MACRO, globalcontext); + command->setDefaultKeySequence(QKeySequence(tr("Alt+)"))); + mmacrotools->addAction(command); + connect(endMacro, SIGNAL(triggered()), m_macroManager, SLOT(endMacro())); + + QAction *executeLastMacro = new QAction(tr("Execute Last Macro"), this); + command = am->registerAction(executeLastMacro, Constants::EXECUTE_LAST_MACRO, textContext); + command->setDefaultKeySequence(QKeySequence(tr("Alt+R,Alt+M"))); + mmacrotools->addAction(command); + connect(executeLastMacro, SIGNAL(triggered()), m_macroManager, SLOT(executeLastMacro())); + + return true; +} + +void MacrosPlugin::extensionsInitialized() +{ +} + +Q_EXPORT_PLUGIN(MacrosPlugin) diff --git a/src/plugins/macros/macrosplugin.h b/src/plugins/macros/macrosplugin.h new file mode 100644 index 0000000000000000000000000000000000000000..893f6cd7e3a8877a3fdb06cdb196a2d3cf1ee59c --- /dev/null +++ b/src/plugins/macros/macrosplugin.h @@ -0,0 +1,59 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROSPLUGIN_H +#define MACROSPLUGIN_MACROSPLUGIN_H + +#include <extensionsystem/iplugin.h> + +namespace Macros { + +class MacroManager; + +namespace Internal { + +class MacrosPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + +public: + MacrosPlugin(); + ~MacrosPlugin(); + + bool initialize(const QStringList &arguments, QString *error_message); + void extensionsInitialized(); + +private: + MacroManager *m_macroManager; +}; + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_MACROSPLUGIN_H diff --git a/src/plugins/macros/macrotextfind.cpp b/src/plugins/macros/macrotextfind.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5fac3c11210ae490bb78461f9353e6783c7f41dd --- /dev/null +++ b/src/plugins/macros/macrotextfind.cpp @@ -0,0 +1,137 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "macrotextfind.h" + +#include <utils/qtcassert.h> + +using namespace Macros; +using namespace Macros::Internal; + +MacroTextFind::MacroTextFind(Find::IFindSupport *currentFind): + Find::IFindSupport(), + m_currentFind(currentFind) +{ +} + +bool MacroTextFind::supportsReplace() const +{ + QTC_ASSERT(m_currentFind, return false); + return m_currentFind->supportsReplace(); +} + +Find::FindFlags MacroTextFind::supportedFindFlags() const +{ + QTC_ASSERT(m_currentFind, return 0); + return m_currentFind->supportedFindFlags(); +} + +void MacroTextFind::resetIncrementalSearch() +{ + QTC_ASSERT(m_currentFind, return); + m_currentFind->resetIncrementalSearch(); + emit incrementalSearchReseted(); +} + +void MacroTextFind::clearResults() +{ + QTC_ASSERT(m_currentFind, return); + m_currentFind->clearResults(); +} + +QString MacroTextFind::currentFindString() const +{ + QTC_ASSERT(m_currentFind, return QString()); + return m_currentFind->currentFindString(); +} + +QString MacroTextFind::completedFindString() const +{ + QTC_ASSERT(m_currentFind, return QString()); + return m_currentFind->completedFindString(); +} + +void MacroTextFind::highlightAll(const QString &txt, Find::FindFlags findFlags) +{ + QTC_ASSERT(m_currentFind, return); + m_currentFind->highlightAll(txt, findFlags); +} + +Find::IFindSupport::Result MacroTextFind::findIncremental(const QString &txt, Find::FindFlags findFlags) +{ + QTC_ASSERT(m_currentFind, return IFindSupport::NotFound); + Find::IFindSupport::Result result = m_currentFind->findIncremental(txt, findFlags); + if (result == Found) + emit incrementalFound(txt, findFlags); + return result; +} + +Find::IFindSupport::Result MacroTextFind::findStep(const QString &txt, Find::FindFlags findFlags) +{ + QTC_ASSERT(m_currentFind, return IFindSupport::NotFound); + Find::IFindSupport::Result result = m_currentFind->findStep(txt, findFlags); + if (result == Found) + emit stepFound(txt, findFlags); + return result; +} + +void MacroTextFind::replace(const QString &before, const QString &after, Find::FindFlags findFlags) +{ + QTC_ASSERT(m_currentFind, return); + m_currentFind->replace(before, after, findFlags); + emit replaced(before, after, findFlags); +} + +bool MacroTextFind::replaceStep(const QString &before, const QString &after, Find::FindFlags findFlags) +{ + QTC_ASSERT(m_currentFind, return false); + bool result = m_currentFind->replaceStep(before, after, findFlags); + emit stepReplaced(before, after, findFlags); + return result; +} + +int MacroTextFind::replaceAll(const QString &before, const QString &after, Find::FindFlags findFlags) +{ + QTC_ASSERT(m_currentFind, return 0); + int result = m_currentFind->replaceAll(before, after, findFlags); + emit allReplaced(before, after, findFlags); + return result; +} + +void MacroTextFind::defineFindScope() +{ + QTC_ASSERT(m_currentFind, return); + m_currentFind->defineFindScope(); +} + +void MacroTextFind::clearFindScope() +{ + QTC_ASSERT(m_currentFind, return); + m_currentFind->clearFindScope(); +} diff --git a/src/plugins/macros/macrotextfind.h b/src/plugins/macros/macrotextfind.h new file mode 100644 index 0000000000000000000000000000000000000000..f175f08ff453dc09b5773ec4494a5e827d073495 --- /dev/null +++ b/src/plugins/macros/macrotextfind.h @@ -0,0 +1,82 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_MACROTEXTFIND_H +#define MACROSPLUGIN_MACROTEXTFIND_H + +#include <find/ifindsupport.h> + +#include <QPointer> + +namespace Macros { +namespace Internal { + +class MacroTextFind : public Find::IFindSupport +{ + Q_OBJECT + +public: + MacroTextFind(Find::IFindSupport *currentFind); + + bool supportsReplace() const; + Find::FindFlags supportedFindFlags() const; + void resetIncrementalSearch(); + void clearResults(); + QString currentFindString() const; + QString completedFindString() const; + + void highlightAll(const QString &txt, Find::FindFlags findFlags); + Find::IFindSupport::Result findIncremental(const QString &txt, Find::FindFlags findFlags); + Find::IFindSupport::Result findStep(const QString &txt, Find::FindFlags findFlags); + void replace(const QString &before, const QString &after, Find::FindFlags findFlags); + bool replaceStep(const QString &before, const QString &after, Find::FindFlags findFlags); + int replaceAll(const QString &before, const QString &after, Find::FindFlags findFlags); + + void defineFindScope(); + void clearFindScope(); + +signals: + void incrementalSearchReseted(); + void incrementalFound(const QString &txt, Find::FindFlags findFlags); + void stepFound(const QString &txt, Find::FindFlags findFlags); + void replaced(const QString &before, const QString &after, + Find::FindFlags findFlags); + void stepReplaced(const QString &before, const QString &after, + Find::FindFlags findFlags); + void allReplaced(const QString &before, const QString &after, + Find::FindFlags findFlags); + +private: + QPointer<Find::IFindSupport> m_currentFind; +}; + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_MACROTEXTFIND_H diff --git a/src/plugins/macros/savedialog.cpp b/src/plugins/macros/savedialog.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ee38315903fe828271b584d71ad7659f8767c37 --- /dev/null +++ b/src/plugins/macros/savedialog.cpp @@ -0,0 +1,70 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "savedialog.h" +#include "ui_savedialog.h" + +#include <QLineEdit> +#include <QCheckBox> +#include <QRegExpValidator> + +using namespace Macros::Internal; + +SaveDialog::SaveDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::SaveDialog) +{ + ui->setupUi(this); + ui->name->setValidator(new QRegExpValidator(QRegExp("\\w*"), this)); +} + +SaveDialog::~SaveDialog() +{ + delete ui; +} + +QString SaveDialog::name() const +{ + return ui->name->text(); +} + +QString SaveDialog::description() const +{ + return ui->description->text(); +} + +bool SaveDialog::hideSaveDialog() const +{ + return ui->hideSaveDialog->isChecked(); +} + +bool SaveDialog::createShortcut() const +{ + return ui->createShortcut->isChecked(); +} diff --git a/src/plugins/macros/savedialog.h b/src/plugins/macros/savedialog.h new file mode 100644 index 0000000000000000000000000000000000000000..171a806b83259e4d5f1dc8df4a6dd0c4826df5ed --- /dev/null +++ b/src/plugins/macros/savedialog.h @@ -0,0 +1,63 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_SAVEDIALOG_H +#define MACROSPLUGIN_SAVEDIALOG_H + +#include <QDialog> + +namespace Macros { +namespace Internal { + +namespace Ui { + class SaveDialog; +} + +class SaveDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SaveDialog(QWidget *parent = 0); + ~SaveDialog(); + + QString name() const; + QString description() const; + bool hideSaveDialog() const; + bool createShortcut() const; + +private: + Ui::SaveDialog *ui; +}; + + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_SAVEDIALOG_H diff --git a/src/plugins/macros/savedialog.ui b/src/plugins/macros/savedialog.ui new file mode 100644 index 0000000000000000000000000000000000000000..268525b99d6285e88d2b1d7833239ccc87bc3396 --- /dev/null +++ b/src/plugins/macros/savedialog.ui @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Macros::Internal::SaveDialog</class> + <widget class="QDialog" name="Macros::Internal::SaveDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>219</width> + <height>153</height> + </rect> + </property> + <property name="windowTitle"> + <string>Save macro</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <property name="fieldGrowthPolicy"> + <enum>QFormLayout::ExpandingFieldsGrow</enum> + </property> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Name:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="name"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Description:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="description"> + <property name="enabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="0" colspan="2"> + <widget class="QCheckBox" name="hideSaveDialog"> + <property name="text"> + <string>Don't show this dialog again</string> + </property> + </widget> + </item> + <item row="4" column="0" colspan="2"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="standardButtons"> + <set>QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + <item row="2" column="0" colspan="2"> + <widget class="QCheckBox" name="createShortcut"> + <property name="text"> + <string>Create a shortcut</string> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>name</tabstop> + <tabstop>description</tabstop> + <tabstop>createShortcut</tabstop> + <tabstop>buttonBox</tabstop> + <tabstop>hideSaveDialog</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>Macros::Internal::SaveDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>264</x> + <y>185</y> + </hint> + <hint type="destinationlabel"> + <x>204</x> + <y>172</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>Macros::Internal::SaveDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>62</x> + <y>185</y> + </hint> + <hint type="destinationlabel"> + <x>47</x> + <y>171</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/plugins/macros/texteditormacrohandler.cpp b/src/plugins/macros/texteditormacrohandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..52d956201f17742d6a037ec49c589bb61ac08753 --- /dev/null +++ b/src/plugins/macros/texteditormacrohandler.cpp @@ -0,0 +1,151 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "texteditormacrohandler.h" +#include "macroevent.h" +#include "macro.h" + +#include <texteditor/itexteditor.h> +#include <texteditor/texteditorconstants.h> + +#include <coreplugin/icore.h> +#include <coreplugin/editormanager/editormanager.h> +#include <coreplugin/editormanager/ieditor.h> +#include <coreplugin/actionmanager/actionmanager.h> +#include <coreplugin/actionmanager/command.h> +#include <coreplugin/uniqueidmanager.h> + +#include <QWidget> +#include <QKeyEvent> +#include <QApplication> +#include <QShortcut> + +using namespace Macros; +using namespace Macros::Internal; + +static const char KEYEVENTNAME[] = "TextEditorKey"; +static quint8 TEXT = 0; +static quint8 TYPE = 1; +static quint8 MODIFIERS = 2; +static quint8 KEY = 3; +static quint8 AUTOREP = 4; +static quint8 COUNT = 5; + + +TextEditorMacroHandler::TextEditorMacroHandler(): + IMacroHandler() +{ + const Core::EditorManager *editorManager = Core::EditorManager::instance(); + connect(editorManager, SIGNAL(currentEditorChanged(Core::IEditor*)), + this, SLOT(changeEditor(Core::IEditor*))); + connect(editorManager, SIGNAL(editorAboutToClose(Core::IEditor*)), + this, SLOT(closeEditor(Core::IEditor*))); +} + +void TextEditorMacroHandler::startRecording(Macros::Macro *macro) +{ + IMacroHandler::startRecording(macro); + if (isRecording() && m_currentEditor && m_currentEditor->widget()) + m_currentEditor->widget()->installEventFilter(this); + + // Block completion + Core::ActionManager *am = Core::ICore::instance()->actionManager(); + am->command(TextEditor::Constants::COMPLETE_THIS)->shortcut()->blockSignals(true); +} + +void TextEditorMacroHandler::endRecordingMacro(Macros::Macro *macro) +{ + if (m_currentEditor && m_currentEditor->widget()) + m_currentEditor->widget()->removeEventFilter(this); + IMacroHandler::endRecordingMacro(macro); + + // Unblock completion + Core::ActionManager *am = Core::ICore::instance()->actionManager(); + am->command(TextEditor::Constants::COMPLETE_THIS)->shortcut()->blockSignals(false); +} + +bool TextEditorMacroHandler::canExecuteEvent(const MacroEvent ¯oEvent) +{ + return (macroEvent.id() == KEYEVENTNAME); +} + +bool TextEditorMacroHandler::executeEvent(const MacroEvent ¯oEvent) +{ + if (!m_currentEditor) + return false; + + QKeyEvent keyEvent((QEvent::Type)macroEvent.value(TYPE).toInt(), + macroEvent.value(KEY).toInt(), + (Qt::KeyboardModifiers)macroEvent.value(MODIFIERS).toInt(), + macroEvent.value(TEXT).toString(), + macroEvent.value(AUTOREP).toBool(), + macroEvent.value(COUNT).toInt()); + QApplication::instance()->sendEvent(m_currentEditor->widget(), &keyEvent); + return true; +} + +bool TextEditorMacroHandler::eventFilter(QObject *watched, QEvent *event) +{ + Q_UNUSED(watched) + + if (!isRecording()) + return false; + + if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) { + QKeyEvent *keyEvent = dynamic_cast<QKeyEvent *>(event); + MacroEvent e; + e.setId(KEYEVENTNAME); + e.setValue(TEXT, keyEvent->text()); + e.setValue(TYPE, keyEvent->type()); + e.setValue(MODIFIERS, (int)keyEvent->modifiers()); + e.setValue(KEY, keyEvent->key()); + e.setValue(AUTOREP, keyEvent->isAutoRepeat()); + e.setValue(COUNT, keyEvent->count()); + addMacroEvent(e); + } + return false; +} + +void TextEditorMacroHandler::changeEditor(Core::IEditor *editor) +{ + if (isRecording() && m_currentEditor && m_currentEditor->widget()) + m_currentEditor->widget()->removeEventFilter(this); + + m_currentEditor = qobject_cast<TextEditor::ITextEditor *>(editor); + if (isRecording() && m_currentEditor && m_currentEditor->widget()) + m_currentEditor->widget()->installEventFilter(this); +} + +void TextEditorMacroHandler::closeEditor(Core::IEditor *editor) +{ + Q_UNUSED(editor); + if (isRecording() && m_currentEditor && m_currentEditor->widget()) + m_currentEditor->widget()->removeEventFilter(this); + m_currentEditor = 0; +} diff --git a/src/plugins/macros/texteditormacrohandler.h b/src/plugins/macros/texteditormacrohandler.h new file mode 100644 index 0000000000000000000000000000000000000000..ea874139cb26cd73e53cdf20d1251c128b92196d --- /dev/null +++ b/src/plugins/macros/texteditormacrohandler.h @@ -0,0 +1,72 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nicolas Arnaud-Cormos. +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MACROSPLUGIN_TEXTEDITOREVENTHANDLER_H +#define MACROSPLUGIN_TEXTEDITOREVENTHANDLER_H + +#include "imacrohandler.h" + +namespace Core { +class IEditor; +} + +namespace TextEditor { +class ITextEditor; +} + +namespace Macros { +namespace Internal { + +class TextEditorMacroHandler : public Macros::IMacroHandler +{ + Q_OBJECT + +public: + TextEditorMacroHandler(); + + void startRecording(Macros::Macro *macro); + void endRecordingMacro(Macros::Macro *macro); + + bool canExecuteEvent(const Macros::MacroEvent ¯oEvent); + bool executeEvent(const Macros::MacroEvent ¯oEvent); + + bool eventFilter(QObject *watched, QEvent *event); + +public slots: + void changeEditor(Core::IEditor *editor); + void closeEditor(Core::IEditor *editor); + +private: + TextEditor::ITextEditor *m_currentEditor; +}; + +} // namespace Internal +} // namespace Macros + +#endif // MACROSPLUGIN_TEXTEDITOREVENTHANDLER_H diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index ed90b1e75dc9397713685d9d20dbc771f877b611..818ab793155b0c3a21625c1eea1db36f01a4fb9e 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -37,6 +37,7 @@ SUBDIRS = plugin_coreplugin \ plugin_classview \ plugin_tasklist \ plugin_qmljstools \ + plugin_macros \ debugger/dumper.pro include(../../qtcreator.pri) @@ -239,3 +240,9 @@ plugin_qmljstools.subdir = qmljstools plugin_qmljstools.depends = plugin_projectexplorer plugin_qmljstools.depends += plugin_coreplugin plugin_qmljstools.depends += plugin_texteditor + +plugin_macros.subdir = macros +plugin_macros.depends = plugin_texteditor +plugin_macros.depends += plugin_find +plugin_macros.depends += plugin_locator +plugin_macros.depends += plugin_coreplugin diff --git a/src/plugins/texteditor/texteditoractionhandler.cpp b/src/plugins/texteditor/texteditoractionhandler.cpp index 0da2681fcbbf96c23c702f6122d182865b1036ac..d90a35d9f1a0f60005a13832b40b6698de1282d5 100644 --- a/src/plugins/texteditor/texteditoractionhandler.cpp +++ b/src/plugins/texteditor/texteditoractionhandler.cpp @@ -123,13 +123,13 @@ void TextEditorActionHandler::initializeActions() void TextEditorActionHandler::createActions() { m_undoAction = registerNewAction(QLatin1String(Core::Constants::UNDO), this, SLOT(undoAction()), - tr("&Undo")); + true, tr("&Undo")); m_redoAction = registerNewAction(QLatin1String(Core::Constants::REDO), this, SLOT(redoAction()), - tr("&Redo")); - m_copyAction = registerNewAction(QLatin1String(Core::Constants::COPY), this, SLOT(copyAction())); - m_cutAction = registerNewAction(QLatin1String(Core::Constants::CUT), this, SLOT(cutAction())); - m_pasteAction = registerNewAction(QLatin1String(Core::Constants::PASTE), this, SLOT(pasteAction())); - m_selectAllAction = registerNewAction(QLatin1String(Core::Constants::SELECTALL), this, SLOT(selectAllAction())); + true, tr("&Redo")); + m_copyAction = registerNewAction(QLatin1String(Core::Constants::COPY), this, SLOT(copyAction()), true); + m_cutAction = registerNewAction(QLatin1String(Core::Constants::CUT), this, SLOT(cutAction()), true); + m_pasteAction = registerNewAction(QLatin1String(Core::Constants::PASTE), this, SLOT(pasteAction()), true); + m_selectAllAction = registerNewAction(QLatin1String(Core::Constants::SELECTALL), this, SLOT(selectAllAction()), true); m_gotoAction = registerNewAction(QLatin1String(Core::Constants::GOTO), this, SLOT(gotoAction())); m_printAction = registerNewAction(QLatin1String(Core::Constants::PRINT), this, SLOT(printAction())); @@ -145,7 +145,7 @@ void TextEditorActionHandler::createActions() m_formatAction = new QAction(tr("Auto-&indent Selection"), this); - command = am->registerAction(m_formatAction, TextEditor::Constants::AUTO_INDENT_SELECTION, m_contextId); + command = am->registerAction(m_formatAction, TextEditor::Constants::AUTO_INDENT_SELECTION, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+I"))); advancedMenu->addAction(command, Core::Constants::G_EDIT_FORMAT); connect(m_formatAction, SIGNAL(triggered(bool)), this, SLOT(formatAction())); @@ -157,7 +157,7 @@ void TextEditorActionHandler::createActions() #endif m_rewrapParagraphAction = new QAction(tr("&Rewrap Paragraph"), this); - command = am->registerAction(m_rewrapParagraphAction, TextEditor::Constants::REWRAP_PARAGRAPH, m_contextId); + command = am->registerAction(m_rewrapParagraphAction, TextEditor::Constants::REWRAP_PARAGRAPH, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("%1+E, R").arg(modifier))); advancedMenu->addAction(command, Core::Constants::G_EDIT_FORMAT); connect(m_rewrapParagraphAction, SIGNAL(triggered(bool)), this, SLOT(rewrapParagraphAction())); @@ -173,7 +173,7 @@ void TextEditorActionHandler::createActions() m_cleanWhitespaceAction = new QAction(tr("Clean Whitespace"), this); command = am->registerAction(m_cleanWhitespaceAction, - TextEditor::Constants::CLEAN_WHITESPACE, m_contextId); + TextEditor::Constants::CLEAN_WHITESPACE, m_contextId, true); advancedMenu->addAction(command, Core::Constants::G_EDIT_FORMAT); connect(m_cleanWhitespaceAction, SIGNAL(triggered()), this, SLOT(cleanWhitespace())); @@ -187,34 +187,34 @@ void TextEditorActionHandler::createActions() m_unCommentSelectionAction = new QAction(tr("(Un)Comment &Selection"), this); - command = am->registerAction(m_unCommentSelectionAction, Constants::UN_COMMENT_SELECTION, m_contextId); + command = am->registerAction(m_unCommentSelectionAction, Constants::UN_COMMENT_SELECTION, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+/"))); connect(m_unCommentSelectionAction, SIGNAL(triggered()), this, SLOT(unCommentSelection())); advancedMenu->addAction(command, Core::Constants::G_EDIT_FORMAT); m_cutLineAction = new QAction(tr("Cut &Line"), this); - command = am->registerAction(m_cutLineAction, Constants::CUT_LINE, m_contextId); + command = am->registerAction(m_cutLineAction, Constants::CUT_LINE, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Shift+Del"))); connect(m_cutLineAction, SIGNAL(triggered()), this, SLOT(cutLine())); m_deleteLineAction = new QAction(tr("Delete &Line"), this); - command = am->registerAction(m_deleteLineAction, Constants::DELETE_LINE, m_contextId); + command = am->registerAction(m_deleteLineAction, Constants::DELETE_LINE, m_contextId, true); connect(m_deleteLineAction, SIGNAL(triggered()), this, SLOT(deleteLine())); m_foldAction = new QAction(tr("Fold"), this); - command = am->registerAction(m_foldAction, Constants::FOLD, m_contextId); + command = am->registerAction(m_foldAction, Constants::FOLD, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+<"))); connect(m_foldAction, SIGNAL(triggered()), this, SLOT(fold())); advancedMenu->addAction(command, Core::Constants::G_EDIT_COLLAPSING); m_unfoldAction = new QAction(tr("Unfold"), this); - command = am->registerAction(m_unfoldAction, Constants::UNFOLD, m_contextId); + command = am->registerAction(m_unfoldAction, Constants::UNFOLD, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+>"))); connect(m_unfoldAction, SIGNAL(triggered()), this, SLOT(unfold())); advancedMenu->addAction(command, Core::Constants::G_EDIT_COLLAPSING); m_unfoldAllAction = new QAction(tr("(Un)&Fold All"), this); - command = am->registerAction(m_unfoldAllAction, Constants::UNFOLD_ALL, m_contextId); + command = am->registerAction(m_unfoldAllAction, Constants::UNFOLD_ALL, m_contextId, true); connect(m_unfoldAllAction, SIGNAL(triggered()), this, SLOT(unfoldAll())); advancedMenu->addAction(command, Core::Constants::G_EDIT_COLLAPSING); @@ -239,97 +239,97 @@ void TextEditorActionHandler::createActions() advancedMenu->addAction(command, Core::Constants::G_EDIT_FONT); m_gotoBlockStartAction = new QAction(tr("Go to Block Start"), this); - command = am->registerAction(m_gotoBlockStartAction, Constants::GOTO_BLOCK_START, m_contextId); + command = am->registerAction(m_gotoBlockStartAction, Constants::GOTO_BLOCK_START, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+["))); connect(m_gotoBlockStartAction, SIGNAL(triggered()), this, SLOT(gotoBlockStart())); advancedMenu->addAction(command, Core::Constants::G_EDIT_BLOCKS); m_gotoBlockEndAction = new QAction(tr("Go to Block End"), this); - command = am->registerAction(m_gotoBlockEndAction, Constants::GOTO_BLOCK_END, m_contextId); + command = am->registerAction(m_gotoBlockEndAction, Constants::GOTO_BLOCK_END, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+]"))); connect(m_gotoBlockEndAction, SIGNAL(triggered()), this, SLOT(gotoBlockEnd())); advancedMenu->addAction(command, Core::Constants::G_EDIT_BLOCKS); m_gotoBlockStartWithSelectionAction = new QAction(tr("Go to Block Start With Selection"), this); - command = am->registerAction(m_gotoBlockStartWithSelectionAction, Constants::GOTO_BLOCK_START_WITH_SELECTION, m_contextId); + command = am->registerAction(m_gotoBlockStartWithSelectionAction, Constants::GOTO_BLOCK_START_WITH_SELECTION, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+{"))); connect(m_gotoBlockStartWithSelectionAction, SIGNAL(triggered()), this, SLOT(gotoBlockStartWithSelection())); m_gotoBlockEndWithSelectionAction = new QAction(tr("Go to Block End With Selection"), this); - command = am->registerAction(m_gotoBlockEndWithSelectionAction, Constants::GOTO_BLOCK_END_WITH_SELECTION, m_contextId); + command = am->registerAction(m_gotoBlockEndWithSelectionAction, Constants::GOTO_BLOCK_END_WITH_SELECTION, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+}"))); connect(m_gotoBlockEndWithSelectionAction, SIGNAL(triggered()), this, SLOT(gotoBlockEndWithSelection())); m_selectBlockUpAction = new QAction(tr("Select Block Up"), this); - command = am->registerAction(m_selectBlockUpAction, Constants::SELECT_BLOCK_UP, m_contextId); + command = am->registerAction(m_selectBlockUpAction, Constants::SELECT_BLOCK_UP, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+U"))); connect(m_selectBlockUpAction, SIGNAL(triggered()), this, SLOT(selectBlockUp())); advancedMenu->addAction(command, Core::Constants::G_EDIT_BLOCKS); m_selectBlockDownAction = new QAction(tr("Select Block Down"), this); - command = am->registerAction(m_selectBlockDownAction, Constants::SELECT_BLOCK_DOWN, m_contextId); + command = am->registerAction(m_selectBlockDownAction, Constants::SELECT_BLOCK_DOWN, m_contextId, true); connect(m_selectBlockDownAction, SIGNAL(triggered()), this, SLOT(selectBlockDown())); advancedMenu->addAction(command, Core::Constants::G_EDIT_BLOCKS); m_moveLineUpAction = new QAction(tr("Move Line Up"), this); - command = am->registerAction(m_moveLineUpAction, Constants::MOVE_LINE_UP, m_contextId); + command = am->registerAction(m_moveLineUpAction, Constants::MOVE_LINE_UP, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+Up"))); connect(m_moveLineUpAction, SIGNAL(triggered()), this, SLOT(moveLineUp())); m_moveLineDownAction = new QAction(tr("Move Line Down"), this); - command = am->registerAction(m_moveLineDownAction, Constants::MOVE_LINE_DOWN, m_contextId); + command = am->registerAction(m_moveLineDownAction, Constants::MOVE_LINE_DOWN, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+Down"))); connect(m_moveLineDownAction, SIGNAL(triggered()), this, SLOT(moveLineDown())); m_copyLineUpAction = new QAction(tr("Copy Line Up"), this); - command = am->registerAction(m_copyLineUpAction, Constants::COPY_LINE_UP, m_contextId); + command = am->registerAction(m_copyLineUpAction, Constants::COPY_LINE_UP, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Up"))); connect(m_copyLineUpAction, SIGNAL(triggered()), this, SLOT(copyLineUp())); m_copyLineDownAction = new QAction(tr("Copy Line Down"), this); - command = am->registerAction(m_copyLineDownAction, Constants::COPY_LINE_DOWN, m_contextId); + command = am->registerAction(m_copyLineDownAction, Constants::COPY_LINE_DOWN, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Alt+Down"))); connect(m_copyLineDownAction, SIGNAL(triggered()), this, SLOT(copyLineDown())); m_joinLinesAction = new QAction(tr("Join Lines"), this); - command = am->registerAction(m_joinLinesAction, Constants::JOIN_LINES, m_contextId); + command = am->registerAction(m_joinLinesAction, Constants::JOIN_LINES, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+J"))); connect(m_joinLinesAction, SIGNAL(triggered()), this, SLOT(joinLines())); m_insertLineAboveAction = new QAction(tr("Insert Line Above Current Line"), this); - command = am->registerAction(m_insertLineAboveAction, Constants::INSERT_LINE_ABOVE, m_contextId); + command = am->registerAction(m_insertLineAboveAction, Constants::INSERT_LINE_ABOVE, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+Return"))); connect(m_insertLineAboveAction, SIGNAL(triggered()), this, SLOT(insertLineAbove())); m_insertLineBelowAction = new QAction(tr("Insert Line Below Current Line"), this); - command = am->registerAction(m_insertLineBelowAction, Constants::INSERT_LINE_BELOW, m_contextId); + command = am->registerAction(m_insertLineBelowAction, Constants::INSERT_LINE_BELOW, m_contextId, true); command->setDefaultKeySequence(QKeySequence(tr("Ctrl+Return"))); connect(m_insertLineBelowAction, SIGNAL(triggered()), this, SLOT(insertLineBelow())); QAction *a = 0; a = new QAction(tr("Goto Line Start"), this); - command = am->registerAction(a, Constants::GOTO_LINE_START, m_contextId); + command = am->registerAction(a, Constants::GOTO_LINE_START, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoLineStart())); a = new QAction(tr("Goto Line End"), this); - command = am->registerAction(a, Constants::GOTO_LINE_END, m_contextId); + command = am->registerAction(a, Constants::GOTO_LINE_END, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoLineEnd())); a = new QAction(tr("Goto Next Line"), this); - command = am->registerAction(a, Constants::GOTO_NEXT_LINE, m_contextId); + command = am->registerAction(a, Constants::GOTO_NEXT_LINE, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoNextLine())); a = new QAction(tr("Goto Previous Line"), this); - command = am->registerAction(a, Constants::GOTO_PREVIOUS_LINE, m_contextId); + command = am->registerAction(a, Constants::GOTO_PREVIOUS_LINE, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoPreviousLine())); a = new QAction(tr("Goto Previous Character"), this); - command = am->registerAction(a, Constants::GOTO_PREVIOUS_CHARACTER, m_contextId); + command = am->registerAction(a, Constants::GOTO_PREVIOUS_CHARACTER, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoPreviousCharacter())); a = new QAction(tr("Goto Next Character"), this); - command = am->registerAction(a, Constants::GOTO_NEXT_CHARACTER, m_contextId); + command = am->registerAction(a, Constants::GOTO_NEXT_CHARACTER, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoNextCharacter())); a = new QAction(tr("Goto Previous Word"), this); - command = am->registerAction(a, Constants::GOTO_PREVIOUS_WORD, m_contextId); + command = am->registerAction(a, Constants::GOTO_PREVIOUS_WORD, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoPreviousWord())); a = new QAction(tr("Goto Next Word"), this); - command = am->registerAction(a, Constants::GOTO_NEXT_WORD, m_contextId); + command = am->registerAction(a, Constants::GOTO_NEXT_WORD, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoNextWord())); a = new QAction(tr("Goto Previous Word Camel Case"), this); command = am->registerAction(a, Constants::GOTO_PREVIOUS_WORD_CAMEL_CASE, m_contextId); @@ -339,28 +339,28 @@ void TextEditorActionHandler::createActions() connect(a, SIGNAL(triggered()), this, SLOT(gotoNextWordCamelCase())); a = new QAction(tr("Goto Line Start With Selection"), this); - command = am->registerAction(a, Constants::GOTO_LINE_START_WITH_SELECTION, m_contextId); + command = am->registerAction(a, Constants::GOTO_LINE_START_WITH_SELECTION, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoLineStartWithSelection())); a = new QAction(tr("Goto Line End With Selection"), this); - command = am->registerAction(a, Constants::GOTO_LINE_END_WITH_SELECTION, m_contextId); + command = am->registerAction(a, Constants::GOTO_LINE_END_WITH_SELECTION, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoLineEndWithSelection())); a = new QAction(tr("Goto Next Line With Selection"), this); - command = am->registerAction(a, Constants::GOTO_NEXT_LINE_WITH_SELECTION, m_contextId); + command = am->registerAction(a, Constants::GOTO_NEXT_LINE_WITH_SELECTION, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoNextLineWithSelection())); a = new QAction(tr("Goto Previous Line With Selection"), this); - command = am->registerAction(a, Constants::GOTO_PREVIOUS_LINE_WITH_SELECTION, m_contextId); + command = am->registerAction(a, Constants::GOTO_PREVIOUS_LINE_WITH_SELECTION, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoPreviousLineWithSelection())); a = new QAction(tr("Goto Previous Character With Selection"), this); - command = am->registerAction(a, Constants::GOTO_PREVIOUS_CHARACTER_WITH_SELECTION, m_contextId); + command = am->registerAction(a, Constants::GOTO_PREVIOUS_CHARACTER_WITH_SELECTION, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoPreviousCharacterWithSelection())); a = new QAction(tr("Goto Next Character With Selection"), this); - command = am->registerAction(a, Constants::GOTO_NEXT_CHARACTER_WITH_SELECTION, m_contextId); + command = am->registerAction(a, Constants::GOTO_NEXT_CHARACTER_WITH_SELECTION, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoNextCharacterWithSelection())); a = new QAction(tr("Goto Previous Word With Selection"), this); - command = am->registerAction(a, Constants::GOTO_PREVIOUS_WORD_WITH_SELECTION, m_contextId); + command = am->registerAction(a, Constants::GOTO_PREVIOUS_WORD_WITH_SELECTION, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoPreviousWordWithSelection())); a = new QAction(tr("Goto Next Word With Selection"), this); - command = am->registerAction(a, Constants::GOTO_NEXT_WORD_WITH_SELECTION, m_contextId); + command = am->registerAction(a, Constants::GOTO_NEXT_WORD_WITH_SELECTION, m_contextId, true); connect(a, SIGNAL(triggered()), this, SLOT(gotoNextWordWithSelection())); a = new QAction(tr("Goto Previous Word Camel Case With Selection"), this); command = am->registerAction(a, Constants::GOTO_PREVIOUS_WORD_CAMEL_CASE_WITH_SELECTION, m_contextId); @@ -376,22 +376,23 @@ bool TextEditorActionHandler::supportsAction(const QString & /*id */) const return true; } -QAction *TextEditorActionHandler::registerNewAction(const QString &id, const QString &title) +QAction *TextEditorActionHandler::registerNewAction(const QString &id, bool scriptable, const QString &title) { if (!supportsAction(id)) return 0; QAction *result = new QAction(title, this); - Core::ICore::instance()->actionManager()->registerAction(result, id, m_contextId); + Core::ICore::instance()->actionManager()->registerAction(result, id, m_contextId, scriptable); return result; } QAction *TextEditorActionHandler::registerNewAction(const QString &id, QObject *receiver, const char *slot, + bool scriptable, const QString &title) { - QAction *rc = registerNewAction(id, title); + QAction *rc = registerNewAction(id, scriptable, title); if (!rc) return 0; diff --git a/src/plugins/texteditor/texteditoractionhandler.h b/src/plugins/texteditor/texteditoractionhandler.h index ec5c9ea8f11e6f37b544a0524c28b4f4da0298fa..4a2b531a1269a9d6d11c491b319f0374e9da8848 100644 --- a/src/plugins/texteditor/texteditoractionhandler.h +++ b/src/plugins/texteditor/texteditoractionhandler.h @@ -74,8 +74,8 @@ public slots: protected: const QPointer<BaseTextEditor> ¤tEditor() const; - QAction *registerNewAction(const QString &id, const QString &title = QString()); - QAction *registerNewAction(const QString &id, QObject *receiver, const char *slot, + QAction *registerNewAction(const QString &id, bool scriptable=false, const QString &title = QString()); + QAction *registerNewAction(const QString &id, QObject *receiver, const char *slot, bool scriptable = false, const QString &title = QString()); enum UpdateMode { ReadOnlyMode, WriteMode };