Enable seamless, if crude, file attachment capability #1544

Open
sgj3 wants to merge 3 commits from sgj3/attachments into v0.6
4 changed files with 65 additions and 13 deletions

View File

@ -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

View File

@ -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))

View File

@ -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>

View File

@ -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):
""" """