URI: 
       tcreate a class for transaction dialog - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit d51a8d0f252b3a57d0b2ab1e2149890d97322824
   DIR parent 27977e6eb0624075d74c773310edad2138db2ef4
  HTML Author: ThomasV <thomasv@gitorious>
       Date:   Sat, 14 Sep 2013 21:07:54 +0200
       
       create a class for transaction dialog
       
       Diffstat:
         M gui/gui_classic/main_window.py      |     155 +++----------------------------
         A gui/gui_classic/transaction_dialog… |     220 +++++++++++++++++++++++++++++++
         M lib/__init__.py                     |       1 +
         M lib/commands.py                     |       2 +-
         M lib/interface.py                    |       2 +-
         M lib/network.py                      |       6 ++++++
         M lib/transaction.py                  |      14 +++++++++++---
         M lib/util.py                         |       5 ++++-
         M setup.py                            |       1 +
       
       9 files changed, 257 insertions(+), 149 deletions(-)
       ---
   DIR diff --git a/gui/gui_classic/main_window.py b/gui/gui_classic/main_window.py
       t@@ -612,59 +612,16 @@ class ElectrumWindow(QMainWindow):
                tx_hash = str(item.data(0, Qt.UserRole).toString())
                if not tx_hash: return
                menu = QMenu()
       -        #menu.addAction(_("Copy ID to Clipboard"), lambda: self.app.clipboard().setText(tx_hash))
       -        menu.addAction(_("Details"), lambda: self.show_tx_details(self.wallet.transactions.get(tx_hash)))
       +        menu.addAction(_("Copy ID to Clipboard"), lambda: self.app.clipboard().setText(tx_hash))
       +        menu.addAction(_("Details"), lambda: self.show_transaction(self.wallet.transactions.get(tx_hash)))
                menu.addAction(_("Edit description"), lambda: self.tx_label_clicked(item,2))
                menu.exec_(self.contacts_list.viewport().mapToGlobal(position))
        
        
       -    def show_tx_details(self, tx):
       -        dialog = QDialog(self)
       -        dialog.setModal(1)
       -        dialog.setWindowTitle(_("Transaction Details"))
       -        vbox = QVBoxLayout()
       -        dialog.setLayout(vbox)
       -        dialog.setMinimumSize(600,300)
       -
       -        tx_hash = tx.hash()
       -        if tx_hash in self.wallet.transactions.keys():
       -            is_relevant, is_mine, v, fee = self.wallet.get_tx_value(tx)
       -            conf, timestamp = self.wallet.verifier.get_confirmations(tx_hash)
       -            if timestamp:
       -                time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
       -            else:
       -                time_str = 'pending'
       -        else:
       -            is_mine = False
       -
       -        vbox.addWidget(QLabel("Transaction ID:"))
       -        e  = QLineEdit(tx_hash)
       -        e.setReadOnly(True)
       -        vbox.addWidget(e)
       -
       -        vbox.addWidget(QLabel("Date: %s"%time_str))
       -        vbox.addWidget(QLabel("Status: %d confirmations"%conf))
       -        if is_mine:
       -            if fee is not None: 
       -                vbox.addWidget(QLabel("Amount sent: %s"% self.format_amount(v-fee)))
       -                vbox.addWidget(QLabel("Transaction fee: %s"% self.format_amount(fee)))
       -            else:
       -                vbox.addWidget(QLabel("Amount sent: %s"% self.format_amount(v)))
       -                vbox.addWidget(QLabel("Transaction fee: unknown"))
       -        else:
       -            vbox.addWidget(QLabel("Amount received: %s"% self.format_amount(v)))
       -
       -        vbox.addWidget( self.generate_transaction_information_widget(tx) )
       -
       -        ok_button = QPushButton(_("Close"))
       -        ok_button.setDefault(True)
       -        ok_button.clicked.connect(dialog.accept)
       -        
       -        hbox = QHBoxLayout()
       -        hbox.addStretch(1)
       -        hbox.addWidget(ok_button)
       -        vbox.addLayout(hbox)
       -        dialog.exec_()
       +    def show_transaction(self, tx):
       +        import transaction_dialog
       +        d = transaction_dialog.TxDialog(tx, self)
       +        d.exec_()
        
            def tx_label_clicked(self, item, column):
                if column==2 and item.isSelected():
       t@@ -1678,45 +1635,6 @@ class ElectrumWindow(QMainWindow):
        
        
        
       -    def generate_transaction_information_widget(self, tx):
       -        tabs = QTabWidget(self)
       -
       -        tab1 = QWidget()
       -        grid_ui = QGridLayout(tab1)
       -        grid_ui.setColumnStretch(0,1)
       -        tabs.addTab(tab1, _('Outputs') )
       -
       -        tree_widget = MyTreeWidget(self)
       -        tree_widget.setColumnCount(2)
       -        tree_widget.setHeaderLabels( [_('Address'), _('Amount')] )
       -        tree_widget.setColumnWidth(0, 300)
       -        tree_widget.setColumnWidth(1, 50)
       -
       -        for address, value in tx.outputs:
       -            item = QTreeWidgetItem( [address, "%s" % ( self.format_amount(value))] )
       -            tree_widget.addTopLevelItem(item)
       -
       -        tree_widget.setMaximumHeight(100)
       -
       -        grid_ui.addWidget(tree_widget)
       -
       -        tab2 = QWidget()
       -        grid_ui = QGridLayout(tab2)
       -        grid_ui.setColumnStretch(0,1)
       -        tabs.addTab(tab2, _('Inputs') )
       -        
       -        tree_widget = MyTreeWidget(self)
       -        tree_widget.setColumnCount(2)
       -        tree_widget.setHeaderLabels( [ _('Address'), _('Previous output')] )
       -
       -        for input_line in tx.inputs:
       -            item = QTreeWidgetItem( [ str(input_line["address"]), str(input_line["prevout_hash"])] )
       -            tree_widget.addTopLevelItem(item)
       -
       -        tree_widget.setMaximumHeight(100)
       -
       -        grid_ui.addWidget(tree_widget)
       -        return tabs
        
        
            def tx_dict_from_text(self, txt):
       t@@ -1747,28 +1665,9 @@ class ElectrumWindow(QMainWindow):
        
            @protected
            def sign_raw_transaction(self, tx, input_info, dialog ="", password = ""):
       -        try:
       -            self.wallet.signrawtransaction(tx, input_info, [], password)
       -            
       -            fileName = self.getSaveFileName(_("Select where to save your signed transaction"), 'signed_%s.txn' % (tx.hash()[0:8]), "*.txn")
       -            if fileName:
       -                with open(fileName, "w+") as f:
       -                    f.write(json.dumps(tx.as_dict(),indent=4) + '\n')
       -                self.show_message(_("Transaction saved successfully"))
       -                if dialog:
       -                    dialog.done(0)
       -        except BaseException, e:
       -            self.show_message(str(e))
       +        self.wallet.signrawtransaction(tx, input_info, [], password)
            
        
       -    def send_raw_transaction(self, raw_tx, dialog = ""):
       -        result, result_message = self.wallet.sendtx( raw_tx )
       -        if result:
       -            self.show_message("Transaction successfully sent: %s" % (result_message))
       -            if dialog:
       -                dialog.done(0)
       -        else:
       -            self.show_message("There was a problem sending your transaction:\n %s" % (result_message))
        
            def do_process_from_text(self):
                text = text_dialog(self, _('Input raw transaction'), _("Transaction:"), _("Load transaction"))
       t@@ -1801,8 +1700,9 @@ class ElectrumWindow(QMainWindow):
                    self.show_message(str(e))
                    return
        
       -        tx_dict = tx.as_dict()
       -        self.create_process_transaction_window(tx_dict)
       +        self.show_transaction(tx)
       +        #tx_dict = tx.as_dict()
       +        #self.create_process_transaction_window(tx_dict)
        
            def do_process_from_csv_file(self):
                fileName = self.getOpenFileName(_("Select your transaction CSV"), "*.csv")
       t@@ -1824,41 +1724,10 @@ class ElectrumWindow(QMainWindow):
                csvReader = csv.reader(f)
                self.do_process_from_csvReader(csvReader)
        
       +
            def create_process_transaction_window(self, tx_dict):
                tx = Transaction(tx_dict["hex"])
       -            
       -        dialog = QDialog(self)
       -        dialog.setMinimumWidth(500)
       -        dialog.setWindowTitle(_('Process raw transaction'))
       -        dialog.setModal(1)
       -
       -        l = QGridLayout()
       -        dialog.setLayout(l)
       -
       -        l.addWidget(QLabel(_("Transaction status:")), 3,0)
       -        l.addWidget(QLabel(_("Actions")), 4,0)
       -
       -        if tx_dict["complete"] == False:
       -            l.addWidget(QLabel(_("Unsigned")), 3,1)
       -            if self.wallet.seed :
       -                b = QPushButton("Sign transaction")
       -                input_info = json.loads(tx_dict["input_info"])
       -                b.clicked.connect(lambda: self.sign_raw_transaction(tx, input_info, dialog))
       -                l.addWidget(b, 4, 1)
       -            else:
       -                l.addWidget(QLabel(_("Wallet is de-seeded, can't sign.")), 4,1)
       -        else:
       -            l.addWidget(QLabel(_("Signed")), 3,1)
       -            b = QPushButton("Broadcast transaction")
       -            b.clicked.connect(lambda: self.send_raw_transaction(tx, dialog))
       -            l.addWidget(b,4,1)
       -
       -        l.addWidget( self.generate_transaction_information_widget(tx), 0,0,2,3)
       -        cancelButton = QPushButton(_("Cancel"))
       -        cancelButton.clicked.connect(lambda: dialog.done(0))
       -        l.addWidget(cancelButton, 4,2)
       -
       -        dialog.exec_()
       +        self.show_transaction(tx)
        
        
            @protected
   DIR diff --git a/gui/gui_classic/transaction_dialog.py b/gui/gui_classic/transaction_dialog.py
       t@@ -0,0 +1,220 @@
       +#!/usr/bin/env python
       +#
       +# Electrum - lightweight Bitcoin client
       +# Copyright (C) 2012 thomasv@gitorious
       +#
       +# This program is free software: you can redistribute it and/or modify
       +# it under the terms of the GNU General Public License as published by
       +# the Free Software Foundation, either version 3 of the License, or
       +# (at your option) any later version.
       +#
       +# This program is distributed in the hope that it will be useful,
       +# but WITHOUT ANY WARRANTY; without even the implied warranty of
       +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
       +# GNU General Public License for more details.
       +#
       +# You should have received a copy of the GNU General Public License
       +# along with this program. If not, see <http://www.gnu.org/licenses/>.
       +
       +import sys, time, datetime, re, threading
       +from electrum.i18n import _, set_language
       +from electrum.util import print_error, print_msg
       +import os.path, json, ast, traceback
       +import shutil
       +import StringIO
       +
       +
       +try:
       +    import PyQt4
       +except:
       +    sys.exit("Error: Could not import PyQt4 on Linux systems, you may try 'sudo apt-get install python-qt4'")
       +
       +from PyQt4.QtGui import *
       +from PyQt4.QtCore import *
       +import PyQt4.QtCore as QtCore
       +
       +from electrum import transaction
       +
       +
       +class TxDialog(QDialog):
       +
       +    def __init__(self, tx, parent):
       +        self.tx = tx
       +        tx_dict = tx.as_dict()
       +        self.parent = parent
       +        self.wallet = parent.wallet
       +            
       +        QDialog.__init__(self)
       +        self.setMinimumWidth(600)
       +        self.setWindowTitle(_('Transaction'))
       +        self.setModal(1)
       +
       +        vbox = QVBoxLayout()
       +        self.setLayout(vbox)
       +
       +        vbox.addWidget(QLabel("Transaction ID:"))
       +        self.tx_hash_e  = QLineEdit()
       +        self.tx_hash_e.setReadOnly(True)
       +        vbox.addWidget(self.tx_hash_e)
       +        self.status_label = QLabel()
       +        vbox.addWidget(self.status_label)
       +
       +        self.date_label = QLabel()
       +        vbox.addWidget(self.date_label)
       +        self.amount_label = QLabel()
       +        vbox.addWidget(self.amount_label)
       +        self.fee_label = QLabel()
       +        vbox.addWidget(self.fee_label)
       +
       +        self.io = self.io_widget(tx)
       +        vbox.addWidget( self.io )
       +
       +        buttons = QHBoxLayout()
       +        vbox.addLayout( buttons )
       +
       +        buttons.addStretch(1)
       +
       +        self.sign_button = b = QPushButton(_("Sign"))
       +        b.clicked.connect(self.sign)
       +        buttons.addWidget(b)
       +
       +        self.broadcast_button = b = QPushButton(_("Broadcast"))
       +        b.clicked.connect(self.broadcast)
       +        b.hide()
       +        buttons.addWidget(b)
       +
       +        self.save_button = b = QPushButton(_("Save"))
       +        b.clicked.connect(self.save)
       +        buttons.addWidget(b)
       +
       +        cancelButton = QPushButton(_("Close"))
       +        cancelButton.clicked.connect(lambda: self.done(0))
       +        buttons.addWidget(cancelButton)
       +
       +        self.update()
       +
       +
       +
       +
       +    def sign(self):
       +        tx_dict = self.tx.as_dict()
       +        input_info = json.loads(tx_dict["input_info"])
       +        self.parent.sign_raw_transaction(self.tx, input_info, self)
       +        self.update()
       +
       +
       +    def save(self):
       +        fileName = self.parent.getSaveFileName(_("Select where to save your signed transaction"), 'signed_%s.txn' % (self.tx.hash()[0:8]), "*.txn")
       +        if fileName:
       +            with open(fileName, "w+") as f:
       +                f.write(json.dumps(self.tx.as_dict(),indent=4) + '\n')
       +            self.show_message(_("Transaction saved successfully"))
       +
       +
       +    def update(self):
       +        tx_hash = self.tx.hash()
       +
       +        is_relevant, is_mine, v, fee = self.wallet.get_tx_value(self.tx)
       +
       +        if self.tx.is_complete:
       +            status = "Status: Signed"
       +            self.sign_button.hide()
       +
       +            if tx_hash in self.wallet.transactions.keys():
       +                conf, timestamp = self.wallet.verifier.get_confirmations(tx_hash)
       +                if timestamp:
       +                    time_str = datetime.datetime.fromtimestamp(timestamp).isoformat(' ')[:-3]
       +                else:
       +                    time_str = 'pending'
       +                status = "Status: %d confirmations"%conf
       +                self.broadcast_button.hide()
       +            else:
       +                time_str = None
       +                conf = 0
       +                self.broadcast_button.show()
       +        else:
       +            status = "Status: Unsigned"
       +            time_str = None
       +            self.sign_button.show()
       +            self.broadcast_button.hide()
       +
       +        self.tx_hash_e.setText(tx_hash)
       +        self.status_label.setText(status)
       +
       +        if time_str is not None:
       +            self.date_label.setText("Date: %s"%time_str)
       +            self.date_label.show()
       +        else:
       +            self.date_label.hide()
       +
       +        if is_relevant:    
       +            if is_mine:
       +                if fee is not None: 
       +                    self.amount_label.setText("Amount sent: %s"% self.parent.format_amount(v-fee))
       +                    self.fee_label.setText("Transaction fee: %s"% self.parent.format_amount(fee))
       +                else:
       +                    self.amount_label.setText("Amount sent: %s"% self.parent.format_amount(v))
       +                    self.fee_label.setText("Transaction fee: unknown")
       +            else:
       +                self.amount_label.setText("Amount received: %s"% self.parent.format_amount(v))
       +        else:
       +            self.amount_label.setText("Transaction unrelated to your wallet")
       +
       +
       +
       +    def io_widget(self, tx):
       +        tabs = QTabWidget(self)
       +
       +        tab1 = QWidget()
       +        grid_ui = QGridLayout(tab1)
       +        grid_ui.setColumnStretch(0,1)
       +        tabs.addTab(tab1, _('Outputs') )
       +
       +        tree_widget = QTreeWidget(self)
       +        tree_widget.setColumnCount(2)
       +        tree_widget.setHeaderLabels( [_('Address'), _('Amount')] )
       +        tree_widget.setColumnWidth(0, 300)
       +        tree_widget.setColumnWidth(1, 50)
       +
       +        for address, value in tx.outputs:
       +            item = QTreeWidgetItem( [address, "%s" % ( self.parent.format_amount(value))] )
       +            tree_widget.addTopLevelItem(item)
       +
       +        tree_widget.setMaximumHeight(100)
       +
       +        grid_ui.addWidget(tree_widget)
       +
       +        tab2 = QWidget()
       +        grid_ui = QGridLayout(tab2)
       +        grid_ui.setColumnStretch(0,1)
       +        tabs.addTab(tab2, _('Inputs') )
       +        
       +        tree_widget = QTreeWidget(self)
       +        tree_widget.setColumnCount(2)
       +        tree_widget.setHeaderLabels( [ _('Address'), _('Previous output')] )
       +
       +        for input_line in tx.inputs:
       +            item = QTreeWidgetItem( [ str(input_line["address"]), str(input_line.get("prevout_hash"))] )
       +            tree_widget.addTopLevelItem(item)
       +
       +        tree_widget.setMaximumHeight(100)
       +
       +        grid_ui.addWidget(tree_widget)
       +        return tabs
       +
       +
       +    def broadcast(self):
       +        result, result_message = self.wallet.sendtx( self.tx )
       +        if result:
       +            self.show_message("Transaction successfully sent: %s" % (result_message))
       +            if dialog:
       +                dialog.done(0)
       +        else:
       +            self.show_message("There was a problem sending your transaction:\n %s" % (result_message))
       +
       +    def show_message(self, msg):
       +        QMessageBox.information(self, _('Message'), msg, _('OK'))
       +
       +
       +
       +
   DIR diff --git a/lib/__init__.py b/lib/__init__.py
       t@@ -8,6 +8,7 @@ from interface import Interface
        from simple_config import SimpleConfig
        import bitcoin
        import account
       +import transaction
        from transaction import Transaction
        from plugins import BasePlugin
        from mnemonic import mn_encode as mnemonic_encode
   DIR diff --git a/lib/commands.py b/lib/commands.py
       t@@ -247,7 +247,7 @@ class Commands:
        
            def mktx(self, to_address, amount, fee = None, change_addr = None, domain = None):
                tx = self._mktx([(to_address, amount)], fee, change_addr, domain)
       -        return tx.as_dict()
       +        return tx
        
            def mksendmanytx(self, outputs, fee = None, change_addr = None, domain = None):
                tx = self._mktx(outputs, fee, change_addr, domain)
   DIR diff --git a/lib/interface.py b/lib/interface.py
       t@@ -449,7 +449,7 @@ class Interface(threading.Thread):
        
            def synchronous_get(self, requests, timeout=100000000):
                # todo: use generators, unanswered_requests should be a list of arrays...
       -        q = Queue.Queue()
       +        queue = Queue.Queue()
                ids = self.send(requests, lambda i,r: queue.put(r))
                id2 = ids[:]
                res = {}
   DIR diff --git a/lib/network.py b/lib/network.py
       t@@ -174,6 +174,12 @@ class Network(threading.Thread):
            def is_running(self):
                with self.lock: return self.running
        
       +    
       +    def retrieve_transaction(self, tx_hash, tx_height=0):
       +        import transaction
       +        r = self.interface.synchronous_get([ ('blockchain.transaction.get',[tx_hash, tx_height]) ])[0]
       +        return transaction.Transaction(r)
       +
        
            def parse_servers(self, result):
                """ parse servers list into dict format"""
   DIR diff --git a/lib/transaction.py b/lib/transaction.py
       t@@ -379,6 +379,13 @@ class Transaction:
                self.input_info = None
                self.is_complete = True
                
       +
       +    def __repr__(self):
       +        return "Transaction('"+self.raw+"')"
       +
       +    def __str__(self):
       +        return self.raw
       +
            @classmethod
            def from_io(klass, inputs, outputs):
                raw = klass.serialize(inputs, outputs, for_sig = -1) # for_sig=-1 means do not sign
       t@@ -390,12 +397,13 @@ class Transaction:
                for i in self.inputs:
                    e = { 'txid':i['tx_hash'], 'vout':i['index'], 'scriptPubKey':i.get('raw_output_script') }
                    extras.append(e)
       +            # fixme: simplify this
       +            i['prevout_hash'] = i['tx_hash']
       +            i['prevout_n'] = i['index']
       +
                self.input_info = extras
                return self
        
       -    def __str__(self):
       -        return self.raw
       -
            @classmethod
            def multisig_script(klass, public_keys, num=None):
                n = len(public_keys)
   DIR diff --git a/lib/util.py b/lib/util.py
       t@@ -24,7 +24,10 @@ def print_msg(*args):
        
        def print_json(obj):
            import json
       -    s = json.dumps(obj,sort_keys = True, indent = 4)
       +    try:
       +        s = json.dumps(obj,sort_keys = True, indent = 4)
       +    except TypeError:
       +        s = repr(obj)
            sys.stdout.write(s + "\n")
            sys.stdout.flush()
        
   DIR diff --git a/setup.py b/setup.py
       t@@ -90,6 +90,7 @@ setup(name = "Electrum",
                          'electrum_gui.gui_classic.network_dialog',
                          'electrum_gui.gui_classic.password_dialog',
                          'electrum_gui.gui_classic.seed_dialog',
       +                  'electrum_gui.gui_classic.transaction dialog',
                          'electrum_gui.gui_classic.version_getter',
                          'electrum_gui.gui_classic.amountedit',
                          'electrum_plugins.pointofsale',