Commit fae7dc95 authored by Oswald Buddenhagen's avatar Oswald Buddenhagen

add errorString output argument to IFile::reload() & IEditor::open()

add/unify read error handling in all affected classes
parent f1f9904d
......@@ -34,6 +34,9 @@
#include "bineditor.h"
#include "bineditorconstants.h"
#include <coreplugin/icore.h>
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QDebug>
......@@ -43,6 +46,7 @@
#include <QtGui/QMenu>
#include <QtGui/QAction>
#include <QtGui/QMainWindow>
#include <QtGui/QMessageBox>
#include <QtGui/QHBoxLayout>
#include <QtGui/QLineEdit>
#include <QtGui/QRegExpValidator>
......@@ -219,16 +223,23 @@ public:
emit changed();
}
bool open(const QString &fileName, quint64 offset = 0) {
bool open(QString *errorString, const QString &fileName, quint64 offset = 0) {
QFile file(fileName);
if (offset < static_cast<quint64>(file.size())
&& file.open(QIODevice::ReadOnly)) {
if (offset >= static_cast<quint64>(file.size()))
return false;
if (file.open(QIODevice::ReadOnly)) {
m_fileName = fileName;
m_editor->setSizes(offset, file.size());
m_editor->editor()->setDisplayName(QFileInfo(fileName).fileName());
file.close();
return true;
}
QString errStr = tr("Cannot open %1: %2").arg(
QDir::toNativeSeparators(fileName), file.errorString());
if (errorString)
*errorString = errStr;
else
QMessageBox::critical(Core::ICore::instance()->mainWindow(), tr("File Error"), errStr);
return false;
}
......@@ -246,19 +257,23 @@ private slots:
data += QByteArray(blockSize - dataSize, 0);
m_editor->addData(block, data);
file.close();
} else {
QMessageBox::critical(Core::ICore::instance()->mainWindow(), tr("File Error"),
tr("Cannot open %1: %2").arg(
QDir::toNativeSeparators(m_fileName), file.errorString()));
}
}
void provideNewRange(Core::IEditor *, quint64 offset) {
open(m_fileName, offset);
open(0, m_fileName, offset);
}
void handleStartOfFileRequested(Core::IEditor *) {
open(m_fileName, 0);
open(0, m_fileName, 0);
}
void handleEndOfFileRequested(Core::IEditor *) {
open(m_fileName, QFileInfo(m_fileName).size() - 1);
open(0, m_fileName, QFileInfo(m_fileName).size() - 1);
}
public:
......@@ -295,16 +310,18 @@ public:
return BehaviorAsk;
}
void reload(ReloadFlag flag, ChangeType type) {
bool reload(QString *errorString, ReloadFlag flag, ChangeType type) {
if (flag == FlagIgnore)
return;
return true;
if (type == TypePermissions) {
emit changed();
} else {
emit aboutToReload();
if (open(m_fileName))
emit reloaded();
if (!open(errorString, m_fileName))
return false;
emit reloaded();
}
return true;
}
private:
......@@ -357,8 +374,8 @@ public:
m_file->setFilename(QString());
return true;
}
bool open(const QString &fileName = QString()) {
return m_file->open(fileName);
bool open(QString *errorString, const QString &fileName = QString()) {
return m_file->open(errorString, fileName);
}
Core::IFile *file() { return m_file; }
QString id() const { return QLatin1String(Core::Constants::K_DEFAULT_BINARY_EDITOR_ID); }
......
......@@ -794,10 +794,12 @@ Core::IFile::ReloadBehavior CMakeFile::reloadBehavior(ChangeTrigger state, Chang
return BehaviorSilent;
}
void CMakeFile::reload(ReloadFlag flag, ChangeType type)
bool CMakeFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
{
Q_UNUSED(errorString)
Q_UNUSED(flag)
Q_UNUSED(type)
return true;
}
CMakeBuildSettingsWidget::CMakeBuildSettingsWidget(CMakeTarget *target)
......
......@@ -211,7 +211,7 @@ public:
bool isSaveAsAllowed() const;
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
void reload(ReloadFlag flag, ChangeType type);
bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
void rename(const QString &newName);
......
......@@ -1217,9 +1217,10 @@ IEditor *EditorManager::openEditor(Core::Internal::EditorView *view, const QStri
// back to the default editor:
if (!editor)
editor = createEditor(QString(), fn);
if (!editor || !editor->open(fn)) {
QString errorString;
if (!editor || !editor->open(&errorString, fn)) {
QApplication::restoreOverrideCursor();
QMessageBox::critical(m_d->m_core->mainWindow(), tr("Opening File"), tr("Cannot open file %1!").arg(QDir::toNativeSeparators(fn)));
QMessageBox::critical(m_d->m_core->mainWindow(), tr("File Error"), errorString);
delete editor;
editor = 0;
return 0;
......@@ -1843,7 +1844,9 @@ void EditorManager::revertToSaved()
return;
}
currEditor->file()->reload(IFile::FlagReload, IFile::TypeContents);
QString errorString;
if (!currEditor->file()->reload(&errorString, IFile::FlagReload, IFile::TypeContents))
QMessageBox::critical(m_d->m_core->mainWindow(), tr("File Error"), errorString);
}
void EditorManager::showEditorInfoBar(const QString &id,
......
......@@ -50,7 +50,7 @@ public:
virtual ~IEditor() {}
virtual bool createNew(const QString &contents = QString()) = 0;
virtual bool open(const QString &fileName = QString()) = 0;
virtual bool open(QString *errorString, const QString &fileName = QString()) = 0;
virtual IFile *file() = 0;
virtual QString id() const = 0;
virtual QString displayName() const = 0;
......
......@@ -912,6 +912,7 @@ void FileManager::checkForReload()
}
// handle the IFiles
QStringList errorStrings;
foreach (IFile *file, changedIFiles) {
IFile::ChangeTrigger behavior = IFile::TriggerInternal;
IFile::ChangeType type = IFile::TypePermissions;
......@@ -958,21 +959,23 @@ void FileManager::checkForReload()
// handle it!
d->m_blockedIFile = file;
bool success = true;
QString errorString;
// 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);
success = file->reload(&errorString, 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);
success = file->reload(&errorString, 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);
success = file->reload(&errorString, 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
......@@ -980,27 +983,27 @@ void FileManager::checkForReload()
// 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);
success = file->reload(&errorString, 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);
success = file->reload(&errorString, IFile::FlagIgnore, IFile::TypeContents);
} else if (previousAnswer == Utils::ReloadAll) {
// answer already given, reload
file->reload(IFile::FlagReload, IFile::TypeContents);
success = file->reload(&errorString, 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);
success = file->reload(&errorString, IFile::FlagReload, IFile::TypeContents);
break;
case Utils::ReloadSkipCurrent:
case Utils::ReloadNone:
file->reload(IFile::FlagIgnore, IFile::TypeContents);
success = file->reload(&errorString, IFile::FlagIgnore, IFile::TypeContents);
break;
}
}
......@@ -1031,12 +1034,21 @@ void FileManager::checkForReload()
}
}
}
if (!success) {
if (errorString.isEmpty())
errorStrings << tr("Cannot reload %1").arg(QDir::toNativeSeparators(file->fileName()));
else
errorStrings << errorString;
}
// update file info, also handling if e.g. link target has changed
removeFileInfo(file);
addFileInfo(file);
d->m_blockedIFile = 0;
}
if (!errorStrings.isEmpty())
QMessageBox::critical(d->m_mainWindow, tr("File Error"),
errorStrings.join(QLatin1String("\n")));
// handle deleted files
EditorManager::instance()->closeEditors(editorsToClose, false);
......
......@@ -95,7 +95,7 @@ public:
virtual bool isSaveAsAllowed() const = 0;
virtual ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const = 0;
virtual void reload(ReloadFlag flag, ChangeType type) = 0;
virtual bool reload(QString *errorString, ReloadFlag flag, ChangeType type) = 0;
virtual void rename(const QString &newName) = 0;
virtual void checkPermissions() {}
......
......@@ -1787,9 +1787,9 @@ QString CPPEditor::id() const
return QLatin1String(CppEditor::Constants::CPPEDITOR_ID);
}
bool CPPEditor::open(const QString & fileName)
bool CPPEditor::open(QString *errorString, const QString & fileName)
{
bool b = TextEditor::BaseTextEditor::open(fileName);
bool b = TextEditor::BaseTextEditor::open(errorString, fileName);
editorWidget()->setMimeType(Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName)).type());
return b;
}
......
......@@ -152,7 +152,7 @@ public:
QString id() const;
bool isTemporary() const { return false; }
virtual bool open(const QString & fileName);
virtual bool open(QString *errorString, const QString & fileName);
};
class CPPEditorWidget : public TextEditor::BaseTextEditorWidget
......
......@@ -46,6 +46,7 @@
#include <texteditor/plaintexteditor.h>
#include <utils/qtcassert.h>
#include <utils/fileutils.h>
#include <QtDesigner/QDesignerFormWindowInterface>
......@@ -79,7 +80,7 @@ FormWindowEditor::FormWindowEditor(Internal::DesignerXmlEditor *editor,
connect(form, SIGNAL(changed()), this, SIGNAL(changed()));
// Revert to saved/load externally modified files.
connect(&d->m_file, SIGNAL(reload(QString)), this, SLOT(slotOpen(QString)));
connect(&d->m_file, SIGNAL(reload(QString*,QString)), this, SLOT(slotOpen(QString*,QString)));
// Force update of open editors model.
connect(&d->m_file, SIGNAL(saved()), this, SIGNAL(changed()));
connect(&d->m_file, SIGNAL(changed()), this, SIGNAL(changed()));
......@@ -126,12 +127,12 @@ bool FormWindowEditor::createNew(const QString &contents)
return true;
}
void FormWindowEditor::slotOpen(const QString &fileName)
void FormWindowEditor::slotOpen(QString *errorString, const QString &fileName)
{
open(fileName);
open(errorString, fileName);
}
bool FormWindowEditor::open(const QString &fileName)
bool FormWindowEditor::open(QString *errorString, const QString &fileName)
{
if (Designer::Constants::Internal::debug)
qDebug() << "FormWindowEditor::open" << fileName;
......@@ -147,15 +148,14 @@ bool FormWindowEditor::open(const QString &fileName)
const QFileInfo fi(fileName);
const QString absfileName = fi.absoluteFilePath();
QFile file(absfileName);
if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
Utils::FileReader reader;
if (!reader.fetch(absfileName, QIODevice::Text, errorString))
return false;
form->setFileName(absfileName);
const QString contents = QString::fromUtf8(file.readAll());
const QString contents = QString::fromUtf8(reader.data());
form->setContents(contents);
file.close();
if (!form->mainContainer())
return false;
form->setDirty(false);
......
......@@ -71,7 +71,7 @@ public:
// IEditor
virtual bool createNew(const QString &contents = QString());
virtual bool open(const QString &fileName = QString());
virtual bool open(QString *errorString, const QString &fileName = QString());
virtual Core::IFile *file();
virtual QString id() const;
virtual QString displayName() const;
......@@ -100,7 +100,7 @@ public slots:
void configureXmlEditor() const;
private slots:
void slotOpen(const QString &fileName);
void slotOpen(QString *errorString, const QString &fileName);
private:
void syncXmlEditor(const QString &contents);
......
......@@ -141,17 +141,20 @@ Core::IFile::ReloadBehavior FormWindowFile::reloadBehavior(ChangeTrigger state,
return BehaviorAsk;
}
void FormWindowFile::reload(ReloadFlag flag, ChangeType type)
bool FormWindowFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
{
if (flag == FlagIgnore)
return;
return true;
if (type == TypePermissions) {
emit changed();
} else {
emit aboutToReload();
emit reload(m_fileName);
emit reload(errorString, m_fileName);
if (!errorString->isEmpty())
return false;
emit reloaded();
}
return true;
}
QString FormWindowFile::defaultPath() const
......
......@@ -59,7 +59,7 @@ public:
virtual bool isReadOnly() const;
virtual bool isSaveAsAllowed() const;
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
void reload(ReloadFlag flag, ChangeType type);
bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
virtual QString defaultPath() const;
virtual QString suggestedFileName() const;
virtual QString mimeType() const;
......@@ -75,7 +75,7 @@ public:
signals:
// Internal
void saved();
void reload(const QString &);
void reload(QString *errorString, const QString &);
void setDisplayName(const QString &);
public slots:
......
......@@ -619,8 +619,10 @@ Core::IFile::ReloadBehavior GenericProjectFile::reloadBehavior(ChangeTrigger sta
return BehaviorSilent;
}
void GenericProjectFile::reload(ReloadFlag flag, ChangeType type)
bool GenericProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
{
Q_UNUSED(errorString)
Q_UNUSED(flag)
Q_UNUSED(type)
return true;
}
......@@ -172,7 +172,7 @@ public:
virtual void rename(const QString &newName);
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
void reload(ReloadFlag flag, ChangeType type);
bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
private:
GenericProject *m_project;
......
......@@ -205,10 +205,10 @@ QString GLSLEditorEditable::id() const
return QLatin1String(GLSLEditor::Constants::C_GLSLEDITOR_ID);
}
bool GLSLEditorEditable::open(const QString &fileName)
bool GLSLEditorEditable::open(QString *errorString, const QString &fileName)
{
editorWidget()->setMimeType(Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName)).type());
bool b = TextEditor::BaseTextEditor::open(fileName);
bool b = TextEditor::BaseTextEditor::open(errorString, fileName);
return b;
}
......
......@@ -51,7 +51,7 @@ public:
Core::IEditor *duplicate(QWidget *parent);
QString id() const;
bool isTemporary() const { return false; }
virtual bool open(const QString &fileName);
virtual bool open(QString *errorString, const QString &fileName);
virtual QString preferredModeType() const;
};
......
......@@ -45,6 +45,7 @@
#include <QtCore/QMap>
#include <QtCore/QFileInfo>
#include <QtCore/QDir>
#include <QtGui/QWidget>
#include <QtCore/QtDebug>
......@@ -116,10 +117,12 @@ bool ImageViewer::createNew(const QString &contents)
return false;
}
bool ImageViewer::open(const QString &fileName)
bool ImageViewer::open(QString *errorString, const QString &fileName)
{
if (!d_ptr->imageView->openFile(fileName))
if (!d_ptr->imageView->openFile(fileName)) {
*errorString = tr("Cannot open image file %1").arg(QDir::toNativeSeparators(fileName));
return false;
}
setDisplayName(QFileInfo(fileName).fileName());
d_ptr->file->setFileName(fileName);
// d_ptr->file->setMimeType
......
......@@ -56,7 +56,7 @@ public:
~ImageViewer();
bool createNew(const QString &contents = QString());
bool open(const QString &fileName = QString());
bool open(QString *errorString, const QString &fileName = QString());
Core::IFile *file();
QString id() const;
QString displayName() const;
......
......@@ -74,15 +74,17 @@ Core::IFile::ReloadBehavior ImageViewerFile::reloadBehavior(Core::IFile::ChangeT
return BehaviorAsk;
}
void ImageViewerFile::reload(Core::IFile::ReloadFlag flag,
bool ImageViewerFile::reload(QString *errorString,
Core::IFile::ReloadFlag flag,
Core::IFile::ChangeType type)
{
if (flag == FlagIgnore)
return;
return true;
if (type == TypePermissions) {
emit changed();
return true;
} else {
d_ptr->editor->open(d_ptr->fileName);
return d_ptr->editor->open(errorString, d_ptr->fileName);
}
}
......
......@@ -62,7 +62,7 @@ public:
bool isSaveAsAllowed() const;
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
void reload(ReloadFlag flag, ChangeType type);
bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
void setMimetype(const QString &mimetype);
void setFileName(const QString &filename);
......
......@@ -740,9 +740,9 @@ QString QmlJSEditorEditable::id() const
return QLatin1String(QmlJSEditor::Constants::C_QMLJSEDITOR_ID);
}
bool QmlJSEditorEditable::open(const QString &fileName)
bool QmlJSEditorEditable::open(QString *errorString, const QString &fileName)
{
bool b = TextEditor::BaseTextEditor::open(fileName);
bool b = TextEditor::BaseTextEditor::open(errorString, fileName);
editorWidget()->setMimeType(Core::ICore::instance()->mimeDatabase()->findByFile(QFileInfo(fileName)).type());
return b;
}
......
......@@ -50,7 +50,7 @@ public:
Core::IEditor *duplicate(QWidget *parent);
QString id() const;
bool isTemporary() const { return false; }
virtual bool open(const QString & fileName);
virtual bool open(QString *errorString, const QString & fileName);
virtual QString preferredModeType() const;
void setTextCodec(QTextCodec *codec, TextCodecReason = TextCodecOtherReason);
};
......
......@@ -100,10 +100,12 @@ Core::IFile::ReloadBehavior QmlProjectFile::reloadBehavior(ChangeTrigger state,
return BehaviorSilent;
}
void QmlProjectFile::reload(ReloadFlag flag, ChangeType type)
bool QmlProjectFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
{
Q_UNUSED(errorString)
Q_UNUSED(flag)
Q_UNUSED(type)
return true;
}
} // namespace Internal
......
......@@ -62,7 +62,7 @@ public:
virtual bool isSaveAsAllowed() const;
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
void reload(ReloadFlag flag, ChangeType type);
bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
private:
QmlProject *m_project;
......
......@@ -231,13 +231,14 @@ Core::IFile::ReloadBehavior Qt4PriFile::reloadBehavior(ChangeTrigger state, Chan
return BehaviorSilent;
}
void Qt4PriFile::reload(ReloadFlag flag, ChangeType type)
bool Qt4PriFile::reload(QString *errorString, ReloadFlag flag, ChangeType type)
{
Q_UNUSED(errorString)
Q_UNUSED(flag)
Q_UNUSED(type)
if (type == TypePermissions)
return;
return true;
m_priFile->scheduleUpdate();
return true;
}
/*!
......@@ -1130,11 +1131,17 @@ void Qt4PriFileNode::changeFiles(const FileType fileType,
// So the modification time might not change between those two saves.
// We manually tell each editor to reload it's file.
// (The .pro files are notified by the file system watcher.)
QStringList errorStrings;
foreach (Core::IEditor *editor, Core::ICore::instance()->editorManager()->editorsForFileName(m_projectFilePath)) {
if (Core::IFile *editorFile = editor->file()) {
editorFile->reload(Core::IFile::FlagReload, Core::IFile::TypeContents);
QString errorString;
if (!editorFile->reload(&errorString, Core::IFile::FlagReload, Core::IFile::TypeContents))
errorStrings << errorString;
}
}
if (!errorStrings.isEmpty())
QMessageBox::warning(Core::ICore::instance()->mainWindow(), tr("File Error"),
errorStrings.join(QLatin1String("\n")));
includeFile->deref();
}
......
......@@ -128,7 +128,7 @@ public:
virtual bool isSaveAsAllowed() const;
ReloadBehavior reloadBehavior(ChangeTrigger state, ChangeType type) const;
void reload(ReloadFlag flag, ChangeType type);
bool reload(QString *errorString, ReloadFlag flag, ChangeType type);
private: