kwave  18.07.70
SelectTimeWidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  SelectTimeWidget.cpp - widget for selecting a time or range
3  -------------------
4  begin : Thu Jan 16 2003
5  copyright : (C) 2002 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.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 <limits.h>
21 #include <math.h>
22 
23 #include <QRadioButton>
24 #include <QSlider>
25 #include <QWidget>
26 
27 #include <KLocalizedString>
28 
29 #include "libkwave/Utils.h"
30 
32 
33 //***************************************************************************
35  :QGroupBox(widget), Ui::SelectTimeWidgetBase(),
36  m_mode(bySamples), m_range(0), m_rate(1.0), m_offset(0), m_length(0),
37  m_timer(this)
38 {
39  setupUi(this);
40  modeChanged(true);
41 }
42 
43 //***************************************************************************
45  double sample_rate, sample_index_t offset,
46  sample_index_t signal_length)
47 {
48  m_mode = mode;
49  m_range = range;
50  m_rate = sample_rate;
51  m_offset = offset;
52  m_length = signal_length;
53 
54  Q_ASSERT(m_rate > 0);
55  Q_ASSERT(m_length);
56  Q_ASSERT(rbTime);
57  Q_ASSERT(rbSamples);
58  Q_ASSERT(rbPercents);
59  Q_ASSERT(m_offset < m_length);
60  if (m_rate <= 0) m_rate = 1.0;
61  if (!m_length) m_length = 1;
62 
63  // limit the length if necessary
64  if ((m_length - m_offset) > INT_MAX)
65  m_length = m_offset + INT_MAX;
66 
67  // set range of selection by sample
68  edSamples->setRange(0, Kwave::toInt(m_length - m_offset));
69  edSamples->setSingleStep(1);
70 
71  // set range of time controls
72  {
73  quint64 t = static_cast<quint64>((m_length * 1E3) / m_rate);
74  sbMilliseconds->setMaximum(Kwave::toInt(qMax(t, quint64(999))));
75  t /= 1000;
76  sbSeconds->setMaximum(Kwave::toInt(qMax(t, quint64(59))));
77  t /= 60;
78  sbMinutes->setMaximum(Kwave::toInt(qMax(t, quint64(59))));
79  t /= 60;
80  sbHours->setMaximum(Kwave::toInt(t));
81  }
82 
83  // activate the current mode
84  setMode(mode);
85  m_range = range;
86 
87  // set initial values
88  switch (m_mode) {
89  case byTime: {
90  quint64 t = m_range;
91  sbMilliseconds->setValue(Kwave::toInt(t % 1000));
92  t /= 1000;
93  sbSeconds->setValue(Kwave::toInt(t % 60));
94  t /= 60;
95  sbMinutes->setValue(Kwave::toInt(t % 60));
96  t /= 60;
97  sbHours->setValue(Kwave::toInt(t));
98  break;
99  }
100  case bySamples: {
101  quint64 samples = qMin<quint64>(m_range, INT_MAX);
102  edSamples->setValue(Kwave::toInt(samples));
103  break;
104  }
105  case byPercents: {
106  sbPercents->setValue(Kwave::toInt(m_range));
107  break;
108  }
109  }
110 
111  // connect mode controls
112  QObject::connect(rbTime, SIGNAL(toggled(bool)),
113  this, SLOT(modeChanged(bool)));
114  QObject::connect(rbSamples,SIGNAL(toggled(bool)),
115  this, SLOT(modeChanged(bool)));
116  QObject::connect(rbPercents,SIGNAL(toggled(bool)),
117  this, SLOT(modeChanged(bool)));
118 
119  connect();
120 
121  // connect percentage control
122  QObject::connect(sbPercents, SIGNAL(valueChanged(int)),
123  this, SLOT(percentsChanged(int)));
124 
125  // update all controls
126  switch (m_mode) {
127  case byTime:
128  timeChanged(0);
129  break;
130  case bySamples:
131  samplesChanged(0);
132  break;
133  case byPercents:
135  break;
136  }
137 
138  adjustSize();
139  setMinimumSize(sizeHint());
140  modeChanged(true);
141 }
142 
143 //***************************************************************************
145 {
146 }
147 
148 //***************************************************************************
150 {
151  // connect the time controls
152  QObject::connect(sbMilliseconds, SIGNAL(valueChanged(int)),
153  this, SLOT(timeChanged(int)));
154  QObject::connect(sbSeconds, SIGNAL(valueChanged(int)),
155  this, SLOT(timeChanged(int)));
156  QObject::connect(sbMinutes, SIGNAL(valueChanged(int)),
157  this, SLOT(timeChanged(int)));
158  QObject::connect(sbHours, SIGNAL(valueChanged(int)),
159  this, SLOT(timeChanged(int)));
160 
161  // connect sample count control
162  QObject::connect(edSamples, SIGNAL(valueChanged(int)),
163  this, SLOT(samplesChanged(int)));
164 
165  // connect the timer for the sample edit
166  QObject::connect(&m_timer, SIGNAL(timeout()),
167  this, SLOT(checkNewSampleEdit()));
168 
169 }
170 
171 //***************************************************************************
173 {
174  // disconnect the time controls
175  QObject::disconnect(sbMilliseconds, SIGNAL(valueChanged(int)),
176  this, SLOT(timeChanged(int)));
177  QObject::disconnect(sbSeconds, SIGNAL(valueChanged(int)),
178  this, SLOT(timeChanged(int)));
179  QObject::disconnect(sbMinutes, SIGNAL(valueChanged(int)),
180  this, SLOT(timeChanged(int)));
181  QObject::disconnect(sbHours, SIGNAL(valueChanged(int)),
182  this, SLOT(timeChanged(int)));
183 
184  // disconnect sample count control
185  QObject::disconnect(edSamples, SIGNAL(valueChanged(int)),
186  this, SLOT(samplesChanged(int)));
187 
188  // disconnect the timer for the sample edit
189  QObject::disconnect(&m_timer, SIGNAL(timeout()),
190  this, SLOT(checkNewSampleEdit()));
191 
192 }
193 
194 //***************************************************************************
196 {
197  // enable the selected mode
198  switch (new_mode) {
199  case byTime:
200  rbTime->setChecked(true);
201  Q_ASSERT(rbTime->isChecked());
202  Q_ASSERT(!rbSamples->isChecked());
203  Q_ASSERT(!rbPercents->isChecked());
204  break;
205  case bySamples:
206  rbSamples->setChecked(true);
207  Q_ASSERT(!rbTime->isChecked());
208  Q_ASSERT(rbSamples->isChecked());
209  Q_ASSERT(!rbPercents->isChecked());
210  break;
211  case byPercents:
212  rbPercents->setChecked(true);
213  Q_ASSERT(!rbTime->isChecked());
214  Q_ASSERT(!rbSamples->isChecked());
215  Q_ASSERT(rbPercents->isChecked());
216  break;
217  }
218  m_mode = new_mode;
219 }
220 
221 //***************************************************************************
223 {
224  if (!checked) return; // ignore disabling of radio buttons
225 
226  if (rbTime->isChecked()) {
227  m_mode = byTime;
228  rbSamples->setChecked(false);
229  rbPercents->setChecked(false);
230  timeChanged(0); // (sets m_range)
231  }
232 
233  if (rbSamples->isChecked()) {
234  m_mode = bySamples;
235  rbTime->setChecked(false);
236  rbPercents->setChecked(false);
237  samplesChanged(0); // (sets m_range)
238 
239  if (rbTime->isChecked()) {
240  m_timer.stop();
241  } else {
242  // activate the sample edit timer
243  m_timer.setSingleShot(false);
244  m_timer.start(100);
245  }
246 
247  }
248 
249  if (rbPercents->isChecked()) {
250  m_mode = byPercents;
251  rbTime->setChecked(false);
252  rbSamples->setChecked(false);
253  percentsChanged(sbPercents->value()); // (sets m_range)
254  }
255 
256 }
257 
258 //***************************************************************************
260 {
261  if (m_mode != byTime) return;
262  disconnect();
263 
264  // get current time and correct wrap-overs
265  int milliseconds = sbMilliseconds->value();
266  int seconds = sbSeconds->value();
267  int minutes = sbMinutes->value();
268  int hours = sbHours->value();
269 
270  if (milliseconds < 0) {
271  milliseconds = 999;
272  seconds--;
273  }
274  if (seconds < 0) {
275  seconds = 59;
276  minutes--;
277  }
278  if (minutes < 0) {
279  minutes = 59;
280  hours--;
281  }
282  if (hours < 0) {
283  hours = 0;
284  minutes = 0;
285  seconds = 0;
286  milliseconds = 0;
287  }
288  Q_ASSERT((hours >= 0) && (minutes >= 0) && (seconds >= 0) &&
289  (milliseconds >= 0));
290 
291  quint64 ms = milliseconds +
292  (seconds + (minutes + (hours * 60)) * 60) * 1000;
293 
294  // limit time
295  quint64 max_ms = static_cast<quint64>(
296  ceil(((m_length - m_offset) * 1E3) / m_rate));
297  if (ms > max_ms) ms = max_ms;
298  quint64 t = ms;
299 
300  milliseconds = Kwave::toInt(t % 1000L);
301  t /= 1000L;
302  seconds = Kwave::toInt(t % 60L);
303  t /= 60L;
304  minutes = Kwave::toInt(t % 60L);
305  hours = Kwave::toInt(t / 60L);
306 
307  sbMilliseconds->setValue(milliseconds);
308  sbSeconds->setValue(seconds);
309  sbMinutes->setValue(minutes);
310  sbHours->setValue(hours);
311 
312  // update the other widgets
314  edSamples->setValue(Kwave::toInt(samples));
315  quint64 percents = samplesToTime(byPercents, samples, m_rate, m_length);
316  sbPercents->setValue(Kwave::toInt(percents));
317 
318  // set range in byTime mode [ms]
319  m_range = ms;
320 
321  emit valueChanged(samples); // emit the change
322  connect();
323 }
324 
325 //***************************************************************************
327 {
328  static int last_samples = -1;
329  if (edSamples->value() != last_samples) {
330  last_samples = edSamples->value();
331  samplesChanged(last_samples);
332  }
333 }
334 
335 //***************************************************************************
337 {
338  if (m_mode != bySamples) return;
339  disconnect();
340 
341  sample_index_t max_samples = m_length - m_offset;
342  sample_index_t samples = edSamples->value();
343 
344  // limit the current value
345  if (samples > max_samples) samples = max_samples;
346 
347  // update the other widgets
348  quint64 t = samplesToTime(byTime, samples, m_rate, m_length);
349  sbMilliseconds->setValue(Kwave::toInt(t % 1000));
350  t /= 1000;
351  sbSeconds->setValue(Kwave::toInt(t % 60));
352  t /= 60;
353  sbMinutes->setValue(Kwave::toInt(t % 60));
354  t /= 60;
355  sbHours->setValue(Kwave::toInt(t));
356 
357  quint64 percents = samplesToTime(byPercents, samples, m_rate, m_length);
358  sbPercents->setValue(Kwave::toInt(percents));
359 
360  // update in samples mode
361  m_range = samples;
362 
363  // re-activate the sample edit timer
364  m_timer.stop();
365  m_timer.setSingleShot(false);
366  m_timer.start(100);
367 
368  emit valueChanged(samples); // emit the change
369  connect();
370 }
371 
372 //***************************************************************************
374 {
375  if (m_mode != byPercents) return;
376  disconnect();
377 
378  // limit to rest of signal
379  int max_percents = 100;
380  if (m_length)
381  max_percents = Kwave::toInt(
382  (100U * static_cast<quint64>(m_length - m_offset)) /
383  static_cast<quint64>(m_length));
384  if (p > max_percents) p = max_percents;
385 
386  // update in byPercents mode [0...100]
387  m_range = p;
388 
389  if (slidePercents->value() != p) slidePercents->setValue(p);
390  if (sbPercents->value() != p) sbPercents->setValue(p);
391 
392  // update the other widgets
394  edSamples->setValue(Kwave::toInt(samples));
395 
396  quint64 t = samplesToTime(byTime, samples, m_rate, m_length);
397  sbMilliseconds->setValue(Kwave::toInt(t % 1000));
398  t /= 1000;
399  sbSeconds->setValue(Kwave::toInt(t % 60));
400  t /= 60;
401  sbMinutes->setValue(Kwave::toInt(t % 60));
402  t /= 60;
403  sbHours->setValue(Kwave::toInt(t));
404 
405  emit valueChanged(samples); // emit the change
406  connect();
407 }
408 
409 //***************************************************************************
410 void Kwave::SelectTimeWidget::setTitle(const QString title)
411 {
412  QGroupBox::setTitle(title);
413 }
414 
415 //***************************************************************************
417 {
418  m_offset = offset;
419  sample_index_t max_samples = m_length - m_offset;
420  sample_index_t samples = edSamples->value();
421 
422  // the range of the sample edit should always get updated
423  if (max_samples > INT_MAX)
424  max_samples = INT_MAX; // limit the length to INT_MAX
425  edSamples->setRange(0, Kwave::toInt(max_samples));
426  edSamples->setSingleStep(1);
427 
428  // no range conflict -> nothing to do
429  if (samples <= max_samples) return;
430 
431  // limit the length to the rest
432  samples = max_samples;
433 
434  // update all widgets
435  disconnect();
436 
437  quint64 t = samplesToTime(bySamples, samples, m_rate, m_length);
438  sbMilliseconds->setValue(Kwave::toInt(t % 1000));
439  t /= 1000;
440  sbSeconds->setValue(Kwave::toInt(t % 60));
441  t /= 60;
442  sbMinutes->setValue(Kwave::toInt(t % 60));
443  t /= 60;
444  sbHours->setValue(Kwave::toInt(t));
445 
446  Q_ASSERT(samples <= INT_MAX);
447  if (samples > INT_MAX) samples = INT_MAX;
448  edSamples->setValue(Kwave::toInt(samples));
449 
450  double percents = 100.0 * static_cast<double>(samples) /
451  static_cast<double>(m_length);
452  sbPercents->setValue(Kwave::toInt(percents));
453 
454  connect();
455 }
456 
457 //***************************************************************************
459 {
460  return (edSamples) ? edSamples->value() : 0;
461 }
462 
463 //***************************************************************************
465  Kwave::SelectTimeWidget::Mode mode, quint64 time, double rate,
466  sample_index_t length)
467 {
468  sample_index_t pos = 0;
469  switch (mode) {
471  // convert from ms to samples
472  pos = static_cast<sample_index_t>(ceil(
473  static_cast<double>(time) * (rate * 1E-3)));
474  break;
476  // simple case -> already in samples
477  pos = time;
478  break;
480  // by percentage of whole signal
481  pos = static_cast<unsigned int>(rint(
482  static_cast<double>(length * (time / 100.0))));
483  break;
484  }
485 
486  if (pos > INT_MAX) pos = INT_MAX;
487  return pos;
488 }
489 
490 //***************************************************************************
492  Mode mode, sample_index_t samples, double rate, sample_index_t length)
493 {
494  quint64 time = 0;
495 
496  switch (mode) {
498  // convert from samples to ms
499  time = static_cast<quint64>(
500  rint(static_cast<double>(samples) * 1E3 / rate));
501  break;
503  // simple case -> already in samples
504  time = samples;
505  break;
507  // by percentage of whole signal
508  time = static_cast<quint64>(100.0 *
509  static_cast<double>(samples) /
510  static_cast<double>(length));
511  break;
512  }
513 
514  return time;
515 }
516 
517 //***************************************************************************
518 //***************************************************************************
sample_index_t samples() const
quint64 sample_index_t
Definition: Sample.h:28
void setOffset(sample_index_t offset)
void valueChanged(sample_index_t samples)
static quint64 samplesToTime(Mode mode, sample_index_t time, double rate, sample_index_t length)
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
void modeChanged(bool checked)
static sample_index_t timeToSamples(Mode mode, quint64 time, double rate, sample_index_t length)
int toInt(T x)
Definition: Utils.h:127
virtual void setTitle(const QString title)
virtual void init(Mode mode, quint64 range, double sample_rate, sample_index_t offset, sample_index_t signal_length)
SelectTimeWidget(QWidget *widget)
void setMode(Mode new_mode)