File: sequencer.hpp

package info (click to toggle)
sight 25.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 42,184 kB
  • sloc: cpp: 289,476; xml: 17,257; ansic: 9,878; python: 1,379; sh: 144; makefile: 33
file content (281 lines) | stat: -rw-r--r-- 11,052 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/************************************************************************
 *
 * Copyright (C) 2016-2025 IRCAD France
 * Copyright (C) 2016-2021 IHU Strasbourg
 *
 * This file is part of Sight.
 *
 * Sight is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Sight is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with Sight. If not, see <https://www.gnu.org/licenses/>.
 *
 ***********************************************************************/

#pragma once

#include <activity/sequencer.hpp>

#include <data/activity_set.hpp>
#include <data/boolean.hpp>

#include <ui/__/editor.hpp>

#include <QButtonGroup>
#include <QPointer>

namespace sight::module::ui::qt::activity
{

/**
 * @brief This editor displays an activity stepper that allows to select the activity to launch, and display the
 * current selection
 *
 * The order of the activities is given in the configuration.
 *
 * Activity are created for each activity using the data produced by the previous activities. This activities are
 * stored in the current ActivitySet. By default all the data are stored, you can to backward and forward as you want in
 * the existing activities. Using the tag 'clearActivities', you can remove the last activities when going backward to
 * force the user to re-generate the data.
 *
 * @warning If an activity can not be launched with the existing parameters, the signal 'dataRequired' is emitted. It
 * can be connected to an activity wizard to add the missing data, or you can supplied 'requirementOverrides' map.
 *
 * @note If the inout ActivitySet already contains activities, their are parsed and the sequencer open on the last
 * activities. Be careful to store them in the right order.
 *
 * @section Signal Signal
 * - \b activity_created(data::activity::sptr) : This signal is emitted when an activity is created (using
 *   next() or previous().
 * - \b data_required() : This signal is emitted when the activity can not be launch because it requires data.
 * - \b hasNext(bool): This signal is emitted on sendInfo() slot, with the information if an activity is present after
 * the current one.
 * - \b hasPrevious(bool): This signal is emitted on sendInfo() slot, with the information if an activity is present
 * before the current one.
 * - \b nextEnabled(bool): This signal is emitted when the next button is enabled and can be launched.
 *
 * @section Slots Slots
 * - \b next() : Create the next activity
 * - \b previous() : Create the next activity
 * - \b go_to(std::string) : If enabled, switch to the given activity
 * - \b send_info() : Send the 'hasNext' and 'hasPrevious' signals for the current activity
 * - \b reset_requirements() : Reset requirements that have been created by the activity
 *
 * @section XML XML Configuration
 * @code{.xml}
    <service  type="sight::module::ui::qt::activity::sequencer">
        <inout key="activitySet" uid=""  auto_connect="true" />
        <activity id="..." name="..." />
        <activity id="..." name="..." />
        <activity id="..." name="..." />
        <clearActivities>false</clearActivities>
        <buttonWidth>200</buttonWidth>
        <fontSize>12</fontSize>
    </service>
   @endcode
 * @subsection In In
 * - \b requirementOverrides [sight::data::map] (optional): provide some data that will be passed as activity
 *   requirements. Can be used to supply required data that cannot be created by the activity, or to override
 *   data that would normally be passed from an activity to the next.
 *
 * @subsection In-Out In-Out
 * - \b activity_set [sight::data::activity_set]: used to store the Activity of the managed activities
 *
 * @subsection Configuration Configuration
 * - \b activity :
 *     - \b id: id of the activities to launch. The first activity in the list is the first that will be launched.
 *     - \b name(optional): name of the activity to display in the editor. If it is empty, the the activity's will be
 *          used
 * - \b clearActivities (optional, default: false): defines if the activities and their requirements should be removed
 * when going backward.
 * - \b buttonWidth (optional): the width of the buttons of the sequencer.
 * - \b fontSize (optional): the size of the font used in the buttons of the sequencer.
 *
 * @todo listen the current activity data to notify when the next activity can be created
 */
class sequencer : public QObject,
                  public sight::ui::editor,
                  public sight::activity::sequencer
{
Q_OBJECT

public:

    SIGHT_DECLARE_SERVICE(sequencer, sight::ui::editor);

    /// Initialize signals and slots
    sequencer() noexcept;

    /// Destructor. Do nothing.
    ~sequencer() noexcept override = default;

    struct slots final
    {
        using key_t = sight::core::com::slots::key_t;

        inline static const key_t GO_TO         = "go_to";
        inline static const key_t CHECK_NEXT    = "check_next";
        inline static const key_t VALIDATE_NEXT = "validate_next";
        inline static const key_t NEXT          = "next";
        inline static const key_t PREVIOUS      = "previous";
        inline static const key_t SEND_INFO     = "send_info";

        inline static const key_t RESET_REQUIREMENTS = "reset_requirements";

        inline static const key_t ENABLE_USER_WARNING  = "enable_user_warning";
        inline static const key_t DISABLE_USER_WARNING = "disable_user_warning";
        inline static const key_t SET_USER_WARNING     = "set_user_warning";
    };

    struct signals final
    {
        using key_t = sight::core::com::signals::key_t;

        inline static const key_t ACTIVITY_CREATED = "activity_created";
        inline static const key_t DATA_REQUIRED    = "data_required";
        inline static const key_t HAS_PREVIOUS     = "hasPrevious";
        inline static const key_t HAS_NEXT         = "hasNext";
        inline static const key_t NEXT_ENABLED     = "nextEnabled";

        inline static const key_t NEXT_VALIDATED = "next_validated";
        inline static const key_t NEXT_VALID     = "next_valid";
        inline static const key_t NEXT_INVALID   = "next_invalid";

        using void_signal_t     = core::com::signal<void ()>;
        using bool_signal_t     = core::com::signal<void (bool)>;
        using activity_signal_t = core::com::signal<void (data::activity::sptr)>;
    };

    /// Slot: Check if the next activities can be enabled
    void check_next();

    /// Slot: Validate the next activities without enabling it. Emits nextValidated(true/false), next(In)Valid signals
    void validate_next();

    /// Slot: Create the next activity, emit 'dataRequired' signal if the activity require additional data
    void next();

    /// Slot: Create the previous activity, emit 'dataRequired' signal if the activity require additional data
    void previous();

    /// Slot: Send the 'hasNext' and 'enablePrevious' signals for the current activity
    void send_info() const;

    // Slot: Reset requirements of activities
    using sight::activity::sequencer::reset_requirements;

    /// Slot: Enables the user warning dialog about possible loss of un-validated data
    /// Does nothing if "warning_message" wasn't configured.
    void enable_user_warning();

    /// Slot: Disables the user warning dialog about possible loss of un-validated data
    /// Does nothing if "warning_message" wasn't configured.
    void disable_user_warning();

    /// Slot: Configures the user warning according to _state value.
    /// Does nothing if "warning_message" wasn't configured.
    void set_user_warning(bool _state);

public Q_SLOTS:

    /// Create the activity at the given index, emit 'dataRequired' signal if the activity require additional data
    void go_to_index(int _index);

protected:

    /// Parses the configuration
    void configuring() override;

    /// Create the sequencer widgets: launch Qml file
    void starting() override;

    /// Destroy the container
    void stopping() override;

    /**
     * @brief Analyse the contained in the current activity_set.
     *
     * - if the is an unknown activity, it is removed
     * - else, the activity data is stored in m_requirements
     * - the last activity is launched
     */
    void updating() override;

    /// Slot: create the activity, emit 'dataRequired' signal if the activity require additional data
    void go_to(std::string _activity_id);

    /// Connect the service to the ActivitySet signals
    connections_t auto_connections() const override;

private:

    /// Invoke 'enableActivity' method in Qml file
    void enable_activity(int _index);

    /// Invokes 'disableActivity' method in Qml file
    void disable_activity(int _index);

    /// List of the activities
    std::vector<std::string> m_activity_names;

    QPointer<QWidget> m_widget;
    QPointer<QButtonGroup> m_button_group;

    /// Defines if the activities should be cleared when going backward
    bool m_clear_activities {false};

    /// Display a warning message if changing activities without validating it.
    bool m_warn_user {false};
    /// Configured warning message, if empty no warnings are displayed.
    std::string m_warning_message;

    std::string m_button_width {"200"};
    double m_font_size {12.0};

    const signals::activity_signal_t::sptr m_activity_created {
        new_signal<signals::activity_signal_t>(signals::ACTIVITY_CREATED)
    };

    const signals::activity_signal_t::sptr m_data_required {
        new_signal<signals::activity_signal_t>(signals::DATA_REQUIRED)
    };

    const signals::bool_signal_t::sptr m_has_previous {
        new_signal<signals::bool_signal_t>(signals::HAS_PREVIOUS)
    };

    const signals::bool_signal_t::sptr m_has_next {
        new_signal<signals::bool_signal_t>(signals::HAS_NEXT)
    };

    const signals::bool_signal_t::sptr m_next_enabled {
        new_signal<signals::bool_signal_t>(signals::NEXT_ENABLED)
    };

    const signals::bool_signal_t::sptr m_next_validated {
        new_signal<signals::bool_signal_t>(signals::NEXT_VALIDATED)
    };

    const signals::void_signal_t::sptr m_next_valid {
        new_signal<signals::void_signal_t>(signals::NEXT_VALID)
    };

    const signals::void_signal_t::sptr m_next_invalid {
        new_signal<signals::void_signal_t>(signals::NEXT_INVALID)
    };

    static constexpr std::string_view ACTIVITY_SET_INOUT = "activitySet";
    data::ptr<data::activity_set, data::access::inout> m_activity_set {this, ACTIVITY_SET_INOUT};

    data::property<data::boolean> m_linear {this, "linear", true};
};

} // namespace sight::module::ui::qt::activity