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

kcalc

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