kwave  18.07.70
MainWidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  MainWidget.cpp - main widget of the Kwave TopWidget
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 
20 #include <errno.h>
21 #include <math.h>
22 #include <stdlib.h>
23 
24 #include <new>
25 
26 #include <QApplication>
27 #include <QFile>
28 #include <QFileInfo>
29 #include <QFrame>
30 #include <QGridLayout>
31 #include <QHBoxLayout>
32 #include <QPoint>
33 #include <QPointer>
34 #include <QResizeEvent>
35 #include <QScrollBar>
36 #include <QTextStream>
37 #include <QWheelEvent>
38 #include <QtGlobal>
39 
40 #include <KLocalizedString>
41 #include <KMessageBox>
42 
43 #include "libkwave/Drag.h"
44 #include "libkwave/FileDrag.h"
45 #include "libkwave/FileInfo.h"
46 #include "libkwave/Label.h"
47 #include "libkwave/LabelList.h"
48 #include "libkwave/Logger.h"
49 #include "libkwave/MessageBox.h"
50 #include "libkwave/Parser.h"
51 #include "libkwave/SignalManager.h"
52 #include "libkwave/String.h"
53 #include "libkwave/Utils.h"
55 
56 #include "libgui/FileDialog.h"
58 #include "libgui/OverViewWidget.h"
59 #include "libgui/SignalWidget.h"
60 
61 #include "App.h"
62 #include "FileContext.h"
63 #include "MainWidget.h"
64 
68 #define CASE_COMMAND(x) } else if (parser.command() == _(x)) {
69 
74 #define MINIMUM_SAMPLES_PER_SCREEN 5
75 
80 #define DEFAULT_DISPLAY_TIME (5 * 60.0)
81 
85 #define LABEL_LIST_EXT _("*.label")
86 
90 #define LABEL_LIST_FILTER \
91  LABEL_LIST_EXT + _("|") + \
92  i18n("Kwave label list") + \
93  _(" (") + LABEL_LIST_EXT + _(")")
94 
95 //***************************************************************************
97  const QSize &preferred_size)
98  :QWidget(parent),
100  Kwave::Zoomable(),
101  m_context(context), m_upper_dock(), m_lower_dock(),
102  m_scroll_area(this), m_horizontal_scrollbar(Q_NULLPTR),
103  m_signal_widget(
104  &m_scroll_area,
105  context.signalManager(),
106  &m_upper_dock,
107  &m_lower_dock
108  ),
109  m_overview(Q_NULLPTR), m_offset(0), m_zoom(1.0),
110  m_preferred_size(preferred_size),
111  m_delayed_update_timer(this)
112 {
113 // qDebug("MainWidget::MainWidget()");
114 
115  setAcceptDrops(true); // enable drag&drop
116 
117  Kwave::SignalManager *signal_manager = m_context.signalManager();
118  Q_ASSERT(signal_manager);
119  if (!signal_manager) return;
120 
121  Kwave::PluginManager *plugin_manager = context.pluginManager();
122  Q_ASSERT(plugin_manager);
123  if (!plugin_manager) return;
124  plugin_manager->registerViewManager(&m_signal_widget);
125 
126  // topLayout:
127  // - upper dock
128  // - view port
129  // - lower dock
130  // - overview
131  // - horizontal scroll bar
132  QVBoxLayout *topLayout = new QVBoxLayout(this);
133  Q_ASSERT(topLayout);
134  if (!topLayout) return;
135 
136  topLayout->setSpacing(0);
137 
138  // -- upper dock --
139  topLayout->addLayout(&m_upper_dock);
140 
141  // -- view port with signal widget --
142  m_signal_widget.setSizePolicy(
143  QSizePolicy::Expanding,
144  QSizePolicy::Expanding
145  );
146  m_scroll_area.setFrameStyle(QFrame::NoFrame);
147  m_scroll_area.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
148  m_scroll_area.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
149  m_scroll_area.setWidgetResizable(true);
150  m_scroll_area.setWidget(&m_signal_widget);
151 
152  topLayout->addWidget(&m_scroll_area);
153 
154  // -- lower dock --
155  topLayout->addLayout(&m_lower_dock);
156 
157  // -- overview widget --
158 
159  m_overview = new Kwave::OverViewWidget(*signal_manager, this);
160  Q_ASSERT(m_overview);
161  if (!m_overview) return;
162  m_overview->setMinimumHeight(m_overview->sizeHint().height());
163  m_overview->setSizePolicy(
164  QSizePolicy::MinimumExpanding, QSizePolicy::Fixed
165  );
166  topLayout->addWidget(m_overview);
167  connect(m_overview, SIGNAL(valueChanged(sample_index_t)),
168  this, SLOT(setOffset(sample_index_t)));
169  connect(m_overview, SIGNAL(sigCommand(QString)),
170  this, SIGNAL(sigCommand(QString)));
171  m_overview->metaDataChanged(signal_manager->metaData());
172  m_overview->hide();
173 
174  // -- horizontal scrollbar --
175 
176  m_horizontal_scrollbar = new QScrollBar(this);
177  Q_ASSERT(m_horizontal_scrollbar);
178  if (!m_horizontal_scrollbar) return;
179  m_horizontal_scrollbar->setOrientation(Qt::Horizontal);
180  topLayout->addWidget(m_horizontal_scrollbar);
181  connect(m_horizontal_scrollbar, SIGNAL(valueChanged(int)),
182  this, SLOT(horizontalScrollBarMoved(int)));
183  m_horizontal_scrollbar->hide();
184 
185  // -- playback position update --
186 
187  Kwave::PlaybackController &playback = signal_manager->playbackController();
188  connect(&playback, SIGNAL(sigPlaybackPos(sample_index_t)),
189  m_overview, SLOT(showCursor(sample_index_t)));
190  connect(&playback, SIGNAL(sigPlaybackStopped()),
191  m_overview, SLOT(showCursor()));
192 
193  // -- connect all signals from/to the signal widget --
194 
195  connect(&m_signal_widget, SIGNAL(sigCommand(QString)),
196  this, SIGNAL(sigCommand(QString)));
197  connect(&m_signal_widget, SIGNAL(sigCursorChanged(sample_index_t)),
198  m_overview, SLOT(showCursor(sample_index_t)));
199 
200  // -- connect all signals from/to the signal manager --
201 
202  connect(signal_manager,
203  SIGNAL(sigTrackInserted(uint,Kwave::Track*)),
204  this,
205  SLOT(slotTrackInserted(uint,Kwave::Track*)));
206  connect(signal_manager,
207  SIGNAL(sigTrackDeleted(uint,Kwave::Track*)),
208  this,
209  SLOT(slotTrackDeleted(uint,Kwave::Track*)));
210  connect(signal_manager,
211  SIGNAL(sigMetaDataChanged(Kwave::MetaDataList)),
212  this,
213  SLOT(updateViewRange()));
214 
215  // set up the timer for delayed view range update
216  m_delayed_update_timer.setSingleShot(true);
217  connect(&m_delayed_update_timer, SIGNAL(timeout()),
218  this, SLOT(updateViewRange()));
219 
220  setLayout(topLayout);
221 }
222 
223 //***************************************************************************
225 {
227 }
228 
229 //***************************************************************************
231 {
232  Kwave::PluginManager *plugin_manager = m_context.pluginManager();
233  Q_ASSERT(plugin_manager);
234  if (plugin_manager) plugin_manager->registerViewManager(Q_NULLPTR);
235 }
236 
237 //***************************************************************************
238 void Kwave::MainWidget::resizeEvent(QResizeEvent *event)
239 {
240  QWidget::resizeEvent(event);
241 
242  if (!m_context.isActive() &&
244  {
245  // HACK: this is a workaround for stupid bug in Qt, which sends us a
246  // resize event with bogus size, when we are in tab mode, just
247  // before getting deactivated !?
248  if (!m_delayed_update_timer.isActive())
249  m_delayed_update_timer.start(0);
250  } else {
251  // update immediately
252  updateViewRange();
253  }
254 }
255 
256 //***************************************************************************
257 void Kwave::MainWidget::dragEnterEvent(QDragEnterEvent *event)
258 {
259  if (!event) return;
260  if ((event->proposedAction() != Qt::MoveAction) &&
261  (event->proposedAction() != Qt::CopyAction))
262  return; /* unsupported action */
263 
264  if (Kwave::FileDrag::canDecode(event->mimeData()))
265  event->acceptProposedAction();
266 }
267 
268 //***************************************************************************
269 void Kwave::MainWidget::dropEvent(QDropEvent *event)
270 {
271  if (!event) return;
272  if (!event->mimeData()) return;
273 
274  Kwave::SignalManager *signal_manager = m_context.signalManager();
275  Q_ASSERT(signal_manager);
276  if (!signal_manager) return;
277 
278  if (signal_manager->isEmpty() &&
279  Kwave::Drag::canDecode(event->mimeData()))
280  {
281  sample_index_t pos = m_offset + pixels2samples(event->pos().x());
282  sample_index_t len = 0;
283 
284  if ((len = Kwave::Drag::decode(this, event->mimeData(),
285  *signal_manager, pos)))
286  {
287  // set selection to the new area where the drop was done
288  signal_manager->selectRange(pos, len);
289  event->acceptProposedAction();
290  } else {
291  QStringList formats = event->mimeData()->formats();
292  QString fmt = (!formats.isEmpty()) ? formats.first() : QString();
293  qWarning("MainWidget::dropEvent(%s): failed !", DBG(fmt));
294  event->ignore();
295  }
296  }
297 }
298 
299 //***************************************************************************
300 void Kwave::MainWidget::wheelEvent(QWheelEvent *event)
301 {
302  if (!event || !m_overview) return;
303 
304  // process only wheel events on the signal and overview frame,
305  // not on the channel controls or scrollbars
306  if (!m_scroll_area.geometry().contains(event->pos()) &&
307  !m_overview->geometry().contains(event->pos()) )
308  {
309  event->ignore();
310  return;
311  }
312 
313  switch (event->modifiers()) {
314  case Qt::NoModifier: {
315  // no modifier + <WheelUp/Down> => scroll left/right
316  if (event->delta() > 0)
317  executeCommand(_("view:scroll_left()"));
318  else if (event->delta() < 0)
319  executeCommand(_("view:scroll_right()"));
320  event->accept();
321  break;
322  }
323  case Qt::ShiftModifier:
324  // <Shift> + <WheelUp/Down> => page up/down
325  if (event->delta() > 0)
326  executeCommand(_("view:scroll_prev()"));
327  else if (event->delta() < 0)
328  executeCommand(_("view:scroll_next()"));
329  event->accept();
330  break;
331  case Qt::ControlModifier: {
332  // <Ctrl> + <WheelUp/Down> => zoom in/out
333  int x = qMax(m_signal_widget.mapToViewPort(event->globalPos()), 0);
334  if (event->delta() > 0)
335  executeCommand(_("view:zoom_in(%1)").arg(x));
336  else if (event->delta() < 0)
337  executeCommand(_("view:zoom_out(%1)").arg(x));
338  event->accept();
339  break;
340  }
341  default:
342  event->ignore();
343  }
344 }
345 
346 //***************************************************************************
347 void Kwave::MainWidget::closeEvent(QCloseEvent *e)
348 {
349  m_context.closeFile() ? e->accept() : e->ignore();
350 }
351 
352 //***************************************************************************
353 void Kwave::MainWidget::slotTrackInserted(unsigned int index,
354  Kwave::Track *track)
355 {
356 // qDebug("MainWidget::slotTrackInserted(%u, %p)",
357 // index, static_cast<void *>(track));
358  Q_UNUSED(index);
359  Q_UNUSED(track);
360 
361  // when the first track has been inserted, set some reasonable zoom
362  Kwave::SignalManager *signal_manager = m_context.signalManager();
363  bool first_track = (signal_manager && (signal_manager->tracks() == 1));
364  if (first_track)
365  zoomAll();
366  else
367  updateViewRange();
368 
369 }
370 
371 //***************************************************************************
372 void Kwave::MainWidget::slotTrackDeleted(unsigned int index,
373  Kwave::Track *track)
374 {
375 // qDebug("MainWidget::slotTrackDeleted(%u)", index);
376  Q_UNUSED(index);
377  Q_UNUSED(track);
378 
379  updateViewRange();
380 }
381 
382 //***************************************************************************
384 {
385  return m_zoom;
386 }
387 
388 //***************************************************************************
389 int Kwave::MainWidget::executeCommand(const QString &command)
390 {
391  Kwave::SignalManager *signal_manager = m_context.signalManager();
392  Q_ASSERT(signal_manager);
393  if (!signal_manager) return -EINVAL;
394  if (!command.length()) return -EINVAL;
395 
396  Kwave::Parser parser(command);
397  const sample_index_t visible_samples = visibleSamples();
398  const sample_index_t signal_length = signal_manager->length();
399 
400  if (false) {
401 
402  // -- zoom --
403  CASE_COMMAND("view:zoom_selection")
404  zoomSelection();
405  CASE_COMMAND("view:zoom_in")
406  int x = parser.hasParams() ? parser.toInt() : -1;
407  zoomIn(x);
408  CASE_COMMAND("view:zoom_out")
409  int x = parser.hasParams() ? parser.toInt() : -1;
410  zoomOut(x);
411  CASE_COMMAND("view:zoom_normal")
412  zoomNormal();
413  CASE_COMMAND("view:zoom_all")
414  zoomAll();
415 
416  // -- navigation --
417  CASE_COMMAND("goto")
418  sample_index_t offset = parser.toSampleIndex();
419  setOffset((offset > (visible_samples / 2)) ?
420  (offset - (visible_samples / 2)) : 0);
421  signal_manager->selectRange(offset, 0);
422  CASE_COMMAND("view:scroll_right")
423  const sample_index_t step = visible_samples / 10;
424  setOffset(m_offset + step);
425  CASE_COMMAND("view:scroll_left")
426  const sample_index_t step = visible_samples / 10;
427  setOffset((step < m_offset) ? (m_offset - step) : 0);
428  CASE_COMMAND("view:scroll_start")
429  setOffset(0);
430  signal_manager->selectRange(0, 0);
431  CASE_COMMAND("view:scroll_end")
432  if (signal_length >= visible_samples)
433  setOffset(signal_length - visible_samples);
434  CASE_COMMAND("view:scroll_next")
435  setOffset(m_offset + visible_samples);
436  CASE_COMMAND("view:scroll_prev")
437  setOffset((visible_samples < m_offset) ?
438  (m_offset - visible_samples) : 0);
439  CASE_COMMAND("view:scroll_next_label")
440  sample_index_t ofs =
441  Kwave::LabelList(signal_manager->metaData()).nextLabelRight(
442  m_offset + (visible_samples / 2));
443  if (ofs > signal_length)
444  ofs = signal_length - 1;
445  setOffset((ofs > (visible_samples / 2)) ?
446  (ofs - (visible_samples / 2)) : 0);
447  CASE_COMMAND("view:scroll_prev_label")
448  sample_index_t ofs =
449  Kwave::LabelList(signal_manager->metaData()).nextLabelLeft(
450  m_offset + (visible_samples / 2));
451  setOffset((ofs > (visible_samples / 2)) ?
452  (ofs - (visible_samples / 2)) : 0);
453  // -- selection --
454  CASE_COMMAND("selectall")
455  signal_manager->selectRange(0, signal_manager->length());
456  CASE_COMMAND("selectnext")
457  if (signal_manager->selection().length())
458  signal_manager->selectRange(signal_manager->selection().last() + 1,
459  signal_manager->selection().length());
460  else
461  signal_manager->selectRange(signal_manager->length() - 1, 0);
462  CASE_COMMAND("selectprev")
463  sample_index_t ofs = signal_manager->selection().first();
464  sample_index_t len = signal_manager->selection().length();
465  if (!len) len = 1;
466  if (len > ofs) len = ofs;
467  signal_manager->selectRange(ofs - len, len);
468  CASE_COMMAND("selecttoleft")
469  signal_manager->selectRange(0, signal_manager->selection().last() + 1);
470  CASE_COMMAND("selecttoright")
471  signal_manager->selectRange(signal_manager->selection().first(),
472  signal_manager->length() - signal_manager->selection().first()
473  );
474  CASE_COMMAND("selectvisible")
475  signal_manager->selectRange(m_offset, visibleSamples());
476  CASE_COMMAND("selectnone")
477  signal_manager->selectRange(m_offset, 0);
478 
479  // label handling
480  CASE_COMMAND("label:add")
481  sample_index_t pos = parser.toSampleIndex();
482  if (!parser.isDone()) {
483  // 2 parameters: position + description
484  QString description = parser.nextParam();
485  signal_manager->addLabel(pos, description);
486  } else {
487  // 1 parameter only: open dialog for editing the description
488  addLabel(pos, QString());
489  }
490  CASE_COMMAND("label:edit")
491  int index = parser.toInt();
492  Kwave::LabelList labels(signal_manager->metaData());
493  if ((index >= labels.count()) || (index < 0))
494  return -EINVAL;
495  Kwave::Label label = labels.at(index);
496  labelProperties(label);
497  CASE_COMMAND("label:load")
498  QString filename = parser.nextParam();
499  return loadLabels(filename);
500  CASE_COMMAND("label:save")
501  QString filename = parser.nextParam();
502  return saveLabels(filename);
503 
504 // CASE_COMMAND("label:by_intensity")
505 // markSignal(command);
506 // CASE_COMMAND("label:to_pitch")
507 // convertMarkstoPitch(command);
508 // CASE_COMMAND("label:by_period")
509 // markPeriods(command);
510 
511  } else {
512  return (signal_manager) ?
513  signal_manager->executeCommand(command) : -ENOSYS;
514  }
515 
516  return 0;
517 }
518 
519 //***************************************************************************
521 {
523 
524  m_horizontal_scrollbar->blockSignals(true);
525 
526  // show/hide the overview widget
527  if (!m_context.signalManager()->isEmpty() && !m_overview->isVisible())
528  m_overview->show();
529  if (m_context.signalManager()->isEmpty() && m_overview->isVisible())
530  m_overview->hide();
531 
532  // adjust the limits of the horizontal scrollbar
533  if (m_context.signalManager()->length() > 1) {
534  // get the view information in samples
536  sample_index_t visible = visibleSamples();
537  if (visible > length) visible = length;
538 
539  // calculate the scrollbar ranges in scrollbar's units
540  //
541  // NOTE: we must take care of possible numeric overflows
542  // as the scrollbar internally works with "int" and
543  // the offsets we use for the samples might be bigger!
544  //
545  // [-------------------------------------------##############]
546  // ^ ^ ^
547  // min max page
548  //
549  // max + page = x | x < INT_MAX (!)
550  // x := length / f
551  // page = x * (visible / length) = visible / f
552  // max = length / f - page
553  // pos = (m_offset / length) * x = m_offset / f
554 
555  const sample_index_t f = qMax(
556  sample_index_t(1),
557  sample_index_t((length + INT_MAX - 1) / INT_MAX)
558  );
559  int page = Kwave::toInt(visible / f);
560  int min = 0;
561  int max = Kwave::toInt(length / f) - page;
562  int pos = Kwave::toInt(m_offset / f);
563  int single = qMax(1, (page / (10 * qApp->wheelScrollLines())));
564  if (page < single) page = single;
565 // qDebug("width=%d, max=%d, page=%d, single=%d, pos=%d, visible=%d",
566 // m_width, max, page, single, pos, visible);
567 // qDebug(" last=%d", pos + visible - 1);
568  m_horizontal_scrollbar->setRange(min, max);
569  m_horizontal_scrollbar->setValue(pos);
570  m_horizontal_scrollbar->setSingleStep(single);
571  m_horizontal_scrollbar->setPageStep(page);
572  } else {
573  m_horizontal_scrollbar->setRange(0, 0);
574  }
575 
576  m_horizontal_scrollbar->blockSignals(false);
577 }
578 
579 //***************************************************************************
581 {
582  // new offset = pos * f
584  const sample_index_t f = qMax(
585  sample_index_t(1),
586  sample_index_t((length + INT_MAX - 1) / INT_MAX)
587  );
588  const sample_index_t pos = newval * f;
589  setOffset(pos);
590 }
591 
592 //***************************************************************************
594 {
595  Kwave::SignalManager *signal_manager = m_context.signalManager();
596  sample_index_t total = (signal_manager) ? signal_manager->length() : 0;
597 
598  if (m_overview) {
600 
601  // show/hide the overview widget and the horizontal scroll bar
602  if (!m_context.signalManager()->isEmpty()) {
603  if (!m_overview->isVisible())
604  m_overview->show();
605  if (!m_horizontal_scrollbar->isVisible())
606  m_horizontal_scrollbar->show();
607  }
608  if (m_context.signalManager()->isEmpty()) {
609  if (m_overview->isVisible())
610  m_overview->hide();
611  if (m_horizontal_scrollbar->isVisible())
612  m_horizontal_scrollbar->hide();
613  }
614  }
615 
616  // forward the zoom and offset to the signal widget and overview
620 }
621 
622 //***************************************************************************
624 {
625  Kwave::SignalManager *signal_manager = m_context.signalManager();
626  Q_ASSERT(signal_manager);
627  if (!signal_manager) return 0;
628 
629  return static_cast<sample_index_t>(
630  rint(ms * signal_manager->rate() / 1E3));
631 }
632 
633 //***************************************************************************
635 {
636  if ((pixels == 0) || (m_zoom <= 0.0)) return 0;
637 
638  return static_cast<sample_index_t>(static_cast<double>(pixels) * m_zoom);
639 }
640 
641 //***************************************************************************
643 {
644  if (m_zoom <= 0.0) return 0;
645  return Kwave::toInt(rint(static_cast<double>(samples) / m_zoom));
646 }
647 
648 //***************************************************************************
650 {
651  return m_signal_widget.visibleWidth();
652 }
653 
654 //***************************************************************************
656 {
657  return pixels2samples(visibleWidth() - 1) + 1;
658 }
659 
660 //***************************************************************************
662 {
663  const int width = visibleWidth();
664  if (width <= 0) return 0.0; // no zoom info, window is not yet ready
665 
666  Kwave::SignalManager *signal_manager = m_context.signalManager();
667  Q_ASSERT(signal_manager);
668  if (!signal_manager) return 0.0;
669  if (signal_manager->isEmpty()) return 0.0; // no zoom if no signal
670 
671  sample_index_t length = signal_manager->length();
672  if (!length) {
673  // no length: streaming mode -> try to use "estimated length"
674  // and add some extra, 10% should be ok
675  Kwave::FileInfo info(signal_manager->metaData());
676  if (info.contains(Kwave::INF_ESTIMATED_LENGTH)) {
677  // estimated length in samples
678  length = info.get(Kwave::INF_ESTIMATED_LENGTH).toULongLong();
679  length += length / 10;
680  }
681  if (length <= 0) {
682  // fallback: start with some default zoom,
683  // use five minutes (just guessed)
684  length = static_cast<sample_index_t>(ceil(DEFAULT_DISPLAY_TIME *
685  signal_manager->rate()));
686  }
687  }
688  if (!length) return 0; // still no length !? -> bail out
689 
690  // example: width = 100 [pixels] and length = 3 [samples]
691  // -> samples should be at positions 0, 49.5 and 99
692  // -> 49.5 [pixels / sample]
693  // -> zoom = 1 / 49.5 [samples / pixel]
694  // => full zoom [samples/pixel] = (length - 1) / (width - 1)
695  if (length < static_cast<sample_index_t>(width) * 2) {
696  // zoom is small enough, no error compensation needed
697  return (static_cast<double>(length) - 1.0) /
698  static_cast<double>(width - 1);
699  } else {
700  // zoom is big, pre-compensate rounding errors
701  return (static_cast<double>(length) - 0.5) /
702  static_cast<double>(width - 1);
703  }
704 }
705 
706 //***************************************************************************
708 {
709  double max_zoom;
710  double min_zoom;
711  sample_index_t length;
712 
713  const double old_zoom = m_zoom;
714  const sample_index_t old_offset = m_offset;
715  const int width = visibleWidth();
716 
717  m_zoom = zoom;
718  m_offset = offset;
719  Q_ASSERT(m_zoom >= 0.0);
720 
721  Kwave::SignalManager *signal_manager = m_context.signalManager();
722  Q_ASSERT(signal_manager);
723  if (!signal_manager) return;
724  if (!width) return;
725 
726  length = signal_manager->length();
727  if (!length) {
728  // in streaming mode we have to use a guessed length
729  length = static_cast<sample_index_t>(ceil(width * fullZoom()));
730  }
731  if (!length) {
732  m_offset = 0;
733  return;
734  };
735 
736  // ensure that m_offset is [0...length-1]
737  if (m_offset >= length) m_offset = (length - 1);
738 
739  // ensure that the zoom is in a reasonable range
740  max_zoom = fullZoom();
741  min_zoom = static_cast<double>(MINIMUM_SAMPLES_PER_SCREEN) /
742  static_cast<double>(width);
743 
744  // ensure that pixel coordinates are within signed int range
745  min_zoom = qMax(min_zoom, static_cast<double>(length) / double(INT_MAX));
746 
747  if (m_zoom < min_zoom) m_zoom = min_zoom;
748  if (m_zoom > max_zoom) m_zoom = max_zoom;
749 
750  // try to correct the offset if there is not enough data to fill
751  // the current window
752  // example: width=100 [pixels], length=3 [samples],
753  // offset=1 [sample], zoom=1/49.5 [samples/pixel] (full)
754  // -> current last displayed sample = length-offset
755  // = 3 - 1 = 2
756  // -> available space = pixels2samples(width-1) + 1
757  // = (99/49.5) + 1 = 3
758  // -> decrease offset by 3 - 2 = 1
759  Q_ASSERT(length >= m_offset);
760  if ((pixels2samples(width - 1) + 1) > (length - m_offset)) {
761  // there is space after the signal -> move offset right
762  sample_index_t shift = pixels2samples(width - 1) + 1 -
763  (length - m_offset);
764  if (shift >= m_offset) {
765  m_offset = 0;
766  } else {
767  m_offset -= shift;
768  }
769  }
770 
771  // emit change in the zoom factor
772  if (!qFuzzyCompare(m_zoom, old_zoom)) emit sigZoomChanged(m_zoom);
773 
774  if ((m_offset != old_offset) || !qFuzzyCompare(m_zoom, old_zoom)) {
776  updateViewRange();
777  }
778 }
779 
780 //***************************************************************************
781 void Kwave::MainWidget::setZoom(double new_zoom)
782 {
783  fixZoomAndOffset(new_zoom, m_offset);
784 }
785 
786 //***************************************************************************
788 {
789  fixZoomAndOffset(m_zoom, new_offset);
790 }
791 
792 //***************************************************************************
794 {
795  sample_index_t visible = visibleSamples();
796 
797  if ( (pos < (m_offset + (visible / 10))) ||
798  (pos > (m_offset + (visible / 2))) )
799  {
800  // new position is out of range or too close to the border
801  sample_index_t offset = (visible / 2);
802  pos = (pos > offset) ? (pos - offset) : 0;
803  if (pos != m_offset) {
804  // check: is the difference >= 1 pixel ?
805  sample_index_t diff = (pos > m_offset) ?
806  (pos - m_offset) : (m_offset - pos);
807  if (samples2pixels(diff) >= 1)
808  setOffset(pos);
809  }
810  }
811 }
812 
813 //***************************************************************************
815 {
816  Kwave::SignalManager *signal_manager = m_context.signalManager();
817  Q_ASSERT(signal_manager);
818  if (!signal_manager) return;
819 
820  sample_index_t ofs = signal_manager->selection().offset();
821  sample_index_t len = signal_manager->selection().length();
822 
823  if (len) {
824  int width = visibleWidth();
825  m_offset = ofs;
826  setZoom((static_cast<double>(len)) / static_cast<double>(width - 1));
827  }
828 }
829 
830 //***************************************************************************
832 {
833  setZoom(fullZoom());
834 }
835 
836 //***************************************************************************
838 {
839  const sample_index_t shift1 = visibleWidth() / 2;
840  const sample_index_t shift2 = visibleSamples() / 2;
841  m_offset = (m_offset + shift2 >= m_offset) ? (m_offset + shift2) : -shift2;
842  m_offset = (m_offset > shift1) ? (m_offset - shift1) : 0;
843  setZoom(1.0);
844 }
845 
846 //***************************************************************************
848 {
849  if (pos >= 0) {
850  // position given, calculate shift:
851  // ofs_old + (pos * m_zoom) := ofs_new + (pos * (m_zoom / 3))
852  // ofs_new = ofs_old + (pos * m_zoom) - (pos * (m_zoom / 3))
854  m_zoom / 3,
855  m_offset + Kwave::toInt(pos * (m_zoom * (2.0 / 3.0)))
856  );
857  } else {
858  // no position given, show centered
860  m_zoom / 3,
861  m_offset + (visibleSamples() / 3)
862  );
863  }
864 }
865 
866 //***************************************************************************
868 {
869  sample_index_t shift;
870 
871  if (pos >= 0) {
872  // position given, calculate shift
873  // ofs_old + (pos * m_zoom) := ofs_new + (pos * (m_zoom * 3))
874  // ofs_new = ofs_old + (pos * m_zoom) - (pos * (m_zoom * 3))
875  shift = Kwave::toInt(m_zoom * 2.0) * pos;
876  } else {
877  // no position given, show centered
878  shift = visibleSamples();
879  }
881  m_zoom * 3,
882  (m_offset > shift) ? (m_offset - shift) : 0
883  );
884 }
885 
886 //***************************************************************************
887 void Kwave::MainWidget::addLabel(sample_index_t pos, const QString &description)
888 {
889  Kwave::SignalManager *signal_manager = m_context.signalManager();
890  Q_ASSERT(signal_manager);
891  if (!signal_manager) return;
892 
893  // remember the last "modified" state, in case that we abort
894  bool was_modified = signal_manager->isModified();
895 
896  // create an own undo transaction
897  Kwave::UndoTransactionGuard undo(*signal_manager, i18n("Add Label"));
898 
899  // add a new label, with undo
900  Kwave::Label label = signal_manager->addLabel(pos, description);
901  if (label.isNull()) {
902  signal_manager->abortUndoTransaction();
903  if (!was_modified) signal_manager->setModified(false);
904  return;
905  }
906 
907  // edit the properties of the new label
908  if (!labelProperties(label)) {
909  // aborted or failed -> delete (without undo)
910  int index = signal_manager->labelIndex(label);
911  signal_manager->deleteLabel(index, false);
912  signal_manager->abortUndoTransaction();
913  if (!was_modified) signal_manager->setModified(false);
914  }
915 }
916 
917 //****************************************************************************
918 int Kwave::MainWidget::loadLabels(const QString &filename)
919 {
920  Kwave::SignalManager *signal_manager = m_context.signalManager();
921  Q_ASSERT(signal_manager);
922  if (!signal_manager) return -1;
923 
924  QUrl url;
925  if (!filename.length()) {
926  QString name(filename);
927 
928  QPointer<Kwave::FileDialog> dlg = new (std::nothrow)Kwave::FileDialog(
929  _("kfiledialog:///kwave_label_dir"),
931  QUrl(), LABEL_LIST_EXT);
932  if (!dlg) return -1;
933  dlg->setWindowTitle(i18n("Load Labels"));
934  if (dlg->exec() != QDialog::Accepted) {
935  delete dlg;
936  return 0;
937  } else {
938  url = dlg->selectedUrl();
939  delete dlg;
940  }
941  } else {
942  url = QUrl::fromUserInput(filename);
943  }
944 
945  // create an own undo transaction
946  Kwave::UndoTransactionGuard undo(*signal_manager, i18n("Load Labels"));
947 
948  return m_context.loadBatch(url);
949 }
950 
951 //****************************************************************************
952 int Kwave::MainWidget::saveLabels(const QString &filename)
953 {
954  Kwave::SignalManager *signal_manager = m_context.signalManager();
955  Q_ASSERT(signal_manager);
956  if (!signal_manager) return false;
957 
958  QUrl url;
959  url = QUrl(m_context.signalName());
960 
961  if (!filename.length()) {
962  QString name(filename);
963 
964  QPointer<Kwave::FileDialog> dlg = new(std::nothrow)Kwave::FileDialog(
965  _("kfiledialog:///kwave_label_dir"),
967  this, url, LABEL_LIST_EXT);
968  if (!dlg) return 0;
969  dlg->setWindowTitle(i18n("Save Labels"));
970  if (dlg->exec() != QDialog::Accepted) {
971  delete dlg;
972  return -1;
973  }
974  url = dlg->selectedUrl();
975  if (url.isEmpty()) {
976  delete dlg;
977  return 0;
978  }
979  delete dlg;
980 
981  // add an extension if necessary
982  name = url.path();
983  if (!QFileInfo(name).suffix().length()) {
984  url.setPath(name + _(".label"));
985  name = url.path();
986  }
987 
988  // check if the file exists and ask before overwriting it
989  // if it is not the old filename
990  if (QFileInfo(name).exists())
991  {
993  i18n("The file '%1' already exists.\n"
994  "Do you really want to overwrite it?", name)) !=
995  KMessageBox::Yes)
996  {
997  return -1;
998  }
999  }
1000  } else {
1001  url = QUrl::fromUserInput(filename);
1002  }
1003 
1004  // now we have a file name -> save all labels...
1006  _("saving labels to '") + url.toDisplayString() + _("'"));
1007 
1008  QFile file(url.path());
1009  file.open(QIODevice::WriteOnly);
1010  QTextStream out(&file);
1011 
1012  Kwave::LabelList labels(signal_manager->metaData());
1013  foreach (const Kwave::Label &label, labels) {
1014  sample_index_t pos = label.pos();
1015  const QString name = Kwave::Parser::escape(label.name());
1016  out << _("label:add(") << pos;
1017  if (name.length()) out << _(", ") << name;
1018  out << _(")") << endl;
1019  }
1020 
1021  file.close();
1022  return 0;
1023 }
1024 
1025 //***************************************************************************
1027 {
1028  Kwave::SignalManager *signal_manager = m_context.signalManager();
1029  Q_ASSERT(signal_manager);
1030  if (!signal_manager) return false;
1031 
1032  if (label.isNull()) return false;
1033  int index = signal_manager->labelIndex(label);
1034  Q_ASSERT(index >= 0);
1035  if (index < 0) return false;
1036 
1037  // try to modify the label. just in case that the user moves it
1038  // to a position where we already have one, catch this situation
1039  // and ask if he wants to abort, re-enter the label properties
1040  // dialog or just replace (remove) the label at the target position
1041  bool accepted;
1042  sample_index_t new_pos = label.pos();
1043  QString new_name = label.name();
1044  int old_index = -1;
1045  while (true) {
1046  // create and prepare the dialog
1048  new Kwave::LabelPropertiesWidget(this);
1049  Q_ASSERT(dlg);
1050  if (!dlg) return false;
1051  dlg->setLabelIndex(index);
1052  dlg->setLabelPosition(new_pos, signal_manager->length(),
1053  signal_manager->rate());
1054  dlg->setLabelName(new_name);
1055 
1056  // execute the dialog
1057  accepted = (dlg->exec() == QDialog::Accepted);
1058  if (!accepted) {
1059  // user pressed "cancel"
1060  delete dlg;
1061  break;
1062  }
1063 
1064  // if we get here the user pressed "OK"
1065  new_pos = dlg->labelPosition();
1066  new_name = dlg->labelName();
1067  dlg->saveSettings();
1068  delete dlg;
1069 
1070  // check: if there already is a label at the new position
1071  // -> ask the user if he wants to overwrite that one
1072  if ((new_pos != label.pos()) &&
1073  !signal_manager->findLabel(new_pos).isNull())
1074  {
1075  int res = Kwave::MessageBox::warningYesNoCancel(this, i18n(
1076  "There already is a label at the position you have chosen.\n"\
1077  "Do you want to replace it?"));
1078  if (res == KMessageBox::Yes) {
1079  // delete the label at the target position (with undo)
1080  Kwave::Label old = signal_manager->findLabel(new_pos);
1081  old_index = signal_manager->labelIndex(old);
1082  break;
1083  }
1084  if (res == KMessageBox::No) {
1085  // make another try -> re-enter the dialog
1086  continue;
1087  }
1088 
1089  // cancel -> abort the whole action
1090  accepted = false;
1091  break;
1092  } else {
1093  // ok, we can put it there
1094  break;
1095  }
1096  }
1097 
1098  if (accepted) {
1099  // shortcut: abort if nothing has changed
1100  if ((new_name == label.name()) && (new_pos == label.pos()))
1101  return true;
1102 
1103  Kwave::UndoTransactionGuard undo(*signal_manager, i18n("Modify Label"));
1104 
1105  // if there is a label at the target position, remove it first
1106  if (old_index >= 0) {
1107  signal_manager->deleteLabel(old_index, true);
1108  // this might have changed the current index!
1109  index = signal_manager->labelIndex(label);
1110  }
1111 
1112  // modify the label through the signal manager
1113  if (!signal_manager->modifyLabel(index, new_pos, new_name, true)) {
1114  // position is already occupied
1115  signal_manager->abortUndoTransaction();
1116  return false;
1117  }
1118 
1119  // reflect the change in the passed label
1120  label.moveTo(new_pos);
1121  label.rename(new_name);
1122 
1123  // NOTE: moving might also change the index, so the complete
1124  // markers layer has to be refreshed
1125  }
1126  else
1127  signal_manager->abortUndoTransaction();
1128 
1129  return accepted;
1130 }
1131 
1132 // ////****************************************************************************
1133 // //void MainWidget::markSignal (const char *str)
1134 // //{
1135 // // if (signalmanage) {
1136 // // Kwave::Label *newmark;
1137 // //
1138 // // Kwave::Parser parser (str);
1139 // //
1140 // // int level = (int) (parser.toDouble() / 100 * (1 << 23));
1141 // //
1142 // // int len = signalmanage->getLength();
1143 // // int *sam = signalmanage->getSignal(0)->getSample(); // ### @@@ ###
1144 // // LabelType *start = findMarkerType(parser.getNextParam());
1145 // // LabelType *stop = findMarkerType (parser.getNextParam());
1146 // // int time = (int) (parser.toDouble () * signalmanage->getRate() / 1000);
1147 // //
1148 // // printf ("%d %d\n", level, time);
1149 // // printf ("%s %s\n", start->name, stop->name);
1150 // //
1151 // // ProgressDialog *dialog =
1152 // // new ProgressDialog (len, "Searching for Signal portions...");
1153 // //
1154 // // if (dialog && start && stop) {
1155 // // dialog->show();
1156 // //
1157 // // newmark = new Kwave::Label(0, start); //generate initial Kwave::Label
1158 // //
1159 // // labels->inSort (newmark);
1160 // //
1161 // // for (int i = 0; i < len; i++) {
1162 // // if (qAbs(sam[i]) < level) {
1163 // // int j = i;
1164 // // while ((i < len) && (qAbs(sam[i]) < level)) i++;
1165 // //
1166 // // if (i - j > time) {
1167 // // //insert labels...
1168 // // newmark = new Kwave::Label(i, start);
1169 // // labels->inSort (newmark);
1170 // //
1171 // // if (start != stop) {
1172 // // newmark = new Kwave::Label(j, stop);
1173 // // labels->inSort (newmark);
1174 // // }
1175 // // }
1176 // // }
1177 // // dialog->setProgress (i);
1178 // // }
1179 // //
1180 // // newmark = new Kwave::Label(len - 1, stop);
1181 // // labels->inSort (newmark);
1182 // //
1183 // // refresh ();
1184 // // delete dialog;
1185 // // }
1186 // // }
1187 // //}
1188 
1189 // ////****************************************************************************
1190 // //void MainWidget::markPeriods (const char *str)
1191 // //{
1192 // // if (signalmanage) {
1193 // // Kwave::Parser parser (str);
1194 // //
1195 // // int high = signalmanage->getRate() / parser.toInt();
1196 // // int low = signalmanage->getRate() / parser.toInt();
1197 // // int octave = parser.toBool ("true");
1198 // // double adjust = parser.toDouble ();
1199 // //
1200 // // for (int i = 0; i < AUTOKORRWIN; i++)
1201 // // autotable[i] = 1 - (((double)i * i * i) / (AUTOKORRWIN * AUTOKORRWIN * AUTOKORRWIN)); //generate static weighting function
1202 // //
1203 // // if (octave) for (int i = 0; i < AUTOKORRWIN; i++) weighttable[i] = 1; //initialise moving weight table
1204 // //
1205 // // Kwave::Label *newmark;
1206 // // int next;
1207 // // int len = signalmanage->getLength();
1208 // // int *sam = signalmanage->getSignal(0)->getSample(); // ### @@@ ###
1209 // // LabelType *start = markertype;
1210 // // int cnt = findFirstMark (sam, len);
1211 // //
1212 // // ProgressDialog *dialog = new ProgressDialog (len - AUTOKORRWIN, "Correlating Signal to find Periods:");
1213 // // if (dialog) {
1214 // // dialog->show();
1215 // //
1216 // // newmark = new Kwave::Label(cnt, start);
1217 // // labels->inSort (newmark);
1218 // //
1219 // // while (cnt < len - 2*AUTOKORRWIN) {
1220 // // if (octave)
1221 // // next = findNextRepeatOctave (&sam[cnt], high, adjust);
1222 // // else
1223 // // next = findNextRepeat (&sam[cnt], high);
1224 // //
1225 // // if ((next < low) && (next > high)) {
1226 // // newmark = new Kwave::Label(cnt, start);
1227 // //
1228 // // labels->inSort (newmark);
1229 // // }
1230 // // if (next < AUTOKORRWIN) cnt += next;
1231 // // else
1232 // // if (cnt < len - AUTOKORRWIN) {
1233 // // int a = findFirstMark (&sam[cnt], len - cnt);
1234 // // if (a > 0) cnt += a;
1235 // // else cnt += high;
1236 // // } else cnt = len;
1237 // //
1238 // // dialog->setProgress (cnt);
1239 // // }
1240 // //
1241 // // delete dialog;
1242 // //
1243 // // refresh ();
1244 // // }
1245 // // }
1246 // //}
1247 
1248 // ////*****************************************************************************
1249 // //int findNextRepeat (int *sample, int high)
1250 // ////autocorellation of a windowed part of the sample
1251 // ////returns length of period, if found
1252 // //{
1253 // // int i, j;
1254 // // double gmax = 0, max, c;
1255 // // int maxpos = AUTOKORRWIN;
1256 // // int down, up; //flags
1257 // //
1258 // // max = 0;
1259 // // for (j = 0; j < AUTOKORRWIN; j++)
1260 // // gmax += ((double)sample[j]) * sample [j];
1261 // //
1262 // // //correlate signal with itself for finding maximum integral
1263 // //
1264 // // down = 0;
1265 // // up = 0;
1266 // // i = high;
1267 // // max = 0;
1268 // // while (i < AUTOKORRWIN) {
1269 // // c = 0;
1270 // // for (j = 0; j < AUTOKORRWIN; j++) c += ((double)sample[j]) * sample [i + j];
1271 // // c = c * autotable[i]; //multiply window with weight for preference of high frequencies
1272 // // if (c > max) max = c, maxpos = i;
1273 // // i++;
1274 // // }
1275 // // return maxpos;
1276 // //}
1277 
1278 // ////*****************************************************************************
1279 // //int findNextRepeatOctave (int *sample, int high, double adjust = 1.005)
1280 // ////autocorellation of a windowed part of the sample
1281 // ////same as above only with an adaptive weighting to decrease fast period changes
1282 // //{
1283 // // int i, j;
1284 // // double gmax = 0, max, c;
1285 // // int maxpos = AUTOKORRWIN;
1286 // // int down, up; //flags
1287 // //
1288 // // max = 0;
1289 // // for (j = 0; j < AUTOKORRWIN; j++)
1290 // // gmax += ((double)sample[j]) * sample [j];
1291 // //
1292 // // //correlate signal with itself for finding maximum integral
1293 // //
1294 // // down = 0;
1295 // // up = 0;
1296 // // i = high;
1297 // // max = 0;
1298 // // while (i < AUTOKORRWIN) {
1299 // // c = 0;
1300 // // for (j = 0; j < AUTOKORRWIN; j++) c += ((double)sample[j]) * sample [i + j];
1301 // // c = c * autotable[i] * weighttable[i];
1302 // // //multiply window with weight for preference of high frequencies
1303 // // if (c > max) max = c, maxpos = i;
1304 // // i++;
1305 // // }
1306 // //
1307 // // for (int i = 0; i < AUTOKORRWIN; i++) weighttable[i] /= adjust;
1308 // //
1309 // // weighttable[maxpos] = 1;
1310 // // weighttable[maxpos + 1] = .9;
1311 // // weighttable[maxpos - 1] = .9;
1312 // // weighttable[maxpos + 2] = .8;
1313 // // weighttable[maxpos - 2] = .8;
1314 // //
1315 // // float buf[7];
1316 // //
1317 // // for (int i = 0; i < 7; buf[i++] = .1)
1318 // //
1319 // // //low pass filter
1320 // // for (int i = high; i < AUTOKORRWIN - 3; i++) {
1321 // // buf[i % 7] = weighttable[i + 3];
1322 // // weighttable[i] = (buf[0] + buf[1] + buf[2] + buf[3] + buf[4] + buf[5] + buf[6]) / 7;
1323 // // }
1324 // //
1325 // // return maxpos;
1326 // //}
1327 
1328 // //*****************************************************************************
1329 // //int findFirstMark (int *sample, int len)
1330 // ////finds first sample that is non-zero, or one that preceeds a zero crossing
1331 // //{
1332 // // int i = 1;
1333 // // int last = sample[0];
1334 // // int act = last;
1335 // // if ((last < 100) && (last > -100)) i = 0;
1336 // // else
1337 // // while (i < len) {
1338 // // act = sample[i];
1339 // // if ((act < 0) && (last >= 0)) break;
1340 // // if ((act > 0) && (last <= 0)) break;
1341 // // last = act;
1342 // // i++;
1343 // // }
1344 // // return i;
1345 // //}
1346 
1347 //***************************************************************************
1348 //***************************************************************************
sample_index_t toSampleIndex()
Definition: Parser.cpp:246
virtual void closeEvent(QCloseEvent *e) Q_DECL_OVERRIDE
Definition: MainWidget.cpp:347
bool isActive() const
Definition: FileContext.h:124
int loadBatch(const QUrl &url)
void selectRange(sample_index_t offset, sample_index_t length)
sample_index_t first() const
Definition: Selection.h:71
static sample_index_t decode(QWidget *widget, const QMimeData *e, Kwave::SignalManager &sig, sample_index_t pos)
Definition: Drag.cpp:76
QUrl selectedUrl() const
Definition: FileDialog.cpp:253
QTimer m_delayed_update_timer
Definition: MainWidget.h:371
Definition: App.h:33
void sigZoomChanged(double zoom)
virtual QSize sizeHint() const Q_DECL_OVERRIDE
void registerViewManager(Kwave::ViewManager *view_manager)
void zoomIn(int pos=-1)
Definition: MainWidget.cpp:847
sample_index_t last() const
Definition: Selection.h:76
double fullZoom() const
Definition: MainWidget.cpp:661
Kwave::MetaDataList & metaData()
virtual void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE
Definition: MainWidget.cpp:257
QVariant get(FileProperty key) const
Definition: FileInfo.cpp:372
void slotTrackInserted(unsigned int index, Kwave::Track *track)
Definition: MainWidget.cpp:353
int loadLabels(const QString &filename)
Definition: MainWidget.cpp:918
virtual void moveTo(sample_index_t position)
Definition: Label.cpp:49
Kwave::Selection & selection()
void deleteLabel(int index, bool with_undo)
virtual sample_index_t pos() const
Definition: Label.cpp:56
virtual void setLabelPosition(sample_index_t pos, sample_index_t length, double rate)
unsigned int tracks()
virtual void scrollTo(sample_index_t pos) Q_DECL_OVERRIDE
Definition: MainWidget.cpp:793
quint64 sample_index_t
Definition: Sample.h:28
Kwave::PlaybackController & playbackController()
void setRange(sample_index_t offset, sample_index_t viewport, sample_index_t total)
void zoomOut(int pos=-1)
Definition: MainWidget.cpp:867
static bool canDecode(const QMimeData *data)
Definition: Drag.cpp:42
int toInt()
Definition: Parser.cpp:216
sample_index_t ms2samples(double ms)
Definition: MainWidget.cpp:623
virtual int visibleWidth() const Q_DECL_OVERRIDE
Definition: MainWidget.cpp:649
#define LABEL_LIST_FILTER
Definition: MainWidget.cpp:90
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
void setModified(bool mod)
sample_index_t length() const
Definition: Selection.h:66
const char name[16]
Definition: memcpy.c:510
#define LABEL_LIST_EXT
Definition: MainWidget.cpp:85
QString signalName() const
int mapToViewPort(const QPoint &pos) const
void setZoomAndOffset(double zoom, sample_index_t offset)
bool labelProperties(Kwave::Label &label)
Kwave::OverViewWidget * m_overview
Definition: MainWidget.h:356
GuiType guiType() const
Definition: App.h:119
int labelIndex(const Kwave::Label &label) const
sample_index_t length()
int toInt(T x)
Definition: Utils.h:127
QVBoxLayout m_lower_dock
Definition: MainWidget.h:344
double rate() const
virtual bool isNull() const
Definition: MetaData.cpp:69
virtual sample_index_t visibleSamples() const Q_DECL_OVERRIDE
Definition: MainWidget.cpp:655
void metaDataChanged(Kwave::MetaDataList meta)
virtual QString name() const
Definition: Label.cpp:74
virtual bool isOK()
Definition: MainWidget.cpp:224
virtual void rename(const QString &name)
Definition: Label.cpp:64
Kwave::SignalWidget m_signal_widget
Definition: MainWidget.h:353
virtual ~MainWidget() Q_DECL_OVERRIDE
Definition: MainWidget.cpp:230
static int warningYesNoCancel(QWidget *widget, QString message, QString caption=QString(), const QString buttonYes=QString(), const QString buttonNo=QString(), const QString &dontAskAgainName=QString())
Definition: MessageBox.cpp:104
MainWidget(QWidget *parent, Kwave::FileContext &context, const QSize &preferred_size)
Definition: MainWidget.cpp:96
void sigVisibleRangeChanged(sample_index_t offset, sample_index_t visible, sample_index_t total)
#define DEFAULT_DISPLAY_TIME
Definition: MainWidget.cpp:80
static int warningYesNo(QWidget *widget, QString message, QString caption=QString(), const QString buttonYes=QString(), const QString buttonNo=QString(), const QString &dontAskAgainName=QString())
Definition: MessageBox.cpp:93
virtual void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE
Definition: MainWidget.cpp:269
bool hasParams()
Definition: Parser.h:57
int executeCommand(const QString &command)
sample_index_t m_offset
Definition: MainWidget.h:362
int saveLabels(const QString &filename)
Definition: MainWidget.cpp:952
Kwave::Label addLabel(sample_index_t pos, const QString &name)
virtual void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE
Definition: MainWidget.cpp:300
virtual sample_index_t labelPosition()
int visibleWidth() const
void setOffset(sample_index_t new_offset)
Definition: MainWidget.cpp:787
#define _(m)
Definition: memcpy.c:66
Kwave::FileContext & m_context
Definition: MainWidget.h:338
#define CASE_COMMAND(x)
Definition: MainWidget.cpp:68
static bool canDecode(const QMimeData *source)
Definition: FileDrag.h:34
bool isDone() const
Definition: Parser.h:70
#define DBG(qs)
Definition: String.h:55
Kwave::Label findLabel(sample_index_t pos)
sample_index_t pixels2samples(unsigned int pixels) const
Definition: MainWidget.cpp:634
virtual void setLabelIndex(unsigned int index)
bool modifyLabel(int index, sample_index_t pos, const QString &name, bool with_undo)
void sigCommand(const QString &command)
QScrollBar * m_horizontal_scrollbar
Definition: MainWidget.h:350
static void Q_DECL_EXPORT log(const QObject *sender, LogLevel level, const QString &msg)
Definition: Logger.cpp:103
virtual void setZoom(double new_zoom) Q_DECL_OVERRIDE
Definition: MainWidget.cpp:781
Kwave::PluginManager * pluginManager() const
virtual void setLabelName(const QString &name)
void addLabel(sample_index_t pos, const QString &description)
Definition: MainWidget.cpp:887
virtual double zoom() const Q_DECL_OVERRIDE
Definition: MainWidget.cpp:383
Kwave::SignalManager * signalManager() const
static QString escape(const QString &text)
Definition: Parser.cpp:277
void fixZoomAndOffset(double zoom, sample_index_t offset)
Definition: MainWidget.cpp:707
int samples2pixels(sample_index_t samples) const
Definition: MainWidget.cpp:642
QVBoxLayout m_upper_dock
Definition: MainWidget.h:341
void slotTrackDeleted(unsigned int index, Kwave::Track *track)
Definition: MainWidget.cpp:372
virtual int executeCommand(const QString &command) Q_DECL_OVERRIDE
Definition: MainWidget.cpp:389
void refreshHorizontalScrollBar()
Definition: MainWidget.cpp:520
Kwave::App & app() const
Definition: FileContext.h:93
#define MINIMUM_SAMPLES_PER_SCREEN
Definition: MainWidget.cpp:74
void horizontalScrollBarMoved(int newval)
Definition: MainWidget.cpp:580
sample_index_t offset() const
Definition: Selection.h:61
const QString & nextParam()
Definition: Parser.cpp:175
QScrollArea m_scroll_area
Definition: MainWidget.h:347
virtual void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE
Definition: MainWidget.cpp:238