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 */
//***************************************************************************
//***************************************************************************
|