Esempio n. 1
0
class UsersTab(RPCBase):
    def __init__(self,app):
        global gw
        self.app=app
        self.vpanel = VerticalPanel()
        self.vpanel.setWidth("100%")
        self.table = FlexTable()
        self.table.setHTML(0, 0, "<b>ID</b>")
        self.table.setHTML(0, 1, "<b>Handle</b>")
        self.table.setHTML(0, 2, "<b>Name</b>")
        self.vpanel.add(self.table)
        if self.app.admin:
            self.btn = Button("Create User",self.createUser)
            self.vpanel.add(self.btn)
        self.cnt = 1
        gw.listUsers(self)

    def reload(self):
        global gw
        gw.listUsers(self)

    def createUser(self,_):
        UserTab(self.app, -1)

    def userLambda(self,uid):
        return lambda: UserTab(self.app, uid)

    def getRoot(self):
        return self.vpanel

    def onRemoteResponse(self, response, request_info):
        while self.cnt > 1:
            self.cnt -= 1
            self.table.removeRow(self.cnt)

        for line in response:
            l=Hyperlink(line[0])
            l.addClickListener(self.userLambda(line[0]));
            self.table.setWidget(self.cnt, 0, l)
            l=Hyperlink(line[1])
            l.addClickListener(self.userLambda(line[0]));
            self.table.setWidget(self.cnt, 1, l)
            l=Hyperlink(line[2])
            l.addClickListener(self.userLambda(line[0]));
            self.table.setWidget(self.cnt, 2, l)
            self.cnt += 1       
Esempio n. 2
0
class StockWatcher:
    def onModuleLoad(self):
        '''
        This is the main entry point method.
        '''
        
        # Setup JSON RPC
        self.remote = DataService()
        
        # Initialize member variables
        self.mainPanel = VerticalPanel()
        self.stocksFlexTable = FlexTable()
        self.addPanel = HorizontalPanel()
        self.newSymbolTextBox = TextBox()
        self.lastUpdatedLabel = Label()
        self.addStockButton = Button('Add', self.addStock)
        self.stocks = []
        self.stocksTableColumns = ['Symbol', 'Price', 'Change', 'Remove']
        
        # Add styles to elements in the stock list table
        self.stocksFlexTable.getRowFormatter().addStyleName(0, 'watchListHeader')
        self.stocksFlexTable.addStyleName('watchList')
        self.stocksFlexTable.getCellFormatter().addStyleName(0, 1, 'watchListNumericColumn')
        self.stocksFlexTable.getCellFormatter().addStyleName(0, 2, 'watchListNumericColumn')
        self.stocksFlexTable.getCellFormatter().addStyleName(0, 3, 'watchListRemoveColumn')
        
        # Create table for stock data
        for i in range(len(self.stocksTableColumns)):
            self.stocksFlexTable.setText(0, i, self.stocksTableColumns[i])
        
        # Assemble Add Stock panel
        self.addPanel.add(self.newSymbolTextBox)
        self.addPanel.add(self.addStockButton)
        self.addPanel.addStyleName('addPanel')
        
        # Assemble Main panel
        self.mainPanel.add(self.stocksFlexTable)
        self.mainPanel.add(self.addPanel)
        self.mainPanel.add(self.lastUpdatedLabel)
        
        # Associate the Main panel with the HTML host page
        RootPanel().add(self.mainPanel)
        
        # Move cursor focus to the input box
        self.newSymbolTextBox.setFocus(True)
        
        # Setup timer to refresh list automatically
        refresh = self.refreshWatchlist
        class MyTimer(Timer):
            def run(self):
                refresh()
        refreshTimer = MyTimer()
        refreshTimer.scheduleRepeating(5000)
        
        # Listen for keyboard events in the input box
        self_addStock = self.addStock
        class StockTextBox_KeyboardHandler():
            def onKeyPress(self, sender, keycode, modifiers):
                if keycode == KEY_ENTER:
                    self_addStock()
            def onKeyDown(self, sender, keycode, modifiers): return
            def onKeyUp(self, sender, keycode, modifiers): return
        self.newSymbolTextBox.addKeyboardListener(StockTextBox_KeyboardHandler())
        
        # Load the stocks
        self.remote.getStocks(self)
    
    def addStock(self, sender, symbol=None):
        '''
        Add stock to FlexTable. Executed when the user clicks the addStockButton
        or presses enter in the newSymbolTextBox
        '''
        
        if symbol is None:
            # Get the symbol
            symbol = self.newSymbolTextBox.getText().upper().trim()
            self.newSymbolTextBox.setText('')
            # Don't add the stock if it's already in the table
            if symbol in self.stocks:
                return
            # Tell the server that we're adding this stock
            self.remote.addStock(symbol, self)
            self.newSymbolTextBox.setFocus(True)
            # Stocks code must be between 1 and 10 chars that are numbers/letters/dots
            p = re.compile('^[0-9A-Z\\.]{1,10}$')
            if p.match(symbol) == None:
                Window.alert('"%s" is not a valid symbol.' % symbol)
                self.newSymbolTextBox.selectAll()
                return    
        
        # Add the stock to the table
        row = self.stocksFlexTable.getRowCount()
        self.stocks.append(symbol)
        self.stocksFlexTable.setText(row, 0, symbol)
        self.stocksFlexTable.setWidget(row, 2, Label())
        self.stocksFlexTable.getCellFormatter().addStyleName(row, 1, 'watchListNumericColumn')
        self.stocksFlexTable.getCellFormatter().addStyleName(row, 2, 'watchListNumericColumn')
        self.stocksFlexTable.getCellFormatter().addStyleName(row, 3, 'watchListRemoveColumn')
        
        # Add a button to remove this stock from the table
        def _removeStockButton_Click(event):
            if symbol not in self.stocks:
                return
            removedIndex = self.stocks.index(symbol)
            self.remote.deleteStock(symbol, self)
            self.stocks.remove(symbol)
            self.stocksFlexTable.removeRow(removedIndex + 1)
        removeStockButton = Button('x', _removeStockButton_Click)
        removeStockButton.addStyleDependentName('remove')
        self.stocksFlexTable.setWidget(row, 3, removeStockButton)
        
        # Get the stock price
        self.refreshWatchlist()
    
    def refreshWatchlist(self):
        '''
        Update the price change for each stock
        '''
        
        MAX_PRICE = 100.0
        MAX_PRICE_CHANGE = 0.02
        
        prices = []
        for i in range(len(self.stocks)):
            price = random.random() * MAX_PRICE
            change = price * MAX_PRICE_CHANGE * (random.random() * 2.0 - 1.0)
            prices.append(StockPrice(self.stocks[i], price, change))
        
        self.updateTable(prices)
    
    def updateTable(self, prices):
        '''
        Update the price and change fields of all the rows in the stock table
        
        prices -- List of StockPrice objects for all rows
        '''
        
        # Type checking
        assert isinstance(prices, list)
        for price in prices:
            assert isinstance(price, StockPrice)
        
        # Nothing to do...
        if len(prices) == 0:
            return
        
        # Update each individual row
        for i in range(len(prices)):
            self.updateRow(prices[i])
        
        # Display timestamp showing last refresh
        self.lastUpdatedLabel.setText("Last update: %s" % datetime.datetime.now().strftime("%m/%d/%Y %I:%M:%S %p"))
    
    def updateRow(self, price):
        '''
        Update a single row in the stock table
        
        price -- StockPrice object for a single row
        '''
        
        # Type checking
        assert isinstance(price, StockPrice)
        
        # Make sure the stock is still in the stock table
        if price.symbol not in self.stocks:
            return
        
        # Find the index of 
        row = self.stocks.index(price.symbol) + 1
        
        # Populate the price and change fields with new data
        self.stocksFlexTable.setText(row, 1, '%.2f' % price.price)
        changeWidget = self.stocksFlexTable.getWidget(row, 2)
        changeWidget.setText('%.2f (%.2f%%)' % (price.change, price.getChangePercent()))
        
        # Change the color of the text in the Change field based on its value
        changeStyleName = 'noChange'
        if price.getChangePercent() < -0.1:
            changeStyleName = 'negativeChange'
        else:
            changeStyleName = 'positiveChange'
        
        changeWidget.setStyleName(changeStyleName)
    
    def onRemoteResponse(self, response, request_info):
        '''
        Called when a response is received from a RPC.
        '''
        if request_info.method in DataService.methods:
            # Compare self.stocks and the stocks in response
            stocks_set = set(self.stocks)
            response_set = set(response)
            # Add the differences
            for symbol in list(response_set.difference(stocks_set)):
                self.addStock(None, symbol)
        else:
            Window.alert('Unrecognized JSONRPC method.')
            
    def onRemoteError(self, code, message, request_info):
        Window.alert(message)
Esempio n. 3
0
class AlarmWidget(object):
    weekday_name = { 0: 'Mo', 1: 'Di', 2: 'Mi', 3: 'Do', 4: 'Fr', 5: 'Sa', 6: 'So' }

    def __init__(self):
        self.alarms = Alarms(self)
        self.make_table()
        self.fill_table()
        self.status = Label()
        self.panel = self.make_panel()

    def make_panel(self):
        message = Label(
            'The configuration has been changed.\n'
            'You must apply the changes in order for them to take effect.')
        DOM.setStyleAttribute(message.getElement(), "whiteSpace", 'pre')

        msgbox = Grid(1, 2, StyleName='changes')
        msgbox.setWidget(0, 0, Image('icons/exclam.png'))
        msgbox.setWidget(0, 1, message)
        msgbox.getCellFormatter().setStyleName(0, 0, 'changes-image')
        msgbox.getCellFormatter().setStyleName(0, 1, 'changes-text')

        button = Button('apply changes')
        button.addClickListener(self.apply_clicked)

        self.changes = VerticalPanel()
        self.changes.setHorizontalAlignment('right')
        self.changes.setVisible(False)
        self.changes.add(msgbox)
        self.changes.add(button)

        panel = VerticalPanel()
        panel.setSpacing(10)
        panel.add(self.table)
        panel.add(self.status)
        panel.add(self.changes)

        return panel

    def make_table(self):
        self.table = FlexTable(StyleName='alarms')
        self.table.setBorderWidth(1)
        self.make_header()
        self.make_footer()

    def make_header(self):
        headers = [ 'Time', 'Days', 'Duration' ]
        for col, text in enumerate(headers):
            self.table.setText(0, col, text)
            self.table.getCellFormatter().setStyleName(0, col, 'tablecell header')

    def make_footer(self):
        self.time = {}

        self.time['hour'] = ListBox()
        self.time['hour'].setVisibleItemCount(1)
        for hour in range(24):
            self.time['hour'].addItem('%02d' % hour)
        self.time['hour'].setSelectedIndex(12)

        self.time['minute'] = ListBox()
        self.time['minute'].setVisibleItemCount(1)
        for minute in range(0, 60, 5):
            self.time['minute'].addItem('%02d' % minute)
        self.time['minute'].setSelectedIndex(0)

        time_panel = HorizontalPanel()
        time_panel.setVerticalAlignment('center')
        time_panel.add(self.time['hour'])
        time_panel.add(Label(':'))
        time_panel.add(self.time['minute'])
        self.table.setWidget(1, 0, time_panel)

        weekdays_panel = HorizontalPanel()
        weekdays_panel.setSpacing(5)
        self.weekdays = {}
        for i in range(7):
            self.weekdays[i] = CheckBox(AlarmWidget.weekday_name[i])
            self.weekdays[i].setChecked(i < 6)
            weekdays_panel.add(self.weekdays[i])
        self.table.setWidget(1, 1, weekdays_panel)

        self.duration = ListBox()
        self.duration.setVisibleItemCount(1)
        choices = [ 1, 2, 3, 4, 5, 7, 10, 15, 20, 25, 30, 40, 50, 60 ]
        for seconds in choices:
            self.duration.addItem(
                    '%ds' % seconds if seconds < 60 else '%dm' % (seconds / 60),
                    seconds)
        self.duration.setSelectedIndex(2)
        self.table.setWidget(1, 2, self.duration)

        image = Image('icons/plus.png')
        image.setTitle('add');
        image.addClickListener(self.plus_clicked)
        self.table.setWidget(1, 3, image)

        for col in range(4):
            self.table.getCellFormatter().setStyleName(1, col, 'tablecell noborder')

    def fill_table(self):
        for idx, alarm in enumerate(self.alarms.get()):
            self.add(alarm['time'], alarm['weekdays'], alarm['duration'])

    def add(self, time, weekdays=range(5), duration=3):
        row = self.table.getRowCount()-1
        self.table.insertRow(row)
        self.table.setText(row, 0, time)
        weekdays_str = []
        for weekday in weekdays:
            weekdays_str.append(AlarmWidget.weekday_name[weekday])

        self.table.setText(row, 1, ', '.join(weekdays_str))
        self.table.setText(row, 2, str(duration) + 's')

        image = Image('icons/x.png')
        image.setTitle('delete');
        image.addClickListener(lambda x: self.x_clicked(row-1))
        self.table.setWidget(row, 3, image)

        for col in range(3):
            self.table.getCellFormatter().setStyleName(row, col, 'tablecell')
        self.table.getCellFormatter().setStyleName(row, 3, 'tablecell noborder')

    def remove(self, idx):
        if idx >= 0 and idx < self.table.getRowCount()-2:
            #self.status.setText('removing idx: %d' % idx)
            self.table.removeRow(idx+1)
        else:
            #self.status.setText('tried to remove idx: %d' % idx)
            pass

    def plus_clicked(self):
        self.changes.setVisible(True)
        getSelectedValue = lambda widget: widget.getValue(widget.getSelectedIndex())
        hour = getSelectedValue(self.time['hour'])
        minute = getSelectedValue(self.time['minute'])
        time = '%02d:%02d:%02d' % ( hour, minute, 0 )
        weekdays = [ i for i in range(7) if self.weekdays[i].isChecked() ]
        duration = getSelectedValue(self.duration)

        self.add(time, weekdays, duration)
        self.alarms.add({'time': time, 'weekdays': weekdays, 'duration': duration})

    def x_clicked(self, idx):
        self.changes.setVisible(True)
        self.remove(idx)
        #self.alarms.remove(idx)

    def apply_clicked(self):
        self.alarms.save()
        self.changes.setVisible(False)