From f967b58e872614458ce613199415b986c4a738e1 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Tue, 12 May 2015 15:18:26 +0200 Subject: [PATCH] EditorManager: Warn before opening big text files ...since these might lead to out of memory situations and thus to crashes. The warning and the file size limited is configurable in Environment > General. Task-number: QTCREATORBUG-14390 Change-Id: I868ceca0bee5551ed55f0df990ed334a8b539a7d Reviewed-by: David Schulz Reviewed-by: Eike Ziller --- .../editormanager/editormanager.cpp | 85 ++++++++++++++++++- .../editormanager/editormanager_p.h | 8 ++ src/plugins/coreplugin/generalsettings.cpp | 17 +++- src/plugins/coreplugin/generalsettings.h | 1 + src/plugins/coreplugin/generalsettings.ui | 69 +++++++++++++-- 5 files changed, 172 insertions(+), 8 deletions(-) diff --git a/src/plugins/coreplugin/editormanager/editormanager.cpp b/src/plugins/coreplugin/editormanager/editormanager.cpp index dfeb50aa129..27ec33a8330 100644 --- a/src/plugins/coreplugin/editormanager/editormanager.cpp +++ b/src/plugins/coreplugin/editormanager/editormanager.cpp @@ -65,6 +65,7 @@ #include #include +#include #include #include #include @@ -107,6 +108,8 @@ static const char documentStatesKey[] = "EditorManager/DocumentStates"; static const char reloadBehaviorKey[] = "EditorManager/ReloadBehavior"; static const char autoSaveEnabledKey[] = "EditorManager/AutoSaveEnabled"; static const char autoSaveIntervalKey[] = "EditorManager/AutoSaveInterval"; +static const char warnBeforeOpeningBigTextFilesKey[] = "EditorManager/WarnBeforeOpeningBigTextFiles"; +static const char bigTextFileSizeLimitKey[] = "EditorManager/BigTextFileSizeLimitInMB"; static const char scratchBufferKey[] = "_q_emScratchBuffer"; @@ -280,7 +283,9 @@ EditorManagerPrivate::EditorManagerPrivate(QObject *parent) : m_coreListener(0), m_reloadSetting(IDocument::AlwaysAsk), m_autoSaveEnabled(true), - m_autoSaveInterval(5) + m_autoSaveInterval(5), + m_warnBeforeOpeningBigFilesEnabled(true), + m_bigFileSizeLimitInMB(5) { d = this; } @@ -544,6 +549,47 @@ EditorArea *EditorManagerPrivate::mainEditorArea() return d->m_editorAreas.at(0); } +bool EditorManagerPrivate::skipOpeningBigTextFile(const QString &filePath) +{ + if (!d->m_warnBeforeOpeningBigFilesEnabled) + return false; + + const QFileInfo fileInfo(filePath); + if (!fileInfo.exists(filePath)) + return false; + + Utils::MimeDatabase mdb; + Utils::MimeType mimeType = mdb.mimeTypeForFile(filePath); + if (!mimeType.inherits(QLatin1String("text/plain"))) + return false; + + const double fileSizeInMB = fileInfo.size() / 1000.0 / 1000.0; + if (fileSizeInMB > d->m_bigFileSizeLimitInMB) { + const QString title = EditorManager::tr("Continue Opening Huge Text File?"); + const QString text = EditorManager::tr( + "The text file \"%1\" has the size %2MB and might take more memory to open" + " and process than available.\n" + "\n" + "Continue?") + .arg(fileInfo.fileName()) + .arg(fileSizeInMB, 0, 'f', 2); + + CheckableMessageBox messageBox(ICore::mainWindow()); + messageBox.setWindowTitle(title); + messageBox.setText(text); + messageBox.setStandardButtons(QDialogButtonBox::Yes|QDialogButtonBox::No); + messageBox.setDefaultButton(QDialogButtonBox::No); + messageBox.setIconPixmap(QMessageBox::standardIcon(QMessageBox::Question)); + messageBox.setCheckBoxVisible(true); + messageBox.setCheckBoxText(CheckableMessageBox::msgDoNotAskAgain()); + messageBox.exec(); + d->setWarnBeforeOpeningBigFilesEnabled(!messageBox.isChecked()); + return messageBox.clickedStandardButton() != QDialogButtonBox::Yes; + } + + return false; +} + IEditor *EditorManagerPrivate::openEditor(EditorView *view, const QString &fileName, Id editorId, EditorManager::OpenEditorFlags flags, bool *newEditor) { @@ -960,6 +1006,11 @@ void EditorManagerPrivate::saveSettings() settings->setValue(QLatin1String(autoSaveEnabledKey), d->m_autoSaveEnabled); settings->setValue(QLatin1String(autoSaveIntervalKey), d->m_autoSaveInterval); settings->endTransaction(); + + QSettings *qsettings = ICore::settings(); + qsettings->setValue(QLatin1String(warnBeforeOpeningBigTextFilesKey), + d->m_warnBeforeOpeningBigFilesEnabled); + qsettings->setValue(QLatin1String(bigTextFileSizeLimitKey), d->m_bigFileSizeLimitInMB); } void EditorManagerPrivate::readSettings() @@ -973,6 +1024,12 @@ void EditorManagerPrivate::readSettings() qs->remove(QLatin1String(documentStatesKey)); } + if (qs->contains(QLatin1String(warnBeforeOpeningBigTextFilesKey))) { + d->m_warnBeforeOpeningBigFilesEnabled + = qs->value(QLatin1String(warnBeforeOpeningBigTextFilesKey)).toBool(); + d->m_bigFileSizeLimitInMB = qs->value(QLatin1String(bigTextFileSizeLimitKey)).toInt(); + } + SettingsDatabase *settings = ICore::settingsDatabase(); if (settings->contains(QLatin1String(documentStatesKey))) d->m_editorStates = settings->value(QLatin1String(documentStatesKey)) @@ -1010,6 +1067,26 @@ int EditorManagerPrivate::autoSaveInterval() return d->m_autoSaveInterval; } +bool EditorManagerPrivate::warnBeforeOpeningBigFilesEnabled() +{ + return d->m_warnBeforeOpeningBigFilesEnabled; +} + +void EditorManagerPrivate::setWarnBeforeOpeningBigFilesEnabled(bool enabled) +{ + d->m_warnBeforeOpeningBigFilesEnabled = enabled; +} + +int EditorManagerPrivate::bigFileSizeLimit() +{ + return d->m_bigFileSizeLimitInMB; +} + +void EditorManagerPrivate::setBigFileSizeLimit(int limitInMB) +{ + d->m_bigFileSizeLimitInMB = limitInMB; +} + EditorManager::EditorFactoryList EditorManagerPrivate::findFactories(Id editorId, const QString &fileName) { if (debugEditorManager) @@ -2451,6 +2528,9 @@ EditorManager::ExternalEditorList IEditor *EditorManager::openEditor(const QString &fileName, Id editorId, OpenEditorFlags flags, bool *newEditor) { + if (EditorManagerPrivate::skipOpeningBigTextFile(fileName)) + return 0; + if (flags & EditorManager::OpenInOtherSplit) EditorManager::gotoOtherSplit(); @@ -2461,6 +2541,9 @@ IEditor *EditorManager::openEditor(const QString &fileName, Id editorId, IEditor *EditorManager::openEditorAt(const QString &fileName, int line, int column, Id editorId, OpenEditorFlags flags, bool *newEditor) { + if (EditorManagerPrivate::skipOpeningBigTextFile(fileName)) + return 0; + if (flags & EditorManager::OpenInOtherSplit) EditorManager::gotoOtherSplit(); diff --git a/src/plugins/coreplugin/editormanager/editormanager_p.h b/src/plugins/coreplugin/editormanager/editormanager_p.h index ea838af285e..217459e445b 100644 --- a/src/plugins/coreplugin/editormanager/editormanager_p.h +++ b/src/plugins/coreplugin/editormanager/editormanager_p.h @@ -111,6 +111,10 @@ public: static bool autoSaveEnabled(); static void setAutoSaveInterval(int interval); static int autoSaveInterval(); + static void setWarnBeforeOpeningBigFilesEnabled(bool enabled); + static bool warnBeforeOpeningBigFilesEnabled(); + static void setBigFileSizeLimit(int limitInMB); + static int bigFileSizeLimit(); static void splitNewWindow(Internal::EditorView *view); static void closeView(Internal::EditorView *view); @@ -188,6 +192,7 @@ private: static void setupSaveActions(IDocument *document, QAction *saveAction, QAction *saveAsAction, QAction *revertToSavedAction); static void updateWindowTitle(); + static bool skipOpeningBigTextFile(const QString &filePath); private: explicit EditorManagerPrivate(QObject *parent); @@ -251,6 +256,9 @@ private: bool m_autoSaveEnabled; int m_autoSaveInterval; + bool m_warnBeforeOpeningBigFilesEnabled; + int m_bigFileSizeLimitInMB; + QString m_placeholderText; }; diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp index f2eb8d1a50a..8d37808fc7d 100644 --- a/src/plugins/coreplugin/generalsettings.cpp +++ b/src/plugins/coreplugin/generalsettings.cpp @@ -144,8 +144,10 @@ QWidget *GeneralSettings::widget() m_page->patchChooser->setPath(PatchTool::patchCommand()); m_page->autoSaveCheckBox->setChecked(EditorManagerPrivate::autoSaveEnabled()); m_page->autoSaveInterval->setValue(EditorManagerPrivate::autoSaveInterval()); - m_page->resetWarningsButton->setEnabled(InfoBar::anyGloballySuppressed() - || CheckableMessageBox::hasSuppressedQuestions(ICore::settings())); + m_page->warnBeforeOpeningBigFiles->setChecked( + EditorManagerPrivate::warnBeforeOpeningBigFilesEnabled()); + m_page->bigFilesLimitSpinBox->setValue(EditorManagerPrivate::bigFileSizeLimit()); + m_page->resetWarningsButton->setEnabled(canResetWarnings()); connect(m_page->resetColorButton, SIGNAL(clicked()), this, SLOT(resetInterfaceColor())); @@ -188,6 +190,9 @@ void GeneralSettings::apply() PatchTool::setPatchCommand(m_page->patchChooser->path()); EditorManagerPrivate::setAutoSaveEnabled(m_page->autoSaveCheckBox->isChecked()); EditorManagerPrivate::setAutoSaveInterval(m_page->autoSaveInterval->value()); + EditorManagerPrivate::setWarnBeforeOpeningBigFilesEnabled( + m_page->warnBeforeOpeningBigFiles->isChecked()); + EditorManagerPrivate::setBigFileSizeLimit(m_page->bigFilesLimitSpinBox->value()); m_page->themeWidget->apply(); } @@ -207,6 +212,7 @@ void GeneralSettings::resetWarnings() { InfoBar::clearGloballySuppressed(); CheckableMessageBox::resetAllDoNotAskAgainQuestions(ICore::settings()); + m_page->warnBeforeOpeningBigFiles->setChecked(true); m_page->resetWarningsButton->setEnabled(false); } @@ -230,6 +236,13 @@ void GeneralSettings::updatePath() m_page->patchChooser->setEnvironment(env); } +bool GeneralSettings::canResetWarnings() const +{ + return InfoBar::anyGloballySuppressed() + || CheckableMessageBox::hasSuppressedQuestions(ICore::settings()) + || !EditorManagerPrivate::warnBeforeOpeningBigFilesEnabled(); +} + void GeneralSettings::variableHelpDialogCreator(const QString &helpText) { if (m_dialog) { diff --git a/src/plugins/coreplugin/generalsettings.h b/src/plugins/coreplugin/generalsettings.h index d315bbdccc0..1ac4f456d2e 100644 --- a/src/plugins/coreplugin/generalsettings.h +++ b/src/plugins/coreplugin/generalsettings.h @@ -64,6 +64,7 @@ private slots: void updatePath(); private: + bool canResetWarnings() const; void variableHelpDialogCreator(const QString &helpText); void fillLanguageBox() const; QString language() const; diff --git a/src/plugins/coreplugin/generalsettings.ui b/src/plugins/coreplugin/generalsettings.ui index 3b333580175..d7fabd91600 100644 --- a/src/plugins/coreplugin/generalsettings.ui +++ b/src/plugins/coreplugin/generalsettings.ui @@ -7,7 +7,7 @@ 0 0 527 - 359 + 366 @@ -310,6 +310,49 @@ + + + + + + Warn before opening text files greater than + + + true + + + + + + + MB + + + 1 + + + 500 + + + 5 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + @@ -362,12 +405,28 @@ setEnabled(bool) - 161 - 262 + 181 + 310 - 342 - 263 + 340 + 311 + + + + + warnBeforeOpeningBigFiles + toggled(bool) + bigFilesLimitSpinBox + setEnabled(bool) + + + 124 + 330 + + + 305 + 332