• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeutils API Reference
  • KDE Home
  • Contact Us
 

kcalc

  • sources
  • kde-4.14
  • kdeutils
  • kcalc
kcalcdisplay.cpp
Go to the documentation of this file.
1 /*
2 Copyright (C) 2001 - 2013 Evan Teran
3  evan.teran@gmail.com
4 
5 Copyright (C) 1996 - 2000 Bernd Johannes Wuebben
6  wuebben@kde.org
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of
11 the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "kcalcdisplay.h"
23 
24 #include <QClipboard>
25 #include <QMouseEvent>
26 #include <QPainter>
27 #include <QStyle>
28 #include <QStyleOption>
29 #include <QTimer>
30 
31 #include <kglobal.h>
32 #include <klocale.h>
33 #include <knotification.h>
34 
35 #include "kcalc_core.h"
36 #include "kcalc_settings.h"
37 
38 #include "kcalcdisplay.moc"
39 
40 //------------------------------------------------------------------------------
41 // Name: KCalcDisplay
42 // Desc: constructor
43 //------------------------------------------------------------------------------
44 KCalcDisplay::KCalcDisplay(QWidget *parent) : QFrame(parent), beep_(false),
45  groupdigits_(true), twoscomplement_(true), button_(0), lit_(false),
46  num_base_(NB_DECIMAL), precision_(9), fixed_precision_(-1), display_amount_(0),
47  history_index_(0), selection_timer_(new QTimer(this)) {
48 
49  setFocusPolicy(Qt::StrongFocus);
50 
51  setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
52 
53  setBackgroundRole(QPalette::Base);
54  setForegroundRole(QPalette::Text);
55  setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); // set in kalc.ui
56 
57  KNumber::setDefaultFloatOutput(true);
58  KNumber::setDefaultFractionalInput(true);
59 
60  connect(this, SIGNAL(clicked()), this, SLOT(slotDisplaySelected()));
61  connect(selection_timer_, SIGNAL(timeout()), this, SLOT(slotSelectionTimedOut()));
62 
63  sendEvent(EventReset);
64 }
65 
66 //------------------------------------------------------------------------------
67 // Name: ~KCalcDisplay
68 // Desc: destructor
69 //------------------------------------------------------------------------------
70 KCalcDisplay::~KCalcDisplay() {
71 }
72 
73 //------------------------------------------------------------------------------
74 // Name: changeSettings
75 // Desc:
76 //------------------------------------------------------------------------------
77 void KCalcDisplay::changeSettings() {
78  QPalette pal = palette();
79 
80  pal.setColor(QPalette::Text, KCalcSettings::foreColor());
81  pal.setColor(QPalette::Base, KCalcSettings::backColor());
82 
83  setPalette(pal);
84 
85  setFont(KCalcSettings::displayFont());
86 
87  setPrecision(KCalcSettings::precision());
88 
89  if (!KCalcSettings::fixed()) {
90  setFixedPrecision(-1);
91  } else {
92  setFixedPrecision(KCalcSettings::fixedPrecision());
93  }
94 
95  setBeep(KCalcSettings::beep());
96  setGroupDigits(KCalcSettings::groupDigits());
97  setTwosComplement(KCalcSettings::twosComplement());
98  setBinaryGrouping(KCalcSettings::binaryGrouping());
99  setOctalGrouping(KCalcSettings::octalGrouping());
100  setHexadecimalGrouping(KCalcSettings::hexadecimalGrouping());
101  updateDisplay();
102 }
103 
104 //------------------------------------------------------------------------------
105 // Name:
106 // Desc:
107 //------------------------------------------------------------------------------
108 void KCalcDisplay::updateFromCore(const CalcEngine &core, bool store_result_in_history) {
109 
110  bool tmp_error;
111  const KNumber &output = core.lastOutput(tmp_error);
112 
113 #if 0
114  // TODO: do we really need explicit error tracking?
115  // isn't the type of the KNumber good enough?
116  // I think it is and that this error tracking is cruft
117  // left over from a LONG time ago...
118  if(output.type() == KNumber::TYPE_ERROR) {
119 #else
120  if (tmp_error) {
121 #endif
122  sendEvent(EventError);
123  }
124 
125  if (setAmount(output) && store_result_in_history && (output != KNumber::Zero)) {
126  // add this latest value to our history
127  history_list_.insert(history_list_.begin(), output);
128  history_index_ = 0;
129  }
130 }
131 
132 //------------------------------------------------------------------------------
133 // Name: enterDigit
134 // Desc:
135 //------------------------------------------------------------------------------
136 void KCalcDisplay::enterDigit(int data) {
137 
138  switch (data) {
139  case 0: newCharacter(QLatin1Char('0')); break;
140  case 1: newCharacter(QLatin1Char('1')); break;
141  case 2: newCharacter(QLatin1Char('2')); break;
142  case 3: newCharacter(QLatin1Char('3')); break;
143  case 4: newCharacter(QLatin1Char('4')); break;
144  case 5: newCharacter(QLatin1Char('5')); break;
145  case 6: newCharacter(QLatin1Char('6')); break;
146  case 7: newCharacter(QLatin1Char('7')); break;
147  case 8: newCharacter(QLatin1Char('8')); break;
148  case 9: newCharacter(QLatin1Char('9')); break;
149  case 0xa: newCharacter(QLatin1Char('A')); break;
150  case 0xb: newCharacter(QLatin1Char('B')); break;
151  case 0xc: newCharacter(QLatin1Char('C')); break;
152  case 0xd: newCharacter(QLatin1Char('D')); break;
153  case 0xe: newCharacter(QLatin1Char('E')); break;
154  case 0xf: newCharacter(QLatin1Char('F')); break;
155  default:
156  Q_ASSERT(0);
157  break;
158  }
159 }
160 
161 //------------------------------------------------------------------------------
162 // Name: slotHistoryForward
163 // Desc:
164 //------------------------------------------------------------------------------
165 void KCalcDisplay::slotHistoryForward() {
166 
167  if (history_list_.empty()) {
168  return;
169  }
170 
171  if (history_index_ <= 0) {
172  return;
173  }
174 
175  history_index_--;
176  setAmount(history_list_[history_index_]);
177 }
178 
179 //------------------------------------------------------------------------------
180 // Name: slotHistoryBack
181 // Desc:
182 //------------------------------------------------------------------------------
183 void KCalcDisplay::slotHistoryBack() {
184 
185  if (history_list_.empty()) {
186  return;
187  }
188 
189  if (history_index_ >= history_list_.size()) {
190  return;
191  }
192 
193  setAmount(history_list_[history_index_]);
194  history_index_++;
195 }
196 
197 //------------------------------------------------------------------------------
198 // Name: sendEvent
199 // Desc:
200 //------------------------------------------------------------------------------
201 bool KCalcDisplay::sendEvent(Event event) {
202 
203  switch (event) {
204  case EventClear:
205  case EventReset:
206  display_amount_ = KNumber::Zero;
207  str_int_ = QLatin1String("0");
208  str_int_exp_.clear();
209 
210  eestate_ = false;
211  period_ = false;
212  neg_sign_ = false;
213 
214  updateDisplay();
215 
216  return true;
217 
218  case EventChangeSign:
219  return changeSign();
220 
221  case EventError:
222  updateDisplay();
223  return true;
224 
225  default:
226  return false;
227  }
228 }
229 
230 //------------------------------------------------------------------------------
231 // Name: slotCut
232 // Desc:
233 //------------------------------------------------------------------------------
234 void KCalcDisplay::slotCut() {
235 
236  slotCopy();
237  sendEvent(EventReset);
238 }
239 
240 //------------------------------------------------------------------------------
241 // Name: slotCopy
242 // Desc:
243 //------------------------------------------------------------------------------
244 void KCalcDisplay::slotCopy() {
245 
246  QString txt = text_;
247 
248  switch(num_base_) {
249  case NB_HEX:
250  txt.prepend(QLatin1String("0x"));
251  txt.remove(QLatin1Char(' '));
252  break;
253  case NB_BINARY:
254  txt.prepend(QLatin1String("0b"));
255  txt.remove(QLatin1Char(' '));
256  break;
257  case NB_OCTAL:
258  txt.prepend(QLatin1String("0"));
259  txt.remove(QLatin1Char(' '));
260  break;
261  case NB_DECIMAL:
262  break;
263  }
264 
265  (QApplication::clipboard())->setText(txt, QClipboard::Clipboard);
266  (QApplication::clipboard())->setText(txt, QClipboard::Selection);
267 }
268 
269 //------------------------------------------------------------------------------
270 // Name: slotPaste
271 // Desc:
272 //------------------------------------------------------------------------------
273 void KCalcDisplay::slotPaste(bool bClipboard) {
274 
275  QString tmp_str = (QApplication::clipboard())->text(bClipboard ? QClipboard::Clipboard : QClipboard::Selection);
276 
277  if (tmp_str.isNull()) {
278  if (beep_) {
279  KNotification::beep();
280  }
281  return;
282  }
283 
284  NumBase tmp_num_base = num_base_;
285 
286  // fix up string
287  tmp_str = tmp_str.trimmed();
288 
289  if (groupdigits_) {
290  tmp_str.remove(KGlobal::locale()->thousandsSeparator());
291  }
292 
293  tmp_str = tmp_str.toLower();
294 
295  // determine base
296  if (tmp_str.startsWith(QLatin1String("0x"))) {
297  tmp_num_base = NB_HEX;
298  tmp_str.remove(0, 2);
299  } else if (tmp_str.startsWith(QLatin1String("0b"))) {
300  tmp_num_base = NB_BINARY;
301  tmp_str.remove(0, 2);
302  } else if (tmp_str.startsWith(QLatin1String("0"))) {
303  // we don't want this to trigger on "0.xxxxxx" cases
304  if(tmp_str.length() < 2 || QString(tmp_str[1]) != KNumber::decimalSeparator()) {
305  tmp_num_base = NB_OCTAL;
306  tmp_str.remove(0, 1);
307  }
308  }
309 
310  if (tmp_num_base != NB_DECIMAL) {
311  bool was_ok;
312  const qint64 tmp_result = tmp_str.toULongLong(&was_ok, tmp_num_base);
313 
314  if (!was_ok) {
315  setAmount(KNumber::NaN);
316  if (beep_) {
317  KNotification::beep();
318  }
319  return;
320  }
321  setAmount(KNumber(tmp_result));
322  } else {
323  setAmount(KNumber(tmp_str));
324  if (beep_ && display_amount_ == KNumber::NaN) {
325  KNotification::beep();
326  }
327  }
328 }
329 
330 //------------------------------------------------------------------------------
331 // Name: slotDisplaySelected
332 // Desc:
333 //------------------------------------------------------------------------------
334 void KCalcDisplay::slotDisplaySelected() {
335 
336  if (button_ == Qt::LeftButton) {
337  if (lit_) {
338  slotCopy();
339  selection_timer_->start(100);
340  } else {
341  selection_timer_->stop();
342  }
343 
344  invertColors();
345  } else {
346  slotPaste(false); // Selection
347  }
348 }
349 
350 //------------------------------------------------------------------------------
351 // Name: slotSelectionTimedOut
352 // Desc:
353 //------------------------------------------------------------------------------
354 void KCalcDisplay::slotSelectionTimedOut() {
355 
356  lit_ = false;
357  invertColors();
358  selection_timer_->stop();
359 }
360 
361 //------------------------------------------------------------------------------
362 // Name: invertColors
363 // Desc:
364 //------------------------------------------------------------------------------
365 void KCalcDisplay::invertColors() {
366 
367  QPalette tmp_palette = palette();
368  tmp_palette.setColor(QPalette::Base, palette().color(QPalette::Text));
369  tmp_palette.setColor(QPalette::Text, palette().color(QPalette::Base));
370  setPalette(tmp_palette);
371 }
372 
373 //------------------------------------------------------------------------------
374 // Name: mousePressEvent
375 // Desc:
376 //------------------------------------------------------------------------------
377 void KCalcDisplay::mousePressEvent(QMouseEvent *e) {
378 
379  if (e->button() == Qt::LeftButton) {
380  lit_ = !lit_;
381  button_ = Qt::LeftButton;
382  } else {
383  button_ = Qt::MidButton;
384  }
385 
386  emit clicked();
387 }
388 
389 //------------------------------------------------------------------------------
390 // Name: setPrecision
391 // Desc:
392 //------------------------------------------------------------------------------
393 void KCalcDisplay::setPrecision(int precision) {
394 
395  precision_ = precision;
396 }
397 
398 //------------------------------------------------------------------------------
399 // Name: setFixedPrecision
400 // Desc:
401 //------------------------------------------------------------------------------
402 void KCalcDisplay::setFixedPrecision(int precision) {
403 
404  if (fixed_precision_ > precision_) {
405  fixed_precision_ = -1;
406  } else {
407  fixed_precision_ = precision;
408  }
409 }
410 
411 //------------------------------------------------------------------------------
412 // Name: setBeep
413 // Desc:
414 //------------------------------------------------------------------------------
415 void KCalcDisplay::setBeep(bool flag) {
416  beep_ = flag;
417 }
418 
419 //------------------------------------------------------------------------------
420 // Name: setGroupDigits
421 // Desc:
422 //------------------------------------------------------------------------------
423 void KCalcDisplay::setGroupDigits(bool flag) {
424  groupdigits_ = flag;
425 }
426 
427 //------------------------------------------------------------------------------
428 // Name: setTwosComplement
429 // Desc:
430 //------------------------------------------------------------------------------
431 void KCalcDisplay::setTwosComplement(bool flag) {
432  twoscomplement_ = flag;
433 }
434 
435 //------------------------------------------------------------------------------
436 // Name: setBinaryGrouping
437 // Desc:
438 //------------------------------------------------------------------------------
439 void KCalcDisplay::setBinaryGrouping(int digits) {
440  binaryGrouping_ = digits;
441 }
442 
443 //------------------------------------------------------------------------------
444 // Name: setOctalGrouping
445 // Desc:
446 //------------------------------------------------------------------------------
447 void KCalcDisplay::setOctalGrouping(int digits) {
448  octalGrouping_ = digits;
449 }
450 
451 //------------------------------------------------------------------------------
452 // Name: setHexadecimalGrouping
453 // Desc:
454 //------------------------------------------------------------------------------
455 void KCalcDisplay::setHexadecimalGrouping(int digits) {
456  hexadecimalGrouping_ = digits;
457 }
458 
459 //------------------------------------------------------------------------------
460 // Name: getAmount
461 // Desc:
462 //------------------------------------------------------------------------------
463 const KNumber &KCalcDisplay::getAmount() const {
464  return display_amount_;
465 }
466 
467 //------------------------------------------------------------------------------
468 // Name: setAmount
469 // Desc:
470 //------------------------------------------------------------------------------
471 bool KCalcDisplay::setAmount(const KNumber &new_amount) {
472 
473  QString display_str;
474 
475  str_int_ = QLatin1String("0");
476  str_int_exp_.clear();
477  period_ = false;
478  neg_sign_ = false;
479  eestate_ = false;
480 
481  if ((num_base_ != NB_DECIMAL) && (new_amount.type() != KNumber::TYPE_ERROR)) {
482  display_amount_ = new_amount.integerPart();
483 
484  if (twoscomplement_) {
485  // treat number as 64-bit unsigned
486  const quint64 tmp_workaround = display_amount_.toUint64();
487  display_str = QString::number(tmp_workaround, num_base_).toUpper();
488  } else {
489  // QString::number treats non-decimal as unsigned
490  qint64 tmp_workaround = display_amount_.toInt64();
491  const bool neg = tmp_workaround < 0;
492  if (neg) {
493  tmp_workaround = qAbs(tmp_workaround);
494  }
495 
496  display_str = QString::number(tmp_workaround, num_base_).toUpper();
497  if (neg) {
498  display_str.prepend(KGlobal::locale()->negativeSign());
499  }
500  }
501  } else {
502  // num_base_ == NB_DECIMAL || new_amount.type() == KNumber::TYPE_ERROR
503  display_amount_ = new_amount;
504  display_str = display_amount_.toQString(KCalcSettings::precision(), fixed_precision_);
505  }
506 
507  setText(display_str);
508  emit changedAmount(display_amount_);
509  return true;
510 }
511 
512 //------------------------------------------------------------------------------
513 // Name: setText
514 // Desc:
515 //------------------------------------------------------------------------------
516 void KCalcDisplay::setText(const QString &string)
517 {
518  // note that "C" locale is being used internally
519  text_ = string;
520 
521  // don't mess with special numbers
522  const bool special = (string.contains(QLatin1String("nan")) || string.contains(QLatin1String("inf")));
523 
524  // The decimal mode needs special treatment for two reasons, because: a) it uses KGlobal::locale() to get a localized
525  // format and b) it has possible numbers after the decimal place. Neither applies to Binary, Hexadecimal or Octal.
526 
527  if (groupdigits_ && !special){
528  switch (num_base_) {
529  case NB_DECIMAL:
530  if (string.endsWith(QLatin1Char('.'))) {
531  text_.chop(1);
532  // Note: rounding happened already above!
533  text_ = KGlobal::locale()->formatNumber(text_, false, 0);
534  text_.append(KGlobal::locale()->decimalSymbol());
535  } else {
536  // Note: rounding happened already above!
537  text_ = KGlobal::locale()->formatNumber(text_, false, 0);
538  }
539  break;
540 
541  case NB_BINARY:
542  text_ = groupDigits(text_, binaryGrouping_);
543  break;
544 
545  case NB_OCTAL:
546  text_ = groupDigits(text_, octalGrouping_);
547  break;
548 
549  case NB_HEX:
550  text_ = groupDigits(text_, hexadecimalGrouping_);
551  break;
552  }
553  } else if(special) {
554 #if 0
555  // TODO: enable this code, it replaces the "inf" with an actual infinity
556  // symbol, but what should be put into the clip board when they copy?
557  if(string.contains(QLatin1String("inf"))) {
558  text_.replace("inf", QChar(0x221e));
559  }
560 #endif
561  }
562 
563  update();
564  emit changedText(text_);
565 }
566 
567 //------------------------------------------------------------------------------
568 // Name: groupDigits
569 // Desc:
570 //------------------------------------------------------------------------------
571 QString KCalcDisplay::groupDigits(const QString &displayString, int numDigits) {
572 
573  QString tmpDisplayString;
574  const int stringLength = displayString.length();
575 
576  for (int i = stringLength; i > 0 ; i--){
577  if(i % numDigits == 0 && i != stringLength) {
578  tmpDisplayString = tmpDisplayString + ' ';
579  }
580 
581  tmpDisplayString = tmpDisplayString + displayString[stringLength - i];
582  }
583 
584  return tmpDisplayString;
585 }
586 
587 //------------------------------------------------------------------------------
588 // Name: text
589 // Desc:
590 //------------------------------------------------------------------------------
591 QString KCalcDisplay::text() const {
592  return text_;
593 }
594 
595 //------------------------------------------------------------------------------
596 // Name: setBase
597 // Desc: change representation of display to new base (i.e. binary, decimal,
598 // octal, hexadecimal). The amount being displayed is changed to this
599 // base, but for now this amount can not be modified anymore (like
600 // being set with "setAmount"). Return value is the new base.
601 //------------------------------------------------------------------------------
602 int KCalcDisplay::setBase(NumBase new_base) {
603 
604  switch (new_base) {
605  case NB_HEX:
606  num_base_ = NB_HEX;
607  period_ = false;
608  break;
609  case NB_DECIMAL:
610  num_base_ = NB_DECIMAL;
611  break;
612  case NB_OCTAL:
613  num_base_ = NB_OCTAL;
614  period_ = false;
615  break;
616  case NB_BINARY:
617  num_base_ = NB_BINARY;
618  period_ = false;
619  break;
620  default:
621  Q_ASSERT(0);
622  }
623 
624  // reset amount
625  setAmount(display_amount_);
626  return num_base_;
627 }
628 
629 //------------------------------------------------------------------------------
630 // Name: setStatusText
631 // Desc:
632 //------------------------------------------------------------------------------
633 void KCalcDisplay::setStatusText(int i, const QString &text) {
634 
635  if (i < NUM_STATUS_TEXT) {
636  str_status_[i] = text;
637  }
638 
639  update();
640 }
641 
642 //------------------------------------------------------------------------------
643 // Name: updateDisplay
644 // Desc:
645 //------------------------------------------------------------------------------
646 void KCalcDisplay::updateDisplay() {
647 
648  // Put sign in front.
649  QString tmp_string;
650  if (neg_sign_) {
651  tmp_string = QLatin1Char('-') + str_int_;
652  } else {
653  tmp_string = str_int_;
654  }
655 
656  bool ok;
657 
658  switch (num_base_) {
659  case NB_BINARY:
660  Q_ASSERT(!period_ && !eestate_);
661  setText(tmp_string);
662  display_amount_ = KNumber(str_int_.toULongLong(&ok, 2));
663  if (neg_sign_) {
664  display_amount_ = -display_amount_;
665  }
666  break;
667 
668  case NB_OCTAL:
669  Q_ASSERT(!period_ && !eestate_);
670  setText(tmp_string);
671  display_amount_ = KNumber(str_int_.toULongLong(&ok, 8));
672  if (neg_sign_) {
673  display_amount_ = -display_amount_;
674  }
675  break;
676 
677  case NB_HEX:
678  Q_ASSERT(!period_ && !eestate_);
679  setText(tmp_string);
680  display_amount_ = KNumber(str_int_.toULongLong(&ok, 16));
681  if (neg_sign_) {
682  display_amount_ = -display_amount_;
683  }
684  break;
685 
686  case NB_DECIMAL:
687  if (!eestate_) {
688  setText(tmp_string);
689  display_amount_ = KNumber(tmp_string);
690  } else {
691  if (str_int_exp_.isNull()) {
692  // add 'e0' to display but not to conversion
693  display_amount_ = KNumber(tmp_string);
694  setText(tmp_string + QLatin1String("e0"));
695  } else {
696  tmp_string += QLatin1Char('e') + str_int_exp_;
697  setText(tmp_string);
698  display_amount_ = KNumber(tmp_string);
699  }
700  }
701  break;
702 
703  default:
704  Q_ASSERT(0);
705  }
706 
707  emit changedAmount(display_amount_);
708 }
709 
710 //------------------------------------------------------------------------------
711 // Name: newCharacter
712 // Desc:
713 //------------------------------------------------------------------------------
714 void KCalcDisplay::newCharacter(const QChar new_char) {
715 
716  // test if character is valid
717  switch (new_char.toLatin1()) {
718  case 'e':
719  // EE can be set only once and in decimal mode
720  if (num_base_ != NB_DECIMAL || eestate_) {
721  if (beep_) {
722  KNotification::beep();
723  }
724  return;
725  }
726  eestate_ = true;
727  break;
728 
729  case 'F':
730  case 'E':
731  case 'D':
732  case 'C':
733  case 'B':
734  case 'A':
735  if (num_base_ == NB_DECIMAL) {
736  if (beep_) {
737  KNotification::beep();
738  }
739  return;
740  }
741  // no break
742  case '9':
743  case '8':
744  if (num_base_ == NB_OCTAL) {
745  if (beep_) {
746  KNotification::beep();
747  }
748  return;
749  }
750  // no break
751  case '7':
752  case '6':
753  case '5':
754  case '4':
755  case '3':
756  case '2':
757  if (num_base_ == NB_BINARY) {
758  if (beep_) {
759  KNotification::beep();
760  }
761  return;
762  }
763  // no break
764  case '1':
765  case '0':
766  break;
767 
768  default:
769  if(new_char == KGlobal::locale()->decimalSymbol()[0]) {
770  // Period can be set only once and only in decimal
771  // mode, also not in EE-mode
772  if (num_base_ != NB_DECIMAL || period_ || eestate_) {
773  if (beep_) {
774  KNotification::beep();
775  }
776  return;
777  }
778  period_ = true;
779  } else {
780  if (beep_) {
781  KNotification::beep();
782  }
783  return;
784  }
785  }
786 
787  // change exponent or mantissa
788  if (eestate_) {
789  // ignore '.' before 'e'. turn e.g. '123.e' into '123e'
790  if (new_char == QLatin1Char('e') && str_int_.endsWith(KGlobal::locale()->decimalSymbol())) {
791  str_int_.chop(1);
792  period_ = false;
793  }
794 
795  // 'e' only starts ee_mode, leaves strings unchanged
796  // do not add '0' if at start of exp
797  if (new_char != QLatin1Char('e') && !(str_int_exp_.isNull() && new_char == QLatin1Char('0'))) {
798  str_int_exp_.append(new_char);
799  }
800  } else {
801  // handle first character
802  if (str_int_ == QLatin1String("0")) {
803  switch (new_char.toLatin1()) {
804  case 'e':
805  // display "0e" not just "e"
806  // "0e" does not make sense either, but...
807  str_int_.append(new_char);
808  break;
809  default:
810  if(new_char == KGlobal::locale()->decimalSymbol()[0]) {
811  // display "0." not just "."
812  str_int_.append(new_char);
813  } else {
814  // no leading '0's
815  str_int_[0] = new_char;
816  }
817  }
818  } else {
819  str_int_.append(new_char);
820  }
821  }
822 
823  updateDisplay();
824 }
825 
826 //------------------------------------------------------------------------------
827 // Name: deleteLastDigit
828 // Desc:
829 //------------------------------------------------------------------------------
830 void KCalcDisplay::deleteLastDigit() {
831 
832  // Only partially implemented !!
833  if (eestate_) {
834  if (str_int_exp_.isNull()) {
835  eestate_ = false;
836  } else {
837  const int length = str_int_exp_.length();
838  if (length > 1) {
839  str_int_exp_.chop(1);
840  } else {
841  str_int_exp_ = QLatin1String((const char *)0);
842  }
843  }
844  } else {
845  const int length = str_int_.length();
846  if (length > 1) {
847  if (str_int_[length-1] == KGlobal::locale()->decimalSymbol()[0]) {
848  period_ = false;
849  }
850  str_int_.chop(1);
851  } else {
852  Q_ASSERT(!period_);
853  str_int_[0] = QLatin1Char('0');
854  }
855  }
856 
857  updateDisplay();
858 }
859 
860 //------------------------------------------------------------------------------
861 // Name: changeSign
862 // Desc: change Sign of display. Problem: Only possible here, when in input
863 // mode. Otherwise return 'false' so that the kcalc_core can handle
864 // things.
865 //------------------------------------------------------------------------------
866 bool KCalcDisplay::changeSign() {
867 
868  //stupid way, to see if in input_mode or display_mode
869  if (str_int_ == QLatin1String("0")) {
870  return false;
871  }
872 
873  if (eestate_) {
874  if (!str_int_exp_.isNull()) {
875  if (str_int_exp_[0] != QLatin1Char('-')) {
876  str_int_exp_.prepend(QLatin1Char('-'));
877  } else {
878  str_int_exp_.remove(QLatin1Char('-'));
879  }
880  }
881  } else {
882  neg_sign_ = !neg_sign_;
883  }
884 
885  updateDisplay();
886  return true;
887 }
888 
889 //------------------------------------------------------------------------------
890 // Name: initStyleOption
891 // Desc:
892 //------------------------------------------------------------------------------
893 void KCalcDisplay::initStyleOption(QStyleOptionFrame *option) const {
894 
895  if (!option) {
896  return;
897  }
898 
899  option->initFrom(this);
900  option->state &= ~QStyle::State_HasFocus; // don't draw focus highlight
901 
902  if (frameShadow() == QFrame::Sunken) {
903  option->state |= QStyle::State_Sunken;
904  } else if (frameShadow() == QFrame::Raised) {
905  option->state |= QStyle::State_Raised;
906  }
907 
908  option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, option, this);
909  option->midLineWidth = 0;
910 }
911 
912 //------------------------------------------------------------------------------
913 // Name: paintEvent
914 // Desc:
915 //------------------------------------------------------------------------------
916 void KCalcDisplay::paintEvent(QPaintEvent *) {
917 
918  QPainter painter(this);
919 
920  QStyleOptionFrame option;
921  initStyleOption(&option);
922 
923  style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, &painter, this);
924 
925  // draw display text
926  const int margin = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, 0);
927  QRect cr = contentsRect();
928  cr.adjust(margin*2, 0, -margin*2, 0); // provide a margin
929 
930  const int align = QStyle::visualAlignment(layoutDirection(), Qt::AlignRight | Qt::AlignVCenter);
931  painter.drawText(cr, align | Qt::TextSingleLine, text_);
932 
933  // draw the status texts using half of the normal
934  // font size but not smaller than 7pt
935  QFont fnt(font());
936  fnt.setPointSize(qMax((fnt.pointSize() / 2), 7));
937  painter.setFont(fnt);
938 
939  QFontMetrics fm(fnt);
940  const uint w = fm.width(QLatin1String("________"));
941  const uint h = fm.height();
942 
943  for (int n = 0; n < NUM_STATUS_TEXT; ++n) {
944  painter.drawText(5 + n * w, h, str_status_[n]);
945  }
946 }
947 
948 //------------------------------------------------------------------------------
949 // Name: sizeHint
950 // Desc:
951 //------------------------------------------------------------------------------
952 QSize KCalcDisplay::sizeHint() const {
953 
954  // basic size
955  QSize sz = fontMetrics().size(Qt::TextSingleLine, text_);
956 
957  // expanded by half font height to make room for the status texts
958  QFont fnt(font());
959  fnt.setPointSize(qMax((fnt.pointSize() / 2), 7));
960 
961  const QFontMetrics fm(fnt);
962  sz.setHeight(sz.height() + fm.height());
963 
964  QStyleOptionFrame option;
965  initStyleOption(&option);
966 
967  return (style()->sizeFromContents(QStyle::CT_LineEdit, &option, sz.expandedTo(QApplication::globalStrut()), this));
968 }
KCalcDisplay::setGroupDigits
void setGroupDigits(bool flag)
Definition: kcalcdisplay.cpp:423
KCalcDisplay::EventReset
Definition: kcalcdisplay.h:68
KCalcDisplay::setBinaryGrouping
void setBinaryGrouping(int digits)
Definition: kcalcdisplay.cpp:439
KCalcSettings::fixedPrecision
static uint fixedPrecision()
Get Number of fixed decimal digits.
Definition: kcalc_settings.h:260
QWidget
QFont::setPointSize
void setPointSize(int pointSize)
QSize::setHeight
void setHeight(int height)
QString::append
QString & append(QChar ch)
KNumber::toQString
QString toQString(int width=-1, int precision=-1) const
Definition: knumber.cpp:601
QWidget::palette
const QPalette & palette() const
QString::toUpper
QString toUpper() const
KNumber::NaN
static const KNumber NaN
Definition: knumber.h:54
KCalcSettings::groupDigits
static bool groupDigits()
Get Whether to group digits.
Definition: kcalc_settings.h:336
QPalette::setColor
void setColor(ColorGroup group, ColorRole role, const QColor &color)
QVector::begin
iterator begin()
KCalcDisplay::enterDigit
void enterDigit(int data)
Definition: kcalcdisplay.cpp:136
QWidget::contentsRect
QRect contentsRect() const
KCalcSettings::backColor
static QColor backColor()
Get The background color of the display.
Definition: kcalc_settings.h:58
KCalcSettings::octalGrouping
static uint octalGrouping()
Get Octal figures will be separated by a whitespace after every Xth digit.
Definition: kcalc_settings.h:488
KNumber::decimalSeparator
static QString decimalSeparator()
Definition: knumber.cpp:203
NUM_STATUS_TEXT
#define NUM_STATUS_TEXT
Definition: kcalcdisplay.h:34
QWidget::setFocusPolicy
void setFocusPolicy(Qt::FocusPolicy policy)
kcalc_core.h
QChar
QString::prepend
QString & prepend(QChar ch)
KNumber::setDefaultFloatOutput
static void setDefaultFloatOutput(bool x)
Definition: knumber.cpp:233
QFont
KNumber::Zero
static const KNumber Zero
Definition: knumber.h:49
QWidget::style
QStyle * style() const
QStyle::pixelMetric
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const =0
QSizePolicy
KCalcDisplay::changeSettings
void changeSettings()
Definition: kcalcdisplay.cpp:77
QVector::insert
void insert(int i, const T &value)
KCalcDisplay::deleteLastDigit
void deleteLastDigit()
Definition: kcalcdisplay.cpp:830
KCalcDisplay::Event
Event
Definition: kcalcdisplay.h:67
KCalcDisplay::getAmount
const KNumber & getAmount() const
Definition: kcalcdisplay.cpp:463
KCalcDisplay::sendEvent
bool sendEvent(Event event)
Definition: kcalcdisplay.cpp:201
QFontMetrics
QMouseEvent
kcalcdisplay.h
QString::remove
QString & remove(int position, int n)
KCalcDisplay::setHexadecimalGrouping
void setHexadecimalGrouping(int digits)
Definition: kcalcdisplay.cpp:455
QFrame::setFrameStyle
void setFrameStyle(int style)
KCalcSettings::displayFont
static QFont displayFont()
Get The font to use in the display.
Definition: kcalc_settings.h:210
QString::chop
void chop(int n)
KNumber::toInt64
qint64 toInt64() const
Definition: knumber.cpp:645
KCalcDisplay::slotPaste
void slotPaste(bool bClipboard=true)
Definition: kcalcdisplay.cpp:273
KNumber::integerPart
KNumber integerPart() const
Definition: knumber.cpp:434
QWidget::update
void update()
KCalcSettings::beep
static bool beep()
Get Whether to beep on error.
Definition: kcalc_settings.h:298
KCalcSettings::binaryGrouping
static uint binaryGrouping()
Get Binary figures will be separated by a whitespace after every Xth digit.
Definition: kcalc_settings.h:469
QApplication::globalStrut
QSize globalStrut()
KCalcDisplay::setStatusText
void setStatusText(int i, const QString &text)
Definition: kcalcdisplay.cpp:633
QString::isNull
bool isNull() const
NB_OCTAL
Definition: kcalcdisplay.h:54
NB_BINARY
Definition: kcalcdisplay.h:53
QString::clear
void clear()
QStyleOption::initFrom
void initFrom(const QWidget *widget)
NumBase
NumBase
Definition: kcalcdisplay.h:52
KCalcDisplay::setBeep
void setBeep(bool flag)
Definition: kcalcdisplay.cpp:415
QRect
QPainter::setFont
void setFont(const QFont &font)
QString::number
QString number(int n, int base)
KCalcDisplay::slotCut
void slotCut()
Definition: kcalcdisplay.cpp:234
QTimer
QWidget::layoutDirection
Qt::LayoutDirection layoutDirection() const
KCalcDisplay::changedText
void changedText(const QString &)
QApplication::clipboard
QClipboard * clipboard()
KCalcDisplay::updateDisplay
void updateDisplay()
Definition: kcalcdisplay.cpp:646
QStyle
KCalcDisplay::~KCalcDisplay
~KCalcDisplay()
Definition: kcalcdisplay.cpp:70
QMouseEvent::button
Qt::MouseButton button() const
KCalcDisplay::setTwosComplement
void setTwosComplement(bool flag)
Definition: kcalcdisplay.cpp:431
KCalcDisplay::setAmount
bool setAmount(const KNumber &new_amount)
Definition: kcalcdisplay.cpp:471
QWidget::setForegroundRole
void setForegroundRole(QPalette::ColorRole role)
QPainter
QString::trimmed
QString trimmed() const
KCalcDisplay::setPrecision
void setPrecision(int precision)
Definition: kcalcdisplay.cpp:393
KNumber::type
Type type() const
Definition: knumber.cpp:400
KCalcDisplay::sizeHint
virtual QSize sizeHint() const
Definition: kcalcdisplay.cpp:952
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
NB_DECIMAL
Definition: kcalcdisplay.h:55
KCalcDisplay::EventError
Definition: kcalcdisplay.h:70
KNumber::setDefaultFractionalInput
static void setDefaultFractionalInput(bool x)
Definition: knumber.cpp:226
QPainter::drawText
void drawText(const QPointF &position, const QString &text)
NB_HEX
Definition: kcalcdisplay.h:56
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QString
QString::toULongLong
qulonglong toULongLong(bool *ok, int base) const
KCalcDisplay::changedAmount
void changedAmount(const KNumber &)
QWidget::setSizePolicy
void setSizePolicy(QSizePolicy)
KCalcDisplay::clicked
void clicked()
KNumber
Definition: knumber.h:30
QString::toLower
QString toLower() const
kcalc_settings.h
QSize
QLatin1Char
QWidget::setFont
void setFont(const QFont &)
KCalcDisplay::setFixedPrecision
void setFixedPrecision(int precision)
Definition: kcalcdisplay.cpp:402
QFrame
QFontMetrics::width
int width(const QString &text, int len) const
QChar::toLatin1
char toLatin1() const
QTimer::stop
void stop()
QFrame::frameShadow
Shadow frameShadow() const
CalcEngine::lastOutput
KNumber lastOutput(bool &error) const
Definition: kcalc_core.cpp:179
KCalcDisplay::setOctalGrouping
void setOctalGrouping(int digits)
Definition: kcalcdisplay.cpp:447
KNumber::toUint64
quint64 toUint64() const
Definition: knumber.cpp:638
KCalcSettings::hexadecimalGrouping
static uint hexadecimalGrouping()
Get Hexadecimal figures will be separated by a whitespace after every Xth digit.
Definition: kcalc_settings.h:507
QString::replace
QString & replace(int position, int n, QChar after)
KCalcDisplay::setText
void setText(const QString &string)
Definition: kcalcdisplay.cpp:516
QWidget::fontMetrics
QFontMetrics fontMetrics() const
KCalcDisplay::setBase
int setBase(NumBase new_base)
Definition: kcalcdisplay.cpp:602
QLatin1String
QSize::expandedTo
QSize expandedTo(const QSize &otherSize) const
KCalcDisplay::EventClear
Definition: kcalcdisplay.h:69
QFontMetrics::height
int height() const
QSize::height
int height() const
QRect::adjust
void adjust(int dx1, int dy1, int dx2, int dy2)
KCalcSettings::precision
static uint precision()
Get Maximum number of digits displayed.
Definition: kcalc_settings.h:241
KCalcDisplay::KCalcDisplay
KCalcDisplay(QWidget *parent=0)
Definition: kcalcdisplay.cpp:44
QString::length
int length() const
KCalcSettings::foreColor
static QColor foreColor()
Get The foreground color of the display.
Definition: kcalc_settings.h:39
KCalcDisplay::newCharacter
void newCharacter(const QChar new_char)
Definition: kcalcdisplay.cpp:714
QStyle::drawPrimitive
virtual void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const =0
QTimer::start
void start(int msec)
KCalcDisplay::EventChangeSign
Definition: kcalcdisplay.h:71
KCalcSettings::twosComplement
static bool twosComplement()
Get Whether to use Two's Complement for non-decimal numbers.
Definition: kcalc_settings.h:355
QFontMetrics::size
QSize size(int flags, const QString &text, int tabStops, int *tabArray) const
QStyle::visualAlignment
Qt::Alignment visualAlignment(Qt::LayoutDirection direction, QFlags< Qt::AlignmentFlag > alignment)
QPaintEvent
QWidget::setBackgroundRole
void setBackgroundRole(QPalette::ColorRole role)
CalcEngine
Definition: kcalc_core.h:29
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KCalcDisplay::groupDigits
QString groupDigits(const QString &displayString, int numDigits)
Definition: kcalcdisplay.cpp:571
KCalcDisplay::slotCopy
void slotCopy()
Definition: kcalcdisplay.cpp:244
QVector::size
int size() const
KCalcDisplay::updateFromCore
void updateFromCore(const CalcEngine &core, bool store_result_in_history=false)
Definition: kcalcdisplay.cpp:108
QStyleOptionFrame
QVector::empty
bool empty() const
QFrame::event
virtual bool event(QEvent *e)
KCalcDisplay::text
QString text() const
Definition: kcalcdisplay.cpp:591
QPalette
QFont::pointSize
int pointSize() const
KCalcSettings::fixed
static bool fixed()
Get Whether to use fixed decimal places.
Definition: kcalc_settings.h:279
KCalcDisplay::mousePressEvent
void mousePressEvent(QMouseEvent *)
Definition: kcalcdisplay.cpp:377
KNumber::TYPE_ERROR
Definition: knumber.h:41
KCalcDisplay::paintEvent
virtual void paintEvent(QPaintEvent *p)
Definition: kcalcdisplay.cpp:916
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:42:28 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kcalc

Skip menu "kcalc"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdeutils API Reference

Skip menu "kdeutils API Reference"
  • ark
  • filelight
  • kcalc
  • kcharselect
  • kdf
  • kfloppy
  • kgpg
  • ktimer
  • kwallet
  • sweeper

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal