Unhide buffers that are marked dirty as a result of external modifications

Several comments in the code point to the fact that hidden buffers are assumed
to be clean.

The other solution was to adapt the closing & saving code to take into account
hidden dirty buffers. Experience shows that it is more useful to unhide the
buffers at the moment of the external modification, in the context of a git
workflow where one has to reload the modified children buffers one-by-one.

Fixes crash at #10603
This commit is contained in:
Guillaume MM 2017-06-10 21:51:44 +02:00
parent fd6189b7e3
commit 5fda4e85c7
8 changed files with 42 additions and 7 deletions

View File

@ -380,7 +380,7 @@ public:
void refreshFileMonitor();
/// Notify or clear of external modification
void fileExternallyModified(bool exists) const;
void fileExternallyModified(bool exists);
/// has been externally modified? Can be reset by the user.
mutable bool externally_modified_;
@ -5332,7 +5332,7 @@ void Buffer::Impl::refreshFileMonitor()
}
void Buffer::Impl::fileExternallyModified(bool const exists) const
void Buffer::Impl::fileExternallyModified(bool const exists)
{
// ignore notifications after our own saving operations
if (checksum_ == filename.checksum()) {
@ -5346,8 +5346,13 @@ void Buffer::Impl::fileExternallyModified(bool const exists) const
// location, then the externally modified warning will appear then.
if (exists)
externally_modified_ = true;
if (wa_)
// Update external modification notification.
// Dirty buffers must be visible at all times.
if (wa_ && wa_->unhide(owner_))
wa_->updateTitles();
else
// Unable to unhide the buffer (e.g. no GUI or not current View)
lyx_clean = true;
}

View File

@ -251,6 +251,8 @@ public:
/// A started long operation is still in progress ?
virtual bool longOperationStarted() = 0;
// Add a buffer to the current view, do not switch to it.
virtual bool unhide(Buffer * buf) = 0;
};
/// Return the list of loadable formats.

View File

@ -13,6 +13,7 @@
#include "WorkAreaManager.h"
#include "Application.h"
#include "WorkArea.h"
@ -46,6 +47,14 @@ void WorkAreaManager::closeAll()
}
bool WorkAreaManager::unhide(Buffer * buf)
{
if (!work_areas_.empty())
return true;
return theApp()->unhide(buf);
}
void WorkAreaManager::updateTitles()
{
for (WorkArea * wa : work_areas_)

View File

@ -15,6 +15,9 @@
#include <list>
namespace lyx {
class Buffer;
namespace frontend {
class WorkArea;
@ -41,6 +44,9 @@ public:
/// Update window titles of all users and the external modifications
/// warning.
void updateTitles();
/// If there is no work area, create a new one in the current view using the
/// buffer buf. Returns false if not possible.
bool unhide(Buffer * buf);
private:
typedef std::list<WorkArea *>::iterator iterator;

View File

@ -2410,6 +2410,15 @@ void GuiApplication::createView(QString const & geometry_arg, bool autoShow,
}
bool GuiApplication::unhide(Buffer * buf)
{
if (!currentView())
return false;
currentView()->setBuffer(buf, false);
return true;
}
Clipboard & GuiApplication::clipboard()
{
return d->clipboard_;

View File

@ -77,6 +77,7 @@ public:
void unregisterSocketCallback(int fd);
bool searchMenu(FuncRequest const & func, docstring_list & names) const;
void handleKeyFunc(FuncCode action);
bool unhide(Buffer * buf); //override
//@}
///

View File

@ -1587,7 +1587,7 @@ void GuiView::updateToolbars()
}
void GuiView::setBuffer(Buffer * newBuffer)
void GuiView::setBuffer(Buffer * newBuffer, bool switch_to)
{
LYXERR(Debug::DEBUG, "Setting buffer: " << newBuffer << endl);
LASSERT(newBuffer, return);
@ -1610,7 +1610,8 @@ void GuiView::setBuffer(Buffer * newBuffer)
}
connectBuffer(*newBuffer);
connectBufferView(wa->bufferView());
setCurrentWorkArea(wa);
if (switch_to)
setCurrentWorkArea(wa);
}

View File

@ -130,8 +130,10 @@ public:
///
void focusInEvent(QFocusEvent * e);
/// set a buffer to the current workarea.
void setBuffer(Buffer * b); ///< \c Buffer to set.
/// Add a Buffer to the View
/// \param b Buffer to set.
/// \param switch_to Whether to set it to the current workarea.
void setBuffer(Buffer * b, bool switch_to = true);
/// load a document into the current workarea.
Buffer * loadDocument(