VCS: Generalize selections preserving on model refresh

Default implementation is between O(n) (for identical models) to
O(n*m) (for disjoint models). If sort order is known, this
can be reduced to O(n+m), like in Git implementation.

Change-Id: I44662a22961311cb882601d20efa9d445f74748b
Reviewed-by: Tobias Hunger <tobias.hunger@digia.com>
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
Orgad Shaneh
2013-01-02 23:21:30 +02:00
committed by hjk
parent 01084aaa38
commit 2396f34fda
4 changed files with 62 additions and 25 deletions

View File

@@ -45,6 +45,36 @@
namespace Git {
namespace Internal {
class GitSubmitFileModel : public VcsBase::SubmitFileModel
{
public:
GitSubmitFileModel(QObject *parent = 0) : VcsBase::SubmitFileModel(parent)
{ }
virtual void updateSelections(SubmitFileModel *source)
{
int j = 0;
for (int i = 0; i < rowCount() && j < source->rowCount(); ++i) {
CommitData::StateFilePair stateFile = stateFilePair(i);
for (; j < source->rowCount(); ++j) {
CommitData::StateFilePair sourceStateFile = stateFilePair(j);
if (stateFile == sourceStateFile) {
setChecked(i, source->checked(j));
break;
} else if (stateFile < sourceStateFile) {
break;
}
}
}
}
private:
CommitData::StateFilePair stateFilePair(int row)
{
return CommitData::StateFilePair(static_cast<FileStates>(extraData(row).toInt()), file(row));
}
};
/* The problem with git is that no diff can be obtained to for a random
* multiselection of staged/unstaged files; it requires the --cached
* option for staged files. So, we sort apart the diff file lists
@@ -63,25 +93,6 @@ GitSubmitEditorWidget *GitSubmitEditor::submitEditorWidget()
return static_cast<GitSubmitEditorWidget *>(widget());
}
static void mergeFileModels(VcsBase::SubmitFileModel *model, const VcsBase::SubmitFileModel *source)
{
int j = 0;
for (int i = 0; i < model->rowCount() && j < source->rowCount(); ++i) {
CommitData::StateFilePair stateFile(
static_cast<FileStates>(model->extraData(i).toInt()), model->file(i));
for (; j < source->rowCount(); ++j) {
CommitData::StateFilePair sourceStateFile(
static_cast<FileStates>(source->extraData(j).toInt()), source->file(j));
if (stateFile == sourceStateFile) {
model->setChecked(i, source->checked(j));
break;
} else if (stateFile < sourceStateFile) {
break;
}
}
}
}
void GitSubmitEditor::setCommitData(const CommitData &d)
{
GitSubmitEditorWidget *w = submitEditorWidget();
@@ -92,8 +103,7 @@ void GitSubmitEditor::setCommitData(const CommitData &d)
m_commitEncoding = d.commitEncoding;
m_workingDirectory = d.panelInfo.repository;
VcsBase::SubmitFileModel *oldModel = m_model;
m_model = new VcsBase::SubmitFileModel(this);
m_model = new GitSubmitFileModel(this);
if (!d.files.isEmpty()) {
for (QList<CommitData::StateFilePair>::const_iterator it = d.files.constBegin();
it != d.files.constEnd(); ++it) {
@@ -112,10 +122,6 @@ void GitSubmitEditor::setCommitData(const CommitData &d)
QVariant(static_cast<int>(state)));
}
}
if (oldModel) {
mergeFileModels(m_model, oldModel);
delete oldModel;
}
setFileModel(m_model, d.panelInfo.repository);
}