Fixes: Use a model for the submit file list (to resolve the git diff mess)

This commit is contained in:
Friedemann Kleint
2009-01-12 17:44:04 +01:00
parent 349c055d47
commit 17daca603a
21 changed files with 602 additions and 343 deletions

View File

@@ -32,8 +32,12 @@
***************************************************************************/
#include "commitdata.h"
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
#include <QtCore/QRegExp>
const char *const kBranchIndicatorC = "# On branch";
namespace Git {
namespace Internal {
@@ -85,6 +89,130 @@ void CommitData::clear()
untrackedFiles.clear();
}
// Split a state/file spec from git status output
// '#<tab>modified:<blanks>git .pro'
// into state and file ('modified', 'git .pro').
CommitData::StateFilePair splitStateFileSpecification(const QString &line)
{
QPair<QString, QString> rc;
const int statePos = 2;
const int colonIndex = line.indexOf(QLatin1Char(':'), statePos);
if (colonIndex == -1)
return rc;
rc.first = line.mid(statePos, colonIndex - statePos);
int filePos = colonIndex + 1;
const QChar blank = QLatin1Char(' ');
while (line.at(filePos) == blank)
filePos++;
if (filePos < line.size())
rc.second = line.mid(filePos, line.size() - filePos);
return rc;
}
// Convenience to add a state/file spec to a list
static inline bool addStateFileSpecification(const QString &line, QList<CommitData::StateFilePair> *list)
{
const CommitData::StateFilePair sf = splitStateFileSpecification(line);
if (sf.first.isEmpty() || sf.second.isEmpty())
return false;
list->push_back(sf);
return true;
}
/* Parse a git status file list:
* \code
# Changes to be committed:
#<tab>modified:<blanks>git.pro
# Changed but not updated:
#<tab>modified:<blanks>git.pro
# Untracked files:
#<tab>git.pro
\endcode
*/
bool CommitData::parseFilesFromStatus(const QString &output)
{
enum State { None, CommitFiles, NotUpdatedFiles, UntrackedFiles };
const QStringList lines = output.split(QLatin1Char('\n'));
const QString branchIndicator = QLatin1String(kBranchIndicatorC);
const QString commitIndicator = QLatin1String("# Changes to be committed:");
const QString notUpdatedIndicator = QLatin1String("# Changed but not updated:");
const QString untrackedIndicator = QLatin1String("# Untracked files:");
State s = None;
// Match added/changed-not-updated files: "#<tab>modified: foo.cpp"
QRegExp filesPattern(QLatin1String("#\\t[^:]+:\\s+.+"));
QTC_ASSERT(filesPattern.isValid(), return false);
const QStringList::const_iterator cend = lines.constEnd();
for (QStringList::const_iterator it = lines.constBegin(); it != cend; ++it) {
const QString line = *it;
if (line.startsWith(branchIndicator)) {
panelInfo.branch = line.mid(branchIndicator.size() + 1);
} else {
if (line.startsWith(commitIndicator)) {
s = CommitFiles;
} else {
if (line.startsWith(notUpdatedIndicator)) {
s = NotUpdatedFiles;
} else {
if (line.startsWith(untrackedIndicator)) {
// Now match untracked: "#<tab>foo.cpp"
s = UntrackedFiles;
filesPattern = QRegExp(QLatin1String("#\\t.+"));
QTC_ASSERT(filesPattern.isValid(), return false);
} else {
if (filesPattern.exactMatch(line)) {
switch (s) {
case CommitFiles:
addStateFileSpecification(line, &stagedFiles);
break;
case NotUpdatedFiles:
addStateFileSpecification(line, &unstagedFiles);
break;
case UntrackedFiles:
untrackedFiles.push_back(line.mid(2).trimmed());
break;
case None:
break;
}
}
}
}
}
}
}
return !stagedFiles.empty() || !unstagedFiles.empty() || !untrackedFiles.empty();
}
// Convert a spec pair list to a list of file names, optionally
// filter for a state
static QStringList specToFileNames(const QList<CommitData::StateFilePair> &files,
const QString &stateFilter)
{
typedef QList<CommitData::StateFilePair>::const_iterator ConstIterator;
if (files.empty())
return QStringList();
const bool emptyFilter = stateFilter.isEmpty();
QStringList rc;
const ConstIterator cend = files.constEnd();
for (ConstIterator it = files.constBegin(); it != cend; ++it)
if (emptyFilter || stateFilter == it->first)
rc.push_back(it->second);
return rc;
}
QStringList CommitData::stagedFileNames(const QString &stateFilter) const
{
return specToFileNames(stagedFiles, stateFilter);
}
QStringList CommitData::unstagedFileNames(const QString &stateFilter) const
{
return specToFileNames(unstagedFiles, stateFilter);
}
QDebug operator<<(QDebug d, const CommitData &data)
{
d << data.panelInfo << data.panelData;

View File

@@ -35,6 +35,7 @@
#define COMMITDATA_H
#include <QtCore/QStringList>
#include <QtCore/QPair>
QT_BEGIN_NAMESPACE
class QDebug;
@@ -68,11 +69,24 @@ QDebug operator<<(QDebug d, const GitSubmitEditorPanelData &);
struct CommitData
{
// A pair of state string/file name ('modified', 'file.cpp').
typedef QPair<QString, QString> StateFilePair;
void clear();
// Parse the files and the branch of panelInfo
// from a git status output
bool parseFilesFromStatus(const QString &output);
// Convenience to retrieve the file names from
// the specification list. Optionally filter for a certain state
QStringList stagedFileNames(const QString &stateFilter = QString()) const;
QStringList unstagedFileNames(const QString &stateFilter = QString()) const;
GitSubmitEditorPanelInfo panelInfo;
GitSubmitEditorPanelData panelData;
QStringList stagedFiles;
QStringList unstagedFiles;
QList<StateFilePair> stagedFiles;
QList<StateFilePair> unstagedFiles;
QStringList untrackedFiles;
};

View File

@@ -622,73 +622,6 @@ GitClient::StatusResult GitClient::gitStatus(const QString &workingDirectory,
return StatusChanged;
}
/* Parse a git status file list:
* \code
# Changes to be committed:
#<tab>modified:<blanks>git.pro
# Changed but not updated:
#<tab>modified:<blanks>git.pro
# Untracked files:
#<tab>git.pro
\endcode
*/
static bool parseFiles(const QString &output, CommitData *d)
{
enum State { None, CommitFiles, NotUpdatedFiles, UntrackedFiles };
const QStringList lines = output.split(QLatin1Char('\n'));
const QString branchIndicator = QLatin1String(kBranchIndicatorC);
const QString commitIndicator = QLatin1String("# Changes to be committed:");
const QString notUpdatedIndicator = QLatin1String("# Changed but not updated:");
const QString untrackedIndicator = QLatin1String("# Untracked files:");
State s = None;
// Match added/changed-not-updated files: "#<tab>modified: foo.cpp"
QRegExp filesPattern(QLatin1String("#\\t[^:]+:\\s+.+"));
QTC_ASSERT(filesPattern.isValid(), return false);
const QStringList::const_iterator cend = lines.constEnd();
for (QStringList::const_iterator it = lines.constBegin(); it != cend; ++it) {
const QString line = *it;
if (line.startsWith(branchIndicator)) {
d->panelInfo.branch = line.mid(branchIndicator.size() + 1);
} else {
if (line.startsWith(commitIndicator)) {
s = CommitFiles;
} else {
if (line.startsWith(notUpdatedIndicator)) {
s = NotUpdatedFiles;
} else {
if (line.startsWith(untrackedIndicator)) {
// Now match untracked: "#<tab>foo.cpp"
s = UntrackedFiles;
filesPattern = QRegExp(QLatin1String("#\\t.+"));
QTC_ASSERT(filesPattern.isValid(), return false);
} else {
if (filesPattern.exactMatch(line)) {
const QString fileSpec = line.mid(2).trimmed();
switch (s) {
case CommitFiles:
d->stagedFiles.push_back(trimFileSpecification(fileSpec));
break;
case NotUpdatedFiles:
d->unstagedFiles.push_back(trimFileSpecification(fileSpec));
break;
case UntrackedFiles:
d->untrackedFiles.push_back(fileSpec);
break;
case None:
break;
}
}
}
}
}
}
}
return !d->stagedFiles.empty() || !d->unstagedFiles.empty() || !d->untrackedFiles.empty();
}
// Filter out untracked files that are not part of the project
static void filterUntrackedFilesOfProject(const QString &repoDir, QStringList *l)
{
@@ -771,20 +704,12 @@ bool GitClient::getCommitData(const QString &workingDirectory,
// #
// # list of files...
if (!parseFiles(output, d)) {
if (!d->parseFilesFromStatus(output)) {
*errorMessage = msgParseFilesFailed();
return false;
}
// Filter out untracked files that are not part of the project and,
// for symmetry, insert the prefix "untracked:" (as "added:" or ":modified"
// for staged files).
// Filter out untracked files that are not part of the project
filterUntrackedFilesOfProject(repoDirectory, &d->untrackedFiles);
if (!d->untrackedFiles.empty()) {
const QString untrackedPrefix = QLatin1String("untracked: ");
const QStringList::iterator pend = d->untrackedFiles.end();
for (QStringList::iterator it = d->untrackedFiles.begin(); it != pend; ++it)
it->insert(0, untrackedPrefix);
}
d->panelData.author = readConfigValue(workingDirectory, QLatin1String("user.name"));
d->panelData.email = readConfigValue(workingDirectory, QLatin1String("user.email"));
@@ -881,7 +806,7 @@ GitClient::RevertResult GitClient::revertI(QStringList files, bool *ptrToIsDirec
return RevertFailed;
}
CommitData data;
if (!parseFiles(output, &data)) {
if (!data.parseFilesFromStatus(output)) {
*errorMessage = msgParseFilesFailed();
return RevertFailed;
}
@@ -896,9 +821,9 @@ GitClient::RevertResult GitClient::revertI(QStringList files, bool *ptrToIsDirec
}
// From the status output, determine all modified [un]staged files.
const QString modifiedPattern = QLatin1String("modified: ");
const QStringList allStagedFiles = GitSubmitEditor::statusListToFileList(data.stagedFiles.filter(modifiedPattern));
const QStringList allUnstagedFiles = GitSubmitEditor::statusListToFileList(data.unstagedFiles.filter(modifiedPattern));
const QString modifiedState = QLatin1String("modified");
const QStringList allStagedFiles = data.stagedFileNames(modifiedState);
const QStringList allUnstagedFiles = data.unstagedFileNames(modifiedState);
// Unless a directory was passed, filter all modified files for the
// argument file list.
QStringList stagedFiles = allStagedFiles;

View File

@@ -602,7 +602,7 @@ void GitPlugin::startCommit()
// Store repository for diff and the original list of
// files to be able to unstage files the user unchecks
m_submitRepository = data.panelInfo.repository;
m_submitOrigCommitFiles = GitSubmitEditor::statusListToFileList(data.stagedFiles);
m_submitOrigCommitFiles = data.stagedFileNames();
if (Git::Constants::debug)
qDebug() << Q_FUNC_INFO << data << commitTemplate;

View File

@@ -36,6 +36,8 @@
#include "gitconstants.h"
#include "commitdata.h"
#include <vcsbase/submitfilemodel.h>
#include <QtCore/QDebug>
namespace Git {
@@ -52,14 +54,14 @@ GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget()
return static_cast<GitSubmitEditorWidget *>(widget());
}
QStringList GitSubmitEditor::statusListToFileList(const QStringList &rawList)
static void addStateFileListToModel(const QList<CommitData::StateFilePair> &l,
VCSBase::SubmitFileModel *model,
bool checked)
{
if (rawList.empty())
return rawList;
QStringList rc;
foreach (const QString &rf, rawList)
rc.push_back(fileFromStatusLine(rf));
return rc;
typedef QList<CommitData::StateFilePair>::const_iterator ConstIterator;
const ConstIterator cend = l.constEnd();
for (ConstIterator it = l.constBegin(); it != cend; ++it)
model->addFile(it->second, it->first, checked);
}
void GitSubmitEditor::setCommitData(const CommitData &d)
@@ -67,10 +69,16 @@ void GitSubmitEditor::setCommitData(const CommitData &d)
submitEditorWidget()->setPanelData(d.panelData);
submitEditorWidget()->setPanelInfo(d.panelInfo);
addFiles(d.stagedFiles, true, true);
// Not Updated: Initially unchecked
addFiles(d.unstagedFiles, false, true);
addFiles(d.untrackedFiles, false, true);
VCSBase::SubmitFileModel *model = new VCSBase::SubmitFileModel(this);
addStateFileListToModel(d.stagedFiles, model, true);
addStateFileListToModel(d.unstagedFiles, model, false);
if (!d.untrackedFiles.empty()) {
const QString untrackedSpec = QLatin1String("untracked");
const QStringList::const_iterator cend = d.untrackedFiles.constEnd();
for (QStringList::const_iterator it = d.untrackedFiles.constBegin(); it != cend; ++it)
model->addFile(*it, untrackedSpec, false);
}
setFileModel(model);
}
GitSubmitEditorPanelData GitSubmitEditor::panelData() const
@@ -78,18 +86,5 @@ GitSubmitEditorPanelData GitSubmitEditor::panelData() const
return const_cast<GitSubmitEditor*>(this)->submitEditorWidget()->panelData();
}
QString GitSubmitEditor::fileFromStatusLine(const QString &line)
{
QString rc = line;
// "modified: mainwindow.cpp"
const int index = rc.indexOf(QLatin1Char(':'));
if (index != -1)
rc.remove(0, index + 1);
const QChar blank(' ');
while (rc.startsWith(blank))
rc.remove(0, 1);
return rc;
}
} // namespace Internal
} // namespace Git

View File

@@ -54,13 +54,6 @@ public:
void setCommitData(const CommitData &);
GitSubmitEditorPanelData panelData() const;
static QString fileFromStatusLine(const QString &line);
static QStringList statusListToFileList(const QStringList &);
protected:
virtual QStringList vcsFileListToFileList(const QStringList &l) const
{ return statusListToFileList(l); }
private:
inline GitSubmitEditorWidget *submitEditorWidget();
};

View File

@@ -494,19 +494,19 @@ void PerforcePlugin::submit()
QTC_ASSERT(m_coreInstance, return);
if (!checkP4Command()) {
showOutput(tr("No p4 executable specified!"));
showOutput(tr("No p4 executable specified!"), true);
return;
}
if (m_changeTmpFile) {
showOutput(tr("Another submit is currently executed."));
showOutput(tr("Another submit is currently executed."), true);
m_perforceOutputWindow->popup(false);
return;
}
m_changeTmpFile = new QTemporaryFile(this);
if (!m_changeTmpFile->open()) {
showOutput(tr("Cannot create temporary file."));
showOutput(tr("Cannot create temporary file."), true);
delete m_changeTmpFile;
m_changeTmpFile = 0;
return;
@@ -970,7 +970,7 @@ bool PerforcePlugin::editorAboutToClose(Core::IEditor *editor)
QByteArray change = m_changeTmpFile->readAll();
m_changeTmpFile->close();
if (!checkP4Command()) {
showOutput(tr("No p4 executable specified!"));
showOutput(tr("No p4 executable specified!"), true);
delete m_changeTmpFile;
m_changeTmpFile = 0;
return false;
@@ -981,8 +981,8 @@ bool PerforcePlugin::editorAboutToClose(Core::IEditor *editor)
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
proc.start(m_settings.p4Command,
basicP4Args() << QLatin1String("submit") << QLatin1String("-i"));
if (!proc.waitForStarted(3000)) {
showOutput(tr("Cannot execute p4 submit."));
if (!proc.waitForStarted(p4Timeout)) {
showOutput(tr("Cannot execute p4 submit."), true);
QApplication::restoreOverrideCursor();
delete m_changeTmpFile;
m_changeTmpFile = 0;
@@ -992,7 +992,7 @@ bool PerforcePlugin::editorAboutToClose(Core::IEditor *editor)
proc.closeWriteChannel();
if (!proc.waitForFinished()) {
showOutput(tr("Cannot execute p4 submit."));
showOutput(tr("Cannot execute p4 submit."), true);
QApplication::restoreOverrideCursor();
delete m_changeTmpFile;
m_changeTmpFile = 0;
@@ -1000,7 +1000,7 @@ bool PerforcePlugin::editorAboutToClose(Core::IEditor *editor)
}
QString output = QString::fromUtf8(proc.readAll());
showOutput(output);
if (output.contains("Out of date files must be resolved or reverted")) {
if (output.contains("Out of date files must be resolved or reverted"), true) {
QMessageBox::warning(editor->widget(), "Pending change", "Could not submit the change, because your workspace was out of date. Created a pending submit instead.");
}
QApplication::restoreOverrideCursor();

View File

@@ -36,6 +36,7 @@
#include "perforceplugin.h"
#include "perforceconstants.h"
#include <vcsbase/submitfilemodel.h>
#include <utils/qtcassert.h>
#include <QtCore/QDebug>
@@ -43,10 +44,14 @@
namespace Perforce {
namespace Internal {
enum { FileSpecRole = Qt::UserRole + 1 };
PerforceSubmitEditor::PerforceSubmitEditor(const VCSBase::VCSBaseSubmitEditorParameters *parameters, QWidget *parent) :
VCSBaseSubmitEditor(parameters, new PerforceSubmitEditorWidget(parent))
VCSBaseSubmitEditor(parameters, new PerforceSubmitEditorWidget(parent)),
m_fileModel(new VCSBase::SubmitFileModel(this))
{
setDisplayName(tr("Perforce Submit"));
setFileModel(m_fileModel);
}
PerforceSubmitEditorWidget *PerforceSubmitEditor::submitEditorWidget()
@@ -54,14 +59,6 @@ PerforceSubmitEditorWidget *PerforceSubmitEditor::submitEditorWidget()
return static_cast<PerforceSubmitEditorWidget *>(widget());
}
QStringList PerforceSubmitEditor::vcsFileListToFileList(const QStringList &rawList) const
{
QStringList rc;
foreach (const QString &rf, rawList)
rc.push_back(fileFromChangeLine(rf));
return rc;
}
QString PerforceSubmitEditor::fileContents() const
{
const_cast<PerforceSubmitEditor*>(this)->updateEntries();
@@ -121,25 +118,7 @@ bool PerforceSubmitEditor::parseText(QString text)
void PerforceSubmitEditor::restrictToProjectFiles(const QStringList &knownProjectFiles)
{
QStringList allFiles = submitEditorWidget()->fileList();
const int oldSize = allFiles.size();
for (int i = oldSize - 1; i >= 0; i--)
if (!knownProjectFiles.contains(fileFromChangeLine(allFiles.at(i))))
allFiles.removeAt(i);
if (allFiles.size() != oldSize)
submitEditorWidget()->setFileList(allFiles);
if (Perforce::Constants::debug)
qDebug() << Q_FUNC_INFO << oldSize << "->" << allFiles.size();
}
QString PerforceSubmitEditor::fileFromChangeLine(const QString &line)
{
QString rc = line;
// " foo.cpp#add"
const int index = rc.lastIndexOf(QLatin1Char('#'));
if (index != -1)
rc.truncate(index);
return rc.trimmed();
m_fileModel->filter(knownProjectFiles, fileNameColumn());
}
void PerforceSubmitEditor::updateFields()
@@ -161,12 +140,15 @@ void PerforceSubmitEditor::updateFields()
widget->setDescriptionText(lines.join(newLine));
lines = m_entries.value(QLatin1String("Files")).split(newLine);
lines.replaceInStrings(leadingTabPattern, QString());
QStringList fileList;
foreach (const QString &line, lines)
if (!line.isEmpty())
fileList.push_back(line);
widget->setFileList(fileList);
// split up "file#add" and store complete spec line as user data
foreach (const QString &specLine, lines) {
const QStringList list = specLine.split(QLatin1Char('#'));
if (list.size() == 2) {
const QString file = list.at(0).trimmed();
const QString state = list.at(1).trimmed();
m_fileModel->addFile(file, state).at(0)->setData(specLine, FileSpecRole);
}
}
}
void PerforceSubmitEditor::updateEntries()
@@ -181,13 +163,14 @@ void PerforceSubmitEditor::updateEntries()
lines.replaceInStrings(QRegExp(QLatin1String("^")), tab);
m_entries.insert(QLatin1String("Description"), newLine + lines.join(newLine) + QLatin1String("\n\n"));
QString files = newLine;
// Files
const QStringList fileList = submitEditorWidget()->fileList();
const int count = fileList.size();
for (int i = 0; i < count; i++) {
files += tab;
files += fileList.at(i);
files += newLine;
// Re-build the file spec '<tab>file#add' from the user data
const int count = m_fileModel->rowCount();
for (int r = 0; r < count; r++) {
const QStandardItem *item = m_fileModel->item(r, 0);
if (item->checkState() == Qt::Checked) {
files += item->data(FileSpecRole).toString();
files += newLine;
}
}
files += newLine;
m_entries.insert(QLatin1String("Files"), files);

View File

@@ -39,6 +39,10 @@
#include <QtCore/QStringList>
#include <QtCore/QMap>
namespace VCSBase {
class SubmitFileModel;
}
namespace Perforce {
namespace Internal {
@@ -66,7 +70,6 @@ public:
static QString fileFromChangeLine(const QString &line);
protected:
virtual QStringList vcsFileListToFileList(const QStringList &) const;
virtual QString fileContents() const;
virtual bool setFileContents(const QString &contents);
@@ -77,6 +80,7 @@ private:
void updateEntries();
QMap<QString, QString> m_entries;
VCSBase::SubmitFileModel *m_fileModel;
};
} // namespace Internal

View File

@@ -139,6 +139,29 @@ inline Core::IEditor* locateEditor(const Core::ICore *core, const char *property
return 0;
}
// Parse "svn status" output for added/modified/deleted files
// "M<7blanks>file"
typedef QList<SubversionSubmitEditor::StatusFilePair> StatusList;
StatusList parseStatusOutput(const QString &output)
{
StatusList changeSet;
const QString newLine = QString(QLatin1Char('\n'));
const QStringList list = output.split(newLine, QString::SkipEmptyParts);
foreach (const QString &l, list) {
const QString line =l.trimmed();
if (line.size() > 8) {
const QChar state = line.at(0);
if (state == QLatin1Char('A') || state == QLatin1Char('D') || state == QLatin1Char('M')) {
const QString fileName = line.mid(7);
changeSet.push_back(SubversionSubmitEditor::StatusFilePair(QString(state), fileName));
}
}
}
return changeSet;
}
// ------------- SubversionPlugin
Core::ICore *SubversionPlugin::m_coreInstance = 0;
SubversionPlugin *SubversionPlugin::m_subversionPluginInstance = 0;
@@ -694,7 +717,7 @@ void SubversionPlugin::startCommit(const QStringList &files)
if (response.error)
return;
// Get list of added/modified/deleted files
const QStringList statusOutput = parseStatusOutput(response.stdOut);
const StatusList statusOutput = parseStatusOutput(response.stdOut);
if (statusOutput.empty()) {
showOutput(tr("There are no modified files."), true);
return;
@@ -717,22 +740,7 @@ void SubversionPlugin::startCommit(const QStringList &files)
m_changeTmpFile->seek(0);
// Create a submit editor and set file list
SubversionSubmitEditor *editor = openSubversionSubmitEditor(m_changeTmpFile->fileName());
editor->setFileList(statusOutput);
}
// Parse "status" output for added/modified/deleted files
QStringList SubversionPlugin::parseStatusOutput(const QString &output) const
{
QStringList changeSet;
const QString newLine = QString(QLatin1Char('\n'));
const QStringList list = output.split(newLine, QString::SkipEmptyParts);
foreach (const QString &l, list) {
QString line(l.trimmed());
if (line.startsWith(QLatin1Char('A')) || line.startsWith(QLatin1Char('D'))
|| line.startsWith(QLatin1Char('M')))
changeSet.append(line);
}
return changeSet;
editor->setStatusList(statusOutput);
}
bool SubversionPlugin::commit(const QString &messageFile,

View File

@@ -133,7 +133,6 @@ private:
SubversionResponse runSvn(const QStringList &arguments, int timeOut,
bool showStdOutInOutputWindow, QTextCodec *outputCodec = 0);
void showOutput(const QString &output, bool bringToForeground = true);
QStringList parseStatusOutput(const QString &output) const;
void annotate(const QString &file);
void filelog(const QString &file);
bool managesDirectory(const QDir &directory) const;

View File

@@ -35,6 +35,7 @@
#include "subversionsubmiteditor.h"
#include <utils/submiteditorwidget.h>
#include <vcsbase/submitfilemodel.h>
using namespace Subversion::Internal;
@@ -45,6 +46,19 @@ SubversionSubmitEditor::SubversionSubmitEditor(const VCSBase::VCSBaseSubmitEdito
setDisplayName(tr("Subversion Submit"));
}
void SubversionSubmitEditor::setStatusList(const QList<StatusFilePair> &statusOutput)
{
typedef QList<StatusFilePair>::const_iterator ConstIterator;
VCSBase::SubmitFileModel *model = new VCSBase::SubmitFileModel(this);
const ConstIterator cend = statusOutput.constEnd();
for (ConstIterator it = statusOutput.constBegin(); it != cend; ++it)
model->addFile(it->second, it->first, true);
setFileModel(model);
}
/*
QStringList SubversionSubmitEditor::vcsFileListToFileList(const QStringList &rl) const
{
QStringList files;
@@ -59,3 +73,5 @@ QString SubversionSubmitEditor::fileFromStatusLine(const QString &statusLine)
enum { filePos = 7 };
return statusLine.mid(filePos, statusLine.size() - filePos);
}
*/

View File

@@ -34,6 +34,9 @@
#ifndef SUBVERSIONSUBMITEDITOR_H
#define SUBVERSIONSUBMITEDITOR_H
#include <QtCore/QPair>
#include <QtCore/QStringList>
#include <vcsbase/vcsbasesubmiteditor.h>
namespace Subversion {
@@ -48,8 +51,10 @@ public:
static QString fileFromStatusLine(const QString &statusLine);
private:
virtual QStringList vcsFileListToFileList(const QStringList &) const;
// A list of ( 'A','M','D') status indicators and file names.
typedef QPair<QString, QString> StatusFilePair;
void setStatusList(const QList<StatusFilePair> &statusOutput);
};
} // namespace Internal

View File

@@ -0,0 +1,78 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#include "submitfilemodel.h"
#include "vcsbaseconstants.h"
#include <QtGui/QStandardItem>
#include <QtCore/QDebug>
namespace VCSBase {
SubmitFileModel::SubmitFileModel(QObject *parent) :
QStandardItemModel(0, 2, parent)
{
// setColumnCount(2);
QStringList headerLabels;
headerLabels << tr("State") << tr("File");
setHorizontalHeaderLabels(headerLabels);
}
QList<QStandardItem *> SubmitFileModel::addFile(const QString &fileName, const QString &status, bool checked)
{
if (VCSBase::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << fileName << status << checked;
QStandardItem *statusItem = new QStandardItem(status);
statusItem->setCheckable(true);
statusItem->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
QStandardItem *fileItem = new QStandardItem(fileName);
QList<QStandardItem *> row;
row << statusItem << fileItem;
appendRow(row);
return row;
}
unsigned SubmitFileModel::filter(const QStringList &filter, int column)
{
unsigned rc = 0;
for (int r = rowCount() - 1; r >= 0; r--)
if (const QStandardItem *i = item(r, column))
if (!filter.contains(i->text())) {
qDeleteAll(takeRow(r));
rc++;
}
if (VCSBase::Constants::Internal::debug)
qDebug() << Q_FUNC_INFO << " deleted " << rc << " items using " << filter << " , remaining " << rowCount();
return rc;
}
}

View File

@@ -0,0 +1,62 @@
/***************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
**
** Non-Open Source Usage
**
** Licensees may use this file in accordance with the Qt Beta Version
** License Agreement, Agreement version 2.2 provided with the Software or,
** alternatively, in accordance with the terms contained in a written
** agreement between you and Nokia.
**
** GNU General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the packaging
** of this file. Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
**
** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
** http://www.gnu.org/copyleft/gpl.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt GPL Exception
** version 1.3, included in the file GPL_EXCEPTION.txt in this package.
**
***************************************************************************/
#ifndef SUBMITMODEL_H
#define SUBMITMODEL_H
#include "vcsbase_global.h"
#include <QtGui/QStandardItemModel>
namespace VCSBase {
/* A 2-column (checkable, state, file name) model to be used to list the files-
* in the submit editor. Provides header items and a convience to add files. */
class VCSBASE_EXPORT SubmitFileModel : public QStandardItemModel
{
Q_OBJECT
public:
explicit SubmitFileModel(QObject *parent = 0);
// Convenience to add a file plus status text.
QList<QStandardItem *> addFile(const QString &fileName, const QString &status = QString(), bool checked = true);
// Filter for entries contained in the filter list. Returns the
// number of deleted entries.
unsigned filter(const QStringList &filter, int column);
};
}
#endif // SUBMITMODEL_H

View File

@@ -1,31 +1,28 @@
TEMPLATE = lib
TARGET = VCSBase
DEFINES += VCSBASE_LIBRARY
include(../../qworkbenchplugin.pri)
include(vcsbase_dependencies.pri)
HEADERS += vcsbase_global.h \
vcsbaseconstants.h \
vcsbaseplugin.h \
baseannotationhighlighter.h \
diffhighlighter.h \
vcsbasetextdocument.h \
vcsbaseeditor.h \
vcsbasesubmiteditor.h \
basevcseditorfactory.h \
submiteditorfile.h \
basevcssubmiteditorfactory.h
vcsbaseconstants.h \
vcsbaseplugin.h \
baseannotationhighlighter.h \
diffhighlighter.h \
vcsbasetextdocument.h \
vcsbaseeditor.h \
vcsbasesubmiteditor.h \
basevcseditorfactory.h \
submiteditorfile.h \
basevcssubmiteditorfactory.h \
submitfilemodel.h
SOURCES += vcsbaseplugin.cpp \
baseannotationhighlighter.cpp \
diffhighlighter.cpp \
vcsbasetextdocument.cpp \
vcsbaseeditor.cpp \
vcsbasesubmiteditor.cpp \
basevcseditorfactory.cpp \
submiteditorfile.cpp \
basevcssubmiteditorfactory.cpp
RESOURCES=vcsbase.qrc
baseannotationhighlighter.cpp \
diffhighlighter.cpp \
vcsbasetextdocument.cpp \
vcsbaseeditor.cpp \
vcsbasesubmiteditor.cpp \
basevcseditorfactory.cpp \
submiteditorfile.cpp \
basevcssubmiteditorfactory.cpp \
submitfilemodel.cpp
RESOURCES = vcsbase.qrc

View File

@@ -129,6 +129,16 @@ VCSBaseSubmitEditor::~VCSBaseSubmitEditor()
delete m_d;
}
int VCSBaseSubmitEditor::fileNameColumn() const
{
return m_d->m_widget->fileNameColumn();
}
void VCSBaseSubmitEditor::setFileNameColumn(int c)
{
m_d->m_widget->setFileNameColumn(c);
}
void VCSBaseSubmitEditor::slotDescriptionChanged()
{
}
@@ -246,22 +256,22 @@ bool VCSBaseSubmitEditor::restoreState(const QByteArray &/*state*/)
QStringList VCSBaseSubmitEditor::checkedFiles() const
{
return vcsFileListToFileList(m_d->m_widget->checkedFiles());
return m_d->m_widget->checkedFiles();
}
void VCSBaseSubmitEditor::setFileList(const QStringList &l)
void VCSBaseSubmitEditor::setFileModel(QAbstractItemModel *m)
{
m_d->m_widget->setFileList(l);
m_d->m_widget->setFileModel(m);
}
void VCSBaseSubmitEditor::addFiles(const QStringList& list, bool checked, bool userCheckable)
QAbstractItemModel *VCSBaseSubmitEditor::fileModel() const
{
m_d->m_widget->addFiles(list, checked, userCheckable);
return m_d->m_widget->fileModel();
}
void VCSBaseSubmitEditor::slotDiffSelectedVCSFiles(const QStringList &rawList)
{
emit diffSelectedFiles(vcsFileListToFileList(rawList));
emit diffSelectedFiles(rawList);
}
bool VCSBaseSubmitEditor::save(const QString &fileName)

View File

@@ -42,6 +42,7 @@
QT_BEGIN_NAMESPACE
class QIcon;
class QAbstractItemModel;
QT_END_NAMESPACE
namespace Core {
@@ -90,6 +91,7 @@ struct VCSBASE_EXPORT VCSBaseSubmitEditorParameters {
class VCSBASE_EXPORT VCSBaseSubmitEditor : public Core::IEditor
{
Q_OBJECT
Q_PROPERTY(int fileNameColumn READ fileNameColumn WRITE setFileNameColumn DESIGNABLE false)
public:
typedef QList<int> Context;
@@ -100,6 +102,9 @@ protected:
public:
virtual ~VCSBaseSubmitEditor();
int fileNameColumn() const;
void setFileNameColumn(int c);
// Core::IEditor
virtual bool createNew(const QString &contents);
virtual bool open(const QString &fileName);
@@ -119,8 +124,8 @@ public:
QStringList checkedFiles() const;
void setFileList(const QStringList&);
void addFiles(const QStringList&, bool checked = true, bool userCheckable = true);
void setFileModel(QAbstractItemModel *m);
QAbstractItemModel *fileModel() const;
// Utilities returning some predefined icons for actions
static QIcon diffIcon();
@@ -139,11 +144,6 @@ private slots:
void slotDescriptionChanged();
protected:
/* Implemented this to extract the real file list from the status
* output of the versioning system as displayed in the file list
* for example "M foo.cpp" -> "foo.cpp". */
virtual QStringList vcsFileListToFileList(const QStringList &) const = 0;
/* These hooks allow for modifying the contents that goes to
* the file. The default implementation uses the text
* of the description editor. */