Core: Use a document subclass for restored documents

Enables name disambiguation for restored documents as well as "real" ones.

Change-Id: Id9c97fa03647e2724612b732091fc92c183c1a17
Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com>
This commit is contained in:
Orgad Shaneh
2015-03-08 22:43:19 +02:00
committed by Orgad Shaneh
parent e8c8968ab6
commit c1ef8edaf9
6 changed files with 67 additions and 49 deletions

View File

@@ -113,6 +113,17 @@ private:
QHash<QString, DocumentModel::Entry *> m_entryByFixedPath; QHash<QString, DocumentModel::Entry *> m_entryByFixedPath;
}; };
class RestoredDocument : public IDocument
{
public:
bool save(QString *, const QString &, bool) { return false; }
QString defaultPath() const { return filePath().toFileInfo().absolutePath(); }
QString suggestedFileName() const { return filePath().fileName(); }
bool isModified() const { return false; }
bool isSaveAsAllowed() const { return false; }
bool reload(QString *, ReloadFlag, ChangeType) { return true; }
};
DocumentModelPrivate::DocumentModelPrivate() : DocumentModelPrivate::DocumentModelPrivate() :
m_lockedIcon(QLatin1String(":/core/images/locked.png")), m_lockedIcon(QLatin1String(":/core/images/locked.png")),
m_unlockedIcon(QLatin1String(":/core/images/unlocked.png")) m_unlockedIcon(QLatin1String(":/core/images/unlocked.png"))
@@ -127,10 +138,17 @@ DocumentModelPrivate::~DocumentModelPrivate()
static DocumentModelPrivate *d; static DocumentModelPrivate *d;
DocumentModel::Entry::Entry() : DocumentModel::Entry::Entry() :
document(0) document(0),
isRestored(false)
{ {
} }
DocumentModel::Entry::~Entry()
{
if (isRestored)
delete document;
}
DocumentModel::DocumentModel() DocumentModel::DocumentModel()
{ {
} }
@@ -162,22 +180,22 @@ QAbstractItemModel *DocumentModel::model()
Utils::FileName DocumentModel::Entry::fileName() const Utils::FileName DocumentModel::Entry::fileName() const
{ {
return document ? document->filePath() : m_fileName; return document->filePath();
} }
QString DocumentModel::Entry::displayName() const QString DocumentModel::Entry::displayName() const
{ {
return document ? document->displayName() : m_displayName; return document->displayName();
} }
QString DocumentModel::Entry::plainDisplayName() const QString DocumentModel::Entry::plainDisplayName() const
{ {
return document ? document->plainDisplayName() : m_displayName; return document->plainDisplayName();
} }
Id DocumentModel::Entry::id() const Id DocumentModel::Entry::id() const
{ {
return document ? document->id() : m_id; return document->id();
} }
int DocumentModelPrivate::columnCount(const QModelIndex &parent) const int DocumentModelPrivate::columnCount(const QModelIndex &parent) const
@@ -214,15 +232,17 @@ void DocumentModel::addEditor(IEditor *editor, bool *isNewDocument)
void DocumentModel::addRestoredDocument(const QString &fileName, const QString &displayName, Id id) void DocumentModel::addRestoredDocument(const QString &fileName, const QString &displayName, Id id)
{ {
Entry *entry = new Entry; Entry *entry = new Entry;
entry->m_fileName = Utils::FileName::fromString(fileName); entry->document = new RestoredDocument;
entry->m_displayName = displayName; entry->document->setFilePath(Utils::FileName::fromString(fileName));
entry->m_id = id; entry->document->setPreferredDisplayName(displayName);
entry->document->setId(id);
entry->isRestored = true;
d->addEntry(entry); d->addEntry(entry);
} }
DocumentModel::Entry *DocumentModel::firstRestoredEntry() DocumentModel::Entry *DocumentModel::firstRestoredEntry()
{ {
return Utils::findOrDefault(d->m_entries, [](Entry *entry) { return !entry->document; }); return Utils::findOrDefault(d->m_entries, [](Entry *entry) { return entry->isRestored; });
} }
void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry) void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
@@ -236,7 +256,7 @@ void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
int previousIndex = indexOfFilePath(fileName); int previousIndex = indexOfFilePath(fileName);
if (previousIndex >= 0) { if (previousIndex >= 0) {
DocumentModel::Entry *previousEntry = m_entries.at(previousIndex); DocumentModel::Entry *previousEntry = m_entries.at(previousIndex);
const bool replace = entry->document && !previousEntry->document; const bool replace = !entry->isRestored && previousEntry->isRestored;
if (replace) { if (replace) {
delete previousEntry; delete previousEntry;
m_entries[previousIndex] = entry; m_entries[previousIndex] = entry;
@@ -268,8 +288,7 @@ void DocumentModelPrivate::addEntry(DocumentModel::Entry *entry)
disambiguateDisplayNames(entry); disambiguateDisplayNames(entry);
if (!fixedPath.isEmpty()) if (!fixedPath.isEmpty())
m_entryByFixedPath[fixedPath] = entry; m_entryByFixedPath[fixedPath] = entry;
if (entry->document) connect(entry->document, SIGNAL(changed()), this, SLOT(itemChanged()));
connect(entry->document, SIGNAL(changed()), this, SLOT(itemChanged()));
endInsertRows(); endInsertRows();
} }
@@ -282,8 +301,6 @@ bool DocumentModelPrivate::disambiguateDisplayNames(DocumentModel::Entry *entry)
for (int i = 0, total = m_entries.count(); i < total; ++i) { for (int i = 0, total = m_entries.count(); i < total; ++i) {
DocumentModel::Entry *e = m_entries.at(i); DocumentModel::Entry *e = m_entries.at(i);
if (!e->document)
continue;
if (e == entry || e->plainDisplayName() == displayName) { if (e == entry || e->plainDisplayName() == displayName) {
e->document->setUniqueDisplayName(QString()); e->document->setUniqueDisplayName(QString());
dups += DynamicEntry(e); dups += DynamicEntry(e);
@@ -349,7 +366,8 @@ int DocumentModelPrivate::indexOfFilePath(const Utils::FileName &filePath) const
void DocumentModel::removeEntry(DocumentModel::Entry *entry) void DocumentModel::removeEntry(DocumentModel::Entry *entry)
{ {
QTC_ASSERT(!entry->document, return); // we wouldn't know what to do with the associated editors // For non restored entries, we wouldn't know what to do with the associated editors
QTC_ASSERT(entry->isRestored, return);
int index = d->m_entries.indexOf(entry); int index = d->m_entries.indexOf(entry);
d->removeDocument(index); d->removeDocument(index);
} }
@@ -373,7 +391,8 @@ void DocumentModel::removeEditor(IEditor *editor, bool *lastOneForDocument)
void DocumentModel::removeDocument(const QString &fileName) void DocumentModel::removeDocument(const QString &fileName)
{ {
int index = d->indexOfFilePath(Utils::FileName::fromString(fileName)); int index = d->indexOfFilePath(Utils::FileName::fromString(fileName));
QTC_ASSERT(!d->m_entries.at(index)->document, return); // we wouldn't know what to do with the associated editors // For non restored entries, we wouldn't know what to do with the associated editors
QTC_ASSERT(d->m_entries.at(index)->isRestored, return);
d->removeDocument(index); d->removeDocument(index);
} }
@@ -393,8 +412,7 @@ void DocumentModelPrivate::removeDocument(int idx)
DocumentManager::ResolveLinks); DocumentManager::ResolveLinks);
m_entryByFixedPath.remove(fixedPath); m_entryByFixedPath.remove(fixedPath);
} }
if (IDocument *document = entry->document) disconnect(entry->document, SIGNAL(changed()), this, SLOT(itemChanged()));
disconnect(document, SIGNAL(changed()), this, SLOT(itemChanged()));
disambiguateDisplayNames(entry); disambiguateDisplayNames(entry);
delete entry; delete entry;
} }
@@ -402,7 +420,7 @@ void DocumentModelPrivate::removeDocument(int idx)
void DocumentModel::removeAllRestoredEntries() void DocumentModel::removeAllRestoredEntries()
{ {
for (int i = d->m_entries.count()-1; i >= 0; --i) { for (int i = d->m_entries.count()-1; i >= 0; --i) {
if (!d->m_entries.at(i)->document) { if (d->m_entries.at(i)->isRestored) {
int row = i + 1/*<no document>*/; int row = i + 1/*<no document>*/;
d->beginRemoveRows(QModelIndex(), row, row); d->beginRemoveRows(QModelIndex(), row, row);
delete d->m_entries.takeAt(i); delete d->m_entries.takeAt(i);
@@ -527,19 +545,12 @@ QVariant DocumentModelPrivate::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case Qt::DisplayRole: { case Qt::DisplayRole: {
QString name = e->displayName(); QString name = e->displayName();
if (e->document && e->document->isModified()) if (e->document->isModified())
name += QLatin1Char('*'); name += QLatin1Char('*');
return name; return name;
} }
case Qt::DecorationRole: case Qt::DecorationRole:
{ return e->document->isFileReadOnly() ? m_lockedIcon : QIcon();
bool showLock = false;
if (e->document)
showLock = e->document->filePath().isEmpty() ? false : e->document->isFileReadOnly();
else
showLock = !e->m_fileName.toFileInfo().isWritable();
return showLock ? m_lockedIcon : QIcon();
}
case Qt::ToolTipRole: case Qt::ToolTipRole:
return e->fileName().isEmpty() ? e->displayName() : e->fileName().toUserOutput(); return e->fileName().isEmpty() ? e->displayName() : e->fileName().toUserOutput();
default: default:

View File

@@ -59,15 +59,15 @@ public:
struct CORE_EXPORT Entry { struct CORE_EXPORT Entry {
Entry(); Entry();
IDocument *document; ~Entry();
Utils::FileName fileName() const; Utils::FileName fileName() const;
QString displayName() const; QString displayName() const;
QString plainDisplayName() const; QString plainDisplayName() const;
QString uniqueDisplayName() const; QString uniqueDisplayName() const;
Id id() const; Id id() const;
Utils::FileName m_fileName;
QString m_displayName; IDocument *document;
Id m_id; bool isRestored;
}; };
static Entry *entryAtRow(int row); static Entry *entryAtRow(int row);

View File

@@ -1050,7 +1050,7 @@ void EditorManagerPrivate::activateEditorForEntry(EditorView *view, DocumentMode
return; return;
} }
IDocument *document = entry->document; IDocument *document = entry->document;
if (document) { if (!entry->isRestored) {
activateEditorForDocument(view, document, flags); activateEditorForDocument(view, document, flags);
return; return;
} }
@@ -2031,10 +2031,10 @@ void EditorManager::closeDocument(DocumentModel::Entry *entry)
{ {
if (!entry) if (!entry)
return; return;
if (entry->document) if (entry->isRestored)
closeDocuments(QList<IDocument *>() << entry->document);
else
DocumentModel::removeEntry(entry); DocumentModel::removeEntry(entry);
else
closeDocuments(QList<IDocument *>() << entry->document);
} }
bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool askAboutModifiedEditors) bool EditorManager::closeEditors(const QList<IEditor*> &editorsToClose, bool askAboutModifiedEditors)
@@ -2520,15 +2520,15 @@ QByteArray EditorManager::saveState()
int entriesCount = 0; int entriesCount = 0;
foreach (DocumentModel::Entry *entry, entries) { foreach (DocumentModel::Entry *entry, entries) {
// The editor may be 0 if it was not loaded yet: In that case it is not temporary // The editor may be 0 if it was not loaded yet: In that case it is not temporary
if (!entry->document || !entry->document->isTemporary()) if (!entry->document->isTemporary())
++entriesCount; ++entriesCount;
} }
stream << entriesCount; stream << entriesCount;
foreach (DocumentModel::Entry *entry, entries) { foreach (DocumentModel::Entry *entry, entries) {
if (!entry->document || !entry->document->isTemporary()) if (!entry->document->isTemporary())
stream << entry->fileName().toString() << entry->displayName() << entry->id(); stream << entry->fileName().toString() << entry->plainDisplayName() << entry->id();
} }
stream << d->m_editorAreas.first()->saveState(); // TODO stream << d->m_editorAreas.first()->saveState(); // TODO

View File

@@ -249,7 +249,7 @@ void OpenEditorsWindow::addHistoryItems(const QList<EditLocation> &history, Edit
void OpenEditorsWindow::addRestoredItems() void OpenEditorsWindow::addRestoredItems()
{ {
foreach (DocumentModel::Entry *entry, DocumentModel::entries()) { foreach (DocumentModel::Entry *entry, DocumentModel::entries()) {
if (entry->document) if (!entry->isRestored)
continue; continue;
QTreeWidgetItem *item = new QTreeWidgetItem(); QTreeWidgetItem *item = new QTreeWidgetItem();
QString title = entry->displayName(); QString title = entry->displayName();

View File

@@ -73,13 +73,13 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
if (!regexp.isValid()) if (!regexp.isValid())
return goodEntries; return goodEntries;
const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry); const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry);
foreach (const DocumentModel::Entry &editorEntry, editors()) { foreach (const Entry &editorEntry, editors()) {
if (future.isCanceled()) if (future.isCanceled())
break; break;
QString fileName = editorEntry.fileName().toString(); QString fileName = editorEntry.fileName.toString();
if (fileName.isEmpty()) if (fileName.isEmpty())
continue; continue;
QString displayName = editorEntry.displayName(); QString displayName = editorEntry.displayName;
if (regexp.exactMatch(displayName)) { if (regexp.exactMatch(displayName)) {
LocatorFilterEntry fiEntry(this, displayName, QString(fileName + lineNoSuffix)); LocatorFilterEntry fiEntry(this, displayName, QString(fileName + lineNoSuffix));
fiEntry.extraInfo = FileUtils::shortNativePath(FileName::fromString(fileName)); fiEntry.extraInfo = FileUtils::shortNativePath(FileName::fromString(fileName));
@@ -98,16 +98,16 @@ void OpenDocumentsFilter::refreshInternally()
QMutexLocker lock(&m_mutex); Q_UNUSED(lock) QMutexLocker lock(&m_mutex); Q_UNUSED(lock)
m_editors.clear(); m_editors.clear();
foreach (DocumentModel::Entry *e, DocumentModel::entries()) { foreach (DocumentModel::Entry *e, DocumentModel::entries()) {
DocumentModel::Entry entry; Entry entry;
// create copy with only the information relevant to use // create copy with only the information relevant to use
// to avoid model deleting entries behind our back // to avoid model deleting entries behind our back
entry.m_displayName = e->displayName(); entry.displayName = e->displayName();
entry.m_fileName = e->fileName(); entry.fileName = e->fileName();
m_editors.append(entry); m_editors.append(entry);
} }
} }
QList<DocumentModel::Entry> OpenDocumentsFilter::editors() const QList<OpenDocumentsFilter::Entry> OpenDocumentsFilter::editors() const
{ {
QMutexLocker lock(&m_mutex); Q_UNUSED(lock) QMutexLocker lock(&m_mutex); Q_UNUSED(lock)
return m_editors; return m_editors;

View File

@@ -57,10 +57,17 @@ public slots:
void refreshInternally(); void refreshInternally();
private: private:
QList<DocumentModel::Entry> editors() const; class Entry
{
public:
Utils::FileName fileName;
QString displayName;
};
QList<Entry> editors() const;
mutable QMutex m_mutex; mutable QMutex m_mutex;
QList<DocumentModel::Entry> m_editors; QList<Entry> m_editors;
}; };
} // namespace Internal } // namespace Internal