Ansichten: QuotePaste - CodePaste - NoPaste
Codesnippet eingetragen am 3.7.2012 um 12:43
Von: Mirrakor
Sprache: c++
Beschreibung: Modified kcalcdisplay.cpp to implement a cosmetic feature (binary, hex and octal grouping of numbers)
CodeSnippet:
  1. // -*- indent-tabs-mode: nil -*-
  2. /*
  3.   $Id$
  4.  
  5.   KCalc, a scientific calculator for the X window system using the
  6.   Qt widget libraries, available at no cost at http://www.troll.no
  7.  
  8.   Copyright (C) 1996 Bernd Johannes Wuebben
  9.   wuebben@math.cornell.edu
  10.  
  11.   This program is free software; you can redistribute it and/or modify
  12.   it under the terms of the GNU General Public License as published by
  13.   the Free Software Foundation; either version 2 of the License, or
  14.   (at your option) any later version.
  15.  
  16.   This program is distributed in the hope that it will be useful,
  17.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19.   GNU General Public License for more details.
  20.  
  21.   You should have received a copy of the GNU General Public License
  22.   along with this program; if not, write to the Free Software
  23.   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  24.  
  25. */
  26.  
  27. #include "kcalcdisplay.h"
  28.  
  29. #include <cerrno>
  30. #include <cstdlib>
  31. #include <cctype>
  32.  
  33. #include <QClipboard>
  34. #include <QMouseEvent>
  35. #include <QPainter>
  36. #include <QStyle>
  37. #include <QStyleOption>
  38. #include <QTimer>
  39.  
  40. #include <kglobal.h>
  41. #include <klocale.h>
  42. #include <knotification.h>
  43. #include "kcalc_core.h"
  44. #include "kcalc_settings.h"
  45. #include "kcalcdisplay.moc"
  46.  
  47. KCalcDisplay::KCalcDisplay(QWidget *parent)
  48. : QFrame(parent), beep_(false), groupdigits_(true), twoscomplement_(true),
  49. button_(0), lit_(false), num_base_(NB_DECIMAL), precision_(9),
  50. fixed_precision_(-1), display_amount_(0), history_index_(0),
  51. selection_timer_(new QTimer)
  52. {
  53. setFocusPolicy(Qt::StrongFocus);
  54.  
  55. setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
  56.  
  57. setBackgroundRole(QPalette::Base);
  58. setForegroundRole(QPalette::Text);
  59. setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); // set in kalc.ui
  60.  
  61. KNumber::setDefaultFloatOutput(true);
  62. KNumber::setDefaultFractionalInput(true);
  63.  
  64. connect(this, SIGNAL(clicked()),
  65. this, SLOT(slotDisplaySelected()));
  66. connect(selection_timer_, SIGNAL(timeout()),
  67. this, SLOT(slotSelectionTimedOut()));
  68.  
  69. sendEvent(EventReset);
  70. }
  71.  
  72. KCalcDisplay::~KCalcDisplay()
  73. {
  74. delete selection_timer_;
  75. }
  76.  
  77. void KCalcDisplay::changeSettings()
  78. {
  79. QPalette pal = palette();
  80.  
  81. pal.setColor(QPalette::Text, KCalcSettings::foreColor());
  82. pal.setColor(QPalette::Base, KCalcSettings::backColor());
  83.  
  84. setPalette(pal);
  85.  
  86. setFont(KCalcSettings::displayFont());
  87.  
  88. setPrecision(KCalcSettings::precision());
  89.  
  90. if (KCalcSettings::fixed() == false)
  91. setFixedPrecision(-1);
  92. else
  93. setFixedPrecision(KCalcSettings::fixedPrecision());
  94.  
  95. setBeep(KCalcSettings::beep());
  96. setGroupDigits(KCalcSettings::groupDigits());
  97. setTwosComplement(KCalcSettings::twosComplement());
  98. updateDisplay();
  99. }
  100.  
  101. void KCalcDisplay::updateFromCore(const CalcEngine &core,
  102. bool store_result_in_history)
  103. {
  104. bool tmp_error;
  105. const KNumber &output = core.lastOutput(tmp_error);
  106. if (tmp_error) sendEvent(EventError);
  107. if (setAmount(output)
  108. && store_result_in_history
  109. && (output != KNumber::Zero)) {
  110. // add this latest value to our history
  111. history_list_.insert(history_list_.begin(), output);
  112. history_index_ = 0;
  113. }
  114. }
  115.  
  116. void KCalcDisplay::enterDigit(int data)
  117. {
  118. char tmp;
  119. switch (data) {
  120. case 0:
  121. tmp = '0';
  122. break;
  123. case 1:
  124. tmp = '1';
  125. break;
  126. case 2:
  127. tmp = '2';
  128. break;
  129. case 3:
  130. tmp = '3';
  131. break;
  132. case 4:
  133. tmp = '4';
  134. break;
  135. case 5:
  136. tmp = '5';
  137. break;
  138. case 6:
  139. tmp = '6';
  140. break;
  141. case 7:
  142. tmp = '7';
  143. break;
  144. case 8:
  145. tmp = '8';
  146. break;
  147. case 9:
  148. tmp = '9';
  149. break;
  150. case 0xA:
  151. tmp = 'A';
  152. break;
  153. case 0xB:
  154. tmp = 'B';
  155. break;
  156. case 0xC:
  157. tmp = 'C';
  158. break;
  159. case 0xD:
  160. tmp = 'D';
  161. break;
  162. case 0xE:
  163. tmp = 'E';
  164. break;
  165. case 0xF:
  166. tmp = 'F';
  167. break;
  168. default:
  169. tmp = '?';
  170. break;
  171. }
  172.  
  173. newCharacter(tmp);
  174. }
  175.  
  176. void KCalcDisplay::slotHistoryForward()
  177. {
  178. if (history_list_.empty()) return;
  179. if (history_index_ <= 0) return;
  180.  
  181. history_index_ --;
  182. setAmount(history_list_[history_index_]);
  183. }
  184.  
  185. void KCalcDisplay::slotHistoryBack()
  186. {
  187. if (history_list_.empty()) return;
  188. if (history_index_ >= history_list_.size()) return;
  189.  
  190. setAmount(history_list_[history_index_]);
  191. history_index_ ++;
  192. }
  193.  
  194. bool KCalcDisplay::sendEvent(Event event)
  195. {
  196. switch (event) {
  197. case EventClear:
  198. case EventReset:
  199. display_amount_ = 0;
  200. str_int_ = QLatin1String( "0" );
  201. str_int_exp_.clear();
  202.  
  203. eestate_ = false;
  204. period_ = false;
  205. neg_sign_ = false;
  206.  
  207. updateDisplay();
  208.  
  209. return true;
  210. case EventChangeSign:
  211. return changeSign();
  212. case EventError:
  213. updateDisplay();
  214.  
  215. return true;
  216. default:
  217. return false;
  218. }
  219. }
  220.  
  221. void KCalcDisplay::slotCut()
  222. {
  223. slotCopy();
  224. sendEvent(EventReset);
  225. }
  226.  
  227. void KCalcDisplay::slotCopy()
  228. {
  229. QString txt = text_;
  230. if (num_base_ == NB_HEX)
  231. txt.prepend(QLatin1String( "0x" ));
  232. (QApplication::clipboard())->setText(txt, QClipboard::Clipboard);
  233. (QApplication::clipboard())->setText(txt, QClipboard::Selection);
  234. }
  235.  
  236. void KCalcDisplay::slotPaste(bool bClipboard)
  237. {
  238. QString tmp_str = (QApplication::clipboard())->text(bClipboard ? QClipboard::Clipboard : QClipboard::Selection);
  239.  
  240. if (tmp_str.isNull()) {
  241. if (beep_) KNotification::beep();
  242. return;
  243. }
  244.  
  245. NumBase tmp_num_base = num_base_;
  246.  
  247. // fix up string
  248. tmp_str = tmp_str.trimmed();
  249. if (groupdigits_) {
  250. tmp_str.remove(KGlobal::locale()->thousandsSeparator());
  251. }
  252. tmp_str = tmp_str.toLower();
  253.  
  254. // determine base
  255. if (tmp_str.startsWith(QLatin1String("0x"))) {
  256. tmp_num_base = NB_HEX;
  257. } else if (tmp_str.startsWith(QLatin1String("0b"))) {
  258. tmp_num_base = NB_BINARY;
  259. tmp_str.remove(0, 2);
  260. }
  261.  
  262. if (tmp_num_base != NB_DECIMAL) {
  263. bool was_ok;
  264. qint64 tmp_result = tmp_str.toULongLong(&was_ok, tmp_num_base);
  265.  
  266. if (!was_ok) {
  267. setAmount(KNumber::NotDefined);
  268. if (beep_) KNotification::beep();
  269. return ;
  270. }
  271. setAmount(KNumber(tmp_result));
  272. } else {
  273. setAmount(KNumber(tmp_str, KGlobal::locale()->decimalSymbol()));
  274. if (beep_ && display_amount_ == KNumber::NotDefined)
  275. KNotification::beep();
  276.  
  277. }
  278. }
  279.  
  280. void KCalcDisplay::slotDisplaySelected()
  281. {
  282. if (button_ == Qt::LeftButton) {
  283. if (lit_) {
  284. slotCopy();
  285. selection_timer_->start(100);
  286. } else {
  287. selection_timer_->stop();
  288. }
  289.  
  290. invertColors();
  291. } else {
  292. slotPaste(false); // Selection
  293. }
  294. }
  295.  
  296. void KCalcDisplay::slotSelectionTimedOut()
  297. {
  298. lit_ = false;
  299. invertColors();
  300. selection_timer_->stop();
  301. }
  302.  
  303. void KCalcDisplay::invertColors()
  304. {
  305. QPalette tmp_palette = palette();
  306. tmp_palette.setColor(QPalette::Base,
  307. palette().color(QPalette::Text));
  308. tmp_palette.setColor(QPalette::Text,
  309. palette().color(QPalette::Base));
  310. setPalette(tmp_palette);
  311. }
  312.  
  313. void KCalcDisplay::mousePressEvent(QMouseEvent *e)
  314. {
  315. if (e->button() == Qt::LeftButton) {
  316. lit_ = !lit_;
  317. button_ = Qt::LeftButton;
  318. } else {
  319. button_ = Qt::MidButton;
  320. }
  321.  
  322. emit clicked();
  323. }
  324.  
  325. void KCalcDisplay::setPrecision(int precision)
  326. {
  327. precision_ = precision;
  328. }
  329.  
  330. void KCalcDisplay::setFixedPrecision(int precision)
  331. {
  332. if (fixed_precision_ > precision_)
  333. fixed_precision_ = -1;
  334. else
  335. fixed_precision_ = precision;
  336. }
  337.  
  338. void KCalcDisplay::setBeep(bool flag)
  339. {
  340. beep_ = flag;
  341. }
  342.  
  343. void KCalcDisplay::setGroupDigits(bool flag)
  344. {
  345. groupdigits_ = flag;
  346. }
  347.  
  348. void KCalcDisplay::setTwosComplement(bool flag)
  349. {
  350. twoscomplement_ = flag;
  351. }
  352.  
  353. const KNumber &KCalcDisplay::getAmount() const
  354. {
  355. return display_amount_;
  356. }
  357.  
  358. bool KCalcDisplay::setAmount(const KNumber &new_amount)
  359. {
  360. QString display_str;
  361.  
  362. str_int_ = QLatin1String( "0" );
  363. str_int_exp_.clear();
  364. period_ = false;
  365. neg_sign_ = false;
  366. eestate_ = false;
  367.  
  368. if ((num_base_ != NB_DECIMAL) &&
  369. (new_amount.type() != KNumber::SpecialType)) {
  370. display_amount_ = new_amount.integerPart();
  371. if (twoscomplement_) {
  372. // treat number as 64-bit unsigned
  373. quint64 tmp_workaround = static_cast<quint64>(display_amount_);
  374. display_str = QString::number(tmp_workaround, num_base_).toUpper();
  375. } else {
  376. // QString::number treats non-decimal as unsigned
  377. qint64 tmp_workaround = static_cast<qint64>(display_amount_);
  378. bool neg = tmp_workaround < 0;
  379. if (neg) tmp_workaround = qAbs(tmp_workaround);
  380. display_str = QString::number(tmp_workaround, num_base_).toUpper();
  381. if (neg) display_str.prepend(KGlobal::locale()->negativeSign());
  382. }
  383. } else {
  384. // num_base_ == NB_DECIMAL || new_amount.type() == KNumber::SpecialType
  385. display_amount_ = new_amount;
  386. display_str = display_amount_.toQString(KCalcSettings::precision(),
  387. fixed_precision_);
  388. }
  389.  
  390. setText(display_str);
  391. emit changedAmount(display_amount_);
  392. return true;
  393. }
  394.  
  395. void KCalcDisplay::setText(const QString &string)
  396. {
  397. // note that "C" locale is being used internally
  398. text_ = string;
  399. // don't mess with special numbers
  400. bool special = (string.contains(QLatin1String( "nan" )) || string.contains(QLatin1String( "inf" )));
  401. // The decimal mode needs special treatment for two reasons, because: a) it uses KGlobal::locale() to get a localized
  402. // format and b) it has possible numbers after the decimal place. Neither applies to Binary, Hexadecimal or Octal.
  403. if ((num_base_ == NB_DECIMAL) && groupdigits_ && !special) {
  404. // when input ends with "." (because incomplete), the
  405. // formatNumber method does not work; fix by hand by
  406. // truncating, formatting and appending again
  407. if (string.endsWith(QLatin1Char( '.' ))) {
  408. text_.chop(1);
  409. // Note: rounding happened already above!
  410. text_ = KGlobal::locale()->formatNumber(text_, false, 0);
  411. text_.append(KGlobal::locale()->decimalSymbol());
  412. } else {
  413. // Note: rounding happened already above!
  414. text_ = KGlobal::locale()->formatNumber(text_, false, 0);
  415. }
  416. // Grouping non-decimal numbers, which don't rely on KGlobal::locale() and don't have decimal places: Binary and Hex
  417. // Binary
  418. }else if ((num_base_ == NB_BINARY) && groupdigits_ && !special) {
  419. /* We create an temporary string to work with, we fill it up with the original figure, number by number
  420. and insert a whitespace after every 4th position */
  421. QString tmp_display_string;
  422. for (int i = 0; i < text_.length(); i++){
  423. /* The actualy check if we are at the 4th position.
  424. * Note: We produce a leading space here, which isn't 'visible' and shouldn't harm anyone so for
  425. * the sake of readability I didn't catch it. (loop start's with 0; 0 % 4 = 0 -> Added whitespace) */
  426. if(i % 4 == 0){
  427. tmp_display_string = tmp_display_string + " ";
  428. }
  429. /* if(i % 8 == 0){
  430. tmp_display_string = tmp_display_string + " ";
  431. } */
  432. tmp_display_string = tmp_display_string + text_[i];
  433. }
  434. text_ = tmp_display_string;
  435. // Hex
  436. }else if ((num_base_ == NB_HEX) && groupdigits_ && !special) {
  437. /* We create an temporary string to work with, we fill it up with the original figure, number by number
  438. and insert a whitespace after every 2nd position */
  439. QString tmp_display_string;
  440. for (int i = 0; i < text_.length(); i++){
  441. /* The actualy check if we are at the 2nd position.
  442. * Note: We produce a leading space here, which isn't 'visible' and shouldn't harm anyone so for
  443. * the sake of readability I didn't catch it. (loop start's with 0; 0 % 2 = 0 -> Added whitespace) */
  444. if(i % 2 == 0){
  445. tmp_display_string = tmp_display_string + " ";
  446. }
  447. tmp_display_string = tmp_display_string + text_[i];
  448. }
  449. text_ = tmp_display_string;
  450. }
  451.  
  452. update();
  453. emit changedText(text_);
  454. }
  455.  
  456. QString KCalcDisplay::text() const
  457. {
  458. return text_;
  459. }
  460.  
  461. /* change representation of display to new base (i.e. binary, decimal,
  462.   octal, hexadecimal). The amount being displayed is changed to this
  463.   base, but for now this amount can not be modified anymore (like
  464.   being set with "setAmount"). Return value is the new base. */
  465. int KCalcDisplay::setBase(NumBase new_base)
  466. {
  467. switch (new_base) {
  468. case NB_HEX:
  469. num_base_ = NB_HEX;
  470. period_ = false;
  471. break;
  472. case NB_DECIMAL:
  473. num_base_ = NB_DECIMAL;
  474. break;
  475. case NB_OCTAL:
  476. num_base_ = NB_OCTAL;
  477. period_ = false;
  478. break;
  479. case NB_BINARY:
  480. num_base_ = NB_BINARY;
  481. period_ = false;
  482. break;
  483. default: // we shouldn't ever end up here
  484. num_base_ = NB_DECIMAL;
  485. }
  486.  
  487. // reset amount
  488. setAmount(display_amount_);
  489.  
  490. return num_base_;
  491. }
  492.  
  493. void KCalcDisplay::setStatusText(int i, const QString &text)
  494. {
  495. if (i < NUM_STATUS_TEXT)
  496. str_status_[i] = text;
  497. update();
  498. }
  499.  
  500. bool KCalcDisplay::updateDisplay()
  501. {
  502. // Put sign in front.
  503. QString tmp_string;
  504. if (neg_sign_ == true) {
  505. tmp_string = QLatin1Char( '-' ) + str_int_;
  506. } else {
  507. tmp_string = str_int_;
  508. }
  509.  
  510. bool ok;
  511.  
  512. switch (num_base_) {
  513. // TODO: use QString:::toULongLong() instead of STRTOUL
  514. case NB_BINARY:
  515. Q_ASSERT(period_ == false && eestate_ == false);
  516. setText(tmp_string);
  517. display_amount_ = str_int_.toULongLong(&ok, 2);
  518. if (neg_sign_) display_amount_ = -display_amount_;
  519. break;
  520.  
  521. case NB_OCTAL:
  522. Q_ASSERT(period_ == false && eestate_ == false);
  523. setText(tmp_string);
  524. display_amount_ = str_int_.toULongLong(&ok, 8);
  525. if (neg_sign_) display_amount_ = -display_amount_;
  526. break;
  527.  
  528. case NB_HEX:
  529. Q_ASSERT(period_ == false && eestate_ == false);
  530. setText(tmp_string);
  531. display_amount_ = str_int_.toULongLong(&ok, 16);
  532. if (neg_sign_) display_amount_ = -display_amount_;
  533. break;
  534.  
  535. case NB_DECIMAL:
  536. if (eestate_ == false) {
  537. setText(tmp_string);
  538. display_amount_ = KNumber(tmp_string);
  539. } else {
  540. if (str_int_exp_.isNull()) {
  541. // add 'e0' to display but not to conversion
  542. display_amount_ = KNumber(tmp_string);
  543. setText(tmp_string + QLatin1String("e0"));
  544. } else {
  545. tmp_string += QLatin1Char('e') + str_int_exp_;
  546. setText(tmp_string);
  547. display_amount_ = KNumber(tmp_string);
  548. }
  549. }
  550. break;
  551.  
  552. default:
  553. return false;
  554. }
  555. emit changedAmount(display_amount_);
  556. return true;
  557. }
  558.  
  559. void KCalcDisplay::newCharacter(char const new_char)
  560. {
  561. // test if character is valid
  562. switch (new_char) {
  563. case 'e':
  564. // EE can be set only once and in decimal mode
  565. if (num_base_ != NB_DECIMAL ||
  566. eestate_ == true) {
  567. if (beep_) KNotification::beep();
  568. return;
  569. }
  570. eestate_ = true;
  571. break;
  572.  
  573. case '.':
  574. // Period can be set only once and only in decimal
  575. // mode, also not in EE-mode
  576. if (num_base_ != NB_DECIMAL ||
  577. period_ == true ||
  578. eestate_ == true) {
  579. if (beep_) KNotification::beep();
  580. return;
  581. }
  582. period_ = true;
  583. break;
  584.  
  585. case 'F':
  586. case 'E':
  587. case 'D':
  588. case 'C':
  589. case 'B':
  590. case 'A':
  591. if (num_base_ == NB_DECIMAL) {
  592. if (beep_) KNotification::beep();
  593. return;
  594. }
  595. // no break
  596. case '9':
  597. case '8':
  598. if (num_base_ == NB_OCTAL) {
  599. if (beep_) KNotification::beep();
  600. return;
  601. }
  602. // no break
  603. case '7':
  604. case '6':
  605. case '5':
  606. case '4':
  607. case '3':
  608. case '2':
  609. if (num_base_ == NB_BINARY) {
  610. if (beep_) KNotification::beep();
  611. return;
  612. }
  613. // no break
  614. case '1':
  615. case '0':
  616. break;
  617.  
  618. default:
  619. if (beep_) KNotification::beep();
  620. return;
  621. }
  622.  
  623. // change exponent or mantissa
  624. if (eestate_) {
  625. // ignore ',' before 'e'. turn e.g. '123.e' into '123e'
  626. if (new_char == 'e' && str_int_.endsWith(QLatin1Char( '.' ))) {
  627. str_int_.chop(1);
  628. period_ = false;
  629. }
  630.  
  631. // 'e' only starts ee_mode, leaves strings unchanged
  632. if (new_char != 'e' &&
  633. // do not add '0' if at start of exp
  634. !(str_int_exp_.isNull() && new_char == '0'))
  635. str_int_exp_.append(QLatin1Char( new_char ));
  636. } else {
  637. // handle first character
  638. if (str_int_ == QLatin1String( "0" )) {
  639. switch (new_char) {
  640. case '.':
  641. // display "0." not just "."
  642. str_int_.append(QLatin1Char( new_char ));
  643. break;
  644. case 'e':
  645. // display "0e" not just "e"
  646. // "0e" does not make sense either, but...
  647. str_int_.append(QLatin1Char( new_char ));
  648. break;
  649. default:
  650. // no leading '0's
  651. str_int_[0] = new_char;
  652. }
  653. } else
  654. str_int_.append(QLatin1Char( new_char ));
  655. }
  656.  
  657. updateDisplay();
  658. }
  659.  
  660. void KCalcDisplay::deleteLastDigit()
  661. {
  662. // Only partially implemented !!
  663. if (eestate_) {
  664. if (str_int_exp_.isNull()) {
  665. eestate_ = false;
  666. } else {
  667. int length = str_int_exp_.length();
  668. if (length > 1) {
  669. str_int_exp_.chop(1);
  670. } else {
  671. str_int_exp_ = QLatin1String( (const char *)0 );
  672. }
  673. }
  674. } else {
  675. int length = str_int_.length();
  676. if (length > 1) {
  677. if (str_int_[length-1] == QLatin1Char( '.' ))
  678. period_ = false;
  679. str_int_.chop(1);
  680. } else {
  681. Q_ASSERT(period_ == false);
  682. str_int_[0] = '0';
  683. }
  684. }
  685.  
  686. updateDisplay();
  687. }
  688.  
  689. // change Sign of display. Problem: Only possible here, when in input
  690. // mode. Otherwise return 'false' so that the kcalc_core can handle
  691. // things.
  692. bool KCalcDisplay::changeSign()
  693. {
  694. //stupid way, to see if in input_mode or display_mode
  695. if (str_int_ == QLatin1String( "0" )) return false;
  696.  
  697. if (eestate_) {
  698. if (!str_int_exp_.isNull()) {
  699. if (str_int_exp_[0] != QLatin1Char( '-' ))
  700. str_int_exp_.prepend(QLatin1Char( '-' ));
  701. else
  702. str_int_exp_.remove(QLatin1Char( '-' ));
  703. }
  704. } else {
  705. neg_sign_ = ! neg_sign_;
  706. }
  707.  
  708. updateDisplay();
  709.  
  710. return true;
  711. }
  712.  
  713. void KCalcDisplay::initStyleOption(QStyleOptionFrame *option) const
  714. {
  715. if (!option) return;
  716.  
  717. option->initFrom(this);
  718. option->state &= ~QStyle::State_HasFocus; // don't draw focus highlight
  719. if (frameShadow() == QFrame::Sunken) {
  720. option->state |= QStyle::State_Sunken;
  721. } else if (frameShadow() == QFrame::Raised) {
  722. option->state |= QStyle::State_Raised;
  723. }
  724. option->lineWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth,
  725. option, this);
  726. option->midLineWidth = 0;
  727. }
  728.  
  729. void KCalcDisplay::paintEvent(QPaintEvent *)
  730. {
  731. QPainter painter(this);
  732.  
  733. QStyleOptionFrame option;
  734. initStyleOption(&option);
  735.  
  736. style()->drawPrimitive(QStyle::PE_PanelLineEdit, &option, &painter, this);
  737.  
  738. // draw display text
  739. int margin = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, 0);
  740. QRect cr = contentsRect();
  741. cr.adjust(margin*2, 0, -margin*2, 0); // provide a margin
  742. int align = QStyle::visualAlignment(layoutDirection(),
  743. Qt::AlignRight | Qt::AlignVCenter);
  744. painter.drawText(cr, align | Qt::TextSingleLine, text_);
  745.  
  746. // draw the status texts using half of the normal
  747. // font size but not smaller than 7pt
  748. QFont fnt(font());
  749. fnt.setPointSize(qMax((fnt.pointSize() / 2), 7));
  750. painter.setFont(fnt);
  751. QFontMetrics fm(fnt);
  752. uint w = fm.width(QLatin1String( "________" ));
  753. uint h = fm.height();
  754.  
  755. for (int n = 0; n < NUM_STATUS_TEXT; n++) {
  756. painter.drawText(5 + n * w, h, str_status_[n]);
  757. }
  758. }
  759.  
  760. QSize KCalcDisplay::sizeHint() const
  761. {
  762. // basic size
  763. QSize sz = fontMetrics().size(Qt::TextSingleLine, text_);
  764.  
  765. // expanded by half font height to make room for the status texts
  766. QFont fnt(font());
  767. fnt.setPointSize(qMax((fnt.pointSize() / 2), 7));
  768. QFontMetrics fm(fnt);
  769. sz.setHeight(sz.height() + fm.height());
  770.  
  771. QStyleOptionFrame option;
  772. initStyleOption(&option);
  773. return (style()->sizeFromContents(QStyle::CT_LineEdit,
  774. &option,
  775. sz.expandedTo(QApplication::globalStrut()),
  776. this));
  777. }
  778.