63 |
63 |
64 class QSpinBoxPrivate : public QAbstractSpinBoxPrivate |
64 class QSpinBoxPrivate : public QAbstractSpinBoxPrivate |
65 { |
65 { |
66 Q_DECLARE_PUBLIC(QSpinBox) |
66 Q_DECLARE_PUBLIC(QSpinBox) |
67 public: |
67 public: |
68 QSpinBoxPrivate(QWidget *parent = 0); |
68 QSpinBoxPrivate(); |
69 void emitSignals(EmitPolicy ep, const QVariant &); |
69 void emitSignals(EmitPolicy ep, const QVariant &); |
70 |
70 |
71 virtual QVariant valueFromText(const QString &n) const; |
71 virtual QVariant valueFromText(const QString &n) const; |
72 virtual QString textFromValue(const QVariant &n) const; |
72 virtual QString textFromValue(const QVariant &n) const; |
73 QVariant validateAndInterpret(QString &input, int &pos, |
73 QVariant validateAndInterpret(QString &input, int &pos, |
74 QValidator::State &state) const; |
74 QValidator::State &state) const; |
75 QChar thousand; |
|
76 |
75 |
77 inline void init() { |
76 inline void init() { |
78 Q_Q(QSpinBox); |
77 Q_Q(QSpinBox); |
79 q->setInputMethodHints(Qt::ImhDigitsOnly); |
78 q->setInputMethodHints(Qt::ImhDigitsOnly); |
80 setLayoutItemMargins(QStyle::SE_SpinBoxLayoutItem); |
79 setLayoutItemMargins(QStyle::SE_SpinBoxLayoutItem); |
83 |
82 |
84 class QDoubleSpinBoxPrivate : public QAbstractSpinBoxPrivate |
83 class QDoubleSpinBoxPrivate : public QAbstractSpinBoxPrivate |
85 { |
84 { |
86 Q_DECLARE_PUBLIC(QDoubleSpinBox) |
85 Q_DECLARE_PUBLIC(QDoubleSpinBox) |
87 public: |
86 public: |
88 QDoubleSpinBoxPrivate(QWidget *parent = 0); |
87 QDoubleSpinBoxPrivate(); |
89 void emitSignals(EmitPolicy ep, const QVariant &); |
88 void emitSignals(EmitPolicy ep, const QVariant &); |
90 |
89 |
91 virtual QVariant valueFromText(const QString &n) const; |
90 virtual QVariant valueFromText(const QString &n) const; |
92 virtual QString textFromValue(const QVariant &n) const; |
91 virtual QString textFromValue(const QVariant &n) const; |
93 QVariant validateAndInterpret(QString &input, int &pos, |
92 QVariant validateAndInterpret(QString &input, int &pos, |
94 QValidator::State &state) const; |
93 QValidator::State &state) const; |
95 double round(double input) const; |
94 double round(double input) const; |
96 // variables |
95 // variables |
97 int decimals; |
96 int decimals; |
98 QChar delimiter, thousand; |
|
99 |
97 |
100 inline void init() { |
98 inline void init() { |
101 Q_Q(QDoubleSpinBox); |
99 Q_Q(QDoubleSpinBox); |
102 q->setInputMethodHints(Qt::ImhFormattedNumbersOnly); |
100 q->setInputMethodHints(Qt::ImhFormattedNumbersOnly); |
103 } |
101 } |
223 /*! |
221 /*! |
224 Use one of the constructors that doesn't take the \a name |
222 Use one of the constructors that doesn't take the \a name |
225 argument and then use setObjectName() instead. |
223 argument and then use setObjectName() instead. |
226 */ |
224 */ |
227 QSpinBox::QSpinBox(int minimum, int maximum, int step, QWidget *parent, const char *name) |
225 QSpinBox::QSpinBox(int minimum, int maximum, int step, QWidget *parent, const char *name) |
228 : QAbstractSpinBox(*new QSpinBoxPrivate(parent), parent) |
226 : QAbstractSpinBox(*new QSpinBoxPrivate, parent) |
229 { |
227 { |
230 Q_D(QSpinBox); |
228 Q_D(QSpinBox); |
231 d->minimum = QVariant(qMin<int>(minimum, maximum)); |
229 d->minimum = QVariant(qMin<int>(minimum, maximum)); |
232 d->maximum = QVariant(qMax<int>(minimum, maximum)); |
230 d->maximum = QVariant(qMax<int>(minimum, maximum)); |
233 d->singleStep = QVariant(step); |
231 d->singleStep = QVariant(step); |
918 /*! |
913 /*! |
919 \reimp |
914 \reimp |
920 */ |
915 */ |
921 void QDoubleSpinBox::fixup(QString &input) const |
916 void QDoubleSpinBox::fixup(QString &input) const |
922 { |
917 { |
923 Q_D(const QDoubleSpinBox); |
918 input.remove(locale().groupSeparator()); |
924 |
|
925 input.remove(d->thousand); |
|
926 } |
919 } |
927 |
920 |
928 // --- QSpinBoxPrivate --- |
921 // --- QSpinBoxPrivate --- |
929 |
922 |
930 /*! |
923 /*! |
931 \internal |
924 \internal |
932 Constructs a QSpinBoxPrivate object |
925 Constructs a QSpinBoxPrivate object |
933 */ |
926 */ |
934 |
927 |
935 QSpinBoxPrivate::QSpinBoxPrivate(QWidget *parent) |
928 QSpinBoxPrivate::QSpinBoxPrivate() |
936 { |
929 { |
937 minimum = QVariant((int)0); |
930 minimum = QVariant((int)0); |
938 maximum = QVariant((int)99); |
931 maximum = QVariant((int)99); |
939 value = minimum; |
932 value = minimum; |
940 singleStep = QVariant((int)1); |
933 singleStep = QVariant((int)1); |
941 type = QVariant::Int; |
934 type = QVariant::Int; |
942 const QString str = (parent ? parent->locale() : QLocale()).toString(4567); |
|
943 if (str.size() == 5) { |
|
944 thousand = QChar(str.at(1)); |
|
945 } |
|
946 |
|
947 } |
935 } |
948 |
936 |
949 /*! |
937 /*! |
950 \internal |
938 \internal |
951 \reimp |
939 \reimp |
1017 QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num; |
1005 QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num; |
1018 } else if (copy.startsWith(QLatin1Char('-')) && min >= 0) { |
1006 } else if (copy.startsWith(QLatin1Char('-')) && min >= 0) { |
1019 state = QValidator::Invalid; // special-case -0 will be interpreted as 0 and thus not be invalid with a range from 0-100 |
1007 state = QValidator::Invalid; // special-case -0 will be interpreted as 0 and thus not be invalid with a range from 0-100 |
1020 } else { |
1008 } else { |
1021 bool ok = false; |
1009 bool ok = false; |
1022 bool removedThousand = false; |
|
1023 num = locale.toInt(copy, &ok, 10); |
1010 num = locale.toInt(copy, &ok, 10); |
1024 if (!ok && copy.contains(thousand) && (max >= 1000 || min <= -1000)) { |
1011 if (!ok && copy.contains(locale.groupSeparator()) && (max >= 1000 || min <= -1000)) { |
1025 const int s = copy.size(); |
1012 QString copy2 = copy; |
1026 copy.remove(thousand); |
1013 copy2.remove(locale.groupSeparator()); |
1027 pos = qMax(0, pos - (s - copy.size())); |
1014 num = locale.toInt(copy2, &ok, 10); |
1028 removedThousand = true; |
|
1029 num = locale.toInt(copy, &ok, 10); |
|
1030 } |
1015 } |
1031 QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num; |
1016 QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num; |
1032 if (!ok) { |
1017 if (!ok) { |
1033 state = QValidator::Invalid; |
1018 state = QValidator::Invalid; |
1034 } else if (num >= min && num <= max) { |
1019 } else if (num >= min && num <= max) { |
1035 state = removedThousand ? QValidator::Intermediate : QValidator::Acceptable; |
1020 state = QValidator::Acceptable; |
1036 } else if (max == min) { |
1021 } else if (max == min) { |
1037 state = QValidator::Invalid; |
1022 state = QValidator::Invalid; |
1038 } else { |
1023 } else { |
1039 if ((num >= 0 && num > max) || (num < 0 && num < min)) { |
1024 if ((num >= 0 && num > max) || (num < 0 && num < min)) { |
1040 state = QValidator::Invalid; |
1025 state = QValidator::Invalid; |
1062 /*! |
1047 /*! |
1063 \internal |
1048 \internal |
1064 Constructs a QSpinBoxPrivate object |
1049 Constructs a QSpinBoxPrivate object |
1065 */ |
1050 */ |
1066 |
1051 |
1067 QDoubleSpinBoxPrivate::QDoubleSpinBoxPrivate(QWidget *parent) |
1052 QDoubleSpinBoxPrivate::QDoubleSpinBoxPrivate() |
1068 { |
1053 { |
1069 minimum = QVariant(0.0); |
1054 minimum = QVariant(0.0); |
1070 maximum = QVariant(99.99); |
1055 maximum = QVariant(99.99); |
1071 value = minimum; |
1056 value = minimum; |
1072 singleStep = QVariant(1.0); |
1057 singleStep = QVariant(1.0); |
1073 decimals = 2; |
1058 decimals = 2; |
1074 type = QVariant::Double; |
1059 type = QVariant::Double; |
1075 const QString str = (parent ? parent->locale() : QLocale()).toString(4567.1); |
|
1076 if (str.size() == 6) { |
|
1077 delimiter = str.at(4); |
|
1078 thousand = QChar((ushort)0); |
|
1079 } else if (str.size() == 7) { |
|
1080 thousand = str.at(1); |
|
1081 delimiter = str.at(5); |
|
1082 } |
|
1083 Q_ASSERT(!delimiter.isNull()); |
|
1084 } |
1060 } |
1085 |
1061 |
1086 /*! |
1062 /*! |
1087 \internal |
1063 \internal |
1088 \reimp |
1064 \reimp |
1153 switch (len) { |
1129 switch (len) { |
1154 case 0: |
1130 case 0: |
1155 state = max != min ? QValidator::Intermediate : QValidator::Invalid; |
1131 state = max != min ? QValidator::Intermediate : QValidator::Invalid; |
1156 goto end; |
1132 goto end; |
1157 case 1: |
1133 case 1: |
1158 if (copy.at(0) == delimiter |
1134 if (copy.at(0) == locale.decimalPoint() |
1159 || (plus && copy.at(0) == QLatin1Char('+')) |
1135 || (plus && copy.at(0) == QLatin1Char('+')) |
1160 || (minus && copy.at(0) == QLatin1Char('-'))) { |
1136 || (minus && copy.at(0) == QLatin1Char('-'))) { |
1161 state = QValidator::Intermediate; |
1137 state = QValidator::Intermediate; |
1162 goto end; |
1138 goto end; |
1163 } |
1139 } |
1164 break; |
1140 break; |
1165 case 2: |
1141 case 2: |
1166 if (copy.at(1) == delimiter |
1142 if (copy.at(1) == locale.decimalPoint() |
1167 && ((plus && copy.at(0) == QLatin1Char('+')) || (minus && copy.at(0) == QLatin1Char('-')))) { |
1143 && ((plus && copy.at(0) == QLatin1Char('+')) || (minus && copy.at(0) == QLatin1Char('-')))) { |
1168 state = QValidator::Intermediate; |
1144 state = QValidator::Intermediate; |
1169 goto end; |
1145 goto end; |
1170 } |
1146 } |
1171 break; |
1147 break; |
1172 default: break; |
1148 default: break; |
1173 } |
1149 } |
1174 |
1150 |
1175 if (copy.at(0) == thousand) { |
1151 if (copy.at(0) == locale.groupSeparator()) { |
1176 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1152 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1177 state = QValidator::Invalid; |
1153 state = QValidator::Invalid; |
1178 goto end; |
1154 goto end; |
1179 } else if (len > 1) { |
1155 } else if (len > 1) { |
1180 const int dec = copy.indexOf(delimiter); |
1156 const int dec = copy.indexOf(locale.decimalPoint()); |
1181 if (dec != -1) { |
1157 if (dec != -1) { |
1182 if (dec + 1 < copy.size() && copy.at(dec + 1) == delimiter && pos == dec + 1) { |
1158 if (dec + 1 < copy.size() && copy.at(dec + 1) == locale.decimalPoint() && pos == dec + 1) { |
1183 copy.remove(dec + 1, 1); // typing a delimiter when you are on the delimiter |
1159 copy.remove(dec + 1, 1); // typing a delimiter when you are on the delimiter |
1184 } // should be treated as typing right arrow |
1160 } // should be treated as typing right arrow |
1185 |
1161 |
1186 if (copy.size() - dec > decimals + 1) { |
1162 if (copy.size() - dec > decimals + 1) { |
1187 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1163 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1188 state = QValidator::Invalid; |
1164 state = QValidator::Invalid; |
1189 goto end; |
1165 goto end; |
1190 } |
1166 } |
1191 for (int i=dec + 1; i<copy.size(); ++i) { |
1167 for (int i=dec + 1; i<copy.size(); ++i) { |
1192 if (copy.at(i).isSpace() || copy.at(i) == thousand) { |
1168 if (copy.at(i).isSpace() || copy.at(i) == locale.groupSeparator()) { |
1193 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1169 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1194 state = QValidator::Invalid; |
1170 state = QValidator::Invalid; |
1195 goto end; |
1171 goto end; |
1196 } |
1172 } |
1197 } |
1173 } |
1198 } else { |
1174 } else { |
1199 const QChar &last = copy.at(len - 1); |
1175 const QChar &last = copy.at(len - 1); |
1200 const QChar &secondLast = copy.at(len - 2); |
1176 const QChar &secondLast = copy.at(len - 2); |
1201 if ((last == thousand || last.isSpace()) |
1177 if ((last == locale.groupSeparator() || last.isSpace()) |
1202 && (secondLast == thousand || secondLast.isSpace())) { |
1178 && (secondLast == locale.groupSeparator() || secondLast.isSpace())) { |
1203 state = QValidator::Invalid; |
1179 state = QValidator::Invalid; |
1204 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1180 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1205 goto end; |
1181 goto end; |
1206 } else if (last.isSpace() && (!thousand.isSpace() || secondLast.isSpace())) { |
1182 } else if (last.isSpace() && (!locale.groupSeparator().isSpace() || secondLast.isSpace())) { |
1207 state = QValidator::Invalid; |
1183 state = QValidator::Invalid; |
1208 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1184 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1209 goto end; |
1185 goto end; |
1210 } |
1186 } |
1211 } |
1187 } |
1213 |
1189 |
1214 { |
1190 { |
1215 bool ok = false; |
1191 bool ok = false; |
1216 num = locale.toDouble(copy, &ok); |
1192 num = locale.toDouble(copy, &ok); |
1217 QSBDEBUG() << __FILE__ << __LINE__ << locale << copy << num << ok; |
1193 QSBDEBUG() << __FILE__ << __LINE__ << locale << copy << num << ok; |
1218 bool notAcceptable = false; |
|
1219 |
1194 |
1220 if (!ok) { |
1195 if (!ok) { |
1221 if (thousand.isPrint()) { |
1196 if (locale.groupSeparator().isPrint()) { |
1222 if (max < 1000 && min > -1000 && copy.contains(thousand)) { |
1197 if (max < 1000 && min > -1000 && copy.contains(locale.groupSeparator())) { |
1223 state = QValidator::Invalid; |
1198 state = QValidator::Invalid; |
1224 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1199 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1225 goto end; |
1200 goto end; |
1226 } |
1201 } |
1227 |
1202 |
1228 const int len = copy.size(); |
1203 const int len = copy.size(); |
1229 for (int i=0; i<len- 1; ++i) { |
1204 for (int i=0; i<len- 1; ++i) { |
1230 if (copy.at(i) == thousand && copy.at(i + 1) == thousand) { |
1205 if (copy.at(i) == locale.groupSeparator() && copy.at(i + 1) == locale.groupSeparator()) { |
1231 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1206 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1232 state = QValidator::Invalid; |
1207 state = QValidator::Invalid; |
1233 goto end; |
1208 goto end; |
1234 } |
1209 } |
1235 } |
1210 } |
1236 |
1211 |
1237 const int s = copy.size(); |
1212 QString copy2 = copy; |
1238 copy.remove(thousand); |
1213 copy2.remove(locale.groupSeparator()); |
1239 pos = qMax(0, pos - (s - copy.size())); |
1214 num = locale.toDouble(copy2, &ok); |
1240 |
1215 QSBDEBUG() << locale.groupSeparator() << num << copy2 << ok; |
1241 |
|
1242 num = locale.toDouble(copy, &ok); |
|
1243 QSBDEBUG() << thousand << num << copy << ok; |
|
1244 |
1216 |
1245 if (!ok) { |
1217 if (!ok) { |
1246 state = QValidator::Invalid; |
1218 state = QValidator::Invalid; |
1247 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1219 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1248 goto end; |
1220 goto end; |
1249 } |
1221 } |
1250 notAcceptable = true; |
|
1251 } |
1222 } |
1252 } |
1223 } |
1253 |
1224 |
1254 if (!ok) { |
1225 if (!ok) { |
1255 state = QValidator::Invalid; |
1226 state = QValidator::Invalid; |
1256 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1227 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1257 } else if (num >= min && num <= max) { |
1228 } else if (num >= min && num <= max) { |
1258 state = notAcceptable ? QValidator::Intermediate : QValidator::Acceptable; |
1229 state = QValidator::Acceptable; |
1259 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to " |
1230 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Acceptable"; |
1260 << (state == QValidator::Intermediate ? "Intermediate" : "Acceptable"); |
|
1261 } else if (max == min) { // when max and min is the same the only non-Invalid input is max (or min) |
1231 } else if (max == min) { // when max and min is the same the only non-Invalid input is max (or min) |
1262 state = QValidator::Invalid; |
1232 state = QValidator::Invalid; |
1263 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1233 QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; |
1264 } else { |
1234 } else { |
1265 if ((num >= 0 && num > max) || (num < 0 && num < min)) { |
1235 if ((num >= 0 && num > max) || (num < 0 && num < min)) { |