ctkSpinBox.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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. // CTK includes
  15. #include "ctkSpinBox.h"
  16. #include "ctkUtils.h"
  17. #include "ctkPimpl.h"
  18. #include <QDebug>
  19. // Qt includes
  20. #include <QDoubleSpinBox>
  21. #include <QEvent>
  22. #include <QHBoxLayout>
  23. #include <QKeySequence>
  24. #include <QShortcut>
  25. #include <QSizePolicy>
  26. #include <QVariant>
  27. //-----------------------------------------------------------------------------
  28. class ctkSpinBoxPrivate
  29. {
  30. Q_DECLARE_PUBLIC(ctkSpinBox);
  31. protected:
  32. ctkSpinBox* const q_ptr;
  33. public:
  34. ctkSpinBoxPrivate(ctkSpinBox& object);
  35. QDoubleSpinBox* SpinBox;
  36. ctkSpinBox::SetMode Mode;
  37. void init();
  38. // Compare two double previously rounded according to the number of decimals
  39. bool compare(double x1, double x2) const;
  40. };
  41. //-----------------------------------------------------------------------------
  42. ctkSpinBoxPrivate::ctkSpinBoxPrivate(ctkSpinBox& object) : q_ptr(&object)
  43. {
  44. qRegisterMetaType<ctkSpinBox::SetMode>("ctkSpinBox::SetMode");
  45. this->SpinBox = 0;
  46. this->Mode = ctkSpinBox::SetIfDifferent;
  47. }
  48. //-----------------------------------------------------------------------------
  49. void ctkSpinBoxPrivate::init()
  50. {
  51. Q_Q(ctkSpinBox);
  52. this->SpinBox = new QDoubleSpinBox(q);
  53. QObject::connect(this->SpinBox, SIGNAL(valueChanged(double)),
  54. q, SIGNAL(valueChanged(double)));
  55. QObject::connect(this->SpinBox, SIGNAL(valueChanged(const QString&)),
  56. q, SIGNAL(valueChanged(const QString &)));
  57. QObject::connect(this->SpinBox, SIGNAL(editingFinished()),
  58. q, SIGNAL(editingFinished()));
  59. QHBoxLayout* l = new QHBoxLayout(q);
  60. l->addWidget(this->SpinBox);
  61. l->setContentsMargins(0,0,0,0);
  62. q->setLayout(l);
  63. q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum,
  64. QSizePolicy::Fixed, QSizePolicy::ButtonBox));
  65. }
  66. //-----------------------------------------------------------------------------
  67. bool ctkSpinBoxPrivate::compare(double x1, double x2) const
  68. {
  69. Q_Q(const ctkSpinBox);
  70. return q->round(x1) == q->round(x2);
  71. }
  72. //-----------------------------------------------------------------------------
  73. ctkSpinBox::ctkSpinBox(QWidget* newParent)
  74. : QWidget(newParent)
  75. , d_ptr(new ctkSpinBoxPrivate(*this))
  76. {
  77. Q_D(ctkSpinBox);
  78. d->init();
  79. }
  80. //-----------------------------------------------------------------------------
  81. ctkSpinBox::ctkSpinBox(ctkSpinBox::SetMode mode, QWidget* newParent)
  82. : QWidget(newParent)
  83. , d_ptr(new ctkSpinBoxPrivate(*this))
  84. {
  85. Q_D(ctkSpinBox);
  86. d->init();
  87. this->setSetMode(mode);
  88. }
  89. //-----------------------------------------------------------------------------
  90. double ctkSpinBox::value() const
  91. {
  92. Q_D(const ctkSpinBox);
  93. return d->SpinBox->value();
  94. }
  95. //-----------------------------------------------------------------------------
  96. double ctkSpinBox::displayedValue() const
  97. {
  98. Q_D(const ctkSpinBox);
  99. return this->round(this->value());
  100. }
  101. //-----------------------------------------------------------------------------
  102. QString ctkSpinBox::text() const
  103. {
  104. Q_D(const ctkSpinBox);
  105. return d->SpinBox->text();
  106. }
  107. //-----------------------------------------------------------------------------
  108. QString ctkSpinBox::cleanText() const
  109. {
  110. Q_D(const ctkSpinBox);
  111. return d->SpinBox->cleanText();
  112. }
  113. //-----------------------------------------------------------------------------
  114. Qt::Alignment ctkSpinBox::alignment() const
  115. {
  116. Q_D(const ctkSpinBox);
  117. return d->SpinBox->alignment();
  118. }
  119. //-----------------------------------------------------------------------------
  120. void ctkSpinBox::setAlignment(Qt::Alignment flag)
  121. {
  122. Q_D(const ctkSpinBox);
  123. if (d->Mode == ctkSpinBox::SetIfDifferent && flag == d->SpinBox->alignment())
  124. {
  125. return;
  126. }
  127. d->SpinBox->setAlignment(flag);
  128. }
  129. //-----------------------------------------------------------------------------
  130. void ctkSpinBox::setFrame(bool frame)
  131. {
  132. Q_D(const ctkSpinBox);
  133. if (d->Mode == ctkSpinBox::SetIfDifferent && frame == d->SpinBox->hasFrame())
  134. {
  135. return;
  136. }
  137. d->SpinBox->setFrame(frame);
  138. }
  139. //-----------------------------------------------------------------------------
  140. bool ctkSpinBox::hasFrame() const
  141. {
  142. Q_D(const ctkSpinBox);
  143. return d->SpinBox->hasFrame();
  144. }
  145. //-----------------------------------------------------------------------------
  146. QString ctkSpinBox::prefix() const
  147. {
  148. Q_D(const ctkSpinBox);
  149. return d->SpinBox->prefix();
  150. }
  151. //-----------------------------------------------------------------------------
  152. void ctkSpinBox::setPrefix(const QString &prefix)
  153. {
  154. Q_D(const ctkSpinBox);
  155. if (d->Mode == ctkSpinBox::SetIfDifferent && prefix == d->SpinBox->prefix())
  156. {
  157. return;
  158. }
  159. #if QT_VERSION < 0x040800
  160. /// Setting the prefix doesn't recompute the sizehint, do it manually here:
  161. /// See: http://bugreports.qt.nokia.com/browse/QTBUG-9530
  162. d->SpinBox->setRange(d->SpinBox->minimum(), d->SpinBox->maximum());
  163. #endif
  164. d->SpinBox->setPrefix(prefix);
  165. }
  166. //-----------------------------------------------------------------------------
  167. QString ctkSpinBox::suffix() const
  168. {
  169. Q_D(const ctkSpinBox);
  170. return d->SpinBox->suffix();
  171. }
  172. //-----------------------------------------------------------------------------
  173. void ctkSpinBox::setSuffix(const QString &suffix)
  174. {
  175. Q_D(const ctkSpinBox);
  176. if (d->Mode == ctkSpinBox::SetIfDifferent && suffix == d->SpinBox->suffix())
  177. {
  178. return;
  179. }
  180. #if QT_VERSION < 0x040800
  181. /// Setting the suffix doesn't recompute the sizehint, do it manually here:
  182. /// See: http://bugreports.qt.nokia.com/browse/QTBUG-9530
  183. d->SpinBox->setRange(d->SpinBox->minimum(), d->SpinBox->maximum());
  184. #endif
  185. d->SpinBox->setSuffix(suffix);
  186. }
  187. //-----------------------------------------------------------------------------
  188. double ctkSpinBox::singleStep() const
  189. {
  190. Q_D(const ctkSpinBox);
  191. return d->SpinBox->singleStep();
  192. }
  193. //-----------------------------------------------------------------------------
  194. void ctkSpinBox::setSingleStep(double step)
  195. {
  196. Q_D(ctkSpinBox);
  197. if (d->Mode == ctkSpinBox::SetIfDifferent
  198. && d->compare(step, this->singleStep()))
  199. {
  200. return;
  201. }
  202. d->SpinBox->setSingleStep(step);
  203. }
  204. //-----------------------------------------------------------------------------
  205. double ctkSpinBox::minimum() const
  206. {
  207. Q_D(const ctkSpinBox);
  208. return d->SpinBox->minimum();
  209. }
  210. //-----------------------------------------------------------------------------
  211. void ctkSpinBox::setMinimum(double min)
  212. {
  213. Q_D(ctkSpinBox);
  214. if (d->Mode == ctkSpinBox::SetIfDifferent
  215. && d->compare(min, this->minimum()))
  216. {
  217. return;
  218. }
  219. d->SpinBox->setMinimum(min);
  220. }
  221. //-----------------------------------------------------------------------------
  222. double ctkSpinBox::maximum() const
  223. {
  224. Q_D(const ctkSpinBox);
  225. return d->SpinBox->maximum();
  226. }
  227. //-----------------------------------------------------------------------------
  228. void ctkSpinBox::setMaximum(double max)
  229. {
  230. Q_D(ctkSpinBox);
  231. if (d->Mode == ctkSpinBox::SetIfDifferent
  232. && d->compare(max, this->maximum()))
  233. {
  234. return;
  235. }
  236. d->SpinBox->setMaximum(max);
  237. }
  238. //-----------------------------------------------------------------------------
  239. void ctkSpinBox::setRange(double min, double max)
  240. {
  241. Q_D(ctkSpinBox);
  242. if (d->Mode == ctkSpinBox::SetIfDifferent
  243. && d->compare(max, this->maximum()) && d->compare(min, this->minimum()))
  244. {
  245. return;
  246. }
  247. d->SpinBox->setRange(min, max);
  248. }
  249. //-----------------------------------------------------------------------------
  250. int ctkSpinBox::decimals() const
  251. {
  252. Q_D(const ctkSpinBox);
  253. return d->SpinBox->decimals();
  254. }
  255. //-----------------------------------------------------------------------------
  256. void ctkSpinBox::setDecimals(int dec)
  257. {
  258. Q_D(const ctkSpinBox);
  259. if (d->Mode == ctkSpinBox::SetIfDifferent && dec == d->SpinBox->decimals())
  260. {
  261. return;
  262. }
  263. d->SpinBox->setDecimals(dec);
  264. }
  265. //-----------------------------------------------------------------------------
  266. double ctkSpinBox::round(double value) const
  267. {
  268. Q_D(const ctkSpinBox);
  269. return QString::number(value, 'f', d->SpinBox->decimals()).toDouble();
  270. }
  271. //-----------------------------------------------------------------------------
  272. QDoubleSpinBox* ctkSpinBox::spinBox() const
  273. {
  274. Q_D(const ctkSpinBox);
  275. return d->SpinBox;
  276. }
  277. //-----------------------------------------------------------------------------
  278. void ctkSpinBox::setValue(double value)
  279. {
  280. Q_D(const ctkSpinBox);
  281. if (d->Mode == ctkSpinBox::SetIfDifferent)
  282. {
  283. this->setValueIfDifferent(value);
  284. }
  285. else
  286. {
  287. this->setValueAlways(value);
  288. }
  289. }
  290. //-----------------------------------------------------------------------------
  291. void ctkSpinBox::setValueIfDifferent(double value)
  292. {
  293. Q_D(ctkSpinBox);
  294. if (! d->compare(this->value(), value))
  295. {
  296. d->SpinBox->setValue(value);
  297. }
  298. }
  299. //-----------------------------------------------------------------------------
  300. void ctkSpinBox::setValueAlways(double value)
  301. {
  302. Q_D(const ctkSpinBox);
  303. d->SpinBox->setValue(value);
  304. }
  305. //-----------------------------------------------------------------------------
  306. void ctkSpinBox::stepUp()
  307. {
  308. Q_D(const ctkSpinBox);
  309. d->SpinBox->stepUp();
  310. }
  311. //-----------------------------------------------------------------------------
  312. void ctkSpinBox::stepDown()
  313. {
  314. Q_D(const ctkSpinBox);
  315. d->SpinBox->stepDown();
  316. }
  317. //-----------------------------------------------------------------------------
  318. ctkSpinBox::SetMode ctkSpinBox::setMode() const
  319. {
  320. Q_D(const ctkSpinBox);
  321. return d->Mode;
  322. }
  323. //-----------------------------------------------------------------------------
  324. void ctkSpinBox::setSetMode(ctkSpinBox::SetMode newMode)
  325. {
  326. Q_D(ctkSpinBox);
  327. d->Mode = newMode;
  328. }