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

30
#include "diffeditor.h"
31
#include "diffeditorconstants.h"
32
#include "diffeditordocument.h"
33
#include "diffeditorguicontroller.h"
34
#include "sidebysidediffeditorwidget.h"
jkobus's avatar
jkobus committed
35
#include "unifieddiffeditorwidget.h"
36 37

#include <coreplugin/icore.h>
38
#include <coreplugin/coreconstants.h>
Jarek Kobus's avatar
Jarek Kobus committed
39 40 41 42 43
#include <coreplugin/minisplitter.h>

#include <texteditor/basetexteditor.h>
#include <texteditor/texteditorsettings.h>
#include <texteditor/displaysettings.h>
44

jkobus's avatar
jkobus committed
45
#include <QStackedWidget>
46 47 48 49
#include <QToolButton>
#include <QSpinBox>
#include <QStyle>
#include <QLabel>
50
#include <QHBoxLayout>
jkobus's avatar
jkobus committed
51 52 53
#include <QToolBar>
#include <QComboBox>
#include <QFileInfo>
54
#include <QDir>
jkobus's avatar
jkobus committed
55
#include <QTextCodec>
56
#include <QTextBlock>
jkobus's avatar
jkobus committed
57 58 59 60 61 62 63 64

static const char settingsGroupC[] = "DiffEditor";
static const char diffEditorTypeKeyC[] = "DiffEditorType";
static const char sideBySideDiffEditorValueC[] = "SideBySide";
static const char unifiedDiffEditorValueC[] = "Unified";

static const char legacySettingsGroupC[] = "Git";
static const char useDiffEditorKeyC[] = "UseDiffEditor";
65

Jarek Kobus's avatar
Jarek Kobus committed
66 67
using namespace TextEditor;

68 69
namespace DiffEditor {

Jarek Kobus's avatar
Jarek Kobus committed
70 71 72 73 74 75 76 77 78
namespace Internal {

class DescriptionEditorWidget : public BaseTextEditorWidget
{
    Q_OBJECT
public:
    DescriptionEditorWidget(QWidget *parent = 0);
    virtual QSize sizeHint() const;

79 80 81
signals:
    void expandBranchesRequested();

Jarek Kobus's avatar
Jarek Kobus committed
82 83 84 85
public slots:
    void setDisplaySettings(const DisplaySettings &ds);

protected:
86 87 88
    BaseTextEditor *createEditor()
    {
        BaseTextEditor *editor = new BaseTextEditor(this);
89
        editor->document()->setId("DiffEditor.DescriptionEditor");
90 91
        return editor;
    }
92 93 94 95 96 97 98 99 100
    void mouseMoveEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *e);

    bool findContentsUnderCursor(const QTextCursor &cursor);
    void highlightCurrentContents();
    void handleCurrentContents();

private:
    QTextCursor m_currentCursor;
Jarek Kobus's avatar
Jarek Kobus committed
101 102 103
};

DescriptionEditorWidget::DescriptionEditorWidget(QWidget *parent)
104
    : BaseTextEditorWidget(parent)
Jarek Kobus's avatar
Jarek Kobus committed
105
{
106
    setTextDocument(BaseTextDocumentPtr(new BaseTextDocument));
Jarek Kobus's avatar
Jarek Kobus committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
    DisplaySettings settings = displaySettings();
    settings.m_textWrapping = false;
    settings.m_displayLineNumbers = false;
    settings.m_highlightCurrentLine = false;
    settings.m_displayFoldingMarkers = false;
    settings.m_markTextChanges = false;
    settings.m_highlightBlocks = false;
    BaseTextEditorWidget::setDisplaySettings(settings);

    setCodeFoldingSupported(true);
    setFrameStyle(QFrame::NoFrame);

    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
}

QSize DescriptionEditorWidget::sizeHint() const
{
    QSize size = BaseTextEditorWidget::sizeHint();
    size.setHeight(size.height() / 5);
    return size;
}

void DescriptionEditorWidget::setDisplaySettings(const DisplaySettings &ds)
{
    DisplaySettings settings = displaySettings();
    settings.m_visualizeWhitespace = ds.m_visualizeWhitespace;
    BaseTextEditorWidget::setDisplaySettings(settings);
}

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
void DescriptionEditorWidget::mouseMoveEvent(QMouseEvent *e)
{
    if (e->buttons()) {
        TextEditor::BaseTextEditorWidget::mouseMoveEvent(e);
        return;
    }

    Qt::CursorShape cursorShape;

    const QTextCursor cursor = cursorForPosition(e->pos());
    if (findContentsUnderCursor(cursor)) {
        highlightCurrentContents();
        cursorShape = Qt::PointingHandCursor;
    } else {
        setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>());
        cursorShape = Qt::IBeamCursor;
    }

    TextEditor::BaseTextEditorWidget::mouseMoveEvent(e);
    viewport()->setCursor(cursorShape);
}

void DescriptionEditorWidget::mouseReleaseEvent(QMouseEvent *e)
{
    if (e->button() == Qt::LeftButton && !(e->modifiers() & Qt::ShiftModifier)) {
        const QTextCursor cursor = cursorForPosition(e->pos());
        if (findContentsUnderCursor(cursor)) {
            handleCurrentContents();
            e->accept();
            return;
        }
    }

    TextEditor::BaseTextEditorWidget::mouseReleaseEvent(e);
}

bool DescriptionEditorWidget::findContentsUnderCursor(const QTextCursor &cursor)
{
    m_currentCursor = cursor;
    return cursor.block().text() == QLatin1String(Constants::EXPAND_BRANCHES);
}

void DescriptionEditorWidget::highlightCurrentContents()
{
    QTextEdit::ExtraSelection sel;
    sel.cursor = m_currentCursor;
    sel.cursor.select(QTextCursor::LineUnderCursor);
    sel.format.setFontUnderline(true);
    setExtraSelections(BaseTextEditorWidget::OtherSelection,
                       QList<QTextEdit::ExtraSelection>() << sel);

}

void DescriptionEditorWidget::handleCurrentContents()
{
    m_currentCursor.select(QTextCursor::LineUnderCursor);
    m_currentCursor.removeSelectedText();
    m_currentCursor.insertText(QLatin1String("Branches: Expanding..."));
    emit expandBranchesRequested();
}

Jarek Kobus's avatar
Jarek Kobus committed
197 198
} // namespace Internal

199
///////////////////////////////// DiffEditor //////////////////////////////////
200

201
DiffEditor::DiffEditor()
jkobus's avatar
jkobus committed
202
    : IEditor(0)
203
    , m_document(new DiffEditorDocument())
204
    , m_descriptionWidget(0)
jkobus's avatar
jkobus committed
205 206 207 208
    , m_stackedWidget(0)
    , m_sideBySideEditor(0)
    , m_unifiedEditor(0)
    , m_currentEditor(0)
209 210
    , m_controller(0)
    , m_guiController(0)
211
    , m_toolBar(0)
jkobus's avatar
jkobus committed
212
    , m_entriesComboBox(0)
Jarek Kobus's avatar
Jarek Kobus committed
213
    , m_toggleDescriptionAction(0)
214
    , m_reloadAction(0)
jkobus's avatar
jkobus committed
215
    , m_diffEditorSwitcher(0)
216 217 218 219 220 221 222 223
{
    ctor();
}

DiffEditor::DiffEditor(DiffEditor *other)
    : IEditor(0)
    , m_document(other->m_document)
    , m_descriptionWidget(0)
jkobus's avatar
jkobus committed
224 225 226 227
    , m_stackedWidget(0)
    , m_sideBySideEditor(0)
    , m_unifiedEditor(0)
    , m_currentEditor(0)
228 229
    , m_controller(0)
    , m_guiController(0)
230 231 232
    , m_toolBar(0)
    , m_entriesComboBox(0)
    , m_toggleDescriptionAction(0)
233
    , m_reloadAction(0)
jkobus's avatar
jkobus committed
234
    , m_diffEditorSwitcher(0)
235 236 237 238 239
{
    ctor();
}

void DiffEditor::ctor()
240
{
jkobus's avatar
jkobus committed
241 242
    setDuplicateSupported(true);

Jarek Kobus's avatar
Jarek Kobus committed
243
    QSplitter *splitter = new Core::MiniSplitter(Qt::Vertical);
244

Jarek Kobus's avatar
Jarek Kobus committed
245 246 247
    m_descriptionWidget = new Internal::DescriptionEditorWidget(splitter);
    m_descriptionWidget->setReadOnly(true);
    splitter->addWidget(m_descriptionWidget);
248

jkobus's avatar
jkobus committed
249 250 251 252 253 254 255 256
    m_stackedWidget = new QStackedWidget(splitter);
    splitter->addWidget(m_stackedWidget);

    m_sideBySideEditor = new SideBySideDiffEditorWidget(m_stackedWidget);
    m_stackedWidget->addWidget(m_sideBySideEditor);

    m_unifiedEditor = new UnifiedDiffEditorWidget(m_stackedWidget);
    m_stackedWidget->addWidget(m_unifiedEditor);
257

Jarek Kobus's avatar
Jarek Kobus committed
258 259
    setWidget(splitter);

260 261
    connect(m_descriptionWidget, SIGNAL(expandBranchesRequested()),
            m_document->controller(), SLOT(expandBranchesRequested()));
jkobus's avatar
jkobus committed
262 263 264 265 266 267
    connect(TextEditorSettings::instance(),
            SIGNAL(displaySettingsChanged(TextEditor::DisplaySettings)),
            m_descriptionWidget,
            SLOT(setDisplaySettings(TextEditor::DisplaySettings)));
    connect(TextEditorSettings::instance(),
            SIGNAL(fontSettingsChanged(TextEditor::FontSettings)),
268
            m_descriptionWidget->textDocument(),
jkobus's avatar
jkobus committed
269 270 271 272 273 274
            SLOT(setFontSettings(TextEditor::FontSettings)));

    m_descriptionWidget->setDisplaySettings(
                TextEditorSettings::displaySettings());
    m_descriptionWidget->setCodeStyle(
                TextEditorSettings::codeStyle());
275
    m_descriptionWidget->textDocument()->setFontSettings(
jkobus's avatar
jkobus committed
276
                TextEditorSettings::fontSettings());
Jarek Kobus's avatar
Jarek Kobus committed
277

278 279
    m_controller = m_document->controller();
    m_guiController = new DiffEditorGuiController(m_controller, this);
280

281
    connect(m_controller, SIGNAL(cleared(QString)),
jkobus's avatar
jkobus committed
282
            this, SLOT(slotCleared(QString)));
jkobus's avatar
jkobus committed
283 284
    connect(m_controller, SIGNAL(diffFilesChanged(QList<FileData>,QString)),
            this, SLOT(slotDiffFilesChanged(QList<FileData>,QString)));
285
    connect(m_controller, SIGNAL(descriptionChanged(QString)),
286
            this, SLOT(slotDescriptionChanged(QString)));
287
    connect(m_controller, SIGNAL(descriptionEnablementChanged(bool)),
288
            this, SLOT(slotDescriptionVisibilityChanged()));
289
    connect(m_guiController, SIGNAL(descriptionVisibilityChanged(bool)),
290
            this, SLOT(slotDescriptionVisibilityChanged()));
291 292
    connect(m_guiController, SIGNAL(currentDiffFileIndexChanged(int)),
            this, SLOT(activateEntry(int)));
293

294
    slotDescriptionChanged(m_controller->description());
295
    slotDescriptionVisibilityChanged();
jkobus's avatar
jkobus committed
296 297 298 299

    showDiffEditor(readCurrentDiffEditorSetting());

    toolBar();
300 301
}

302
DiffEditor::~DiffEditor()
303
{
304
    delete m_toolBar;
305 306 307 308
    if (m_widget)
        delete m_widget;
}

309 310 311 312 313
Core::IEditor *DiffEditor::duplicate()
{
    return new DiffEditor(this);
}

jkobus's avatar
jkobus committed
314 315 316
bool DiffEditor::open(QString *errorString,
                      const QString &fileName,
                      const QString &realFileName)
317 318
{
    Q_UNUSED(realFileName)
jkobus's avatar
jkobus committed
319 320 321 322

    if (!m_controller)
        return false;

323 324
    QString patch;
    if (m_document->read(fileName, &patch, errorString) != Utils::TextFileFormat::ReadSuccess)
jkobus's avatar
jkobus committed
325 326 327 328 329 330 331 332 333 334 335 336 337 338
        return false;

    bool ok = false;
    QList<FileData> fileDataList
            = DiffUtils::readPatch(patch,
                                   m_controller->isIgnoreWhitespace(),
                                   &ok);
    if (!ok) {
        *errorString = tr("Could not parse patch file \"%1\". "
                          "The contents is not of unified diff format.")
                .arg(fileName);
        return false;
    }

339 340 341
    const QFileInfo fi(fileName);
    m_document->setFilePath(QDir::cleanPath(fi.absoluteFilePath()));
    m_controller->setDiffFiles(fileDataList, fi.absolutePath());
342 343 344
    return true;
}

345
Core::IDocument *DiffEditor::document()
346
{
347
    return m_document.data();
348 349 350 351 352 353
}

static QToolBar *createToolBar(const QWidget *someWidget)
{
    // Create
    QToolBar *toolBar = new QToolBar;
354
    toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
355 356 357 358 359 360
    const int size = someWidget->style()->pixelMetric(QStyle::PM_SmallIconSize);
    toolBar->setIconSize(QSize(size, size));

    return toolBar;
}

361
QWidget *DiffEditor::toolBar()
362
{
363 364
    if (m_toolBar)
        return m_toolBar;
365 366

    // Create
jkobus's avatar
jkobus committed
367
    m_toolBar = createToolBar(m_sideBySideEditor);
368

jkobus's avatar
jkobus committed
369 370 371 372 373 374 375 376
    m_entriesComboBox = new QComboBox;
    m_entriesComboBox->setMinimumContentsLength(20);
    // Make the combo box prefer to expand
    QSizePolicy policy = m_entriesComboBox->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Expanding);
    m_entriesComboBox->setSizePolicy(policy);
    connect(m_entriesComboBox, SIGNAL(activated(int)),
            this, SLOT(entryActivated(int)));
377
    m_toolBar->addWidget(m_entriesComboBox);
378

379
    QToolButton *whitespaceButton = new QToolButton(m_toolBar);
Tobias Hunger's avatar
Tobias Hunger committed
380
    whitespaceButton->setText(tr("Ignore Whitespace"));
381
    whitespaceButton->setCheckable(true);
jkobus's avatar
jkobus committed
382
    whitespaceButton->setChecked(m_controller->isIgnoreWhitespace());
383
    m_toolBar->addWidget(whitespaceButton);
384

385
    QLabel *contextLabel = new QLabel(m_toolBar);
hjk's avatar
hjk committed
386
    contextLabel->setText(tr("Context Lines:"));
387
    contextLabel->setContentsMargins(6, 0, 6, 0);
388
    m_toolBar->addWidget(contextLabel);
389

390
    QSpinBox *contextSpinBox = new QSpinBox(m_toolBar);
jkobus's avatar
jkobus committed
391 392
    contextSpinBox->setRange(1, 100);
    contextSpinBox->setValue(m_controller->contextLinesNumber());
hjk's avatar
hjk committed
393
    contextSpinBox->setFrame(false);
jkobus's avatar
jkobus committed
394 395
    contextSpinBox->setSizePolicy(QSizePolicy::Minimum,
                                  QSizePolicy::Expanding); // Mac Qt5
396
    m_toolBar->addWidget(contextSpinBox);
397

398
    QToolButton *toggleDescription = new QToolButton(m_toolBar);
jkobus's avatar
jkobus committed
399 400
    toggleDescription->setIcon(
                QIcon(QLatin1String(Constants::ICON_TOP_BAR)));
Jarek Kobus's avatar
Jarek Kobus committed
401
    toggleDescription->setCheckable(true);
jkobus's avatar
jkobus committed
402
    toggleDescription->setChecked(m_guiController->isDescriptionVisible());
403
    m_toggleDescriptionAction = m_toolBar->addWidget(toggleDescription);
Jarek Kobus's avatar
Jarek Kobus committed
404 405
    slotDescriptionVisibilityChanged();

jkobus's avatar
jkobus committed
406
    QToolButton *reloadButton = new QToolButton(m_toolBar);
407
    reloadButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_RELOAD_GRAY)));
jkobus's avatar
jkobus committed
408
    reloadButton->setToolTip(tr("Reload Editor"));
409 410 411 412 413 414 415 416 417
    m_reloadAction = m_toolBar->addWidget(reloadButton);
    slotReloaderChanged(m_controller->reloader());

    QToolButton *toggleSync = new QToolButton(m_toolBar);
    toggleSync->setIcon(QIcon(QLatin1String(Core::Constants::ICON_LINK)));
    toggleSync->setCheckable(true);
    toggleSync->setChecked(m_guiController->horizontalScrollBarSynchronization());
    toggleSync->setToolTip(tr("Synchronize Horizontal Scroll Bars"));
    m_toolBar->addWidget(toggleSync);
jkobus's avatar
jkobus committed
418 419 420 421 422

    m_diffEditorSwitcher = new QToolButton(m_toolBar);
    m_toolBar->addWidget(m_diffEditorSwitcher);
    updateDiffEditorSwitcher();

jkobus's avatar
jkobus committed
423
    connect(whitespaceButton, SIGNAL(clicked(bool)),
jkobus's avatar
jkobus committed
424 425 426
            m_controller, SLOT(setIgnoreWhitespace(bool)));
    connect(m_controller, SIGNAL(ignoreWhitespaceChanged(bool)),
            whitespaceButton, SLOT(setChecked(bool)));
jkobus's avatar
jkobus committed
427
    connect(contextSpinBox, SIGNAL(valueChanged(int)),
jkobus's avatar
jkobus committed
428 429 430
            m_controller, SLOT(setContextLinesNumber(int)));
    connect(m_controller, SIGNAL(contextLinesNumberChanged(int)),
            contextSpinBox, SLOT(setValue(int)));
jkobus's avatar
jkobus committed
431
    connect(toggleSync, SIGNAL(clicked(bool)),
432
            m_guiController, SLOT(setHorizontalScrollBarSynchronization(bool)));
jkobus's avatar
jkobus committed
433
    connect(toggleDescription, SIGNAL(clicked(bool)),
434
            m_guiController, SLOT(setDescriptionVisible(bool)));
jkobus's avatar
jkobus committed
435 436 437 438
    connect(m_diffEditorSwitcher, SIGNAL(clicked()),
            this, SLOT(slotDiffEditorSwitched()));
    connect(reloadButton, SIGNAL(clicked()),
            m_controller, SLOT(requestReload()));
439 440
    connect(m_controller, SIGNAL(reloaderChanged(DiffEditorReloader*)),
            this, SLOT(slotReloaderChanged(DiffEditorReloader*)));
jkobus's avatar
jkobus committed
441

442
    return m_toolBar;
443 444
}

jkobus's avatar
jkobus committed
445
DiffEditorController *DiffEditor::controller() const
jkobus's avatar
jkobus committed
446
{
447
    return m_controller;
jkobus's avatar
jkobus committed
448 449 450 451 452 453 454 455 456 457
}

void DiffEditor::updateEntryToolTip()
{
    const QString &toolTip = m_entriesComboBox->itemData(
                m_entriesComboBox->currentIndex(), Qt::ToolTipRole).toString();
    m_entriesComboBox->setToolTip(toolTip);
}

void DiffEditor::entryActivated(int index)
jkobus's avatar
jkobus committed
458
{
jkobus's avatar
jkobus committed
459
    updateEntryToolTip();
460
    m_guiController->setCurrentDiffFileIndex(index);
jkobus's avatar
jkobus committed
461 462 463 464 465 466 467 468 469 470
}

void DiffEditor::slotCleared(const QString &message)
{
    Q_UNUSED(message)

    m_entriesComboBox->clear();
    updateEntryToolTip();
}

jkobus's avatar
jkobus committed
471 472
void DiffEditor::slotDiffFilesChanged(const QList<FileData> &diffFileList,
                                      const QString &workingDirectory)
jkobus's avatar
jkobus committed
473 474 475
{
    Q_UNUSED(workingDirectory)

jkobus's avatar
jkobus committed
476 477 478
    m_entriesComboBox->clear();
    const int count = diffFileList.count();
    for (int i = 0; i < count; i++) {
jkobus's avatar
jkobus committed
479 480
        const DiffFileInfo leftEntry = diffFileList.at(i).leftFileInfo;
        const DiffFileInfo rightEntry = diffFileList.at(i).rightFileInfo;
jkobus's avatar
jkobus committed
481 482 483 484 485 486 487 488 489 490 491
        const QString leftShortFileName = QFileInfo(leftEntry.fileName).fileName();
        const QString rightShortFileName = QFileInfo(rightEntry.fileName).fileName();
        QString itemText;
        QString itemToolTip;
        if (leftEntry.fileName == rightEntry.fileName) {
            itemText = leftShortFileName;

            if (leftEntry.typeInfo.isEmpty() && rightEntry.typeInfo.isEmpty()) {
                itemToolTip = leftEntry.fileName;
            } else {
                itemToolTip = tr("[%1] vs. [%2] %3")
jkobus's avatar
jkobus committed
492 493 494
                        .arg(leftEntry.typeInfo,
                             rightEntry.typeInfo,
                             leftEntry.fileName);
jkobus's avatar
jkobus committed
495 496 497 498 499 500
            }
        } else {
            if (leftShortFileName == rightShortFileName) {
                itemText = leftShortFileName;
            } else {
                itemText = tr("%1 vs. %2")
jkobus's avatar
jkobus committed
501 502
                        .arg(leftShortFileName,
                             rightShortFileName);
jkobus's avatar
jkobus committed
503 504 505 506
            }

            if (leftEntry.typeInfo.isEmpty() && rightEntry.typeInfo.isEmpty()) {
                itemToolTip = tr("%1 vs. %2")
jkobus's avatar
jkobus committed
507 508
                        .arg(leftEntry.fileName,
                             rightEntry.fileName);
jkobus's avatar
jkobus committed
509 510
            } else {
                itemToolTip = tr("[%1] %2 vs. [%3] %4")
jkobus's avatar
jkobus committed
511 512 513 514
                        .arg(leftEntry.typeInfo,
                             leftEntry.fileName,
                             rightEntry.typeInfo,
                             rightEntry.fileName);
jkobus's avatar
jkobus committed
515 516 517
            }
        }
        m_entriesComboBox->addItem(itemText);
jkobus's avatar
jkobus committed
518 519
        m_entriesComboBox->setItemData(m_entriesComboBox->count() - 1,
                                       itemToolTip, Qt::ToolTipRole);
jkobus's avatar
jkobus committed
520 521 522 523
    }
    updateEntryToolTip();
}

524
void DiffEditor::activateEntry(int index)
jkobus's avatar
jkobus committed
525 526 527 528 529 530 531
{
    m_entriesComboBox->blockSignals(true);
    m_entriesComboBox->setCurrentIndex(index);
    m_entriesComboBox->blockSignals(false);
    updateEntryToolTip();
}

Jarek Kobus's avatar
Jarek Kobus committed
532 533 534 535 536 537 538
void DiffEditor::slotDescriptionChanged(const QString &description)
{
    m_descriptionWidget->setPlainText(description);
}

void DiffEditor::slotDescriptionVisibilityChanged()
{
539 540
    const bool enabled = m_controller->isDescriptionEnabled();
    const bool visible = m_guiController->isDescriptionVisible();
Jarek Kobus's avatar
Jarek Kobus committed
541 542 543 544 545 546

    m_descriptionWidget->setVisible(visible && enabled);

    if (!m_toggleDescriptionAction)
        return;

547
    QWidget *toggle = m_toolBar->widgetForAction(m_toggleDescriptionAction);
Jarek Kobus's avatar
Jarek Kobus committed
548 549 550 551 552 553
    if (visible)
        toggle->setToolTip(tr("Hide Change Description"));
    else
        toggle->setToolTip(tr("Show Change Description"));

    m_toggleDescriptionAction->setVisible(enabled);
jkobus's avatar
jkobus committed
554 555
}

556 557 558 559 560
void DiffEditor::slotReloaderChanged(DiffEditorReloader *reloader)
{
    m_reloadAction->setVisible(reloader);
}

jkobus's avatar
jkobus committed
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
void DiffEditor::slotDiffEditorSwitched()
{
    QWidget *oldEditor = m_currentEditor;
    QWidget *newEditor = 0;
    if (oldEditor == m_sideBySideEditor)
        newEditor = m_unifiedEditor;
    else if (oldEditor == m_unifiedEditor)
        newEditor = m_sideBySideEditor;
    else
        newEditor = readCurrentDiffEditorSetting();

    showDiffEditor(newEditor);
}

void DiffEditor::updateDiffEditorSwitcher()
{
    if (!m_diffEditorSwitcher)
        return;

    QIcon actionIcon;
    QString actionToolTip;
    if (m_currentEditor == m_unifiedEditor) {
        actionIcon = QIcon(QLatin1String(Constants::ICON_SIDE_BY_SIDE_DIFF));
        actionToolTip = tr("Switch to Side By Side Diff Editor");
    } else if (m_currentEditor == m_sideBySideEditor) {
        actionIcon = QIcon(QLatin1String(Constants::ICON_UNIFIED_DIFF));
        actionToolTip = tr("Switch to Unified Diff Editor");
    }
Jarek Kobus's avatar
Jarek Kobus committed
589

jkobus's avatar
jkobus committed
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
    m_diffEditorSwitcher->setIcon(actionIcon);
    m_diffEditorSwitcher->setToolTip(actionToolTip);
}

void DiffEditor::showDiffEditor(QWidget *newEditor)
{
    if (m_currentEditor == newEditor)
        return;

    if (m_currentEditor == m_sideBySideEditor)
        m_sideBySideEditor->setDiffEditorGuiController(0);
    else if (m_currentEditor == m_unifiedEditor)
        m_unifiedEditor->setDiffEditorGuiController(0);

    m_currentEditor = newEditor;

    if (m_currentEditor == m_unifiedEditor)
        m_unifiedEditor->setDiffEditorGuiController(m_guiController);
    else if (m_currentEditor == m_sideBySideEditor)
        m_sideBySideEditor->setDiffEditorGuiController(m_guiController);

    m_stackedWidget->setCurrentWidget(m_currentEditor);

    writeCurrentDiffEditorSetting(m_currentEditor);
    updateDiffEditorSwitcher();
jkobus's avatar
jkobus committed
615
    widget()->setFocusProxy(m_currentEditor);
jkobus's avatar
jkobus committed
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
}

QWidget *DiffEditor::readLegacyCurrentDiffEditorSetting()
{
    QSettings *s = Core::ICore::settings();

    s->beginGroup(QLatin1String(legacySettingsGroupC));
    const bool legacyExists = s->contains(QLatin1String(useDiffEditorKeyC));
    const bool legacyEditor = s->value(
                QLatin1String(useDiffEditorKeyC), true).toBool();
    if (legacyExists)
        s->remove(QLatin1String(useDiffEditorKeyC));
    s->endGroup();

    QWidget *currentEditor = m_sideBySideEditor;
    if (!legacyEditor)
        currentEditor = m_unifiedEditor;

    if (legacyExists && currentEditor == m_unifiedEditor)
        writeCurrentDiffEditorSetting(currentEditor);

    return currentEditor;
}

QWidget *DiffEditor::readCurrentDiffEditorSetting()
{
    // replace it with m_sideBySideEditor when dropping legacy stuff
    QWidget *defaultEditor = readLegacyCurrentDiffEditorSetting();

    QSettings *s = Core::ICore::settings();
    s->beginGroup(QLatin1String(settingsGroupC));
    const QString editorString = s->value(
                QLatin1String(diffEditorTypeKeyC)).toString();
    s->endGroup();
    if (editorString == QLatin1String(unifiedDiffEditorValueC))
        return m_unifiedEditor;

    if (editorString == QLatin1String(sideBySideDiffEditorValueC))
        return m_sideBySideEditor;

    return defaultEditor;
}

void DiffEditor::writeCurrentDiffEditorSetting(QWidget *currentEditor)
{
    const QString editorString = currentEditor == m_unifiedEditor
            ? QLatin1String(unifiedDiffEditorValueC)
            : QLatin1String(sideBySideDiffEditorValueC);
    QSettings *s = Core::ICore::settings();
    s->beginGroup(QLatin1String(settingsGroupC));
    s->setValue(QLatin1String(diffEditorTypeKeyC), editorString);
    s->endGroup();
Jarek Kobus's avatar
Jarek Kobus committed
668 669
}

670
} // namespace DiffEditor
Jarek Kobus's avatar
Jarek Kobus committed
671 672

#include "diffeditor.moc"