#!/usr/bin/env python ############################################################################# ## ## Copyright (C) 2005-2005 Trolltech AS. All rights reserved. ## ## This file is part of the example classes of the Qt Toolkit. ## ## This file may be used under the terms of the GNU General Public ## License version 2.0 as published by the Free Software Foundation ## and appearing in the file LICENSE.GPL included in the packaging of ## this file. Please review the following information to ensure GNU ## General Public Licensing requirements will be met: ## http://www.trolltech.com/products/qt/opensource.html ## ## If you are unsure which license is appropriate for your use, please ## review the following information: ## http://www.trolltech.com/products/qt/licensing.html or contact the ## sales department at sales@trolltech.com. ## ## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ## ############################################################################# import sys import math from PyQt4 import QtCore, QtGui class Button(QtGui.QToolButton): def __init__(self, text, color, parent=None): QtGui.QToolButton.__init__(self, parent) self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred) self.setText(text) newPalette = self.palette() newPalette.setColor(QtGui.QPalette.Button, color) self.setPalette(newPalette) def sizeHint(self): size = QtGui.QToolButton.sizeHint(self) size.setHeight(size.height() + 20) size.setWidth(max(size.width(), size.height())) return size class Calculator(QtGui.QDialog): NumDigitButtons = 10 def __init__(self, parent=None): QtGui.QDialog.__init__(self, parent) self.pendingAdditiveOperator = QtCore.QString() self.pendingMultiplicativeOperator = QtCore.QString() self.sumInMemory = 0.0 self.sumSoFar = 0.0 self.factorSoFar = 0.0 self.waitingForOperand = True self.display = QtGui.QLineEdit("0") self.display.setReadOnly(True) self.display.setAlignment(QtCore.Qt.AlignRight) self.display.setMaxLength(15) self.display.installEventFilter(self) font = self.display.font() font.setPointSize(font.pointSize() + 8) self.display.setFont(font) digitColor = QtGui.QColor(150, 205, 205) backspaceColor = QtGui.QColor(225, 185, 135) memoryColor = QtGui.QColor(100, 155, 155) operatorColor = QtGui.QColor(155, 175, 195) self.digitButtons = [] for i in range(Calculator.NumDigitButtons): self.digitButtons.append(self.createButton(QtCore.QString.number(i), digitColor, self.digitClicked)) self.pointButton = self.createButton(self.tr("."), digitColor, self.pointClicked) self.changeSignButton = self.createButton(self.tr("\261"), digitColor, self.changeSignClicked) self.backspaceButton = self.createButton(self.tr("Backspace"), backspaceColor, self.backspaceClicked) self.clearButton = self.createButton(self.tr("Clear"), backspaceColor, self.clear) self.clearAllButton = self.createButton(self.tr("Clear All"), backspaceColor.light(120), self.clearAll) self.clearMemoryButton = self.createButton(self.tr("MC"), memoryColor, self.clearMemory) self.readMemoryButton = self.createButton(self.tr("MR"), memoryColor, self.readMemory) self.setMemoryButton = self.createButton(self.tr("MS"), memoryColor, self.setMemory) self.addToMemoryButton = self.createButton(self.tr("M+"), memoryColor, self.addToMemory) self.divisionButton = self.createButton(self.tr("\367"), operatorColor, self.multiplicativeOperatorClicked) self.timesButton = self.createButton(self.tr("\327"), operatorColor, self.multiplicativeOperatorClicked) self.minusButton = self.createButton(self.tr("-"), operatorColor, self.additiveOperatorClicked) self.plusButton = self.createButton(self.tr("+"), operatorColor, self.additiveOperatorClicked) self.squareRootButton = self.createButton(self.tr("Sqrt"), operatorColor, self.unaryOperatorClicked) self.powerButton = self.createButton(self.tr("x\262"), operatorColor, self.unaryOperatorClicked) self.reciprocalButton = self.createButton(self.tr("1/x"), operatorColor, self.unaryOperatorClicked) self.equalButton = self.createButton(self.tr("="), operatorColor.light(120), self.equalClicked) mainLayout = QtGui.QGridLayout() mainLayout.setSizeConstraint(QtGui.QLayout.SetFixedSize) mainLayout.addWidget(self.display, 0, 0, 1, 6) mainLayout.addWidget(self.backspaceButton, 1, 0, 1, 2) mainLayout.addWidget(self.clearButton, 1, 2, 1, 2) mainLayout.addWidget(self.clearAllButton, 1, 4, 1, 2) mainLayout.addWidget(self.clearMemoryButton, 2, 0) mainLayout.addWidget(self.readMemoryButton, 3, 0) mainLayout.addWidget(self.setMemoryButton, 4, 0) mainLayout.addWidget(self.addToMemoryButton, 5, 0) for i in range(1, Calculator.NumDigitButtons): row = ((9 - i) / 3) + 2 column = ((i - 1) % 3) + 1 mainLayout.addWidget(self.digitButtons[i], row, column) mainLayout.addWidget(self.digitButtons[0], 5, 1) mainLayout.addWidget(self.pointButton, 5, 2) mainLayout.addWidget(self.changeSignButton, 5, 3) mainLayout.addWidget(self.divisionButton, 2, 4) mainLayout.addWidget(self.timesButton, 3, 4) mainLayout.addWidget(self.minusButton, 4, 4) mainLayout.addWidget(self.plusButton, 5, 4) mainLayout.addWidget(self.squareRootButton, 2, 5) mainLayout.addWidget(self.powerButton, 3, 5) mainLayout.addWidget(self.reciprocalButton, 4, 5) mainLayout.addWidget(self.equalButton, 5, 5) self.setLayout(mainLayout) self.setWindowTitle(self.tr("Calculator")) def eventFilter(self, target, event): if target == self.display: if (event.type() == QtCore.QEvent.MouseButtonPress or event.type() == QtCore.QEvent.MouseButtonDblClick or event.type() == QtCore.QEvent.MouseButtonRelease or event.type() == QtCore.QEvent.ContextMenu): if mouseEvent.buttons() & QtCore.Qt.LeftButton: newPalette = self.palette() newPalette.setColor(QtGui.QPalette.Base, self.display.palette().color(QtGui.QPalette.Text)) newPalette.setColor(QtGui.QPalette.Text, self.display.palette().color(QtGui.QPalette.Base)) self.display.setPalette(newPalette) else: self.display.setPalette(palette()) return True return QtGui.QDialog.eventFilter(self, target, event) def digitClicked(self): clickedButton = self.sender() digitValue, success = clickedButton.text().toInt() if self.display.text() == "0" and digitValue == 0.0: return if self.waitingForOperand: self.display.clear() self.waitingForOperand = False self.display.setText(self.display.text() + QtCore.QString.number(digitValue)) def unaryOperatorClicked(self): clickedButton = self.sender() clickedOperator = clickedButton.text() operand, success = self.display.text().toDouble() if clickedOperator == self.tr("Sqrt"): if operand < 0.0: self.abortOperation() return result = math.sqrt(operand) elif clickedOperator == self.tr("x\262"): result = math.pow(operand, 2.0) elif clickedOperator == self.tr("1/x"): if operand == 0.0: self.abortOperation() return result = 1.0 / operand self.display.setText(QtCore.QString.number(result)) self.waitingForOperand = True def additiveOperatorClicked(self): clickedButton = self.sender() clickedOperator = clickedButton.text() operand, success = self.display.text().toDouble() if not self.pendingMultiplicativeOperator.isEmpty(): if not self.calculate(operand, self.pendingMultiplicativeOperator): self.abortOperation() return self.display.setText(QtCore.QString.number(self.factorSoFar)) operand = self.factorSoFar self.factorSoFar = 0.0 self.pendingMultiplicativeOperator.clear() if not self.pendingAdditiveOperator.isEmpty(): if not self.calculate(operand, self.pendingAdditiveOperator): self.abortOperation() return self.display.setText(QtCore.QString.number(self.sumSoFar)) else: self.sumSoFar = operand self.pendingAdditiveOperator = clickedOperator self.waitingForOperand = True def multiplicativeOperatorClicked(self): clickedButton = self.sender() clickedOperator = clickedButton.text() operand, success = self.display.text().toDouble() if not self.pendingMultiplicativeOperator.isEmpty(): if not self.calculate(operand, self.pendingMultiplicativeOperator): self.abortOperation() return self.display.setText(QtCore.QString.number(self.factorSoFar)) else: self.factorSoFar = operand self.pendingMultiplicativeOperator = clickedOperator self.waitingForOperand = True def equalClicked(self): operand, success = self.display.text().toDouble() if not self.pendingMultiplicativeOperator.isEmpty(): if not self.calculate(operand, self.pendingMultiplicativeOperator): self.abortOperation() return operand = self.factorSoFar self.factorSoFar = 0.0 self.pendingMultiplicativeOperator.clear() if not self.pendingAdditiveOperator.isEmpty(): if not self.calculate(operand, self.pendingAdditiveOperator): self.abortOperation() return self.pendingAdditiveOperator.clear() else: self.sumSoFar = operand self.display.setText(QtCore.QString.number(self.sumSoFar)) self.sumSoFar = 0.0 self.waitingForOperand = True def pointClicked(self): if self.waitingForOperand: self.display.setText("0") if not self.display.text().contains("."): self.display.setText(self.display.text() + self.tr(".")) self.waitingForOperand = False def changeSignClicked(self): text = self.display.text() value, success = text.toDouble() if value > 0.0: text.prepend(self.tr("-")) elif value < 0.0: text.remove(0, 1) self.display.setText(text) def backspaceClicked(self): if self.waitingForOperand: return text = self.display.text() text.chop(1) if text.isEmpty(): text = "0" self.waitingForOperand = True self.display.setText(text) def clear(self): if self.waitingForOperand: return self.display.setText("0") self.waitingForOperand = True def clearAll(self): self.sumSoFar = 0.0 self.factorSoFar = 0.0 self.pendingAdditiveOperator.clear() self.pendingMultiplicativeOperator.clear() self.display.setText("0") self.waitingForOperand = True def clearMemory(self): self.sumInMemory = 0.0 def readMemory(self): self.display.setText(QtCore.QString.number(self.sumInMemory)) self.waitingForOperand = True def setMemory(self): self.equalClicked() self.sumInMemory, success = self.display.text().toDouble() def addToMemory(self): self.equalClicked() value, success = self.display.text().toDouble() self.sumInMemory += value def createButton(self, text, color, member): button = Button(text, color) self.connect(button, QtCore.SIGNAL("clicked()"), member) return button def abortOperation(self): self.clearAll() self.display.setText(self.tr("####")) def calculate(self, rightOperand, pendingOperator): if pendingOperator == self.tr("+"): self.sumSoFar += rightOperand elif pendingOperator == self.tr("-"): self.sumSoFar -= rightOperand elif pendingOperator == self.tr("\327"): self.factorSoFar *= rightOperand elif pendingOperator == self.tr("\367"): if rightOperand == 0.0: return False self.factorSoFar /= rightOperand return True if __name__ == "__main__": app = QtGui.QApplication(sys.argv) calc = Calculator() sys.exit(calc.exec_())