bineditorplugin.cpp 18.9 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
hjk's avatar
hjk committed
3
4
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8
9
10
11
12
13
14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
18
19
20
21
22
23
24
25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30
31
32
33
#include "bineditorplugin.h"
#include "bineditor.h"
#include "bineditorconstants.h"

34
35
#include <coreplugin/icore.h>

36
#include <QCoreApplication>
37
38
39
40
41
42
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QDebug>
#include <QRegExp>
#include <QVariant>
43

44
45
46
47
48
49
50
#include <QMenu>
#include <QAction>
#include <QMessageBox>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QRegExpValidator>
#include <QToolBar>
con's avatar
con committed
51

52
#include <coreplugin/actionmanager/actionmanager.h>
con's avatar
con committed
53
#include <coreplugin/coreconstants.h>
54
#include <coreplugin/id.h>
55
#include <coreplugin/editormanager/editormanager.h>
56
#include <coreplugin/editormanager/ieditor.h>
57
#include <coreplugin/icore.h>
58
#include <coreplugin/idocument.h>
con's avatar
con committed
59
#include <coreplugin/mimedatabase.h>
60
#include <extensionsystem/pluginmanager.h>
con's avatar
con committed
61
#include <find/ifindsupport.h>
62
63
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorsettings.h>
con's avatar
con committed
64
#include <utils/reloadpromptutils.h>
65
#include <utils/qtcassert.h>
con's avatar
con committed
66
67
68
69
70
71
72
73
74

using namespace BINEditor;
using namespace BINEditor::Internal;


class BinEditorFind : public Find::IFindSupport
{
    Q_OBJECT
public:
ck's avatar
ck committed
75
76
77
78
79
    BinEditorFind(BinEditor *editor)
    {
        m_editor = editor;
        m_incrementalStartPos = m_contPos = -1;
    }
con's avatar
con committed
80
81
82
    ~BinEditorFind() {}

    bool supportsReplace() const { return false; }
83
    Find::FindFlags supportedFindFlags() const
84
    {
85
        return Find::FindBackward | Find::FindCaseSensitively;
86
87
    }

ck's avatar
ck committed
88
89
90
91
92
    void resetIncrementalSearch()
    {
        m_incrementalStartPos = m_contPos = -1;
    }

93
94
95
96
97
    virtual void highlightAll(const QString &txt, Find::FindFlags findFlags)
    {
        m_editor->highlightSearchResults(txt.toLatin1(), Find::textDocumentFlagsForFindFlags(findFlags));
    }

con's avatar
con committed
98
99
100
101
102
    void clearResults() { m_editor->highlightSearchResults(QByteArray()); }
    QString currentFindString() const { return QString(); }
    QString completedFindString() const { return QString(); }


103
    int find(const QByteArray &pattern, int pos, Find::FindFlags findFlags) {
con's avatar
con committed
104
105
106
107
108
        if (pattern.isEmpty()) {
            m_editor->setCursorPosition(pos);
            return pos;
        }

109
        return m_editor->find(pattern, pos, Find::textDocumentFlagsForFindFlags(findFlags));
con's avatar
con committed
110
111
    }

112
    Result findIncremental(const QString &txt, Find::FindFlags findFlags) {
con's avatar
con committed
113
        QByteArray pattern = txt.toLatin1();
ck's avatar
ck committed
114
115
116
        if (pattern != m_lastPattern)
            resetIncrementalSearch(); // Because we don't search for nibbles.
        m_lastPattern = pattern;
con's avatar
con committed
117
118
        if (m_incrementalStartPos < 0)
            m_incrementalStartPos = m_editor->selectionStart();
ck's avatar
ck committed
119
120
121
122
123
124
        if (m_contPos == -1)
            m_contPos = m_incrementalStartPos;
        int found = find(pattern, m_contPos, findFlags);
        Result result;
        if (found >= 0) {
            result = Found;
125
            m_editor->highlightSearchResults(pattern, Find::textDocumentFlagsForFindFlags(findFlags));
ck's avatar
ck committed
126
127
128
129
130
            m_contPos = -1;
        } else {
            if (found == -2) {
                result = NotYetFound;
                m_contPos +=
131
                        findFlags & Find::FindBackward
ck's avatar
ck committed
132
133
134
135
136
137
138
139
                        ? -BinEditor::SearchStride : BinEditor::SearchStride;
            } else {
                result = NotFound;
                m_contPos = -1;
                m_editor->highlightSearchResults(QByteArray(), 0);
            }
        }
        return result;
con's avatar
con committed
140
141
    }

142
    Result findStep(const QString &txt, Find::FindFlags findFlags) {
con's avatar
con committed
143
144
        QByteArray pattern = txt.toLatin1();
        bool wasReset = (m_incrementalStartPos < 0);
ck's avatar
ck committed
145
146
        if (m_contPos == -1) {
            m_contPos = m_editor->cursorPosition();
147
            if (findFlags & Find::FindBackward)
ck's avatar
ck committed
148
149
150
151
152
153
                m_contPos = m_editor->selectionStart()-1;
        }
        int found = find(pattern, m_contPos, findFlags);
        Result result;
        if (found >= 0) {
            result = Found;
con's avatar
con committed
154
            m_incrementalStartPos = found;
ck's avatar
ck committed
155
156
            m_contPos = -1;
            if (wasReset)
157
                m_editor->highlightSearchResults(pattern, Find::textDocumentFlagsForFindFlags(findFlags));
ck's avatar
ck committed
158
159
        } else if (found == -2) {
            result = NotYetFound;
160
            m_contPos += findFlags & Find::FindBackward
ck's avatar
ck committed
161
162
163
164
165
166
167
                         ? -BinEditor::SearchStride : BinEditor::SearchStride;
        } else {
            result = NotFound;
            m_contPos = -1;
        }

        return result;
con's avatar
con committed
168
    }
ck's avatar
ck committed
169

con's avatar
con committed
170
171
172
private:
    BinEditor *m_editor;
    int m_incrementalStartPos;
ck's avatar
ck committed
173
174
    int m_contPos; // Only valid if last result was NotYetFound.
    QByteArray m_lastPattern;
con's avatar
con committed
175
176
177
};


178
class BinEditorDocument : public Core::IDocument
con's avatar
con committed
179
180
181
{
    Q_OBJECT
public:
182
183
    BinEditorDocument(BinEditor *parent) :
        Core::IDocument(parent)
con's avatar
con committed
184
185
    {
        m_editor = parent;
hjk's avatar
hjk committed
186
        connect(m_editor, SIGNAL(dataRequested(Core::IEditor*,quint64)),
Robert Loehning's avatar
Robert Loehning committed
187
            this, SLOT(provideData(Core::IEditor*,quint64)));
ck's avatar
ck committed
188
189
        connect(m_editor, SIGNAL(newRangeRequested(Core::IEditor*,quint64)),
            this, SLOT(provideNewRange(Core::IEditor*,quint64)));
190
191
192
193
        connect(m_editor, SIGNAL(startOfFileRequested(Core::IEditor*)), this,
            SLOT(handleStartOfFileRequested(Core::IEditor*)));
        connect(m_editor, SIGNAL(endOfFileRequested(Core::IEditor*)), this,
            SLOT(handleEndOfFileRequested(Core::IEditor*)));
con's avatar
con committed
194
    }
195
    ~BinEditorDocument() {}
con's avatar
con committed
196

hjk's avatar
hjk committed
197
198
199
    QString mimeType() const {
        return QLatin1String(Constants::C_BINEDITOR_MIMETYPE);
    }
con's avatar
con committed
200

201
    bool save(QString *errorString, const QString &fileName, bool autoSave)
202
    {
203
        QTC_ASSERT(!autoSave, return true); // bineditor does not support autosave - it would be a bit expensive
204
205
        const QString fileNameToUse
            = fileName.isEmpty() ? m_fileName : fileName;
206
        if (m_editor->save(errorString, m_fileName, fileNameToUse)) {
207
            m_fileName = fileNameToUse;
hjk's avatar
hjk committed
208
            m_editor->editor()->setDisplayName(QFileInfo(fileNameToUse).fileName());
con's avatar
con committed
209
210
            emit changed();
            return true;
ck's avatar
ck committed
211
212
        } else {
            return false;
con's avatar
con committed
213
214
215
        }
    }

dt's avatar
dt committed
216
217
    void rename(const QString &newName) {
        m_fileName = newName;
hjk's avatar
hjk committed
218
        m_editor->editor()->setDisplayName(QFileInfo(fileName()).fileName());
dt's avatar
dt committed
219
220
221
        emit changed();
    }

222
    bool open(QString *errorString, const QString &fileName, quint64 offset = 0) {
con's avatar
con committed
223
        QFile file(fileName);
224
225
        quint64 size = static_cast<quint64>(file.size());
        if (size == 0) {
Robert Loehning's avatar
Robert Loehning committed
226
            QString msg = tr("The Binary Editor cannot open empty files.");
227
228
229
230
            if (errorString)
                *errorString = msg;
            else
                QMessageBox::critical(Core::ICore::mainWindow(), tr("File Error"), msg);
231
            return false;
232
        }
233
234
        if (offset >= size)
            return false;
235
        if (file.open(QIODevice::ReadOnly)) {
Daniel Teske's avatar
Daniel Teske committed
236
            file.close();
con's avatar
con committed
237
            m_fileName = fileName;
238
            m_editor->setSizes(offset, file.size());
hjk's avatar
hjk committed
239
            m_editor->editor()->setDisplayName(QFileInfo(fileName).fileName());
con's avatar
con committed
240
241
            return true;
        }
242
243
244
245
246
        QString errStr = tr("Cannot open %1: %2").arg(
                QDir::toNativeSeparators(fileName), file.errorString());
        if (errorString)
            *errorString = errStr;
        else
hjk's avatar
hjk committed
247
            QMessageBox::critical(Core::ICore::mainWindow(), tr("File Error"), errStr);
con's avatar
con committed
248
249
250
        return false;
    }

251
private slots:
252
    void provideData(Core::IEditor *, quint64 block) {
253
254
        if (m_fileName.isEmpty())
            return;
255
256
        QFile file(m_fileName);
        if (file.open(QIODevice::ReadOnly)) {
hjk's avatar
hjk committed
257
            int blockSize = m_editor->dataBlockSize();
258
259
            file.seek(block * blockSize);
            QByteArray data = file.read(blockSize);
260
            file.close();
261
262
263
            const int dataSize = data.size();
            if (dataSize != blockSize)
                data += QByteArray(blockSize - dataSize, 0);
hjk's avatar
hjk committed
264
            m_editor->addData(block, data);
265
        } else {
hjk's avatar
hjk committed
266
            QMessageBox::critical(Core::ICore::mainWindow(), tr("File Error"),
267
268
                                  tr("Cannot open %1: %2").arg(
                                        QDir::toNativeSeparators(m_fileName), file.errorString()));
269
270
        }
    }
271

ck's avatar
ck committed
272
    void provideNewRange(Core::IEditor *, quint64 offset) {
273
        open(0, m_fileName, offset);
274
275
    }

276
    void handleStartOfFileRequested(Core::IEditor *) {
277
        open(0, m_fileName, 0);
278
279
280
    }

    void handleEndOfFileRequested(Core::IEditor *) {
281
        open(0, m_fileName, QFileInfo(m_fileName).size() - 1);
282
283
    }

284
public:
con's avatar
con committed
285
286
287
288
289

    void setFilename(const QString &filename) {
        m_fileName = filename;
    }

hjk's avatar
hjk committed
290
    QString fileName() const { return m_fileName; }
con's avatar
con committed
291
292

    QString defaultPath() const { return QString(); }
hjk's avatar
hjk committed
293

con's avatar
con committed
294
295
    QString suggestedFileName() const { return QString(); }

296
    bool isModified() const { return m_editor->isMemoryView() ? false : m_editor->isModified(); }
hjk's avatar
hjk committed
297

298
    bool isFileReadOnly() const {
299
        if (m_editor->isMemoryView() || m_fileName.isEmpty())
hjk's avatar
hjk committed
300
            return false;
con's avatar
con committed
301
302
303
304
305
306
        const QFileInfo fi(m_fileName);
        return !fi.isWritable();
    }

    bool isSaveAsAllowed() const { return true; }

307
    bool reload(QString *errorString, ReloadFlag flag, ChangeType type) {
308
        if (flag == FlagIgnore)
309
            return true;
310
        if (type == TypePermissions) {
con's avatar
con committed
311
            emit changed();
312
        } else {
313
            emit aboutToReload();
314
315
316
            if (!open(errorString, m_fileName))
                return false;
            emit reloaded();
con's avatar
con committed
317
        }
318
        return true;
con's avatar
con committed
319
320
321
322
323
324
325
326
327
328
329
    }

private:
    BinEditor *m_editor;
    QString m_fileName;
};

class BinEditorInterface : public Core::IEditor
{
    Q_OBJECT
public:
330
    BinEditorInterface(BinEditor *editor)
331
    {
332
        setWidget(editor);
333
        m_editor = editor;
334
        m_file = new BinEditorDocument(m_editor);
335
336
        m_context.add(Core::Constants::K_DEFAULT_BINARY_EDITOR_ID);
        m_context.add(Constants::C_BINEDITOR);
337
338
339
340
341
        m_addressEdit = new QLineEdit;
        QRegExpValidator * const addressValidator
            = new QRegExpValidator(QRegExp(QLatin1String("[0-9a-fA-F]{1,16}")),
                m_addressEdit);
        m_addressEdit->setValidator(addressValidator);
con's avatar
con committed
342
343
344
345
346
347

        QHBoxLayout *l = new QHBoxLayout;
        QWidget *w = new QWidget;
        l->setMargin(0);
        l->setContentsMargins(0, 0, 5, 0);
        l->addStretch(1);
348
        l->addWidget(m_addressEdit);
con's avatar
con committed
349
350
351
352
353
354
        w->setLayout(l);

        m_toolBar = new QToolBar;
        m_toolBar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
        m_toolBar->addWidget(w);

355
356
        connect(m_editor, SIGNAL(cursorPositionChanged(int)), this,
            SLOT(updateCursorPosition(int)));
dt's avatar
dt committed
357
        connect(m_file, SIGNAL(changed()), this, SIGNAL(changed()));
358
359
360
        connect(m_addressEdit, SIGNAL(editingFinished()), this,
            SLOT(jumpToAddress()));
        updateCursorPosition(m_editor->cursorPosition());
con's avatar
con committed
361
    }
362
363
364
    ~BinEditorInterface() {
        delete m_editor;
    }
con's avatar
con committed
365
366

    bool createNew(const QString & /* contents */ = QString()) {
hjk's avatar
hjk committed
367
        m_editor->clear();
con's avatar
con committed
368
369
370
        m_file->setFilename(QString());
        return true;
    }
371
372
    bool open(QString *errorString, const QString &fileName, const QString &realFileName) {
        QTC_ASSERT(fileName == realFileName, return false); // The bineditor can do no autosaving
373
        return m_file->open(errorString, fileName);
con's avatar
con committed
374
    }
375
    Core::IDocument *document() { return m_file; }
Orgad Shaneh's avatar
Orgad Shaneh committed
376
    Core::Id id() const { return Core::Id(Core::Constants::K_DEFAULT_BINARY_EDITOR_ID); }
con's avatar
con committed
377
378
379
380
    QString displayName() const { return m_displayName; }
    void setDisplayName(const QString &title) { m_displayName = title; emit changed(); }

    bool duplicateSupported() const { return false; }
381
    IEditor *duplicate(QWidget * /* parent */) { return 0; }
con's avatar
con committed
382

Eike Ziller's avatar
Eike Ziller committed
383
384
    QByteArray saveState() const { return QByteArray(); } // not supported
    bool restoreState(const QByteArray & /* state */) { return false; }  // not supported
con's avatar
con committed
385

con's avatar
con committed
386
    QWidget *toolBar() { return m_toolBar; }
con's avatar
con committed
387

388
    bool isTemporary() const { return m_editor->isMemoryView(); }
dt's avatar
dt committed
389

390
private slots:
con's avatar
con committed
391
    void updateCursorPosition(int position) {
392
393
394
395
396
397
        m_addressEdit->setText(QString::number(m_editor->baseAddress() + position, 16));
    }

    void jumpToAddress() {
        m_editor->jumpToAddress(m_addressEdit->text().toULongLong(0, 16));
        updateCursorPosition(m_editor->cursorPosition());
con's avatar
con committed
398
399
400
401
402
    }

private:
    BinEditor *m_editor;
    QString m_displayName;
403
    BinEditorDocument *m_file;
con's avatar
con committed
404
    QToolBar *m_toolBar;
405
    QLineEdit *m_addressEdit;
con's avatar
con committed
406
407
408
409
410
411
412
};



///////////////////////////////// BinEditorFactory //////////////////////////////////

BinEditorFactory::BinEditorFactory(BinEditorPlugin *owner) :
hjk's avatar
hjk committed
413
    m_mimeTypes(QLatin1String(Constants::C_BINEDITOR_MIMETYPE)),
con's avatar
con committed
414
415
416
417
    m_owner(owner)
{
}

hjk's avatar
hjk committed
418
Core::Id BinEditorFactory::id() const
con's avatar
con committed
419
{
Orgad Shaneh's avatar
Orgad Shaneh committed
420
    return Core::Id(Core::Constants::K_DEFAULT_BINARY_EDITOR_ID);
421
422
423
424
}

QString BinEditorFactory::displayName() const
{
425
    return qApp->translate("OpenWith::Editors", Constants::C_BINEDITOR_DISPLAY_NAME);
con's avatar
con committed
426
427
428
429
430
431
}

Core::IEditor *BinEditorFactory::createEditor(QWidget *parent)
{
    BinEditor *editor = new BinEditor(parent);
    m_owner->initializeEditor(editor);
hjk's avatar
hjk committed
432
    return editor->editor();
con's avatar
con committed
433
434
435
436
437
438
439
}

QStringList BinEditorFactory::mimeTypes() const
{
    return m_mimeTypes;
}

440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
/*!
   \class BINEditor::BinEditorWidgetFactory
   \brief Service registered with PluginManager to create bin editor widgets for plugins
   without direct linkage.

   \sa ExtensionSystem::PluginManager::getObjectByClassName, ExtensionSystem::invoke
*/

BinEditorWidgetFactory::BinEditorWidgetFactory(QObject *parent) :
    QObject(parent)
{
}

QWidget *BinEditorWidgetFactory::createWidget(QWidget *parent)
{
    return new BinEditor(parent);
}

con's avatar
con committed
458
459
///////////////////////////////// BinEditorPlugin //////////////////////////////////

460
BinEditorPlugin::BinEditorPlugin()
con's avatar
con committed
461
462
463
464
465
466
467
468
{
    m_undoAction = m_redoAction = m_copyAction = m_selectAllAction = 0;
}

BinEditorPlugin::~BinEditorPlugin()
{
}

hjk's avatar
hjk committed
469
QAction *BinEditorPlugin::registerNewAction(Core::Id id, const QString &title)
con's avatar
con committed
470
471
{
    QAction *result = new QAction(title, this);
hjk's avatar
hjk committed
472
    Core::ActionManager::registerAction(result, id, m_context);
con's avatar
con committed
473
474
475
    return result;
}

hjk's avatar
hjk committed
476
QAction *BinEditorPlugin::registerNewAction(Core::Id id,
con's avatar
con committed
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
                                            QObject *receiver,
                                            const char *slot,
                                            const QString &title)
{
    QAction *rc = registerNewAction(id, title);
    if (!rc)
        return 0;

    connect(rc, SIGNAL(triggered()), receiver, slot);
    return rc;
}

void BinEditorPlugin::initializeEditor(BinEditor *editor)
{
    BinEditorInterface *editorInterface = new BinEditorInterface(editor);
    QObject::connect(editor, SIGNAL(modificationChanged(bool)), editorInterface, SIGNAL(changed()));
hjk's avatar
hjk committed
493
    editor->setEditor(editorInterface);
con's avatar
con committed
494

495
    m_context.add(Constants::C_BINEDITOR);
con's avatar
con committed
496
    if (!m_undoAction) {
hjk's avatar
hjk committed
497
498
499
500
        m_undoAction      = registerNewAction(Core::Constants::UNDO, this, SLOT(undoAction()), tr("&Undo"));
        m_redoAction      = registerNewAction(Core::Constants::REDO, this, SLOT(redoAction()), tr("&Redo"));
        m_copyAction      = registerNewAction(Core::Constants::COPY, this, SLOT(copyAction()));
        m_selectAllAction = registerNewAction(Core::Constants::SELECTALL, this, SLOT(selectAllAction()));
con's avatar
con committed
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
    }

    // Font settings
    TextEditor::TextEditorSettings *settings = TextEditor::TextEditorSettings::instance();
    editor->setFontSettings(settings->fontSettings());
    connect(settings, SIGNAL(fontSettingsChanged(TextEditor::FontSettings)),
            editor, SLOT(setFontSettings(TextEditor::FontSettings)));

    QObject::connect(editor, SIGNAL(undoAvailable(bool)), this, SLOT(updateActions()));
    QObject::connect(editor, SIGNAL(redoAvailable(bool)), this, SLOT(updateActions()));

    Aggregation::Aggregate *aggregate = new Aggregation::Aggregate;
    BinEditorFind *binEditorFind = new BinEditorFind(editor);
    aggregate->add(binEditorFind);
    aggregate->add(editor);
}

518
bool BinEditorPlugin::initialize(const QStringList &arguments, QString *errorMessage)
con's avatar
con committed
519
{
520
    Q_UNUSED(arguments)
521
    Q_UNUSED(errorMessage)
522

Robert Loehning's avatar
Robert Loehning committed
523
524
    connect(Core::ICore::instance(), SIGNAL(contextAboutToChange(Core::IContext*)),
        this, SLOT(updateCurrentEditor(Core::IContext*)));
con's avatar
con committed
525
526

    addAutoReleasedObject(new BinEditorFactory(this));
527
    addAutoReleasedObject(new BinEditorWidgetFactory);
con's avatar
con committed
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
    return true;
}

void BinEditorPlugin::extensionsInitialized()
{
}

void BinEditorPlugin::updateCurrentEditor(Core::IContext *object)
{
    do {
        if (!object) {
            if (!m_currentEditor)
                return;

            m_currentEditor = 0;
            break;
        }
        BinEditor *editor = qobject_cast<BinEditor *>(object->widget());
        if (!editor) {
            if (!m_currentEditor)
                return;

            m_currentEditor = 0;
            break;
        }

        if (editor == m_currentEditor)
            return;

        m_currentEditor = editor;

    } while (false);
    updateActions();
}

void BinEditorPlugin::updateActions()
{
    bool hasEditor = (m_currentEditor != 0);
    if (m_selectAllAction)
        m_selectAllAction->setEnabled(hasEditor);
    if (m_undoAction)
        m_undoAction->setEnabled(m_currentEditor && m_currentEditor->isUndoAvailable());
    if (m_redoAction)
        m_redoAction->setEnabled(m_currentEditor && m_currentEditor->isRedoAvailable());
}

void BinEditorPlugin::undoAction()
{
    if (m_currentEditor)
        m_currentEditor->undo();
}

void BinEditorPlugin::redoAction()
{
    if (m_currentEditor)
        m_currentEditor->redo();
}

void BinEditorPlugin::copyAction()
{
    if (m_currentEditor)
        m_currentEditor->copy();
}

void BinEditorPlugin::selectAllAction()
{
    if (m_currentEditor)
        m_currentEditor->selectAll();
}


Q_EXPORT_PLUGIN(BinEditorPlugin)

#include "bineditorplugin.moc"