ui: empty space. pseudo offline file transfers
This commit is contained in:
parent
63774ba5df
commit
d3c8c99048
9 changed files with 192 additions and 57 deletions
|
@ -68,6 +68,7 @@ def friend_status(tox, friend_num, new_status, user_data):
|
|||
if friend.status is None and Settings.get_instance()['sound_notifications'] and profile.status != TOX_USER_STATUS['BUSY']:
|
||||
sound_notification(SOUND_NOTIFICATION['FRIEND_CONNECTION_STATUS'])
|
||||
invoke_in_main_thread(friend.set_status, new_status)
|
||||
invoke_in_main_thread(profile.send_files, friend_num)
|
||||
invoke_in_main_thread(profile.update_filtration)
|
||||
|
||||
|
||||
|
@ -85,7 +86,6 @@ def friend_connection_status(tox, friend_num, new_status, user_data):
|
|||
sound_notification(SOUND_NOTIFICATION['FRIEND_CONNECTION_STATUS'])
|
||||
elif friend.status is None:
|
||||
invoke_in_main_thread(profile.send_avatar, friend_num)
|
||||
profile.friend_online(friend_num)
|
||||
invoke_in_main_thread(PluginLoader.get_instance().friend_online, friend_num)
|
||||
|
||||
|
||||
|
|
|
@ -116,6 +116,18 @@ class Friend(contact.Contact):
|
|||
self._corr = filter(lambda x: x.get_type() in (2, 3) and x.get_status() >= 2, self._corr)
|
||||
self._unsaved_messages = 0
|
||||
|
||||
def get_curr_text(self):
|
||||
return self._curr_text
|
||||
|
||||
def set_curr_text(self, value):
|
||||
self._curr_text = value
|
||||
|
||||
curr_text = property(get_curr_text, set_curr_text)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# File transfers support
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def update_transfer_data(self, file_number, status, inline=None):
|
||||
"""
|
||||
Update status of active transfer and load inline if needed
|
||||
|
@ -131,13 +143,15 @@ class Friend(contact.Contact):
|
|||
except:
|
||||
pass
|
||||
|
||||
def get_curr_text(self):
|
||||
return self._curr_text
|
||||
def get_unsent_files(self):
|
||||
messages = filter(lambda x: type(x) is UnsentFile, self._corr)
|
||||
return messages
|
||||
|
||||
def set_curr_text(self, value):
|
||||
self._curr_text = value
|
||||
def clear_unsent_files(self):
|
||||
self._corr = filter(lambda x: type(x) is not UnsentFile, self._corr)
|
||||
|
||||
curr_text = property(get_curr_text, set_curr_text)
|
||||
def delete_one_unsent_file(self, time):
|
||||
self._corr = filter(lambda x: not (type(x) is UnsentFile and x.get_data()[2] == time), self._corr)
|
||||
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
# Alias support
|
||||
|
|
BIN
src/images/search.png
Executable file → Normal file
BIN
src/images/search.png
Executable file → Normal file
Binary file not shown.
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.7 KiB |
|
@ -356,6 +356,60 @@ class FileTransferItem(QtGui.QListWidget):
|
|||
self.state = state
|
||||
|
||||
|
||||
class UnsentFileItem(QtGui.QListWidget):
|
||||
|
||||
def __init__(self, file_name, size, user, time, width, parent=None):
|
||||
QtGui.QListWidget.__init__(self, parent)
|
||||
self.resize(QtCore.QSize(width, 34))
|
||||
self.time = time
|
||||
self.setStyleSheet('QListWidget { border: 1px solid #FF8000; }')
|
||||
|
||||
self.name = DataLabel(self)
|
||||
self.name.setGeometry(QtCore.QRect(3, 7, 95, 20))
|
||||
self.name.setTextFormat(QtCore.Qt.PlainText)
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Times New Roman")
|
||||
font.setPointSize(11)
|
||||
font.setBold(True)
|
||||
self.name.setFont(font)
|
||||
self.name.setText(user)
|
||||
|
||||
self.time = QtGui.QLabel(self)
|
||||
self.time.setGeometry(QtCore.QRect(width - 53, 7, 50, 20))
|
||||
font.setPointSize(10)
|
||||
font.setBold(False)
|
||||
self.time.setFont(font)
|
||||
self.time.setText(convert_time(time))
|
||||
|
||||
self.cancel = QtGui.QPushButton(self)
|
||||
self.cancel.setGeometry(QtCore.QRect(width - 120, 2, 30, 30))
|
||||
pixmap = QtGui.QPixmap(curr_directory() + '/images/decline.png')
|
||||
icon = QtGui.QIcon(pixmap)
|
||||
self.cancel.setIcon(icon)
|
||||
self.cancel.setIconSize(QtCore.QSize(30, 30))
|
||||
self.cancel.clicked.connect(self.cancel_transfer)
|
||||
self.cancel.setStyleSheet('QPushButton:hover { border: 1px solid #3A3939; background-color: none;}')
|
||||
|
||||
self.file_name = DataLabel(self)
|
||||
self.file_name.setGeometry(QtCore.QRect(210, 7, width - 400, 20))
|
||||
font.setPointSize(12)
|
||||
self.file_name.setFont(font)
|
||||
file_size = size / 1024
|
||||
if not file_size:
|
||||
file_size = '{}B'.format(size)
|
||||
elif file_size >= 1024:
|
||||
file_size = '{}MB'.format(file_size / 1024)
|
||||
else:
|
||||
file_size = '{}KB'.format(file_size)
|
||||
file_data = u'{} {}'.format(file_size, file_name)
|
||||
self.file_name.setText(file_data)
|
||||
self.setFocusPolicy(QtCore.Qt.NoFocus)
|
||||
|
||||
def cancel_transfer(self):
|
||||
pr = profile.Profile.get_instance()
|
||||
pr.cancel_not_started_transfer(self.time)
|
||||
|
||||
|
||||
class InlineImageItem(QtGui.QWidget):
|
||||
|
||||
def __init__(self, data, width, parent=None):
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
from menu import *
|
||||
from profile import *
|
||||
from list_items import *
|
||||
from widgets import QRightClickButton, RubberBand, MultilineEdit
|
||||
from widgets import MultilineEdit
|
||||
import plugin_support
|
||||
from mainscreen_widgets import *
|
||||
|
||||
|
@ -142,33 +142,34 @@ class MainWindow(QtGui.QMainWindow):
|
|||
def setup_left_center_menu(self, Form):
|
||||
Form.resize(270, 25)
|
||||
self.search_label = QtGui.QLabel(Form)
|
||||
self.search_label.setGeometry(QtCore.QRect(3, 0, 25, 25))
|
||||
pixmap = QtGui.QPixmap(QtCore.QSize(25, 25))
|
||||
self.search_label.setGeometry(QtCore.QRect(3, 2, 20, 20))
|
||||
pixmap = QtGui.QPixmap()
|
||||
pixmap.load(curr_directory() + '/images/search.png')
|
||||
self.search_label.setScaledContents(False)
|
||||
self.search_label.setPixmap(pixmap.scaled(25, 25, QtCore.Qt.KeepAspectRatio))
|
||||
self.search_label.setPixmap(pixmap)
|
||||
|
||||
self.contact_name = QtGui.QLineEdit(Form)
|
||||
self.contact_name.setGeometry(QtCore.QRect(30, 0, 120, 25))
|
||||
self.contact_name.setGeometry(QtCore.QRect(0, 0, 150, 25))
|
||||
self.contact_name.setObjectName("contact_name")
|
||||
self.contact_name.textChanged.connect(self.filtering)
|
||||
self.online_contacts = QtGui.QComboBox(Form)
|
||||
self.online_contacts.setGeometry(QtCore.QRect(150, 0, 120, 25))
|
||||
self.online_contacts.activated[int].connect(lambda x: self.filtering())
|
||||
self.search_label.raise_()
|
||||
|
||||
QtCore.QMetaObject.connectSlotsByName(Form)
|
||||
|
||||
def setup_left_top(self, Form):
|
||||
Form.setObjectName("left_top")
|
||||
Form.setCursor(QtCore.Qt.PointingHandCursor)
|
||||
Form.setMinimumSize(QtCore.QSize(270, 80))
|
||||
Form.setMaximumSize(QtCore.QSize(270, 80))
|
||||
Form.setBaseSize(QtCore.QSize(270, 80))
|
||||
Form.setMinimumSize(QtCore.QSize(270, 100))
|
||||
Form.setMaximumSize(QtCore.QSize(270, 100))
|
||||
Form.setBaseSize(QtCore.QSize(270, 100))
|
||||
self.avatar_label = Form.avatar_label = QtGui.QLabel(Form)
|
||||
self.avatar_label.setGeometry(QtCore.QRect(5, 15, 64, 64))
|
||||
self.avatar_label.setGeometry(QtCore.QRect(5, 30, 64, 64))
|
||||
self.avatar_label.setScaledContents(True)
|
||||
self.name = Form.name = DataLabel(Form)
|
||||
Form.name.setGeometry(QtCore.QRect(80, 25, 150, 25))
|
||||
Form.name.setGeometry(QtCore.QRect(80, 40, 150, 25))
|
||||
font = QtGui.QFont()
|
||||
font.setFamily("Times New Roman")
|
||||
font.setPointSize(14)
|
||||
|
@ -176,7 +177,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||
Form.name.setFont(font)
|
||||
Form.name.setObjectName("name")
|
||||
self.status_message = Form.status_message = DataLabel(Form)
|
||||
Form.status_message.setGeometry(QtCore.QRect(80, 55, 170, 20))
|
||||
Form.status_message.setGeometry(QtCore.QRect(80, 60, 170, 25))
|
||||
font.setPointSize(12)
|
||||
font.setBold(False)
|
||||
Form.status_message.setFont(font)
|
||||
|
@ -194,9 +195,9 @@ class MainWindow(QtGui.QMainWindow):
|
|||
|
||||
def setup_right_top(self, Form):
|
||||
Form.setObjectName("Form")
|
||||
Form.resize(650, 80)
|
||||
Form.resize(650, 100)
|
||||
self.account_avatar = QtGui.QLabel(Form)
|
||||
self.account_avatar.setGeometry(QtCore.QRect(10, 17, 64, 64))
|
||||
self.account_avatar.setGeometry(QtCore.QRect(10, 30, 64, 64))
|
||||
self.account_avatar.setScaledContents(True)
|
||||
self.account_name = DataLabel(Form)
|
||||
self.account_name.setGeometry(QtCore.QRect(100, 25, 400, 25))
|
||||
|
@ -224,7 +225,7 @@ class MainWindow(QtGui.QMainWindow):
|
|||
self.videocallButton.clicked.connect(lambda: self.profile.call_click(True, True))
|
||||
self.update_call_state('call')
|
||||
self.typing = QtGui.QLabel(Form)
|
||||
self.typing.setGeometry(QtCore.QRect(500, 40, 50, 30))
|
||||
self.typing.setGeometry(QtCore.QRect(500, 50, 50, 30))
|
||||
pixmap = QtGui.QPixmap(QtCore.QSize(50, 30))
|
||||
pixmap.load(curr_directory() + '/images/typing.png')
|
||||
self.typing.setScaledContents(False)
|
||||
|
@ -299,11 +300,13 @@ class MainWindow(QtGui.QMainWindow):
|
|||
self.setup_left_center(main_list)
|
||||
grid.addWidget(main_list, 2, 1, 2, 1)
|
||||
grid.setColumnMinimumWidth(0, 500)
|
||||
grid.setColumnMinimumWidth(1, 270)
|
||||
grid.setRowMinimumHeight(0, 82)
|
||||
grid.setColumnMinimumWidth(1, 280)
|
||||
grid.setSpacing(0)
|
||||
grid.setContentsMargins(0, 0, 0, 0)
|
||||
grid.setRowMinimumHeight(0, 100)
|
||||
grid.setRowMinimumHeight(1, 25)
|
||||
grid.setRowMinimumHeight(2, 410)
|
||||
grid.setRowMinimumHeight(3, 60)
|
||||
grid.setRowMinimumHeight(2, 320)
|
||||
grid.setRowMinimumHeight(3, 55)
|
||||
grid.setColumnStretch(1, 1)
|
||||
grid.setRowStretch(2, 1)
|
||||
main.setLayout(grid)
|
||||
|
@ -321,19 +324,19 @@ class MainWindow(QtGui.QMainWindow):
|
|||
QtGui.QApplication.closeAllWindows()
|
||||
|
||||
def resizeEvent(self, *args, **kwargs):
|
||||
self.messages.setGeometry(0, 0, self.width() - 294, self.height() - 172)
|
||||
self.friends_list.setGeometry(0, 0, 270, self.height() - 135)
|
||||
self.messages.setGeometry(0, 0, self.width() - 270, self.height() - 155)
|
||||
self.friends_list.setGeometry(0, 0, 270, self.height() - 125)
|
||||
|
||||
self.videocallButton.setGeometry(QtCore.QRect(self.width() - 350, 20, 50, 50))
|
||||
self.callButton.setGeometry(QtCore.QRect(self.width() - 410, 20, 50, 50))
|
||||
self.typing.setGeometry(QtCore.QRect(self.width() - 470, 30, 50, 30))
|
||||
self.videocallButton.setGeometry(QtCore.QRect(self.width() - 330, 40, 50, 50))
|
||||
self.callButton.setGeometry(QtCore.QRect(self.width() - 390, 40, 50, 50))
|
||||
self.typing.setGeometry(QtCore.QRect(self.width() - 450, 50, 50, 30))
|
||||
|
||||
self.messageEdit.setGeometry(QtCore.QRect(60, 2, self.width() - 430, 55))
|
||||
self.menuButton.setGeometry(QtCore.QRect(0, 2, 55, 55))
|
||||
self.sendMessageButton.setGeometry(QtCore.QRect(self.width() - 360, 2, 60, 55))
|
||||
self.messageEdit.setGeometry(QtCore.QRect(55, 0, self.width() - 395, 55))
|
||||
self.menuButton.setGeometry(QtCore.QRect(0, 0, 55, 55))
|
||||
self.sendMessageButton.setGeometry(QtCore.QRect(self.width() - 340, 0, 70, 55))
|
||||
|
||||
self.account_name.setGeometry(QtCore.QRect(100, 30, self.width() - 600, 25))
|
||||
self.account_status.setGeometry(QtCore.QRect(100, 50, self.width() - 520, 25))
|
||||
self.account_name.setGeometry(QtCore.QRect(100, 40, self.width() - 560, 25))
|
||||
self.account_status.setGeometry(QtCore.QRect(100, 60, self.width() - 560, 25))
|
||||
self.messageEdit.setFocus()
|
||||
self.profile.update()
|
||||
|
||||
|
@ -391,9 +394,10 @@ class MainWindow(QtGui.QMainWindow):
|
|||
if hasattr(self, 'menu') and self.menu.isVisible():
|
||||
self.menu.hide()
|
||||
return
|
||||
self.menu = DropdownMenu(self)
|
||||
elif not hasattr(self, 'menu'):
|
||||
self.menu = DropdownMenu(self)
|
||||
self.menu.setGeometry(QtCore.QRect(0 if Settings.get_instance()['mirror_mode'] else 270,
|
||||
self.height() - 160,
|
||||
self.height() - 100,
|
||||
150,
|
||||
100))
|
||||
self.menu.show()
|
||||
|
@ -408,20 +412,18 @@ class MainWindow(QtGui.QMainWindow):
|
|||
|
||||
def send_file(self):
|
||||
self.menu.hide()
|
||||
if self.profile.is_active_online(): # active friend exists and online
|
||||
choose_file = QtGui.QApplication.translate("MainWindow", 'Choose file', None, QtGui.QApplication.UnicodeUTF8)
|
||||
choose = QtGui.QApplication.translate("MainWindow", choose_file, None, QtGui.QApplication.UnicodeUTF8)
|
||||
name = QtGui.QFileDialog.getOpenFileName(self, choose)
|
||||
if name[0]:
|
||||
self.profile.send_file(name[0])
|
||||
choose_file = QtGui.QApplication.translate("MainWindow", 'Choose file', None, QtGui.QApplication.UnicodeUTF8)
|
||||
choose = QtGui.QApplication.translate("MainWindow", choose_file, None, QtGui.QApplication.UnicodeUTF8)
|
||||
name = QtGui.QFileDialog.getOpenFileName(self, choose)
|
||||
if name[0]:
|
||||
self.profile.send_file(name[0])
|
||||
|
||||
def send_screenshot(self, hide=False):
|
||||
self.menu.hide()
|
||||
if self.profile.is_active_online(): # active friend exists and online
|
||||
self.sw = ScreenShotWindow(self)
|
||||
self.sw.show()
|
||||
if hide:
|
||||
self.hide()
|
||||
self.sw = ScreenShotWindow(self)
|
||||
self.sw.show()
|
||||
if hide:
|
||||
self.hide()
|
||||
|
||||
def send_smiley(self):
|
||||
self.menu.hide()
|
||||
|
|
|
@ -80,6 +80,18 @@ class TransferMessage(Message):
|
|||
return self._file_name, self._size, self._time, self._owner, self._friend_number, self._file_number, self._status
|
||||
|
||||
|
||||
class UnsentFile(Message):
|
||||
def __init__(self, path, data, time):
|
||||
super(UnsentFile, self).__init__(MESSAGE_TYPE['FILE_TRANSFER'], 0, time)
|
||||
self._data, self._path = data, path
|
||||
|
||||
def get_data(self):
|
||||
return self._path, self._data, self._time
|
||||
|
||||
def get_status(self):
|
||||
return None
|
||||
|
||||
|
||||
class InlineImage(Message):
|
||||
"""
|
||||
Inline image
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from list_items import MessageItem, ContactItem, FileTransferItem, InlineImageItem
|
||||
from list_items import *
|
||||
try:
|
||||
from PySide import QtCore, QtGui
|
||||
except ImportError:
|
||||
|
@ -169,6 +169,9 @@ class Profile(contact.Contact, Singleton):
|
|||
friend.name if data[1] == MESSAGE_OWNER['FRIEND'] else self._name,
|
||||
data[3])
|
||||
elif message.get_type() == MESSAGE_TYPE['FILE_TRANSFER']:
|
||||
if message.get_status() is None:
|
||||
self.create_unsent_file_item(message)
|
||||
continue
|
||||
item = self.create_file_transfer_item(message)
|
||||
if message.get_status() >= 2: # active file transfer
|
||||
try:
|
||||
|
@ -246,9 +249,23 @@ class Profile(contact.Contact, Singleton):
|
|||
# Friend connection status callbacks
|
||||
# -----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
def friend_online(self, friend_number):
|
||||
for key in filter(lambda x: x[0] == friend_number, self._file_transfers.keys()):
|
||||
self.resume_transfer(key[0], key[1], True)
|
||||
def send_files(self, friend_number):
|
||||
# for key in filter(lambda x: x[0] == friend_number, self._file_transfers.keys()):
|
||||
# self.resume_transfer(key[0], key[1], True)
|
||||
friend = self.get_friend_by_number(friend_number)
|
||||
files = friend.get_unsent_files()
|
||||
try:
|
||||
for fl in files:
|
||||
data = fl.get_data()
|
||||
if data[1] is not None:
|
||||
self.send_inline(data[1], data[0], friend_number, True)
|
||||
else:
|
||||
self.send_file(data[0], friend_number, True)
|
||||
friend.clear_unsent_files()
|
||||
if friend_number == self.get_active_number():
|
||||
self.update()
|
||||
except:
|
||||
pass
|
||||
|
||||
def friend_exit(self, friend_number):
|
||||
"""
|
||||
|
@ -483,6 +500,21 @@ class Profile(contact.Contact, Singleton):
|
|||
self._messages.setItemWidget(elem, item)
|
||||
return item
|
||||
|
||||
def create_unsent_file_item(self, message, append=True):
|
||||
data = message.get_data()
|
||||
item = UnsentFileItem(os.path.basename(data[0]),
|
||||
os.path.getsize(data[0]) if data[1] is None else len(data[1]),
|
||||
self.name,
|
||||
data[2],
|
||||
self._messages.width())
|
||||
elem = QtGui.QListWidgetItem()
|
||||
elem.setSizeHint(QtCore.QSize(self._messages.width() - 30, 34))
|
||||
if append:
|
||||
self._messages.addItem(elem)
|
||||
else:
|
||||
self._messages.insertItem(0, elem)
|
||||
self._messages.setItemWidget(elem, item)
|
||||
|
||||
def create_inline_item(self, data, append=True):
|
||||
item = InlineImageItem(data, self._messages.width())
|
||||
elem = QtGui.QListWidgetItem()
|
||||
|
@ -786,6 +818,10 @@ class Profile(contact.Contact, Singleton):
|
|||
else:
|
||||
self._tox.file_control(friend_number, file_number, TOX_FILE_CONTROL['CANCEL'])
|
||||
|
||||
def cancel_not_started_transfer(self, time):
|
||||
self._friends[self._active_friend].delete_one_unsent_file(time)
|
||||
self.update()
|
||||
|
||||
def pause_transfer(self, friend_number, file_number, by_friend=False):
|
||||
"""
|
||||
Pause transfer with specified data
|
||||
|
@ -840,10 +876,16 @@ class Profile(contact.Contact, Singleton):
|
|||
data = fl.read()
|
||||
self.send_inline(data, 'sticker.png')
|
||||
|
||||
def send_inline(self, data, file_name):
|
||||
friend = self._friends[self._active_friend]
|
||||
if friend.status is None:
|
||||
def send_inline(self, data, file_name, friend_number=None, is_resend=False):
|
||||
friend_number = friend_number or self.get_active_number()
|
||||
friend = self.get_friend_by_number(friend_number)
|
||||
if friend.status is None and not is_resend:
|
||||
m = UnsentFile(file_name, data, time.time())
|
||||
friend.append_message(m)
|
||||
self.update()
|
||||
return
|
||||
elif friend.status is None and is_resend:
|
||||
raise Exception()
|
||||
st = SendFromBuffer(self._tox, friend.number, data, file_name)
|
||||
self._file_transfers[(friend.number, st.get_file_number())] = st
|
||||
tm = TransferMessage(MESSAGE_OWNER['ME'],
|
||||
|
@ -858,15 +900,21 @@ class Profile(contact.Contact, Singleton):
|
|||
st.set_state_changed_handler(item.update)
|
||||
self._messages.scrollToBottom()
|
||||
|
||||
def send_file(self, path, number=None):
|
||||
def send_file(self, path, number=None, is_resend=False):
|
||||
"""
|
||||
Send file to current active friend
|
||||
:param path: file path
|
||||
:param number: friend_number
|
||||
"""
|
||||
friend_number = number or self.get_active_number()
|
||||
if self.get_friend_by_number(friend_number).status is None:
|
||||
friend = self.get_friend_by_number(friend_number)
|
||||
if friend.status is None and not is_resend:
|
||||
m = UnsentFile(path, None, time.time())
|
||||
friend.append_message(m)
|
||||
self.update()
|
||||
return
|
||||
elif friend.status is None and is_resend:
|
||||
raise Exception()
|
||||
st = SendTransfer(path, self._tox, friend_number)
|
||||
self._file_transfers[(friend_number, st.get_file_number())] = st
|
||||
tm = TransferMessage(MESSAGE_OWNER['ME'],
|
||||
|
|
|
@ -72,7 +72,7 @@ class SmileyLoader(util.Singleton):
|
|||
|
||||
def sticker_loader():
|
||||
"""
|
||||
:return dict of stickers
|
||||
:return list of stickers
|
||||
"""
|
||||
result = []
|
||||
d = util.curr_directory() + '/stickers/'
|
||||
|
|
|
@ -1271,4 +1271,9 @@ QCheckBox
|
|||
QListWidget > QLabel
|
||||
{
|
||||
color: #A9A9A9;
|
||||
}
|
||||
|
||||
#contact_name
|
||||
{
|
||||
padding-left: 22px;
|
||||
}
|
Loading…
Reference in a new issue