/src/libreoffice/sd/inc/Outliner.hxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #pragma once |
21 | | |
22 | | #include <svx/svdoutl.hxx> |
23 | | #include "pres.hxx" |
24 | | #include "OutlinerIterator.hxx" |
25 | | #include <editeng/SpellPortions.hxx> |
26 | | #include <memory> |
27 | | #include <utility> |
28 | | |
29 | | class SdrObject; |
30 | | class SdrTextObj; |
31 | | class SdDrawDocument; |
32 | | |
33 | | namespace weld |
34 | | { |
35 | | class Window; |
36 | | } |
37 | | |
38 | | namespace sd |
39 | | { |
40 | | class View; |
41 | | class ViewShell; |
42 | | class Window; |
43 | | |
44 | | /// Describes a single search hit: a set of rectangles on a given page. |
45 | | struct SearchSelection |
46 | | { |
47 | | /// 0-based index of the page that has the selection. |
48 | | int m_nPage; |
49 | | |
50 | | /** |
51 | | * List of selection rectangles in twips -- multiple rectangles only in |
52 | | * case the selection spans over more layout lines. |
53 | | */ |
54 | | OString m_aRectangles; |
55 | | |
56 | | SearchSelection(int nPage, OString aRectangles) |
57 | 0 | : m_nPage(nPage) |
58 | 0 | , m_aRectangles(std::move(aRectangles)) |
59 | 0 | { |
60 | 0 | } |
61 | | |
62 | | bool operator==(const SearchSelection& rOther) const |
63 | 0 | { |
64 | 0 | return m_nPage == rOther.m_nPage && m_aRectangles == rOther.m_aRectangles; |
65 | 0 | } |
66 | | }; |
67 | | |
68 | | } // end of namespace sd |
69 | | |
70 | | /** The main purpose of this class is searching and replacing as well as |
71 | | spelling of impress documents. The main part of both tasks lies in |
72 | | iterating over the pages and view modes of a document and apply the |
73 | | respective function to all objects containing text on those pages. |
74 | | |
75 | | <p>Relevant objects: There are two sets of objects to search/spell |
76 | | check. One is the set of all selected objects. The other consists of |
77 | | all objects on all pages in draw-, notes-, and handout view as well as |
78 | | slide- and background view (draw pages and master pages).</p> |
79 | | |
80 | | <p>Iteration: Search/replace and spelling functions operate on shapes |
81 | | containing text. To cover all relevant objects an order has to be |
82 | | defined on the objects. For the set of all selected objects this order |
83 | | is simply the order in which they can be retrieved from the selection |
84 | | object.<br> |
85 | | When there is no selection the order is nested. The three modes of the |
86 | | draw view are on the outer level: draw mode, notes mode, handout mode. |
87 | | The inner level switches between draw pages and master pages. This |
88 | | leads to the following order: |
89 | | <ol> |
90 | | <li>draw pages of draw mode</li> |
91 | | <li>master pages of draw mode</li> |
92 | | <li>draw pages of notes mode</li> |
93 | | <li>master pages of notes mode</li> |
94 | | <li>draw pages of handout mode</li> |
95 | | <li>master pages of handout mode</li> |
96 | | </ol> |
97 | | Iteration starts at the top of the current page. When reaching the end |
98 | | of the document, i.e. the last master page of the handout mode, it jumps |
99 | | to the first draw page of draw mode. In backward searches this order is |
100 | | reversed. When doing a <em>replace all</em> then the whole document is |
101 | | searched for matches starting at the first page of the draw/slide view |
102 | | (or last page of handout/background view even though search |
103 | | direction).</p> |
104 | | |
105 | | <p>The start position is restored after finishing spell checking or |
106 | | replacing all matches in a document.</p> |
107 | | |
108 | | <p>Some related pieces of information: |
109 | | The search dialog (<type>SvxSearchDialog</type>) can be controlled in |
110 | | more than one way: |
111 | | <ul><li>A set of option flags returned by the slot call |
112 | | SID_SEARCH_OPTIONS handled by the |
113 | | <member>SdDrawDocument::GetState()</member> method.</li> |
114 | | <li>The contents of the search item of type |
115 | | <type>SvxSearchItem</type>.</li> |
116 | | <li>The <member>HasSelection()</member> view shell method that returns |
117 | | whether or not a selection exists. However, it is called from the |
118 | | search dialog with an argument so that only text selections are |
119 | | queried. This is only sufficient for searching the outline view. |
120 | | </p> |
121 | | */ |
122 | | class SdOutliner final : public SdrOutliner |
123 | | { |
124 | | public: |
125 | | friend class ::sd::outliner::OutlinerContainer; |
126 | | |
127 | | /** Create a new sd outliner object. |
128 | | @param rDoc |
129 | | The draw document from which to take the content. |
130 | | @param nMode |
131 | | The valid values <const>OutlinerMode::DontKnow</const>, |
132 | | <const>OutlinerMode::TextObject</const>, |
133 | | <const>OutlinerMode::TitleObject</const>, |
134 | | <const>OutlinerMode::OutlineObject</const>, and |
135 | | <const>OutlinerMode::OutlineView</const> are defined in |
136 | | editeng/outliner.hxx. |
137 | | */ |
138 | | SdOutliner(SdDrawDocument& rDoc, OutlinerMode nMode); |
139 | | virtual ~SdOutliner() override; |
140 | | /// Forbid copy construction and copy assignment |
141 | | SdOutliner(const Outliner&) = delete; |
142 | | SdOutliner& operator=(const Outliner&) = delete; |
143 | | |
144 | | /** Despite the name this method is called prior to spell checking *and* |
145 | | searching and replacing. The position of current view |
146 | | mode/page/object/caret position is remembered and, depending on the |
147 | | search mode, may be restored after finishing searching/spell |
148 | | checking. |
149 | | */ |
150 | | void PrepareSpelling(); |
151 | | |
152 | | /** Initialize a spell check but do not start it yet. This method |
153 | | is a better candidate for the name PrepareSpelling. |
154 | | */ |
155 | | void StartSpelling(); |
156 | | |
157 | | /** Initiate a find and/or replace on the next relevant text object. |
158 | | @return |
159 | | Returns </sal_True> when the search/replace is finished (as |
160 | | indicated by user input to the search dialog). A </sal_False> value |
161 | | indicates that another call to this method is required. |
162 | | */ |
163 | | bool StartSearchAndReplace(const SvxSearchItem* pSearchItem); |
164 | | |
165 | | /** Iterate over the sentences in all text shapes and stop at the |
166 | | next sentence with spelling errors. While doing so the view |
167 | | mode may be changed and text shapes are set into edit mode. |
168 | | */ |
169 | | svx::SpellPortions GetNextSpellSentence(); |
170 | | |
171 | | /** Release all resources that have been created during the find&replace |
172 | | or spell check. |
173 | | */ |
174 | | void EndSpelling(); |
175 | | |
176 | | /** callback for textconversion */ |
177 | | bool ConvertNextDocument() override; |
178 | | |
179 | | /** Starts the text conversion (hangul/hanja or Chinese simplified/traditional) |
180 | | for the current viewshell */ |
181 | | void StartConversion(LanguageType nSourceLanguage, LanguageType nTargetLanguage, |
182 | | const vcl::Font* pTargetFont, sal_Int32 nOptions, bool bIsInteractive); |
183 | | |
184 | | /** This is called internally when text conversion is started. |
185 | | The position of current view mode/page/object/caret position |
186 | | is remembered and will be restored after conversion. |
187 | | */ |
188 | | void BeginConversion(); |
189 | | |
190 | | /** Release all resources that have been created during the conversion */ |
191 | | void EndConversion(); |
192 | | |
193 | 0 | int GetIgnoreCurrentPageChangesLevel() const { return mnIgnoreCurrentPageChangesLevel; }; |
194 | 0 | void IncreIgnoreCurrentPageChangesLevel() { mnIgnoreCurrentPageChangesLevel++; }; |
195 | 0 | void DecreIgnoreCurrentPageChangesLevel() { mnIgnoreCurrentPageChangesLevel--; }; |
196 | 0 | SdDrawDocument& GetDoc() const { return mrDrawDocument; } |
197 | | |
198 | | private: |
199 | | class Implementation; |
200 | | ::std::unique_ptr<Implementation> mpImpl; |
201 | | |
202 | | /// Returns the current outline view |
203 | | OutlinerView* getOutlinerView(); |
204 | | |
205 | | /// Specifies whether to search and replace, to spell check or to do a |
206 | | /// text conversion. |
207 | | enum mode |
208 | | { |
209 | | SEARCH, |
210 | | SPELL, |
211 | | TEXT_CONVERSION |
212 | | } meMode; |
213 | | |
214 | | /// The view which displays the searched objects. |
215 | | ::sd::View* mpView; |
216 | | /** The view shell containing the view. It is held as weak |
217 | | pointer to avoid keeping it alive when the view is changed |
218 | | during searching. |
219 | | */ |
220 | | std::weak_ptr<::sd::ViewShell> mpWeakViewShell; |
221 | | /// This window contains the view. |
222 | | VclPtr<::sd::Window> mpWindow; |
223 | | /// The document on whose objects and pages this class operates. |
224 | | SdDrawDocument& mrDrawDocument; |
225 | | |
226 | | /** this is the language that is used for current text conversion. |
227 | | Only valid if meMode is TEXT_CONVERSION. |
228 | | */ |
229 | | LanguageType mnConversionLanguage; |
230 | | |
231 | | /** While the value of this flag is greater than 0 changes of the current page |
232 | | do not lead to selecting the corresponding text in the outliner. |
233 | | */ |
234 | | int mnIgnoreCurrentPageChangesLevel; |
235 | | |
236 | | /// Specifies whether the search string has been found so far. |
237 | | bool mbStringFound; |
238 | | |
239 | | /** This flag indicates whether there may exist a match of the search |
240 | | string before/after the current position in the document. It can be |
241 | | set to </sal_False> only when starting from the beginning/end of the |
242 | | document. When reaching the end/beginning with it still be set to |
243 | | </sal_False> then there exists no match and the search can be terminated. |
244 | | */ |
245 | | bool mbMatchMayExist; |
246 | | |
247 | | /// The number of pages in the current view. |
248 | | sal_uInt16 mnPageCount; |
249 | | |
250 | | /** A <TRUE/> value indicates that the end of the find&replace or spell |
251 | | check has been reached. |
252 | | */ |
253 | | bool mbEndOfSearch; |
254 | | |
255 | | /** Set to <TRUE/> when an object has been prepared successfully for |
256 | | searching/spell checking. This flag directs the internal iteration |
257 | | which stops when set to </sal_True>. |
258 | | */ |
259 | | bool mbFoundObject; |
260 | | |
261 | | /** This flag indicates whether to search forward or backwards. |
262 | | */ |
263 | | bool mbDirectionIsForward; |
264 | | |
265 | | /** This flag indicates that only the selected objects are to be |
266 | | searched. |
267 | | */ |
268 | | bool mbRestrictSearchToSelection; |
269 | | |
270 | | /** When the search is restricted to the current selection then |
271 | | this list contains pointers to all the objects of the |
272 | | selection. This copy is necessary because during the search |
273 | | process the mark list is modified. |
274 | | */ |
275 | | ::std::vector<unotools::WeakReference<SdrObject>> maMarkListCopy; |
276 | | |
277 | | /** Current object that may be a text object. The object pointer to |
278 | | corresponds to <member>mnObjIndex</member>. While iterating over the |
279 | | objects on a page <member>mpObj</member> will point to every object |
280 | | while <member>mpTextObj</member> will be set only to valid text |
281 | | objects. |
282 | | */ |
283 | | SdrObject* mpObj; |
284 | | |
285 | | /** this stores the first object that is used for text conversion. |
286 | | Conversion automatically wraps around the document and stops when it |
287 | | finds this object again. |
288 | | */ |
289 | | SdrObject* mpFirstObj; |
290 | | |
291 | | /// Candidate for being searched/spell checked. |
292 | | SdrTextObj* mpSearchSpellTextObj; |
293 | | |
294 | | /// Current text to be searched/spelled inside the current text object |
295 | | sal_Int32 mnText; |
296 | | |
297 | | /// Paragraph object of <member>mpTextObj</member>. |
298 | | OutlinerParaObject* mpParaObj; |
299 | | |
300 | | /// The view mode that was active when starting to search/spell check. |
301 | | PageKind meStartViewMode; |
302 | | |
303 | | /// The master page mode that was active when starting to search/spell check. |
304 | | EditMode meStartEditMode; |
305 | | |
306 | | /// The current page index on starting to search/spell check. |
307 | | sal_uInt16 mnStartPageIndex; |
308 | | |
309 | | /// The object in edit mode when searching /spell checking was started |
310 | | /// (if any). |
311 | | SdrObject* mpStartEditedObject; |
312 | | |
313 | | /// The position of the caret when searching /spell checking was started. |
314 | | ESelection maStartSelection; |
315 | | |
316 | | /** The search item contains various attributes that define the type of |
317 | | search. It is set every time the |
318 | | <member>SearchAndReplaceAll</member> method is called. |
319 | | */ |
320 | | std::unique_ptr<const SvxSearchItem> mpSearchItem; |
321 | | |
322 | | /// The actual object iterator. |
323 | | ::sd::outliner::Iterator maObjectIterator; |
324 | | /// The current position of the object iterator. |
325 | | ::sd::outliner::IteratorPosition maCurrentPosition; |
326 | | /// The position when the search started. Corresponds largely to the |
327 | | /// m?Start* members. |
328 | | ::sd::outliner::Iterator maSearchStartPosition; |
329 | | /** The last valid position describes where the last text object has been |
330 | | found. This position is restored when some dialogs are shown. The |
331 | | position is initially set to the where the search begins. |
332 | | */ |
333 | | ::sd::outliner::IteratorPosition maLastValidPosition; |
334 | | |
335 | | /** When this flag is true then a PrepareSpelling() is executed when |
336 | | StartSearchAndReplace() is called the next time. |
337 | | */ |
338 | | bool mbPrepareSpellingPending; |
339 | | |
340 | | /** Initialize the object iterator. Call this method after being |
341 | | invoked from the search or spellcheck dialog. It creates a new |
342 | | iterator pointing at the current object when this has not been done |
343 | | before. It reverses the direction of iteration if the given flag |
344 | | differs from the current direction. |
345 | | @param bDirectionIsForward |
346 | | This flag specifies in which direction to iterator over the |
347 | | objects. If it differs from the current direction the iterator |
348 | | is reversed. |
349 | | */ |
350 | | void Initialize(bool bDirectionIsForward); |
351 | | |
352 | | /** Do search and replace for whole document. |
353 | | */ |
354 | | bool SearchAndReplaceAll(); |
355 | | |
356 | | /** Do search and replace for next match. |
357 | | @param pSelections |
358 | | When tiled rendering and not 0, then don't emit LOK events, instead |
359 | | assume the caller will do so. |
360 | | @return |
361 | | The return value specifies whether the search ended (</sal_True>) or |
362 | | another call to this method is required (</sal_False>). |
363 | | */ |
364 | | bool SearchAndReplaceOnce(std::vector<::sd::SearchSelection>* pSelections = nullptr); |
365 | | |
366 | | void sendLOKSearchResultCallback(const std::shared_ptr<sd::ViewShell>& pViewShell, |
367 | | const OutlinerView* pOutlinerView, |
368 | | std::vector<sd::SearchSelection>* pSelections); |
369 | | |
370 | | /** Detect changes of the document or view and react accordingly. Such |
371 | | changes may occur because different calls to |
372 | | <member>SearchAndReplace()</member> there usually is user |
373 | | interaction. This is at least the press of the search or replace |
374 | | button but may include any other action some of which affect the |
375 | | search. |
376 | | */ |
377 | | void DetectChange(); |
378 | | |
379 | | /** Detect whether the selection has changed. |
380 | | @return |
381 | | Return <TRUE/> when the selection has been changed since the |
382 | | last call to this method. |
383 | | */ |
384 | | bool DetectSelectionChange(); |
385 | | |
386 | | /** Remember the current edited object/caret position/page/view mode |
387 | | when starting to search/spell check so that it can be restored on |
388 | | termination. |
389 | | */ |
390 | | void RememberStartPosition(); |
391 | | |
392 | | /** Restore the position stored in the last call of |
393 | | <member>RememberStartPositiony</member>. |
394 | | */ |
395 | | void RestoreStartPosition(); |
396 | | |
397 | | /** Provide next object to search or spell check as text object in edit |
398 | | mode on the current page. This skips all objects that do not |
399 | | match or are no text object. |
400 | | */ |
401 | | void ProvideNextTextObject(); |
402 | | |
403 | | /** Handle the situation that the iterator has reached the last object. |
404 | | This may result in setting the <member>mbEndOfSearch</member> flag |
405 | | back to </sal_False>. This method may show either the end-of-search |
406 | | dialog or the wrap-around dialog. |
407 | | */ |
408 | | void EndOfSearch(); |
409 | | |
410 | | /** Show a dialog that tells the user that the search has ended either |
411 | | because there are no more matches after finding at least one or that |
412 | | no match has been found at all. |
413 | | */ |
414 | | void ShowEndOfSearchDialog(); |
415 | | |
416 | | /** Show a dialog that asks the user whether to wrap around to the |
417 | | beginning/end of the document and continue with the search/spell |
418 | | check. |
419 | | */ |
420 | | bool ShowWrapAroundDialog(); |
421 | | |
422 | | /** Put text of current text object into outliner so that the text can |
423 | | be searched/spell checked. |
424 | | */ |
425 | | void PutTextIntoOutliner(); |
426 | | |
427 | | /** Prepare to do spell checking on the current text object. This |
428 | | includes putting it into edit mode. Under certain conditions this |
429 | | method sets <member>mbEndOfSearch</member> to <TRUE/>. |
430 | | */ |
431 | | void PrepareSpellCheck(); |
432 | | |
433 | | /** Prepare to search and replace on the current text object. This |
434 | | includes putting it into edit mode. |
435 | | */ |
436 | | void PrepareSearchAndReplace(); |
437 | | |
438 | | /** Prepare to do a text conversion on the current text |
439 | | object. This includes putting it into edit mode. |
440 | | */ |
441 | | void PrepareConversion(); |
442 | | |
443 | | /** Switch to a new view mode. Try to restore the original edit mode |
444 | | before doing so. |
445 | | @param ePageKind |
446 | | Specifies the new view mode. |
447 | | */ |
448 | | void SetViewMode(PageKind ePageKind); |
449 | | |
450 | | /** Switch to the page or master page specified by the |
451 | | <member>mnPage</member> index. Master page mode is specified by |
452 | | <member>meEditMode</member>. |
453 | | @param eEditMode |
454 | | The new edit mode. |
455 | | @param nPageIndex |
456 | | The new page index. |
457 | | */ |
458 | | void SetPage(EditMode eEditMode, sal_uInt16 nPageIndex); |
459 | | |
460 | | /** Switch on edit mode for the currently selected text object. |
461 | | */ |
462 | | void EnterEditMode(bool bGrabFocus); |
463 | | |
464 | | /** Return the position at which a new search is started with respect to |
465 | | the search direction as specified by the argument. |
466 | | @return |
467 | | The position mentioned above in form of a selection with start |
468 | | equals end. |
469 | | */ |
470 | | ESelection GetSearchStartPosition() const; |
471 | | |
472 | | /** Detect whether there exists a previous match. Note that only the |
473 | | absence of such a match can be detected reliably. An existing match |
474 | | is assumed when the search started not at the beginning/end of the |
475 | | presentation. This does not have to be true. The user can have set |
476 | | the cursor at the middle of the text without a prior search. |
477 | | @return |
478 | | Returns </True> when there is no previous match and </False> |
479 | | when there may be one. |
480 | | */ |
481 | | bool HasNoPreviousMatch(); |
482 | | |
483 | | /** Handle a failed search (with or without replace) for the outline |
484 | | mode. Show message boxes when the search failed completely, |
485 | | i.e. there is no match in the whole presentation, or when no further |
486 | | match exists. |
487 | | @return |
488 | | The returned value indicates whether another (wrapped around) |
489 | | search shall take place. If that is so, then it is the caller's |
490 | | responsibility to set the cursor position accordingly. |
491 | | */ |
492 | | bool HandleFailedSearch(); |
493 | | |
494 | | /** Take a position as returned by an object iterator and switch to the |
495 | | view and page on which the object specified by this position is |
496 | | located. |
497 | | @param rPosition |
498 | | This position points to a <type>SdrObject</type> object and |
499 | | contains the view and page where it is located. |
500 | | @return |
501 | | Return a pointer to the <type>SdrObject</type>. |
502 | | */ |
503 | | SdrObject* SetObject(const ::sd::outliner::IteratorPosition& rPosition); |
504 | | |
505 | | /** Use this method when the view shell in which to search has changed. |
506 | | It handles i.e. registering at the associated view as selection |
507 | | change listener. |
508 | | */ |
509 | | void SetViewShell(const std::shared_ptr<::sd::ViewShell>& rpViewShell); |
510 | | |
511 | | /** Activate or deactivate the search in the current selection. Call |
512 | | this method whenever the selection has changed. This method creates |
513 | | a copy of the current selection and reassigns the object iterator to |
514 | | the current() iterator. |
515 | | */ |
516 | | void HandleChangedSelection(); |
517 | | |
518 | | /** Initiate the spell check of the next relevant text object. |
519 | | When the outline view is active then this method is called |
520 | | after a wrap around to continue at the beginning of the document. |
521 | | @return |
522 | | Returns <TRUE/> to indicate that another call to this method is |
523 | | required. When all text objects have been processed then |
524 | | <FALSE/> is returned. |
525 | | */ |
526 | | virtual bool SpellNextDocument() override; |
527 | | |
528 | | /** Find the right parent to use for a message. This function makes sure |
529 | | that the otherwise non-modal search or spell dialogs, if visible, are |
530 | | locked, too. |
531 | | */ |
532 | | weld::Window* GetMessageBoxParent(); |
533 | | }; |
534 | | |
535 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |