2009-02-25 09:15:00 +01:00
|
|
|
/**************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
|
|
|
|
** This file is part of Qt Creator
|
|
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2009-06-17 00:01:27 +10:00
|
|
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** Commercial Usage
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** Licensees holding valid Qt Commercial licenses may use this file in
|
|
|
|
|
** accordance with the Qt Commercial License Agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and Nokia.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** 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.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** If you are unsure which license is appropriate for your use, please
|
2009-08-14 09:30:56 +02:00
|
|
|
** contact the sales department at http://qt.nokia.com/contact.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
**************************************************************************/
|
2008-12-02 16:19:05 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "vcsbasesubmiteditor.h"
|
2009-03-19 17:40:01 +01:00
|
|
|
#include "vcsbasesettings.h"
|
2009-12-08 14:26:41 +01:00
|
|
|
#include "vcsplugin.h"
|
2009-03-19 17:40:01 +01:00
|
|
|
#include "nicknamedialog.h"
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "submiteditorfile.h"
|
|
|
|
|
|
2009-03-04 09:38:01 +01:00
|
|
|
#include <aggregation/aggregate.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/ifile.h>
|
2009-03-19 17:40:01 +01:00
|
|
|
#include <coreplugin/icore.h>
|
2009-05-27 16:17:24 +02:00
|
|
|
#include <coreplugin/editormanager/editormanager.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <coreplugin/uniqueidmanager.h>
|
2009-01-13 13:39:31 +01:00
|
|
|
#include <coreplugin/actionmanager/actionmanager.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <utils/submiteditorwidget.h>
|
2009-06-19 16:34:38 +02:00
|
|
|
#include <utils/checkablemessagebox.h>
|
2009-03-23 12:03:20 +01:00
|
|
|
#include <utils/submitfieldwidget.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <find/basetextfind.h>
|
2009-03-25 08:52:39 +01:00
|
|
|
#include <texteditor/fontsettings.h>
|
|
|
|
|
#include <texteditor/texteditorsettings.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2009-01-09 17:52:41 +01:00
|
|
|
#include <projectexplorer/projectexplorer.h>
|
|
|
|
|
#include <projectexplorer/session.h>
|
2009-09-25 11:35:44 +02:00
|
|
|
#include <projectexplorer/project.h>
|
2009-01-09 17:52:41 +01:00
|
|
|
|
2009-01-19 12:39:20 +01:00
|
|
|
#include <QtCore/QDebug>
|
2009-01-09 17:52:41 +01:00
|
|
|
#include <QtCore/QDir>
|
2009-03-19 17:40:01 +01:00
|
|
|
#include <QtCore/QTemporaryFile>
|
|
|
|
|
#include <QtCore/QProcess>
|
2009-01-19 12:39:20 +01:00
|
|
|
#include <QtCore/QFile>
|
|
|
|
|
#include <QtCore/QFileInfo>
|
|
|
|
|
#include <QtCore/QPointer>
|
2008-12-02 12:01:29 +01:00
|
|
|
#include <QtCore/QTextStream>
|
2009-01-19 12:39:20 +01:00
|
|
|
#include <QtGui/QStyle>
|
|
|
|
|
#include <QtGui/QToolBar>
|
2009-03-19 17:40:01 +01:00
|
|
|
#include <QtGui/QAction>
|
|
|
|
|
#include <QtGui/QApplication>
|
|
|
|
|
#include <QtGui/QMessageBox>
|
|
|
|
|
#include <QtGui/QMainWindow>
|
|
|
|
|
#include <QtGui/QCompleter>
|
|
|
|
|
#include <QtGui/QLineEdit>
|
2009-10-01 16:38:08 +02:00
|
|
|
#include <QtGui/QTextEdit>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
enum { debug = 0 };
|
2008-12-02 17:05:53 +01:00
|
|
|
enum { wantToolBar = 0 };
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
namespace VCSBase {
|
|
|
|
|
|
2009-03-19 17:40:01 +01:00
|
|
|
static inline QString submitMessageCheckScript()
|
|
|
|
|
{
|
2009-12-08 14:26:41 +01:00
|
|
|
return Internal::VCSPlugin::instance()->settings().submitMessageCheckScript;
|
2009-03-19 17:40:01 +01:00
|
|
|
}
|
|
|
|
|
|
2009-01-20 11:52:04 +01:00
|
|
|
struct VCSBaseSubmitEditorPrivate
|
|
|
|
|
{
|
2008-12-02 12:01:29 +01:00
|
|
|
VCSBaseSubmitEditorPrivate(const VCSBaseSubmitEditorParameters *parameters,
|
2009-10-05 11:06:05 +02:00
|
|
|
Utils::SubmitEditorWidget *editorWidget,
|
2008-12-02 12:01:29 +01:00
|
|
|
QObject *q);
|
|
|
|
|
|
2009-10-05 11:06:05 +02:00
|
|
|
Utils::SubmitEditorWidget *m_widget;
|
2008-12-02 12:01:29 +01:00
|
|
|
QToolBar *m_toolWidget;
|
|
|
|
|
const VCSBaseSubmitEditorParameters *m_parameters;
|
|
|
|
|
QString m_displayName;
|
|
|
|
|
VCSBase::Internal::SubmitEditorFile *m_file;
|
|
|
|
|
QList<int> m_contexts;
|
|
|
|
|
|
|
|
|
|
QPointer<QAction> m_diffAction;
|
2009-01-13 14:06:42 +01:00
|
|
|
QPointer<QAction> m_submitAction;
|
2009-03-19 17:40:01 +01:00
|
|
|
|
|
|
|
|
Internal::NickNameDialog *m_nickNameDialog;
|
2008-12-02 12:01:29 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VCSBaseSubmitEditorPrivate::VCSBaseSubmitEditorPrivate(const VCSBaseSubmitEditorParameters *parameters,
|
2009-10-05 11:06:05 +02:00
|
|
|
Utils::SubmitEditorWidget *editorWidget,
|
2008-12-02 12:01:29 +01:00
|
|
|
QObject *q) :
|
|
|
|
|
m_widget(editorWidget),
|
|
|
|
|
m_toolWidget(0),
|
|
|
|
|
m_parameters(parameters),
|
2009-03-19 17:40:01 +01:00
|
|
|
m_file(new VCSBase::Internal::SubmitEditorFile(QLatin1String(m_parameters->mimeType), q)),
|
|
|
|
|
m_nickNameDialog(0)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2009-01-21 15:52:34 +01:00
|
|
|
m_contexts << Core::UniqueIDManager::instance()->uniqueIdentifier(m_parameters->context);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VCSBaseSubmitEditor::VCSBaseSubmitEditor(const VCSBaseSubmitEditorParameters *parameters,
|
2009-10-05 11:06:05 +02:00
|
|
|
Utils::SubmitEditorWidget *editorWidget) :
|
2008-12-02 12:01:29 +01:00
|
|
|
m_d(new VCSBaseSubmitEditorPrivate(parameters, editorWidget, this))
|
|
|
|
|
{
|
2009-03-25 16:16:34 +01:00
|
|
|
// Message font according to settings
|
2009-03-25 08:52:39 +01:00
|
|
|
const TextEditor::FontSettings fs = TextEditor::TextEditorSettings::instance()->fontSettings();
|
|
|
|
|
QFont font = editorWidget->descriptionEdit()->font();
|
|
|
|
|
font.setFamily(fs.family());
|
2009-03-25 16:16:34 +01:00
|
|
|
font.setPointSize(fs.fontSize());
|
2009-03-25 08:52:39 +01:00
|
|
|
editorWidget->descriptionEdit()->setFont(font);
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
m_d->m_file->setModified(false);
|
|
|
|
|
// We are always clean to prevent the editor manager from asking to save.
|
|
|
|
|
connect(m_d->m_file, SIGNAL(saveMe(QString)), this, SLOT(save(QString)));
|
|
|
|
|
|
|
|
|
|
connect(m_d->m_widget, SIGNAL(diffSelected(QStringList)), this, SLOT(slotDiffSelectedVCSFiles(QStringList)));
|
|
|
|
|
connect(m_d->m_widget->descriptionEdit(), SIGNAL(textChanged()), this, SLOT(slotDescriptionChanged()));
|
|
|
|
|
|
2009-12-08 14:26:41 +01:00
|
|
|
const Internal::VCSBaseSettings settings = Internal::VCSPlugin::instance()->settings();
|
2009-03-19 17:40:01 +01:00
|
|
|
// Add additional context menu settings
|
2009-03-20 10:16:18 +01:00
|
|
|
if (!settings.submitMessageCheckScript.isEmpty() || !settings.nickNameMailMap.isEmpty()) {
|
2009-03-19 17:40:01 +01:00
|
|
|
QAction *sep = new QAction(this);
|
|
|
|
|
sep->setSeparator(true);
|
|
|
|
|
m_d->m_widget->addDescriptionEditContextMenuAction(sep);
|
|
|
|
|
// Run check action
|
|
|
|
|
if (!settings.submitMessageCheckScript.isEmpty()) {
|
|
|
|
|
QAction *checkAction = new QAction(tr("Check message"), this);
|
|
|
|
|
connect(checkAction, SIGNAL(triggered()), this, SLOT(slotCheckSubmitMessage()));
|
|
|
|
|
m_d->m_widget->addDescriptionEditContextMenuAction(checkAction);
|
|
|
|
|
}
|
|
|
|
|
// Insert nick
|
2009-03-20 10:16:18 +01:00
|
|
|
if (!settings.nickNameMailMap.isEmpty()) {
|
2009-03-19 17:40:01 +01:00
|
|
|
QAction *insertAction = new QAction(tr("Insert name..."), this);
|
|
|
|
|
connect(insertAction, SIGNAL(triggered()), this, SLOT(slotInsertNickName()));
|
|
|
|
|
m_d->m_widget->addDescriptionEditContextMenuAction(insertAction);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Do we have user fields?
|
|
|
|
|
if (!settings.nickNameFieldListFile.isEmpty())
|
|
|
|
|
createUserFields(settings.nickNameFieldListFile);
|
2009-03-20 14:22:20 +01:00
|
|
|
|
|
|
|
|
// wrapping. etc
|
|
|
|
|
slotUpdateEditorSettings(settings);
|
2009-12-08 14:26:41 +01:00
|
|
|
connect(Internal::VCSPlugin::instance(),
|
2009-03-20 14:22:20 +01:00
|
|
|
SIGNAL(settingsChanged(VCSBase::Internal::VCSBaseSettings)),
|
|
|
|
|
this, SLOT(slotUpdateEditorSettings(VCSBase::Internal::VCSBaseSettings)));
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
Aggregation::Aggregate *aggregate = new Aggregation::Aggregate;
|
|
|
|
|
aggregate->add(new Find::BaseTextFind(m_d->m_widget->descriptionEdit()));
|
|
|
|
|
aggregate->add(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VCSBaseSubmitEditor::~VCSBaseSubmitEditor()
|
|
|
|
|
{
|
|
|
|
|
delete m_d->m_toolWidget;
|
|
|
|
|
delete m_d->m_widget;
|
|
|
|
|
delete m_d;
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-20 14:22:20 +01:00
|
|
|
void VCSBaseSubmitEditor::slotUpdateEditorSettings(const Internal::VCSBaseSettings &s)
|
|
|
|
|
{
|
|
|
|
|
setLineWrapWidth(s.lineWrapWidth);
|
|
|
|
|
setLineWrap(s.lineWrap);
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-23 12:03:20 +01:00
|
|
|
// Return a trimmed list of non-empty field texts
|
|
|
|
|
static inline QStringList fieldTexts(const QString &fileContents)
|
|
|
|
|
{
|
|
|
|
|
QStringList rc;
|
|
|
|
|
const QStringList rawFields = fileContents.trimmed().split(QLatin1Char('\n'));
|
|
|
|
|
foreach(const QString &field, rawFields) {
|
|
|
|
|
const QString trimmedField = field.trimmed();
|
|
|
|
|
if (!trimmedField.isEmpty())
|
|
|
|
|
rc.push_back(trimmedField);
|
|
|
|
|
}
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-19 17:40:01 +01:00
|
|
|
void VCSBaseSubmitEditor::createUserFields(const QString &fieldConfigFile)
|
|
|
|
|
{
|
|
|
|
|
QFile fieldFile(fieldConfigFile);
|
|
|
|
|
if (!fieldFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
|
|
|
|
qWarning("%s: Unable to open %s: %s", Q_FUNC_INFO, qPrintable(fieldConfigFile), qPrintable(fieldFile.errorString()));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Parse into fields
|
2009-03-23 12:03:20 +01:00
|
|
|
const QStringList fields = fieldTexts(QString::fromUtf8(fieldFile.readAll()));
|
2009-03-19 17:40:01 +01:00
|
|
|
if (fields.empty())
|
|
|
|
|
return;
|
|
|
|
|
// Create a completer on user names
|
2009-12-08 14:26:41 +01:00
|
|
|
const QStandardItemModel *nickNameModel = Internal::VCSPlugin::instance()->nickNameModel();
|
2009-03-20 14:22:20 +01:00
|
|
|
QCompleter *completer = new QCompleter(Internal::NickNameDialog::nickNameList(nickNameModel), this);
|
2009-03-23 12:03:20 +01:00
|
|
|
|
2009-10-05 11:06:05 +02:00
|
|
|
Utils::SubmitFieldWidget *fieldWidget = new Utils::SubmitFieldWidget;
|
2009-03-23 12:03:20 +01:00
|
|
|
connect(fieldWidget, SIGNAL(browseButtonClicked(int,QString)),
|
2009-12-11 16:43:39 +01:00
|
|
|
this, SLOT(slotSetFieldNickName(int)));
|
2009-03-23 12:03:20 +01:00
|
|
|
fieldWidget->setCompleter(completer);
|
|
|
|
|
fieldWidget->setAllowDuplicateFields(true);
|
|
|
|
|
fieldWidget->setHasBrowseButton(true);
|
|
|
|
|
fieldWidget->setFields(fields);
|
|
|
|
|
m_d->m_widget->addSubmitFieldWidget(fieldWidget);
|
2009-03-19 17:40:01 +01:00
|
|
|
}
|
|
|
|
|
|
2009-01-13 14:06:42 +01:00
|
|
|
void VCSBaseSubmitEditor::registerActions(QAction *editorUndoAction, QAction *editorRedoAction,
|
|
|
|
|
QAction *submitAction, QAction *diffAction)\
|
|
|
|
|
{
|
|
|
|
|
m_d->m_widget->registerActions(editorUndoAction, editorRedoAction, submitAction, diffAction);
|
|
|
|
|
m_d->m_diffAction = diffAction;
|
|
|
|
|
m_d->m_submitAction = submitAction;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VCSBaseSubmitEditor::unregisterActions(QAction *editorUndoAction, QAction *editorRedoAction,
|
|
|
|
|
QAction *submitAction, QAction *diffAction)
|
|
|
|
|
{
|
|
|
|
|
m_d->m_widget->unregisterActions(editorUndoAction, editorRedoAction, submitAction, diffAction);
|
|
|
|
|
m_d->m_diffAction = m_d->m_submitAction = 0;
|
|
|
|
|
}
|
2009-01-12 17:44:04 +01:00
|
|
|
int VCSBaseSubmitEditor::fileNameColumn() const
|
|
|
|
|
{
|
|
|
|
|
return m_d->m_widget->fileNameColumn();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VCSBaseSubmitEditor::setFileNameColumn(int c)
|
|
|
|
|
{
|
|
|
|
|
m_d->m_widget->setFileNameColumn(c);
|
|
|
|
|
}
|
|
|
|
|
|
2009-01-13 10:06:06 +01:00
|
|
|
QAbstractItemView::SelectionMode VCSBaseSubmitEditor::fileListSelectionMode() const
|
|
|
|
|
{
|
|
|
|
|
return m_d->m_widget->fileListSelectionMode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VCSBaseSubmitEditor::setFileListSelectionMode(QAbstractItemView::SelectionMode sm)
|
|
|
|
|
{
|
|
|
|
|
m_d->m_widget->setFileListSelectionMode(sm);
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-20 14:22:20 +01:00
|
|
|
bool VCSBaseSubmitEditor::lineWrap() const
|
|
|
|
|
{
|
|
|
|
|
return m_d->m_widget->lineWrap();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VCSBaseSubmitEditor::setLineWrap(bool w)
|
|
|
|
|
{
|
|
|
|
|
m_d->m_widget->setLineWrap(w);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int VCSBaseSubmitEditor::lineWrapWidth() const
|
|
|
|
|
{
|
|
|
|
|
return m_d->m_widget->lineWrapWidth();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VCSBaseSubmitEditor::setLineWrapWidth(int w)
|
|
|
|
|
{
|
|
|
|
|
m_d->m_widget->setLineWrapWidth(w);
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
void VCSBaseSubmitEditor::slotDescriptionChanged()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool VCSBaseSubmitEditor::createNew(const QString &contents)
|
|
|
|
|
{
|
|
|
|
|
setFileContents(contents);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool VCSBaseSubmitEditor::open(const QString &fileName)
|
|
|
|
|
{
|
|
|
|
|
if (fileName.isEmpty())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const QFileInfo fi(fileName);
|
|
|
|
|
if (!fi.isFile() || !fi.isReadable())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
QFile file(fileName);
|
|
|
|
|
if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
|
|
|
|
|
qWarning("Unable to open %s: %s", qPrintable(fileName), qPrintable(file.errorString()));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QString text = QString::fromLocal8Bit(file.readAll());
|
|
|
|
|
if (!createNew(text))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
m_d->m_file->setFileName(fi.absoluteFilePath());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Core::IFile *VCSBaseSubmitEditor::file()
|
|
|
|
|
{
|
|
|
|
|
return m_d->m_file;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString VCSBaseSubmitEditor::displayName() const
|
|
|
|
|
{
|
|
|
|
|
return m_d->m_displayName;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VCSBaseSubmitEditor::setDisplayName(const QString &title)
|
|
|
|
|
{
|
|
|
|
|
m_d->m_displayName = title;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool VCSBaseSubmitEditor::duplicateSupported() const
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Core::IEditor *VCSBaseSubmitEditor::duplicate(QWidget * /*parent*/)
|
|
|
|
|
{
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *VCSBaseSubmitEditor::kind() const
|
|
|
|
|
{
|
|
|
|
|
return m_d->m_parameters->kind;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 17:05:53 +01:00
|
|
|
static QToolBar *createToolBar(const QWidget *someWidget, QAction *submitAction, QAction *diffAction)
|
|
|
|
|
{
|
|
|
|
|
// Create
|
|
|
|
|
QToolBar *toolBar = new QToolBar;
|
|
|
|
|
toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
|
|
|
|
|
const int size = someWidget->style()->pixelMetric(QStyle::PM_SmallIconSize);
|
|
|
|
|
toolBar->setIconSize(QSize(size, size));
|
|
|
|
|
toolBar->addSeparator();
|
|
|
|
|
|
|
|
|
|
if (submitAction)
|
|
|
|
|
toolBar->addAction(submitAction);
|
|
|
|
|
if (diffAction)
|
|
|
|
|
toolBar->addAction(diffAction);
|
|
|
|
|
return toolBar;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-15 16:23:07 +02:00
|
|
|
QWidget *VCSBaseSubmitEditor::toolBar()
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2008-12-02 17:05:53 +01:00
|
|
|
if (!wantToolBar)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
if (m_d->m_toolWidget)
|
|
|
|
|
return m_d->m_toolWidget;
|
|
|
|
|
|
|
|
|
|
if (!m_d->m_diffAction && !m_d->m_submitAction)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
// Create
|
2008-12-02 17:05:53 +01:00
|
|
|
m_d->m_toolWidget = createToolBar(m_d->m_widget, m_d->m_submitAction, m_d->m_diffAction);
|
|
|
|
|
return m_d->m_toolWidget;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<int> VCSBaseSubmitEditor::context() const
|
|
|
|
|
{
|
|
|
|
|
return m_d->m_contexts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget *VCSBaseSubmitEditor::widget()
|
|
|
|
|
{
|
|
|
|
|
return m_d->m_widget;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray VCSBaseSubmitEditor::saveState() const
|
|
|
|
|
{
|
|
|
|
|
return QByteArray();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool VCSBaseSubmitEditor::restoreState(const QByteArray &/*state*/)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-03 13:21:50 +01:00
|
|
|
QStringList VCSBaseSubmitEditor::checkedFiles() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2009-01-12 17:44:04 +01:00
|
|
|
return m_d->m_widget->checkedFiles();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2009-01-12 17:44:04 +01:00
|
|
|
void VCSBaseSubmitEditor::setFileModel(QAbstractItemModel *m)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2009-01-12 17:44:04 +01:00
|
|
|
m_d->m_widget->setFileModel(m);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2009-01-12 17:44:04 +01:00
|
|
|
QAbstractItemModel *VCSBaseSubmitEditor::fileModel() const
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2009-01-12 17:44:04 +01:00
|
|
|
return m_d->m_widget->fileModel();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2008-12-03 13:21:50 +01:00
|
|
|
void VCSBaseSubmitEditor::slotDiffSelectedVCSFiles(const QStringList &rawList)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2009-01-12 17:44:04 +01:00
|
|
|
emit diffSelectedFiles(rawList);
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool VCSBaseSubmitEditor::save(const QString &fileName)
|
|
|
|
|
{
|
|
|
|
|
const QString fName = fileName.isEmpty() ? m_d->m_file->fileName() : fileName;
|
|
|
|
|
QFile file(fName);
|
|
|
|
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
|
|
|
|
|
qWarning("Unable to open %s: %s", qPrintable(fName), qPrintable(file.errorString()));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
file.write(fileContents().toLocal8Bit());
|
|
|
|
|
if (!file.flush())
|
|
|
|
|
return false;
|
|
|
|
|
file.close();
|
|
|
|
|
const QFileInfo fi(fName);
|
|
|
|
|
m_d->m_file->setFileName(fi.absoluteFilePath());
|
|
|
|
|
m_d->m_file->setModified(false);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString VCSBaseSubmitEditor::fileContents() const
|
|
|
|
|
{
|
2009-03-20 16:02:14 +01:00
|
|
|
return m_d->m_widget->descriptionText();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool VCSBaseSubmitEditor::setFileContents(const QString &contents)
|
|
|
|
|
{
|
|
|
|
|
m_d->m_widget->setDescriptionText(contents);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-19 17:40:01 +01:00
|
|
|
enum { checkDialogMinimumWidth = 500 };
|
|
|
|
|
|
|
|
|
|
VCSBaseSubmitEditor::PromptSubmitResult
|
2009-03-20 10:16:18 +01:00
|
|
|
VCSBaseSubmitEditor::promptSubmit(const QString &title,
|
|
|
|
|
const QString &question,
|
|
|
|
|
const QString &checkFailureQuestion,
|
2009-06-19 16:34:38 +02:00
|
|
|
bool *promptSetting,
|
2009-03-20 10:16:18 +01:00
|
|
|
bool forcePrompt) const
|
2009-03-19 17:40:01 +01:00
|
|
|
{
|
|
|
|
|
QString errorMessage;
|
|
|
|
|
QMessageBox::StandardButton answer = QMessageBox::Yes;
|
|
|
|
|
|
2009-06-19 16:34:38 +02:00
|
|
|
const bool prompt = forcePrompt || *promptSetting;
|
2009-03-20 10:16:18 +01:00
|
|
|
|
2009-03-19 17:40:01 +01:00
|
|
|
QWidget *parent = Core::ICore::instance()->mainWindow();
|
|
|
|
|
// Pop up a message depending on whether the check succeeded and the
|
|
|
|
|
// user wants to be prompted
|
|
|
|
|
if (checkSubmitMessage(&errorMessage)) {
|
|
|
|
|
// Check ok, do prompt?
|
2009-03-20 10:16:18 +01:00
|
|
|
if (prompt) {
|
2009-06-19 16:34:38 +02:00
|
|
|
// Provide check box to turn off prompt ONLY if it was not forced
|
|
|
|
|
if (*promptSetting && !forcePrompt) {
|
|
|
|
|
const QDialogButtonBox::StandardButton danswer =
|
2009-10-05 11:06:05 +02:00
|
|
|
Utils::CheckableMessageBox::question(parent, title, question,
|
2009-06-19 16:34:38 +02:00
|
|
|
tr("Prompt to submit"), promptSetting,
|
|
|
|
|
QDialogButtonBox::Yes|QDialogButtonBox::No|QDialogButtonBox::Cancel,
|
|
|
|
|
QDialogButtonBox::Yes);
|
2009-10-05 11:06:05 +02:00
|
|
|
answer = Utils::CheckableMessageBox::dialogButtonBoxToMessageBoxButton(danswer);
|
2009-06-19 16:34:38 +02:00
|
|
|
} else {
|
|
|
|
|
answer = QMessageBox::question(parent, title, question,
|
|
|
|
|
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
|
|
|
|
|
QMessageBox::Yes);
|
|
|
|
|
}
|
2009-03-19 17:40:01 +01:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Check failed.
|
|
|
|
|
QMessageBox msgBox(QMessageBox::Question, title, checkFailureQuestion,
|
|
|
|
|
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, parent);
|
|
|
|
|
msgBox.setDefaultButton(QMessageBox::Cancel);
|
|
|
|
|
msgBox.setInformativeText(errorMessage);
|
|
|
|
|
msgBox.setMinimumWidth(checkDialogMinimumWidth);
|
|
|
|
|
answer = static_cast<QMessageBox::StandardButton>(msgBox.exec());
|
|
|
|
|
}
|
|
|
|
|
switch (answer) {
|
|
|
|
|
case QMessageBox::Cancel:
|
|
|
|
|
return SubmitCanceled;
|
|
|
|
|
case QMessageBox::No:
|
|
|
|
|
return SubmitDiscarded;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return SubmitConfirmed;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString VCSBaseSubmitEditor::promptForNickName()
|
|
|
|
|
{
|
|
|
|
|
if (!m_d->m_nickNameDialog)
|
2009-12-08 14:26:41 +01:00
|
|
|
m_d->m_nickNameDialog = new Internal::NickNameDialog(Internal::VCSPlugin::instance()->nickNameModel(), m_d->m_widget);
|
2009-03-19 17:40:01 +01:00
|
|
|
if (m_d->m_nickNameDialog->exec() == QDialog::Accepted)
|
|
|
|
|
return m_d->m_nickNameDialog->nickName();
|
|
|
|
|
return QString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VCSBaseSubmitEditor::slotInsertNickName()
|
|
|
|
|
{
|
|
|
|
|
const QString nick = promptForNickName();
|
|
|
|
|
if (!nick.isEmpty())
|
|
|
|
|
m_d->m_widget->descriptionEdit()->textCursor().insertText(nick);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VCSBaseSubmitEditor::slotSetFieldNickName(int i)
|
|
|
|
|
{
|
2009-10-05 11:06:05 +02:00
|
|
|
if (Utils::SubmitFieldWidget *sfw =m_d->m_widget->submitFieldWidgets().front()) {
|
2009-03-23 12:03:20 +01:00
|
|
|
const QString nick = promptForNickName();
|
|
|
|
|
if (!nick.isEmpty())
|
|
|
|
|
sfw->setFieldValue(i, nick);
|
|
|
|
|
}
|
2009-03-19 17:40:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VCSBaseSubmitEditor::slotCheckSubmitMessage()
|
|
|
|
|
{
|
|
|
|
|
QString errorMessage;
|
|
|
|
|
if (!checkSubmitMessage(&errorMessage)) {
|
|
|
|
|
QMessageBox msgBox(QMessageBox::Warning, tr("Submit Message Check failed"),
|
|
|
|
|
errorMessage, QMessageBox::Ok, m_d->m_widget);
|
|
|
|
|
msgBox.setMinimumWidth(checkDialogMinimumWidth);
|
|
|
|
|
msgBox.exec();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool VCSBaseSubmitEditor::checkSubmitMessage(QString *errorMessage) const
|
|
|
|
|
{
|
|
|
|
|
const QString checkScript = submitMessageCheckScript();
|
|
|
|
|
if (checkScript.isEmpty())
|
|
|
|
|
return true;
|
2009-03-20 10:16:18 +01:00
|
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
|
|
|
const bool rc = runSubmitMessageCheckScript(checkScript, errorMessage);
|
|
|
|
|
QApplication::restoreOverrideCursor();
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool VCSBaseSubmitEditor::runSubmitMessageCheckScript(const QString &checkScript, QString *errorMessage) const
|
|
|
|
|
{
|
2009-03-19 17:40:01 +01:00
|
|
|
// Write out message
|
|
|
|
|
QString tempFilePattern = QDir::tempPath();
|
|
|
|
|
if (!tempFilePattern.endsWith(QDir::separator()))
|
|
|
|
|
tempFilePattern += QDir::separator();
|
|
|
|
|
tempFilePattern += QLatin1String("msgXXXXXX.txt");
|
|
|
|
|
QTemporaryFile messageFile(tempFilePattern);
|
|
|
|
|
messageFile.setAutoRemove(true);
|
|
|
|
|
if (!messageFile.open()) {
|
|
|
|
|
*errorMessage = tr("Unable to open '%1': %2").arg(messageFile.fileName(), messageFile.errorString());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const QString messageFileName = messageFile.fileName();
|
|
|
|
|
messageFile.write(fileContents().toUtf8());
|
|
|
|
|
messageFile.close();
|
|
|
|
|
// Run check process
|
|
|
|
|
QProcess checkProcess;
|
|
|
|
|
checkProcess.start(checkScript, QStringList(messageFileName));
|
|
|
|
|
if (!checkProcess.waitForStarted()) {
|
|
|
|
|
*errorMessage = tr("The check script '%1' could not be started: %2").arg(checkScript, checkProcess.errorString());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (!checkProcess.waitForFinished()) {
|
|
|
|
|
*errorMessage = tr("The check script '%1' could not be run: %2").arg(checkScript, checkProcess.errorString());
|
|
|
|
|
return false;
|
2009-12-11 16:43:39 +01:00
|
|
|
}
|
2009-03-19 17:40:01 +01:00
|
|
|
const int exitCode = checkProcess.exitCode();
|
|
|
|
|
if (exitCode != 0) {
|
|
|
|
|
*errorMessage = QString::fromLocal8Bit(checkProcess.readAllStandardError());
|
|
|
|
|
if (errorMessage->isEmpty())
|
|
|
|
|
*errorMessage = tr("The check script returned exit code %1.").arg(exitCode);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-02 17:05:53 +01:00
|
|
|
QIcon VCSBaseSubmitEditor::diffIcon()
|
|
|
|
|
{
|
|
|
|
|
return QIcon(QLatin1String(":/vcsbase/images/diff.png"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QIcon VCSBaseSubmitEditor::submitIcon()
|
|
|
|
|
{
|
|
|
|
|
return QIcon(QLatin1String(":/vcsbase/images/submit.png"));
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-21 11:14:48 +02:00
|
|
|
// Compile a list if files in the current projects. TODO: Recurse down qrc files?
|
2009-01-09 17:52:41 +01:00
|
|
|
QStringList VCSBaseSubmitEditor::currentProjectFiles(bool nativeSeparators, QString *name)
|
|
|
|
|
{
|
|
|
|
|
if (name)
|
|
|
|
|
name->clear();
|
2009-12-11 16:43:39 +01:00
|
|
|
|
|
|
|
|
if (ProjectExplorer::ProjectExplorerPlugin *pe = ProjectExplorer::ProjectExplorerPlugin::instance()) {
|
|
|
|
|
if (const ProjectExplorer::Project *currentProject = pe->currentProject()) {
|
|
|
|
|
QStringList files = currentProject->files(ProjectExplorer::Project::ExcludeGeneratedFiles);
|
2009-01-09 17:52:41 +01:00
|
|
|
if (name)
|
2009-12-11 16:43:39 +01:00
|
|
|
*name = currentProject->name();
|
|
|
|
|
if (nativeSeparators && !files.empty()) {
|
|
|
|
|
const QStringList::iterator end = files.end();
|
|
|
|
|
for (QStringList::iterator it = files.begin(); it != end; ++it)
|
|
|
|
|
*it = QDir::toNativeSeparators(*it);
|
|
|
|
|
}
|
|
|
|
|
return files;
|
2009-01-09 17:52:41 +01:00
|
|
|
}
|
|
|
|
|
}
|
2009-12-11 16:43:39 +01:00
|
|
|
return QStringList();
|
2009-01-09 17:52:41 +01:00
|
|
|
}
|
2009-05-27 16:17:24 +02:00
|
|
|
|
2009-07-21 11:14:48 +02:00
|
|
|
// Reduce a list of untracked files reported by a VCS down to the files
|
|
|
|
|
// that are actually part of the current project(s).
|
|
|
|
|
void VCSBaseSubmitEditor::filterUntrackedFilesOfProject(const QString &repositoryDirectory, QStringList *untrackedFiles)
|
|
|
|
|
{
|
|
|
|
|
if (untrackedFiles->empty())
|
|
|
|
|
return;
|
|
|
|
|
const QStringList nativeProjectFiles = VCSBase::VCSBaseSubmitEditor::currentProjectFiles(true);
|
|
|
|
|
if (nativeProjectFiles.empty())
|
|
|
|
|
return;
|
|
|
|
|
const QDir repoDir(repositoryDirectory);
|
|
|
|
|
for (QStringList::iterator it = untrackedFiles->begin(); it != untrackedFiles->end(); ) {
|
|
|
|
|
const QString path = QDir::toNativeSeparators(repoDir.absoluteFilePath(*it));
|
|
|
|
|
if (nativeProjectFiles.contains(path)) {
|
|
|
|
|
++it;
|
|
|
|
|
} else {
|
|
|
|
|
it = untrackedFiles->erase(it);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-27 16:17:24 +02:00
|
|
|
// Helper to raise an already open submit editor to prevent opening twice.
|
|
|
|
|
bool VCSBaseSubmitEditor::raiseSubmitEditor()
|
|
|
|
|
{
|
|
|
|
|
Core::EditorManager *em = Core::EditorManager::instance();
|
|
|
|
|
// Nothing to do?
|
|
|
|
|
if (Core::IEditor *ce = em->currentEditor())
|
|
|
|
|
if (qobject_cast<VCSBaseSubmitEditor*>(ce))
|
|
|
|
|
return true;
|
|
|
|
|
// Try to activate a hidden one
|
|
|
|
|
foreach (Core::IEditor *e, em->openedEditors()) {
|
|
|
|
|
if (qobject_cast<VCSBaseSubmitEditor*>(e)) {
|
|
|
|
|
em->activateEditor(e, Core::EditorManager::IgnoreNavigationHistory);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-03 13:21:50 +01:00
|
|
|
} // namespace VCSBase
|