crashtesting: crash seen on exporting forum-it-5909.ods to xlsx
[LibreOffice.git] / include / svl / undo.hxx
blobeff352298a5c06e71d7f6d0dce6e03d75919170f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #ifndef INCLUDED_SVL_UNDO_HXX
20 #define INCLUDED_SVL_UNDO_HXX
22 #include <svl/svldllapi.h>
23 #include <rtl/ustring.hxx>
24 #include <tools/datetime.hxx>
25 #include <o3tl/strong_int.hxx>
27 #include <memory>
28 #include <vector>
30 typedef o3tl::strong_int<sal_Int32, struct ViewShellIdTag> ViewShellId;
31 typedef o3tl::strong_int<int, struct ViewShellDocIdTag> ViewShellDocId;
33 typedef struct _xmlTextWriter* xmlTextWriterPtr;
35 class SVL_DLLPUBLIC SfxRepeatTarget
37 public:
38 virtual ~SfxRepeatTarget() = 0;
42 class SVL_DLLPUBLIC SfxUndoContext
44 public:
45 /**
46 * Don't undo the top undo action, but an earlier one. It's the caller's responsibility to
47 * ensure that the earlier undo action is independent from the following ones.
49 virtual size_t GetUndoOffset() { return 0; }
51 virtual ~SfxUndoContext() = 0;
55 class SVL_DLLPUBLIC SfxUndoAction
57 public:
58 SfxUndoAction();
59 virtual ~SfxUndoAction() COVERITY_NOEXCEPT_FALSE;
61 virtual void Undo();
62 virtual void UndoWithContext( SfxUndoContext& i_context );
63 virtual void Redo();
64 virtual void RedoWithContext( SfxUndoContext& i_context );
65 virtual void Repeat(SfxRepeatTarget&);
66 virtual bool CanRepeat(SfxRepeatTarget&) const;
68 virtual bool Merge( SfxUndoAction *pNextAction );
70 virtual OUString GetComment() const;
71 virtual OUString GetRepeatComment(SfxRepeatTarget&) const;
72 /// ID of the view shell that created this undo action.
73 virtual ViewShellId GetViewShellId() const;
74 /// Timestamp when this undo item was created.
75 const DateTime& GetDateTime() const;
76 virtual void dumpAsXml(xmlTextWriterPtr pWriter) const;
78 private:
79 SfxUndoAction( const SfxUndoAction& ) = delete;
80 SfxUndoAction& operator=( const SfxUndoAction& ) = delete;
82 DateTime m_aDateTime;
86 /// is a mark on the Undo stack
87 typedef sal_Int32 UndoStackMark;
88 #define MARK_INVALID ::std::numeric_limits< UndoStackMark >::max()
90 struct MarkedUndoAction
92 std::unique_ptr<SfxUndoAction> pAction;
93 ::std::vector< UndoStackMark > aMarks;
95 MarkedUndoAction(std::unique_ptr<SfxUndoAction> p) : pAction(std::move(p)) {}
98 /** do not make use of these implementation details, unless you
99 really really have to! */
100 struct SVL_DLLPUBLIC SfxUndoArray
102 std::vector<MarkedUndoAction> maUndoActions;
103 size_t nMaxUndoActions;
104 size_t nCurUndoAction;
105 SfxUndoArray *pFatherUndoArray;
107 SfxUndoArray(size_t nMax=0) :
108 nMaxUndoActions(nMax), nCurUndoAction(0), pFatherUndoArray(nullptr) {}
109 virtual ~SfxUndoArray();
111 SfxUndoArray& operator=( SfxUndoArray const & ) = delete; // MSVC2017 workaround
112 SfxUndoArray( SfxUndoArray const & ) = delete; // MSVC2017 workaround
114 SfxUndoAction* GetUndoAction(size_t idx) { return maUndoActions[idx].pAction.get(); }
115 std::unique_ptr<SfxUndoAction> Remove(int idx);
116 void Remove( size_t i_pos, size_t i_count );
117 void Insert( std::unique_ptr<SfxUndoAction> i_action, size_t i_pos );
121 /** do not make use of these implementation details, unless you
122 really really have to! */
123 class SVL_DLLPUBLIC SfxListUndoAction final : public SfxUndoAction, public SfxUndoArray
125 /* [Explanation]
127 UndoAction to composite multiple Undos in one UndoAction.
128 These actions are used by SfxUndomanager. With < SfxUndoManager::EnterListAction >
129 you can go one composite level down and with < SfxUndoManager::LeaveListAction > up again.
130 Redo and Undo work element wise on SfxListUndoActions.
133 struct Impl;
134 std::unique_ptr<Impl> mpImpl;
136 public:
138 SfxListUndoAction(
139 const OUString &rComment, const OUString& rRepeatComment, sal_uInt16 nId, ViewShellId nViewShellId, SfxUndoArray *pFather );
140 virtual ~SfxListUndoAction() override;
142 virtual void Undo() override;
143 virtual void UndoWithContext( SfxUndoContext& i_context ) override;
144 virtual void Redo() override;
145 virtual void RedoWithContext( SfxUndoContext& i_context ) override;
146 virtual void Repeat(SfxRepeatTarget&) override;
147 virtual bool CanRepeat(SfxRepeatTarget&) const override;
149 virtual bool Merge( SfxUndoAction *pNextAction ) override;
151 virtual OUString GetComment() const override;
152 /// See SfxUndoAction::GetViewShellId().
153 ViewShellId GetViewShellId() const override;
154 virtual OUString GetRepeatComment(SfxRepeatTarget&) const override;
155 sal_uInt16 GetId() const;
157 void SetComment(const OUString& rComment);
158 void dumpAsXml(xmlTextWriterPtr pWriter) const override;
162 /** is a callback interface for notifications about state changes of an SfxUndoManager
164 class SAL_NO_VTABLE SfxUndoListener
166 public:
167 virtual void actionUndone( const OUString& i_actionComment ) = 0;
168 virtual void actionRedone( const OUString& i_actionComment ) = 0;
169 virtual void undoActionAdded( const OUString& i_actionComment ) = 0;
170 virtual void cleared() = 0;
171 virtual void clearedRedo() = 0;
172 virtual void resetAll() = 0;
173 virtual void listActionEntered( const OUString& i_comment ) = 0;
174 virtual void listActionLeft( const OUString& i_comment ) = 0;
175 virtual void listActionCancelled() = 0;
177 protected:
178 ~SfxUndoListener() {}
182 namespace svl::undo::impl
184 class UndoManagerGuard;
185 class LockGuard;
188 struct SfxUndoManager_Data;
189 class SVL_DLLPUBLIC SfxUndoManager
191 std::unique_ptr< SfxUndoManager_Data >
192 m_xData;
193 public:
194 static bool const CurrentLevel = true;
195 static bool const TopLevel = false;
197 SfxUndoManager( size_t nMaxUndoActionCount = 20 );
198 virtual ~SfxUndoManager();
200 void SetMaxUndoActionCount( size_t nMaxUndoActionCount );
201 virtual void AddUndoAction( std::unique_ptr<SfxUndoAction> pAction, bool bTryMerg=false );
202 virtual size_t GetUndoActionCount( bool const i_currentLevel = CurrentLevel ) const;
203 OUString GetUndoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const;
204 SfxUndoAction* GetUndoAction( size_t nNo=0 ) const;
205 /// Get info about all undo actions (comment, view shell id, etc.)
206 OUString GetUndoActionsInfo() const;
207 virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const;
208 OUString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const;
209 SfxUndoAction* GetRedoAction(size_t nNo = 0) const;
210 /// Get info about all redo actions (comment, view shell id, etc.)
211 OUString GetRedoActionsInfo() const;
212 virtual bool Undo();
213 virtual bool Redo();
214 /** Clears both the Redo and the Undo stack.
215 Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
217 virtual void Clear();
218 /** Clears the Redo stack.
219 Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
221 virtual void ClearRedo();
222 /** leaves any possible open list action (<member>IsInListAction</member>), and clears both the Undo and the
223 Redo stack.
225 Effectively, calling this method is equivalent to <code>while ( IsInListAction() ) LeaveListAction();</code>,
226 followed by <code>Clear()</code>. The only difference to this calling sequence is that Reset is an
227 atomic operation, also resulting in only one notification.
229 void Reset();
230 /** determines whether an Undo or Redo is currently running
232 bool IsDoing() const;
233 size_t GetRepeatActionCount() const;
234 OUString GetRepeatActionComment( SfxRepeatTarget &rTarget) const;
235 bool Repeat( SfxRepeatTarget &rTarget );
236 bool CanRepeat( SfxRepeatTarget &rTarget ) const;
237 virtual void EnterListAction(const OUString &rComment, const OUString& rRepeatComment, sal_uInt16 nId, ViewShellId nViewShellId);
238 /** Leaves the list action entered with EnterListAction
239 @return the number of the sub actions in the list which has just been left. Note that in case no such
240 actions exist, the list action does not contribute to the Undo stack, but is silently removed.
242 size_t LeaveListAction();
244 /** Leaves the list action entered with EnterListAction, and forcefully merges the previous
245 action on the stack into the newly created list action.
247 Say you have an Undo action A on the stack, then call EnterListAction, followed by one or more calls to
248 AddUndoAction, followed by a call to LeaveAndMergeListAction. In opposite to LeaveListAction, your Undo
249 stack will now still contain one undo action: the newly created list action, whose first child is the
250 original A, whose other children are those you added via AddUndoAction, and whose comment is the same as
251 the comment of A.
253 Effectively, this means that all actions added between EnterListAction and LeaveAndMergeListAction are
254 hidden from the user.
256 @return the number of the sub actions in the list which has just been left. Note that in case no such
257 actions exist, the list action does not contribute to the Undo stack, but is silently removed.
259 size_t LeaveAndMergeListAction();
260 /// determines whether we're within a ListAction context, i.e. a LeaveListAction/LeaveAndMergeListAction call is pending
261 bool IsInListAction() const;
262 /// Determines how many nested list actions are currently open
263 size_t GetListActionDepth() const;
264 /** Clears the redo stack and removes the top undo action */
265 void RemoveLastUndoAction();
266 /** enables (true) or disables (false) recording of undo actions
268 If undo actions are added while undo is disabled, they are deleted.
269 Disabling undo does not clear the current undo buffer!
271 Multiple calls to <code>EnableUndo</code> are not cumulative. That is, calling <code>EnableUndo( false )</code>
272 twice, and then calling <code>EnableUndo( true )</code> means that Undo is enable afterwards.
274 void EnableUndo( bool bEnable );
275 /// returns true if undo is currently enabled.
276 /// This returns false if undo was disabled using EnableUndo( false ) and
277 /// also during the runtime of the Undo() and Redo() methods.
278 bool IsUndoEnabled() const;
279 /// Adds a new listener to be notified about changes in the UndoManager's state
280 void AddUndoListener( SfxUndoListener& i_listener );
281 void RemoveUndoListener( SfxUndoListener& i_listener );
282 bool IsEmptyActions() const;
285 /** marks the current top-level element of the Undo stack, and returns a unique ID for it
287 UndoStackMark MarkTopUndoAction();
289 /** removes a mark given by its ID.
290 After the call, the mark ID is invalid.
292 void RemoveMark( UndoStackMark const i_mark );
294 /** determines whether the top action on the Undo stack has a given mark
296 bool HasTopUndoActionMark( UndoStackMark const i_mark );
298 /** removes the oldest Undo actions from the stack
300 void RemoveOldestUndoAction();
302 void dumpAsXml(xmlTextWriterPtr pWriter) const;
304 protected:
305 bool UndoWithContext( SfxUndoContext& i_context );
306 bool RedoWithContext( SfxUndoContext& i_context );
308 void ImplClearRedo_NoLock( bool const i_currentLevel );
310 /** clears all undo actions on the current level, plus all undo actions on superordinate levels,
311 as soon as those levels are reached.
313 If no list action is active currently, i.e. we're on the top level already, this method is equivalent to
314 ->Clear.
316 Otherwise, the Undo actions on the current level are removed. Upon leaving the current list action, all
317 undo actions on the then-current level are removed, too. This is continued until the top level is reached.
319 void ClearAllLevels();
320 virtual void EmptyActionsChanged();
322 private:
323 size_t ImplLeaveListAction( const bool i_merge, ::svl::undo::impl::UndoManagerGuard& i_guard );
324 bool ImplAddUndoAction_NoNotify( std::unique_ptr<SfxUndoAction> pAction, bool bTryMerge, bool bClearRedo, ::svl::undo::impl::UndoManagerGuard& i_guard );
325 void ImplClearRedo( ::svl::undo::impl::UndoManagerGuard& i_guard, bool const i_currentLevel );
326 void ImplClearUndo( ::svl::undo::impl::UndoManagerGuard& i_guard );
327 void ImplClearCurrentLevel_NoNotify( ::svl::undo::impl::UndoManagerGuard& i_guard );
328 size_t ImplGetRedoActionCount_Lock( bool const i_currentLevel = CurrentLevel ) const;
329 bool ImplIsUndoEnabled_Lock() const;
330 bool ImplIsInListAction_Lock() const;
331 void ImplEnableUndo_Lock( bool const i_enable );
333 bool ImplUndo( SfxUndoContext* i_contextOrNull );
334 bool ImplRedo( SfxUndoContext* i_contextOrNull );
335 void ImplCheckEmptyActions();
336 inline bool ImplIsEmptyActions() const;
338 friend class ::svl::undo::impl::LockGuard;
341 #endif
343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */