Skip to content

Commit

Permalink
pushMsg will now accept a static message index number for an incoming…
Browse files Browse the repository at this point in the history
… message. This means something like the stock ticker can always update message #1 in the queue.  (We don't want it showing old quotes, do we? ;)

Fixed a bug relating to editing selected messages when selecting them with the mouse vs. keyboard.

Added the "Replace" feature so we can finally replace messages in the queue.

Replaced the RSS panel's initialization code in the main file to call the "RSS" library's init_ui() function.  This sets the stage for the standard way to initialize UI panels for this application in the future, assuming I don't rewrite it in C++ in the meantime :-P.

Fixed some of the "hackiness" around the stock quote/RSS module.
  • Loading branch information
mrcity committed Sep 1, 2015
1 parent 7217204 commit cb3e439
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 31 deletions.
56 changes: 35 additions & 21 deletions Python_src/LEDgoesGlobals.py
Expand Up @@ -8,7 +8,10 @@

html = u'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:\'MS Shell Dlg 2\'; font-size:8.25pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">%s</p></body></html>'
initMsgs = [html % '<span style=" color:#808000;"> :: AWAITING MESSAGES </span>']
panelColors = [0x800000, 0x008000]
red = 0x800000
green = 0x008000
yellow = red | green
panelColors = [red, green]

animTuple = None # Tuple containing deques of each band (RGB), themselves containing a matrix of each frame
boards = deque() # Location of boards present in the marquee
Expand All @@ -28,6 +31,7 @@
uiMsgList = 0 # reference to the message list on the UI of "Raw Text"
rowPixels = 7 # how many pixels exist in each row of a 5x7 matrix (hint: 7)
application_path = "" # path to the application executable (not always the cwd)
#plugins = [] # reference to user-defined plugins

# This is the new "password" to get into Command Mode
# It consists of the ASCII for "PassWord" + 0x80 on each letter, plus 0xFF at the end
Expand All @@ -39,31 +43,41 @@ def msgIndexToOverwrite():
global msgToOverwrite
return msgToOverwrite

def pushMsg(source, rawMessage, richMessage, isSticky):
def pushMsg(source, rawMessage, richMessage, isSticky, desiredIndex=None):
global richMsgs, msgLimit, msgToOverwrite, uiMsgList
console.cwrite("Attempting to add message: " + rawMessage)
console.cwrite(richMessage)
# Count how many items exist in the list now
msgList = uiMsgList.findItems('.*', Qt.MatchRegExp)
if len(msgList) >= msgLimit:
# We are at or above our message limit; find one to overwrite
written = False # Keep track of if we've successfully overwritten a message
# Start with the message at index "msgToOverwrite", go to the end of the list, then restart at the beginning
msgIndexes = range(msgToOverwrite, msgLimit) + range(0, msgToOverwrite)
for index in msgIndexes:
if not msgList[index].sticky: # Do not overwrite sticky messages
formattedSource = "[%s]" % source
formattedSource = formattedSource + " sticky" if isSticky else formattedSource
msgList[index].setText("%s %s" % (formattedSource, rawMessage))
msgList[index].formattedText = richMessage
msgList[index].sticky = isSticky
msgToOverwrite = index + 1
written = True
break
if not written:
raise Exception("Could not overwrite any messages; they are all sticky")
if desiredIndex is None:
if len(msgList) >= msgLimit:
# We are at or above our message limit; find one to overwrite
written = False # Keep track of if we've successfully overwritten a message
# Start with the message at index "msgToOverwrite", go to the end of the list, then restart at the beginning
msgIndexes = range(msgToOverwrite, msgLimit) + range(0, msgToOverwrite)
for index in msgIndexes:
if not msgList[index].sticky: # Do not overwrite sticky messages
formattedSource = "[%s]" % source
formattedSource = formattedSource + " sticky" if isSticky else formattedSource
msgList[index].setText("%s %s" % (formattedSource, rawMessage))
msgList[index].formattedText = richMessage
msgList[index].sticky = isSticky
msgToOverwrite = index + 1
written = True
break
if not written:
raise Exception("Could not overwrite any messages; they are all sticky")
else:
# We have not exceeded the maximum message count; add the message to the UI list
RawTextItem(richMessage, source, isSticky, uiMsgList)
else:
# We have not exceeded the maximum message count; add the message to the UI list
RawTextItem(richMessage, source, isSticky, uiMsgList)
# This is the same code as before
formattedSource = "[%s]" % source
formattedSource = formattedSource + " sticky" if isSticky else formattedSource
msgList[desiredIndex].setText("%s %s" % (formattedSource, rawMessage))
msgList[desiredIndex].formattedText = richMessage
msgList[desiredIndex].sticky = isSticky

# Reconstruct the global list by pulling out "formattedText" from the UI list objects
richMsgs = [x.formattedText for x in uiMsgList.findItems('.*', Qt.MatchRegExp)]
return len(uiMsgList.findItems('.*', Qt.MatchRegExp)) - 1
34 changes: 30 additions & 4 deletions Python_src/LEDgoesPCInterface.py
Expand Up @@ -595,17 +595,20 @@ def __init__(self):
self.ui.btnInsertRawTextBefore.clicked.connect(lambda: self.insertMessage(0))
self.ui.btnInsertRawTextAfter.clicked.connect(lambda: self.insertMessage(1))
self.ui.spinMsgLimit.valueChanged.connect(self.updateMsgLimit)
self.ui.rawTextList.itemClicked.connect(self.selectMessageWithMouse)
self.ui.rawTextList.currentItemChanged.connect(self.selectMessageWithKeyboard)
self.ui.btnGreen.clicked.connect(self.setGreen)
self.ui.btnRed.clicked.connect(self.setRed)
self.ui.btnYellow.clicked.connect(self.setYellow)
self.ui.btnPush.clicked.connect(self.pushMessage)
self.ui.btnReplace.clicked.connect(self.replaceMessage)
# Twitter Feed panel
self.ui.btnTwitterAuth.clicked.connect(self.twitterAuth)
self.ui.btnTwitterStream.clicked.connect(self.twitterStream)
# Animation panel
self.ui.btnAnim.clicked.connect(self.showAnimation)
# RSS panel
self.ui.btnGetQuotes.clicked.connect(self.doQuotes)
RSS.init_ui(self)
# Firmware panel
#self.ui.btnShowTestPattern.clicked.connect(lambda: self.showTestPatternOn(self.ui.txtTestOn))
#self.ui.btnShowAllTestPatterns.clicked.connect(lambda: self.showTestPatternOn(64))
Expand Down Expand Up @@ -758,6 +761,16 @@ def insertMessage(self, direction):
def updateMsgLimit(self, event):
globals.msgLimit = event

def selectMessageWithMouse(self, listItem):
self.ui.txtMessage.setText(listItem.formattedText)
self.ui.btnReplace.setEnabled(True)
self.ui.isSticky.setChecked(listItem.sticky)

def selectMessageWithKeyboard(self, newListItem, oldListItem):
self.ui.txtMessage.setText(newListItem.formattedText)
self.ui.btnReplace.setEnabled(True)
self.ui.isSticky.setChecked(listItem.sticky)

def setGreen(self, event):
# Set the rich text editor to write in green and/or set selected text to green
self.ui.txtMessage.setTextColor(Qt.GlobalColor(14))
Expand Down Expand Up @@ -787,6 +800,22 @@ def pushMessage(self, event):
globals.pushMsg("raw-text", self.ui.txtMessage.toPlainText(), self.ui.txtMessage.toHtml(), self.ui.isSticky.isChecked())
self.ui.txtMessage.setText("")

def replaceMessage(self, event):
if self.ui.txtMessage.toPlainText() == "":
msgBox = QMessageBox()
msgBox.setWindowTitle("BriteBlox PC Interface")
msgBox.setText("Error: No empty messages allowed")
msgBox.setInformativeText("You cannot replace a message with an empty message. If you want to delete this message, click \"Delete Selected\".")
msgBox.setStandardButtons(QMessageBox.Ok)
msgBox.setDefaultButton(QMessageBox.Ok)
msgBox.setIcon(QMessageBox.Warning)
ret = msgBox.exec_()
return
# delete the message from the UI list
for SelectedItem in self.ui.rawTextList.selectedItems():
globals.pushMsg("raw-text", self.ui.txtMessage.toPlainText(), self.ui.txtMessage.toHtml(), self.ui.isSticky.isChecked(), SelectedItem)
self.ui.txtMessage.setText("")

def twitterAuth(self, event):
global twitterApi
twitterApi = LEDgoesTwitter.twitterAuth(
Expand Down Expand Up @@ -829,9 +858,6 @@ def showAnimation(self, animFileContainer):
globals.cxn1 = serial.Serial(portName, 9600, timeout=2)
serialWelcome("animation")

def doQuotes(self):
RSS.toggleQuotes(self.ui.txtQuotes.toPlainText())

def selectAllBoards(self, event):
# Just make the box say "All" - the program will pick up on that keyword
self.ui.txtSrcBoard.setPlainText("All")
Expand Down
22 changes: 16 additions & 6 deletions Python_src/LEDgoesRSS.py
Expand Up @@ -12,16 +12,22 @@

setColor = '\n<span style="color:#%s;">'
endColor = '</span>'
red = '800000'
green = '008000'
yellow = '808000'
red = '800000' # TODO: Try to use globals.red instead; convert that into the hex string without 0x in front
green = '008000' # TODO: Ditto...
yellow = '808000' # TODO: Ditto...
counter = 0
stockInstance = None
desiredIndex = None # TODO: Make this a class variable, and prevent the class instance from getting deleted until the user deletes the item in the panel


# Run initialization to connect this module's UI components to the code they are supposed to run
def init_ui(windowInstance):
windowInstance.ui.btnGetQuotes.clicked.connect(lambda: toggleQuotes(windowInstance))

# Handle button click for "Get Quotes" from the main UI
def toggleQuotes(tickerString):
def toggleQuotes(windowInstance):
global stockInstance
tickerString = windowInstance.ui.txtQuotes.toPlainText()
if len(tickerString) == 0:
console.cwrite("You must enter at least one ticker symbol in order to use this feature.")
return
Expand All @@ -33,14 +39,17 @@ def toggleQuotes(tickerString):
stockInstance.join()
stockInstance = None
console.cwrite("Stock quote thread terminated.")
windowInstance.ui.btnGetQuotes.setText("Get Quotes")
else:
stockInstance = stockThread(tickerString)
stockInstance.setDaemon(True)
stockInstance.start()
windowInstance.ui.btnGetQuotes.setText("Stop Quotes")

# Each stockThread object will fetch up to 10 quotes and update the scrolling message JIT (just-in-time)
class stockThread (threading.Thread):
def __init__(self, tickerString):
global desiredIndex
# Find out if there is enough space in the message list to start this thread
# Start the thread; call it active, and register the event
super(stockThread, self).__init__()
Expand All @@ -56,9 +65,11 @@ def __init__(self, tickerString):
console.cwrite("You did not enter any valid ticker symbols.")
return;
self.feedURL = 'http://www.nasdaq.com/aspxcontent/NasdaqRSS.aspx?data=quotes&symbol=%s' % ("&symbol=".join(stocks))
desiredIndex = globals.pushMsg("RSS-stocks", "This is the stock feed", globals.html % "Awaiting stock data...", True, desiredIndex)
console.cwrite("Stock quote thread is now running...")

def run(self):
global desiredIndex
while self.active: # The user can toggle if this RSS feed is actively being read
sleep(1)
if not self.evt.is_set():
Expand Down Expand Up @@ -97,8 +108,7 @@ def run(self):
counter += 1
# We're done parsing, so join everything together
newMessage = globals.html % ''.join(info)
# FIXME: For now, this will be Message #1
globals.richMsgs[0] = newMessage
desiredIndex = globals.pushMsg("RSS-stocks", "This is the stock feed", newMessage, True, desiredIndex)
self.evt.set()
# After the while loop terminates, remove references to the event
globals.asyncEvts.remove(self.evt)
Expand Down

0 comments on commit cb3e439

Please sign in to comment.