bazaarplugin.cpp 26.1 KB
Newer Older
cerf's avatar
cerf committed
1 2 3 4 5 6
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Hugues Delorme
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
cerf's avatar
cerf committed
8 9 10 11
**
**
** GNU Lesser General Public License Usage
**
hjk's avatar
hjk committed
12 13 14 15 16 17
** 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.
cerf's avatar
cerf committed
18 19
**
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
cerf's avatar
cerf committed
21 22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23 24 25 26 27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
cerf's avatar
cerf committed
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
cerf's avatar
cerf committed
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
**
**************************************************************************/

#include "bazaarplugin.h"
#include "constants.h"
#include "bazaarclient.h"
#include "bazaarcontrol.h"
#include "optionspage.h"
#include "bazaarcommitwidget.h"
#include "bazaareditor.h"
#include "pullorpushdialog.h"
#include "commiteditor.h"
#include "clonewizard.h"

#include "ui_revertdialog.h"

#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
49
#include <coreplugin/id.h>
cerf's avatar
cerf committed
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
#include <coreplugin/vcsmanager.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
#include <coreplugin/filemanager.h>
#include <coreplugin/editormanager/editormanager.h>

#include <locator/commandlocator.h>

#include <utils/parameteraction.h>
#include <utils/qtcassert.h>

#include <vcsbase/basevcseditorfactory.h>
#include <vcsbase/basevcssubmiteditorfactory.h>
#include <vcsbase/vcsbasesubmiteditor.h>
#include <vcsbase/vcsbaseeditor.h>
#include <vcsbase/vcsbaseoutputwindow.h>

#include <QtCore/QtPlugin>
#include <QtGui/QAction>
#include <QtGui/QMenu>
#include <QtGui/QMainWindow>
#include <QtCore/QtDebug>
#include <QtCore/QtGlobal>
#include <QtCore/QDir>
#include <QtGui/QDialog>
#include <QtGui/QFileDialog>
#include <QtCore/QTemporaryFile>


using namespace Bazaar::Internal;
using namespace Bazaar;

hjk's avatar
hjk committed
82
static const VcsBase::VcsBaseEditorParameters editorParameters[] = {
cerf's avatar
cerf committed
83
    {
hjk's avatar
hjk committed
84
        VcsBase::RegularCommandOutput, //type
cerf's avatar
cerf committed
85 86 87 88 89 90
        Constants::COMMANDLOG_ID, // id
        Constants::COMMANDLOG_DISPLAY_NAME, // display name
        Constants::COMMANDLOG, // context
        Constants::COMMANDAPP, // mime type
        Constants::COMMANDEXT}, //extension

hjk's avatar
hjk committed
91
    {   VcsBase::LogOutput,
cerf's avatar
cerf committed
92 93 94 95 96 97
        Constants::FILELOG_ID,
        Constants::FILELOG_DISPLAY_NAME,
        Constants::FILELOG,
        Constants::LOGAPP,
        Constants::LOGEXT},

hjk's avatar
hjk committed
98
    {    VcsBase::AnnotateOutput,
cerf's avatar
cerf committed
99 100 101 102 103 104
         Constants::ANNOTATELOG_ID,
         Constants::ANNOTATELOG_DISPLAY_NAME,
         Constants::ANNOTATELOG,
         Constants::ANNOTATEAPP,
         Constants::ANNOTATEEXT},

hjk's avatar
hjk committed
105
    {   VcsBase::DiffOutput,
cerf's avatar
cerf committed
106 107 108 109 110 111 112
        Constants::DIFFLOG_ID,
        Constants::DIFFLOG_DISPLAY_NAME,
        Constants::DIFFLOG,
        Constants::DIFFAPP,
        Constants::DIFFEXT}
};

hjk's avatar
hjk committed
113
static const VcsBase::VcsBaseSubmitEditorParameters submitEditorParameters = {
cerf's avatar
cerf committed
114 115 116 117 118 119 120 121 122
    Constants::COMMITMIMETYPE,
    Constants::COMMIT_ID,
    Constants::COMMIT_DISPLAY_NAME,
    Constants::COMMIT_ID
};


BazaarPlugin *BazaarPlugin::m_instance = 0;

123
BazaarPlugin::BazaarPlugin()
hjk's avatar
hjk committed
124
    : VcsBase::VcsBasePlugin(QLatin1String(Constants::COMMIT_ID)),
125 126 127 128 129 130 131 132
      m_optionsPage(0),
      m_client(0),
      m_core(0),
      m_commandLocator(0),
      m_changeLog(0),
      m_addAction(0),
      m_deleteAction(0),
      m_menuAction(0)
cerf's avatar
cerf committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
{
    m_instance = this;
}

BazaarPlugin::~BazaarPlugin()
{
    if (m_client) {
        delete m_client;
        m_client = 0;
    }

    deleteCommitLog();

    m_instance = 0;
}

149
bool BazaarPlugin::initialize(const QStringList &arguments, QString *errorMessage)
cerf's avatar
cerf committed
150
{
151 152 153
    Q_UNUSED(arguments);
    Q_UNUSED(errorMessage);

hjk's avatar
hjk committed
154
    typedef VcsBase::VcsEditorFactory<BazaarEditor> BazaarEditorFactory;
cerf's avatar
cerf committed
155

156
    m_client = new BazaarClient(&m_bazaarSettings);
157
    initializeVcs(new BazaarControl(m_client));
cerf's avatar
cerf committed
158 159 160 161 162 163

    m_core = Core::ICore::instance();
    m_actionManager = m_core->actionManager();

    m_optionsPage = new OptionsPage();
    addAutoReleasedObject(m_optionsPage);
164
    m_bazaarSettings.readSettings(m_core->settings());
cerf's avatar
cerf committed
165 166 167 168

    connect(m_client, SIGNAL(changed(QVariant)), versionControl(), SLOT(changed(QVariant)));

    static const char *describeSlot = SLOT(view(QString,QString));
hjk's avatar
hjk committed
169
    const int editorCount = sizeof(editorParameters) / sizeof(VcsBase::VcsBaseEditorParameters);
cerf's avatar
cerf committed
170 171 172
    for (int i = 0; i < editorCount; i++)
        addAutoReleasedObject(new BazaarEditorFactory(editorParameters + i, m_client, describeSlot));

hjk's avatar
hjk committed
173
    addAutoReleasedObject(new VcsBase::VcsSubmitEditorFactory<CommitEditor>(&submitEditorParameters));
cerf's avatar
cerf committed
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205

    addAutoReleasedObject(new CloneWizard);

    const QString prefix = QLatin1String("bzr");
    m_commandLocator = new Locator::CommandLocator(QLatin1String("Bazaar"), prefix, prefix);
    addAutoReleasedObject(m_commandLocator);

    createMenu();

    createSubmitEditorActions();

    return true;
}

BazaarPlugin *BazaarPlugin::instance()
{
    return m_instance;
}

BazaarClient *BazaarPlugin::client() const
{
    return m_client;
}

const BazaarSettings &BazaarPlugin::settings() const
{
    return m_bazaarSettings;
}

void BazaarPlugin::setSettings(const BazaarSettings &settings)
{
    if (settings != m_bazaarSettings) {
cerf's avatar
cerf committed
206 207 208 209
        const bool userIdChanged = !m_bazaarSettings.sameUserId(settings);
        m_bazaarSettings = settings;
        if (userIdChanged)
            client()->synchronousSetUserId();
210
        static_cast<BazaarControl *>(versionControl())->emitConfigurationChanged();
cerf's avatar
cerf committed
211 212 213 214 215 216 217 218 219 220 221 222 223
    }
}

void BazaarPlugin::createMenu()
{
    Core::Context context(Core::Constants::C_GLOBAL);

    // Create menu item for Bazaar
    m_bazaarContainer = m_actionManager->createMenu(Core::Id("Bazaar.BazaarMenu"));
    QMenu *menu = m_bazaarContainer->menu();
    menu->setTitle(tr("Bazaar"));

    createFileActions(context);
224
    createSeparator(context, Core::Id("Bazaar.FileDirSeperator"));
cerf's avatar
cerf committed
225
    createDirectoryActions(context);
226
    createSeparator(context, Core::Id("Bazaar.DirRepoSeperator"));
cerf's avatar
cerf committed
227
    createRepositoryActions(context);
228
    createSeparator(context, Core::Id("Bazaar.Repository Management"));
cerf's avatar
cerf committed
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

    // Request the Tools menu and add the Bazaar menu to it
    Core::ActionContainer *toolsMenu = m_actionManager->actionContainer(Core::Id(Core::Constants::M_TOOLS));
    toolsMenu->addMenu(m_bazaarContainer);
    m_menuAction = m_bazaarContainer->menu()->menuAction();
}

void BazaarPlugin::createFileActions(const Core::Context &context)
{
    Core::Command *command;

    m_annotateFile = new Utils::ParameterAction(tr("Annotate Current File"), tr("Annotate \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
    command = m_actionManager->registerAction(m_annotateFile, Core::Id(Constants::ANNOTATE), context);
    command->setAttribute(Core::Command::CA_UpdateText);
    connect(m_annotateFile, SIGNAL(triggered()), this, SLOT(annotateCurrentFile()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    m_diffFile = new Utils::ParameterAction(tr("Diff Current File"), tr("Diff \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
    command = m_actionManager->registerAction(m_diffFile, Core::Id(Constants::DIFF), context);
    command->setAttribute(Core::Command::CA_UpdateText);
250
    command->setDefaultKeySequence(QKeySequence(tr("ALT+Z,Alt+D")));
cerf's avatar
cerf committed
251 252 253 254 255 256 257
    connect(m_diffFile, SIGNAL(triggered()), this, SLOT(diffCurrentFile()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    m_logFile = new Utils::ParameterAction(tr("Log Current File"), tr("Log \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
    command = m_actionManager->registerAction(m_logFile, Core::Id(Constants::LOG), context);
    command->setAttribute(Core::Command::CA_UpdateText);
258
    command->setDefaultKeySequence(QKeySequence(tr("ALT+Z,Alt+L")));
cerf's avatar
cerf committed
259 260 261 262 263 264 265
    connect(m_logFile, SIGNAL(triggered()), this, SLOT(logCurrentFile()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    m_statusFile = new Utils::ParameterAction(tr("Status Current File"), tr("Status \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
    command = m_actionManager->registerAction(m_statusFile, Core::Id(Constants::STATUS), context);
    command->setAttribute(Core::Command::CA_UpdateText);
266
    command->setDefaultKeySequence(QKeySequence(tr("ALT+Z,Alt+S")));
cerf's avatar
cerf committed
267 268 269 270
    connect(m_statusFile, SIGNAL(triggered()), this, SLOT(statusCurrentFile()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

271
    createSeparator(context, Core::Id("Bazaar.FileDirSeperator1"));
cerf's avatar
cerf committed
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296

    m_addAction = new Utils::ParameterAction(tr("Add"), tr("Add \"%1\""), Utils::ParameterAction::EnabledWithParameter, this);
    command = m_actionManager->registerAction(m_addAction, Core::Id(Constants::ADD), context);
    command->setAttribute(Core::Command::CA_UpdateText);
    connect(m_addAction, SIGNAL(triggered()), this, SLOT(addCurrentFile()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    m_deleteAction = new Utils::ParameterAction(tr("Delete..."), tr("Delete \"%1\"..."), Utils::ParameterAction::EnabledWithParameter, this);
    command = m_actionManager->registerAction(m_deleteAction, Core::Id(Constants::DELETE), context);
    command->setAttribute(Core::Command::CA_UpdateText);
    connect(m_deleteAction, SIGNAL(triggered()), this, SLOT(promptToDeleteCurrentFile()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    m_revertFile = new Utils::ParameterAction(tr("Revert Current File..."), tr("Revert \"%1\"..."), Utils::ParameterAction::EnabledWithParameter, this);
    command = m_actionManager->registerAction(m_revertFile, Core::Id(Constants::REVERT), context);
    command->setAttribute(Core::Command::CA_UpdateText);
    connect(m_revertFile, SIGNAL(triggered()), this, SLOT(revertCurrentFile()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);
}

void BazaarPlugin::addCurrentFile()
{
hjk's avatar
hjk committed
297
    const VcsBase::VcsBasePluginState state = currentState();
Tobias Hunger's avatar
Tobias Hunger committed
298 299
    QTC_ASSERT(state.hasFile(), return);
    m_client->synchronousAdd(state.currentFileTopLevel(), state.relativeCurrentFile());
cerf's avatar
cerf committed
300 301 302 303
}

void BazaarPlugin::annotateCurrentFile()
{
hjk's avatar
hjk committed
304
    const VcsBase::VcsBasePluginState state = currentState();
Tobias Hunger's avatar
Tobias Hunger committed
305 306
    QTC_ASSERT(state.hasFile(), return);
    m_client->annotate(state.currentFileTopLevel(), state.relativeCurrentFile());
cerf's avatar
cerf committed
307 308 309 310
}

void BazaarPlugin::diffCurrentFile()
{
hjk's avatar
hjk committed
311
    const VcsBase::VcsBasePluginState state = currentState();
Tobias Hunger's avatar
Tobias Hunger committed
312 313
    QTC_ASSERT(state.hasFile(), return);
    m_client->diff(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()));
cerf's avatar
cerf committed
314 315 316 317
}

void BazaarPlugin::logCurrentFile()
{
hjk's avatar
hjk committed
318
    const VcsBase::VcsBasePluginState state = currentState();
Tobias Hunger's avatar
Tobias Hunger committed
319
    QTC_ASSERT(state.hasFile(), return);
320
    m_client->log(state.currentFileTopLevel(), QStringList(state.relativeCurrentFile()),
321
                  QStringList(), true);
cerf's avatar
cerf committed
322 323 324 325
}

void BazaarPlugin::revertCurrentFile()
{
hjk's avatar
hjk committed
326
    const VcsBase::VcsBasePluginState state = currentState();
cerf's avatar
cerf committed
327 328 329 330 331 332 333 334 335 336 337 338 339 340
    QTC_ASSERT(state.hasFile(), return);

    QDialog dialog;
    Ui::RevertDialog revertUi;
    revertUi.setupUi(&dialog);
    if (dialog.exec() != QDialog::Accepted)
        return;
    m_client->revertFile(state.currentFileTopLevel(),
                         state.relativeCurrentFile(),
                         revertUi.revisionLineEdit->text());
}

void BazaarPlugin::statusCurrentFile()
{
hjk's avatar
hjk committed
341
    const VcsBase::VcsBasePluginState state = currentState();
Tobias Hunger's avatar
Tobias Hunger committed
342 343
    QTC_ASSERT(state.hasFile(), return);
    m_client->status(state.currentFileTopLevel(), state.relativeCurrentFile());
cerf's avatar
cerf committed
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
}

void BazaarPlugin::createDirectoryActions(const Core::Context &context)
{
    QAction *action;
    Core::Command *command;

    action = new QAction(tr("Diff"), this);
    m_repositoryActionList.append(action);
    command = m_actionManager->registerAction(action, Core::Id(Constants::DIFFMULTI), context);
    connect(action, SIGNAL(triggered()), this, SLOT(diffRepository()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    action = new QAction(tr("Log"), this);
    m_repositoryActionList.append(action);
    command = m_actionManager->registerAction(action, Core::Id(Constants::LOGMULTI), context);
    connect(action, SIGNAL(triggered()), this, SLOT(logRepository()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    action = new QAction(tr("Revert..."), this);
    m_repositoryActionList.append(action);
    command = m_actionManager->registerAction(action, Core::Id(Constants::REVERTMULTI), context);
    connect(action, SIGNAL(triggered()), this, SLOT(revertAll()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    action = new QAction(tr("Status"), this);
    m_repositoryActionList.append(action);
    command = m_actionManager->registerAction(action, Core::Id(Constants::STATUSMULTI), context);
    connect(action, SIGNAL(triggered()), this, SLOT(statusMulti()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);
}


void BazaarPlugin::diffRepository()
{
hjk's avatar
hjk committed
383
    const VcsBase::VcsBasePluginState state = currentState();
Tobias Hunger's avatar
Tobias Hunger committed
384 385
    QTC_ASSERT(state.hasTopLevel(), return);
    m_client->diff(state.topLevel());
cerf's avatar
cerf committed
386 387 388 389
}

void BazaarPlugin::logRepository()
{
hjk's avatar
hjk committed
390
    const VcsBase::VcsBasePluginState state = currentState();
Tobias Hunger's avatar
Tobias Hunger committed
391
    QTC_ASSERT(state.hasTopLevel(), return);
392
    QStringList extraOptions;
393
    extraOptions += QString("--limit=%1").arg(settings().intValue(BazaarSettings::logCountKey));
394
    m_client->log(state.topLevel(), QStringList(), extraOptions);
cerf's avatar
cerf committed
395 396 397 398
}

void BazaarPlugin::revertAll()
{
hjk's avatar
hjk committed
399
    const VcsBase::VcsBasePluginState state = currentState();
cerf's avatar
cerf committed
400 401 402 403 404 405 406 407 408 409 410 411
    QTC_ASSERT(state.hasTopLevel(), return);

    QDialog dialog;
    Ui::RevertDialog revertUi;
    revertUi.setupUi(&dialog);
    if (dialog.exec() != QDialog::Accepted)
        return;
    m_client->revertAll(state.topLevel(), revertUi.revisionLineEdit->text());
}

void BazaarPlugin::statusMulti()
{
hjk's avatar
hjk committed
412
    const VcsBase::VcsBasePluginState state = currentState();
cerf's avatar
cerf committed
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
    QTC_ASSERT(state.hasTopLevel(), return);
    m_client->status(state.topLevel());
}

void BazaarPlugin::createRepositoryActions(const Core::Context &context)
{
    QAction *action = 0;
    Core::Command *command = 0;

    action = new QAction(tr("Pull..."), this);
    m_repositoryActionList.append(action);
    command = m_actionManager->registerAction(action, Core::Id(Constants::PULL), context);
    connect(action, SIGNAL(triggered()), this, SLOT(pull()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    action = new QAction(tr("Push..."), this);
    m_repositoryActionList.append(action);
    command = m_actionManager->registerAction(action, Core::Id(Constants::PUSH), context);
    connect(action, SIGNAL(triggered()), this, SLOT(push()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    action = new QAction(tr("Update..."), this);
    m_repositoryActionList.append(action);
    command = m_actionManager->registerAction(action, Core::Id(Constants::UPDATE), context);
    connect(action, SIGNAL(triggered()), this, SLOT(update()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

    action = new QAction(tr("Commit..."), this);
    m_repositoryActionList.append(action);
    command = m_actionManager->registerAction(action, Core::Id(Constants::COMMIT), context);
446
    command->setDefaultKeySequence(QKeySequence(tr("ALT+Z,Alt+C")));
cerf's avatar
cerf committed
447 448 449 450
    connect(action, SIGNAL(triggered()), this, SLOT(commit()));
    m_bazaarContainer->addAction(command);
    m_commandLocator->appendCommand(command);

cerf's avatar
cerf committed
451
    QAction *createRepositoryAction = new QAction(tr("Create Repository..."), this);
cerf's avatar
cerf committed
452 453 454 455 456 457 458
    command = m_actionManager->registerAction(createRepositoryAction, Core::Id(Constants::CREATE_REPOSITORY), context);
    connect(createRepositoryAction, SIGNAL(triggered()), this, SLOT(createRepository()));
    m_bazaarContainer->addAction(command);
}

void BazaarPlugin::pull()
{
hjk's avatar
hjk committed
459
    const VcsBase::VcsBasePluginState state = currentState();
cerf's avatar
cerf committed
460 461 462 463 464
    QTC_ASSERT(state.hasTopLevel(), return);

    PullOrPushDialog dialog(PullOrPushDialog::PullMode);
    if (dialog.exec() != QDialog::Accepted)
        return;
465 466 467 468 469 470 471 472 473
    QStringList extraOptions;
    if (dialog.isRememberOptionEnabled())
        extraOptions += QLatin1String("--remember");
    if (dialog.isOverwriteOptionEnabled())
        extraOptions += QLatin1String("--overwrite");
    if (dialog.isLocalOptionEnabled())
        extraOptions += QLatin1String("--local");
    if (!dialog.revision().isEmpty())
        extraOptions << QLatin1String("-r") << dialog.revision();
cerf's avatar
cerf committed
474 475 476 477 478
    m_client->synchronousPull(state.topLevel(), dialog.branchLocation(), extraOptions);
}

void BazaarPlugin::push()
{
hjk's avatar
hjk committed
479
    const VcsBase::VcsBasePluginState state = currentState();
cerf's avatar
cerf committed
480 481 482 483 484
    QTC_ASSERT(state.hasTopLevel(), return);

    PullOrPushDialog dialog(PullOrPushDialog::PushMode);
    if (dialog.exec() != QDialog::Accepted)
        return;
485 486 487 488 489 490 491 492 493 494 495
    QStringList extraOptions;
    if (dialog.isRememberOptionEnabled())
        extraOptions += QLatin1String("--remember");
    if (dialog.isOverwriteOptionEnabled())
        extraOptions += QLatin1String("--overwrite");
    if (dialog.isUseExistingDirectoryOptionEnabled())
        extraOptions += QLatin1String("--use-existing-dir");
    if (dialog.isCreatePrefixOptionEnabled())
        extraOptions += QLatin1String("--create-prefix");
    if (!dialog.revision().isEmpty())
        extraOptions << QLatin1String("-r") << dialog.revision();
cerf's avatar
cerf committed
496 497 498 499 500
    m_client->synchronousPush(state.topLevel(), dialog.branchLocation(), extraOptions);
}

void BazaarPlugin::update()
{
hjk's avatar
hjk committed
501
    const VcsBase::VcsBasePluginState state = currentState();
cerf's avatar
cerf committed
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
    QTC_ASSERT(state.hasTopLevel(), return);

    QDialog dialog;
    Ui::RevertDialog revertUi;
    revertUi.setupUi(&dialog);
    dialog.setWindowTitle(tr("Update"));
    if (dialog.exec() != QDialog::Accepted)
        return;
    m_client->update(state.topLevel(), revertUi.revisionLineEdit->text());
}

void BazaarPlugin::createSubmitEditorActions()
{
    Core::Context context(Constants::COMMIT_ID);
    Core::Command *command;

hjk's avatar
hjk committed
518
    m_editorCommit = new QAction(VcsBase::VcsBaseSubmitEditor::submitIcon(), tr("Commit"), this);
cerf's avatar
cerf committed
519 520 521 522
    command = m_actionManager->registerAction(m_editorCommit, Core::Id(Constants::COMMIT), context);
    command->setAttribute(Core::Command::CA_UpdateText);
    connect(m_editorCommit, SIGNAL(triggered()), this, SLOT(commitFromEditor()));

hjk's avatar
hjk committed
523
    m_editorDiff = new QAction(VcsBase::VcsBaseSubmitEditor::diffIcon(), tr("Diff &Selected Files"), this);
cerf's avatar
cerf committed
524 525 526 527 528 529 530 531 532 533 534
    command = m_actionManager->registerAction(m_editorDiff, Core::Id(Constants::DIFFEDITOR), context);

    m_editorUndo = new QAction(tr("&Undo"), this);
    command = m_actionManager->registerAction(m_editorUndo, Core::Id(Core::Constants::UNDO), context);

    m_editorRedo = new QAction(tr("&Redo"), this);
    command = m_actionManager->registerAction(m_editorRedo, Core::Id(Core::Constants::REDO), context);
}

void BazaarPlugin::commit()
{
hjk's avatar
hjk committed
535
    if (VcsBase::VcsBaseSubmitEditor::raiseSubmitEditor())
cerf's avatar
cerf committed
536 537
        return;

hjk's avatar
hjk committed
538
    const VcsBase::VcsBasePluginState state = currentState();
cerf's avatar
cerf committed
539 540 541 542
    QTC_ASSERT(state.hasTopLevel(), return);

    m_submitRepository = state.topLevel();

hjk's avatar
hjk committed
543 544
    connect(m_client, SIGNAL(parsedStatus(QList<VcsBase::VcsBaseClient::StatusItem>)),
            this, SLOT(showCommitWidget(QList<VcsBase::VcsBaseClient::StatusItem>)));
545 546
    // The "--short" option allows to easily parse status output
    m_client->emitParsedStatus(m_submitRepository, QStringList(QLatin1String("--short")));
cerf's avatar
cerf committed
547 548
}

hjk's avatar
hjk committed
549
void BazaarPlugin::showCommitWidget(const QList<VcsBase::VcsBaseClient::StatusItem> &status)
cerf's avatar
cerf committed
550
{
hjk's avatar
hjk committed
551
    VcsBase::VcsBaseOutputWindow *outputWindow = VcsBase::VcsBaseOutputWindow::instance();
cerf's avatar
cerf committed
552
    //Once we receive our data release the connection so it can be reused elsewhere
hjk's avatar
hjk committed
553 554
    disconnect(m_client, SIGNAL(parsedStatus(QList<VcsBase::VcsBaseClient::StatusItem>)),
               this, SLOT(showCommitWidget(QList<VcsBase::VcsBaseClient::StatusItem>)));
cerf's avatar
cerf committed
555 556 557 558 559 560 561 562 563

    if (status.isEmpty()) {
        outputWindow->appendError(tr("There are no changes to commit."));
        return;
    }

    deleteCommitLog();

    // Open commit log
564 565 566 567 568
    QString changeLogPattern = QDir::tempPath();
    if (!changeLogPattern.endsWith(QLatin1Char('/')))
        changeLogPattern += QLatin1Char('/');
    changeLogPattern += QLatin1String("qtcreator-bzr-XXXXXX.msg");
    m_changeLog = new QTemporaryFile(changeLogPattern, this);
cerf's avatar
cerf committed
569 570 571 572 573 574
    if (!m_changeLog->open()) {
        outputWindow->appendError(tr("Unable to generate a temporary file for the commit editor."));
        return;
    }

    Core::IEditor *editor = m_core->editorManager()->openEditor(m_changeLog->fileName(),
hjk's avatar
hjk committed
575
                                                                Constants::COMMIT_ID,
cerf's avatar
cerf committed
576 577 578 579 580 581 582 583 584 585 586 587 588
                                                                Core::EditorManager::ModeSwitch);
    if (!editor) {
        outputWindow->appendError(tr("Unable to create an editor for the commit."));
        return;
    }

    CommitEditor *commitEditor = qobject_cast<CommitEditor *>(editor);

    if (!commitEditor) {
        outputWindow->appendError(tr("Unable to create a commit editor."));
        return;
    }

589 590 591 592 593
    commitEditor->registerActions(m_editorUndo, m_editorRedo, m_editorCommit, m_editorDiff);
    connect(commitEditor, SIGNAL(diffSelectedFiles(QStringList)),
            this, SLOT(diffFromEditorSelected(QStringList)));
    commitEditor->setCheckScriptWorkingDirectory(m_submitRepository);

cerf's avatar
cerf committed
594 595 596 597 598
    const QString msg = tr("Commit changes for \"%1\".").
            arg(QDir::toNativeSeparators(m_submitRepository));
    commitEditor->setDisplayName(msg);

    const BranchInfo branch = m_client->synchronousBranchQuery(m_submitRepository);
599 600
    commitEditor->setFields(m_submitRepository, branch,
                            m_bazaarSettings.stringValue(BazaarSettings::userNameKey),
601
                            m_bazaarSettings.stringValue(BazaarSettings::userEmailKey), status);
cerf's avatar
cerf committed
602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617
}

void BazaarPlugin::diffFromEditorSelected(const QStringList &files)
{
    m_client->diff(m_submitRepository, files);
}

void BazaarPlugin::commitFromEditor()
{
    if (!m_changeLog)
        return;

    //use the same functionality than if the user closes the file without completing the commit
    m_core->editorManager()->closeEditors(m_core->editorManager()->editorsForFileName(m_changeLog->fileName()));
}

hjk's avatar
hjk committed
618
bool BazaarPlugin::submitEditorAboutToClose(VcsBase::VcsBaseSubmitEditor *submitEditor)
cerf's avatar
cerf committed
619 620 621 622 623 624 625 626
{
    if (!m_changeLog)
        return true;
    Core::IFile *editorFile = submitEditor->file();
    const CommitEditor *commitEditor = qobject_cast<const CommitEditor *>(submitEditor);
    if (!editorFile || !commitEditor)
        return true;

627
    bool dummyPrompt = m_bazaarSettings.boolValue(BazaarSettings::promptOnSubmitKey);
hjk's avatar
hjk committed
628
    const VcsBase::VcsBaseSubmitEditor::PromptSubmitResult response =
cerf's avatar
cerf committed
629 630
            commitEditor->promptSubmit(tr("Close Commit Editor"), tr("Do you want to commit the changes?"),
                                       tr("Message check failed. Do you want to proceed?"),
631
                                       &dummyPrompt, dummyPrompt);
cerf's avatar
cerf committed
632 633

    switch (response) {
hjk's avatar
hjk committed
634
    case VcsBase::VcsBaseSubmitEditor::SubmitCanceled:
cerf's avatar
cerf committed
635
        return false;
hjk's avatar
hjk committed
636
    case VcsBase::VcsBaseSubmitEditor::SubmitDiscarded:
cerf's avatar
cerf committed
637 638 639 640 641 642
        deleteCommitLog();
        return true;
    default:
        break;
    }

643
    QStringList files = commitEditor->checkedFiles();
cerf's avatar
cerf committed
644 645
    if (!files.empty()) {
        //save the commit message
646 647
        if (!m_core->fileManager()->saveFile(editorFile))
            return false;
cerf's avatar
cerf committed
648

649 650 651 652 653 654 655 656
        //rewrite entries of the form 'file => newfile' to 'newfile' because
        //this would mess the commit command
        for (QStringList::iterator iFile = files.begin(); iFile != files.end(); ++iFile) {
            const QStringList parts = iFile->split(" => ", QString::SkipEmptyParts);
            if (!parts.isEmpty())
                *iFile = parts.last();
        }

cerf's avatar
cerf committed
657
        const BazaarCommitWidget *commitWidget = commitEditor->commitWidget();
658 659 660 661 662 663 664 665 666 667 668 669
        QStringList extraOptions;
        // Author
        if (!commitWidget->committer().isEmpty())
            extraOptions.append(QLatin1String("--author=") + commitWidget->committer());
        // Fixed bugs
        foreach (const QString &fix, commitWidget->fixedBugs()) {
            if (!fix.isEmpty())
                extraOptions << QLatin1String("--fixes") << fix;
        }
        // Whether local commit or not
        if (commitWidget->isLocalOptionEnabled())
            extraOptions += QLatin1String("--local");
cerf's avatar
cerf committed
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
        m_client->commit(m_submitRepository, files, editorFile->fileName(), extraOptions);
    }
    return true;
}

void BazaarPlugin::deleteCommitLog()
{
    if (m_changeLog) {
        delete m_changeLog;
        m_changeLog = 0;
    }
}

void BazaarPlugin::createSeparator(const Core::Context &context, const Core::Id &id)
{
    QAction *action = new QAction(this);
    action->setSeparator(true);
    m_bazaarContainer->addAction(m_actionManager->registerAction(action, id, context));
}

hjk's avatar
hjk committed
690
void BazaarPlugin::updateActions(VcsBase::VcsBasePlugin::ActionState as)
cerf's avatar
cerf committed
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
{
    if (!enableMenuAction(as, m_menuAction)) {
        m_commandLocator->setEnabled(false);
        return;
    }
    const QString filename = currentState().currentFileName();
    const bool repoEnabled = currentState().hasTopLevel();
    m_commandLocator->setEnabled(repoEnabled);

    m_annotateFile->setParameter(filename);
    m_diffFile->setParameter(filename);
    m_logFile->setParameter(filename);
    m_addAction->setParameter(filename);
    m_deleteAction->setParameter(filename);
    m_revertFile->setParameter(filename);
    m_statusFile->setParameter(filename);

    foreach (QAction *repoAction, m_repositoryActionList)
        repoAction->setEnabled(repoEnabled);
}

Q_EXPORT_PLUGIN(BazaarPlugin)