Merge branch 'macos-dvc-isdeleting'
Fix crash in wxDataViewModel::Cleared() under Mac. See #22025.
This commit is contained in:
@@ -259,11 +259,6 @@ public:
|
|||||||
{
|
{
|
||||||
m_CustomRendererPtr = NewCustomRendererPtr;
|
m_CustomRendererPtr = NewCustomRendererPtr;
|
||||||
}
|
}
|
||||||
// sets the flag indicating a deletion process:
|
|
||||||
void SetDeleting(bool deleting)
|
|
||||||
{
|
|
||||||
m_Deleting = deleting;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdjustAutosizedColumns() const;
|
void AdjustAutosizedColumns() const;
|
||||||
|
|
||||||
@@ -305,6 +300,9 @@ private:
|
|||||||
// after the actual deletion of the item; then, native callback functions/delegates may try to update data of variables that are already deleted;
|
// after the actual deletion of the item; then, native callback functions/delegates may try to update data of variables that are already deleted;
|
||||||
// if this flag is set all native variable update requests will be ignored
|
// if this flag is set all native variable update requests will be ignored
|
||||||
|
|
||||||
|
// This class can set (and reset) m_Deleting.
|
||||||
|
friend class wxOSXDVCScopedDeleter;
|
||||||
|
|
||||||
void* m_cgContext; // pointer to core graphics context
|
void* m_cgContext; // pointer to core graphics context
|
||||||
|
|
||||||
wxDataViewCustomRenderer* m_CustomRendererPtr; // pointer to a valid custom renderer while editing; this class does NOT own the pointer
|
wxDataViewCustomRenderer* m_CustomRendererPtr; // pointer to a valid custom renderer while editing; this class does NOT own the pointer
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ private:
|
|||||||
#endif // wxHAS_GENERIC_DATAVIEWCTRL
|
#endif // wxHAS_GENERIC_DATAVIEWCTRL
|
||||||
void OnGetPageInfo(wxCommandEvent& event);
|
void OnGetPageInfo(wxCommandEvent& event);
|
||||||
void OnDisable(wxCommandEvent& event);
|
void OnDisable(wxCommandEvent& event);
|
||||||
|
void OnClearMyMusicTreeModel(wxCommandEvent& event);
|
||||||
void OnSetForegroundColour(wxCommandEvent& event);
|
void OnSetForegroundColour(wxCommandEvent& event);
|
||||||
void OnIncIndent(wxCommandEvent& event);
|
void OnIncIndent(wxCommandEvent& event);
|
||||||
void OnDecIndent(wxCommandEvent& event);
|
void OnDecIndent(wxCommandEvent& event);
|
||||||
@@ -398,6 +399,7 @@ enum
|
|||||||
ID_CLEARLOG = wxID_HIGHEST+1,
|
ID_CLEARLOG = wxID_HIGHEST+1,
|
||||||
ID_GET_PAGE_INFO,
|
ID_GET_PAGE_INFO,
|
||||||
ID_DISABLE,
|
ID_DISABLE,
|
||||||
|
ID_CLEAR_MODEL,
|
||||||
ID_BACKGROUND_COLOUR,
|
ID_BACKGROUND_COLOUR,
|
||||||
ID_FOREGROUND_COLOUR,
|
ID_FOREGROUND_COLOUR,
|
||||||
ID_CUSTOM_HEADER_ATTR,
|
ID_CUSTOM_HEADER_ATTR,
|
||||||
@@ -479,6 +481,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||||||
|
|
||||||
EVT_MENU( ID_GET_PAGE_INFO, MyFrame::OnGetPageInfo )
|
EVT_MENU( ID_GET_PAGE_INFO, MyFrame::OnGetPageInfo )
|
||||||
EVT_MENU( ID_DISABLE, MyFrame::OnDisable )
|
EVT_MENU( ID_DISABLE, MyFrame::OnDisable )
|
||||||
|
EVT_MENU( ID_CLEAR_MODEL, MyFrame::OnClearMyMusicTreeModel )
|
||||||
EVT_MENU( ID_FOREGROUND_COLOUR, MyFrame::OnSetForegroundColour )
|
EVT_MENU( ID_FOREGROUND_COLOUR, MyFrame::OnSetForegroundColour )
|
||||||
EVT_MENU( ID_BACKGROUND_COLOUR, MyFrame::OnSetBackgroundColour )
|
EVT_MENU( ID_BACKGROUND_COLOUR, MyFrame::OnSetBackgroundColour )
|
||||||
EVT_MENU( ID_CUSTOM_HEADER_ATTR, MyFrame::OnCustomHeaderAttr )
|
EVT_MENU( ID_CUSTOM_HEADER_ATTR, MyFrame::OnCustomHeaderAttr )
|
||||||
@@ -597,6 +600,7 @@ MyFrame::MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int
|
|||||||
file_menu->Append(ID_CLEARLOG, "&Clear log\tCtrl-L");
|
file_menu->Append(ID_CLEARLOG, "&Clear log\tCtrl-L");
|
||||||
file_menu->Append(ID_GET_PAGE_INFO, "Show current &page info");
|
file_menu->Append(ID_GET_PAGE_INFO, "Show current &page info");
|
||||||
file_menu->AppendCheckItem(ID_DISABLE, "&Disable\tCtrl-D");
|
file_menu->AppendCheckItem(ID_DISABLE, "&Disable\tCtrl-D");
|
||||||
|
file_menu->Append(ID_CLEAR_MODEL, "&Clear MyMusicTreeModel\tCtrl-W");
|
||||||
file_menu->Append(ID_FOREGROUND_COLOUR, "Set &foreground colour...\tCtrl-S");
|
file_menu->Append(ID_FOREGROUND_COLOUR, "Set &foreground colour...\tCtrl-S");
|
||||||
file_menu->Append(ID_BACKGROUND_COLOUR, "Set &background colour...\tCtrl-B");
|
file_menu->Append(ID_BACKGROUND_COLOUR, "Set &background colour...\tCtrl-B");
|
||||||
file_menu->AppendCheckItem(ID_CUSTOM_HEADER_ATTR, "C&ustom header attributes");
|
file_menu->AppendCheckItem(ID_CUSTOM_HEADER_ATTR, "C&ustom header attributes");
|
||||||
@@ -1144,6 +1148,11 @@ void MyFrame::OnDisable(wxCommandEvent& event)
|
|||||||
m_ctrl[m_notebook->GetSelection()]->Enable(!event.IsChecked());
|
m_ctrl[m_notebook->GetSelection()]->Enable(!event.IsChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyFrame::OnClearMyMusicTreeModel(wxCommandEvent& WXUNUSED(event))
|
||||||
|
{
|
||||||
|
m_music_model->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
void MyFrame::OnSetForegroundColour(wxCommandEvent& WXUNUSED(event))
|
void MyFrame::OnSetForegroundColour(wxCommandEvent& WXUNUSED(event))
|
||||||
{
|
{
|
||||||
wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
|
wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
|
||||||
|
|||||||
@@ -145,6 +145,21 @@ void MyMusicTreeModel::Delete( const wxDataViewItem &item )
|
|||||||
// notify control
|
// notify control
|
||||||
ItemDeleted( parent, item );
|
ItemDeleted( parent, item );
|
||||||
}
|
}
|
||||||
|
void MyMusicTreeModel::Clear()
|
||||||
|
{
|
||||||
|
m_pop = NULL;
|
||||||
|
m_classical = NULL;
|
||||||
|
m_ninth = NULL;
|
||||||
|
|
||||||
|
while (!m_root->GetChildren().IsEmpty())
|
||||||
|
{
|
||||||
|
MyMusicTreeModelNode* node = m_root->GetNthChild(0);
|
||||||
|
m_root->GetChildren().Remove(node);
|
||||||
|
delete node;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cleared();
|
||||||
|
}
|
||||||
|
|
||||||
int MyMusicTreeModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
|
int MyMusicTreeModel::Compare( const wxDataViewItem &item1, const wxDataViewItem &item2,
|
||||||
unsigned int column, bool ascending ) const
|
unsigned int column, bool ascending ) const
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ public:
|
|||||||
void AddToClassical( const wxString &title, const wxString &artist,
|
void AddToClassical( const wxString &title, const wxString &artist,
|
||||||
unsigned int year );
|
unsigned int year );
|
||||||
void Delete( const wxDataViewItem &item );
|
void Delete( const wxDataViewItem &item );
|
||||||
|
void Clear();
|
||||||
|
|
||||||
wxDataViewItem GetNinthItem() const
|
wxDataViewItem GetNinthItem() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -551,6 +551,11 @@ outlineView:(NSOutlineView*)outlineView
|
|||||||
{
|
{
|
||||||
wxUnusedVar(outlineView);
|
wxUnusedVar(outlineView);
|
||||||
|
|
||||||
|
// See the comment in outlineView:objectValueForTableColumn:byItem: below:
|
||||||
|
// this function can also be called in the same circumstances.
|
||||||
|
if ( implementation->GetDataViewCtrl()->IsDeleting() )
|
||||||
|
return nil;
|
||||||
|
|
||||||
if ((item == currentParentItem) &&
|
if ((item == currentParentItem) &&
|
||||||
(index < ((NSInteger) [self getChildCount])))
|
(index < ((NSInteger) [self getChildCount])))
|
||||||
return [self getChild:index];
|
return [self getChild:index];
|
||||||
|
|||||||
@@ -49,6 +49,33 @@ wxString ConcatenateDataViewItemValues(wxDataViewCtrl const* dataViewCtrlPtr, wx
|
|||||||
return dataString;
|
return dataString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// wxOSXDVCScopedDeleter
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// Helper class which exists only to reset m_Deleting on scope exit.
|
||||||
|
class wxOSXDVCScopedDeleter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit wxOSXDVCScopedDeleter(wxDataViewCtrl* dvc) :
|
||||||
|
m_dvc(dvc),
|
||||||
|
m_valueOrig(m_dvc->m_Deleting)
|
||||||
|
{
|
||||||
|
m_dvc->m_Deleting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~wxOSXDVCScopedDeleter()
|
||||||
|
{
|
||||||
|
m_dvc->m_Deleting = m_valueOrig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
wxDataViewCtrl* const m_dvc;
|
||||||
|
const bool m_valueOrig;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_CLASS(wxOSXDVCScopedDeleter);
|
||||||
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// wxOSXDataViewModelNotifier
|
// wxOSXDataViewModelNotifier
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -192,42 +219,33 @@ bool wxOSXDataViewModelNotifier::ItemsChanged(wxDataViewItemArray const& items)
|
|||||||
|
|
||||||
bool wxOSXDataViewModelNotifier::ItemDeleted(wxDataViewItem const& parent, wxDataViewItem const& item)
|
bool wxOSXDataViewModelNotifier::ItemDeleted(wxDataViewItem const& parent, wxDataViewItem const& item)
|
||||||
{
|
{
|
||||||
bool noFailureFlag;
|
|
||||||
|
|
||||||
|
|
||||||
wxCHECK_MSG(item.IsOk(),false,"To be deleted item is invalid.");
|
wxCHECK_MSG(item.IsOk(),false,"To be deleted item is invalid.");
|
||||||
// when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
|
// when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
|
||||||
// not to be identical because the being edited item might be below the passed item in the hierarchy);
|
// not to be identical because the being edited item might be below the passed item in the hierarchy);
|
||||||
// to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
|
// to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
|
||||||
// has been started and that variables can currently not be updated even when requested by the system:
|
// has been started and that variables can currently not be updated even when requested by the system:
|
||||||
m_DataViewCtrlPtr->SetDeleting(true);
|
wxOSXDVCScopedDeleter setDeleting(m_DataViewCtrlPtr);
|
||||||
noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent);
|
|
||||||
// enable automatic updating again:
|
bool ok = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent);
|
||||||
m_DataViewCtrlPtr->SetDeleting(false);
|
|
||||||
|
|
||||||
AdjustAutosizedColumns();
|
AdjustAutosizedColumns();
|
||||||
// done:
|
|
||||||
return noFailureFlag;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxOSXDataViewModelNotifier::ItemsDeleted(wxDataViewItem const& parent, wxDataViewItemArray const& WXUNUSED(items))
|
bool wxOSXDataViewModelNotifier::ItemsDeleted(wxDataViewItem const& parent, wxDataViewItemArray const& WXUNUSED(items))
|
||||||
{
|
{
|
||||||
bool noFailureFlag;
|
|
||||||
|
|
||||||
|
|
||||||
// when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
|
// when this method is called and currently an item is being edited this item may have already been deleted in the model (the passed item and the being edited item have
|
||||||
// not to be identical because the being edited item might be below the passed item in the hierarchy);
|
// not to be identical because the being edited item might be below the passed item in the hierarchy);
|
||||||
// to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
|
// to prevent the control trying to ask the model to update an already deleted item the control is informed that currently a deleting process
|
||||||
// has been started and that variables can currently not be updated even when requested by the system:
|
// has been started and that variables can currently not be updated even when requested by the system:
|
||||||
m_DataViewCtrlPtr->SetDeleting(true);
|
wxOSXDVCScopedDeleter setDeleting(m_DataViewCtrlPtr);
|
||||||
// delete all specified items:
|
// delete all specified items:
|
||||||
noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent);
|
bool ok = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent);
|
||||||
// enable automatic updating again:
|
|
||||||
m_DataViewCtrlPtr->SetDeleting(false);
|
|
||||||
|
|
||||||
AdjustAutosizedColumns();
|
AdjustAutosizedColumns();
|
||||||
// done:
|
|
||||||
return noFailureFlag;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxOSXDataViewModelNotifier::ValueChanged(wxDataViewItem const& item, unsigned int col)
|
bool wxOSXDataViewModelNotifier::ValueChanged(wxDataViewItem const& item, unsigned int col)
|
||||||
@@ -251,6 +269,8 @@ bool wxOSXDataViewModelNotifier::ValueChanged(wxDataViewItem const& item, unsign
|
|||||||
|
|
||||||
bool wxOSXDataViewModelNotifier::Cleared()
|
bool wxOSXDataViewModelNotifier::Cleared()
|
||||||
{
|
{
|
||||||
|
// NOTE: See comments in ItemDeleted method above
|
||||||
|
wxOSXDVCScopedDeleter setDeleting(m_DataViewCtrlPtr);
|
||||||
return m_DataViewCtrlPtr->GetDataViewPeer()->Reload();
|
return m_DataViewCtrlPtr->GetDataViewPeer()->Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user