fakevimplugin.cpp 10.3 KB
Newer Older
hjk's avatar
hjk committed
1
2
3
4
/***************************************************************************
**
** This file is part of Qt Creator
**
5
** Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
hjk's avatar
hjk committed
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/

#include "fakevimplugin.h"

36
37
#include "fakevimconstants.h"
#include "fakevimhandler.h"
hjk's avatar
hjk committed
38

39
#include <coreplugin/actionmanager/actionmanager.h>
hjk's avatar
hjk committed
40
41
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
42
#include <coreplugin/filemanager.h>
hjk's avatar
hjk committed
43
#include <coreplugin/icore.h>
44
#include <coreplugin/ifile.h>
hjk's avatar
hjk committed
45
46
47
48
49
50
51
52
53
54
55
#include <coreplugin/messagemanager.h>
#include <coreplugin/modemanager.h>
#include <coreplugin/uniqueidmanager.h>

#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/session.h>

#include <texteditor/basetexteditor.h>
#include <texteditor/basetextmark.h>
#include <texteditor/itexteditor.h>
#include <texteditor/texteditorconstants.h>
56
#include <texteditor/interactionsettings.h>
57
58
#include <texteditor/tabsettings.h>
#include <texteditor/texteditorsettings.h>
hjk's avatar
hjk committed
59
60
61
62

#include <utils/qtcassert.h>

#include <QtCore/QDebug>
63
#include <QtCore/QtPlugin>
hjk's avatar
hjk committed
64
65
66
67
#include <QtCore/QObject>
#include <QtCore/QPoint>
#include <QtCore/QSettings>

68
#include <QtGui/QMessageBox>
hjk's avatar
hjk committed
69
70
71
#include <QtGui/QPlainTextEdit>
#include <QtGui/QTextBlock>
#include <QtGui/QTextCursor>
72
#include <QtGui/QTextEdit>
hjk's avatar
hjk committed
73
74
75
76
77
78
79
80
81
82
83


using namespace FakeVim::Internal;
using namespace TextEditor;
using namespace Core;
using namespace ProjectExplorer;


namespace FakeVim {
namespace Constants {

84
85
const char * const INSTALL_HANDLER        = "TextEditor.FakeVimHandler";
const char * const MINI_BUFFER            = "TextEditor.FakeVimMiniBuffer";
hjk's avatar
hjk committed
86
87
88
89
90
91
92
93
const char * const INSTALL_KEY            = "Alt+V,Alt+V";

} // namespace Constants
} // namespace FakeVim


///////////////////////////////////////////////////////////////////////
//
94
// FakeVimPluginPrivate
hjk's avatar
hjk committed
95
96
97
//
///////////////////////////////////////////////////////////////////////

98
99
100
101
namespace FakeVim {
namespace Internal {

class FakeVimPluginPrivate : public QObject
hjk's avatar
hjk committed
102
{
103
104
105
106
107
108
109
    Q_OBJECT

public:
    FakeVimPluginPrivate(FakeVimPlugin *);
    ~FakeVimPluginPrivate();
    friend class FakeVimPlugin;

110
    bool initialize();
111
112
113
114
115
    void shutdown();

private slots:
    void editorOpened(Core::IEditor *);
    void editorAboutToClose(Core::IEditor *);
116

hjk's avatar
hjk committed
117
    void installHandlerOnCurrentEditor();
118
119
120
121
122
123
124
    void installHandler(Core::IEditor *editor);
    void removeHandler();

    void showCommandBuffer(const QString &contents);
    void showExtraInformation(const QString &msg);
    void changeSelection(const QList<QTextEdit::ExtraSelection> &selections);
    void writeFile(bool *handled, const QString &fileName, const QString &contents);
125
126
127
128
129
130
131
132
133
134
135
136
137

private:
    FakeVimPlugin *q;
    QAction *m_installHandlerAction; 
};

} // namespace Internal
} // namespace FakeVim

FakeVimPluginPrivate::FakeVimPluginPrivate(FakeVimPlugin *plugin)
{       
    q = plugin;
    m_installHandlerAction = 0;
hjk's avatar
hjk committed
138
139
}

140
141
142
FakeVimPluginPrivate::~FakeVimPluginPrivate()
{
}
hjk's avatar
hjk committed
143

144
void FakeVimPluginPrivate::shutdown()
hjk's avatar
hjk committed
145
146
147
{
}

148
bool FakeVimPluginPrivate::initialize()
hjk's avatar
hjk committed
149
{
hjk's avatar
hjk committed
150
    Core::ActionManager *actionManager = Core::ICore::instance()->actionManager();
hjk's avatar
hjk committed
151
152
153
154
155
156
157
158
    QTC_ASSERT(actionManager, return false);

    QList<int> globalcontext;
    globalcontext << Core::Constants::C_GLOBAL_ID;

    m_installHandlerAction = new QAction(this);
    m_installHandlerAction->setText(tr("Set vi-Style Keyboard Action Handler"));
    
con's avatar
con committed
159
    Core::Command *cmd = 0;
hjk's avatar
hjk committed
160
161
162
163
    cmd = actionManager->registerAction(m_installHandlerAction,
        Constants::INSTALL_HANDLER, globalcontext);
    cmd->setDefaultKeySequence(QKeySequence(Constants::INSTALL_KEY));

164
    ActionContainer *advancedMenu =
hjk's avatar
hjk committed
165
        actionManager->actionContainer(Core::Constants::M_EDIT_ADVANCED);
166
    advancedMenu->addAction(cmd, Core::Constants::G_EDIT_EDITOR);
hjk's avatar
hjk committed
167
168

    connect(m_installHandlerAction, SIGNAL(triggered()),
hjk's avatar
hjk committed
169
        this, SLOT(installHandlerOnCurrentEditor()));
170
171

    // EditorManager
hjk's avatar
hjk committed
172
    QObject *editorManager = Core::ICore::instance()->editorManager();
173
174
175
176
177
    connect(editorManager, SIGNAL(editorAboutToClose(Core::IEditor*)),
        this, SLOT(editorAboutToClose(Core::IEditor*)));
    connect(editorManager, SIGNAL(editorOpened(Core::IEditor*)),
        this, SLOT(editorOpened(Core::IEditor*)));

hjk's avatar
hjk committed
178
179
180
    return true;
}

181
void FakeVimPluginPrivate::installHandler(Core::IEditor *editor)
182
{
183
184
185
    if (!editor)
        return;

186
    QWidget *widget = editor->widget();
187
188
    if (!widget)
        return;
189
190
191
192

    // we can only handle QTextEdit and QPlainTextEdit
    if (!qobject_cast<QTextEdit *>(widget) && !qobject_cast<QPlainTextEdit *>(widget))
        return;
193
    
194
    FakeVimHandler *handler = new FakeVimHandler(widget, widget);
195
196
197
198

    connect(handler, SIGNAL(extraInformationChanged(QString)),
        this, SLOT(showExtraInformation(QString)));
    connect(handler, SIGNAL(commandBufferChanged(QString)),
hjk's avatar
hjk committed
199
        this, SLOT(showCommandBuffer(QString)));
200
201
202
203
204
205
206
207
208
    connect(handler, SIGNAL(quitRequested()),
        this, SLOT(removeHandler()), Qt::QueuedConnection);
    connect(handler, SIGNAL(writeFileRequested(bool*,QString,QString)),
        this, SLOT(writeFile(bool*,QString,QString)));
    connect(handler, SIGNAL(selectionChanged(QList<QTextEdit::ExtraSelection>)),
        this, SLOT(changeSelection(QList<QTextEdit::ExtraSelection>)));

    handler->setupWidget();
    handler->setExtraData(editor);
209

210
    if (BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(widget)) {
211
212
        using namespace TextEditor;
        using namespace FakeVim::Constants;
213
        handler->setCurrentFileName(editor->file()->fileName());
214
        TabSettings settings = bt->tabSettings();
215
        handler->setConfigValue(ConfigTabStop,
216
            QString::number(settings.m_tabSize));
217
        handler->setConfigValue(ConfigShiftWidth,
218
            QString::number(settings.m_indentSize));
219
        handler->setConfigValue(ConfigExpandTab,
220
            settings.m_spacesForTabs ? ConfigOn : ConfigOff);
221
        handler->setConfigValue(ConfigSmartTab,
222
            settings.m_smartBackspace ? ConfigOn : ConfigOff); 
223
        handler->setConfigValue(ConfigAutoIndent,
224
            settings.m_autoIndent ? ConfigOn : ConfigOff); 
225
    }
hjk's avatar
hjk committed
226
227
}

hjk's avatar
hjk committed
228
229
230
231
232
void FakeVimPluginPrivate::installHandlerOnCurrentEditor()
{
    installHandler(EditorManager::instance()->currentEditor());
}

233
234
void FakeVimPluginPrivate::writeFile(bool *handled,
    const QString &fileName, const QString &contents)
235
{
236
237
    Q_UNUSED(contents);

238
239
240
241
242
243
    FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
    if (!handler)
        return;

    Core::IEditor *editor = qobject_cast<Core::IEditor *>(handler->extraData());
    if (editor && editor->file()->fileName() == fileName) {
hjk's avatar
hjk committed
244
        // Handle that as a special case for nicer interaction with core
245
        Core::IFile *file = editor->file();
hjk's avatar
hjk committed
246
        Core::ICore::instance()->fileManager()->blockFileChange(file);
247
        file->save(fileName);
hjk's avatar
hjk committed
248
        Core::ICore::instance()->fileManager()->unblockFileChange(file);
249
250
        *handled = true;
    } 
251
252
}

253
void FakeVimPluginPrivate::removeHandler()
hjk's avatar
hjk committed
254
{
255
256
257
258
    if (FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender())) {
        handler->restoreWidget();
        handler->deleteLater();
    }
hjk's avatar
hjk committed
259
260
    Core::EditorManager::instance()->hideEditorInfoBar(
        QLatin1String(Constants::MINI_BUFFER));
hjk's avatar
hjk committed
261
262
}

263
void FakeVimPluginPrivate::editorOpened(Core::IEditor *editor)
264
265
{
    //qDebug() << "OPENING: " << editor << editor->widget();
266
267
268
269
    QSettings *s = ICore::instance()->settings();
    bool automatic = s->value("textInteractionSettings/UseVim").toBool();
    if (automatic)
       installHandler(editor);
270
271
}

272
void FakeVimPluginPrivate::editorAboutToClose(Core::IEditor *editor)
273
{
hjk's avatar
hjk committed
274
    //qDebug() << "CLOSING: " << editor << editor->widget();
275
    Q_UNUSED(editor);
276
277
}

278
void FakeVimPluginPrivate::showCommandBuffer(const QString &contents)
hjk's avatar
hjk committed
279
{
280
281
282
283
284
285
286
    //qDebug() << "SHOW COMMAND BUFFER" << contents;
    FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
    if (handler) {
        Core::EditorManager::instance()->showEditorInfoBar( 
            QLatin1String(Constants::MINI_BUFFER), contents,
            tr("Quit FakeVim"), handler, SLOT(quit()));
    }
hjk's avatar
hjk committed
287
288
}

289
void FakeVimPluginPrivate::showExtraInformation(const QString &text)
290
{
291
292
293
    FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender());
    if (handler)
        QMessageBox::information(handler->widget(), tr("FakeVim Information"), text);
294
295
}

296
297
void FakeVimPluginPrivate::changeSelection
    (const QList<QTextEdit::ExtraSelection> &selection)
298
{
299
300
301
    if (FakeVimHandler *handler = qobject_cast<FakeVimHandler *>(sender()))
        if (BaseTextEditor *bt = qobject_cast<BaseTextEditor *>(handler->widget()))
            bt->setExtraSelections(BaseTextEditor::FakeVimSelection, selection);
302
303
}

304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319

///////////////////////////////////////////////////////////////////////
//
// FakeVimPlugin
//
///////////////////////////////////////////////////////////////////////

FakeVimPlugin::FakeVimPlugin()
    : d(new FakeVimPluginPrivate(this))
{}

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

320
bool FakeVimPlugin::initialize(const QStringList &arguments, QString *errorMessage)
321
{
322
323
324
    Q_UNUSED(arguments);
    Q_UNUSED(errorMessage);
    return d->initialize();
325
326
327
328
329
330
331
332
333
334
335
336
}

void FakeVimPlugin::shutdown()
{
    d->shutdown();
}

void FakeVimPlugin::extensionsInitialized()
{
}

#include "fakevimplugin.moc"
hjk's avatar
hjk committed
337
338

Q_EXPORT_PLUGIN(FakeVimPlugin)