diff --git a/ArmoryQt.py b/ArmoryQt.py
index cfcee1ef5..6bc8da002 100644
--- a/ArmoryQt.py
+++ b/ArmoryQt.py
@@ -65,6 +65,10 @@ def __init__(self, parent=None, settingsPath=None):
self.extraHeartbeatFunctions = []
+ self.lblArmoryStatus = QRichLabel('Offline', \
+ doWrap=False)
+ self.statusBar().insertPermanentWidget(0, self.lblArmoryStatus)
+
# Keep a persistent printer object for paper backups
self.printer = QPrinter(QPrinter.HighResolution)
self.printer.setPageSize(QPrinter.Letter)
@@ -746,9 +750,13 @@ def loadBlockchain(self):
self.ledgerSize = len(self.combinedLedger)
print 'Ledger entries:', len(self.combinedLedger), 'Max Block:', self.latestBlockNum
self.statusBar().showMessage('Blockchain loaded, wallets sync\'d!', 10000)
+ self.lblArmoryStatus.setText(\
+ 'Connected (%s blocks) ' % self.latestBlockNum)
+ self.blkReceived = self.settings.getSettingOrSetDefault('LastBlkRecvTime', 0)
else:
self.statusBar().showMessage('! Blockchain loading failed !', 10000)
+
# This will force the table to refresh with new data
self.walletModel.reset()
@@ -1479,6 +1487,7 @@ def Heartbeat(self, nextBeatSec=2):
# Check for new blocks in the blk0001.dat file
if TheBDM.isInitialized():
newBlks = TheBDM.readBlkFileUpdate()
+ self.topTimestamp = TheBDM.getTopBlockHeader().getTimestamp()
if newBlks>0:
self.ledgerModel.reset()
self.latestBlockNum = TheBDM.getTopBlockHeader().getBlockHeight()
@@ -1495,6 +1504,23 @@ def Heartbeat(self, nextBeatSec=2):
self.walletListChanged()
self.NetworkingFactory.purgeMemoryPool()
self.createCombinedLedger()
+ self.blkReceived = RightNow()
+ self.settings.set('LastBlkRecvTime', self.blkReceived)
+ self.lblArmoryStatus.setText(\
+ 'Connected (%s blocks) ' % self.latestBlockNum)
+
+ nowtime = RightNow()
+ blkRecvAgo = nowtime - self.blkReceived
+ blkStampAgo = nowtime - self.topTimestamp
+ #if self.usermode==USERMODE.Standard:
+ #self.lblArmoryStatus.setToolTip( 'Last block was received %s ago' % \
+ #secondsToHumanTime(blkRecvAgo))
+ #else:
+ ##self.lblArmoryStatus.setToolTip( \
+ #'Last block was received %s ago \n(block timestamp is %s ago)' % \
+ #(secondsToHumanTime(blkRecvAgo), secondsToHumanTime(blkStampAgo)))
+ self.lblArmoryStatus.setToolTip('Last block timestamp is %s ago' % \
+ secondsToHumanTime(blkStampAgo))
#for wltID, wlt in self.walletMap.iteritems():
@@ -1503,6 +1529,7 @@ def Heartbeat(self, nextBeatSec=2):
self.walletBalances[idx] = self.walletMap[wltID].getBalance()
self.walletMap[wltID].checkWalletLockTimeout()
+
for func in self.extraHeartbeatFunctions:
func()
diff --git a/Using_Armory.README b/Using_Armory.README
index 91b94e241..b0ba64ef0 100755
--- a/Using_Armory.README
+++ b/Using_Armory.README
@@ -54,6 +54,8 @@ that all features with an X in either column are accessible in SWIG.
All OS: https://launchpad.net/qt4reactor
Windows Only: qt4reactor relies on pywin32 (for win32event module)
http://sourceforge.net/projects/pywin32/files/pywin32/Build216/
+
+ - pywin32
- py2exe
(OPTIONAL - if you want to make a standalone executable in Windows)
Windows: http://www.py2exe.org/
diff --git a/WindowsBuild.txt b/WindowsBuild.txt
new file mode 100644
index 000000000..12c9207fc
--- /dev/null
+++ b/WindowsBuild.txt
@@ -0,0 +1,52 @@
+
+Make sure you have MSVS 2005 or 2008. [b]And if you are on a 64-bit system, make sure you select to install the x64 compilers under C++ options
+
+(The MSVS 2010 project is desperately out of date. Don't even bother trying it unless you're ready for a battle! However, I will be updating at some point in the future, I just want to make available the 2005 project first.
+
+
+Install Git and TortoiseGit
+ http://code.google.com/p/msysgit/downloads/detail?name=Git-1.7.8-preview20111206.exe
+ http://code.google.com/p/tortoisegit/downloads/list
+
+
+Clone the repo:
+ Right click on the directory where you want the code to go: select "Git clone..."
+ URL: git://github.com/etotheipi/BitcoinArmory.git
+ Click OK
+
+
+While that's going, start downloading python-related stuff (there's a lot!)
+
+-- Download and install Python 2.6 or 2.7:
+ http://www.python.org/ftp/python/2.7.2/
+-- Download and install Python-Twisted:
+ http://twistedmatrix.com/trac/wiki/Downloads
+-- Download and install zope.interface (for python-twisted):
+ http://pypi.python.org/pypi/zope.interface/3.8.0#downloads
+ Unless you know what to with an .egg file, you're going to have
+ to download the tar.gz, unpack it, and then execute setup.py via:
+ python setup.py install
+
+-- Download and UNPACK SWIG.
+ http://www.swig.org/download.html
+
+ Move the inner-most swig-2.0.4 directory to BtcoinArmory/cppForSwig
+ (you should now see 3 subdirectories in cppForSwig dir:
+ cryptopp, reorgTest and swig-2.0.4):
+
+-- Download and full-install PyQt4:
+ http://www.riverbankcomputing.co.uk/software/pyqt/download
+
+-- (OPTIONAL) py2exe AND pywin32 AND MSVCP90.dll
+ http://sourceforge.net/projects/py2exe/files/py2exe/0.6.9/
+ http://sourceforge.net/projects/pywin32/files/pywin32/Build216/
+
+ MSVS is setup to create a standalone .exe of Armory if it finds
+ py2exe (otherwise it bails at the last build-step, but you can
+ still manually run ArmoryQt.py as long as the SWIG dir is in the
+ right place, and all packages are installed). pywin32 is needed
+ to
+
+
+
+During the last compilation step, you might observe an error about not finding 'python'. For whatever reason, python doesn't add itself to your PATH environment variable. You'll have to add ";C:\Python27\" or ";C:\Python26" to your path depending on which version you're using. Do this through control panel, search for "environment" and then edit the path and append the appropriate string. Reboot
diff --git a/armoryengine.py b/armoryengine.py
index f1bf2ef33..592f0af94 100644
--- a/armoryengine.py
+++ b/armoryengine.py
@@ -612,6 +612,29 @@ def unixTimeToFormatStr(unixTime, formatStr='%Y-%b-%d %I:%M%p'):
dtstr = dtobj.strftime(formatStr)
return dtstr[:-2] + dtstr[-2:].lower()
+def secondsToHumanTime(nSec):
+ strPieces = []
+ floatSec = float(nSec)
+ if floatSec < 0.9*MINUTE:
+ strPieces = [floatSec, 'second']
+ elif floatSec < 0.9*HOUR:
+ strPieces = [floatSec/MINUTE, 'minute']
+ elif floatSec < 0.9*DAY:
+ strPieces = [floatSec/HOUR, 'hour']
+ elif floatSec < 0.9*WEEK:
+ strPieces = [floatSec/DAY, 'day']
+ elif floatSec < 0.9*MONTH:
+ strPieces = [floatSec/WEEK, 'week']
+ else:
+ strPieces = [floatSec/MONTH, 'month']
+
+ if strPieces[0]<1.25:
+ return '1 '+strPieces[1]
+ elif strPieces[0]<=1.75:
+ return '1.5 '+strPieces[1]+'s'
+ else:
+ return '%d %ss' % (int(strPieces[0]+0.5), strPieces[1])
+
##### HEXSTR/VARINT #####
def packVarInt(n):
diff --git a/img/armory_logo_green_h72.png b/img/armory_logo_green_h72.png
new file mode 100644
index 000000000..1dbf62407
Binary files /dev/null and b/img/armory_logo_green_h72.png differ
diff --git a/qtdialogs.py b/qtdialogs.py
index ba92786db..3c4598608 100755
--- a/qtdialogs.py
+++ b/qtdialogs.py
@@ -4708,6 +4708,15 @@ def signTx(self):
def broadTx(self):
+ if not self.main.internetAvail:
+ QMessageBox.warning(self, 'No Internet!', \
+ 'You do not currently have a connection to the Bitcoin network. '
+ 'If this does not seem correct, verify your internet connection '
+ 'and restart Armory!', QMessageBox.Ok)
+ return
+
+
+
try:
finalTx = self.txdpObj.prepareFinalTx()
except: