diff --git a/src/main.py b/src/main.py index 44c5754..88767e5 100644 --- a/src/main.py +++ b/src/main.py @@ -1,7 +1,7 @@ from loginscreen import LoginScreen from settings import Settings from mainscreen import MainWindow -from profile import Profile, tox_factory +from profile import ProfileHelper, tox_factory import sys from PySide import QtCore, QtGui from callbacks import init_callbacks @@ -42,7 +42,7 @@ def main(): # show login screen if default profile not found ls = LoginScreen() ls.setWindowIconText("Toxygen") - profiles = Profile.find_profiles() + profiles = ProfileHelper.find_profiles() ls.update_select(map(lambda x: x[1], profiles)) _login = login(profiles) ls.update_on_close(_login.login_screen_close) @@ -57,17 +57,17 @@ def main(): tox = tox_factory() tox.self_set_name('Toxygen User') tox.self_set_status('Toxing on Toxygen') - Profile.save_profile(tox.get_savedata(), name) + ProfileHelper.save_profile(tox.get_savedata(), name) else: # load existing profile path, name = _login.get_data() if _login.default: settings['auto_profile'] = (path, name) settings.save() - data = Profile.open_profile(path, name) + data = ProfileHelper.open_profile(path, name) tox = tox_factory(data, settings) else: path, name = settings['auto_profile'] - data = Profile.open_profile(path, name) + data = ProfileHelper.open_profile(path, name) tox = tox_factory(data, settings) ms = MainWindow(tox) diff --git a/src/mainscreen.py b/src/mainscreen.py index 97ca21c..b8376ce 100644 --- a/src/mainscreen.py +++ b/src/mainscreen.py @@ -3,9 +3,35 @@ import sys from PySide import QtGui, QtCore from menu import * +from profile import Profile from toxcore_enums_and_consts import * +class ContactItem(QtGui.QListWidget): + + def __init__(self, parent=None): + QtGui.QListWidget.__init__(self, parent) + # self.setMinimumSize(QtCore.QSize(250, 50)) + # self.setMaximumSize(QtCore.QSize(250, 50)) + self.setBaseSize(QtCore.QSize(250, 50)) + self.name = QtGui.QLabel(self) + self.name.setGeometry(QtCore.QRect(80, 10, 191, 25)) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(12) + font.setBold(True) + self.name.setFont(font) + self.name.setObjectName("name") + self.status_message = QtGui.QLabel(self) + self.status_message.setGeometry(QtCore.QRect(80, 30, 191, 17)) + font = QtGui.QFont() + font.setFamily("Times New Roman") + font.setPointSize(10) + font.setBold(False) + self.status_message.setFont(font) + self.status_message.setObjectName("status_message") + + class StatusCircle(QtGui.QWidget): def __init__(self, parent): @@ -126,6 +152,7 @@ class MainWindow(QtGui.QMainWindow): self.sendMessageButton = QtGui.QPushButton(Form) self.sendMessageButton.setGeometry(QtCore.QRect(440, 10, 51, 131)) self.sendMessageButton.setObjectName("sendMessageButton") + self.sendMessageButton.clicked.connect(self.send_message) self.screenshotButton.setText(QtGui.QApplication.translate("Form", "Screenshot", None, QtGui.QApplication.UnicodeUTF8)) self.fileTransferButton.setText(QtGui.QApplication.translate("Form", "File transfer", None, QtGui.QApplication.UnicodeUTF8)) self.sendMessageButton.setText(QtGui.QApplication.translate("Form", "Send", None, QtGui.QApplication.UnicodeUTF8)) @@ -148,7 +175,7 @@ class MainWindow(QtGui.QMainWindow): Form.resize(500, 300) Form.setMinimumSize(QtCore.QSize(250, 100)) Form.setMaximumSize(QtCore.QSize(250, 100)) - Form.setBaseSize(QtCore.QSize(2500, 100)) + Form.setBaseSize(QtCore.QSize(250, 100)) self.graphicsView = QtGui.QGraphicsView(Form) self.graphicsView.setGeometry(QtCore.QRect(10, 20, 64, 64)) self.graphicsView.setMinimumSize(QtCore.QSize(64, 64)) @@ -201,16 +228,36 @@ class MainWindow(QtGui.QMainWindow): self.callButton = QtGui.QPushButton(Form) self.callButton.setGeometry(QtCore.QRect(380, 30, 98, 27)) self.callButton.setObjectName("callButton") - self.account_name.setText(QtGui.QApplication.translate("Form", "TextLabel", None, QtGui.QApplication.UnicodeUTF8)) - self.account_status.setText(QtGui.QApplication.translate("Form", "TextLabel", None, QtGui.QApplication.UnicodeUTF8)) self.callButton.setText(QtGui.QApplication.translate("Form", "Start call", None, QtGui.QApplication.UnicodeUTF8)) QtCore.QMetaObject.connectSlotsByName(Form) + def setup_left_bottom(self, widget): + # widget.setFixedWidth(250) + # widget.setMinimumSize(QtCore.QSize(250, 500)) + # widget.setMaximumSize(QtCore.QSize(250, 500)) + # widget.setBaseSize(QtCore.QSize(250, 500)) + self.friends_list = QtGui.QListWidget(widget) + self.friends_list.setGeometry(0, 0, 250, 300) + count = self.tox.self_get_friend_list_size() + widgets = [] + for i in xrange(count): + item = ContactItem() + elem = QtGui.QListWidgetItem(self.friends_list) + print item.sizeHint() + elem.setSizeHint(QtCore.QSize(250, 50)) + self.friends_list.addItem(elem) + self.friends_list.setItemWidget(elem, item) + widgets.append(item) + self.profile = Profile(self.tox, widgets, None) + self.friends_list.clicked.connect(self.friend_click) + def initUI(self): + self.setMinimumSize(800, 400) + self.setGeometry(400, 400, 800, 400) + self.setWindowTitle('Toxygen') main = QtGui.QWidget() grid = QtGui.QGridLayout() search = QtGui.QWidget() - grid.setColumnStretch(1, 1) self.setup_left_center(search) grid.addWidget(search, 1, 0) name = QtGui.QWidget() @@ -222,12 +269,14 @@ class MainWindow(QtGui.QMainWindow): message = QtGui.QWidget() self.setup_right_bottom(message) grid.addWidget(message, 2, 1) + main_list = QtGui.QWidget() + self.setup_left_bottom(main_list) + grid.addWidget(main_list, 2, 0) + grid.setColumnMinimumWidth(1, 500) + grid.setColumnMinimumWidth(0, 250) main.setLayout(grid) self.setCentralWidget(main) self.setup_menu(self) - self.setMinimumSize(800, 400) - self.setGeometry(400, 400, 800, 400) - self.setWindowTitle('Toxygen') def mouseReleaseEvent(self, event): pass @@ -238,6 +287,7 @@ class MainWindow(QtGui.QMainWindow): # self.connection_status.repaint() def setup_info_from_tox(self): + # TODO: remove - use Profile() self.name.setText(self.tox.self_get_name()) self.status_message.setText(self.tox.self_get_status_message()) @@ -276,6 +326,28 @@ class MainWindow(QtGui.QMainWindow): self.int_s = InterfaceSettings() self.int_s.show() +# ----------------------------------------------------------------------------------------------------------------- +# Messages +# ----------------------------------------------------------------------------------------------------------------- + + def send_message(self): + text = self.messageEdit.toPlainText() + if self.profile.isActiveOnline() and text: + num = self.profile.getActiveNumber() + self.tox.friend_send_message(num, TOX_MESSAGE_TYPE['NORMAL'], text) + +# ----------------------------------------------------------------------------------------------------------------- +# Functions which called when user click somewhere else +# ----------------------------------------------------------------------------------------------------------------- + + def friend_click(self, index): + print 'row:', index.row() + num = index.row() + self.profile.setActive(num) + friend = self.profile.friends[num] + self.account_name.setText(friend.name) + self.account_status.setText(friend.status_message) + if __name__ == '__main__': app = QtGui.QApplication(sys.argv) diff --git a/src/notifications.py b/src/notifications.py index 9f621f1..57fc395 100644 --- a/src/notifications.py +++ b/src/notifications.py @@ -10,5 +10,5 @@ def tray_notification(title, text): tray.setContextMenu(QtGui.QMenu()) tray.show() if len(text) > 30: - text = text[:30] + '...' + text = text[:27] + '...' tray.showMessage(title, text, QtGui.QSystemTrayIcon.NoIcon, 3000) diff --git a/src/profile.py b/src/profile.py index 5480f89..7c55c31 100644 --- a/src/profile.py +++ b/src/profile.py @@ -1,11 +1,12 @@ from settings import Settings import os from tox import Tox +from util import Singleton from toxcore_enums_and_consts import * from ctypes import * -class Profile(object): +class ProfileHelper(object): @staticmethod def find_profiles(): @@ -26,22 +27,112 @@ class Profile(object): @staticmethod def open_profile(path, name): - Profile._path = path + name + '.tox' - with open(Profile._path, 'rb') as fl: + ProfileHelper._path = path + name + '.tox' + with open(ProfileHelper._path, 'rb') as fl: data = fl.read() if data: - print 'Data loaded from: {}'.format(Profile._path) + print 'Data loaded from: {}'.format(ProfileHelper._path) return data else: - raise IOError('Save file not found. Path: {}'.format(Profile._path)) + raise IOError('Save file not found. Path: {}'.format(ProfileHelper._path)) @staticmethod def save_profile(data, name=None): if name is not None: - Profile._path = Settings.get_default_path() + name + '.tox' - with open(Profile._path, 'wb') as fl: + ProfileHelper._path = Settings.get_default_path() + name + '.tox' + with open(ProfileHelper._path, 'wb') as fl: fl.write(data) - print 'Data saved to: {}'.format(Profile._path) + print 'Data saved to: {}'.format(ProfileHelper._path) + + +class Contact(object): + + def __init__(self, name, status_message, number, widget): + self._name, self._status_message, self._number = name, status_message, number + self._status, self._widget = None, widget + widget.name.setText(name) + widget.status_message.setText(status_message) + + def getName(self): + return self._name + + def setName(self, value): + self._name = value + self._widget.name.setText(value) + + name = property(getName, setName) + + def getStatusMessage(self): + return self._status_message + + def setStatusMessage(self, value): + self._status_message = value + self._widget.status.setText(value) + + status_message = property(getStatusMessage, setStatusMessage) + + def getStatus(self): + return self._status + + def setStatus(self, value): + self._status = value + + status = property(getStatus, setStatus) + + +class Friend(Contact): + + def __init__(self, *args): + super(Friend, self).__init__(*args) + self._new_messages = False + + def setVisibility(self, value): + self._widget.setVisibility(value) + + def setMessages(self, value): + self._new_messages = value + + messages = property(None, setMessages) + + def getNumber(self): + return self._number + + number = property(getNumber) + + +class Profile(Contact, Singleton): + + def __init__(self, tox, widgets, widget): + self._widget = widget + self.tox = tox + data = tox.self_get_friend_list() + self.friends, num, self._active_friend = [], 0, -1 + for i in data: + name = tox.friend_get_name(i) + status_message = tox.friend_get_status_message(i) + self.friends.append(Friend(name, status_message, i, widgets[num])) + num += 1 + + def getActive(self): + return self._active_friend + + def setActive(self, value): + if 0 <= value < self.tox.self_get_friend_list_size(): + self._active_friend = value + + active_friend = property(getActive, setActive) + + def getActiveNumber(self): + return self.friends[self._active_friend].getNumber() + + def isActiveOnline(self): + if not self._active_friend + 1: # no active friend + return False + else: + # TODO: callbacks! + return True + status = self.friends[self._active_friend].getStatus() + return status is not None def tox_factory(data=None, settings=None): diff --git a/src/util.py b/src/util.py index a49bd5e..fe2ca40 100644 --- a/src/util.py +++ b/src/util.py @@ -23,7 +23,7 @@ def curr_directory(): class Singleton(object): - def __new__(cls): + def __new__(cls, *args): if not hasattr(cls, 'instance'): - cls.instance = super(Singleton, cls).__new__(cls) + cls.instance = super(Singleton, cls,).__new__(cls, *args) return cls.instance diff --git a/tests/tests.py b/tests/tests.py index ea8ad30..a7e087b 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -2,7 +2,7 @@ from src.settings import Settings from src.util import bin_to_string, string_to_bin import sys from src.bootstrap import node_generator -from src.profile import Profile, tox_factory +from src.profile import ProfileHelper, tox_factory import os @@ -23,17 +23,17 @@ class TestSettings(): class TestProfile(): def test_search(self): - arr = Profile.find_profiles() + arr = ProfileHelper.find_profiles() assert arr def test_open(self): - data = Profile.open_profile(Settings.get_default_path(), 'tox_save') + data = ProfileHelper.open_profile(Settings.get_default_path(), 'tox_save') assert data def test_open_save(self): - data = Profile.open_profile(Settings.get_default_path(), 'tox_save') - Profile.save_profile(data) - new_data = Profile.open_profile(Settings.get_default_path(), 'tox_save') + data = ProfileHelper.open_profile(Settings.get_default_path(), 'tox_save') + ProfileHelper.save_profile(data) + new_data = ProfileHelper.open_profile(Settings.get_default_path(), 'tox_save') assert new_data == data @@ -60,7 +60,7 @@ class TestNodeGen(): class TestTox(): def test_loading(self): - data = Profile.open_profile(Settings.get_default_path(), 'tox_save') + data = ProfileHelper.open_profile(Settings.get_default_path(), 'tox_save') settings = Settings.get_default_settings() tox = tox_factory(data, settings) for data in node_generator(): @@ -68,9 +68,11 @@ class TestTox(): del tox def test_friend_list(self): - data = Profile.open_profile(Settings.get_default_path(), 'tox_save') + data = ProfileHelper.open_profile(Settings.get_default_path(), 'tox_save') settings = Settings.get_default_settings() tox = tox_factory(data, settings) s = tox.self_get_friend_list() + size = tox.self_get_friend_list_size() + assert size assert s del tox