Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from PyQt4.QtCore import *
- from PyQt4.QtGui import *
- from PyQt4.QtNetwork import QHttp
- from PyKDE4.plasma import Plasma
- from PyKDE4 import plasmascript
- from PyKDE4.kdeui import KMessageBox
- import sys
- import os
- import os.path
- import time
- import datetime
- import urllib2
- # parsing modules
- from BeautifulSoup import BeautifulSoup
- import re
- class ShowDesc(QThread):
- def __init__(self, app, showName):
- QThread.__init__(self)
- self.app = app
- self.showName = showName.replace("_", " ")
- HOST = "http://www.tvrage.com/"
- self.showUrl = QUrl(HOST+showName.replace(" ","_"))
- self.imageLocal = self.app.applet.package().path()+"contents/shows/"+self.showName.toLower()+".jpg"
- self.imageUrl = None
- self.title = None
- self.ntimestamp = None
- self.ptimestamp = None
- self.busy = True
- self.finalEpisode = False
- self.label = None
- self.ntime = None
- self.ntimestamp = float(sys.maxint)
- self.__initGui()
- self.setEdit(False)
- def __del__(self):
- print "removed this showdesc"
- def __initGui(self):
- if not self.label == None:
- print "already guied bitch!"
- return
- l = Plasma.Label(self.app.applet)
- l.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
- l.setMinimumSize(48,48)
- l.setMaximumSize(48,48)
- self.imgLabel = l
- l = Plasma.Label(self.app.applet)
- l.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
- l.setMinimumSize(170,48)
- l.setMaximumSize(170,48)
- #l.setAutoFillBackground(True)
- #l.setStyleSheet("QLabel {background: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #eef, stop: 1 #ccf); padding: 1px;border-style: solid;border: 2px solid black;border-radius: 8px;}")
- #l.setAutoFillBackground(True)
- self.label = l
- l = Plasma.Label(self.app.applet)
- l.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
- l.setMinimumSize(80,48)
- l.setMaximumSize(80,48)
- #l.setAutoFillBackground(True)
- #l.setStyleSheet("QLabel {background: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #eef, stop: 1 #ccf); padding: 1px;border-style: solid;border: 2px solid black;border-radius: 8px;}")
- #l.setAutoFillBackground(True)
- self.dateLabel = l
- p = Plasma.PushButton(self.app.applet)
- icon23 = QIcon()
- icon23.addPixmap(QPixmap(self.app.applet.package().filePath("ui","remove.png")), QIcon.Normal, QIcon.Off)
- p.setIcon(icon23)
- p.setEnabled(False)
- p.setMinimumSize(48,48)
- p.setMaximumSize(48,48)
- p.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
- self.removeButton = p
- self.busyWidget = Plasma.BusyWidget()
- self.busyWidget.setRunning(True)
- self.imgLabelContainer = QGraphicsAnchorLayout ()
- self.imgLabelContainer.addAnchor(self.imgLabel,Qt.AnchorVerticalCenter,self.removeButton,Qt.AnchorVerticalCenter)
- self.imgLabelContainer.addAnchor(self.imgLabel,Qt.AnchorVerticalCenter,self.busyWidget,Qt.AnchorVerticalCenter)
- self.containerLayout = QGraphicsLinearLayout(Qt.Horizontal)
- self.containerLayout.setSizePolicy(QSizePolicy.Minimum,QSizePolicy.Minimum)
- self.containerLayout.addItem(self.imgLabelContainer)
- self.containerLayout.addItem(self.label)
- self.containerLayout.addItem(self.dateLabel)
- self.containerLayout.setSpacing(0)
- self.container = Plasma.Frame()
- self.container.setLayout(self.containerLayout)
- self.container.setContentsMargins(0,0,0,0)
- self.container.setWindowFrameMargins(0,0,0,0)
- QObject.connect(self.removeButton, SIGNAL("clicked()"), self.destroy)
- def setEdit(self, t):
- if not t:
- self.removeButton.setEnabled(False)
- self.removeButton.setVisible(False)
- else:
- self.removeButton.setEnabled(True)
- self.removeButton.setVisible(True)
- def destroy(self):
- print "destroy"
- self.label.close()
- self.imgLabel.close()
- self.dateLabel.close()
- self.container.close()
- # delete show
- for s in self.app.shows:
- if s == self:
- print "removing %s" % self.showName
- self.app.shows.remove(s)
- self.app.update()
- self.app.saveShows()
- self.quit()
- def outputElements(self):
- return self.container
- def get(self):
- self.begin()
- print "Preparing http"
- print self.showUrl.host()
- self.http = QHttp(self.showUrl.host());
- self.infoBuffer = QBuffer()
- self.http.get(self.showUrl.path(), self.infoBuffer)
- QObject.connect(self.http, SIGNAL("done(bool)"), self.fetchedInfo)
- return True
- def getImage(self):
- if self.imageUrl == None:
- return
- if (QFile.exists(self.imageLocal)):
- print "Local copy of image found for '%s'" % self.showName
- self.imageBuffer = QFile(self.imageLocal)
- self.http = None
- self.fetchedImage(False)
- return
- print "Preparing http request for image retrieval 'http://%s%s'" % (self.imageUrl.host(),self.imageUrl.path())
- self.http = QHttp(self.imageUrl.host());
- self.imageBuffer = QFile(self.imageLocal)
- if not self.imageBuffer.open(QIODevice.WriteOnly):
- print "Can't open '%s' for writing" % self.imageLocal
- return
- self.http.get(self.imageUrl.path(), self.imageBuffer)
- QObject.connect(self.http, SIGNAL("done(bool)"), self.fetchedImage)
- def fetchedImage(self,error):
- filename = self.imageBuffer.fileName()
- print "fetched image '%s'" % filename
- self.updateImage(filename)
- if not self.http == None:
- self.http.close();
- self.imageBuffer.close();
- self.end()
- def begin(self):
- self.busy = True
- self.busyWidget.setRunning(True)
- self.busyWidget.setVisible(True)
- def end(self,bypassFlag=False):
- self.busyWidget.setRunning(False)
- self.busyWidget.setVisible(False)
- if not bypassFlag:
- self.busy = False
- def fetchedInfo(self, error):
- print "Got a Http response"
- html = str(self.infoBuffer.data())
- # got a http respose, now let's parse it
- soup = BeautifulSoup(html)
- numFields = 6
- newEpisode = [ None for i in xrange(numFields)]
- prevEpisode = [ None for i in xrange(numFields)]
- self.fetchOkay = False
- # get episode infos
- h2Tags = soup.findAll('h2')
- for h in h2Tags:
- print h
- # get new episode infos
- matchObj = re.match(r'.*Next: <a.*>([0-9]*)x([0-9]*).--.(.*)</a>.\((.*)\/(.*)\/(.*)\) ', str(h), re.M|re.I)
- if matchObj:
- newEpisode = matchObj.groups()
- fetchOkay = True
- continue
- # get previous episode infos
- matchObj = re.match(r'.*Prev: <a.*>([0-9]*)x([0-9]*).--.(.*)</a>.\((.*)\/(.*)\/(.*)\) ', str(h), re.M|re.I)
- if matchObj:
- prevEpisode = matchObj.groups()
- print "matched prev"
- self.fetchOkay = True
- continue
- # check if last episode aired?
- matchObj = re.match(r'.*Final: <a.*>([0-9]*)x([0-9]*).--.(.*)</a>.\((.*)\/(.*)\/(.*)\) ', str(h), re.M|re.I)
- if matchObj:
- prevEpisode = matchObj.groups()
- print "matched prev"
- self.finalEpisode = True
- self.fetchOkay = True
- continue
- # check if we got valid data or not
- if not self.fetchOkay and self.app.loaded and self.app.initialized:
- KMessageBox.messageBox(None, KMessageBox.Information, "Show '%s' can't be found, sorry!" % self.showName)
- print "fetch wasn't valid"
- self.destroy()
- return False
- # get image info, since we already scanned anyway
- imgTags = soup.findAll('img', {'src' : re.compile(r'(.*shows.*)(jpe?g)|(png)$')})
- for i in imgTags:
- matchObj = re.match(r'.*src..(.*shows.*).jpg.*>', str(i))
- if matchObj:
- imgSrc = matchObj.group(1)
- continue
- self.imageUrl = QUrl(imgSrc+".jpg")
- # start image retrieval
- self.getImage()
- # use the time that it takes to get the image for assignment of the fetched info
- self.ntime = None
- self.ptime = None
- self.title = None
- self.ntimestamp = float(sys.maxint)
- self.ptimestamp = None
- # title
- self.title = newEpisode[2]
- monthNum = {'Feb': 2, 'Aug': 8, 'Jan': 1, 'Dec': 12, 'Oct': 10, 'Mar': 3, 'Sep': 9, 'May': 5, 'Jun': 6, 'Jul': 7, 'Apr': 4, 'Nov': 11}
- # time new episode
- day = newEpisode[3]
- month = newEpisode[4]
- year = newEpisode[5]
- if not (day==None and month==None and year==None):
- datestring = "%s %s %s" % (monthNum[day], month, year)
- self.ntime = time.strptime(datestring,"%m %d %Y")
- self.ntimestamp = time.mktime(self.ntime)
- # time prev episode
- day = prevEpisode[3]
- month = prevEpisode[4]
- year = prevEpisode[5]
- if not (day==None and month==None and year==None):
- datestring = "%s %s %s" % (monthNum[day], month, year)
- self.ptime = time.strptime(datestring,"%m %d %Y")
- self.ptimestamp = time.mktime(self.ptime)
- print self.ptime
- self.updateText()
- def updateImage(self, filename):
- self.imgLabel.nativeWidget().setPixmap(QPixmap(filename).scaled(48,48))
- def updateText(self):
- if self.title == None:
- ntitle="TBA"
- else:
- ntitle=self.title
- if self.finalEpisode:
- ntitle="no more episodes"
- self.label.setText(" " \
- "<b>%(name)s</b><br>%(title)s" % dict(name=self.showName.replace("_"," "), title=ntitle))
- if self.ntime == None:
- ntimestr = "TBA"
- elif time.strftime("%d. %b %y",self.ntime) == time.strftime("%d. %b %y",time.localtime()):
- ntimestr = "Today"
- else:
- ntimestr = time.strftime("%d. %b %y",self.ntime)
- if self.finalEpisode:
- ntimestr="finished"
- self.dateLabel.setText(" " \
- "<span style=\"color:#1245aa; font-weight:bold;\">%(ntime)s</span><br><span style=\"font-size:7pt;color:#1245aa;\">%(ptime)s</span>" % dict(name=self.showName, \
- ntime=ntimestr, \
- ptime=time.strftime("%d. %b %y",self.ptime) if not self.ptime == None else "n/a", \
- ))
- class AirdatePlasmoidApplet(plasmascript.Applet):
- def __init__(self,parent,args=None):
- plasmascript.Applet.__init__(self,parent)
- def init(self):
- self.__initGui()
- self.setEnabled(False)
- self.firstRun = True
- self.loaded = False
- self.initialized = False
- self.needsInitRefetch = True
- self.timeEngine = self.dataEngine("time")
- self.timeEngine.connectSource("Local", self, 1000)
- self.firstRun = False
- def __initGui(self):
- self.setAspectRatioMode(Plasma.IgnoreAspectRatio)
- self.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)
- self.setMinimumSize(370,250)
- # No configuration interface supported
- self.setHasConfigurationInterface(False)
- self.layout = QGraphicsLinearLayout(Qt.Vertical, self.applet)
- self.setLayout(self.layout)
- # setup gui
- self.scrollArea = Plasma.ScrollWidget()
- self.frame = Plasma.Frame()
- self.frame.setLayout(QGraphicsLinearLayout(Qt.Vertical))
- self.scrollArea.setWidget(self.frame)
- self.outputLayout = self.frame.layout()
- self.outputLayout.setSpacing(0)
- self.layout.addItem(self.scrollArea)
- self.controlLayout = QGraphicsLinearLayout(Qt.Horizontal)
- self.controlLayout.setSizePolicy(QSizePolicy.Preferred,QSizePolicy.Preferred)
- self.layout.addItem(self.controlLayout)
- self.showUrl = Plasma.LineEdit(self.applet)
- self.controlLayout.addItem(self.showUrl)
- self.showUrl.setEnabled(False)
- self.addButton = Plasma.PushButton(self.applet)
- icon23 = QIcon()
- icon23.addPixmap(QPixmap(self.applet.package().filePath("ui","add.png")), QIcon.Normal, QIcon.Off)
- self.addButton.setIcon(icon23)
- self.addButton.setMinimumSize(24,24)
- self.addButton.setMaximumSize(24,24)
- self.addButton.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
- self.addButton.setEnabled(False)
- self.controlLayout.addItem(self.addButton)
- QObject.connect(self.addButton, SIGNAL("clicked()"), self.addShow)
- self.updateButton = Plasma.PushButton(self.applet)
- self.updateButton.setMinimumSize(24,24)
- self.updateButton.setMaximumSize(24,24)
- self.updateButton.setEnabled(False)
- icon23 = QIcon()
- icon23.addPixmap(QPixmap(self.applet.package().filePath("ui","reload.png")), QIcon.Normal, QIcon.Off)
- self.updateButton.setIcon(icon23)
- self.updateButton.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
- self.controlLayout.addItem(self.updateButton)
- QObject.connect(self.updateButton, SIGNAL("clicked()"), self.refetch)
- self.editButton = Plasma.PushButton(self.applet)
- self.editButton.setEnabled(False)
- self.editButton.setMinimumSize(24,24)
- self.editButton.setMaximumSize(24,24)
- self.editButton.setCheckable(True)
- icon23 = QIcon()
- icon23.addPixmap(QPixmap(self.applet.package().filePath("ui","edit.png")), QIcon.Normal, QIcon.Off)
- self.editButton.setIcon(icon23)
- self.editButton.setSizePolicy(QSizePolicy.Fixed,QSizePolicy.Fixed)
- self.controlLayout.addItem(self.editButton)
- QObject.connect(self.editButton, SIGNAL("clicked()"), self.editShows)
- def editShows(self):
- if self.editButton.isChecked():
- self.addButton.setEnabled(True)
- self.showUrl.setEnabled(True)
- for s in self.shows:
- s.setEdit(True)
- else:
- self.addButton.setEnabled(False)
- self.showUrl.setEnabled(False)
- for s in self.shows:
- s.setEdit(False)
- def addShow(self):
- self.setEnabled(False)
- showName = self.showUrl.text()
- print "adding show %s" % showName
- for sd in self.shows:
- if str(sd.showName).lower() == str(showName).lower():
- print "show is already there!!"
- return
- newShowDesc = ShowDesc(self,showName)
- newShowDesc.setEdit(self.editButton.isChecked())
- if newShowDesc.get():
- self.shows.append(newShowDesc)
- self.outputLayout.addItem(newShowDesc.outputElements())
- self.saveShows()
- # switch to watch mode
- self.timeEngine.connectSource("Local",self,1000)
- def saveShows(self):
- settings = QSettings("Airdate-Plasmoid","Airdate-Plasmoid")
- showNames = [ s.showName for s in self.shows ]
- settings.setValue("shows", showNames)
- showTitles = [ s.title for s in self.shows ]
- settings.setValue("titles", showTitles)
- showNTimestamps = [ s.ntimestamp for s in self.shows ]
- print showNTimestamps
- settings.setValue("ntimestamps", showNTimestamps)
- showPTimestamps = [ s.ptimestamp for s in self.shows ]
- settings.setValue("ptimestamps", showPTimestamps)
- def output(self):
- print "updating output"
- # sort shows:
- self.shows = sorted(self.shows, key=lambda ShowDesc: ShowDesc.ntimestamp, reverse=False)
- for i,s in enumerate(self.shows):
- self.outputLayout.addItem(s.outputElements())
- def update(self):
- removeList = []
- for i in range(self.outputLayout.count()):
- if not self.outputLayout.itemAt(i).graphicsItem().isVisible():
- removeList.append(i)
- print "not visible!"
- for i in removeList:
- self.outputLayout.removeAt(i)
- def isConnectedToInternet(self):
- try:
- response=urllib2.urlopen('http://www.tvrage.com',timeout=2)
- return True
- except urllib2.URLError as err: pass
- return False
- def refetch(self):
- self.setEnabled(False)
- self.updateButton.setEnabled(False)
- if not self.isConnectedToInternet():
- print "not connected to internet"
- self.needsInitRefetch = True
- if self.loaded:
- self.loaded=False
- print "switching to watch mode"
- self.timeEngine.connectSource("Local",self,1000)
- for sd in self.shows:
- sd.end(bypassFlag=True)
- return False
- for i,sd in enumerate(self.shows):
- sd.get()
- # switch to watch mode
- if self.loaded:
- print "switching to watch mode"
- self.timeEngine.connectSource("Local",self,1000)
- return True
- def isEverythingFetched(self):
- for s in self.shows:
- if s.busy == True:
- return False
- return True
- @pyqtSignature("dataUpdated(const QString &, const Plasma::DataEngine::Data &)")
- def dataUpdated(self, sourceName, data):
- if self.firstRun:
- return
- print "Status: init %s | needinitrefetch %s | loaded %s | internet %s" % (str(self.initialized), str(self.needsInitRefetch), str(self.loaded), self.isConnectedToInternet())
- if not self.initialized:
- print "\tInitialising"
- # load settings
- settings = QSettings("Airdate-Plasmoid","Airdate-Plasmoid")
- nstamps = settings.value("ntimestamps").toList()
- pstamps = settings.value("ptimestamps").toList()
- titles = settings.value("titles").toList()
- shows = settings.value("shows").toList()
- self.shows = []
- for s in shows:
- sd = ShowDesc(self, s.toString().replace("_", " "))
- self.shows.append(sd)
- self.initialized = True
- self.needsInitRefetch = True
- elif self.needsInitRefetch and self.initialized:
- self.output()
- self.loaded = self.refetch()
- self.needsInitRefetch = not self.loaded
- elif self.loaded and self.isEverythingFetched():
- print "\teverything is fetched"
- ## do sorting when everything is ready
- self.setEnabled(True)
- #delete everything, now we can do some sorting!
- for s in self.shows:
- self.outputLayout.removeItem(s.outputElements())
- #sort this ...
- self.output()
- # switch to more conservative mode
- self.timeEngine.disconnectSource("Local",self)
- self.editButton.setEnabled(True)
- self.updateButton.setEnabled(True)
- self.loaded = True
- else:
- print "\t skipped"
- def CreateApplet(parent):
- return AirdatePlasmoidApplet(parent)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement