Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/control/wizardmachine.cxx
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
#include <comphelper/lok.hxx>
21
#include <officecfg/Office/Common.hxx>
22
#include <tools/debug.hxx>
23
#include <vcl/roadmapwizardmachine.hxx>
24
#include <comphelper/diagnose_ex.hxx>
25
#include <strings.hrc>
26
#include <svdata.hxx>
27
#include <stack>
28
#include "wizimpldata.hxx"
29
30
namespace vcl
31
{
32
    //= WizardPageImplData
33
    OWizardPage::OWizardPage(weld::Container* pPage, weld::DialogController* pController, const OUString& rUIXMLDescription, const OUString& rID)
34
0
        : BuilderPage(pPage, pController, rUIXMLDescription, rID)
35
0
    {
36
0
    }
37
38
    OWizardPage::~OWizardPage()
39
0
    {
40
0
    }
41
42
    void OWizardPage::initializePage()
43
0
    {
44
0
    }
45
46
    void OWizardPage::Activate()
47
0
    {
48
0
        BuilderPage::Activate();
49
0
        updateDialogTravelUI();
50
0
    }
51
52
    void OWizardPage::updateDialogTravelUI()
53
0
    {
54
0
        auto pWizardMachine = dynamic_cast<RoadmapWizardMachine*>(m_pDialogController);
55
0
        if (pWizardMachine)
56
0
            pWizardMachine->updateTravelUI();
57
0
    }
58
59
    bool OWizardPage::canAdvance() const
60
0
    {
61
0
        return true;
62
0
    }
63
64
    bool OWizardPage::commitPage( WizardTypes::CommitPageReason )
65
0
    {
66
0
        return true;
67
0
    }
68
69
    WizardMachine::WizardMachine(weld::Window* pParent, WizardButtonFlags nButtonFlags)
70
0
        : AssistantController(pParent, u"vcl/ui/wizard.ui"_ustr, u"Wizard"_ustr)
71
0
        , m_pCurTabPage(nullptr)
72
0
        , m_nCurState(0)
73
0
        , m_pFirstPage(nullptr)
74
0
        , m_xFinish(m_xAssistant->weld_button_for_response(RET_OK))
75
0
        , m_xCancel(m_xAssistant->weld_button_for_response(RET_CANCEL))
76
0
        , m_xNextPage(m_xAssistant->weld_button_for_response(RET_YES))
77
0
        , m_xPrevPage(m_xAssistant->weld_button_for_response(RET_NO))
78
0
        , m_xHelp(m_xAssistant->weld_button_for_response(RET_HELP))
79
0
        , m_pImpl(new WizardMachineImplData)
80
0
    {
81
0
        implConstruct(nButtonFlags);
82
0
    }
83
84
    void WizardMachine::implConstruct(const WizardButtonFlags nButtonFlags)
85
0
    {
86
0
        m_pImpl->sTitleBase = m_xAssistant->get_title();
87
88
0
        const bool bHideHelp = comphelper::LibreOfficeKit::isActive() &&
89
0
            officecfg::Office::Common::Help::HelpRootURL::get().isEmpty();
90
        // create the buttons according to the wizard button flags
91
        // the help button
92
0
        if (nButtonFlags & WizardButtonFlags::HELP && !bHideHelp)
93
0
            m_xHelp->show();
94
0
        else
95
0
            m_xHelp->hide();
96
97
        // the previous button
98
0
        if (nButtonFlags & WizardButtonFlags::PREVIOUS)
99
0
        {
100
0
            m_xPrevPage->set_help_id( HID_WIZARD_PREVIOUS );
101
0
            m_xPrevPage->show();
102
103
0
            m_xPrevPage->connect_clicked( LINK( this, WizardMachine, OnPrevPage ) );
104
0
        }
105
0
        else
106
0
            m_xPrevPage->hide();
107
108
        // the next button
109
0
        if (nButtonFlags & WizardButtonFlags::NEXT)
110
0
        {
111
0
            m_xNextPage->set_help_id( HID_WIZARD_NEXT );
112
0
            m_xNextPage->show();
113
114
0
            m_xNextPage->connect_clicked( LINK( this, WizardMachine, OnNextPage ) );
115
0
        }
116
0
        else
117
0
            m_xNextPage->hide();
118
119
        // the finish button
120
0
        if (nButtonFlags & WizardButtonFlags::FINISH)
121
0
        {
122
0
            m_xFinish->show();
123
124
0
            m_xFinish->connect_clicked( LINK( this, WizardMachine, OnFinish ) );
125
0
        }
126
0
        else
127
0
            m_xFinish->hide();
128
129
        // the cancel button
130
0
        if (nButtonFlags & WizardButtonFlags::CANCEL)
131
0
        {
132
0
            m_xCancel->show();
133
0
            m_xCancel->connect_clicked( LINK( this, WizardMachine, OnCancel ) );
134
0
        }
135
0
        else
136
0
            m_xCancel->hide();
137
0
    }
138
139
    WizardMachine::~WizardMachine()
140
0
    {
141
0
        if (m_pImpl)
142
0
        {
143
0
            while (m_pFirstPage)
144
0
                RemovePage(m_pFirstPage->mxPage.get());
145
0
            m_pImpl.reset();
146
0
        }
147
0
    }
148
149
    void WizardMachine::implUpdateTitle()
150
0
    {
151
0
        OUString sCompleteTitle(m_pImpl->sTitleBase);
152
153
        // append the page title
154
0
        BuilderPage* pCurrentPage = GetPage(getCurrentState());
155
0
        if ( pCurrentPage && !pCurrentPage->GetPageTitle().isEmpty() )
156
0
        {
157
0
            sCompleteTitle += " - " + pCurrentPage->GetPageTitle();
158
0
        }
159
160
0
        m_xAssistant->set_title(sCompleteTitle);
161
0
    }
162
163
    void WizardMachine::setTitleBase(const OUString& _rTitleBase)
164
0
    {
165
0
        m_pImpl->sTitleBase = _rTitleBase;
166
0
        implUpdateTitle();
167
0
    }
168
169
    OUString WizardMachine::getPageIdentForState(WizardTypes::WizardState nState) const
170
0
    {
171
0
        return OUString::number(nState);
172
0
    }
173
174
    WizardTypes::WizardState WizardMachine::getStateFromPageIdent(const OUString& rIdent) const
175
0
    {
176
0
        return rIdent.toInt32();
177
0
    }
178
179
    BuilderPage* WizardMachine::GetOrCreatePage( const WizardTypes::WizardState i_nState )
180
0
    {
181
0
        if ( nullptr == GetPage( i_nState ) )
182
0
        {
183
0
            std::unique_ptr<BuilderPage> xNewPage = createPage( i_nState );
184
0
            DBG_ASSERT( xNewPage, "WizardMachine::GetOrCreatePage: invalid new page (NULL)!" );
185
186
            // fill up the page sequence of our base class (with dummies)
187
0
            while ( m_pImpl->nFirstUnknownPage < i_nState )
188
0
            {
189
0
                AddPage( nullptr );
190
0
                ++m_pImpl->nFirstUnknownPage;
191
0
            }
192
193
0
            if ( m_pImpl->nFirstUnknownPage == i_nState )
194
0
            {
195
                // encountered this page number the first time
196
0
                AddPage(std::move(xNewPage));
197
0
                ++m_pImpl->nFirstUnknownPage;
198
0
            }
199
0
            else
200
                // already had this page - just change it
201
0
                SetPage(i_nState, std::move(xNewPage));
202
0
        }
203
0
        return GetPage( i_nState );
204
0
    }
205
206
    void WizardMachine::ActivatePage()
207
0
    {
208
0
        WizardTypes::WizardState nCurrentLevel = m_nCurState;
209
0
        GetOrCreatePage( nCurrentLevel );
210
211
0
        enterState( nCurrentLevel );
212
0
    }
213
214
    bool WizardMachine::DeactivatePage()
215
0
    {
216
0
        WizardTypes::WizardState nCurrentState = getCurrentState();
217
0
        return leaveState(nCurrentState);
218
0
    }
219
220
    void WizardMachine::defaultButton(WizardButtonFlags _nWizardButtonFlags)
221
0
    {
222
        // the new default button
223
0
        weld::Button* pNewDefButton = nullptr;
224
0
        if (_nWizardButtonFlags & WizardButtonFlags::FINISH)
225
0
            pNewDefButton = m_xFinish.get();
226
0
        if (_nWizardButtonFlags & WizardButtonFlags::NEXT)
227
0
            pNewDefButton = m_xNextPage.get();
228
0
        if (_nWizardButtonFlags & WizardButtonFlags::PREVIOUS)
229
0
            pNewDefButton = m_xPrevPage.get();
230
0
        if (_nWizardButtonFlags & WizardButtonFlags::HELP)
231
0
            pNewDefButton = m_xHelp.get();
232
0
        if (_nWizardButtonFlags & WizardButtonFlags::CANCEL)
233
0
            pNewDefButton = m_xCancel.get();
234
235
0
        defaultButton(pNewDefButton);
236
0
    }
237
238
    void WizardMachine::defaultButton(weld::Button* _pNewDefButton)
239
0
    {
240
        // loop through all (direct and indirect) descendants which participate in our tabbing order, and
241
        // reset the WB_DEFBUTTON for every window which is a button and set _pNewDefButton as the new
242
        // WB_DEFBUTTON
243
0
        m_xAssistant->change_default_button(nullptr, _pNewDefButton);
244
0
    }
245
246
    void WizardMachine::enableButtons(WizardButtonFlags _nWizardButtonFlags, bool _bEnable)
247
0
    {
248
0
        if (_nWizardButtonFlags & WizardButtonFlags::FINISH)
249
0
            m_xFinish->set_sensitive(_bEnable);
250
0
        if (_nWizardButtonFlags & WizardButtonFlags::NEXT)
251
0
            m_xNextPage->set_sensitive(_bEnable);
252
0
        if (_nWizardButtonFlags & WizardButtonFlags::PREVIOUS)
253
0
            m_xPrevPage->set_sensitive(_bEnable);
254
0
        if (_nWizardButtonFlags & WizardButtonFlags::HELP)
255
0
            m_xHelp->set_sensitive(_bEnable);
256
0
        if (_nWizardButtonFlags & WizardButtonFlags::CANCEL)
257
0
            m_xCancel->set_sensitive(_bEnable);
258
0
    }
259
260
    void WizardMachine::enterState(WizardTypes::WizardState _nState)
261
0
    {
262
        // tell the page
263
0
        IWizardPageController* pController = getPageController( GetPage( _nState ) );
264
0
        OSL_ENSURE( pController, "WizardMachine::enterState: no controller for the given page!" );
265
0
        if ( pController )
266
0
            pController->initializePage();
267
268
0
        if ( isAutomaticNextButtonStateEnabled() )
269
0
            enableButtons( WizardButtonFlags::NEXT, canAdvance() );
270
271
0
        enableButtons( WizardButtonFlags::PREVIOUS, !m_pImpl->aStateHistory.empty() );
272
273
        // set the new title - it depends on the current page (i.e. state)
274
0
        implUpdateTitle();
275
0
    }
276
277
    bool WizardMachine::leaveState(WizardTypes::WizardState)
278
0
    {
279
        // no need to ask the page here.
280
        // If we reach this point, we already gave the current page the chance to commit it's data,
281
        // and it was allowed to commit it's data
282
283
0
        return true;
284
0
    }
285
286
    bool WizardMachine::onFinish()
287
0
    {
288
0
        return Finish(RET_OK);
289
0
    }
290
291
    IMPL_LINK_NOARG(WizardMachine, OnFinish, weld::Button&, void)
292
0
    {
293
0
        if ( isTravelingSuspended() )
294
0
            return;
295
296
        // prevent WizardTravelSuspension from using this instance
297
        // after will be destructed due to onFinish and async response call
298
0
        {
299
0
            WizardTravelSuspension aTravelGuard( *this );
300
0
            if (!prepareLeaveCurrentState(WizardTypes::eFinish))
301
0
            {
302
0
                return;
303
0
            }
304
0
        }
305
306
0
        onFinish();
307
0
    }
308
309
    IMPL_LINK_NOARG(WizardMachine, OnCancel, weld::Button&, void)
310
0
    {
311
0
        m_xAssistant->response(RET_CANCEL);
312
0
    }
313
314
    WizardTypes::WizardState WizardMachine::determineNextState(WizardTypes::WizardState _nCurrentState ) const
315
0
    {
316
0
        return _nCurrentState + 1;
317
0
    }
318
319
    bool WizardMachine::prepareLeaveCurrentState( WizardTypes::CommitPageReason _eReason )
320
0
    {
321
0
        IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) );
322
0
        ENSURE_OR_RETURN( pController != nullptr, "WizardMachine::prepareLeaveCurrentState: no controller for the current page!", true );
323
0
        return pController->commitPage( _eReason );
324
0
    }
325
326
    bool WizardMachine::skipBackwardUntil(WizardTypes::WizardState _nTargetState)
327
0
    {
328
        // allowed to leave the current page?
329
0
        if ( !prepareLeaveCurrentState( WizardTypes::eTravelBackward ) )
330
0
            return false;
331
332
        // don't travel directly on m_pImpl->aStateHistory, in case something goes wrong
333
0
        std::stack< WizardTypes::WizardState > aTravelVirtually = m_pImpl->aStateHistory;
334
0
        std::stack< WizardTypes::WizardState > aOldStateHistory = m_pImpl->aStateHistory;
335
336
0
        WizardTypes::WizardState nCurrentRollbackState = getCurrentState();
337
0
        while ( nCurrentRollbackState != _nTargetState )
338
0
        {
339
0
            DBG_ASSERT( !aTravelVirtually.empty(), "WizardMachine::skipBackwardUntil: this target state does not exist in the history!" );
340
0
            nCurrentRollbackState = aTravelVirtually.top();
341
0
            aTravelVirtually.pop();
342
0
        }
343
0
        m_pImpl->aStateHistory = std::move(aTravelVirtually);
344
0
        if ( !ShowPage( _nTargetState ) )
345
0
        {
346
0
            m_pImpl->aStateHistory = std::move(aOldStateHistory);
347
0
            return false;
348
0
        }
349
0
        return true;
350
0
    }
351
352
    bool WizardMachine::skipUntil( WizardTypes::WizardState _nTargetState )
353
0
    {
354
0
        WizardTypes::WizardState nCurrentState = getCurrentState();
355
356
        // allowed to leave the current page?
357
0
        if ( !prepareLeaveCurrentState( nCurrentState < _nTargetState ? WizardTypes::eTravelForward : WizardTypes::eTravelBackward ) )
358
0
            return false;
359
360
        // don't travel directly on m_pImpl->aStateHistory, in case something goes wrong
361
0
        std::stack< WizardTypes::WizardState > aTravelVirtually = m_pImpl->aStateHistory;
362
0
        std::stack< WizardTypes::WizardState > aOldStateHistory = m_pImpl->aStateHistory;
363
0
        while ( nCurrentState != _nTargetState )
364
0
        {
365
0
            WizardTypes::WizardState nNextState = determineNextState( nCurrentState );
366
0
            if ( WZS_INVALID_STATE == nNextState )
367
0
            {
368
0
                OSL_FAIL( "WizardMachine::skipUntil: the given target state does not exist!" );
369
0
                return false;
370
0
            }
371
372
            // remember the skipped state in the history
373
0
            aTravelVirtually.push( nCurrentState );
374
375
            // get the next state
376
0
            nCurrentState = nNextState;
377
0
        }
378
0
        m_pImpl->aStateHistory = std::move(aTravelVirtually);
379
        // show the target page
380
0
        if ( !ShowPage( nCurrentState ) )
381
0
        {
382
            // argh! prepareLeaveCurrentPage succeeded, determineNextState succeeded,
383
            // but ShowPage doesn't? Somebody behaves very strange here...
384
0
            OSL_FAIL( "WizardMachine::skipUntil: very unpolite..." );
385
0
            m_pImpl->aStateHistory = std::move(aOldStateHistory);
386
0
            return false;
387
0
        }
388
0
        return true;
389
0
    }
390
391
    void WizardMachine::skip()
392
0
    {
393
        // allowed to leave the current page?
394
0
        if ( !prepareLeaveCurrentState( WizardTypes::eTravelForward ) )
395
0
            return;
396
397
0
        WizardTypes::WizardState nCurrentState = getCurrentState();
398
0
        WizardTypes::WizardState nNextState = determineNextState(nCurrentState);
399
400
0
        if (WZS_INVALID_STATE == nNextState)
401
0
            return;
402
403
        // remember the skipped state in the history
404
0
        m_pImpl->aStateHistory.push(nCurrentState);
405
406
        // get the next state
407
0
        nCurrentState = nNextState;
408
409
        // show the (n+1)th page
410
0
        if (!ShowPage(nCurrentState))
411
0
        {
412
            // TODO: this leaves us in a state where we have no current page and an inconsistent state history.
413
            // Perhaps we should rollback the skipping here...
414
0
            OSL_FAIL("WizardMachine::skip: very unpolite...");
415
                // if somebody does a skip and then does not allow to leave...
416
                // (can't be a commit error, as we've already committed the current page. So if ShowPage fails here,
417
                // somebody behaves really strange ...)
418
0
            return;
419
0
        }
420
421
        // all fine
422
0
    }
423
424
    bool WizardMachine::travelNext()
425
0
    {
426
        // allowed to leave the current page?
427
0
        if ( !prepareLeaveCurrentState( WizardTypes::eTravelForward ) )
428
0
            return false;
429
430
        // determine the next state to travel to
431
0
        WizardTypes::WizardState nCurrentState = getCurrentState();
432
0
        WizardTypes::WizardState nNextState = determineNextState(nCurrentState);
433
0
        if (WZS_INVALID_STATE == nNextState)
434
0
            return false;
435
436
        // the state history is used by the enterState method
437
        // all fine
438
0
        m_pImpl->aStateHistory.push(nCurrentState);
439
0
        if (!ShowPage(nNextState))
440
0
        {
441
0
            m_pImpl->aStateHistory.pop();
442
0
            return false;
443
0
        }
444
445
0
        return true;
446
0
    }
447
448
    bool WizardMachine::ShowPage(WizardTypes::WizardState nState)
449
0
    {
450
0
        if (DeactivatePage())
451
0
        {
452
0
            BuilderPage* pOldTabPage = m_pCurTabPage;
453
454
0
            m_nCurState = nState;
455
0
            ActivatePage();
456
457
0
            if (pOldTabPage)
458
0
                pOldTabPage->Deactivate();
459
460
0
            m_xAssistant->set_current_page(getPageIdentForState(nState));
461
462
0
            m_pCurTabPage = GetPage(m_nCurState);
463
0
            m_pCurTabPage->Activate();
464
465
0
            return true;
466
0
        }
467
0
        return false;
468
0
    }
469
470
    bool WizardMachine::ShowNextPage()
471
0
    {
472
0
        return ShowPage(m_nCurState + 1);
473
0
    }
474
475
    bool WizardMachine::ShowPrevPage()
476
0
    {
477
0
        if (!m_nCurState)
478
0
            return false;
479
0
        return ShowPage(m_nCurState - 1);
480
0
    }
481
482
    bool WizardMachine::travelPrevious()
483
0
    {
484
0
        DBG_ASSERT(!m_pImpl->aStateHistory.empty(), "WizardMachine::travelPrevious: have no previous page!");
485
486
        // allowed to leave the current page?
487
0
        if ( !prepareLeaveCurrentState( WizardTypes::eTravelBackward ) )
488
0
            return false;
489
490
        // the next state to switch to
491
0
        WizardTypes::WizardState nPreviousState = m_pImpl->aStateHistory.top();
492
493
        // the state history is used by the enterState method
494
0
        m_pImpl->aStateHistory.pop();
495
        // show this page
496
0
        if (!ShowPage(nPreviousState))
497
0
        {
498
0
            m_pImpl->aStateHistory.push(nPreviousState);
499
0
            return false;
500
0
        }
501
502
        // all fine
503
0
        return true;
504
0
    }
505
506
507
    void  WizardMachine::removePageFromHistory( WizardTypes::WizardState nToRemove )
508
0
    {
509
510
0
        std::stack< WizardTypes::WizardState > aTemp;
511
0
        while(!m_pImpl->aStateHistory.empty())
512
0
        {
513
0
            WizardTypes::WizardState nPreviousState = m_pImpl->aStateHistory.top();
514
0
            m_pImpl->aStateHistory.pop();
515
0
            if(nPreviousState != nToRemove)
516
0
                aTemp.push( nPreviousState );
517
0
            else
518
0
                break;
519
0
        }
520
0
        while(!aTemp.empty())
521
0
        {
522
0
            m_pImpl->aStateHistory.push( aTemp.top() );
523
0
            aTemp.pop();
524
0
        }
525
0
    }
526
527
528
    void WizardMachine::enableAutomaticNextButtonState()
529
0
    {
530
0
        m_pImpl->m_bAutoNextButtonState = true;
531
0
    }
532
533
534
    bool WizardMachine::isAutomaticNextButtonStateEnabled() const
535
0
    {
536
0
        return m_pImpl->m_bAutoNextButtonState;
537
0
    }
538
539
    IMPL_LINK_NOARG(WizardMachine, OnPrevPage, weld::Button&, void)
540
0
    {
541
0
        if ( isTravelingSuspended() )
542
0
            return;
543
0
        WizardTravelSuspension aTravelGuard( *this );
544
0
        travelPrevious();
545
0
    }
546
547
    IMPL_LINK_NOARG(WizardMachine, OnNextPage, weld::Button&, void)
548
0
    {
549
0
        if ( isTravelingSuspended() )
550
0
            return;
551
0
        WizardTravelSuspension aTravelGuard( *this );
552
0
        travelNext();
553
0
    }
554
555
    IWizardPageController* WizardMachine::getPageController(BuilderPage* pCurrentPage) const
556
0
    {
557
0
        IWizardPageController* pController = dynamic_cast<IWizardPageController*>(pCurrentPage);
558
0
        return pController;
559
0
    }
560
561
    void WizardMachine::getStateHistory( std::vector< WizardTypes::WizardState >& _out_rHistory )
562
0
    {
563
0
        std::stack< WizardTypes::WizardState > aHistoryCopy( m_pImpl->aStateHistory );
564
0
        while ( !aHistoryCopy.empty() )
565
0
        {
566
0
            _out_rHistory.push_back( aHistoryCopy.top() );
567
0
            aHistoryCopy.pop();
568
0
        }
569
0
    }
570
571
    bool WizardMachine::canAdvance() const
572
0
    {
573
0
        return WZS_INVALID_STATE != determineNextState( getCurrentState() );
574
0
    }
575
576
    void WizardMachine::updateTravelUI()
577
0
    {
578
0
        const IWizardPageController* pController = getPageController( GetPage( getCurrentState() ) );
579
0
        OSL_ENSURE( pController != nullptr, "WizardMachine::updateTravelUI: no controller for the current page!" );
580
581
0
        bool bCanAdvance =
582
0
                ( !pController || pController->canAdvance() )   // the current page allows to advance
583
0
            &&  canAdvance();                                   // the dialog as a whole allows to advance
584
0
        enableButtons( WizardButtonFlags::NEXT, bCanAdvance );
585
0
    }
586
587
    bool WizardMachine::isTravelingSuspended() const
588
0
    {
589
0
        return m_pImpl->m_bTravelingSuspended;
590
0
    }
591
592
    void WizardMachine::suspendTraveling( AccessGuard )
593
0
    {
594
0
        DBG_ASSERT( !m_pImpl->m_bTravelingSuspended, "WizardMachine::suspendTraveling: already suspended!" );
595
0
        m_pImpl->m_bTravelingSuspended = true;
596
0
    }
597
598
    void WizardMachine::resumeTraveling( AccessGuard )
599
0
    {
600
0
        if (!m_pImpl)
601
0
            return;
602
603
0
        DBG_ASSERT( m_pImpl->m_bTravelingSuspended, "WizardMachine::resumeTraveling: nothing to resume!" );
604
0
        m_pImpl->m_bTravelingSuspended = false;
605
0
    }
606
607
    bool WizardMachine::Finish(short nResult)
608
0
    {
609
0
        if ( DeactivatePage() )
610
0
        {
611
0
            if (m_pCurTabPage)
612
0
                m_pCurTabPage->Deactivate();
613
614
0
            m_xAssistant->response(nResult);
615
0
            return true;
616
0
        }
617
0
        else
618
0
            return false;
619
0
    }
620
621
    void WizardMachine::AddPage(std::unique_ptr<BuilderPage> xPage)
622
0
    {
623
0
        WizPageData* pNewPageData = new WizPageData;
624
0
        pNewPageData->mpNext = nullptr;
625
0
        pNewPageData->mxPage = std::move(xPage);
626
627
0
        if ( !m_pFirstPage )
628
0
            m_pFirstPage = pNewPageData;
629
0
        else
630
0
        {
631
0
            WizPageData* pPageData = m_pFirstPage;
632
0
            while ( pPageData->mpNext )
633
0
                pPageData = pPageData->mpNext;
634
0
            pPageData->mpNext = pNewPageData;
635
0
        }
636
0
    }
637
638
    void WizardMachine::RemovePage(const BuilderPage* pPage)
639
0
    {
640
0
        WizPageData* pPrevPageData = nullptr;
641
0
        WizPageData* pPageData = m_pFirstPage;
642
0
        while ( pPageData )
643
0
        {
644
0
            if (pPageData->mxPage.get() == pPage)
645
0
            {
646
0
                if (pPrevPageData)
647
0
                    pPrevPageData->mpNext = pPageData->mpNext;
648
0
                else
649
0
                    m_pFirstPage = pPageData->mpNext;
650
0
                if (pPage == m_pCurTabPage)
651
0
                    m_pCurTabPage = nullptr;
652
0
                delete pPageData;
653
0
                return;
654
0
            }
655
656
0
            pPrevPageData = pPageData;
657
0
            pPageData = pPageData->mpNext;
658
0
        }
659
660
0
        OSL_FAIL( "WizardMachine::RemovePage() - Page not in list" );
661
0
    }
662
663
    void WizardMachine::SetPage(WizardTypes::WizardState nLevel, std::unique_ptr<BuilderPage> xPage)
664
0
    {
665
0
        sal_uInt16              nTempLevel = 0;
666
0
        WizPageData*    pPageData = m_pFirstPage;
667
0
        while ( pPageData )
668
0
        {
669
0
            if ( (nTempLevel == nLevel) || !pPageData->mpNext )
670
0
                break;
671
672
0
            nTempLevel++;
673
0
            pPageData = pPageData->mpNext;
674
0
        }
675
676
0
        if ( pPageData )
677
0
        {
678
0
            if (pPageData->mxPage.get() == m_pCurTabPage)
679
0
                m_pCurTabPage = nullptr;
680
0
            pPageData->mxPage = std::move(xPage);
681
0
        }
682
0
    }
683
684
    BuilderPage* WizardMachine::GetPage(WizardTypes::WizardState nLevel) const
685
0
    {
686
0
        sal_uInt16 nTempLevel = 0;
687
688
0
        for (WizPageData* pPageData = m_pFirstPage; pPageData;
689
0
             pPageData = pPageData->mpNext)
690
0
        {
691
0
            if ( nTempLevel == nLevel )
692
0
                return pPageData->mxPage.get();
693
0
            nTempLevel++;
694
0
        }
695
696
0
        return nullptr;
697
0
    }
698
}   // namespace svt
699
700
701
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */