1 from PySide.QtCore import *
2 from PySide.QtGui import *
3 from PySide.QtWebKit import *
6 class FocusLineEdit(QLineEdit):
7 def __init__(self, text):
8 super(FocusLineEdit, self).__init__(text)
12 def mousePressEvent(self, event):
13 if event.button() == Qt.LeftButton:
14 self.setCursorPosition(100)
18 super(FocusLineEdit, self).mousePressEvent(event)
20 def focusOutEvent(self, event):
24 sizeh = super(FocusLineEdit, self).sizeHint()
25 sizeh.setWidth(self.fontMetrics().averageCharWidth() * self.maxLength())
28 class TransactionItem(QTableWidgetItem):
29 def __init__(self, text, align=Qt.AlignLeft):
30 super(TransactionItem, self).__init__(text)
31 self.setFlags(Qt.ItemIsEnabled)
32 self.setTextAlignment(align|Qt.AlignVCenter)
34 class TransactionsTable(QTableWidget):
35 # These are the proportions for the various columns
36 hedprops = (130, 150, 400, 100, 100)
39 super(TransactionsTable, self).__init__()
41 self.setColumnCount(5)
42 hedlabels = (self.tr('Status'),
44 self.tr('Transactions'),
47 self.setHorizontalHeaderLabels(hedlabels)
48 for i, sz in enumerate(self.hedprops):
49 self.horizontalHeader().resizeSection(i, sz)
51 self.setSelectionBehavior(self.SelectRows)
52 self.setSelectionMode(self.NoSelection)
53 self.setFocusPolicy(Qt.NoFocus)
54 self.setAlternatingRowColors(True)
55 self.verticalHeader().hide()
56 self.setShowGrid(False)
57 self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
58 self.horizontalHeader().setStretchLastSection(True)
60 # Resize columns while maintaining proportions
61 def resizeEvent(self, event):
62 self_width = event.size().width()
63 total_prop_width = sum(self.hedprops)
64 newszs = [sz * self_width / total_prop_width for sz in self.hedprops]
65 for i, sz in enumerate(newszs):
66 self.horizontalHeader().resizeSection(i, sz)
68 def add_transaction_entry(self, transaction):
70 confirms = transaction['confirmations']
71 unixtime = transaction['time']
72 address = transaction['address']
73 credit = transaction['amount']
75 category = transaction['category']
79 status = self.tr('Confirmed (%i)')%confirms
81 status = self.tr('Processing... (%i)')%confirms
83 status = self.tr('Validating... (%i)')%confirms
85 status_item = TransactionItem(status)
86 self.setItem(0, 0, status_item)
88 date_formatter = QDateTime()
89 date_formatter.setTime_t(unixtime)
90 # we need to do this in parts to have a month name translation
91 # datetime = date_formatter.toString('hh:mm d ')
92 # datetime += self.tr(date_formatter.toString('MMM '))
93 # datetime += date_formatter.toString('yy')
94 datetime = date_formatter.toString('hh:mm d MMM yy')
95 date_item = TransactionItem(datetime)
96 self.setItem(0, 1, date_item)
98 if category == 'send':
99 description = self.tr('Sent to %s')%address
100 elif category == 'receive':
101 description = self.tr('Received to %s')%address
102 trans_item = TransactionItem(description)
103 self.setItem(0, 2, trans_item)
105 credits_item = TransactionItem(str(credit), Qt.AlignRight)
106 self.setItem(0, 3, credits_item)
108 balance_item = TransactionItem(str(balance), Qt.AlignRight)
109 self.setItem(0, 4, balance_item)
112 self.disable_table_item(status_item)
113 self.disable_table_item(date_item)
114 self.disable_table_item(trans_item)
115 self.disable_table_item(credits_item)
116 self.disable_table_item(balance_item)
118 def disable_table_item(self, item):
119 brush = item.foreground()
120 brush.setColor(Qt.gray)
121 item.setForeground(brush)
123 font.setStyle(font.StyleItalic)
126 class Cashier(QDialog):
127 def __init__(self, core, clipboard, parent=None):
128 super(Cashier, self).__init__(parent)
130 self.clipboard = clipboard
132 self.create_actions()
133 main_layout = QVBoxLayout(self)
135 youraddy = QHBoxLayout()
136 # Balance + Send button
137 self.balance_label = QLabel()
138 self.refresh_balance()
139 sendbtn = QToolButton(self)
140 sendbtn.setDefaultAction(self.send_act)
141 # Address + New button + Copy button
142 uraddtext = QLabel(self.tr('Your address:'))
143 self.addy = FocusLineEdit(self.core.default_address())
144 newaddybtn = QToolButton(self)
145 newaddybtn.setDefaultAction(self.newaddy_act)
146 copyaddybtn = QToolButton(self)
147 copyaddybtn.setDefaultAction(self.copyaddy_act)
148 # Add them to the layout
149 youraddy.addWidget(uraddtext)
150 youraddy.addWidget(self.addy)
151 youraddy.addWidget(newaddybtn)
152 youraddy.addWidget(copyaddybtn)
153 youraddy.addStretch()
154 youraddy.addWidget(self.balance_label)
155 youraddy.addWidget(sendbtn)
156 main_layout.addLayout(youraddy)
158 self.transactions_table = TransactionsTable()
159 main_layout.addWidget(self.transactions_table)
161 #webview = QWebView()
162 #webview.load('http://bitcoinwatch.com/')
163 #webview.setFixedSize(880, 300)
164 #mf = webview.page().mainFrame()
165 #mf.setScrollBarPolicy(Qt.Horizontal,
166 # Qt.ScrollBarAlwaysOff)
167 #mf.setScrollBarPolicy(Qt.Vertical,
168 # Qt.ScrollBarAlwaysOff)
169 #main_layout.addWidget(webview)
171 self.setWindowTitle(self.tr('Spesmilo'))
172 if parent is not None:
173 self.setWindowIcon(parent.bitcoin_icon)
174 self.setAttribute(Qt.WA_DeleteOnClose, False)
176 refresh_info_timer = QTimer(self)
177 refresh_info_timer.timeout.connect(self.refresh_info)
178 refresh_info_timer.start(1000)
179 # Stores time of last transaction added to the table
180 self.last_tx_time = 0
181 # Used for updating number of confirms
182 # key=txid, category val=row, confirms
183 self.trans_lookup = {}
185 #self.transactions_table.add_transaction_entry({'confirmations': 3, 'time': 1223332, 'address': 'fake', 'amount': 111, 'category': 'send'})
186 #self.transactions_table.add_transaction_entry({'confirmations': 0, 'time': 1223332, 'address': 'fake', 'amount': 111, 'category': 'send'})
188 self.resize(900, 300)
190 def refresh_info(self):
191 self.refresh_balance()
192 self.refresh_transactions()
194 def refresh_transactions(self):
195 #transactions = [t for t in self.core.transactions() if t['time'] > self.last_tx_time]
196 transactions = self.core.transactions()
197 self.transactions_table.clearContents()
198 self.transactions_table.setRowCount(0)
199 # whether list has updates
200 #if not transactions:
202 #self.last_tx_time = transactions[-1]['time']
203 transactions.sort(key=lambda t: t['time'])
205 #txids = [t['txid'] for t in transactions]
207 #txids = list(set(txids))
209 # mattrans = [t for t in transactions if t['txid'] == txid]
211 for t in transactions:
212 self.transactions_table.add_transaction_entry(t)
214 def refresh_balance(self):
215 bltext = self.tr('Balance: %.2f BTC')%self.core.balance()
216 self.balance_label.setText(bltext)
218 def create_actions(self):
219 icon = lambda s: QIcon('./icons/' + s)
221 self.send_act = QAction(icon('forward.png'), self.tr('Send'),
222 self, toolTip=self.tr('Send bitcoins to another person'),
223 triggered=self.new_send_dialog)
224 self.newaddy_act = QAction(icon('document_new.png'),
225 self.tr('New address'), self,
226 toolTip=self.tr('Create new address for accepting bitcoins'),
227 triggered=self.new_address)
228 self.copyaddy_act = QAction(icon('klipper.png'),
229 self.tr('Copy address'),
230 self, toolTip=self.tr('Copy address to clipboard'),
231 triggered=self.copy_address)
233 def new_send_dialog(self):
234 if self.parent() is not None:
235 send_dialog = send.SendDialog(self.core, self.parent())
237 send_dialog = send.SendDialog(self.core, self)
239 def new_address(self):
240 self.addy.setText(self.core.new_address())
242 def copy_address(self):
243 self.clipboard.setText(self.addy.text())
245 if __name__ == '__main__':
248 import core_interface
249 os.system('/home/genjix/src/bitcoin/bitcoind')
250 translator = QTranslator()
251 #translator.load('data/translations/eo_EO')
252 app = QApplication(sys.argv)
253 core = core_interface.CoreInterface()
254 clipboard = qApp.clipboard()
255 cashier = Cashier(core, clipboard)
257 sys.exit(app.exec_())