ctkDoubleRangeSlider.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. // Qt includes
  15. #include <QDebug>
  16. #include <QHBoxLayout>
  17. #include <QPointer>
  18. #include <QVariant>
  19. // CTK includes
  20. #include "ctkRangeSlider.h"
  21. #include "ctkDoubleRangeSlider.h"
  22. #include "ctkValueProxy.h"
  23. // STD includes
  24. #include <limits>
  25. //-----------------------------------------------------------------------------
  26. class ctkDoubleRangeSliderPrivate
  27. {
  28. Q_DECLARE_PUBLIC(ctkDoubleRangeSlider);
  29. protected:
  30. ctkDoubleRangeSlider* const q_ptr;
  31. public:
  32. ctkDoubleRangeSliderPrivate(ctkDoubleRangeSlider& object);
  33. int toInt(double _value)const;
  34. double minFromInt(int _value)const;
  35. double maxFromInt(int _value)const;
  36. double safeMinFromInt(int _value)const;
  37. double safeMaxFromInt(int _value)const;
  38. void init();
  39. void connectSlider();
  40. void updateMinOffset(double value);
  41. void updateMaxOffset(double value);
  42. ctkRangeSlider* Slider;
  43. double Minimum;
  44. double Maximum;
  45. bool SettingRange;
  46. // we should have a MinValueOffset and MinPositionOffset (and MinimumOffset?)
  47. double MinOffset;
  48. // we should have a MaxValueOffset and MaxPositionOffset (and MaximumOffset?)
  49. double MaxOffset;
  50. double SingleStep;
  51. double MinValue;
  52. double MaxValue;
  53. QPointer<ctkValueProxy> Proxy;
  54. private:
  55. Q_DISABLE_COPY(ctkDoubleRangeSliderPrivate);
  56. };
  57. // --------------------------------------------------------------------------
  58. ctkDoubleRangeSliderPrivate::ctkDoubleRangeSliderPrivate(ctkDoubleRangeSlider& object)
  59. :q_ptr(&object)
  60. {
  61. // the initial values will be overwritten in
  62. // ctkDoubleRangeSliderPrivate::init()
  63. this->Slider = 0;
  64. this->Minimum = 0.;
  65. this->Maximum = 99.;
  66. this->SettingRange = false;
  67. this->MinOffset = 0.;
  68. this->MaxOffset = 0.;
  69. this->SingleStep = 1.;
  70. this->MinValue = 0.;
  71. this->MaxValue = 99.;
  72. }
  73. // --------------------------------------------------------------------------
  74. void ctkDoubleRangeSliderPrivate::init()
  75. {
  76. Q_Q(ctkDoubleRangeSlider);
  77. this->Slider = new ctkRangeSlider(q);
  78. QHBoxLayout* l = new QHBoxLayout(q);
  79. l->addWidget(this->Slider);
  80. l->setContentsMargins(0,0,0,0);
  81. this->Minimum = this->Slider->minimum();
  82. this->Maximum = this->Slider->maximum();
  83. this->MinValue = this->Slider->minimumValue();
  84. this->MaxValue = this->Slider->maximumValue();
  85. this->SingleStep = this->Slider->singleStep();
  86. q->setSizePolicy(this->Slider->sizePolicy());
  87. q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
  88. this->connectSlider();
  89. }
  90. // --------------------------------------------------------------------------
  91. void ctkDoubleRangeSliderPrivate::connectSlider()
  92. {
  93. Q_Q(ctkDoubleRangeSlider);
  94. q->connect(this->Slider, SIGNAL(valuesChanged(int,int)),
  95. q, SLOT(onValuesChanged(int,int)));
  96. q->connect(this->Slider, SIGNAL(minimumPositionChanged(int)),
  97. q, SLOT(onMinPosChanged(int)));
  98. q->connect(this->Slider, SIGNAL(maximumPositionChanged(int)),
  99. q, SLOT(onMaxPosChanged(int)));
  100. q->connect(this->Slider, SIGNAL(positionsChanged(int,int)),
  101. q, SLOT(onPositionsChanged(int,int)));
  102. q->connect(this->Slider, SIGNAL(sliderPressed()),
  103. q, SIGNAL(sliderPressed()));
  104. q->connect(this->Slider, SIGNAL(sliderReleased()),
  105. q, SIGNAL(sliderReleased()));
  106. q->connect(this->Slider, SIGNAL(rangeChanged(int,int)),
  107. q, SLOT(onRangeChanged(int,int)));
  108. }
  109. // --------------------------------------------------------------------------
  110. int ctkDoubleRangeSliderPrivate::toInt(double doubleValue)const
  111. {
  112. double tmp = doubleValue / this->SingleStep;
  113. static const double minInt = std::numeric_limits<int>::min();
  114. static const double maxInt = std::numeric_limits<int>::max();
  115. #ifndef QT_NO_DEBUG
  116. static const double maxDouble = std::numeric_limits<double>::max();
  117. if ( (tmp < minInt || tmp > maxInt) &&
  118. // If the value is the min or max double, there is no need
  119. // to warn. It is expected that the number is outside of bounds.
  120. (doubleValue != -maxDouble && doubleValue != maxDouble) )
  121. {
  122. qWarning() << __FUNCTION__ << ": value " << doubleValue
  123. << " for singleStep " << this->SingleStep
  124. << " is out of integer bounds !";
  125. }
  126. #endif
  127. tmp = qBound(minInt, tmp, maxInt);
  128. int intValue = qRound(tmp);
  129. return intValue;
  130. }
  131. // --------------------------------------------------------------------------
  132. double ctkDoubleRangeSliderPrivate::minFromInt(int intValue)const
  133. {
  134. double doubleValue = this->SingleStep * (this->MinOffset + intValue) ;
  135. return doubleValue;
  136. }
  137. // --------------------------------------------------------------------------
  138. double ctkDoubleRangeSliderPrivate::maxFromInt(int intValue)const
  139. {
  140. double doubleValue = this->SingleStep * (this->MaxOffset + intValue) ;
  141. return doubleValue;
  142. }
  143. // --------------------------------------------------------------------------
  144. double ctkDoubleRangeSliderPrivate::safeMinFromInt(int intValue)const
  145. {
  146. return qBound(this->Minimum, this->minFromInt(intValue), this->Maximum);
  147. }
  148. // --------------------------------------------------------------------------
  149. double ctkDoubleRangeSliderPrivate::safeMaxFromInt(int intValue)const
  150. {
  151. return qBound(this->Minimum, this->maxFromInt(intValue), this->Maximum);
  152. }
  153. // --------------------------------------------------------------------------
  154. void ctkDoubleRangeSliderPrivate::updateMinOffset(double value)
  155. {
  156. this->MinOffset = (value / this->SingleStep) - this->toInt(value);
  157. }
  158. // --------------------------------------------------------------------------
  159. void ctkDoubleRangeSliderPrivate::updateMaxOffset(double value)
  160. {
  161. this->MaxOffset = (value / this->SingleStep) - this->toInt(value);
  162. }
  163. // --------------------------------------------------------------------------
  164. ctkDoubleRangeSlider::ctkDoubleRangeSlider(QWidget* _parent) : Superclass(_parent)
  165. , d_ptr(new ctkDoubleRangeSliderPrivate(*this))
  166. {
  167. Q_D(ctkDoubleRangeSlider);
  168. d->init();
  169. }
  170. // --------------------------------------------------------------------------
  171. ctkDoubleRangeSlider::ctkDoubleRangeSlider(Qt::Orientation _orientation, QWidget* _parent)
  172. : Superclass(_parent)
  173. , d_ptr(new ctkDoubleRangeSliderPrivate(*this))
  174. {
  175. Q_D(ctkDoubleRangeSlider);
  176. d->init();
  177. this->setOrientation(_orientation);
  178. }
  179. // --------------------------------------------------------------------------
  180. ctkDoubleRangeSlider::~ctkDoubleRangeSlider()
  181. {
  182. }
  183. // --------------------------------------------------------------------------
  184. void ctkDoubleRangeSlider::setMinimum(double newMin)
  185. {
  186. Q_D(ctkDoubleRangeSlider);
  187. if (d->Proxy)
  188. {
  189. newMin = d->Proxy.data()->proxyValueFromValue(newMin);
  190. }
  191. double oldMin = d->Minimum;
  192. d->Minimum = newMin;
  193. if (d->Minimum >= d->MinValue)
  194. {// TBD: use same offset
  195. d->updateMinOffset(d->Minimum);
  196. }
  197. if (d->Minimum >= d->MaxValue)
  198. {// TBD: use same offset
  199. d->updateMaxOffset(d->Minimum);
  200. }
  201. bool wasSettingRange = d->SettingRange;
  202. d->SettingRange = true;
  203. d->Slider->setMinimum(d->toInt(newMin));
  204. d->SettingRange = wasSettingRange;
  205. if (!wasSettingRange && d->Minimum != oldMin)
  206. {
  207. emit this->rangeChanged(this->minimum(), this->maximum());
  208. }
  209. }
  210. // --------------------------------------------------------------------------
  211. double ctkDoubleRangeSlider::minimum()const
  212. {
  213. Q_D(const ctkDoubleRangeSlider);
  214. double min = d->Minimum;
  215. double max = d->Maximum;
  216. if (d->Proxy)
  217. {
  218. min = d->Proxy.data()->valueFromProxyValue(min);
  219. max = d->Proxy.data()->valueFromProxyValue(max);
  220. }
  221. return qMin(min, max);
  222. }
  223. // --------------------------------------------------------------------------
  224. void ctkDoubleRangeSlider::setMaximum(double newMax)
  225. {
  226. Q_D(ctkDoubleRangeSlider);
  227. if (d->Proxy)
  228. {
  229. newMax = d->Proxy.data()->proxyValueFromValue(newMax);
  230. }
  231. double oldMax = d->Maximum;
  232. d->Maximum = newMax;
  233. if (d->Maximum <= d->MinValue)
  234. {// TBD: use same offset
  235. d->updateMinOffset(d->Maximum);
  236. }
  237. if (d->Maximum <= d->MaxValue)
  238. {// TBD: use same offset ?
  239. d->updateMaxOffset(d->Maximum);
  240. }
  241. bool wasSettingRange = d->SettingRange;
  242. d->SettingRange = true;
  243. d->Slider->setMaximum(d->toInt(newMax));
  244. d->SettingRange = wasSettingRange;
  245. if (!wasSettingRange && d->Maximum != oldMax)
  246. {
  247. emit this->rangeChanged(this->minimum(), this->maximum());
  248. }
  249. }
  250. // --------------------------------------------------------------------------
  251. double ctkDoubleRangeSlider::maximum()const
  252. {
  253. Q_D(const ctkDoubleRangeSlider);
  254. double min = d->Minimum;
  255. double max = d->Maximum;
  256. if (d->Proxy)
  257. {
  258. min = d->Proxy.data()->valueFromProxyValue(min);
  259. max = d->Proxy.data()->valueFromProxyValue(max);
  260. }
  261. return qMax(min, max);
  262. }
  263. // --------------------------------------------------------------------------
  264. void ctkDoubleRangeSlider::setRange(double newMin, double newMax)
  265. {
  266. Q_D(ctkDoubleRangeSlider);
  267. if (d->Proxy)
  268. {
  269. newMin = d->Proxy.data()->proxyValueFromValue(newMin);
  270. newMax = d->Proxy.data()->proxyValueFromValue(newMax);
  271. }
  272. if (newMin > newMax)
  273. {
  274. qSwap(newMin, newMax);
  275. }
  276. double oldMin = d->Minimum;
  277. double oldMax = d->Maximum;
  278. d->Minimum = newMin;
  279. d->Maximum = newMax;
  280. if (d->Minimum >= d->MinValue)
  281. {// TBD: use same offset
  282. d->updateMinOffset(d->Minimum);
  283. }
  284. if (d->Minimum >= d->MaxValue)
  285. {// TBD: use same offset
  286. d->updateMaxOffset(d->Minimum);
  287. }
  288. if (d->Maximum <= d->MinValue)
  289. {// TBD: use same offset
  290. d->updateMinOffset(d->Maximum);
  291. }
  292. if (d->Maximum <= d->MaxValue)
  293. {// TBD: use same offset ?
  294. d->updateMaxOffset(d->Maximum);
  295. }
  296. bool wasSettingRange = d->SettingRange;
  297. d->SettingRange = true;
  298. d->Slider->setRange(d->toInt(newMin), d->toInt(newMax));
  299. d->SettingRange = wasSettingRange;
  300. if (!wasSettingRange && (d->Minimum != oldMin || d->Maximum != oldMax))
  301. {
  302. emit this->rangeChanged(this->minimum(), this->maximum());
  303. }
  304. }
  305. // --------------------------------------------------------------------------
  306. double ctkDoubleRangeSlider::minimumPosition()const
  307. {
  308. Q_D(const ctkDoubleRangeSlider);
  309. int intMinPos = d->Slider->minimumPosition();
  310. double minPos = d->safeMinFromInt(intMinPos);
  311. if (d->Proxy)
  312. {
  313. minPos = d->Proxy.data()->valueFromProxyValue(minPos);
  314. }
  315. return minPos;
  316. }
  317. // --------------------------------------------------------------------------
  318. void ctkDoubleRangeSlider::setMinimumPosition(double newMinPos)
  319. {
  320. Q_D(ctkDoubleRangeSlider);
  321. if (d->Proxy)
  322. {
  323. newMinPos = d->Proxy.data()->proxyValueFromValue(newMinPos);
  324. }
  325. int newIntMinPos = d->toInt(newMinPos);
  326. d->Slider->setMinimumPosition(newIntMinPos);
  327. }
  328. // --------------------------------------------------------------------------
  329. double ctkDoubleRangeSlider::maximumPosition()const
  330. {
  331. Q_D(const ctkDoubleRangeSlider);
  332. int intMaxPos = d->Slider->maximumPosition();
  333. double maxPos = d->safeMaxFromInt(intMaxPos);
  334. if (d->Proxy)
  335. {
  336. maxPos = d->Proxy.data()->valueFromProxyValue(maxPos);
  337. }
  338. return maxPos;
  339. }
  340. // --------------------------------------------------------------------------
  341. void ctkDoubleRangeSlider::setMaximumPosition(double newMaxPos)
  342. {
  343. Q_D(ctkDoubleRangeSlider);
  344. if (d->Proxy)
  345. {
  346. newMaxPos = d->Proxy.data()->proxyValueFromValue(newMaxPos);
  347. }
  348. int newIntMaxPos = d->toInt(newMaxPos);
  349. d->Slider->setMaximumPosition(newIntMaxPos);
  350. }
  351. // --------------------------------------------------------------------------
  352. void ctkDoubleRangeSlider::setPositions(double newMinPos, double newMaxPos)
  353. {
  354. Q_D(ctkDoubleRangeSlider);
  355. if (d->Proxy)
  356. {
  357. newMinPos = d->Proxy.data()->proxyValueFromValue(newMinPos);
  358. newMaxPos = d->Proxy.data()->proxyValueFromValue(newMaxPos);
  359. }
  360. int newIntMinPos = d->toInt(newMinPos);
  361. int newIntMaxPos = d->toInt(newMaxPos);
  362. d->Slider->setPositions(newIntMinPos, newIntMaxPos);
  363. }
  364. // --------------------------------------------------------------------------
  365. double ctkDoubleRangeSlider::minimumValue()const
  366. {
  367. Q_D(const ctkDoubleRangeSlider);
  368. double minValue = d->MinValue;
  369. double maxValue = d->MaxValue;
  370. if (d->Proxy)
  371. {
  372. minValue = d->Proxy.data()->valueFromProxyValue(minValue);
  373. maxValue = d->Proxy.data()->valueFromProxyValue(maxValue);
  374. }
  375. return qMin(minValue, maxValue);
  376. }
  377. // --------------------------------------------------------------------------
  378. void ctkDoubleRangeSlider::setMinimumValue(double newMinValue)
  379. {
  380. Q_D(ctkDoubleRangeSlider);
  381. if (d->Proxy)
  382. {
  383. newMinValue = d->Proxy.data()->proxyValueFromValue(newMinValue);
  384. }
  385. newMinValue = qBound(d->Minimum, newMinValue, d->Maximum);
  386. d->updateMinOffset(newMinValue);
  387. if (newMinValue >= d->MaxValue)
  388. {
  389. d->updateMaxOffset(newMinValue);
  390. }
  391. int newIntValue = d->toInt(newMinValue);
  392. if (newIntValue != d->Slider->minimumValue())
  393. {
  394. // d->Slider will emit a minimumValueChanged signal that is connected to
  395. // ctkDoubleSlider::onValueChanged
  396. d->Slider->setMinimumValue(newIntValue);
  397. }
  398. else
  399. {
  400. double oldValue = d->MinValue;
  401. d->MinValue = newMinValue;
  402. // don't emit a valuechanged signal if the new value is quite
  403. // similar to the old value.
  404. if (qAbs(newMinValue - oldValue) > (d->SingleStep * 0.000000001))
  405. {
  406. emit this->valuesChanged(this->minimumValue(), this->maximumValue());
  407. emit this->minimumValueChanged(this->minimumValue());
  408. }
  409. }
  410. }
  411. // --------------------------------------------------------------------------
  412. double ctkDoubleRangeSlider::maximumValue()const
  413. {
  414. Q_D(const ctkDoubleRangeSlider);
  415. double minValue = d->MinValue;
  416. double maxValue = d->MaxValue;
  417. if (d->Proxy)
  418. {
  419. minValue = d->Proxy.data()->valueFromProxyValue(minValue);
  420. maxValue = d->Proxy.data()->valueFromProxyValue(maxValue);
  421. }
  422. return qMax(minValue, maxValue);
  423. }
  424. // --------------------------------------------------------------------------
  425. void ctkDoubleRangeSlider::setMaximumValue(double newMaxValue)
  426. {
  427. Q_D(ctkDoubleRangeSlider);
  428. if (d->Proxy)
  429. {
  430. newMaxValue = d->Proxy.data()->proxyValueFromValue(newMaxValue);
  431. }
  432. newMaxValue = qBound(d->Minimum, newMaxValue, d->Maximum);
  433. d->updateMaxOffset(newMaxValue);
  434. if (newMaxValue <= d->MinValue)
  435. {
  436. d->updateMinOffset(newMaxValue);
  437. }
  438. int newIntValue = d->toInt(newMaxValue);
  439. if (newIntValue != d->Slider->maximumValue())
  440. {
  441. // d->Slider will emit a maximumValueChanged signal that is connected to
  442. // ctkDoubleSlider::onValueChanged
  443. d->Slider->setMaximumValue(newIntValue);
  444. }
  445. else
  446. {
  447. double oldValue = d->MaxValue;
  448. d->MaxValue = newMaxValue;
  449. // don't emit a valuechanged signal if the new value is quite
  450. // similar to the old value.
  451. if (qAbs(newMaxValue - oldValue) > (d->SingleStep * 0.000000001))
  452. {
  453. emit this->valuesChanged(this->minimumValue(), this->maximumValue());
  454. emit this->maximumValueChanged(this->maximumValue());
  455. }
  456. }
  457. }
  458. // --------------------------------------------------------------------------
  459. void ctkDoubleRangeSlider::setValues(double newMinVal, double newMaxVal)
  460. {
  461. Q_D(ctkDoubleRangeSlider);
  462. // We can't call setMinimumValue() and setMaximumValue() as they would
  463. // generate an inconsistent state. when minimumValueChanged() is fired the
  464. // new max value wouldn't be updated yet.
  465. if (d->Proxy)
  466. {
  467. newMaxVal = d->Proxy.data()->proxyValueFromValue(newMaxVal);
  468. newMinVal = d->Proxy.data()->proxyValueFromValue(newMinVal);
  469. }
  470. double newMinValue = qBound(d->Minimum, qMin(newMinVal, newMaxVal), d->Maximum);
  471. double newMaxValue = qBound(d->Minimum, qMax(newMinVal, newMaxVal), d->Maximum);
  472. d->updateMinOffset(newMinValue);
  473. d->updateMaxOffset(newMaxValue);
  474. int newMinIntValue = d->toInt(newMinValue);
  475. int newMaxIntValue = d->toInt(newMaxValue);
  476. if (newMinIntValue != d->Slider->minimumValue() ||
  477. newMaxIntValue != d->Slider->maximumValue())
  478. {
  479. // d->Slider will emit a maximumValueChanged signal that is connected to
  480. // ctkDoubleSlider::onValueChanged
  481. d->Slider->setValues(newMinIntValue, newMaxIntValue);
  482. }
  483. else
  484. {
  485. double oldMinValue = d->MinValue;
  486. double oldMaxValue = d->MaxValue;
  487. d->MinValue = newMinValue;
  488. d->MaxValue = newMaxValue;
  489. // don't emit a valuechanged signal if the new value is quite
  490. // similar to the old value.
  491. bool minChanged = qAbs(newMinValue - oldMinValue) > (d->SingleStep * 0.000000001);
  492. bool maxChanged = qAbs(newMaxValue - oldMaxValue) > (d->SingleStep * 0.000000001);
  493. if (minChanged || maxChanged)
  494. {
  495. emit this->valuesChanged(this->minimumValue(), this->maximumValue());
  496. if (minChanged)
  497. {
  498. emit this->minimumValueChanged(this->minimumValue());
  499. }
  500. if (maxChanged)
  501. {
  502. emit this->maximumValueChanged(this->maximumValue());
  503. }
  504. }
  505. }
  506. }
  507. // --------------------------------------------------------------------------
  508. double ctkDoubleRangeSlider::singleStep()const
  509. {
  510. Q_D(const ctkDoubleRangeSlider);
  511. double step = d->SingleStep;
  512. return step;
  513. }
  514. // --------------------------------------------------------------------------
  515. void ctkDoubleRangeSlider::setSingleStep(double newStep)
  516. {
  517. Q_D(ctkDoubleRangeSlider);
  518. if (!this->isValidStep(newStep))
  519. {
  520. qWarning() << "ctkDoubleRangeSlider::setSingleStep("<< newStep <<")"
  521. << "is outside of valid bounds.";
  522. return;
  523. }
  524. d->SingleStep = newStep;
  525. // The following can fire A LOT of signals that shouldn't be fired.
  526. bool oldBlockSignals = this->blockSignals(true);
  527. d->updateMinOffset(d->MinValue);
  528. d->updateMaxOffset(d->MaxValue);
  529. double minimum = d->Minimum;
  530. double maximum = d->Maximum;
  531. // update the new int values
  532. double minValue = d->MinValue;
  533. double maxValue = d->MaxValue;
  534. if (d->Proxy)
  535. {
  536. minimum = d->Proxy.data()->valueFromProxyValue(minimum);
  537. maximum = d->Proxy.data()->valueFromProxyValue(maximum);
  538. minValue = d->Proxy.data()->valueFromProxyValue(minValue);
  539. maxValue = d->Proxy.data()->valueFromProxyValue(maxValue);
  540. }
  541. // calling setRange can change the MinimumValue and MaximumValue values,
  542. // this is why we re-set them after.
  543. this->setRange(minimum, maximum);
  544. this->setValues(minValue, maxValue);
  545. this->setPositions(minValue, maxValue);
  546. this->blockSignals(oldBlockSignals);
  547. }
  548. // --------------------------------------------------------------------------
  549. bool ctkDoubleRangeSlider::isValidStep(double step)const
  550. {
  551. Q_D(const ctkDoubleRangeSlider);
  552. if (d->Minimum == d->Maximum)
  553. {
  554. return true;
  555. }
  556. const double minStep = qMax(d->Maximum / std::numeric_limits<double>::max(),
  557. std::numeric_limits<double>::epsilon());
  558. const double maxStep = qMin(d->Maximum - d->Minimum,
  559. static_cast<double>(std::numeric_limits<int>::max()));
  560. return (step >= minStep) && (step <= maxStep);
  561. }
  562. // --------------------------------------------------------------------------
  563. double ctkDoubleRangeSlider::tickInterval()const
  564. {
  565. Q_D(const ctkDoubleRangeSlider);
  566. double interval = d->SingleStep * d->Slider->tickInterval();
  567. if (d->Proxy)
  568. {
  569. interval = d->Proxy.data()->valueFromProxyValue(interval);
  570. }
  571. return interval;
  572. }
  573. // --------------------------------------------------------------------------
  574. void ctkDoubleRangeSlider::setTickInterval(double newInterval)
  575. {
  576. Q_D(ctkDoubleRangeSlider);
  577. if (d->Proxy)
  578. {
  579. newInterval = d->Proxy.data()->proxyValueFromValue(newInterval);
  580. }
  581. int newIntInterval = d->toInt(newInterval);
  582. d->Slider->setTickInterval(newIntInterval);
  583. }
  584. // --------------------------------------------------------------------------
  585. QSlider::TickPosition ctkDoubleRangeSlider::tickPosition()const
  586. {
  587. Q_D(const ctkDoubleRangeSlider);
  588. return d->Slider->tickPosition();
  589. }
  590. // --------------------------------------------------------------------------
  591. void ctkDoubleRangeSlider::setTickPosition(QSlider::TickPosition newTickPosition)
  592. {
  593. Q_D(ctkDoubleRangeSlider);
  594. d->Slider->setTickPosition(newTickPosition);
  595. }
  596. // --------------------------------------------------------------------------
  597. bool ctkDoubleRangeSlider::hasTracking()const
  598. {
  599. Q_D(const ctkDoubleRangeSlider);
  600. return d->Slider->hasTracking();
  601. }
  602. // --------------------------------------------------------------------------
  603. void ctkDoubleRangeSlider::setTracking(bool enable)
  604. {
  605. Q_D(ctkDoubleRangeSlider);
  606. d->Slider->setTracking(enable);
  607. }
  608. // --------------------------------------------------------------------------
  609. void ctkDoubleRangeSlider::triggerAction( QAbstractSlider::SliderAction action)
  610. {
  611. Q_D(ctkDoubleRangeSlider);
  612. d->Slider->triggerAction(action);
  613. }
  614. // --------------------------------------------------------------------------
  615. void ctkDoubleRangeSlider::setOrientation(Qt::Orientation newOrientation)
  616. {
  617. Q_D(ctkDoubleRangeSlider);
  618. if (this->orientation() == newOrientation)
  619. {
  620. return;
  621. }
  622. if (!testAttribute(Qt::WA_WState_OwnSizePolicy))
  623. {
  624. QSizePolicy sp = this->sizePolicy();
  625. sp.transpose();
  626. this->setSizePolicy(sp);
  627. this->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
  628. }
  629. // d->Slider will take care of calling updateGeometry
  630. d->Slider->setOrientation(newOrientation);
  631. }
  632. // --------------------------------------------------------------------------
  633. Qt::Orientation ctkDoubleRangeSlider::orientation()const
  634. {
  635. Q_D(const ctkDoubleRangeSlider);
  636. return d->Slider->orientation();
  637. }
  638. // --------------------------------------------------------------------------
  639. bool ctkDoubleRangeSlider::symmetricMoves()const
  640. {
  641. Q_D(const ctkDoubleRangeSlider);
  642. return d->Slider->symmetricMoves();
  643. }
  644. // --------------------------------------------------------------------------
  645. void ctkDoubleRangeSlider::setSymmetricMoves(bool symmetry)
  646. {
  647. Q_D(ctkDoubleRangeSlider);
  648. d->Slider->setSymmetricMoves(symmetry);
  649. }
  650. // --------------------------------------------------------------------------
  651. void ctkDoubleRangeSlider::onValuesChanged(int newMinValue, int newMaxValue)
  652. {
  653. Q_D(ctkDoubleRangeSlider);
  654. double doubleNewMinValue = d->safeMinFromInt(newMinValue);
  655. double doubleNewMaxValue = d->safeMaxFromInt(newMaxValue);
  656. bool emitMinValueChanged = (d->MinValue != doubleNewMinValue);
  657. bool emitMaxValueChanged = (d->MaxValue != doubleNewMaxValue);
  658. if (!emitMinValueChanged && !emitMaxValueChanged)
  659. {
  660. return;
  661. }
  662. d->MinValue = doubleNewMinValue;
  663. d->MaxValue = doubleNewMaxValue;
  664. emit this->valuesChanged(this->minimumValue(), this->maximumValue());
  665. if (emitMinValueChanged)
  666. {
  667. emit this->minimumValueChanged(this->minimumValue());
  668. }
  669. if (emitMaxValueChanged)
  670. {
  671. emit this->maximumValueChanged(this->maximumValue());
  672. }
  673. }
  674. // --------------------------------------------------------------------------
  675. void ctkDoubleRangeSlider::onMinPosChanged(int newIntMinPos)
  676. {
  677. Q_D(const ctkDoubleRangeSlider);
  678. double newMinPos = d->safeMinFromInt(newIntMinPos);
  679. if (d->Proxy)
  680. {
  681. newMinPos = d->Proxy.data()->valueFromProxyValue(newMinPos);
  682. }
  683. emit this->minimumPositionChanged(newMinPos);
  684. }
  685. // --------------------------------------------------------------------------
  686. void ctkDoubleRangeSlider::onMaxPosChanged(int newIntMaxPos)
  687. {
  688. Q_D(const ctkDoubleRangeSlider);
  689. double newMaxPos = d->safeMaxFromInt(newIntMaxPos);
  690. if (d->Proxy)
  691. {
  692. //newMaxPos = d->Proxy.data()->valueFromProxyValue(newMaxPos);
  693. }
  694. emit this->maximumPositionChanged(newMaxPos);
  695. }
  696. // --------------------------------------------------------------------------
  697. void ctkDoubleRangeSlider::onPositionsChanged(int newIntMinPos, int newIntMaxPos)
  698. {
  699. Q_D(const ctkDoubleRangeSlider);
  700. double newMinPos = d->safeMinFromInt(newIntMinPos);
  701. double newMaxPos = d->safeMaxFromInt(newIntMaxPos);
  702. if (d->Proxy)
  703. {
  704. newMinPos = d->Proxy.data()->valueFromProxyValue(newMinPos);
  705. newMaxPos = d->Proxy.data()->valueFromProxyValue(newMaxPos);
  706. }
  707. emit this->positionsChanged(newMinPos, newMaxPos);
  708. }
  709. // --------------------------------------------------------------------------
  710. void ctkDoubleRangeSlider::onRangeChanged(int newIntMin, int newIntMax)
  711. {
  712. Q_D(const ctkDoubleRangeSlider);
  713. if (d->SettingRange)
  714. {
  715. return;
  716. }
  717. double newMin = d->minFromInt(newIntMin);
  718. double newMax = d->maxFromInt(newIntMax);
  719. if (d->Proxy)
  720. {
  721. newMin = d->Proxy.data()->valueFromProxyValue(newMin);
  722. newMax = d->Proxy.data()->valueFromProxyValue(newMax);
  723. }
  724. this->setRange(newMin, newMax);
  725. }
  726. // --------------------------------------------------------------------------
  727. ctkRangeSlider* ctkDoubleRangeSlider::slider()const
  728. {
  729. Q_D(const ctkDoubleRangeSlider);
  730. return d->Slider;
  731. }
  732. // --------------------------------------------------------------------------
  733. void ctkDoubleRangeSlider::setSlider(ctkRangeSlider* newslider)
  734. {
  735. Q_D(ctkDoubleRangeSlider);
  736. newslider->setOrientation(d->Slider->orientation());
  737. newslider->setMinimum(d->Slider->minimum());
  738. newslider->setMaximum(d->Slider->maximum());
  739. newslider->setValues(d->Slider->minimumValue(), d->Slider->maximumValue());
  740. newslider->setSingleStep(d->Slider->singleStep());
  741. newslider->setTracking(d->Slider->hasTracking());
  742. newslider->setTickInterval(d->Slider->tickInterval());
  743. newslider->setTickPosition(d->Slider->tickPosition());
  744. delete d->Slider;
  745. qobject_cast<QHBoxLayout*>(this->layout())->addWidget(newslider);
  746. d->Slider = newslider;
  747. d->connectSlider();
  748. }
  749. //----------------------------------------------------------------------------
  750. void ctkDoubleRangeSlider::setValueProxy(ctkValueProxy* proxy)
  751. {
  752. Q_D(ctkDoubleRangeSlider);
  753. if (proxy == d->Proxy.data())
  754. {
  755. return;
  756. }
  757. this->onValueProxyAboutToBeModified();
  758. if (d->Proxy.data())
  759. {
  760. disconnect(d->Proxy.data(), 0, this, 0);
  761. }
  762. d->Proxy = proxy;
  763. if (d->Proxy)
  764. {
  765. connect(d->Proxy.data(), SIGNAL(proxyAboutToBeModified()),
  766. this, SLOT(onValueProxyAboutToBeModified()));
  767. connect(d->Proxy.data(), SIGNAL(proxyModified()),
  768. this, SLOT(onValueProxyModified()));
  769. }
  770. this->onValueProxyModified();
  771. }
  772. //----------------------------------------------------------------------------
  773. ctkValueProxy* ctkDoubleRangeSlider::valueProxy() const
  774. {
  775. Q_D(const ctkDoubleRangeSlider);
  776. return d->Proxy.data();
  777. }
  778. //-----------------------------------------------------------------------------
  779. void ctkDoubleRangeSlider::onValueProxyAboutToBeModified()
  780. {
  781. Q_D(ctkDoubleRangeSlider);
  782. d->Slider->setProperty("inputMinimumValue", this->minimumValue());
  783. d->Slider->setProperty("inputMaximumValue", this->maximumValue());
  784. d->Slider->setProperty("inputMinimum", this->minimum());
  785. d->Slider->setProperty("inputMaximum", this->maximum());
  786. }
  787. //-----------------------------------------------------------------------------
  788. void ctkDoubleRangeSlider::onValueProxyModified()
  789. {
  790. Q_D(ctkDoubleRangeSlider);
  791. bool wasBlockingSignals = this->blockSignals(true);
  792. bool wasSettingRange = d->SettingRange;
  793. d->SettingRange = true;
  794. this->setRange(d->Slider->property("inputMinimum").toDouble(),
  795. d->Slider->property("inputMaximum").toDouble());
  796. d->SettingRange = wasSettingRange;
  797. this->setValues(d->Slider->property("inputMinimumValue").toDouble(),
  798. d->Slider->property("inputMaximumValue").toDouble());
  799. this->blockSignals(wasBlockingSignals);
  800. }