File: SignalView.h

package info (click to toggle)
kwave 25.04.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 23,272 kB
  • sloc: cpp: 56,173; xml: 817; perl: 688; sh: 57; makefile: 11
file content (448 lines) | stat: -rw-r--r-- 15,174 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
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
/***************************************************************************
    SignalView.h  -  base class for widgets for views to a signal
                             -------------------
    begin                : Mon Jan 18 2010
    copyright            : (C) 2010 by Thomas Eschenbacher
    email                : Thomas.Eschenbacher@gmx.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef SIGNAL_VIEW_H
#define SIGNAL_VIEW_H

#include "config.h"
#include "libkwavegui_export.h"

#include <QtGlobal>
#include <QLabel>
#include <QList>
#include <QObject>
#include <QPointer>
#include <QPolygon>
#include <QSharedPointer>
#include <QSize>
#include <QString>
#include <QTimer>
#include <QWidget>

#include "libkwave/Sample.h"

#include "libgui/MouseMark.h"
#include "libgui/ViewItem.h"

class QEvent;
class QMouseEvent;
class QPaintEvent;
class QPoint;

namespace Kwave
{

    class SignalManager; // forward declaration

    class LIBKWAVEGUI_EXPORT SignalView: public QWidget
    {
        Q_OBJECT
    public:

        /** preferred location of the SignalView */
        typedef enum {
            UpperDockTop,     /**< upper dock area, top               */
            UpperDockBottom,  /**< upper dock area, bottom            */
            Top,              /**< above all others                   */
            AboveTrackTop,    /**< above the associated track, top    */
            AboveTrackBottom, /**< above the associated track, bottom */
            BelowTrackTop,    /**< below the associated track, top    */
            BelowTrackBottom, /**< below the associated track, bottom */
            Bottom,           /**< below all others                   */
            LowerDockTop,     /**< lower dock area, top               */
            LowerDockBottom   /**< lower dock area, bottom            */
        } Location;

        /**
         * Constructor
         * @param parent pointer to the parent widget
         * @param controls container widget for associated controls
         * @param signal_manager the signal manager
         * @param preferred_location the location where to insert the view
         * @param track (optional) index of the associated track or -1 if
         *              not related to a specific track (default)
         */
        SignalView(QWidget *parent, QWidget *controls,
                   Kwave::SignalManager *signal_manager,
                   Location preferred_location,
                   int track = -1);

        /** Destructor */
        ~SignalView() override;

        /**
         * refresh the content of the view.
         * The default implementation calls repaint().
         * Can be overwritten to trigger more complex refresh scenarios.
         * @see TrackView::refresh() for an example
         */
        virtual void refresh();

        /** returns the preferred location */
        Location preferredLocation() const {
            return m_preferred_location;
        }

        /** returns the associated signal manager */
        inline Kwave::SignalManager *signalManager() const {
            return m_signal_manager;
        }

        /** returns the index of the associated track (or -1) */
        inline int track() const {
            return m_track_index;
        }

        /** returns the current start position */
        inline sample_index_t offset() const {
            return m_offset;
        }

        /** returns the current zoom [pixels/sample] */
        inline double zoom() const {
            return m_zoom;
        }

        /** returns the current vertical zoom factor */
        inline double verticalZoom() const {
            return m_vertical_zoom;
        }

        /** returns the index of the first visible sample */
        inline sample_index_t firstVisible() const {
            return m_offset;
        }

        /** returns the index of the last visible sample */
        inline sample_index_t lastVisible() const {
            const sample_index_t w = pixels2samples(width());
            return m_offset + ((w) ? (w - 1) : 0);
        }

        /**
         * converts a number of samples into a number of pixels,
         * based on the current zoom factor
         * @param samples a small number of samples (must be positive)
         * @return number of pixels
         */
        int samples2pixels(sample_index_t samples) const;

        /**
         * Converts a number of pixels into a number of samples,
         * based on the current zoom factor
         * @param pixels number of pixels (should be positive)
         * @return number of samples
         */
        sample_index_t pixels2samples(int pixels) const;

        /**
         * Converts a number of samples to a time in milliseconds, based on the
         * current signal rate.
         * @param samples number of samples
         * @return time in milliseconds
         */
        double samples2ms(sample_index_t samples);

        /**
         * Should be overwritten by subclasses that can display the currently
         * selected range and allow the user to change the selection by mouse.
         * @return true if mouse selection is handled
         */
        virtual bool canHandleSelection() const { return false; }

        /**
         * Tries to find the nearest item that is visible in this view
         * at a given position
         *
         * @param pos position to look at, relative to view [pixels]
         * @return the nearest ViewObject in range
         *         or a null pointer if nothing found
         */
        virtual QSharedPointer<Kwave::ViewItem> findItem(const QPoint &pos);

        /** slot for mouse moves, used for selection and drag&drop */
        void mouseMoveEvent(QMouseEvent *e) override;

        /** slot for mouse press, used for selection and drag&drop */
        void mousePressEvent(QMouseEvent *e) override;

        /** slot for mouse release, used for selection and drag&drop */
        void mouseReleaseEvent(QMouseEvent *e) override;

        /** slot when the mouse leaves the widget */
        void leaveEvent(QEvent *e) override;

        /** handles key press events (e.g. the Escape key) */
        void keyPressEvent(QKeyEvent *e) override;

        /**
         * tolerance in pixel for snapping to a label or selection border
         * @return number of pixels
         */
        virtual int selectionTolerance() const;

        /**
         * Called when the context menu has been activated over this view
         * @param pos a position in pixel within this widget
         * @param menu pointer to the context menu
         */
        virtual void handleContextMenu(const QPoint &pos, QMenu *menu);

        /**
         * Adds a widget to the list of associated widgets
         * @param widget a QWidget that is associated to this view
         */
        virtual void addSibling(QWidget *widget);

    signals:

        /** emitted whenever the size of the content has changed */
        void contentSizeChanged();

        /** emitted to request update of the cursor */
        void sigCursorChanged(sample_index_t pos);

        /**
         * Can be emitted to signal that this view needs to be repainted,
         * probably after synchronizing with other views and additionally
         * throttled to reduce GUI load
         * @param view pointer to the view that needs to be repainted
         */
        void sigNeedRepaint(Kwave::SignalView *view);

        /** forward a sigCommand to the next layer */
        void sigCommand(const QString &command);

    public slots:

        /**
         * changes the association to a track
         * @param track the new track index, or -1 if not associated
         */
        virtual void setTrack(int track);

        /**
         * sets new zoom factor and offset
         * @param zoom the new zoom factor in pixels/sample
         * @param offset the index of the first visible sample
         */
        virtual void setZoomAndOffset(double zoom, sample_index_t offset);

        /**
         * sets new vertical zoom factor
         * @param zoom vertical zoom factor
         */
        virtual void setVerticalZoom(double zoom);

        /**
         * shows the cursor at a given position
         * @param pos current position of the cursor
         */
        virtual void showCursor(sample_index_t pos = SAMPLE_INDEX_MAX);

    protected slots:

        /**
         * Shows the current cursor position as a tooltip
         * @param text description of the position
         * @param pos marker position [samples]
         * @param mouse the coordinates of the mouse cursor,
         *              relative to this widget [pixel]
         */
        virtual void showPosition(const QString &text, sample_index_t pos,
                                  const QPoint &mouse);

        /**
         * Hide the current position marker
         * @see showPosition
         */
        virtual void hidePosition() {
            showPosition(QString(), 0, QPoint(-1,-1));
        }

    protected:

        /** @see Qt XDND documentation */
        void dragEnterEvent(QDragEnterEvent *event) override;

        /** @see Qt XDND documentation */
        void dragLeaveEvent(QDragLeaveEvent *event) override;

        /** @see Qt XDND documentation */
        void dropEvent(QDropEvent *event) override;

        /** @see Qt XDND documentation */
        void dragMoveEvent(QDragMoveEvent *event) override;

    protected:

        /**
         * Relationship between a screen position and the current selection.
         */
        enum SelectionPosEnum {
            None        = 0x0000, /**< not near a border           */
            LeftBorder  = 0x0001, /**< close to start of selection */
            RightBorder = 0x0002, /**< close to end of selection   */
            Selection   = 0x8000  /**< within the selection        */
        };
        Q_DECLARE_FLAGS(SelectionPos, SelectionPosEnum)

        /**
         * Determines the relationship between a screen position and
         * the current selection.
         * @param x screen position
         * @return a SelectionPos
         */
        SelectionPos selectionPosition(int x);

        /**
         * Checks if a pixel position is within the left and right border
         * of a selection. The tolerance is 2% of the currently
         * visible area.
         * @param x pixel position to be tested
         * @return true if the position is within range
         */
        bool isInSelection(int x);

        /**
         * Tries to find the nearest item that is visible in this view
         * at a given position and show or hide the corresponding tool tip.
         *
         * @param mouse_pos position to look at, relative to view [pixels]
         * @param active if true an operation (move or drag&drop) is active,
         *               otherwise it is only a hover over an item
         */
        void findNewItem(const QPoint &mouse_pos, bool active);

    protected:

        /** widget for displaying associated controls */
        QWidget *m_controls;

        /** the signal manager */
        Kwave::SignalManager *m_signal_manager;

        /** the preferred location, as per construction */
        Location m_preferred_location;

        /** index of the associated track or -1 if no relation to a track */
        int m_track_index;

        /**
         * Offset from which signal is being displayed. This is equal to
         * the index of the first visible sample.
         */
        sample_index_t m_offset;

        /** number of samples per pixel */
        double m_zoom;

    private:

        class PositionWidget: public QWidget
        {
        public:
            /** Constructor */
            explicit PositionWidget(QWidget *parent);

            /** Destructor */
            ~PositionWidget() override;

            /**
             * set a new label text and alignment
             * @param text the text of the label, can be multiline and rtf/html
             * @param alignment the alignment of the label and the widget,
             *                  can be Qt::AlignLeft, Qt::AlignRight or
             *                  Qt::AlignHCenter
             */
            virtual void setText(const QString &text, Qt::Alignment alignment);

        protected:

            /** paint event: draws the text and the arrow */
            void paintEvent(QPaintEvent *) override;

            /**
             * re-creates the mask and the polygon when
             * size/alignment has changed
             */
            virtual void updateMask();

        private:

            /** the label that contains the text */
            QLabel *m_label;

            /** alignment of the label / text */
            Qt::Alignment m_alignment;

            /** the radius of the corners [pixel] */
            int m_radius;

            /** the length of the arrows [pixel] */
            int m_arrow_length;

            /** for detecting changes: previous width */
            Qt::Alignment m_last_alignment;

            /** for detecting changes: previous size */
            QSize m_last_size;

            /** polygon used as widget outline */
            QPolygon m_polygon;
        };

    private:

        /** zoom factor for vertical size */
        double m_vertical_zoom;

        /** mode of the mouse cursor */
        enum {
            MouseNormal = 0,   /**< over the signal [default]         */
            MouseMoveItem,     /**< while moving an item              */
            MouseDragItem      /**< while dragging an item            */
        } m_mouse_mode;

        /** selection handler */
        Kwave::MouseMark m_mouse_selection;

        /**
         * x position where the user clicked the last time, needed for
         * finding out where to start a drag&drop operation [pixel]
         */
        int m_mouse_down_x;

        /** small widget for showing the mouse cursor position */
        PositionWidget m_position_widget;

        /** timer for automatic hiding */
        QTimer m_position_widget_timer;

        /** list of associated widgets, e.g. controls etc */
        QList<QPointer<QWidget> > m_siblings;

        /** currently selected view item or null */
        QSharedPointer<Kwave::ViewItem> m_selected_item;
    };

}

#endif /* SIGNAL_VIEW_H */

//***************************************************************************
//***************************************************************************