LibreOffice Module sc (master)  1
fprogressbar.cxx
Go to the documentation of this file.
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 <fprogressbar.hxx>
21 #include <globstr.hrc>
22 #include <scresid.hxx>
23 #include <progress.hxx>
24 #include <osl/diagnose.h>
25 #include <tools/stream.hxx>
26 
27 #include <climits>
28 
30  mnSize( nSize ),
31  mnPos( 0 )
32 {
33 }
34 
36 {
37 }
38 
39 ScfProgressBar::ScfProgressBar( SfxObjectShell* pDocShell, const OUString& rText ) :
40  maText( rText )
41 {
42  Init( pDocShell );
43 }
44 
45 ScfProgressBar::ScfProgressBar(SfxObjectShell* pDocShell, const char* pResId)
46  : maText(ScResId(pResId))
47 {
48  Init( pDocShell );
49 }
50 
52 {
53  Init( rParProgress.mpDocShell );
54  mpParentProgress = &rParProgress;
55  mpParentSegment = pParSegment;
56 }
57 
59 {
60 }
61 
63 {
64  mpDocShell = pDocShell;
65  mpParentProgress = nullptr;
66  mpParentSegment = mpCurrSegment = nullptr;
68  mnSysProgressScale = 1; // used to workaround the ULONG_MAX/100 limit
69  mbInProgress = false;
70 }
71 
73 {
74  if( nSegment < 0 )
75  return nullptr;
76  return maSegments.at( nSegment ).get();
77 }
78 
80 {
81  if( mpCurrSegment != pSegment )
82  {
83  mpCurrSegment = pSegment;
84 
86  {
88  }
89  else if( !mxSysProgress && (mnTotalSize > 0) )
90  {
91  // System progress has an internal limit of ULONG_MAX/100.
93  sal_uLong nSysTotalSize = static_cast< sal_uLong >( mnTotalSize );
94  while( nSysTotalSize >= ULONG_MAX / 100 )
95  {
96  nSysTotalSize /= 2;
97  mnSysProgressScale *= 2;
98  }
99  mxSysProgress.reset( new ScProgress( mpDocShell, maText, nSysTotalSize, true ) );
100  }
101 
102  if( !mbInProgress && mpCurrSegment && (mnTotalSize > 0) )
103  {
104  mnUnitSize = mnTotalSize / 256 + 1; // at most 256 calls of system progress
105  mnNextUnitPos = 0;
106  mbInProgress = true;
107  }
108  }
109 }
110 
111 void ScfProgressBar::IncreaseProgressBar( std::size_t nDelta )
112 {
113  std::size_t nNewPos = mnTotalPos + nDelta;
114 
115  // call back to parent progress bar
117  {
118  // calculate new position of parent progress bar
119  std::size_t nParentPos = static_cast< std::size_t >(
120  static_cast< double >( nNewPos ) * mpParentSegment->mnSize / mnTotalSize );
121  mpParentProgress->ProgressAbs( nParentPos );
122  }
123  // modify system progress bar
124  else if( mxSysProgress )
125  {
126  if( nNewPos >= mnNextUnitPos )
127  {
128  mnNextUnitPos = nNewPos + mnUnitSize;
129  mxSysProgress->SetState( static_cast< sal_uLong >( nNewPos / mnSysProgressScale ) );
130  }
131  }
132  else
133  {
134  OSL_FAIL( "ScfProgressBar::IncreaseProgressBar - no progress bar found" );
135  }
136 
137  mnTotalPos = nNewPos;
138 }
139 
140 sal_Int32 ScfProgressBar::AddSegment( std::size_t nSize )
141 {
142  OSL_ENSURE( !mbInProgress, "ScfProgressBar::AddSegment - already in progress mode" );
143  if( nSize == 0 )
144  return SCF_INV_SEGMENT;
145 
146  maSegments.push_back( std::make_unique<ScfProgressSegment>( nSize ) );
147  mnTotalSize += nSize;
148  return static_cast< sal_Int32 >( maSegments.size() - 1 );
149 }
150 
152 {
153  ScfProgressSegment* pSegment = GetSegment( nSegment );
154  OSL_ENSURE( !pSegment || (pSegment->mnPos == 0), "ScfProgressBar::GetSegmentProgressBar - segment already started" );
155  if( pSegment && (pSegment->mnPos == 0) )
156  {
157  if( !pSegment->mxProgress )
158  pSegment->mxProgress.reset( new ScfProgressBar( *this, pSegment ) );
159  return *pSegment->mxProgress;
160  }
161  return *this;
162 }
163 
165 {
166  OSL_ENSURE( mbInProgress && mpCurrSegment, "ScfProgressBar::IsFull - no segment started" );
168 }
169 
170 void ScfProgressBar::ActivateSegment( sal_Int32 nSegment )
171 {
172  OSL_ENSURE( mnTotalSize > 0, "ScfProgressBar::ActivateSegment - progress range is zero" );
173  if( mnTotalSize > 0 )
174  SetCurrSegment( GetSegment( nSegment ) );
175 }
176 
177 void ScfProgressBar::ProgressAbs( std::size_t nPos )
178 {
179  OSL_ENSURE( mbInProgress && mpCurrSegment, "ScfProgressBar::ProgressAbs - no segment started" );
180  if( mpCurrSegment )
181  {
182  OSL_ENSURE( mpCurrSegment->mnPos <= nPos, "ScfProgressBar::ProgressAbs - delta pos < 0" );
183  OSL_ENSURE( nPos <= mpCurrSegment->mnSize, "ScfProgressBar::ProgressAbs - segment overflow" );
184  if( (mpCurrSegment->mnPos < nPos) && (nPos <= mpCurrSegment->mnSize) )
185  {
187  mpCurrSegment->mnPos = nPos;
188  }
189  }
190 }
191 
192 void ScfProgressBar::Progress( std::size_t nDelta )
193 {
194  ProgressAbs( mpCurrSegment ? (mpCurrSegment->mnPos + nDelta) : 0 );
195 }
196 
197 ScfSimpleProgressBar::ScfSimpleProgressBar( std::size_t nSize, SfxObjectShell* pDocShell, const OUString& rText ) :
198  maProgress( pDocShell, rText )
199 {
200  Init( nSize );
201 }
202 
203 ScfSimpleProgressBar::ScfSimpleProgressBar(std::size_t nSize, SfxObjectShell* pDocShell, const char* pResId)
204  : maProgress(pDocShell, pResId)
205 {
206  Init( nSize );
207 }
208 
209 void ScfSimpleProgressBar::Init( std::size_t nSize )
210 {
211  sal_Int32 nSegment = maProgress.AddSegment( nSize );
212  if( nSegment >= 0 )
213  maProgress.ActivateSegment( nSegment );
214 }
215 
217  mrStrm( rStrm )
218 {
219  Init( pDocShell, ScResId( STR_LOAD_DOC ) );
220 }
221 
223 {
224  mxProgress->ProgressAbs( mrStrm.Tell() );
225 }
226 
227 void ScfStreamProgressBar::Init( SfxObjectShell* pDocShell, const OUString& rText )
228 {
229  sal_uInt64 const nSize = mrStrm.TellEnd();
230  mxProgress.reset( new ScfSimpleProgressBar( nSize, pDocShell, rText ) );
231  Progress();
232 }
233 
234 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void ActivateSegment(sal_Int32 nSegment)
Starts the progress bar or activates another segment.
ScfProgressSegment * mpCurrSegment
Parent segment, if this is a segment progress bar.
ScfSimpleProgressBarPtr mxProgress
ScProgressPtr mxSysProgress
UI string for system progress.
ScfProgressBar maProgress
std::size_t mnSysProgressScale
Limit for next system progress call.
std::size_t mnNextUnitPos
Size between two calls of system progress.
ScfStreamProgressBar(SvStream &rStrm, SfxObjectShell *pDocShell)
virtual sal_uInt64 TellEnd()
A simplified progress bar with only one segment.
sal_uIntPtr sal_uLong
SfxObjectShell * mpDocShell
System progress bar.
std::size_t mnTotalSize
Current segment for progress.
ScfProgressBar * mpParentProgress
The document shell for the progress bar.
void IncreaseProgressBar(std::size_t nDelta)
Increases mnTotalPos and calls the system progress bar.
ScfProgressSegment * mpParentSegment
Parent progress bar, if this is a segment progress bar.
ScfProgressBar(const ScfProgressBar &)=delete
std::size_t mnUnitSize
Sum of positions of all segments.
ScfProgressBar & GetSegmentProgressBar(sal_Int32 nSegment)
Returns a complete progress bar for the specified segment.
OUString maText
List of progress segments.
bool IsFull() const
Returns true, if the current progress segment is already full.
ScfSegmentList maSegments
bool mbInProgress
Additionally scaling factor for system progress.
const sal_Int32 SCF_INV_SEGMENT
ScfProgressSegment * GetSegment(sal_Int32 nSegment)
Returns the segment specified by list index.
void Progress(std::size_t nDelta=1)
Increase current segment by the passed value.
Contains all data of a segment of the progress bar.
Any maProgress
void Init(SfxObjectShell *pDocShell)
Initializes all members on construction.
std::size_t mnPos
Size of this segment.
void Init(SfxObjectShell *pDocShell, const OUString &rText)
Initializes and starts the progress bar.
std::size_t mnTotalPos
Total size of all segments.
OUString ScResId(const char *pId)
Definition: scdll.cxx:95
std::size_t mnSize
Pointer to sub progress bar for this segment.
void Progress()
Sets the progress bar to the current stream position.
Progress bar for complex progress representation.
Text maText
sal_uInt64 Tell() const
void ProgressAbs(std::size_t nPos)
Set current segment to the specified absolute position.
ScfProgressSegment(std::size_t nSize)
Current position of this segment.
void SetCurrSegment(ScfProgressSegment *pSegment)
Activates progress bar and sets current segment.
ScfSimpleProgressBar(std::size_t nSize, SfxObjectShell *pDocShell, const OUString &rText)
sal_Int32 AddSegment(std::size_t nSize)
Adds a new segment to the progress bar.
SvStream & mrStrm
The used progress bar.
sal_uInt32 mnSize
void Init(std::size_t nSize)
Initializes and starts the progress bar.