ctkDoubleRangeSlider.cpp 24 KB

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