The Code

I’m going to start by posting the code for the whole app and then Im going to comment it. Unfortunately I can’t indent properly on this blog, but I will put a link at the end of the post from where you can download the python file containing the code.


import sys
from PySide import QtCore, QtGui
from PySide import QtWebKit
from MainForm import Ui_MainForm
from random import randint
import res_rc

class TubeItem:
 def __init__(self, code, name = None):
 self.code = code
 if name == None:
 self.name = code
 else:
 self.name = name

 def __str__(self):
 return self.name

class PlayList(QtCore.QAbstractListModel):
 def __init__(self, contents):
 super(PlayList, self).__init__()
 self.contents = contents
 self.rnd = False
 self.crt = 0

 def rowCount(self, parent):
 return len(self.contents)

 def data(self, index, role):
 if role == QtCore.Qt.DisplayRole:
 return str(self.contents[index.row()])
 elif role == QtCore.Qt.ForegroundRole:
 if index.row() == self.crt:
 return QtGui.QBrush(QtCore.Qt.red)
 else:
 return QtGui.QBrush(QtCore.Qt.green)

class Player(QtCore.QObject):
 def __init__(self, parent=None):
 super(Player, self).__init__(parent)
 videoOver = QtCore.Signal()

 @QtCore.Slot()
 def video_over(self):
 self.videoOver.emit()

class MainForm(QtGui.QWidget):
 def __init__(self):
 super(MainForm, self).__init__()
 self.ui = Ui_MainForm()
 self.ui.setupUi(self)
 self.ui.webView.settings().setAttribute(QtWebKit.QWebSettings.PluginsEnabled, True)
 url = 'qrc:/res/docs/index.html'
 self.ui.webView.setUrl(QtCore.QUrl(url))
 self.play_list = PlayList([])
 self.ui.listView.setModel(self.play_list)
 self.ui.shuffleButton.setFlat(self.play_list.rnd)
 self.player = Player()
 self.ui.lineEdit.returnPressed.connect(self.get_url)
 self.ui.addButton.clicked.connect(self.get_url)
 self.ui.listView.doubleClicked.connect(self.play_list_doubleClicked)
 self.ui.playButton.clicked.connect(self.playButton_clicked)
 self.ui.stopButton.clicked.connect(self.stopButton_clicked)
 self.ui.webView.loadFinished.connect(self.web_loadFinished)
 self.player.videoOver.connect(self.play_next)
 self.ui.shuffleButton.clicked.connect(self.shuffleButton_clicked)

 def web_loadFinished(self):
 self.ui.webView.page().mainFrame().addToJavaScriptWindowObject('main', self.player)

 def get_url(self):
 """Adds url to the playlist"""
 url = self.ui.lineEdit.text()
 vid_code = self.get_vid_code(url)
 if vid_code == 'xxx':
 QtGui.QMessageBox.warning(self, "Error", "Invalid video!")
 return
 tube_item = TubeItem(vid_code)
 self.play_list.contents.append(tube_item)
 self.play_list.reset()
 self.ui.lineEdit.clear()

 def get_vid_code(self,url):
 """Parses the text in lineEdit"""
 idx = url.find("?v=")
 if idx >= 0:
 idx += 3
 vid_code = url[idx: idx+11]
 else:
 idx = url.find("youtu.be/")
 if idx >= 0:
 idx+=9
 vid_code = url[idx: idx+11]
 else:
 if idx <0:
 return "xxx"
 return vid_code

 def playButton_clicked(self):
 try:
 if self.ui.listView.selectedIndexes():
 self.play_video(self.ui.listView.selectedIndexes()[0].row())
 else:
 self.play_video(0)
 except:
 pass

 def play_list_doubleClicked(self, index):
 self.play_video(index.row())

 def play_video(self, index):
 self.play_list.crt = index
 tube_item = self.play_list.contents[index]
 self.ui.webView.page().mainFrame().evaluateJavaScript("showVideo('"+tube_item.code+"')")
 self.play_list.reset()

 def stopButton_clicked(self):
 self.ui.webView.page().mainFrame().evaluateJavaScript("stopVideo()")

 def shuffleButton_clicked(self):
 self.ui.shuffleButton.setFlat(not self.ui.shuffleButton.isFlat())
 self.play_list.rnd = self.ui.shuffleButton.isFlat()

 def play_next(self):
 maxx = len(self.play_list.contents)-1
 if self.play_list.rnd:
 while True:
 new = randint(0,maxx)
 if new != self.play_list.crt:
 break
 else:
 new = self.play_list.crt + 1
 if new > maxx:
 new = 0
 self.play_video(new)

if __name__ == '__main__':
 app = QtGui.QApplication(sys.argv)
 myapp = MainForm()
 myapp.show()
sys.exit(app.exec_())

The ‘TubeItem’ class defines that will be in out playlist. That object will contain the name of the video and the youtube video code. For starters the name will be the same as the code.

Class ‘Playlist’ is the model class for our QListView. The property ‘crt’ holds the number of the current item being played, while the property ‘rnd’ is a boolean variable which is false if shuffle is off. An important property is contents, which represets the list of TubeItem objects from the playlist.
The ‘data’ method is used by QListView directly, which gets information based on the ‘role’ parameter. The DisplayRole return information about the contents of the playlist. We use the ForegroundRole to display the currently played item in a different color from the other items in the playlist.

We use the ‘Player’ class to communicate with the youtube player in  index.html. We will use this object to receive signals from html, like when the video finishes playing the ‘video_over’ method is called and we emit a videoOver signal witch is connected to a handler which jumps to the next video in the playlist

The ‘MainForm’ class is our app’s main window. It loads data from MainForm.py which we created with QtCreator. url = ‘qrc:/res/docs/index.html’  sets out QWebView to the index.html page we compiled in the res_rc.py with the script. We’ll turn the ‘shuffleButton’ into a Toggle Button with ‘setFlat(self.play_list.rnd)’, and we’ll call this method again whenever ‘shuffleButton’ is pushed. Next we do the handling of events, connecting signals to handler methods.

When the  web page finishes loading we send it a Player object with addToJavaScriptWindowObject(‘main’, self.player). 

To add an item to the playlist the user pastes a link in the ‘lineEdit’ widget and presses ‘addButton’ after that the link isvalidated, the video code is extracted, a ‘TubeItem’ object is created and added to the playlist.

When the user presses ‘playButton’ or double click an item in the playlist the app sends the video code of the current video in the playlist to the html page via the ‘showVideo’ method in the javascript file. When the stopButton is pressed the html revives the signal to run the ‘stopVideo’ method.

if __name__ == '__main__':
<p style="padding-left: 30px;">
 app = QtGui.QApplication(sys.argv)
 myapp = MainForm()
 myapp.show()
 sys.exit(app.exec_())

This last part is something all the PySide apps must have. It checks if the current python module is the one that;s running and not just used as a library in another app, and if it does it instantiates the main window of the app.

The files for this post are here: https://sourceforge.net/projects/playertutorial/files/player%200.3/

Next post: Compiling

Advertisements
This entry was posted in PySide, Python, TubePlayer and tagged , , , , , , , , , , , , , , , . Bookmark the permalink.

One Response to The Code

  1. Pingback: GUI | CodeForce

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s