kwave  18.07.70
SignalWidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  SignalWidget.cpp - Widget for displaying the signal
3  -------------------
4  begin : 1999
5  copyright : (C) 1999 by Martin Wilz
6  email : Martin Wilz <mwilz@ernie.mi.uni-koeln.de>
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "config.h"
19 #include <errno.h>
20 #include <math.h>
21 #include <stdlib.h>
22 
23 #include <QApplication>
24 #include <QBitmap>
25 #include <QContextMenuEvent>
26 #include <QDragEnterEvent>
27 #include <QDragLeaveEvent>
28 #include <QDragMoveEvent>
29 #include <QDropEvent>
30 #include <QEvent>
31 #include <QFrame>
32 #include <QIcon>
33 #include <QMenu>
34 #include <QMouseEvent>
35 #include <QPaintEvent>
36 #include <QResizeEvent>
37 #include <QTime>
38 #include <QToolTip>
39 
40 #include <KCursor>
41 #include <KLocalizedString>
42 
43 #include "libkwave/ClipBoard.h"
44 #include "libkwave/LabelList.h"
45 #include "libkwave/SignalManager.h"
46 #include "libkwave/String.h"
47 #include "libkwave/Track.h"
48 #include "libkwave/Utils.h"
49 
50 #include "libgui/SignalView.h"
51 #include "libgui/SignalWidget.h"
52 #include "libgui/TrackPixmap.h"
53 #include "libgui/TrackView.h"
54 // #include "libgui/ShortcutWrapper.h"
55 
56 // /** table of keyboard shortcuts 0...9 */
57 // static const int tbl_keys[10] = {
58 // Qt::Key_1,
59 // Qt::Key_2,
60 // Qt::Key_3,
61 // Qt::Key_4,
62 // Qt::Key_5,
63 // Qt::Key_6,
64 // Qt::Key_7,
65 // Qt::Key_8,
66 // Qt::Key_9,
67 // Qt::Key_0
68 // };
69 
71 #define VERTICAL_ZOOM_MIN 1.0
72 
74 #define VERTICAL_ZOOM_MAX 100.0
75 
77 #define VERTICAL_ZOOM_STEP_FACTOR 1.5
78 
80 #define REPAINT_INTERVAL 50
81 
82 //***************************************************************************
84  Kwave::SignalManager *signal_manager,
85  QVBoxLayout *upper_dock,
86  QVBoxLayout *lower_dock)
87  :QWidget(parent),
88  m_signal_manager(signal_manager),
89  m_views(),
90  m_layout(this),
91  m_upper_dock(upper_dock),
92  m_lower_dock(lower_dock),
93  m_offset(0),
94  m_zoom(0.0),
95  m_vertical_zoom(1.0),
96  m_repaint_timer()
97 {
98 // qDebug("SignalWidget::SignalWidget()");
99 
100  // connect to the signal manager's signals
102 
103  connect(sig, SIGNAL(sigTrackInserted(uint,Kwave::Track*)),
104  this, SLOT(slotTrackInserted(uint,Kwave::Track*)));
105  connect(sig, SIGNAL(sigTrackDeleted(uint,Kwave::Track*)),
106  this, SLOT(slotTrackDeleted(uint,Kwave::Track*)));
107 
108  // use a timer for limiting the repaint rate
109  m_repaint_timer.setSingleShot(true);
110  connect(&m_repaint_timer, SIGNAL(timeout()),
111  this, SLOT(repaintTimerElapsed()));
112 
113 // // -- accelerator keys for 1...9 --
114 // for (int i = 0; i < 10; i++) {
115 // Kwave::ShortcutWrapper *shortcut =
116 // new Kwave::ShortcutWrapper(this, tbl_keys[i], i);
117 // connect(shortcut, SIGNAL(activated(int)),
118 // this, SLOT(parseKey(int)));
119 // }
120 
121  setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
122 
123  m_layout.setColumnStretch(0, 0);
124  m_layout.setColumnStretch(1, 100);
125  m_layout.setMargin(0);
126  m_layout.setVerticalSpacing(3);
127  setLayout(&m_layout);
128  m_layout.activate();
129 }
130 
131 //***************************************************************************
133 {
134 }
135 
136 //***************************************************************************
138 {
139  Q_ASSERT(zoom >= 0.0);
140  foreach (QPointer<Kwave::SignalView> view, m_views)
141  view->setZoomAndOffset(zoom, offset);
142 }
143 
144 //***************************************************************************
145 void Kwave::SignalWidget::forwardCommand(const QString &command)
146 {
147  emit sigCommand(command);
148 }
149 
150 //***************************************************************************
152 {
153  // add the view to the repaint queue (if not already there)
154  if (!m_repaint_queue.contains(view))
155  m_repaint_queue.enqueue(view);
156 
157  if (!m_repaint_timer.isActive()) {
158  // start the repaint timer
160  }
161  // else: repainting is inhibited -> wait until the
162  // repaint timer is elapsed
163 }
164 
165 //***************************************************************************
167 {
168  while (!m_repaint_queue.isEmpty())
169  {
170  Kwave::SignalView *view = m_repaint_queue.dequeue();
171  if (!view) continue;
172  view->refresh();
173  }
174 }
175 
176 //***************************************************************************
177 void Kwave::SignalWidget::contextMenuEvent(QContextMenuEvent *e)
178 {
179  Q_ASSERT(e);
180 
181  bool have_signal = m_signal_manager && !m_signal_manager->isEmpty();
182  if (!have_signal)return;
183  bool have_selection = (m_signal_manager->selection().length() > 1);
184  bool have_labels =
185  !(Kwave::LabelList(m_signal_manager->metaData()).isEmpty());
186 
187  QMenu *context_menu = new QMenu(this);
188  Q_ASSERT(context_menu);
189  if (!context_menu) return;
190 
191  /* menu items common to all cases */
192 
193  // undo
194  QAction *action;
195  action = context_menu->addAction(
196  QIcon::fromTheme(_("edit-undo")),
197  i18n("&Undo"), this, SLOT(contextMenuEditUndo()),
198  Qt::CTRL + Qt::Key_Z);
199  Q_ASSERT(action);
200  if (!action) return;
201  if (!m_signal_manager->canUndo())
202  action->setEnabled(false);
203 
204  // redo
205  action = context_menu->addAction(
206  QIcon::fromTheme(_("edit-redo")),
207  i18n("&Redo"), this, SLOT(contextMenuEditRedo()),
208  Qt::CTRL + Qt::Key_Y);
209  Q_ASSERT(action);
210  if (!action) return;
211  if (!m_signal_manager->canRedo())
212  action->setEnabled(false);
213  context_menu->addSeparator();
214 
215  // cut/copy/paste
216  QAction *action_cut = context_menu->addAction(
217  QIcon::fromTheme(_("edit-cut")),
218  i18n("Cu&t"), this, SLOT(contextMenuEditCut()),
219  Qt::CTRL + Qt::Key_X);
220  QAction *action_copy = context_menu->addAction(
221  QIcon::fromTheme(_("edit-copy")),
222  i18n("&Copy"), this, SLOT(contextMenuEditCopy()),
223  Qt::CTRL + Qt::Key_C);
224  QAction *action_paste = context_menu->addAction(
225  QIcon::fromTheme(_("edit-paste")),
226  i18n("&Paste"), this, SLOT(contextMenuEditPaste()),
227  Qt::CTRL + Qt::Key_V);
228  context_menu->addSeparator();
229  if (action_cut) action_cut->setEnabled(have_selection);
230  if (action_copy) action_copy->setEnabled(have_selection);
231  if (action_paste)
232  action_paste->setEnabled(!Kwave::ClipBoard::instance().isEmpty());
233 
234  int mouse_x = mapFromGlobal(e->globalPos()).x();
235  int mouse_y = mapFromGlobal(e->globalPos()).y();
236  if (mouse_x < 0) mouse_x = 0;
237  if (mouse_y < 0) mouse_y = 0;
238  if (mouse_x >= width()) mouse_x = width() - 1;
239  if (mouse_y >= height()) mouse_y = height() - 1;
240 
241 
242  QMenu *submenu_select = context_menu->addMenu(i18n("Selection"));
243  Q_ASSERT(submenu_select);
244  if (!submenu_select) return;
245 
246  // Selection / &Save
247  QAction *action_select_save = submenu_select->addAction(
248  QIcon::fromTheme(_("document-save")),
249  i18n("&Save..."), this, SLOT(contextMenuSaveSelection()));
250  Q_ASSERT(action_select_save);
251  if (!action_select_save) return;
252  action_select_save->setEnabled(have_selection);
253 
254  // Selection / &Expand to labels
255  QAction *action_select_expand_to_labels = submenu_select->addAction(
256  i18n("&Expand to Labels"), this,
257  SLOT(contextMenuSelectionExpandToLabels()), Qt::Key_E);
258  Q_ASSERT(action_select_expand_to_labels);
259  if (!action_select_expand_to_labels) return;
260  action_select_expand_to_labels->setEnabled(have_labels);
261 
262  // Selection / to next labels
263  QAction *action_select_next_labels = submenu_select->addAction(
264  i18n("To Next Labels"), this,
266  Qt::SHIFT + Qt::CTRL + Qt::Key_N);
267  Q_ASSERT(action_select_next_labels);
268  if (!action_select_next_labels) return;
269  action_select_next_labels->setEnabled(have_labels);
270 
271  // Selection / to previous labels
272  QAction *action_select_prev_labels = submenu_select->addAction(
273  i18n("To Previous Labels"), this,
275  Qt::SHIFT + Qt::CTRL + Qt::Key_P);
276  Q_ASSERT(action_select_prev_labels);
277  if (!action_select_prev_labels) return;
278  action_select_prev_labels->setEnabled(have_labels);
279 
280  // find out whether there was a click within a signal view
281  QSharedPointer<Kwave::ViewItem> item(Q_NULLPTR);
282  foreach (QPointer<Kwave::SignalView> view, m_views) {
283  // map the rect of the view to our coordinate system
284  const QRect view_rect = QRect(
285  view->mapToParent(view->rect().topLeft()),
286  view->mapToParent(view->rect().bottomRight()));
287 
288  // check: mouse click was into that view?
289  if (view_rect.contains(mouse_x, mouse_y)) {
290  // map mouse click position to coordinate system of the view
291  QPoint pos = view->mapFromParent(QPoint(mouse_x, mouse_y));
292 
293  // give the view the chance to extend the context menu
294  view->handleContextMenu(pos, context_menu);
295 
296  // try to find a view item at these coordinates
297  item = view->findItem(pos);
298 
299  // if found, give the item the chance to extend the context menu
300  if (!item.isNull()) {
301  connect(item.data(), SIGNAL(sigCommand(QString)),
302  this, SLOT(forwardCommand(QString)));
303  item->appendContextMenu(context_menu);
304  }
305 
306  // we process only one view, views cannot overlap!
307  break;
308  }
309  }
310 
311  context_menu->exec(QCursor::pos());
312  delete context_menu;
313 }
314 
315 //***************************************************************************
316 void Kwave::SignalWidget::wheelEvent(QWheelEvent *event)
317 {
318  if (!event) return;
319 
320  // we currently are only interested in <Alt> + <WheelUp/Down>
321  if (event->modifiers() != Qt::AltModifier) {
322  event->ignore();
323  return;
324  }
325 
326  if (event->delta() > 0) {
327  // zoom in
329  event->accept();
330  } else if (event->delta() < 0) {
331  // zoom out
333  event->accept();
334  } else {
335  // no change
336  event->ignore();
337  }
338 }
339 
340 //***************************************************************************
342 {
343  if (zoom > VERTICAL_ZOOM_MAX) zoom = VERTICAL_ZOOM_MAX;
344  if (zoom < VERTICAL_ZOOM_MIN) zoom = VERTICAL_ZOOM_MIN;
345  if (qFuzzyCompare(zoom, m_vertical_zoom)) return; // no change
346 
347  // take over the zoom factor
348  m_vertical_zoom = zoom;
349 
350  // propagate the zoom to all views
351  foreach (QPointer<Kwave::SignalView> view, m_views)
352  if (view) view->setVerticalZoom(m_vertical_zoom);
353 
354  // get back the maximum zoom set by the views
355  foreach (QPointer<Kwave::SignalView> view, m_views)
356  if (view && view->verticalZoom() > m_vertical_zoom)
357  m_vertical_zoom = view->verticalZoom();
358 }
359 
360 //***************************************************************************
361 int Kwave::SignalWidget::mapToViewPort(const QPoint &pos) const
362 {
363  if (m_views.isEmpty()) return mapFromGlobal(pos).x(); // if empty
364  return mapFromGlobal(pos).x() - m_layout.cellRect(0, 1).left();
365 }
366 
367 //***************************************************************************
369 {
370  if (m_views.isEmpty()) return width(); // if empty
371  return m_layout.cellRect(0, 1).width();
372 }
373 
374 //***************************************************************************
376  QWidget *controls)
377 {
378  const int rows = m_layout.rowCount();
379  const int cols = m_layout.columnCount();
380 
381  // update the layout: move all items from the index on to the next row
382  for (int row = rows; row > index; row--) {
383  for (int col = 0; col < cols; col++) {
384  QLayoutItem *item = m_layout.itemAtPosition(row - 1, col);
385  if (item) {
386  m_layout.removeItem(item);
387  m_layout.addItem(item, row, col);
388  }
389  }
390  }
391 
392  // add the widget to the layout
393  m_layout.addWidget(view, index, 1);
394 
395  if (controls) {
396  // add the controls to the layout
397  m_layout.addWidget(controls, index, 0);
398 
399  // associate the controls to the view, so that when the view
400  // gets removed/deleted, the controls get removed as well
401  view->addSibling(controls);
402 
403  m_layout.activate();
404  // NOTE: QLayout::activate() does not really activate the layout
405  // synchronously as expected. Instead it posts an event to
406  // invalidate the layout of it's parent widget.
407  // Unfortunately we need reliable geometry information
408  // already *now*, which forces us to do the event loop
409  // right here.
410  qApp->processEvents(QEventLoop::ExcludeUserInputEvents |
411  QEventLoop::ExcludeSocketNotifiers);
412  }
413 }
414 
415 //***************************************************************************
417 {
418  const int rows = m_layout.rowCount();
419  const int cols = m_layout.columnCount();
420 
421  if (index >= rows)
422  return;
423 
424  // update the layout: move all items from this row to the previous
425  for (int row = index; row < (rows - 1); row++) {
426  for (int col = 0; col < cols; col++) {
427  QLayoutItem *item = m_layout.itemAtPosition(row + 1, col);
428  if (item) {
429  m_layout.removeItem(item);
430  m_layout.addItem(item, row, col);
431  }
432  }
433  }
434 }
435 
436 //***************************************************************************
438  QWidget *controls)
439 {
440  Q_ASSERT(m_upper_dock);
441  Q_ASSERT(m_lower_dock);
442  Q_ASSERT(view);
443  if (!m_upper_dock || !m_lower_dock) return;
444  if (!view) return;
445 
446  // set initial vertical zoom
448 
449  // find the proper row to insert the track view
450  int index = 0;
451  int track = (view) ? view->track() : -1;
452  const Kwave::SignalView::Location where = view->preferredLocation();
453  switch (where) {
455  // upper dock area, top
456  index = 0;
457  m_upper_dock->insertWidget(0, view);
458  Q_ASSERT(!controls);
459  break;
460  }
462  // upper dock area, bottom
463  index = m_upper_dock->count();
464  m_upper_dock->addWidget(view);
465  Q_ASSERT(!controls);
466  break;
467  }
468  case Kwave::SignalView::Top: {
469  // central layout, above all others
470  index = m_upper_dock->count();
471  int row = 0;
472  insertRow(row, view, controls);
473  break;
474  }
476  // above the corresponding track, start of group
477  index = m_upper_dock->count();
478  int row = 0;
479  for (;index < m_views.count(); ++row, ++index) {
480  if (m_views[index]->track() >= track) break; // reached top
481  if (m_views[index]->preferredLocation() >=
483  }
484  insertRow(row, view, controls);
485  break;
486  }
488  // above the corresponding track, end of group
489  index = m_upper_dock->count();
490  int row = 0;
491  for (;index < m_views.count(); ++row, ++index) {
492  if (m_views[index]->track() < track) continue; // too early
493  if (m_views[index]->track() != track) break; // next track
494  if (m_views[index]->preferredLocation() !=
496  }
497  insertRow(row, view, controls);
498  break;
499  }
501  // below the corresponding track, start of group
502  index = m_upper_dock->count();
503  int row = 0;
504  for (;index < m_views.count(); ++row, ++index) {
505  if (m_views[index]->track() < track) continue; // too early
506  if (m_views[index]->track() != track) break; // next track
507  if (m_views[index]->preferredLocation() >=
509  }
510  insertRow(row, view, controls);
511  break;
512  }
514  // below the corresponding track, end of group
515  index = m_upper_dock->count();
516  int row = 0;
517  for (;index < m_views.count(); ++row, ++index) {
518  if (m_views[index]->track() < track) continue; // too early
519  if (m_views[index]->track() != track) break; // next track
520  if (m_views[index]->preferredLocation() >=
522  }
523  insertRow(row, view, controls);
524  break;
525  }
527  // below all others
528  int row = m_layout.rowCount();
529  index = m_upper_dock->count() + row;
530  insertRow(row, view, controls);
531  break;
532  }
534  // lower dock area, top
535  index = m_upper_dock->count() + m_layout.rowCount();
536  m_lower_dock->insertWidget(0, view);
537  Q_ASSERT(!controls);
538  break;
539  }
541  // lower dock area, bottom
542  index = m_upper_dock->count() + m_layout.rowCount() +
543  m_lower_dock->count();
544  m_lower_dock->addWidget(view);
545  Q_ASSERT(!controls);
546  break;
547  }
548 
549  // insert the view into the list of views
550  Q_ASSERT(index >= 0);
551  Q_ASSERT(index < m_upper_dock->count() + m_layout.rowCount() +
552  m_lower_dock->count());
553  m_views.insert(index, view);
554 
555  // initially set the current view info
557 
558  // connect all signals
559  connect(view, SIGNAL(sigCommand(QString)),
560  this, SIGNAL(sigCommand(QString)),
561  Qt::QueuedConnection);
562 
563  connect(view, SIGNAL(sigNeedRepaint(Kwave::SignalView*)),
564  this, SLOT(requestRepaint(Kwave::SignalView*)));
565 
566  connect(view, SIGNAL(contentSizeChanged()),
567  this, SLOT(updateMinimumHeight()));
568  connect(view, SIGNAL(destroyed(QObject*)),
569  this, SLOT(updateMinimumHeight()));
570  connect(view, SIGNAL(sigCursorChanged(sample_index_t)),
571  this, SIGNAL(sigCursorChanged(sample_index_t)));
572  connect(this, SIGNAL(sigCursorChanged(sample_index_t)),
573  view, SLOT(showCursor(sample_index_t)));
574 
576 }
577 
578 //***************************************************************************
580  Kwave::Track *track)
581 {
582  Q_ASSERT(track);
583  if (!track) return;
584 
585  // create a container widget for the track controls
586  QWidget *controls = new QWidget(Q_NULLPTR);
587  Q_ASSERT(controls);
588  if (!controls) return;
589 
590  // create a new view for the track's signal
591  Kwave::SignalView *new_view = new Kwave::TrackView(
592  this, controls, m_signal_manager, track);
593  Q_ASSERT(new_view);
594  if (!new_view) {
595  delete controls;
596  return;
597  }
598 
599  // loop over all views and adjust the track index of the following ones
600  foreach (QPointer<Kwave::SignalView> view, m_views) {
601  if (view->track() >= Kwave::toInt(index))
602  view->setTrack(view->track() + 1);
603  }
604 
605  // assign the view to the new track
606  new_view->setTrack(index);
607 
608  insertView(new_view, controls);
609 }
610 
611 //***************************************************************************
613  Kwave::Track *track)
614 {
615  Q_UNUSED(track);
616 
617  // loop over all views, delete those that are bound to this track
618  // and adjust the index of the following ones
619  bool empty = true;
620  QMutableListIterator<QPointer<Kwave::SignalView> > it(m_views);
621  while (it.hasNext()) {
622  Kwave::SignalView *view = it.next();
623  if (view->track() == Kwave::toInt(index)) {
624  it.remove();
625  delete view;
626  } else if (view->track() > Kwave::toInt(index)) {
627  view->setTrack(view->track() - 1);
628  empty = false;
629  } else if (view->track() != -1) {
630  empty = false;
631  }
632  }
633 
634  // find out if there are any empty rows in the grid now
635  const int rows = m_layout.rowCount();
636  const int cols = m_layout.columnCount();
637  for (int row = 0; row < rows; row++) {
638  bool row_is_empty = true;
639  for (int col = 0; col < cols; col++) {
640  QLayoutItem *item = m_layout.itemAtPosition(row, col);
641  if (item) {
642  row_is_empty = false;
643  break;
644  }
645  }
646  if (row_is_empty) deleteRow(row);
647  }
648 
649  // if there are only views with track() == -1, we are empty,
650  // in that case delete the rest (all views)
651  if (empty) {
652  while (!m_views.isEmpty())
653  delete m_views.takeFirst();
654  }
655 }
656 
657 //***************************************************************************
659 {
660  int height = 0;
661 
662  const int rows = m_layout.rowCount();
663  const int cols = m_layout.columnCount();
664  for (int row = 0; row < rows; row++) {
665  int h = 0;
666  for (int col = 0; col < cols; col++) {
667  QLayoutItem *item = m_layout.itemAtPosition(row, col);
668  QWidget *widget = (item) ? item->widget() : Q_NULLPTR;
669  if (widget) {
670  int min_height = widget->minimumSize().height();
671  if (min_height > h) h = min_height;
672  }
673  }
674  height += h;
675  }
676  if (rows > 1) height += (rows - 1) * m_layout.verticalSpacing();
677 
678  setMinimumHeight(height);
679 }
680 
681 //***************************************************************************
682 // void Kwave::SignalWidget::parseKey(int key)
683 // {
684 // if ((key < 0) || (key >= m_lamps.count()))
685 // return;
686 // if (m_lamps.at(key)) m_lamps.at(key)->nextState();
687 // }
688 
689 //***************************************************************************
690 //***************************************************************************
#define VERTICAL_ZOOM_MAX
QList< QPointer< Kwave::SignalView > > m_views
Definition: SignalWidget.h:270
void insertRow(int index, Kwave::SignalView *view, QWidget *controls)
void sigCommand(const QString &command)
bool canRedo() const
void contextMenuSaveSelection()
Definition: SignalWidget.h:188
static ClipBoard & instance()
Definition: ClipBoard.cpp:39
SignalWidget(QWidget *parent, Kwave::SignalManager *signal_manager, QVBoxLayout *upper_dock, QVBoxLayout *lower_dock)
Kwave::MetaDataList & metaData()
void contextMenuSelectionPrevLabels()
Definition: SignalWidget.h:203
virtual void addSibling(QWidget *widget)
Definition: SignalView.cpp:107
Kwave::Selection & selection()
virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
void requestRepaint(Kwave::SignalView *view)
quint64 sample_index_t
Definition: Sample.h:28
virtual void setVerticalZoom(double zoom)
Definition: SignalView.cpp:137
QQueue< QPointer< Kwave::SignalView > > m_repaint_queue
Definition: SignalWidget.h:297
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
void setVerticalZoom(double zoom)
sample_index_t length() const
Definition: Selection.h:66
#define VERTICAL_ZOOM_MIN
void slotTrackInserted(unsigned int index, Kwave::Track *track)
virtual void insertView(Kwave::SignalView *view, QWidget *controls) Q_DECL_OVERRIDE
int mapToViewPort(const QPoint &pos) const
void setZoomAndOffset(double zoom, sample_index_t offset)
QPointer< QVBoxLayout > m_upper_dock
Definition: SignalWidget.h:276
int toInt(T x)
Definition: Utils.h:127
QGridLayout m_layout
Definition: SignalWidget.h:273
sample_index_t m_offset
Definition: SignalWidget.h:285
#define REPAINT_INTERVAL
bool canUndo() const
virtual void setTrack(int track)
Definition: SignalView.cpp:113
void sigCursorChanged(sample_index_t pos)
virtual void contextMenuEvent(QContextMenuEvent *e) Q_DECL_OVERRIDE
#define VERTICAL_ZOOM_STEP_FACTOR
int visibleWidth() const
#define _(m)
Definition: memcpy.c:66
void slotTrackDeleted(unsigned int index, Kwave::Track *track)
QPointer< QVBoxLayout > m_lower_dock
Definition: SignalWidget.h:279
void deleteRow(int index)
int track() const
Definition: SignalView.h:105
virtual void setZoomAndOffset(double zoom, sample_index_t offset)
Definition: SignalView.cpp:119
Kwave::SignalManager * m_signal_manager
Definition: SignalWidget.h:262
void forwardCommand(const QString &command)
Location preferredLocation() const
Definition: SignalView.h:95
virtual void refresh()
Definition: SignalView.cpp:101
virtual ~SignalWidget() Q_DECL_OVERRIDE
void contextMenuSelectionNextLabels()
Definition: SignalWidget.h:198
void contextMenuSelectionExpandToLabels()
Definition: SignalWidget.h:193