Gav Wood
10 years ago
14 changed files with 810 additions and 639 deletions
@ -0,0 +1,325 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum 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. |
|||
|
|||
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file Transact.cpp
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
#include "Transact.h" |
|||
|
|||
#include <fstream> |
|||
#include <QFileDialog> |
|||
#include <QMessageBox> |
|||
#include <liblll/Compiler.h> |
|||
#include <liblll/CodeFragment.h> |
|||
#include <libsolidity/CompilerStack.h> |
|||
#include <libsolidity/Scanner.h> |
|||
#include <libsolidity/AST.h> |
|||
#include <libsolidity/SourceReferenceFormatter.h> |
|||
#include <libethereum/Client.h> |
|||
#include <libethereum/Utility.h> |
|||
#ifndef _MSC_VER |
|||
#include <libserpent/funcs.h> |
|||
#include <libserpent/util.h> |
|||
#endif |
|||
#include "Debugger.h" |
|||
#include "ui_Transact.h" |
|||
using namespace std; |
|||
using namespace dev; |
|||
using namespace dev::eth; |
|||
|
|||
Transact::Transact(Context* _c, QWidget* _parent): |
|||
QDialog(_parent), |
|||
ui(new Ui::Transact), |
|||
m_context(_c) |
|||
{ |
|||
ui->setupUi(this); |
|||
|
|||
initUnits(ui->gasPriceUnits); |
|||
initUnits(ui->valueUnits); |
|||
ui->valueUnits->setCurrentIndex(6); |
|||
ui->gasPriceUnits->setCurrentIndex(4); |
|||
ui->gasPrice->setValue(10); |
|||
on_destination_currentTextChanged(); |
|||
} |
|||
|
|||
Transact::~Transact() |
|||
{ |
|||
delete ui; |
|||
} |
|||
|
|||
void Transact::setEnvironment(QList<dev::KeyPair> _myKeys, dev::eth::Client* _eth, NatSpecFace* _natSpecDB) |
|||
{ |
|||
m_myKeys = _myKeys; |
|||
m_ethereum = _eth; |
|||
m_natSpecDB = _natSpecDB; |
|||
} |
|||
|
|||
bool Transact::isCreation() const |
|||
{ |
|||
return ui->destination->currentText().isEmpty() || ui->destination->currentText() == "(Create Contract)"; |
|||
} |
|||
|
|||
u256 Transact::fee() const |
|||
{ |
|||
return ui->gas->value() * gasPrice(); |
|||
} |
|||
|
|||
u256 Transact::value() const |
|||
{ |
|||
if (ui->valueUnits->currentIndex() == -1) |
|||
return 0; |
|||
return ui->value->value() * units()[units().size() - 1 - ui->valueUnits->currentIndex()].first; |
|||
} |
|||
|
|||
u256 Transact::gasPrice() const |
|||
{ |
|||
if (ui->gasPriceUnits->currentIndex() == -1) |
|||
return 0; |
|||
return ui->gasPrice->value() * units()[units().size() - 1 - ui->gasPriceUnits->currentIndex()].first; |
|||
} |
|||
|
|||
u256 Transact::total() const |
|||
{ |
|||
return value() + fee(); |
|||
} |
|||
|
|||
void Transact::updateDestination() |
|||
{ |
|||
cwatch << "updateDestination()"; |
|||
QString s; |
|||
for (auto i: ethereum()->addresses()) |
|||
if ((s = m_context->pretty(i)).size()) |
|||
// A namereg address
|
|||
if (ui->destination->findText(s, Qt::MatchExactly | Qt::MatchCaseSensitive) == -1) |
|||
ui->destination->addItem(s); |
|||
for (int i = 0; i < ui->destination->count(); ++i) |
|||
if (ui->destination->itemText(i) != "(Create Contract)" && !m_context->fromString(ui->destination->itemText(i))) |
|||
ui->destination->removeItem(i--); |
|||
} |
|||
|
|||
void Transact::updateFee() |
|||
{ |
|||
ui->fee->setText(QString("(gas sub-total: %1)").arg(formatBalance(fee()).c_str())); |
|||
auto totalReq = total(); |
|||
ui->total->setText(QString("Total: %1").arg(formatBalance(totalReq).c_str())); |
|||
|
|||
bool ok = false; |
|||
for (auto i: m_myKeys) |
|||
if (ethereum()->balanceAt(i.address()) >= totalReq) |
|||
{ |
|||
ok = true; |
|||
break; |
|||
} |
|||
ui->send->setEnabled(ok); |
|||
QPalette p = ui->total->palette(); |
|||
p.setColor(QPalette::WindowText, QColor(ok ? 0x00 : 0x80, 0x00, 0x00)); |
|||
ui->total->setPalette(p); |
|||
} |
|||
|
|||
string Transact::getFunctionHashes(dev::solidity::CompilerStack const& _compiler, string const& _contractName) |
|||
{ |
|||
string ret = ""; |
|||
auto const& contract = _compiler.getContractDefinition(_contractName); |
|||
auto interfaceFunctions = contract.getInterfaceFunctions(); |
|||
|
|||
for (auto const& it: interfaceFunctions) |
|||
{ |
|||
ret += it.first.abridged(); |
|||
ret += " :"; |
|||
ret += it.second->getDeclaration().getName() + "\n"; |
|||
} |
|||
return ret; |
|||
} |
|||
|
|||
void Transact::on_destination_currentTextChanged() |
|||
{ |
|||
if (ui->destination->currentText().size() && ui->destination->currentText() != "(Create Contract)") |
|||
if (Address a = m_context->fromString(ui->destination->currentText())) |
|||
ui->calculatedName->setText(m_context->render(a)); |
|||
else |
|||
ui->calculatedName->setText("Unknown Address"); |
|||
else |
|||
ui->calculatedName->setText("Create Contract"); |
|||
rejigData(); |
|||
// updateFee();
|
|||
} |
|||
|
|||
void Transact::rejigData() |
|||
{ |
|||
if (isCreation()) |
|||
{ |
|||
string src = ui->data->toPlainText().toStdString(); |
|||
vector<string> errors; |
|||
QString lll; |
|||
QString solidity; |
|||
if (src.find_first_not_of("1234567890abcdefABCDEF") == string::npos && src.size() % 2 == 0) |
|||
{ |
|||
m_data = fromHex(src); |
|||
} |
|||
else if (sourceIsSolidity(src)) |
|||
{ |
|||
dev::solidity::CompilerStack compiler; |
|||
try |
|||
{ |
|||
// compiler.addSources(dev::solidity::StandardSources);
|
|||
m_data = compiler.compile(src, ui->optimize->isChecked()); |
|||
solidity = "<h4>Solidity</h4>"; |
|||
solidity += "<pre>var " + QString::fromStdString(compiler.defaultContractName()) + " = web3.eth.contractFromAbi(" + QString::fromStdString(compiler.getInterface()).replace(QRegExp("\\s"), "").toHtmlEscaped() + ");</pre>"; |
|||
solidity += "<pre>" + QString::fromStdString(compiler.getSolidityInterface()).toHtmlEscaped() + "</pre>"; |
|||
solidity += "<pre>" + QString::fromStdString(getFunctionHashes(compiler)).toHtmlEscaped() + "</pre>"; |
|||
} |
|||
catch (dev::Exception const& exception) |
|||
{ |
|||
ostringstream error; |
|||
solidity::SourceReferenceFormatter::printExceptionInformation(error, exception, "Error", compiler); |
|||
solidity = "<h4>Solidity</h4><pre>" + QString::fromStdString(error.str()).toHtmlEscaped() + "</pre>"; |
|||
} |
|||
catch (...) |
|||
{ |
|||
solidity = "<h4>Solidity</h4><pre>Uncaught exception.</pre>"; |
|||
} |
|||
} |
|||
#ifndef _MSC_VER |
|||
else if (sourceIsSerpent(src)) |
|||
{ |
|||
try |
|||
{ |
|||
m_data = dev::asBytes(::compile(src)); |
|||
for (auto& i: errors) |
|||
i = "(LLL " + i + ")"; |
|||
} |
|||
catch (string err) |
|||
{ |
|||
errors.push_back("Serpent " + err); |
|||
} |
|||
} |
|||
#endif |
|||
else |
|||
{ |
|||
m_data = compileLLL(src, ui->optimize->isChecked(), &errors); |
|||
if (errors.empty()) |
|||
{ |
|||
auto asmcode = compileLLLToAsm(src, false); |
|||
lll = "<h4>Pre</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>"; |
|||
if (ui->optimize->isChecked()) |
|||
{ |
|||
asmcode = compileLLLToAsm(src, true); |
|||
lll = "<h4>Opt</h4><pre>" + QString::fromStdString(asmcode).toHtmlEscaped() + "</pre>" + lll; |
|||
} |
|||
} |
|||
} |
|||
QString errs; |
|||
if (errors.size()) |
|||
{ |
|||
errs = "<h4>Errors</h4>"; |
|||
for (auto const& i: errors) |
|||
errs.append("<div style=\"border-left: 6px solid #c00; margin-top: 2px\">" + QString::fromStdString(i).toHtmlEscaped() + "</div>"); |
|||
} |
|||
ui->code->setHtml(errs + lll + solidity + "<h4>Code</h4>" + QString::fromStdString(disassemble(m_data)).toHtmlEscaped() + "<h4>Hex</h4>" Div(Mono) + QString::fromStdString(toHex(m_data)) + "</div>"); |
|||
ui->gas->setMinimum((qint64)Interface::txGas(m_data, 0)); |
|||
if (!ui->gas->isEnabled()) |
|||
ui->gas->setValue(m_backupGas); |
|||
ui->gas->setEnabled(true); |
|||
} |
|||
else |
|||
{ |
|||
m_data = parseData(ui->data->toPlainText().toStdString()); |
|||
ui->code->setHtml(QString::fromStdString(dev::memDump(m_data, 8, true))); |
|||
if (ethereum()->codeAt(m_context->fromString(ui->destination->currentText()), 0).size()) |
|||
{ |
|||
ui->gas->setMinimum((qint64)Interface::txGas(m_data, 1)); |
|||
if (!ui->gas->isEnabled()) |
|||
ui->gas->setValue(m_backupGas); |
|||
ui->gas->setEnabled(true); |
|||
} |
|||
else |
|||
{ |
|||
if (ui->gas->isEnabled()) |
|||
m_backupGas = ui->gas->value(); |
|||
ui->gas->setValue((qint64)Interface::txGas(m_data)); |
|||
ui->gas->setEnabled(false); |
|||
} |
|||
} |
|||
updateFee(); |
|||
} |
|||
|
|||
void Transact::on_send_clicked() |
|||
{ |
|||
u256 totalReq = value() + fee(); |
|||
for (auto const& i: m_myKeys) |
|||
if (ethereum()->balanceAt(i.address(), 0) >= totalReq) |
|||
{ |
|||
Secret s = i.secret(); |
|||
if (isCreation()) |
|||
{ |
|||
// If execution is a contract creation, add Natspec to
|
|||
// a local Natspec LEVELDB
|
|||
ethereum()->transact(s, value(), m_data, ui->gas->value(), gasPrice()); |
|||
string src = ui->data->toPlainText().toStdString(); |
|||
if (sourceIsSolidity(src)) |
|||
try |
|||
{ |
|||
dev::solidity::CompilerStack compiler; |
|||
m_data = compiler.compile(src, ui->optimize->isChecked()); |
|||
for (string const& s: compiler.getContractNames()) |
|||
{ |
|||
h256 contractHash = compiler.getContractCodeHash(s); |
|||
m_natSpecDB->add(contractHash, compiler.getMetadata(s, dev::solidity::DocumentationType::NatspecUser)); |
|||
} |
|||
} |
|||
catch (...) |
|||
{ |
|||
} |
|||
close(); |
|||
return; |
|||
} |
|||
else |
|||
ethereum()->transact(s, value(), m_context->fromString(ui->destination->currentText()), m_data, ui->gas->value(), gasPrice()); |
|||
return; |
|||
} |
|||
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount."); |
|||
} |
|||
|
|||
void Transact::on_debug_clicked() |
|||
{ |
|||
try |
|||
{ |
|||
u256 totalReq = value() + fee(); |
|||
for (auto i: m_myKeys) |
|||
if (ethereum()->balanceAt(i.address()) >= totalReq) |
|||
{ |
|||
State st(ethereum()->postState()); |
|||
Secret s = i.secret(); |
|||
Transaction t = isCreation() ? |
|||
Transaction(value(), gasPrice(), ui->gas->value(), m_data, st.transactionsFrom(dev::toAddress(s)), s) : |
|||
Transaction(value(), gasPrice(), ui->gas->value(), m_context->fromString(ui->destination->currentText()), m_data, st.transactionsFrom(dev::toAddress(s)), s); |
|||
Debugger dw(m_context, this); |
|||
Executive e(st, ethereum()->blockChain(), 0); |
|||
dw.populate(e, t); |
|||
dw.exec(); |
|||
close(); |
|||
return; |
|||
} |
|||
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction: no single account contains at least the required amount."); |
|||
} |
|||
catch (dev::Exception const& _e) |
|||
{ |
|||
QMessageBox::critical(this, "Transaction Failed", "Couldn't make transaction. Low-level error: " + QString::fromStdString(diagnostic_information(_e))); |
|||
// this output is aimed at developers, reconsider using _e.what for more user friendly output.
|
|||
} |
|||
} |
@ -0,0 +1,82 @@ |
|||
/*
|
|||
This file is part of cpp-ethereum. |
|||
|
|||
cpp-ethereum 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. |
|||
|
|||
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
/** @file Transact.h
|
|||
* @author Gav Wood <i@gavwood.com> |
|||
* @date 2015 |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <libdevcore/RLP.h> |
|||
#include <libethcore/CommonEth.h> |
|||
#include <libethereum/Transaction.h> |
|||
#include <QDialog> |
|||
#include <QMap> |
|||
#include <QList> |
|||
#include "Context.h" |
|||
|
|||
namespace Ui { class Transact; } |
|||
namespace dev { namespace eth { class Client; } } |
|||
namespace dev { namespace solidity { class CompilerStack; } } |
|||
|
|||
class Transact: public QDialog |
|||
{ |
|||
Q_OBJECT |
|||
|
|||
public: |
|||
explicit Transact(Context* _context, QWidget* _parent = 0); |
|||
~Transact(); |
|||
|
|||
void setEnvironment(QList<dev::KeyPair> _myKeys, dev::eth::Client* _eth, NatSpecFace* _natSpecDB); |
|||
|
|||
private slots: |
|||
void on_destination_currentTextChanged(); |
|||
void on_value_valueChanged() { updateFee(); } |
|||
void on_gas_valueChanged() { updateFee(); } |
|||
void on_valueUnits_currentIndexChanged() { updateFee(); } |
|||
void on_gasPriceUnits_currentIndexChanged() { updateFee(); } |
|||
void on_gasPrice_valueChanged() { updateFee(); } |
|||
void on_data_textChanged() { rejigData(); } |
|||
void on_optimize_clicked() { rejigData(); } |
|||
void on_send_clicked(); |
|||
void on_debug_clicked(); |
|||
void on_cancel_clicked() { close(); } |
|||
|
|||
private: |
|||
dev::eth::Client* ethereum() { return m_ethereum; } |
|||
void rejigData(); |
|||
|
|||
void updateDestination(); |
|||
void updateFee(); |
|||
bool isCreation() const; |
|||
dev::u256 fee() const; |
|||
dev::u256 total() const; |
|||
dev::u256 value() const; |
|||
dev::u256 gasPrice() const; |
|||
|
|||
std::string getFunctionHashes(dev::solidity::CompilerStack const& _compiler, std::string const& _contractName = std::string()); |
|||
|
|||
Ui::Transact* ui; |
|||
|
|||
unsigned m_backupGas; |
|||
dev::bytes m_data; |
|||
|
|||
QList<dev::KeyPair> m_myKeys; |
|||
dev::eth::Client* m_ethereum; |
|||
Context* m_context; |
|||
NatSpecFace* m_natSpecDB; |
|||
}; |
@ -0,0 +1,244 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<ui version="4.0"> |
|||
<class>Transact</class> |
|||
<widget class="QDialog" name="Transact"> |
|||
<property name="geometry"> |
|||
<rect> |
|||
<x>0</x> |
|||
<y>0</y> |
|||
<width>543</width> |
|||
<height>695</height> |
|||
</rect> |
|||
</property> |
|||
<property name="windowTitle"> |
|||
<string>Dialog</string> |
|||
</property> |
|||
<layout class="QGridLayout" name="gridLayout"> |
|||
<item row="2" column="1" colspan="2"> |
|||
<widget class="QSpinBox" name="value"> |
|||
<property name="suffix"> |
|||
<string/> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>430000000</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>0</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="2" column="0"> |
|||
<widget class="QLabel" name="label5_2"> |
|||
<property name="text"> |
|||
<string>&Amount</string> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>value</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="1" column="1" colspan="3"> |
|||
<widget class="QLineEdit" name="calculatedName"> |
|||
<property name="enabled"> |
|||
<bool>false</bool> |
|||
</property> |
|||
<property name="readOnly"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<property name="placeholderText"> |
|||
<string/> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="5" column="0" colspan="4"> |
|||
<widget class="QSplitter" name="splitter_5"> |
|||
<property name="orientation"> |
|||
<enum>Qt::Vertical</enum> |
|||
</property> |
|||
<widget class="QPlainTextEdit" name="data"> |
|||
<property name="frameShape"> |
|||
<enum>QFrame::NoFrame</enum> |
|||
</property> |
|||
<property name="lineWidth"> |
|||
<number>0</number> |
|||
</property> |
|||
</widget> |
|||
<widget class="QTextEdit" name="code"> |
|||
<property name="focusPolicy"> |
|||
<enum>Qt::ClickFocus</enum> |
|||
</property> |
|||
<property name="frameShape"> |
|||
<enum>QFrame::NoFrame</enum> |
|||
</property> |
|||
<property name="lineWidth"> |
|||
<number>0</number> |
|||
</property> |
|||
<property name="readOnly"> |
|||
<bool>true</bool> |
|||
</property> |
|||
</widget> |
|||
</widget> |
|||
</item> |
|||
<item row="3" column="3"> |
|||
<widget class="QComboBox" name="gasPriceUnits"/> |
|||
</item> |
|||
<item row="4" column="1" colspan="2"> |
|||
<widget class="QLabel" name="fee"> |
|||
<property name="sizePolicy"> |
|||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> |
|||
<horstretch>0</horstretch> |
|||
<verstretch>0</verstretch> |
|||
</sizepolicy> |
|||
</property> |
|||
<property name="text"> |
|||
<string/> |
|||
</property> |
|||
<property name="alignment"> |
|||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="0" column="0"> |
|||
<widget class="QLabel" name="label5"> |
|||
<property name="sizePolicy"> |
|||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred"> |
|||
<horstretch>0</horstretch> |
|||
<verstretch>0</verstretch> |
|||
</sizepolicy> |
|||
</property> |
|||
<property name="text"> |
|||
<string>&To</string> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>destination</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="2" column="3"> |
|||
<widget class="QComboBox" name="valueUnits"/> |
|||
</item> |
|||
<item row="7" column="2"> |
|||
<widget class="QPushButton" name="debug"> |
|||
<property name="text"> |
|||
<string>&Debug</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="7" column="3"> |
|||
<widget class="QPushButton" name="send"> |
|||
<property name="text"> |
|||
<string>&Execute</string> |
|||
</property> |
|||
<property name="default"> |
|||
<bool>false</bool> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="3" column="0"> |
|||
<widget class="QLabel" name="label_6"> |
|||
<property name="text"> |
|||
<string>&Gas</string> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>gas</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="3" column="1"> |
|||
<widget class="QSpinBox" name="gas"> |
|||
<property name="suffix"> |
|||
<string> gas</string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>430000000</number> |
|||
</property> |
|||
<property name="value"> |
|||
<number>10000</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="3" column="2"> |
|||
<widget class="QSpinBox" name="gasPrice"> |
|||
<property name="prefix"> |
|||
<string>@ </string> |
|||
</property> |
|||
<property name="minimum"> |
|||
<number>1</number> |
|||
</property> |
|||
<property name="maximum"> |
|||
<number>430000000</number> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="4" column="3"> |
|||
<widget class="QCheckBox" name="optimize"> |
|||
<property name="text"> |
|||
<string>&Optimise</string> |
|||
</property> |
|||
<property name="checked"> |
|||
<bool>true</bool> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="4" column="0"> |
|||
<widget class="QLabel" name="label_2"> |
|||
<property name="sizePolicy"> |
|||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum"> |
|||
<horstretch>0</horstretch> |
|||
<verstretch>0</verstretch> |
|||
</sizepolicy> |
|||
</property> |
|||
<property name="text"> |
|||
<string>D&ata</string> |
|||
</property> |
|||
<property name="alignment"> |
|||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> |
|||
</property> |
|||
<property name="buddy"> |
|||
<cstring>data</cstring> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="0" column="1" colspan="3"> |
|||
<widget class="QComboBox" name="destination"> |
|||
<property name="editable"> |
|||
<bool>true</bool> |
|||
</property> |
|||
<item> |
|||
<property name="text"> |
|||
<string>(Create Contract)</string> |
|||
</property> |
|||
</item> |
|||
</widget> |
|||
</item> |
|||
<item row="6" column="0" colspan="4"> |
|||
<widget class="QLabel" name="total"> |
|||
<property name="sizePolicy"> |
|||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> |
|||
<horstretch>0</horstretch> |
|||
<verstretch>0</verstretch> |
|||
</sizepolicy> |
|||
</property> |
|||
<property name="text"> |
|||
<string/> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
<item row="7" column="0"> |
|||
<widget class="QPushButton" name="cancel"> |
|||
<property name="text"> |
|||
<string>&Cancel</string> |
|||
</property> |
|||
<property name="shortcut"> |
|||
<string>Esc</string> |
|||
</property> |
|||
</widget> |
|||
</item> |
|||
</layout> |
|||
</widget> |
|||
<resources/> |
|||
<connections/> |
|||
</ui> |
Loading…
Reference in new issue