- fix: Crash when a project is removed from the disk while it is openned in RedPanda-C++.
This commit is contained in:
parent
56cd6c4d76
commit
b951ac6636
1
NEWS.md
1
NEWS.md
|
@ -2,6 +2,7 @@ Red Panda C++ Version 2.19
|
||||||
|
|
||||||
- fix: Crash when directive line ends with '\' and at the last line.
|
- fix: Crash when directive line ends with '\' and at the last line.
|
||||||
- fix: The option "Minimal indent for a continuous conditional beloning to a conditional header:" for formatter is not correct.
|
- fix: The option "Minimal indent for a continuous conditional beloning to a conditional header:" for formatter is not correct.
|
||||||
|
- fix: Crash when a project is removed from the disk while it is openned in RedPanda-C++.
|
||||||
|
|
||||||
Red Panda C++ Version 2.18
|
Red Panda C++ Version 2.18
|
||||||
|
|
||||||
|
|
|
@ -1430,10 +1430,11 @@ void Editor::hideEvent(QHideEvent */*event*/)
|
||||||
this,
|
this,
|
||||||
&Editor::onEndParsing);
|
&Editor::onEndParsing);
|
||||||
}
|
}
|
||||||
pMainWindow->updateForEncodingInfo(nullptr);
|
if (!pMainWindow->isQuitting()) {
|
||||||
pMainWindow->updateStatusbarForLineCol(nullptr);
|
pMainWindow->updateForEncodingInfo(nullptr);
|
||||||
pMainWindow->updateForStatusbarModeInfo(nullptr);
|
pMainWindow->updateStatusbarForLineCol(nullptr);
|
||||||
|
pMainWindow->updateForStatusbarModeInfo(nullptr);
|
||||||
|
}
|
||||||
setHideTime(QDateTime::currentDateTime());
|
setHideTime(QDateTime::currentDateTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,8 +185,12 @@ bool EditorList::closeEditor(Editor* editor, bool transferFocus, bool force) {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (editor->inProject() && pMainWindow->project()) {
|
if (editor->inProject() && pMainWindow->project()) {
|
||||||
PProjectUnit unit = pMainWindow->project()->findUnit(editor);
|
if (fileExists(pMainWindow->project()->directory())) {
|
||||||
pMainWindow->project()->closeUnit(unit);
|
PProjectUnit unit = pMainWindow->project()->findUnit(editor);
|
||||||
|
pMainWindow->project()->closeUnit(unit);
|
||||||
|
} else {
|
||||||
|
editor->setProject(nullptr);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!editor->isNew() && pMainWindow->visitHistoryManager()->addFile(editor->filename())) {
|
if (!editor->isNew() && pMainWindow->visitHistoryManager()->addFile(editor->filename())) {
|
||||||
pMainWindow->rebuildOpenedFileHisotryMenu();
|
pMainWindow->rebuildOpenedFileHisotryMenu();
|
||||||
|
|
|
@ -402,6 +402,8 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
|
|
||||||
connect(&mFileSystemWatcher,&QFileSystemWatcher::fileChanged,
|
connect(&mFileSystemWatcher,&QFileSystemWatcher::fileChanged,
|
||||||
this, &MainWindow::onFileChanged);
|
this, &MainWindow::onFileChanged);
|
||||||
|
connect(&mFileSystemWatcher,&QFileSystemWatcher::directoryChanged,
|
||||||
|
this, &MainWindow::onDirChanged);
|
||||||
|
|
||||||
mStatementColors = std::make_shared<QHash<StatementKind, PColorSchemeItem> >();
|
mStatementColors = std::make_shared<QHash<StatementKind, PColorSchemeItem> >();
|
||||||
mCompletionPopup = std::make_shared<CodeCompletionPopup>();
|
mCompletionPopup = std::make_shared<CodeCompletionPopup>();
|
||||||
|
@ -463,6 +465,8 @@ MainWindow::MainWindow(QWidget *parent)
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
mQuitting=true;
|
mQuitting=true;
|
||||||
|
if (mProject)
|
||||||
|
mProject=nullptr;
|
||||||
delete mProjectProxyModel;
|
delete mProjectProxyModel;
|
||||||
delete mEditorList;
|
delete mEditorList;
|
||||||
delete ui;
|
delete ui;
|
||||||
|
@ -5106,51 +5110,56 @@ void MainWindow::closeProject(bool refreshEditor)
|
||||||
//save all files
|
//save all files
|
||||||
|
|
||||||
// TODO: should we save watches?
|
// TODO: should we save watches?
|
||||||
if (mEditorList->projectEditorsModified()) {
|
if (fileExists(mProject->directory())){
|
||||||
QString s;
|
if (mEditorList->projectEditorsModified()) {
|
||||||
if (mProject->name().isEmpty()) {
|
QString s;
|
||||||
s = mProject->filename();
|
if (mProject->name().isEmpty()) {
|
||||||
} else {
|
s = mProject->filename();
|
||||||
s = mProject->name();
|
} else {
|
||||||
}
|
s = mProject->name();
|
||||||
if (mSystemTurnedOff) {
|
}
|
||||||
mProject->saveAll();
|
if (mSystemTurnedOff) {
|
||||||
mEditorList->saveAllForProject();
|
|
||||||
} else {
|
|
||||||
int answer = QMessageBox::question(
|
|
||||||
this,
|
|
||||||
tr("Save project"),
|
|
||||||
tr("The project '%1' has modifications.").arg(s)
|
|
||||||
+ "<br />"
|
|
||||||
+ tr("Do you want to save it?"),
|
|
||||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
|
|
||||||
QMessageBox::Yes);
|
|
||||||
switch (answer) {
|
|
||||||
case QMessageBox::Yes:
|
|
||||||
mProject->saveAll();
|
mProject->saveAll();
|
||||||
mEditorList->saveAllForProject();
|
mEditorList->saveAllForProject();
|
||||||
break;
|
} else {
|
||||||
case QMessageBox::No:
|
int answer = QMessageBox::question(
|
||||||
mEditorList->clearProjectEditorsModified();
|
this,
|
||||||
mProject->setModified(false);
|
tr("Save project"),
|
||||||
mProject->saveLayout();
|
tr("The project '%1' has modifications.").arg(s)
|
||||||
break;
|
+ "<br />"
|
||||||
case QMessageBox::Cancel:
|
+ tr("Do you want to save it?"),
|
||||||
mProject->saveLayout();
|
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
|
||||||
return;
|
QMessageBox::Yes);
|
||||||
|
switch (answer) {
|
||||||
|
case QMessageBox::Yes:
|
||||||
|
mProject->saveAll();
|
||||||
|
mEditorList->saveAllForProject();
|
||||||
|
break;
|
||||||
|
case QMessageBox::No:
|
||||||
|
mEditorList->clearProjectEditorsModified();
|
||||||
|
mProject->setModified(false);
|
||||||
|
mProject->saveLayout();
|
||||||
|
break;
|
||||||
|
case QMessageBox::Cancel:
|
||||||
|
mProject->saveLayout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
} else
|
mProject->saveAll(); // always save layout, but not when SaveAll has been called
|
||||||
mProject->saveAll(); // always save layout, but not when SaveAll has been called
|
}
|
||||||
|
|
||||||
mClosingProject=true;
|
mClosingProject=true;
|
||||||
mBookmarkModel->saveProjectBookmarks(
|
|
||||||
changeFileExt(mProject->filename(), PROJECT_BOOKMARKS_EXT),
|
|
||||||
mProject->directory());
|
|
||||||
|
|
||||||
mDebugger->saveForProject(
|
if (fileExists(mProject->directory())){
|
||||||
changeFileExt(mProject->filename(), PROJECT_DEBUG_EXT),
|
mBookmarkModel->saveProjectBookmarks(
|
||||||
mProject->directory());
|
changeFileExt(mProject->filename(), PROJECT_BOOKMARKS_EXT),
|
||||||
|
mProject->directory());
|
||||||
|
|
||||||
|
mDebugger->saveForProject(
|
||||||
|
changeFileExt(mProject->filename(), PROJECT_DEBUG_EXT),
|
||||||
|
mProject->directory());
|
||||||
|
}
|
||||||
|
|
||||||
mClassBrowserModel.beginUpdate();
|
mClassBrowserModel.beginUpdate();
|
||||||
// Remember it
|
// Remember it
|
||||||
|
@ -5251,6 +5260,22 @@ void MainWindow::onFileChanged(const QString &path)
|
||||||
mFilesChangedNotifying.remove(path);
|
mFilesChangedNotifying.remove(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onDirChanged(const QString &path)
|
||||||
|
{
|
||||||
|
if (mFilesChangedNotifying.contains(path))
|
||||||
|
return;
|
||||||
|
mFilesChangedNotifying.insert(path);
|
||||||
|
if (mProject && QString::compare(mProject->directory(),path,PATH_SENSITIVITY)==0
|
||||||
|
&& !fileExists(path)) {
|
||||||
|
QMessageBox::information(this,tr("Project folder removed."),
|
||||||
|
tr("Folder for project '%1' was removed.").arg(path)
|
||||||
|
+"<BR /><BR />"
|
||||||
|
+ tr("It will be closed."));
|
||||||
|
closeProject(false);
|
||||||
|
}
|
||||||
|
mFilesChangedNotifying.remove(path);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::onFilesViewPathChanged()
|
void MainWindow::onFilesViewPathChanged()
|
||||||
{
|
{
|
||||||
QString filesPath = ui->cbFilesPath->currentText();
|
QString filesPath = ui->cbFilesPath->currentText();
|
||||||
|
|
|
@ -340,6 +340,7 @@ private slots:
|
||||||
void onEditorRenamed(const QString &oldFilename, const QString &newFilename, bool firstSave);
|
void onEditorRenamed(const QString &oldFilename, const QString &newFilename, bool firstSave);
|
||||||
void onAutoSaveTimeout();
|
void onAutoSaveTimeout();
|
||||||
void onFileChanged(const QString &path);
|
void onFileChanged(const QString &path);
|
||||||
|
void onDirChanged(const QString &path);
|
||||||
void onFilesViewPathChanged();
|
void onFilesViewPathChanged();
|
||||||
void onWatchViewContextMenu(const QPoint& pos);
|
void onWatchViewContextMenu(const QPoint& pos);
|
||||||
void onBookmarkContextMenu(const QPoint& pos);
|
void onBookmarkContextMenu(const QPoint& pos);
|
||||||
|
|
|
@ -61,6 +61,7 @@ Project::Project(const QString &filename, const QString &name,
|
||||||
std::bind(
|
std::bind(
|
||||||
&EditorList::getContentFromOpenedEditor,mEditorList,
|
&EditorList::getContentFromOpenedEditor,mEditorList,
|
||||||
std::placeholders::_1, std::placeholders::_2));
|
std::placeholders::_1, std::placeholders::_2));
|
||||||
|
mFileSystemWatcher->addPath(directory());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Project> Project::load(const QString &filename, EditorList *editorList, QFileSystemWatcher *fileSystemWatcher, QObject *parent)
|
std::shared_ptr<Project> Project::load(const QString &filename, EditorList *editorList, QFileSystemWatcher *fileSystemWatcher, QObject *parent)
|
||||||
|
@ -103,12 +104,14 @@ std::shared_ptr<Project> Project::create(
|
||||||
|
|
||||||
Project::~Project()
|
Project::~Project()
|
||||||
{
|
{
|
||||||
|
mFileSystemWatcher->removePath(directory());
|
||||||
mEditorList->beginUpdate();
|
mEditorList->beginUpdate();
|
||||||
foreach (const PProjectUnit& unit, mUnits) {
|
foreach (const PProjectUnit& unit, mUnits) {
|
||||||
Editor * editor = unitEditor(unit);
|
Editor * editor = unitEditor(unit);
|
||||||
if (editor) {
|
if (editor) {
|
||||||
editor->setProject(nullptr);
|
editor->setProject(nullptr);
|
||||||
mEditorList->forceCloseEditor(editor);
|
if (fileExists(directory()))
|
||||||
|
mEditorList->forceCloseEditor(editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mEditorList->endUpdate();
|
mEditorList->endUpdate();
|
||||||
|
@ -259,15 +262,15 @@ void Project::open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Project::setFileName(QString value)
|
//void Project::setFileName(QString value)
|
||||||
{
|
//{
|
||||||
value = QFileInfo(value).absoluteFilePath();
|
// value = QFileInfo(value).absoluteFilePath();
|
||||||
if (mFilename!=value) {
|
// if (mFilename!=value) {
|
||||||
QFile::rename(mFilename,value);
|
// QFile::rename(mFilename,value);
|
||||||
mFilename = value;
|
// mFilename = value;
|
||||||
setModified(true);
|
// setModified(true);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
void Project::setModified(bool value)
|
void Project::setModified(bool value)
|
||||||
{
|
{
|
||||||
|
@ -611,6 +614,9 @@ void Project::saveAll()
|
||||||
|
|
||||||
void Project::saveLayout()
|
void Project::saveLayout()
|
||||||
{
|
{
|
||||||
|
if (!fileExists(directory()))
|
||||||
|
return;
|
||||||
|
|
||||||
QHash<QString, PProjectEditorLayout> oldLayouts = loadLayout();
|
QHash<QString, PProjectEditorLayout> oldLayouts = loadLayout();
|
||||||
|
|
||||||
QHash<QString,int> editorOrderSet;
|
QHash<QString,int> editorOrderSet;
|
||||||
|
@ -669,9 +675,6 @@ void Project::saveLayout()
|
||||||
QJsonDocument doc(jsonLayouts);
|
QJsonDocument doc(jsonLayouts);
|
||||||
file.write(doc.toJson(QJsonDocument::Indented));
|
file.write(doc.toJson(QJsonDocument::Indented));
|
||||||
file.close();
|
file.close();
|
||||||
} else {
|
|
||||||
throw FileError(QObject::tr("Can't open file '%1' for write.")
|
|
||||||
.arg(jsonFilename));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,6 +714,8 @@ void Project::renameUnit(PProjectUnit& unit, const QString &newFileName)
|
||||||
|
|
||||||
bool Project::saveUnits()
|
bool Project::saveUnits()
|
||||||
{
|
{
|
||||||
|
if (!fileExists(directory()))
|
||||||
|
return false;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
SimpleIni ini;
|
SimpleIni ini;
|
||||||
SI_Error error = ini.LoadFile(mFilename.toLocal8Bit());
|
SI_Error error = ini.LoadFile(mFilename.toLocal8Bit());
|
||||||
|
@ -1140,6 +1145,8 @@ void Project::setEncoding(const QByteArray &encoding)
|
||||||
|
|
||||||
void Project::saveOptions()
|
void Project::saveOptions()
|
||||||
{
|
{
|
||||||
|
if (!fileExists(directory()))
|
||||||
|
return;
|
||||||
SimpleIni ini;
|
SimpleIni ini;
|
||||||
ini.LoadFile(mFilename.toLocal8Bit());
|
ini.LoadFile(mFilename.toLocal8Bit());
|
||||||
ini.SetValue("Project","FileName", toByteArray(extractRelativePath(directory(), mFilename)));
|
ini.SetValue("Project","FileName", toByteArray(extractRelativePath(directory(), mFilename)));
|
||||||
|
|
|
@ -218,7 +218,7 @@ public:
|
||||||
bool unitsModifiedSince(const QDateTime& time);
|
bool unitsModifiedSince(const QDateTime& time);
|
||||||
bool modified() const;
|
bool modified() const;
|
||||||
bool modifiedSince(const QDateTime& time);
|
bool modifiedSince(const QDateTime& time);
|
||||||
void setFileName(QString value);
|
// void setFileName(QString value);
|
||||||
void setModified(bool value);
|
void setModified(bool value);
|
||||||
|
|
||||||
PProjectModelNode addFolder(PProjectModelNode parentFolder, const QString& s);
|
PProjectModelNode addFolder(PProjectModelNode parentFolder, const QString& s);
|
||||||
|
|
|
@ -5187,6 +5187,18 @@
|
||||||
<source>Save settings failed!</source>
|
<source>Save settings failed!</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Project folder removed.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Folder for project '%1' was removed.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>It will be closed.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MemoryModel</name>
|
<name>MemoryModel</name>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -4920,6 +4920,18 @@
|
||||||
<source>F11</source>
|
<source>F11</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Project folder removed.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Folder for project '%1' was removed.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>It will be closed.</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>MemoryModel</name>
|
<name>MemoryModel</name>
|
||||||
|
|
Loading…
Reference in New Issue