File: AccordionWidget.h

package info (click to toggle)
bornagain 1.18.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 118,800 kB
  • sloc: cpp: 469,684; python: 38,920; xml: 805; awk: 630; sh: 286; ansic: 37; makefile: 25
file content (383 lines) | stat: -rw-r--r-- 12,434 bytes parent folder | download
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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
// ************************************************************************** //
//
//  BornAgain: simulate and fit scattering at grazing incidence
//
//! @file      GUI/coregui/Views/AccordionWidget/AccordionWidget.h
//! @brief     Defines AccordionWidget class
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************** //

// This file is part of qAccordion. An Accordion widget for Qt
// Copyright (C) 2015 Christian Rapp <0x2a at posteo dot org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#ifndef BORNAGAIN_GUI_COREGUI_VIEWS_ACCORDIONWIDGET_ACCORDIONWIDGET_H
#define BORNAGAIN_GUI_COREGUI_VIEWS_ACCORDIONWIDGET_ACCORDIONWIDGET_H

#include "GUI/coregui/Views/AccordionWidget/ClickableFrame.h"
#include <QGridLayout>
#include <QHBoxLayout>
#include <QPainter>
#include <QSpacerItem>
#include <QString>
#include <QStyleOption>
#include <QVBoxLayout>
#include <QWidget>
#include <algorithm>
#include <iterator>
#include <memory>
#include <vector>

class ContentPane;

/**
 * @brief QAccordion base class
 *
 * @details
 * This class is the basis of the qAccordion widget. If you want to add a
 * accordion widget to your gui then you have to create an object of this class.
 *
 * Managing content panes is simpel:
 * * You can either add (addContentPane()) or insert (insertContentPane()) new ContentPanes.
 * * Use removeContentPane() to remove existing ContentPanes.
 * * moveContentPane() allows you to change the order of the ContentPanes.
 * * To change a ContentPane in place use swapContentPane()
 *
 * @note
 * Many of the mentioned functions are overloaded, provided for convenience.
 *
 * @details
 * The signal numberOfContentPanesChanged() is emitted whenever the number of
 * content panes changed.
 *
 * In case of an error you may get a more detailed error description with
 * getError().
 *
 * @warning
 * Currently Headers have to be unique
 *
 */
class AccordionWidget : public QWidget
{
    Q_OBJECT
public:
    /**
     * @brief QAccordion constructor
     * @param parent Optionally provide a parent widget
     */
    explicit AccordionWidget(QWidget* parent = 0);

    /**
     * @brief Returns the number of content panes
     * @return int
     */
    int numberOfContentPanes();

    /**
     * @brief Add a new content Pane
     * @param header Header of the content pane
     * @return Content pane index
     *
     * @details
     * Use this method to add a new content pane with the Header header.
     * The method will return the index of the new content pane, or <b>-1</b> if
     * the pane was not added because header already exists.
     */
    int addContentPane(QString header);
    /**
     * @brief Add a new content Pane
     * @param header Header of the content pane
     * @param contentFrame The content of the pane
     * @return Content pane index
     *
     * @details
     * This is an overloaded method of addContentPane(QString), that
     * allows you to provide your own content frame.
     * @warning
     * Headers have to be unique
     */
    int addContentPane(QString header, QFrame* contentFrame);
    /**
     * @brief Add content pane
     * @param cpane New content pane to add
     * @return Content pane index
     *
     * @details
     * This is an overloaded method of addContentPane(QString), that
     * allows you to provide your own content pane.
     */
    int addContentPane(ContentPane* cpane);
    /**
     * @brief Insert content pane
     * @param index Index of the content pane
     * @param header Header of the content pane
     * @return bool True if insert was successfull
     *
     * @details
     * You can use this method to insert a new content pane at given index with
     * header defining the Header. An empty content pane will be created that
     * you can get with getContentPane().
     *
     * Returns true if the insert was successfull.
     */
    bool insertContentPane(uint index, QString header);
    /**
     * @brief Insert content pane
     * @param index Index of the content pane
     * @param header Header of the content pane
     * @param contentFrame Content frame of the content pane
     * @return bool True if insert was successfull
     *
     * @details
     * This is an overloaded method of insertContentPane(uint, QString).
     * Use this method when you already created a content frame that you want to
     * insert.
     * @warning
     * Headers have to be unique
     */
    bool insertContentPane(uint index, QString header, QFrame* contentFrame);
    /**
     * @brief Insert content pane
     * @param index Index of the content pane
     * @param cpane Content Pane to insert
     * @return bool True if insert was successfull
     *
     * @details
     * This is an overloaded method of insertContentPane(uint, QString).
     * Use this method when you already created a content pane that you want to
     * insert.
     */
    bool insertContentPane(uint index, ContentPane* cpane);

    /**
     * @brief Swap the content pane
     * @param index Index of the content pane to swap
     * @param cpane New content pane
     * @return bool True if swap was successfull
     *
     * @details
     * With this method you can replace an existing content pane at index with
     * a new one cpane.
     *
     * Returns true if the swap was successfull.
     *
     * The old content pane will be __deleted__.
     */
    bool swapContentPane(uint index, ContentPane* cpane);

    /**
     * @brief Remove a content pane
     * @param deleteObject Delete the object and free memory
     * @param index Index of the content pane
     * @return bool
     *
     * @details
     * Remove a content pane at index. If deleteObject is true the
     * object will be deleted. Otherwise it is up to the user to
     * free the allocated memory.
     *
     * Returns true if the pane was removed and false otherwise.
     */
    bool removeContentPane(bool deleteObject, uint index);
    /**
     * @brief Remove a content pane
     * @param deleteObject Delete the object and free memory
     * @param header Header of the content pane
     * @return bool
     *
     * @details
     * This is an overloaded method of removeContentPane(bool, uint).
     */
    bool removeContentPane(bool deleteObject, QString header);
    /**
     * @brief Remove a content pane
     * @param deleteObject Delete the object and free memory
     * @param contentframe Content frame of the content pane
     * @return bool
     *
     * @details
     * This is an overloaded method of removeContentPane(bool, uint).
     */
    bool removeContentPane(bool deleteObject, QFrame* contentframe);
    /**
     * @brief Remove a content pane
     * @param deleteObject Delete the object and free memory
     * @param contentPane The content pane to remove
     * @return bool
     *
     * @details
     * This is an overloaded method of removeContentPane(bool, uint).
     */
    bool removeContentPane(bool deleteObject, ContentPane* contentPane);

    /**
     * @brief Move content pane
     * @param currentIndex The current index of the content pane.
     * @param newIndex The new index of the current pane
     * @return bool
     *
     * @details
     * Moves a content from currentIndex to newIndex. Returns true if the
     * content pane was moved, false otherwise.
     */
    bool moveContentPane(uint currentIndex, uint newIndex);

    /**
     * @brief Get content pane
     * @param index Index of the content pane
     * @return QFrame* or nullptr
     *
     * @details
     * Get a content pane (QFrame*) with index. This method will return a
     * __nullptr__ if the content pane does not exist.
     */
    ContentPane* getContentPane(uint index);

    /**
     * @brief Get the index of a content pane
     * @param header Header of the Content Pane
     * @return Index of the content pane
     *
     * @details
     * Get the index of a ContentPane with header. This method will return
     * <b>-1</b> if a ContentPane with this header does not exist.
     */
    int getContentPaneIndex(QString header);
    /**
     * @brief Get the index of a content pane
     * @param contentFrame Content Frame
     * @return Index of the content pane
     *
     * @details
     * This is an overloaded function of getContentPaneIndex(QString)
     */
    int getContentPaneIndex(QFrame* contentFrame);
    /**
     * @brief Get the index of a content pane
     * @param contentPane ContentPane*
     * @return Index of the content pane
     *
     * @details
     * This is an overloaded function of getContentPaneIndex(QString)
     */
    int getContentPaneIndex(ContentPane* contentPane);

    /**
     * @brief Get the index of the active ContentPane
     * @return Vector with indexes of all active ContentPanes
     *
     * @details
     * This method will fill a vector with the index of all active ContentPanes.
     * The vector will be empty if no ContentPane is active
     */
    void getActiveContentPaneIndex(std::vector<int>& indexVector);

    /**
     * @brief Allow multiple ContentPane to be open
     * @param status
     *
     * @details
     * This option allows you to open several ContentPane at the same time.
     * @note
     * Default value for this option is false.
     */
    void setMultiActive(bool status);
    /**
     * @brief Check status of multiActive
     * @return bool
     *
     * @sa
     * setMultiActive()
     */
    bool getMultiActive();

    /**
     * @brief If collapsible is true you can close all ContentPanes
     * @param status
     *
     * @details
     * With the collapsible option you can control if one content pane has to be
     * open and can't be closed.
     */
    void setCollapsible(bool status);
    /**
     * @brief Get collapsible status
     * @return bool
     * @sa
     * setCollapsible()
     */
    bool getCollapsible();

    /**
     * @brief Get error string
     * @return Error string
     *
     * @details
     * Call this method after a function call failed for a detailed error
     * description.
     */
    QString getError();

signals:
    /**
     * @brief Signals the new number of content panes
     * @param number Number of content panes
     *
     * @details
     * Signal will be emitted if the number of content panes changes
     */
    void numberOfContentPanesChanged(int number);

public slots:

private:
    std::vector<ContentPane*> contentPanes;

    QSpacerItem* spacer;

    QString errorString;

    bool multiActive;
    bool collapsible;

    int internalAddContentPane(QString header, QFrame* cframe = nullptr,
                               ContentPane* cpane = nullptr);
    bool internalInsertContentPane(uint index, QString header, QFrame* contentFrame = nullptr,
                                   ContentPane* cpane = nullptr);
    bool internalRemoveContentPane(bool deleteOject, int index = -1, QString name = "",
                                   QFrame* contentFrame = nullptr, ContentPane* cpane = nullptr);
    int findContentPaneIndex(QString name = "", QFrame* cframe = nullptr,
                             ContentPane* cpane = nullptr);

    bool checkIndexError(uint index, bool sizeIndexAllowed, const QString& errMessage);
    void handleClickedSignal(ContentPane* cpane);

private slots:
    void numberOfPanesChanged(int number);

protected:
    /**
     * @brief paintEvent Reimplement paintEvent to use stylesheets in derived Widgets
     * @param event
     */
    void paintEvent(ATTR_UNUSED QPaintEvent* event);
};

#endif // BORNAGAIN_GUI_COREGUI_VIEWS_ACCORDIONWIDGET_ACCORDIONWIDGET_H