Cancel Senging Message Feature
This commit is contained in:
parent
e423343e9a
commit
554b4f8cce
|
@ -390,6 +390,12 @@ class MyForm(QtGui.QMainWindow):
|
||||||
_translate(
|
_translate(
|
||||||
"MainWindow", "Copy destination address to clipboard"),
|
"MainWindow", "Copy destination address to clipboard"),
|
||||||
self.on_action_SentClipboard)
|
self.on_action_SentClipboard)
|
||||||
|
self.actionCancelPoW = self.ui.sentContextMenuToolbar.addAction(
|
||||||
|
_translate(
|
||||||
|
"MainWindow", "Cancel sending"), self.on_action_CancelPoW)
|
||||||
|
self.actionContinuePoW = self.ui.sentContextMenuToolbar.addAction(
|
||||||
|
_translate(
|
||||||
|
"MainWindow", "Continue sending"), self.on_action_ContinuePoW)
|
||||||
self.actionForceSend = self.ui.sentContextMenuToolbar.addAction(
|
self.actionForceSend = self.ui.sentContextMenuToolbar.addAction(
|
||||||
_translate(
|
_translate(
|
||||||
"MainWindow", "Force send"), self.on_action_ForceSend)
|
"MainWindow", "Force send"), self.on_action_ForceSend)
|
||||||
|
@ -849,6 +855,9 @@ class MyForm(QtGui.QMainWindow):
|
||||||
elif status == 'toodifficult':
|
elif status == 'toodifficult':
|
||||||
statusText = _translate("MainWindow", "Problem: The work demanded by the recipient is more difficult than you are willing to do. %1").arg(
|
statusText = _translate("MainWindow", "Problem: The work demanded by the recipient is more difficult than you are willing to do. %1").arg(
|
||||||
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
||||||
|
elif status == 'PoW_Cancelled':
|
||||||
|
statusText = _translate("MainWindow", "Problem: The sending was cancelled. %1").arg(
|
||||||
|
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
||||||
elif status == 'badkey':
|
elif status == 'badkey':
|
||||||
statusText = _translate("MainWindow", "Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1").arg(
|
statusText = _translate("MainWindow", "Problem: The recipient\'s encryption key is no good. Could not encrypt message. %1").arg(
|
||||||
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
unicode(strftime(shared.config.get('bitmessagesettings', 'timeformat'), localtime(lastactiontime)),'utf-8'))
|
||||||
|
@ -2718,6 +2727,31 @@ class MyForm(QtGui.QMainWindow):
|
||||||
clipboard = QtGui.QApplication.clipboard()
|
clipboard = QtGui.QApplication.clipboard()
|
||||||
clipboard.setText(str(addressAtCurrentRow))
|
clipboard.setText(str(addressAtCurrentRow))
|
||||||
|
|
||||||
|
def on_action_CancelPoW(self):
|
||||||
|
#The user wants to cancel the sending
|
||||||
|
if shared.PoWQueue.empty() == True: #The PoW calculation finished
|
||||||
|
QMessageBox.about(self, _translate("MainWindow", "PoW Finished"), _translate(
|
||||||
|
"MainWindow", "The message has already been sent!"))
|
||||||
|
else: #The PoW calculation is still in progress
|
||||||
|
if shared.PoWQueue.get() == 'PoW_Single_Thread': #It is the single threaded version
|
||||||
|
QMessageBox.about(self, _translate("MainWindow", "PoW Cancelled"), _translate(
|
||||||
|
"MainWindow", "The sending was cancelled!"))
|
||||||
|
else: #The multi threaded version is different, because of the possible overhead of the termination of the threads.
|
||||||
|
QMessageBox.about(self, _translate("MainWindow", "PoW Cancellation"), _translate(
|
||||||
|
"MainWindow", "The cancellation of sending can take up to a few seconds because of the multi-threaded environment. If the message is not be sent during this period it will be cancelled!"))
|
||||||
|
time.sleep(0.2) # We need to give some time to the PoW process to terminate and change the status of the message
|
||||||
|
self.loadSent()
|
||||||
|
|
||||||
|
def on_action_ContinuePoW(self):
|
||||||
|
#Continue sending of a message if it was cancelled by the user
|
||||||
|
currentRow = self.ui.tableWidgetSent.selectedIndexes()[0].row()
|
||||||
|
ackdataToContinue = str(self.ui.tableWidgetSent.item(
|
||||||
|
currentRow, 3).data(Qt.UserRole).toPyObject())
|
||||||
|
sqlExecute('''UPDATE sent SET status='msgqueued' WHERE status='PoW_Cancelled' AND ackdata=?''', ackdataToContinue)
|
||||||
|
self.statusBar().showMessage(_translate(
|
||||||
|
"MainWindow", "The sending will be continued."))
|
||||||
|
shared.workerQueue.put(('sendmessage', ''))
|
||||||
|
|
||||||
# Group of functions for the Address Book dialog box
|
# Group of functions for the Address Book dialog box
|
||||||
def on_action_AddressBookNew(self):
|
def on_action_AddressBookNew(self):
|
||||||
self.click_pushButtonAddAddressBook()
|
self.click_pushButtonAddAddressBook()
|
||||||
|
@ -3060,6 +3094,12 @@ class MyForm(QtGui.QMainWindow):
|
||||||
status, = row
|
status, = row
|
||||||
if status == 'toodifficult':
|
if status == 'toodifficult':
|
||||||
self.popMenuSent.addAction(self.actionForceSend)
|
self.popMenuSent.addAction(self.actionForceSend)
|
||||||
|
if status == 'PoW_Cancelled':
|
||||||
|
self.popMenuSent.addSeparator()
|
||||||
|
self.popMenuSent.addAction(self.actionContinuePoW)
|
||||||
|
if (status == 'doingmsgpow') and (shared.PoWQueue.empty() == False): #The PoW of a message is calculating
|
||||||
|
self.popMenuSent.addSeparator()
|
||||||
|
self.popMenuSent.addAction(self.actionCancelPoW)
|
||||||
self.popMenuSent.exec_(self.ui.tableWidgetSent.mapToGlobal(point))
|
self.popMenuSent.exec_(self.ui.tableWidgetSent.mapToGlobal(point))
|
||||||
|
|
||||||
def inboxSearchLineEditPressed(self):
|
def inboxSearchLineEditPressed(self):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#import shared
|
import shared
|
||||||
#import time
|
#import time
|
||||||
#from multiprocessing import Pool, cpu_count
|
#from multiprocessing import Pool, cpu_count
|
||||||
import hashlib
|
import hashlib
|
||||||
|
@ -30,16 +30,19 @@ def _pool_worker(nonce, initialHash, target, pool_size):
|
||||||
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
||||||
return [trialValue, nonce]
|
return [trialValue, nonce]
|
||||||
|
|
||||||
def _doSafePoW(target, initialHash):
|
def _doSafePoW(target, initialHash, cancellable):
|
||||||
nonce = 0
|
nonce = 0
|
||||||
trialValue = float('inf')
|
trialValue = float('inf')
|
||||||
while trialValue > target:
|
while trialValue > target:
|
||||||
|
if (shared.PoWQueue.empty() == True) and cancellable: #If the PoW is cancellable it can be interrupted
|
||||||
|
return [-1,-1] #Special value for differentiation
|
||||||
nonce += 1
|
nonce += 1
|
||||||
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
trialValue, = unpack('>Q',hashlib.sha512(hashlib.sha512(pack('>Q',nonce) + initialHash).digest()).digest()[0:8])
|
||||||
|
|
||||||
|
if cancellable: shared.PoWQueue.get() #If the PoW is cancellable we need to communicate its end to the UI
|
||||||
return [trialValue, nonce]
|
return [trialValue, nonce]
|
||||||
|
|
||||||
def _doFastPoW(target, initialHash):
|
def _doFastPoW(target, initialHash, cancellable):
|
||||||
import shared
|
|
||||||
import time
|
import time
|
||||||
from multiprocessing import Pool, cpu_count
|
from multiprocessing import Pool, cpu_count
|
||||||
try:
|
try:
|
||||||
|
@ -62,16 +65,33 @@ def _doFastPoW(target, initialHash):
|
||||||
while True:
|
while True:
|
||||||
time.sleep(10) # Don't let this thread return here; it will return nothing and cause an exception in bitmessagemain.py
|
time.sleep(10) # Don't let this thread return here; it will return nothing and cause an exception in bitmessagemain.py
|
||||||
return
|
return
|
||||||
|
if (shared.PoWQueue.empty() == True) and cancellable: #If the PoW is cancellable it can be interrupted
|
||||||
|
pool.terminate()
|
||||||
|
pool.join() #Wait for the workers to exit...
|
||||||
|
return [-1, -1] #Special value for differentiation
|
||||||
for i in range(pool_size):
|
for i in range(pool_size):
|
||||||
if result[i].ready():
|
if result[i].ready():
|
||||||
result = result[i].get()
|
result = result[i].get()
|
||||||
pool.terminate()
|
pool.terminate()
|
||||||
pool.join() #Wait for the workers to exit...
|
pool.join() #Wait for the workers to exit...
|
||||||
|
if cancellable: shared.PoWQueue.get() #If the PoW is cancellable we need to communicate its end to the UI
|
||||||
return result[0], result[1]
|
return result[0], result[1]
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
|
|
||||||
def run(target, initialHash):
|
def run(target, initialHash, cancellable):
|
||||||
|
import time
|
||||||
|
#Only message PoW calculations are cancellable, Key requests are not.
|
||||||
|
if cancellable:
|
||||||
|
#If the PoW is cancellable we need to communicate its beginning to the UI
|
||||||
if frozen == "macosx_app" or not frozen:
|
if frozen == "macosx_app" or not frozen:
|
||||||
return _doFastPoW(target, initialHash)
|
shared.PoWQueue.put('PoW_Single_Thread')
|
||||||
else:
|
else:
|
||||||
return _doSafePoW(target, initialHash)
|
shared.PoWQueue.put('PoW_Multi_Thread')
|
||||||
|
while shared.PoWQueue.empty() == True: #Necessary to wait because of the interprocess/interthread communication
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
if frozen == "macosx_app" or not frozen:
|
||||||
|
return _doFastPoW(target, initialHash, cancellable)
|
||||||
|
else:
|
||||||
|
return _doSafePoW(target, initialHash, cancellable)
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import ConfigParser
|
||||||
import os
|
import os
|
||||||
import pickle
|
import pickle
|
||||||
import Queue
|
import Queue
|
||||||
|
from multiprocessing import Queue as MQueue #A Multiproccessing Queue is necessary for the PoW cancellation.
|
||||||
import random
|
import random
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
|
@ -39,6 +40,7 @@ broadcastSendersForWhichImWatching = {}
|
||||||
workerQueue = Queue.Queue()
|
workerQueue = Queue.Queue()
|
||||||
UISignalQueue = Queue.Queue()
|
UISignalQueue = Queue.Queue()
|
||||||
addressGeneratorQueue = Queue.Queue()
|
addressGeneratorQueue = Queue.Queue()
|
||||||
|
PoWQueue = MQueue() #Multithreaded queue for interprocess communication. It is used for the PoW calculation
|
||||||
knownNodesLock = threading.Lock()
|
knownNodesLock = threading.Lock()
|
||||||
knownNodes = {}
|
knownNodes = {}
|
||||||
sendDataQueues = [] #each sendData thread puts its queue in this list.
|
sendDataQueues = [] #each sendData thread puts its queue in this list.
|
||||||
|
|
Reference in New Issue
Block a user