source: tags/ms_r18q1/CORE/arb_progress.h

Last change on this file was 16763, checked in by westram, 6 years ago
File size: 8.8 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : arb_progress.h                                     //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in November 2010   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11
12#ifndef ARB_PROGRESS_H
13#define ARB_PROGRESS_H
14
15#ifndef ARB_ASSERT_H
16#include <arb_assert.h>
17#endif
18#ifndef ARB_ERROR_H
19#include <arb_error.h>
20#endif
21#ifndef ARBTOOLS_H
22#include <arbtools.h>
23#endif
24
25#if defined(DEBUG)
26#define TEST_COUNTERS
27#if defined(DEVEL_RALF)
28#define DUMP_PROGRESS
29#endif
30#endif
31
32
33class  arb_parent_progress;
34struct arb_status_implementation;
35
36class arb_progress_counter : virtual Noncopyable {
37protected:
38    arb_parent_progress *progress;
39public:
40    arb_progress_counter(arb_parent_progress *progress_)
41        : progress(progress_)
42    {}
43    virtual ~arb_progress_counter() {}
44
45    virtual void inc()                              = 0;
46    virtual void implicit_inc()                     = 0;
47    virtual void inc_to(int x)                      = 0;
48    virtual void child_updates_gauge(double gauge)  = 0;
49    virtual void done()                             = 0;
50    virtual void force_update()                     = 0;
51    virtual void restart(int overall_count)         = 0;
52    virtual void auto_subtitles(const char *prefix) = 0;
53    virtual bool has_auto_subtitles()               = 0;
54
55#if defined(DUMP_PROGRESS)
56    virtual void dump() = 0;
57#endif
58
59    virtual arb_progress_counter *clone(arb_parent_progress *parent, int overall_count) const = 0;
60};
61
62const int LEVEL_TITLE    = 0;
63const int LEVEL_SUBTITLE = 1;
64
65class arb_parent_progress : virtual Noncopyable {
66    arb_parent_progress *prev_recent;
67    bool                 reuse_allowed; // display may be reused by childs
68
69protected:
70#if defined(DUMP_PROGRESS)
71    char *name;
72#endif
73   
74    bool                  has_title;
75    arb_progress_counter *counter;
76
77    static arb_parent_progress       *recent;
78    static arb_status_implementation *impl; // defines implementation to display status
79
80    virtual SmartPtr<arb_parent_progress> create_child_progress(const char *title, int overall_count) = 0;
81
82    arb_parent_progress(arb_progress_counter *counter_, bool has_title_) 
83        : reuse_allowed(false),
84          has_title(has_title_),
85          counter(counter_)
86    {
87        prev_recent = recent;
88        recent      = this;
89       
90#if defined(DUMP_PROGRESS)
91        name = NULp;
92#endif
93
94#if defined(TEST_COUNTERS)
95        accept_invalid_counters = false;
96#endif
97    }
98public:
99#if defined(TEST_COUNTERS)
100    bool accept_invalid_counters; // if true, do not complain about unfinished counters
101#endif
102
103    virtual ~arb_parent_progress() {
104        delete counter;
105        recent = prev_recent;
106#if defined(DUMP_PROGRESS)
107        free(name);
108#endif
109    }
110
111    static SmartPtr<arb_parent_progress> create(const char *title, int overall_count);
112    static SmartPtr<arb_parent_progress> create_suppressor();
113
114    virtual bool aborted() const                       = 0;
115    virtual void set_text(int level, const char *text) = 0;
116    virtual void update_gauge(double gauge)            = 0;
117
118#if defined(DUMP_PROGRESS)
119    virtual void dump();
120#endif
121
122    void child_sets_text(int level, const char *text) {
123        set_text(level+1-reuse_allowed+counter->has_auto_subtitles(), text);
124    }
125    void allow_title_reuse() { reuse_allowed = true; }
126
127    void child_updates_gauge(double gauge) { counter->child_updates_gauge(gauge); }
128    void child_terminated() { counter->implicit_inc(); }
129
130    arb_progress_counter *clone_counter(int overall_count) { return counter->clone(this, overall_count); }
131    void initial_update() { counter->force_update(); }
132    void force_update() { counter->force_update(); }
133
134    void inc() { counter->inc(); }
135    void inc_to(int x) { counter->inc_to(x); }
136    void done() { counter->done(); }
137    void auto_subtitles(const char *prefix) { counter->auto_subtitles(prefix); }
138
139    static void show_comment(const char *comment) {
140        if (recent) recent->set_text(LEVEL_SUBTITLE, comment);
141    }
142};
143
144class arb_progress {
145    SmartPtr<arb_parent_progress> used;
146
147    void setup(const char *title, int overall_count) {
148        used = arb_parent_progress::create(title, overall_count);
149        used->initial_update();
150    }
151    // cppcheck-suppress functionConst
152    void accept_invalid_counters() {
153#if defined(TEST_COUNTERS)
154        used->accept_invalid_counters = true;
155#endif
156    }
157
158public:
159    // ------------------------------
160    // recommended interface:
161
162    arb_progress(const char *title, int overall_count) {
163        // open a progress indicator
164        //
165        // expects to be incremented 'overall_count' times
166        //      incrementation is done either
167        //      - explicitly by calling one of the inc...()-functions below or
168        //      - implicitely by creating another arb_progress while this one remains
169        //
170        // if you can't ahead-determine the exact number of incrementations,
171        // specify an upper-limit and call .done() before dtor.
172
173        arb_assert(overall_count >= 0);
174        setup(title, overall_count);
175    }
176    explicit arb_progress(const char *title) {
177        // open a wrapping progress indicator
178        //
179        // expects NOT to be incremented explicitly!
180        //      if arb_progresses are created while this exists, they reuse the progress window.
181        //      Useful to avoid spamming the user with numerous popping-up progress windows.
182        setup(title, 0);
183    }
184    explicit arb_progress(int overall_count) {
185        // open counting progress (reuses text of parent progress).
186        //
187        // Useful to separate text- from gauge-display or
188        // to summarize several consecutive child-progresses into one.
189        setup(NULp, overall_count);
190    }
191    arb_progress() {
192        // plain wrapper (avoids multiple implicit increments of its parent).
193        //
194        // usage-conditions:
195        // * caller increments progress in a loop and
196        // * loop calls one or more callees and callees open multiple progress bars.
197        //
198        // in this case the parent progress would be implicitely incremented several times
199        // per loop, resulting in wrong gauge.
200        //
201        // if you know the number of opened progresses, use arb_progress(int),
202        // otherwise add one wrapper-progress into the loop.
203        setup(NULp, 0);
204    }
205
206    void allow_title_reuse() { used->allow_title_reuse(); }
207
208    void subtitle(const char *stitle) { used->set_text(LEVEL_SUBTITLE, stitle); }
209
210    GB_ERROR error_if_aborted() {
211        return aborted() ? "Operation aborted on user request" : NULp;
212    }
213
214    GB_ERROR inc_and_error_if_aborted() {
215        inc();
216        return error_if_aborted();
217    }
218
219    void inc_and_check_user_abort(GB_ERROR& error)  { if (!error) error = inc_and_error_if_aborted(); else accept_invalid_counters(); }
220    void inc_and_check_user_abort(ARB_ERROR& error) { if (!error) error = inc_and_error_if_aborted(); else accept_invalid_counters(); }
221
222    bool aborted() {
223        // true if user pressed "Abort"
224        bool aborted_ = used->aborted();
225#if defined(TEST_COUNTERS)
226        if (aborted_) accept_invalid_counters();
227#endif
228        return aborted_;
229    }
230
231    void auto_subtitles(const char *prefix) {
232        // automatically update subtitles ("prefix #/#")
233        // prefix = NULp -> switch off
234        used->auto_subtitles(prefix);
235    }
236    static void show_comment(const char *comment) {
237        // Like subtitle(), but w/o needing to know anything about a eventually open progress
238        // e.g. used to show ARB is connecting to ptserver
239        arb_parent_progress::show_comment(comment);
240    }
241   
242    // ------------------------------
243    // less recommended interface:
244
245    void inc() { used->inc(); } // increment progress
246    const arb_progress& operator++() { inc(); return *this; } // ++progress
247
248    void inc_by(int count) { arb_assert(count>0); while (count--) inc(); }
249    void inc_to(int x) { used->inc_to(x); }
250
251    void sub_progress_skipped() { used->child_terminated(); }
252
253    void done() { used->done(); } // set "done" (aka 100%). Useful when exiting some loop early
254#if defined(DUMP_PROGRESS)
255    void dump();
256#endif
257    void force_update() { used->force_update(); }
258};
259
260class arb_suppress_progress {
261    SmartPtr<arb_parent_progress> suppressor;
262public:
263    arb_suppress_progress()
264        : suppressor(arb_parent_progress::create_suppressor())
265    {}
266};
267
268#else
269#error arb_progress.h included twice
270#endif // ARB_PROGRESS_H
Note: See TracBrowser for help on using the repository browser.