Esempio n. 1
0
class Modal(Window):

    MODAL_WIDTH = 640
    MODAL_HEIGHT = 480

    def __init__(self,
                 root,
                 title,
                 buttons: dict = None,
                 width=MODAL_WIDTH,
                 height=MODAL_HEIGHT,
                 **args):
        Window.__init__(self, root, title, width, height, **args)

        # Header
        self.frm_header = Frame(self, bg=white, padx=20, pady=20)
        self.frm_header.pack(side=TOP, fill=X)
        self.lbl_title = Label(self.frm_header,
                               text=title,
                               bg=white,
                               fg=black,
                               font='-size 20 -weight bold')
        self.lbl_title.pack(side=LEFT)
        self.btn_close = IconFrame(self.frm_header,
                                   'resources/icons/ui/cancel.png', 10, black,
                                   50, lambda e: self.destroy(), danger)
        self.btn_close.pack(side=RIGHT)
        self.frm_header.update()

        # Header Bottom Border
        self.frm_border_bottom = Frame(self,
                                       highlightthickness=1,
                                       highlightbackground=border)
        self.frm_border_bottom.pack(side=TOP, fill=X)

        # Body
        self.frm_body = Frame(self, bg=background, padx=30, pady=30)
        self.frm_body.pack(side=TOP, fill=BOTH)

        # Footer
        self.frm_footer = Frame(self, bg=silver, padx=15, pady=15)
        self.frm_footer.pack(side=BOTTOM, fill=X)

        if buttons != None:
            for button in buttons:
                btn = (DangerButton if button.get('mode', 'main') == 'danger'
                       else MainButton)(self.frm_footer,
                                        button.get('text', 'Text'),
                                        button.get('icon', 'error.png'),
                                        button.get('cmnd', None))
                btn.pack(side=RIGHT, padx=(10, 0))

        # Footer Bottom Border
        self.frm_border_top = Frame(self,
                                    highlightthickness=1,
                                    highlightbackground=border)
        self.frm_border_top.pack(side=BOTTOM, fill=X)

        self.grab_set_global()
        self.resizable(False, False)
Esempio n. 2
0
class TextBox(Frame, Animatable):
    def __init__(self, master, iconPath, **args):
        Frame.__init__(self, master, **args)

        self.configure(bg=black, pady=3)

        self.icon = IconFrame(self, iconPath, 15, black, 40, bg=black)
        self.icon.pack(side=LEFT)

        self.entry = Entry(self,
                           relief=FLAT,
                           font='-size 12 -weight bold',
                           bd=5,
                           fg=black)
        self.entry.pack(side=LEFT, fill=BOTH, expand=1, padx=(0, 3))

        Animatable.__init__(self)

    def get_text(self):
        return str(self.entry.get()).lstrip(' ').rstrip(' ')

    def clear(self):
        self.entry.delete(0, len(self.entry.get()))

    def bind_events(self):
        self.entry.bind('<FocusIn>', lambda e: self.onEnter())
        self.entry.bind('<FocusOut>', lambda e: self.onLeave())

    def changeFocusColor(self, color):
        self.stop_transitions()

        def _set(v):
            self['bg'] = v

        _get = lambda: self['bg']

        def _set1(v):
            self.icon['bg'] = v

        _get1 = lambda: self.icon['bg']

        def _set2(v):
            self.entry['fg'] = v

        _get2 = lambda: self.entry['fg']

        self.icon.set_bgColor(color)
        self.save_transition(ColorTransition(_set, _get, color))
        self.save_transition(ColorTransition(_set1, _get1, color))
        self.save_transition(ColorTransition(_set2, _get2, color))

    def onEnter(self):
        self.changeFocusColor(teal)

    def onLeave(self):
        self.changeFocusColor(black)
Esempio n. 3
0
    def __init__(self,
                 root,
                 title: str,
                 message: str,
                 messageType: str = 'error',
                 actions: dict = None,
                 **args):

        # Prepare modal buttons
        buttons = [{
            'text': 'Okay',
            'icon': 'yes.png',
            'cmnd': lambda e: self.destroy()
        }]

        if actions != None:
            buttons = [{
                'text': 'No',
                'icon': 'no.png',
                'cmnd': actions.get('no', lambda e: self.destroy()),
                'mode': 'danger'
            }, {
                'text': 'Yes',
                'icon': 'yes.png',
                'cmnd': actions.get('yes', None)
            }]

        Modal.__init__(self, root, title, buttons, self.MODAL_WIDTH, 345,
                       **args)

        color = black if messageType == self.PROMPT else (
            teal if messageType == self.INFO else danger)

        img_icon = IconFrame(self.frm_body,
                             'resources/icons/ui/' + messageType + '.png', 6,
                             color, 75)
        img_icon.pack(side=LEFT)

        lbl_message = Label(self.frm_body,
                            text=message,
                            bg=background,
                            fg=color,
                            font='-size 15 -weight bold',
                            justify=LEFT,
                            wraplength=self.MODAL_WIDTH - 150)
        lbl_message.pack(side=LEFT, padx=(10, 0))
Esempio n. 4
0
class ListItem(Frame):
    
    def __init__(self, master, dataObject, bindings, buttons, creationMethod = None, **args):
        Frame.__init__(self, master, **args)

        self.buttons = []
        self.dataObject = dataObject
        self.bindings = bindings
        self.buttonSettings = buttons
        self.creationMethod = creationMethod

        (ListItem.create if creationMethod == None else creationMethod)(self)

    def create(item):
        self = item

        # binding values
        username = '******' if self.bindings == None else self.bindings.get('username', '{username}')

        self.configure(padx=10, pady=10, relief=SOLID, highlightthickness=1, highlightbackground=border, bg=white)

        self.img_icon = IconFrame(self, self.bindings.get('image') if self.bindings.get('image') != None else 'resources/icons/ui/face.png', 0, black, 40, highlightbackground=border, highlightthickness=1)
        self.img_icon.pack(side=LEFT)

        self.lbl_username = Label(self, text=username, bg=white, font='-size 12 -weight bold', fg=black)
        self.lbl_username.pack(side=LEFT, fill=Y, padx=5)

        def correct(call, obj):
            return lambda e: call(obj)

        if self.buttonSettings != None:
            for s in self.buttonSettings:
                path = 'resources/icons/ui/' + s.get('icon', 'error.png')
                btn = IconButton(self, s.get('text', 'Button Text'), '-size 10 -weight bold', teal, path, 15, {'fg': white, 'bg': teal}, teal, 30, correct(s.get('cmd', None), self.dataObject), bg=white, highlightthickness=1, highlightbackground=border, padx=7, pady=5)
                btn.pack(side=RIGHT, padx=(0, 5))
                self.buttons.append(btn)
Esempio n. 5
0
class SessionWindow(Window):

    # Chat Session Item Styles
    CHAT_NORMAL = {
        'bg': white,
        'lbl_username': teal,
        'lbl_user': black,
        'lbl_content': black,
        'lbl_time': gray 
    }
    CHAT_UNREAD = {
        'bg': teal,
        'lbl_username': white,
        'lbl_user': background,
        'lbl_content': background,
        'lbl_time': background 
    }

    # BOOKMARK_TOCHANGE: make it None
    ACTIVE_USER = None

    def __init__(self, root, title='Welcome', width=Window.DEFAULT_WIDTH, height=Window.DEFAULT_HEIGHT, **args):
        Window.__init__(self, root, title, width, height)
        
        if SessionWindow.ACTIVE_USER == None: SessionWindow.ACTIVE_USER = args.get('user', None)

        self.frm_rSection = Frame(self, bg=background)
        self.frm_rSection.pack_propagate(0)
        
        self.frm_vBar = Frame(self, bg=black, padx=15, pady=15)
        self.frm_hBar = Frame(self.frm_rSection, bg=white, padx=20, pady=20)
        self.frm_hBarBorder = Frame(self.frm_rSection, height=1, bg=border)
        self.frm_body = Frame(self.frm_rSection, bg=background, padx=30, pady=30)

        self.frm_body.pack_propagate(0)
        self.frm_body.grid_propagate(0)

        self.frm_rSection.pack(side=RIGHT, fill=BOTH, expand=1)
        self.frm_vBar.pack(side=LEFT, fill=Y)
        self.frm_hBar.pack(side=TOP, fill=X)
        self.frm_hBarBorder.pack(side=TOP, fill=X)
        self.frm_body.pack(side=BOTTOM, expand=1, fill=BOTH)

        # vbar buttons
        self.vBarButtons = {}

        # Set up the bars
        self.config_vBar()
        self.config_hBar()

        self.created_notif_items = []


    def runnable(self):
        try:
            while self.time_to_kill != True:
                Container.threadSession.flush()
                # declaration of 
                noNewNotifs, noNewMessages = True, True
                # check for new unseen notifications
                unseen_notifs = Container.threadSafeFilter(Notification,Notification.recipient == SessionWindow.ACTIVE_USER, Notification.id.notin_(Container.threadSafeFilter(SeenNotification.notificationId.distinct()))).all()
                for notif in unseen_notifs:
                    if Container.threadSafeFilter(SeenNotification, SeenNotification.notificationId == notif.id, SeenNotification.seerId == SessionWindow.ACTIVE_USER.id).first() == None: 
                        self.icn_notification.set_image('resources/icons/ui/bell_ring.png')
                        self.lbl_notif_counter['fg'] = teal
                        self.lbl_notif_counter['text'] = str(len(unseen_notifs))
                        noNewNotifs = False
                        break
                # change the icon if there is no new notifications
                if noNewNotifs: 
                    self.icn_notification.set_image('resources/icons/ui/bell_outline.png')
                    self.lbl_notif_counter['text'] = '0'
                    self.lbl_notif_counter['fg'] = black
                # check for new unseen messages
                if len (self.getUnreadMessages()) > 0:
                    self.icn_discussion.set_image('resources/icons/ui/discussion.png')
                    self.lbl_discus_counter['fg'] = teal
                    self.lbl_discus_counter['text'] = str (len (self.getUnreadMessages()))
                    noNewMessages = False
                # change the icon if there is no new messages
                if noNewMessages: 
                    self.icn_discussion.set_image('resources/icons/ui/discussion_outline.png')
                    self.lbl_discus_counter['text'] = '0'
                    self.lbl_discus_counter['fg'] = black
                # wait for the next frame
                time.sleep(5)
        except: pass
        
    def hide(self):
        # thread killer logic will be here
        self.time_to_kill = True
        # continute the original work
        super().hide()

    def refresh(self): # this should run 
        self.time_to_kill = False
        # start thread
        threading.Thread(target=self.runnable).start()

    def change_session_item_style(self, item, style=CHAT_UNREAD):
        # Change background
        for w in [item, item.frm_content, item.lbl_username, item.lbl_user, item.lbl_content, item.lbl_time, item.img_photo]:
            w.config(bg=style['bg'])
        # Change foreground
        for i in style.keys():
            if hasattr(item, i):
                getattr(item, i).config(fg=style[i])

    def configure_msg_listitem(self, root, item):
        li = ListItemFactory.DiscussionListItem(root, item)
        # set message listItem click
        for c in [li, li.frm_content, li.lbl_username, li.lbl_user, li.lbl_content, li.lbl_time, li.img_photo]:
            c.bind('<Button-1>', lambda e: self.windowManager.run_tag('discussion',session= item.session))
        # change style for unread messages
        if item.user != self.ACTIVE_USER and Container.filter(SeenMessage, SeenMessage.messageId == item.id,SeenMessage.seerId == SessionWindow.ACTIVE_USER.id).first() == None:
            self.change_session_item_style(li,self.CHAT_UNREAD)
        # return list item
        return li

    def configure_notif_listitem(self, root, item):
        li= ListItemFactory.NotificationListItem(root, item)
        li.window = self
        # save notification that are not recieveInv as seen 
        if item.type != NotificationType.INVITED.value and Container.filter(SeenNotification, SeenNotification.notificationId == item.id, SeenNotification.seerId == SessionWindow.ACTIVE_USER.id).first() == None: 
                Container.save(SeenNotification(date= datetime.datetime.now(), seer= SessionWindow.ACTIVE_USER, notification= item))
        # append this item to a list
        self.created_notif_items.append (li)
        # return 
        return li

    def clean_notifications(self):
        notifs = Container.filter(Notification)
        for notif in notifs:
            if notif.nature == NotificationNature.INV.value and Container.filter(Invitation, Invitation.id == notif.invitationId).first() == None:
                Container.deleteObject(notif)
            elif notif.nature == NotificationNature.INVLINK.value:
                invitationLink = Container.filter(InvitationLink, InvitationLink.id == notif.invitationId).first()
                if invitationLink == None or Container.filter(Collaboration, Collaboration.sessionId == invitationLink.sessionId, Collaboration.userId == notif.actorId).first() == None: Container.deleteObject(notif)
            elif notif.nature == NotificationNature.SHARELINK.value and Container.filter(ShareLink, ShareLink.id == notif.invitationId).first() == None:
                Container.deleteObject(notif)
            
    def config_vBar(self):
        
        def callback(tag):
            return lambda e: self.windowManager.run_tag(tag)

        for i in SessionWindow.vBarSettings:
            # retrieve callable
            cb = callback(i.get('dest'))
            # instantiate button
            btn = IconButton(self.frm_vBar, i.get('text', 'Icon Button'), '-size 11 -weight bold', white, f'resources/icons/ui/{i["icon"]}', 0, None, black, 32, cb, bg=black, pady=10)
            btn.label.pack_forget()
            btn.pack(side=i.get('dock', TOP), fill=X)
            # save button
            self.vBarButtons[i.get('name')] = btn

        def quit():
            self.time_to_kill = True
            self.windowManager.run_tag('sign')
            SessionWindow.ACTIVE_USER = None

            # self.windowManager.quit()

        self.vBarButtons['btn_quit'].bind_click(lambda e: quit() )

    def getLastMessages(self):
        msgs = []
        for i in Container.filter(Session):
            if i.owner == SessionWindow.ACTIVE_USER or Container.filter(Collaboration, Collaboration.userId == SessionWindow.ACTIVE_USER.id, Collaboration.sessionId == i.id).first() != None:
                msg = Container.filter(Message, Message.sessionId == i.id).order_by(Message.sentDate.desc()).first()
                if msg != None: msgs.append(msg)
        # make the order key
        def orderKey (e): return e.sentDate
        # sort
        msgs.sort(key=orderKey, reverse=True)
        # return
        return msgs

    def getUnreadMessages(self):
        # first we will get the sessions that this user
        # has collaborated in
        sessions = [] 
        # search for collaborations
        for c in Container.filter(Collaboration, Collaboration.userId == SessionWindow.ACTIVE_USER.id):
            sessions.append(c.sessionId)
        # search for owned sessions
        for s in Container.filter(Session, Session.ownerId == SessionWindow.ACTIVE_USER.id):
            sessions.append(s.id)
        # retrieve all received messages
        allmsgs = []
        for s in sessions:
            for m in Container.filter(Message, Message.sessionId == s):
                if m not in allmsgs and m != None:
                    allmsgs.append(m)
        # retrieve seen messages
        seenmsgs = []
        for m in allmsgs:
            if m.userId == SessionWindow.ACTIVE_USER.id:
                seenmsgs.append(m)
            elif len(Container.filter(SeenMessage, SeenMessage.messageId == m.id, SeenMessage.seerId == SessionWindow.ACTIVE_USER.id).all()) > 0:
                seenmsgs.append(m)
        # retrieve unseen messages
        unseenmsgs = []
        for m in allmsgs:
            if m not in seenmsgs:
                unseenmsgs.append(m)
        # return
        return unseenmsgs

    def config_hBar(self):
        # Creation of elements
        # BOOKMARK_DONE: change user profile image
        self.clean_notifications()
        # username
        self.btn_username = IconButton(self.frm_hBar, SessionWindow.ACTIVE_USER.userName, '-size 15', biege, 'resources/icons/ui/face.png' if SessionWindow.ACTIVE_USER.image == None else SessionWindow.ACTIVE_USER.image, 6, None, biege, 40, lambda e: self.windowManager.run_tag('profile'), bg=white)
        # bell icon
        self.icn_notification = IconFrame(
            self.frm_hBar, 'resources/icons/ui/bell_outline.png', 0, None, 32,
            lambda e: self.show_popup(
                self.to_window_coords(e.x_root, e.y_root)[0] - 360,
                self.to_window_coords(e.x_root, e.y_root)[1] + 20,
                # BOOKMARK_DONE: notification data list
                Container.filter(Notification,Notification.recipient == SessionWindow.ACTIVE_USER, Notification.id.notin_(Container.filter(SeenNotification.notificationId.distinct(), SeenNotification.notificationId == Notification.id, Notification.type == NotificationType.INVITED.value))).all(), 
                self.configure_notif_listitem
            )
        )
        # discussion icon
        self.icn_discussion = IconFrame(
            self.frm_hBar, 'resources/icons/ui/discussion_outline.png', 0, None, 32,
            lambda e: self.show_popup(
                self.to_window_coords(e.x_root, e.y_root)[0] - 360, 
                self.to_window_coords(e.x_root, e.y_root)[1] + 20, 
                # BOOKMARK_DONE: discussion data list
                # Container.filter(Message,Message.sessionId == Collaboration.sessionId,or_(Collaboration.userId == SessionWindow.ACTIVE_USER.id, and_(Message.sessionId == Session.id, Session.ownerId == SessionWindow.ACTIVE_USER.id) ),Message.sentDate.in_(Container.filter(func.max(Message.sentDate)).group_by(Message.sessionId))).group_by(Message.sessionId).all(), 
                self.getLastMessages(),
                self.configure_msg_listitem
            )
        )
        # notification counter label
        self.lbl_notif_counter = Label(self.frm_hBar, fg=black, bg=white, text='0', font='-weight bold -size 9')
        self.lbl_discus_counter = Label(self.frm_hBar, fg=black, bg=white, text='0', font='-weight bold -size 9')
        # Positioning elements
        self.btn_username.pack(side=LEFT)
        self.lbl_notif_counter.pack(side=RIGHT)
        self.icn_notification.pack(side=RIGHT)
        self.lbl_discus_counter.pack(side=RIGHT)
        self.icn_discussion.pack(side=RIGHT, padx=(0, 5))

    # Vertical Bar Settings
    vBarSettings = [
        {
            'name': 'btn_home',
            'icon': 'home.png',
            'text': 'Home',
            'dest': 'home'
        },
        {
            'name': 'btn_discussion',
            'icon': 'discussion_original.png',
            'text': 'Discussions',
            'dest': 'discussion'
        },
        {
            'name': 'btn_profile',
            'icon': 'settings.png',
            'text': 'Settings',
            'dest': 'profile'
        },
        {
            'name': 'btn_quit',
            'icon': 'logout.png',
            'text': 'Sign Out',
            'dest': None,
            'dock': BOTTOM
        }
    ]
Esempio n. 6
0
class IconButton(Frame, Animatable):
    def __init__(self,
                 master,
                 text,
                 textFont,
                 textColor,
                 imagePath,
                 imageScale,
                 hoverEff: dict,
                 imgBgColor=None,
                 imgSize=50,
                 btnCommand=None,
                 **args):
        Frame.__init__(self, master, **args)
        Animatable.__init__(self)

        self.hover_theme = hoverEff
        # Create the icon
        self.icon = IconFrame(self, imagePath, imageScale, imgBgColor, imgSize)
        self.icon.pack(side=LEFT)
        # Create the label
        self.label = Label(self,
                           text=text,
                           font=textFont,
                           fg=textColor,
                           bg=self['bg'])
        self.label.pack(side=LEFT, padx=5)
        # Save the initial theme
        self.theme = {'bg': self['bg'], 'fg': textColor}
        # Bind click event
        if btnCommand != None:
            self.bind_click(btnCommand)

    def bind_click(self, command):
        def prepareCommand(e):
            # Invoke command
            command(e)

        self.bind('<Button-1>', prepareCommand)
        self.label.bind('<Button-1>', prepareCommand)
        self.icon.bind('<Button-1>', prepareCommand)

    def onEnter(self):
        if self.hover_theme == None:
            return

        Animatable.onEnter(self)

        def set1(v):
            self['bg'] = v

        def set2(v):
            self.label['bg'] = v

        def set3(v):
            self.icon['bg'] = v

        def set4(v):
            self.label['fg'] = v

        get1 = lambda: self['bg']
        get2 = lambda: self.label['bg']
        get3 = lambda: self.icon['bg']
        get4 = lambda: self.label['fg']

        self.save_transition(
            ColorTransition(set1, get1, self.hover_theme['bg']))
        self.save_transition(
            ColorTransition(set2, get2, self.hover_theme['bg']))
        self.save_transition(
            ColorTransition(set3, get3, self.hover_theme['bg']))
        self.save_transition(
            ColorTransition(set4, get4, self.hover_theme['fg']))

        if 'config' in self.hover_theme:
            self.configure(**self.hover_theme['config'])

    def onLeave(self):
        if self.hover_theme == None:
            return

        self.temp_theme = self.hover_theme
        self.hover_theme = self.theme
        self.onEnter()
        self.hover_theme = self.temp_theme