Enable seamless, if crude, file attachment capability #1544
|
@ -11,6 +11,7 @@ import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import base64
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from sqlite3 import register_adapter
|
from sqlite3 import register_adapter
|
||||||
|
|
||||||
|
@ -161,6 +162,8 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
"clicked()"), self.click_pushButtonTTL)
|
"clicked()"), self.click_pushButtonTTL)
|
||||||
QtCore.QObject.connect(self.ui.pushButtonClear, QtCore.SIGNAL(
|
QtCore.QObject.connect(self.ui.pushButtonClear, QtCore.SIGNAL(
|
||||||
"clicked()"), self.click_pushButtonClear)
|
"clicked()"), self.click_pushButtonClear)
|
||||||
|
QtCore.QObject.connect(self.ui.pushButtonAttach, QtCore.SIGNAL(
|
||||||
|
"clicked()"), self.click_pushButtonAttach)
|
||||||
QtCore.QObject.connect(self.ui.pushButtonSend, QtCore.SIGNAL(
|
QtCore.QObject.connect(self.ui.pushButtonSend, QtCore.SIGNAL(
|
||||||
"clicked()"), self.click_pushButtonSend)
|
"clicked()"), self.click_pushButtonSend)
|
||||||
QtCore.QObject.connect(self.ui.pushButtonFetchNamecoinID, QtCore.SIGNAL(
|
QtCore.QObject.connect(self.ui.pushButtonFetchNamecoinID, QtCore.SIGNAL(
|
||||||
|
@ -1951,6 +1954,23 @@ class MyForm(settingsmixin.SMainWindow):
|
||||||
self.ui.textEditMessage.reset()
|
self.ui.textEditMessage.reset()
|
||||||
self.ui.comboBoxSendFrom.setCurrentIndex(0)
|
self.ui.comboBoxSendFrom.setCurrentIndex(0)
|
||||||
|
|
||||||
|
def click_pushButtonAttach(self):
|
||||||
|
"""Launch a file picker and append to the current message the base64-encoded contents of the chosen file."""
|
||||||
|
filename = QtGui.QFileDialog.getOpenFileName(self, "Attach File")
|
||||||
|
if filename:
|
||||||
|
f = open(filename, 'rb')
|
||||||
|
data = f.read()
|
||||||
|
f.close()
|
||||||
|
data_b64 = base64.b64encode(data)
|
||||||
|
html_data = '<a href="data:application/octet-stream;base64,' + data_b64 + '">' \
|
||||||
|
+ os.path.basename(unicode(filename)) + '</a>'
|
||||||
|
if self.ui.tabWidgetSend.currentIndex() == self.ui.tabWidgetSend.indexOf(self.ui.sendDirect):
|
||||||
|
# send direct message
|
||||||
|
self.ui.textEditMessage.insertPlainText(html_data)
|
||||||
|
else:
|
||||||
|
# send broadcast message
|
||||||
|
self.ui.textEditMessageBroadcast.insertPlainText(html_data)
|
||||||
|
|
||||||
def click_pushButtonSend(self):
|
def click_pushButtonSend(self):
|
||||||
encoding = 3 if QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier else 2
|
encoding = 3 if QtGui.QApplication.queryKeyboardModifiers() & QtCore.Qt.ShiftModifier else 2
|
||||||
|
|
||||||
|
|
|
@ -340,6 +340,9 @@ class Ui_MainWindow(object):
|
||||||
self.pushButtonClear = QtGui.QPushButton(self.send)
|
self.pushButtonClear = QtGui.QPushButton(self.send)
|
||||||
self.pushButtonClear.setObjectName(_fromUtf8("pushButtonClear"))
|
self.pushButtonClear.setObjectName(_fromUtf8("pushButtonClear"))
|
||||||
self.horizontalLayout_5.addWidget(self.pushButtonClear, 0, QtCore.Qt.AlignRight)
|
self.horizontalLayout_5.addWidget(self.pushButtonClear, 0, QtCore.Qt.AlignRight)
|
||||||
|
self.pushButtonAttach = QtGui.QPushButton(self.send)
|
||||||
|
self.pushButtonAttach.setObjectName(_fromUtf8("pushButtonAttach"))
|
||||||
|
self.horizontalLayout_5.addWidget(self.pushButtonAttach, 0, QtCore.Qt.AlignRight)
|
||||||
self.pushButtonSend = QtGui.QPushButton(self.send)
|
self.pushButtonSend = QtGui.QPushButton(self.send)
|
||||||
self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend"))
|
self.pushButtonSend.setObjectName(_fromUtf8("pushButtonSend"))
|
||||||
self.horizontalLayout_5.addWidget(self.pushButtonSend, 0, QtCore.Qt.AlignRight)
|
self.horizontalLayout_5.addWidget(self.pushButtonSend, 0, QtCore.Qt.AlignRight)
|
||||||
|
@ -713,6 +716,7 @@ class Ui_MainWindow(object):
|
||||||
pass
|
pass
|
||||||
self.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, hours))
|
self.labelHumanFriendlyTTLDescription.setText(_translate("MainWindow", "%n hour(s)", None, QtCore.QCoreApplication.CodecForTr, hours))
|
||||||
self.pushButtonClear.setText(_translate("MainWindow", "Clear", None))
|
self.pushButtonClear.setText(_translate("MainWindow", "Clear", None))
|
||||||
|
self.pushButtonAttach.setText(_translate("MainWindow", "Attach File", None))
|
||||||
self.pushButtonSend.setText(_translate("MainWindow", "Send", None))
|
self.pushButtonSend.setText(_translate("MainWindow", "Send", None))
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.send), _translate("MainWindow", "Send", None))
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.send), _translate("MainWindow", "Send", None))
|
||||||
self.treeWidgetSubscriptions.headerItem().setText(0, _translate("MainWindow", "Subscriptions", None))
|
self.treeWidgetSubscriptions.headerItem().setText(0, _translate("MainWindow", "Subscriptions", None))
|
||||||
|
|
|
@ -594,6 +594,19 @@ p, li { white-space: pre-wrap; }
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButtonAttach">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Attach File</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -5,6 +5,8 @@ src/bitmessageqt/messageview.py
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from PyQt4 import QtCore, QtGui
|
from PyQt4 import QtCore, QtGui
|
||||||
|
import re
|
||||||
|
import base64
|
||||||
|
|
||||||
from safehtmlparser import SafeHTMLParser
|
from safehtmlparser import SafeHTMLParser
|
||||||
|
|
||||||
|
@ -64,6 +66,9 @@ class MessageView(QtGui.QTextBrowser):
|
||||||
|
|
||||||
def confirmURL(self, link):
|
def confirmURL(self, link):
|
||||||
"""Show a dialog requesting URL opening confirmation"""
|
"""Show a dialog requesting URL opening confirmation"""
|
||||||
|
link_str = link.toString()
|
||||||
|
datablob_re = r'^data:.*/.*;base64,.*'
|
||||||
|
datablob_match = re.match(datablob_re, link_str)
|
||||||
if link.scheme() == "mailto":
|
if link.scheme() == "mailto":
|
||||||
window = QtGui.QApplication.activeWindow()
|
window = QtGui.QApplication.activeWindow()
|
||||||
window.ui.lineEditTo.setText(link.path())
|
window.ui.lineEditTo.setText(link.path())
|
||||||
|
@ -80,19 +85,29 @@ class MessageView(QtGui.QTextBrowser):
|
||||||
)
|
)
|
||||||
window.ui.textEditMessage.setFocus()
|
window.ui.textEditMessage.setFocus()
|
||||||
return
|
return
|
||||||
reply = QtGui.QMessageBox.warning(
|
if datablob_match:
|
||||||
self,
|
name = QtGui.QFileDialog.getSaveFileName(self, 'Save File')
|
||||||
QtGui.QApplication.translate(
|
if name:
|
||||||
"MessageView",
|
f = open(name, 'wb')
|
||||||
"Follow external link"),
|
data_begin_pos = re.finditer(";base64,", link_str).next()
|
||||||
QtGui.QApplication.translate(
|
data_b64 = link_str[data_begin_pos.span()[1]:]
|
||||||
"MessageView",
|
data = base64.b64decode(data_b64)
|
||||||
"The link \"%1\" will open in a browser. It may be a security risk, it could de-anonymise you"
|
f.write(data)
|
||||||
" or download malicious data. Are you sure?").arg(unicode(link.toString())),
|
f.close()
|
||||||
QtGui.QMessageBox.Yes,
|
else:
|
||||||
QtGui.QMessageBox.No)
|
reply = QtGui.QMessageBox.warning(
|
||||||
if reply == QtGui.QMessageBox.Yes:
|
self,
|
||||||
QtGui.QDesktopServices.openUrl(link)
|
QtGui.QApplication.translate(
|
||||||
|
"MessageView",
|
||||||
|
"Follow external link"),
|
||||||
|
QtGui.QApplication.translate(
|
||||||
|
"MessageView",
|
||||||
|
"The link \"%1\" will open in a browser. It may be a security risk, it could de-anonymise you"
|
||||||
|
" or download malicious data. Are you sure?").arg(unicode(link.toString())),
|
||||||
|
QtGui.QMessageBox.Yes,
|
||||||
|
QtGui.QMessageBox.No)
|
||||||
|
if reply == QtGui.QMessageBox.Yes:
|
||||||
|
QtGui.QDesktopServices.openUrl(link)
|
||||||
|
|
||||||
def loadResource(self, restype, name):
|
def loadResource(self, restype, name):
|
||||||
"""
|
"""
|
||||||
|
|
Reference in New Issue
Block a user