summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/coreplugin/editormanager/editormanager.cpp4
-rw-r--r--src/plugins/coreplugin/filemanager.cpp530
-rw-r--r--src/plugins/coreplugin/filemanager.h11
-rw-r--r--src/plugins/projectexplorer/projectexplorer.cpp2
4 files changed, 308 insertions, 239 deletions
diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp
index 15008a72cc..8e06c85175 100644
--- a/src/plugins/coreplugin/editormanager/editormanager.cpp
+++ b/src/plugins/coreplugin/editormanager/editormanager.cpp
@@ -578,9 +578,9 @@ Core::Internal::EditorView *EditorManager::currentEditorView() const
QList<IEditor *> EditorManager::editorsForFileName(const QString &filename) const
{
QList<IEditor *> found;
- QString fixedname = FileManager::fixFileName(filename);
+ QString fixedname = FileManager::fixFileName(filename, FileManager::KeepLinks);
foreach (IEditor *editor, openedEditors()) {
- if (fixedname == FileManager::fixFileName(editor->file()->fileName()))
+ if (fixedname == FileManager::fixFileName(editor->file()->fileName(), FileManager::KeepLinks))
found << editor;
}
return found;
diff --git a/src/plugins/coreplugin/filemanager.cpp b/src/plugins/coreplugin/filemanager.cpp
index ba9c520697..d7f18179d9 100644
--- a/src/plugins/coreplugin/filemanager.cpp
+++ b/src/plugins/coreplugin/filemanager.cpp
@@ -112,6 +112,7 @@ struct FileManagerPrivate {
QMap<QString, FileState> m_states;
QStringList m_changedFiles;
QList<IFile *> m_filesWithoutWatch;
+ QMap<IFile *, QStringList> m_filesWithWatch;
QStringList m_recentFiles;
static const int m_maxRecentFiles = 7;
@@ -120,6 +121,7 @@ struct FileManagerPrivate {
QMainWindow *m_mainWindow;
QFileSystemWatcher *m_fileWatcher;
+ QFileSystemWatcher *m_linkWatcher;
bool m_blockActivated;
QString m_lastVisitedDirectory;
QString m_projectsDirectory;
@@ -143,6 +145,16 @@ FileManagerPrivate::FileManagerPrivate(QObject *q, QMainWindow *mw) :
#endif
m_blockedIFile(0)
{
+ q->connect(m_fileWatcher, SIGNAL(fileChanged(QString)),
+ q, SLOT(changedFile(QString)));
+#ifdef Q_OS_UNIX
+ m_linkWatcher = new QFileSystemWatcher(q);
+ m_linkWatcher->setObjectName(QLatin1String("_qt_autotest_force_engine_poller"));
+ q->connect(m_linkWatcher, SIGNAL(fileChanged(QString)),
+ q, SLOT(changedFile(QString)));
+#else
+ m_linkWatcher = m_fileWatcher;
+#endif
}
} // namespace Internal
@@ -152,8 +164,6 @@ FileManager::FileManager(QMainWindow *mw)
d(new Internal::FileManagerPrivate(this, mw))
{
Core::ICore *core = Core::ICore::instance();
- connect(d->m_fileWatcher, SIGNAL(fileChanged(QString)),
- this, SLOT(changedFile(QString)));
connect(d->m_mainWindow, SIGNAL(windowActivated()),
this, SLOT(mainWindowActivated()));
connect(core, SIGNAL(contextChanged(Core::IContext*,Core::Context)),
@@ -173,148 +183,167 @@ FileManager::~FileManager()
Adds a list of IFile's to the collection. If \a addWatcher is true (the default),
the files are added to a file system watcher that notifies the file manager
about file changes.
-
- Returns true if the file specified by \a files have not been yet part of the file list.
*/
void FileManager::addFiles(const QList<IFile *> &files, bool addWatcher)
{
if (!addWatcher) {
// We keep those in a separate list
- foreach(IFile *file, files)
- connect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
-
- d->m_filesWithoutWatch.append(files);
+ foreach(IFile *file, files) {
+ if (file && !d->m_filesWithoutWatch.contains(file)) {
+ connect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
+ d->m_filesWithoutWatch.append(file);
+ }
+ }
return;
}
foreach (IFile *file, files) {
- if (!file)
- continue;
- const QString &fixedFileName = fixFileName(file->fileName());
- if (d->m_states.value(fixedFileName).lastUpdatedState.contains(file))
- continue;
- connect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName()));
- connect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
-
- addFileInfo(file);
+ if (file && !d->m_filesWithWatch.contains(file)) {
+ connect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName()));
+ connect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
+ addFileInfo(file);
+ }
}
}
+/* Adds the IFile's file and possibly it's final link target to both m_states
+ (if it's file name is not empty), and the m_filesWithWatch list,
+ and adds a file watcher for each if not already done.
+ (The added file names are guaranteed to be absolute and cleaned.) */
void FileManager::addFileInfo(IFile *file)
{
- // We do want to insert the IFile into d->m_states even if the filename is empty
- // Such that m_states always contains all IFiles
-
- const QString fixedname = fixFileName(file->fileName());
- Internal::FileStateItem item;
- if (!fixedname.isEmpty()) {
- const QFileInfo fi(file->fileName());
- item.modified = fi.lastModified();
- item.permissions = fi.permissions();
- }
+ const QString fixedName = fixFileName(file->fileName(), KeepLinks);
+ const QString fixedResolvedName = fixFileName(file->fileName(), ResolveLinks);
+ addFileInfo(fixedResolvedName, file, false);
+ if (fixedName != fixedResolvedName)
+ addFileInfo(fixedName, file, true);
+}
- if (!d->m_states.contains(fixedname)) {
- d->m_states.insert(fixedname, Internal::FileState());
- if (!fixedname.isEmpty()) {
- d->m_fileWatcher->addPath(fixedname);
+/* only called from addFileInfo(IFile *) */
+void FileManager::addFileInfo(const QString &fileName, IFile *file, bool isLink)
+{
+ Internal::FileStateItem state;
+ if (!fileName.isEmpty()) {
+ const QFileInfo fi(fileName);
+ state.modified = fi.lastModified();
+ state.permissions = fi.permissions();
+ // Add watcher if we don't have that already
+ if (!d->m_states.contains(fileName)) {
+ d->m_states.insert(fileName, Internal::FileState());
+
+ if (isLink)
+ d->m_linkWatcher->addPath(fileName);
+ else
+ d->m_fileWatcher->addPath(fileName);
}
+ d->m_states[fileName].lastUpdatedState.insert(file, state);
}
-
- d->m_states[fixedname].lastUpdatedState.insert(file, item);
+ d->m_filesWithWatch[file].append(fileName); // inserts a new QStringList if not already there
}
+/* Updates the time stamp and permission information of the files
+ registered for this IFile (in m_filesWithWatch; can be the IFile's file + final link target) */
void FileManager::updateFileInfo(IFile *file)
{
- const QString fixedname = fixFileName(file->fileName());
- // If the filename is empty there's nothing to do
- if (fixedname.isEmpty())
- return;
- const QFileInfo fi(file->fileName());
-
- Internal::FileStateItem item;
- item.modified = fi.lastModified();
- item.permissions = fi.permissions();
-
- if (d->m_states.contains(fixedname) && d->m_states.value(fixedname).lastUpdatedState.contains(file))
- d->m_states[fixedname].lastUpdatedState.insert(file, item);
+ foreach (const QString &fileName, d->m_filesWithWatch.value(file)) {
+ // If the filename is empty there's nothing to do
+ if (fileName.isEmpty())
+ continue;
+ const QFileInfo fi(fileName);
+ Internal::FileStateItem item;
+ item.modified = fi.lastModified();
+ item.permissions = fi.permissions();
+ QTC_ASSERT(d->m_states.contains(fileName), continue);
+ QTC_ASSERT(d->m_states.value(fileName).lastUpdatedState.contains(file), continue);
+ d->m_states[fileName].lastUpdatedState.insert(file, item);
+ }
}
/// Dumps the state of the file manager's map
/// For debugging purposes
void FileManager::dump()
{
+ qDebug() << "======== dumping state map";
QMap<QString, Internal::FileState>::const_iterator it, end;
it = d->m_states.constBegin();
end = d->m_states.constEnd();
for (; it != end; ++it) {
- qDebug()<<" ";
qDebug() << it.key();
- qDebug() << it.value().expected.modified;
+ qDebug() << " expected:" << it.value().expected.modified;
QMap<IFile *, Internal::FileStateItem>::const_iterator jt, jend;
jt = it.value().lastUpdatedState.constBegin();
jend = it.value().lastUpdatedState.constEnd();
for (; jt != jend; ++jt) {
- qDebug() << jt.key() << jt.value().modified;
+ qDebug() << " " << jt.key()->fileName() << jt.value().modified;
}
}
+ qDebug() << "------- dumping files with watch list";
+ foreach (IFile *key, d->m_filesWithWatch.keys()) {
+ qDebug() << key->fileName() << d->m_filesWithWatch.value(key);
+ }
+ qDebug() << "------- dumping watch list";
+ qDebug() << d->m_fileWatcher->files();
+ qDebug() << "------- dumping link watch list";
+ qDebug() << d->m_linkWatcher->files();
}
+/*!
+ \fn void FileManager::renamedFile(const QString &from, QString &to)
+ \brief Tells the file manager that a file has been renamed on disk from within Qt Creator.
+
+ Needs to be called right after the actual renaming on disk (i.e. before the file system
+ watcher can report the event during the next event loop run). \a from needs to be an absolute file path.
+ This will notify all IFile objects pointing to that file of the rename
+ by calling IFile::rename, and update the cached time and permission
+ information to avoid annoying the user with "file has been removed"
+ popups.
+*/
void FileManager::renamedFile(const QString &from, QString &to)
{
- QString fixedFrom = fixFileName(from);
- QString fixedTo = fixFileName(to);
- if (d->m_states.contains(fixedFrom)) {
- QTC_ASSERT(!d->m_states.contains(to), return);
- d->m_states.insert(fixedTo, d->m_states.value(fixedFrom));
- d->m_states.remove(fixedFrom);
- QFileInfo fi(to);
- d->m_states[fixedTo].expected.modified = fi.lastModified();
- d->m_states[fixedTo].expected.permissions = fi.permissions();
-
- d->m_fileWatcher->removePath(fixedFrom);
- d->m_fileWatcher->addPath(fixedTo);
-
- QMap<IFile *, Internal::FileStateItem>::iterator it, end;
- it = d->m_states[fixedTo].lastUpdatedState.begin();
- end = d->m_states[fixedTo].lastUpdatedState.end();
-
- for ( ; it != end; ++it) {
- d->m_blockedIFile = it.key();
- it.key()->rename(to);
- d->m_blockedIFile = it.key();
- it.value().modified = fi.lastModified();
- }
- }
-}
+ const QString &fixedFrom = fixFileName(from, KeepLinks);
-///
-/// Does not use file->fileName, as such is save to use
-/// with renamed files and deleted files
-void FileManager::removeFileInfo(IFile *file)
-{
- QMap<QString, Internal::FileState>::const_iterator it, end;
- end = d->m_states.constEnd();
- for (it = d->m_states.constBegin(); it != end; ++it) {
- if (it.value().lastUpdatedState.contains(file)) {
- removeFileInfo(it.key(), file);
- break;
- }
+ // gather the list of IFiles
+ QList<IFile *> filesToRename;
+ QMapIterator<IFile *, QStringList> it(d->m_filesWithWatch);
+ while (it.hasNext()) {
+ it.next();
+ if (it.value().contains(fixedFrom))
+ filesToRename.append(it.key());
}
+ // rename the IFiles
+ foreach (IFile *file, filesToRename) {
+ d->m_blockedIFile = file;
+ removeFileInfo(file);
+ file->rename(to);
+ addFileInfo(file);
+ d->m_blockedIFile = 0;
+ }
}
-/* only called from removeFileInfo(IFile*) */
-void FileManager::removeFileInfo(const QString &fileName, IFile *file)
+/* Removes all occurrances of the IFile from m_filesWithWatch and m_states.
+ If that results in a file no longer being referenced by any IFile, this
+ also removes the file watcher.
+*/
+void FileManager::removeFileInfo(IFile *file)
{
- QTC_ASSERT(d->m_states.value(fileName).lastUpdatedState.contains(file), return);
- d->m_states[fileName].lastUpdatedState.remove(file);
- if (d->m_states.value(fileName).lastUpdatedState.isEmpty()) {
- if (!fileName.isEmpty())
- d->m_fileWatcher->removePath(fileName);
- d->m_states.remove(fileName); // this deletes fileName
+ if (!d->m_filesWithWatch.contains(file))
+ return;
+ foreach (const QString &fileName, d->m_filesWithWatch.value(file)) {
+ if (!d->m_states.contains(fileName))
+ continue;
+ d->m_states[fileName].lastUpdatedState.remove(file);
+ if (d->m_states.value(fileName).lastUpdatedState.isEmpty()) {
+ if (d->m_fileWatcher->files().contains(fileName))
+ d->m_fileWatcher->removePath(fileName);
+ if (d->m_linkWatcher->files().contains(fileName))
+ d->m_linkWatcher->removePath(fileName);
+ d->m_states.remove(fileName);
+ }
}
+ d->m_filesWithWatch.remove(file);
}
/*!
@@ -323,8 +352,6 @@ void FileManager::removeFileInfo(const QString &fileName, IFile *file)
Adds a IFile object to the collection. If \a addWatcher is true (the default),
the file is added to a file system watcher that notifies the file manager
about file changes.
-
- Returns true if the file specified by \a file has not been yet part of the file list.
*/
void FileManager::addFile(IFile *file, bool addWatcher)
{
@@ -333,7 +360,6 @@ void FileManager::addFile(IFile *file, bool addWatcher)
void FileManager::fileDestroyed(QObject *obj)
{
- // removeFileInfo works even if the file does not really exist anymore
IFile *file = static_cast<IFile*>(obj);
// Check the special unwatched first:
if (d->m_filesWithoutWatch.contains(file)) {
@@ -352,8 +378,7 @@ void FileManager::fileDestroyed(QObject *obj)
*/
void FileManager::removeFile(IFile *file)
{
- if (!file)
- return;
+ QTC_ASSERT(file, return);
// Special casing unwatched files
if (d->m_filesWithoutWatch.contains(file)) {
@@ -362,12 +387,13 @@ void FileManager::removeFile(IFile *file)
return;
}
+ removeFileInfo(file);
disconnect(file, SIGNAL(changed()), this, SLOT(checkForNewFileName()));
disconnect(file, SIGNAL(destroyed(QObject *)), this, SLOT(fileDestroyed(QObject *)));
-
- removeFileInfo(file);
}
+/* Slot reacting on IFile::changed. We need to check if the signal was sent
+ because the file was saved under different name. */
void FileManager::checkForNewFileName()
{
IFile *file = qobject_cast<IFile *>(sender());
@@ -376,32 +402,33 @@ void FileManager::checkForNewFileName()
if (file == d->m_blockedIFile)
return;
QTC_ASSERT(file, return);
- const QString &fileName = fixFileName(file->fileName());
-
- // check if the IFile is in the map
- if (d->m_states.value(fileName).lastUpdatedState.contains(file)) {
- // the file might have been deleted and written again, so guard against that
- d->m_fileWatcher->removePath(fileName);
- d->m_fileWatcher->addPath(fileName);
- updateFileInfo(file);
- return;
- }
+ QTC_ASSERT(d->m_filesWithWatch.contains(file), return);
- // Probably the name has changed...
+ // Maybe the name has changed or file has been deleted and created again ...
// This also updates the state to the on disk state
removeFileInfo(file);
addFileInfo(file);
}
-// TODO Rename to nativeFileName
-QString FileManager::fixFileName(const QString &fileName)
+/*!
+ \fn QString FileManager::fixFileName(const QString &fileName, FixMode fixmode)
+ Returns a guaranteed cleaned path in native form. If the file exists,
+ it will either be a cleaned absolute file path (fixmode == KeepLinks), or
+ a cleaned canonical file path (fixmode == ResolveLinks).
+*/
+QString FileManager::fixFileName(const QString &fileName, FixMode fixmode)
{
QString s = fileName;
QFileInfo fi(s);
- if (!fi.exists())
- s = QDir::toNativeSeparators(s);
- else
- s = QDir::toNativeSeparators(fi.canonicalFilePath());
+ if (fi.exists()) {
+ if (fixmode == ResolveLinks)
+ s = fi.canonicalFilePath();
+ else
+ s = QDir::cleanPath(fi.absoluteFilePath());
+ } else {
+ s = QDir::cleanPath(s);
+ }
+ s = QDir::toNativeSeparators(s);
#ifdef Q_OS_WIN
s = s.toLower();
#endif
@@ -417,16 +444,11 @@ QList<IFile *> FileManager::modifiedFiles() const
{
QList<IFile *> modifiedFiles;
- QMap<QString, Internal::FileState>::const_iterator it, end;
- end = d->m_states.constEnd();
- for(it = d->m_states.constBegin(); it != end; ++it) {
- QMap<IFile *, Internal::FileStateItem>::const_iterator jt, jend;
- jt = (*it).lastUpdatedState.constBegin();
- jend = (*it).lastUpdatedState.constEnd();
- for( ; jt != jend; ++jt)
- if (jt.key()->isModified())
- modifiedFiles << jt.key();
+ foreach (IFile *file, d->m_filesWithWatch.keys()) {
+ if (file->isModified())
+ modifiedFiles << file;
}
+
foreach(IFile *file, d->m_filesWithoutWatch) {
if (file->isModified())
modifiedFiles << file;
@@ -464,7 +486,8 @@ void FileManager::unblockFileChange(IFile *file)
// If so then it's a expected change
updateFileInfo(file);
- updateExpectedState(fixFileName(file->fileName()));
+ foreach (const QString &fileName, d->m_filesWithWatch.value(file))
+ updateExpectedState(fileName);
}
/*!
@@ -494,18 +517,24 @@ void FileManager::unexpectFileChange(const QString &fileName)
// is the same as the saved one here
// If so then it's a expected change
- updateExpectedState(fileName);
+ if (fileName.isEmpty())
+ return;
+ const QString fixedName = fixFileName(fileName, KeepLinks);
+ updateExpectedState(fixedName);
+ const QString fixedResolvedName = fixFileName(fileName, ResolveLinks);
+ if (fixedName != fixedResolvedName)
+ updateExpectedState(fixedResolvedName);
}
+/* only called from unblock and unexpect file change methods */
void FileManager::updateExpectedState(const QString &fileName)
{
- const QString &fixedName = fixFileName(fileName);
- if (fixedName.isEmpty())
+ if (fileName.isEmpty())
return;
- QFileInfo fi(fixedName);
- if (d->m_states.contains(fixedName)) {
- d->m_states[fixedName].expected.modified = fi.lastModified();
- d->m_states[fixedName].expected.permissions = fi.permissions();
+ if (d->m_states.contains(fileName)) {
+ QFileInfo fi(fileName);
+ d->m_states[fileName].expected.modified = fi.lastModified();
+ d->m_states[fileName].expected.permissions = fi.permissions();
}
}
@@ -769,9 +798,8 @@ void FileManager::changedFile(const QString &fileName)
{
const bool wasempty = d->m_changedFiles.isEmpty();
- const QString &fixedName = fixFileName(fileName);
- if (!d->m_changedFiles.contains(fixedName))
- d->m_changedFiles.append(fixedName);
+ if (!d->m_changedFiles.contains(fileName) && d->m_states.contains(fileName))
+ d->m_changedFiles.append(fileName);
if (wasempty && !d->m_changedFiles.isEmpty()) {
QTimer::singleShot(200, this, SLOT(checkForReload()));
@@ -788,6 +816,8 @@ void FileManager::mainWindowActivated()
void FileManager::checkForReload()
{
+ if (d->m_changedFiles.isEmpty())
+ return;
if (QApplication::activeWindow() != d->m_mainWindow)
return;
@@ -801,120 +831,154 @@ void FileManager::checkForReload()
QList<IEditor*> editorsToClose;
QMap<IFile*, QString> filesToSave;
- QStringList modifiedFileNames;
+
+ // collect file information
+ QMap<QString, Internal::FileStateItem> currentStates;
+ QMap<QString, IFile::ChangeType> changeTypes;
+ QSet<IFile *> changedIFiles;
foreach (const QString &fileName, d->m_changedFiles) {
- // Get the information from the filesystem
- IFile::ChangeTrigger behavior = IFile::TriggerExternal;
IFile::ChangeType type = IFile::TypeContents;
+ Internal::FileStateItem state;
QFileInfo fi(fileName);
if (!fi.exists()) {
type = IFile::TypeRemoved;
} else {
- modifiedFileNames << fileName;
- if (fi.lastModified() == d->m_states.value(fileName).expected.modified
- && fi.permissions() == d->m_states.value(fileName).expected.permissions) {
- behavior = IFile::TriggerInternal;
- }
+ state.modified = fi.lastModified();
+ state.permissions = fi.permissions();
}
+ currentStates.insert(fileName, state);
+ changeTypes.insert(fileName, type);
+ foreach (IFile *file, d->m_states.value(fileName).lastUpdatedState.keys())
+ changedIFiles.insert(file);
+ }
+
+ // handle the IFiles
+ foreach (IFile *file, changedIFiles) {
+ IFile::ChangeTrigger behavior = IFile::TriggerInternal;
+ IFile::ChangeType type = IFile::TypePermissions;
+ bool changed = false;
+ // find out the type & behavior from the two possible files
+ // behavior is internal if all changes are expected (and none removed)
+ // type is "max" of both types (remove > contents > permissions)
+ foreach (const QString & fileName, d->m_filesWithWatch.value(file)) {
+ // was the file reported?
+ if (!currentStates.contains(fileName))
+ continue;
- const QMap<IFile *, Internal::FileStateItem> &lastUpdated =
- d->m_states.value(fileName).lastUpdatedState;
- QMap<IFile *, Internal::FileStateItem>::const_iterator it, end;
- it = lastUpdated.constBegin();
- end = lastUpdated.constEnd();
- for ( ; it != end; ++it) {
- IFile *file = it.key();
- d->m_blockedIFile = file;
- // Compare
- if (it.value().modified == fi.lastModified()
- && it.value().permissions == fi.permissions()) {
- // Already up to date
+ Internal::FileStateItem currentState = currentStates.value(fileName);
+ Internal::FileStateItem expectedState = d->m_states.value(fileName).expected;
+ Internal::FileStateItem lastState = d->m_states.value(fileName).lastUpdatedState.value(file);
+ // did the file actually change?
+ if (lastState.modified == currentState.modified && lastState.permissions == currentState.permissions)
continue;
+ changed = true;
+
+ // was it only a permission change?
+ if (lastState.modified == currentState.modified)
+ continue;
+
+ // was the change unexpected?
+ if (currentState.modified != expectedState.modified || currentState.permissions != expectedState.permissions) {
+ behavior = IFile::TriggerExternal;
}
- // we've got some modification
- // check if it's contents or permissions:
- if (it.value().modified == fi.lastModified()) {
- // Only permission change
- file->reload(IFile::FlagReload, IFile::TypePermissions);
- // now we know it's a content change or file was removed
- } else if (defaultBehavior == IFile::ReloadUnmodified
- && type == IFile::TypeContents && !file->isModified()) {
- // content change, but unmodified (and settings say to reload in this case)
+
+ // find out the type
+ IFile::ChangeType fileChange = changeTypes.value(fileName);
+ if (fileChange == IFile::TypeRemoved) {
+ type = IFile::TypeRemoved;
+ behavior = IFile::TriggerExternal; // removed files always trigger externally
+ } else if (fileChange == IFile::TypeContents && type == IFile::TypePermissions) {
+ type = IFile::TypeContents;
+ }
+ }
+
+ if (!changed) // probably because the change was blocked with (un)blockFileChange
+ continue;
+
+ // handle it!
+ d->m_blockedIFile = file;
+
+ // we've got some modification
+ // check if it's contents or permissions:
+ if (type == IFile::TypePermissions) {
+ // Only permission change
+ file->reload(IFile::FlagReload, IFile::TypePermissions);
+ // now we know it's a content change or file was removed
+ } else if (defaultBehavior == IFile::ReloadUnmodified
+ && type == IFile::TypeContents && !file->isModified()) {
+ // content change, but unmodified (and settings say to reload in this case)
+ file->reload(IFile::FlagReload, type);
+ // file was removed or it's a content change and the default behavior for
+ // unmodified files didn't kick in
+ } else if (defaultBehavior == IFile::IgnoreAll) {
+ // content change or removed, but settings say ignore
+ file->reload(IFile::FlagIgnore, type);
+ // either the default behavior is to always ask,
+ // or the ReloadUnmodified default behavior didn't kick in,
+ // so do whatever the IFile wants us to do
+ } else {
+ // check if IFile wants us to ask
+ if (file->reloadBehavior(behavior, type) == IFile::BehaviorSilent) {
+ // content change or removed, IFile wants silent handling
file->reload(IFile::FlagReload, type);
- // file was removed or it's a content change and the default behavior for
- // unmodified files didn't kick in
- } else if (defaultBehavior == IFile::IgnoreAll) {
- // content change or removed, but settings say ignore
- file->reload(IFile::FlagIgnore, type);
- // either the default behavior is to always ask,
- // or the ReloadUnmodified default behavior didn't kick in,
- // so do whatever the IFile wants us to do
- } else {
- // check if IFile wants us to ask
- if (file->reloadBehavior(behavior, type) == IFile::BehaviorSilent) {
- // content change or removed, IFile wants silent handling
- file->reload(IFile::FlagReload, type);
- // IFile wants us to ask
- } else if (type == IFile::TypeContents) {
- // content change, IFile wants to ask user
- if (previousAnswer == Utils::ReloadNone) {
- // answer already given, ignore
- file->reload(IFile::FlagIgnore, IFile::TypeContents);
- } else if (previousAnswer == Utils::ReloadAll) {
- // answer already given, reload
+ // IFile wants us to ask
+ } else if (type == IFile::TypeContents) {
+ // content change, IFile wants to ask user
+ if (previousAnswer == Utils::ReloadNone) {
+ // answer already given, ignore
+ file->reload(IFile::FlagIgnore, IFile::TypeContents);
+ } else if (previousAnswer == Utils::ReloadAll) {
+ // answer already given, reload
+ file->reload(IFile::FlagReload, IFile::TypeContents);
+ } else {
+ // Ask about content change
+ previousAnswer = Utils::reloadPrompt(file->fileName(), file->isModified(), QApplication::activeWindow());
+ switch (previousAnswer) {
+ case Utils::ReloadAll:
+ case Utils::ReloadCurrent:
file->reload(IFile::FlagReload, IFile::TypeContents);
- } else {
- // Ask about content change
- previousAnswer = Utils::reloadPrompt(fileName, file->isModified(), QApplication::activeWindow());
- switch (previousAnswer) {
- case Utils::ReloadAll:
- case Utils::ReloadCurrent:
- file->reload(IFile::FlagReload, IFile::TypeContents);
- break;
- case Utils::ReloadSkipCurrent:
- case Utils::ReloadNone:
- file->reload(IFile::FlagIgnore, IFile::TypeContents);
- break;
- }
+ break;
+ case Utils::ReloadSkipCurrent:
+ case Utils::ReloadNone:
+ file->reload(IFile::FlagIgnore, IFile::TypeContents);
+ break;
}
- // IFile wants us to ask, and it's the TypeRemoved case
- } else {
- // Ask about removed file
- bool unhandled = true;
- while (unhandled) {
- switch (Utils::fileDeletedPrompt(fileName, QApplication::activeWindow())) {
- case Utils::FileDeletedSave:
- filesToSave.insert(file, fileName);
- unhandled = false;
- break;
- case Utils::FileDeletedSaveAs:
- {
- const QString &saveFileName = getSaveAsFileName(file);
- if (!saveFileName.isEmpty()) {
- filesToSave.insert(file, saveFileName);
- unhandled = false;
- }
- break;
- }
- case Utils::FileDeletedClose:
- editorsToClose << EditorManager::instance()->editorsForFile(file);
+ }
+ // IFile wants us to ask, and it's the TypeRemoved case
+ } else {
+ // Ask about removed file
+ bool unhandled = true;
+ while (unhandled) {
+ switch (Utils::fileDeletedPrompt(file->fileName(), QApplication::activeWindow())) {
+ case Utils::FileDeletedSave:
+ filesToSave.insert(file, file->fileName());
+ unhandled = false;
+ break;
+ case Utils::FileDeletedSaveAs:
+ {
+ const QString &saveFileName = getSaveAsFileName(file);
+ if (!saveFileName.isEmpty()) {
+ filesToSave.insert(file, saveFileName);
unhandled = false;
- break;
}
+ break;
+ }
+ case Utils::FileDeletedClose:
+ editorsToClose << EditorManager::instance()->editorsForFile(file);
+ unhandled = false;
+ break;
}
}
}
-
- updateFileInfo(file);
- d->m_blockedIFile = 0;
}
- }
- // cleanup
- if (!modifiedFileNames.isEmpty()) {
- d->m_fileWatcher->removePaths(modifiedFileNames);
- d->m_fileWatcher->addPaths(modifiedFileNames);
+ // update file info, also handling if e.g. link target has changed
+ removeFileInfo(file);
+ addFileInfo(file);
+ d->m_blockedIFile = 0;
}
+
+ // clean up
d->m_changedFiles.clear();
// handle deleted files
@@ -929,6 +993,8 @@ void FileManager::checkForReload()
}
d->m_blockActivated = false;
+
+// dump();
}
void FileManager::syncWithEditor(Core::IContext *context)
@@ -951,10 +1017,10 @@ void FileManager::addToRecentFiles(const QString &fileName)
{
if (fileName.isEmpty())
return;
- QString unifiedForm(fixFileName(fileName));
+ QString unifiedForm(fixFileName(fileName, KeepLinks));
QMutableStringListIterator it(d->m_recentFiles);
while (it.hasNext()) {
- QString recentUnifiedForm(fixFileName(it.next()));
+ QString recentUnifiedForm(fixFileName(it.next(), KeepLinks));
if (unifiedForm == recentUnifiedForm)
it.remove();
}
diff --git a/src/plugins/coreplugin/filemanager.h b/src/plugins/coreplugin/filemanager.h
index c6e827e3c1..5db7453282 100644
--- a/src/plugins/coreplugin/filemanager.h
+++ b/src/plugins/coreplugin/filemanager.h
@@ -53,6 +53,11 @@ class CORE_EXPORT FileManager : public QObject
{
Q_OBJECT
public:
+ enum FixMode {
+ ResolveLinks,
+ KeepLinks
+ };
+
explicit FileManager(QMainWindow *ew);
virtual ~FileManager();
@@ -80,7 +85,7 @@ public:
QString currentFile() const;
// helper methods
- static QString fixFileName(const QString &fileName);
+ static QString fixFileName(const QString &fileName, FixMode fixmode);
QStringList getOpenFileNames(const QString &filters,
const QString path = QString(),
@@ -134,11 +139,9 @@ private:
void readSettings();
void dump();
void addFileInfo(IFile *file);
+ void addFileInfo(const QString &fileName, IFile *file, bool isLink);
void removeFileInfo(IFile *file);
- void removeFileInfo(const QString &fileName, IFile *file);
- void addWatch(const QString &filename);
- void removeWatch(const QString &filename);
void updateFileInfo(IFile *file);
void updateExpectedState(const QString &fileName);
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 027e399155..8ac905e9ce 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -2262,7 +2262,7 @@ void ProjectExplorerPlugin::renameFile(Node *node, const QString &to)
FileNode *fileNode = qobject_cast<FileNode *>(node);
if (!fileNode)
return;
- QString orgFilePath = node->path();
+ QString orgFilePath = QFileInfo(node->path()).absoluteFilePath();
QString dir = QFileInfo(orgFilePath).absolutePath();
QString newFilePath = dir + "/" + to;
Core::ICore *core = Core::ICore::instance();