diff --git a/CHANGELOG.mkdn b/CHANGELOG.mkdn index 95d74db..2c7b108 100644 --- a/CHANGELOG.mkdn +++ b/CHANGELOG.mkdn @@ -28,6 +28,8 @@ CHANGELOG * Customizable name alerts - Kiooeht [evacipatedBox] * Update bug reporter - Kiooeht [evacipatedBox] * Explain why a chumhandle is invalid - Kiooeht [evacipatedBox] (Idea: Lexi [lexicalNuance]) +* Netsplit notification in memos - Kiooeht [evacipatedBox] +* Toast Notifications - Kiooeht [evacipatedBox] * Bug fixes * Don't delete random chum when blocking someone not on chumroll - Kiooeht [evacipatedBox] * Openning global userlist doesn't reset OP status of memo users - Kiooeht [evacipatedBox] diff --git a/TODO.mkdn b/TODO.mkdn index ed61864..d12e3bc 100644 --- a/TODO.mkdn +++ b/TODO.mkdn @@ -18,6 +18,7 @@ Features * Fully working Toasts * Auto download/install updates via Windows installer * Turn memo notifications on/off from right-click menu on memos (Idea: lostGash) +* Gray out random encounter option when RE is offline Bugs ---- diff --git a/menus.py b/menus.py index a13c953..f595ac0 100644 --- a/menus.py +++ b/menus.py @@ -996,7 +996,7 @@ class PesterOptions(QtGui.QDialog): self.tabs = QtGui.QButtonGroup(self) self.connect(self.tabs, QtCore.SIGNAL('buttonClicked(int)'), self, QtCore.SLOT('changePage(int)')) - tabNames = ["Chum List", "Conversations", "Interface", "Sound", "Logging", "Idle/Updates", "Theme"] + tabNames = ["Chum List", "Conversations", "Interface", "Sound", "Notifications", "Logging", "Idle/Updates", "Theme"] if parent.advanced: tabNames.append("Advanced") for t in tabNames: button = QtGui.QPushButton(t) @@ -1038,6 +1038,9 @@ class PesterOptions(QtGui.QDialog): self.editMentions = QtGui.QPushButton("Edit Mentions", self) self.connect(self.editMentions, QtCore.SIGNAL('clicked()'), self, QtCore.SLOT('openMentions()')) + self.editMentions2 = QtGui.QPushButton("Edit Mentions", self) + self.connect(self.editMentions2, QtCore.SIGNAL('clicked()'), + self, QtCore.SLOT('openMentions()')) self.volume = QtGui.QSlider(QtCore.Qt.Horizontal, self) self.volume.setMinimum(0) @@ -1186,6 +1189,21 @@ class PesterOptions(QtGui.QDialog): layout_type = QtGui.QHBoxLayout() layout_type.addWidget(self.notifyTypeLabel) layout_type.addWidget(self.notifyOptions) + self.notifySigninCheck = QtGui.QCheckBox("Chum signs in", self) + if self.config.notifyOptions() & self.config.SIGNIN: + self.notifySigninCheck.setChecked(True) + self.notifySignoutCheck = QtGui.QCheckBox("Chum signs out", self) + if self.config.notifyOptions() & self.config.SIGNOUT: + self.notifySignoutCheck.setChecked(True) + self.notifyNewMsgCheck = QtGui.QCheckBox("New messages", self) + if self.config.notifyOptions() & self.config.NEWMSG: + self.notifyNewMsgCheck.setChecked(True) + self.notifyNewConvoCheck = QtGui.QCheckBox("Only new conversations", self) + if self.config.notifyOptions() & self.config.NEWCONVO: + self.notifyNewConvoCheck.setChecked(True) + self.notifyMentionsCheck = QtGui.QCheckBox("Memo Mentions (initials)", self) + if self.config.notifyOptions() & self.config.INITIALS: + self.notifyMentionsCheck.setChecked(True) self.notifyChange(self.notifycheck.checkState()) if parent.advanced: @@ -1245,13 +1263,6 @@ class PesterOptions(QtGui.QDialog): layout_interface.addLayout(layout_close) layout_interface.addWidget(self.pesterBlink) layout_interface.addWidget(self.memoBlink) - layout_interface.addSpacing(16) - layout_interface.addWidget(QtGui.QLabel("NOT FULLY COMPLETE YET:")) - layout_interface.addWidget(self.notifycheck) - layout_indent = QtGui.QVBoxLayout() - layout_indent.addLayout(layout_type) - layout_indent.setContentsMargins(22,0,0,0) - layout_interface.addLayout(layout_indent) self.pages.addWidget(widget) # Sound @@ -1276,6 +1287,26 @@ class PesterOptions(QtGui.QDialog): layout_sound.addWidget(self.currentVol) self.pages.addWidget(widget) + # Notifications + widget = QtGui.QWidget() + layout_notify = QtGui.QVBoxLayout(widget) + layout_notify.setAlignment(QtCore.Qt.AlignTop) + layout_notify.addWidget(self.notifycheck) + layout_indent = QtGui.QVBoxLayout() + layout_indent.addLayout(layout_type) + layout_indent.setContentsMargins(22,0,0,0) + layout_indent.addWidget(self.notifySigninCheck) + layout_indent.addWidget(self.notifySignoutCheck) + layout_indent.addWidget(self.notifyNewMsgCheck) + layout_doubleindent = QtGui.QVBoxLayout() + layout_doubleindent.addWidget(self.notifyNewConvoCheck) + layout_doubleindent.setContentsMargins(22,0,0,0) + layout_indent.addLayout(layout_doubleindent) + layout_indent.addWidget(self.notifyMentionsCheck) + layout_indent.addWidget(self.editMentions2) + layout_notify.addLayout(layout_indent) + self.pages.addWidget(widget) + # Logging widget = QtGui.QWidget() layout_logs = QtGui.QVBoxLayout(widget) @@ -1335,9 +1366,19 @@ class PesterOptions(QtGui.QDialog): if state == 0: self.notifyTypeLabel.setEnabled(False) self.notifyOptions.setEnabled(False) + self.notifySigninCheck.setEnabled(False) + self.notifySignoutCheck.setEnabled(False) + self.notifyNewMsgCheck.setEnabled(False) + self.notifyNewConvoCheck.setEnabled(False) + self.notifyMentionsCheck.setEnabled(False) else: self.notifyTypeLabel.setEnabled(True) self.notifyOptions.setEnabled(True) + self.notifySigninCheck.setEnabled(True) + self.notifySignoutCheck.setEnabled(True) + self.notifyNewMsgCheck.setEnabled(True) + self.notifyNewConvoCheck.setEnabled(True) + self.notifyMentionsCheck.setEnabled(True) @QtCore.pyqtSlot(int) def soundChange(self, state): diff --git a/pesterchum.py b/pesterchum.py index e12db02..df0a56b 100644 --- a/pesterchum.py +++ b/pesterchum.py @@ -328,6 +328,12 @@ class userConfig(object): # Use for bit flag blink self.PBLINK = 1 self.MBLINK = 2 + # Use for bit flag notfications + self.SIGNIN = 1 + self.SIGNOUT = 2 + self.NEWMSG = 4 + self.NEWCONVO = 8 + self.INITIALS = 16 self.filename = _datadir+"pesterchum.js" fp = open(self.filename) self.config = json.load(fp) @@ -435,6 +441,8 @@ class userConfig(object): return self.config.get('notify', True) def notifyType(self): return self.config.get('notifyType', "default") + def notifyOptions(self): + return self.config.get('notifyOptions', self.SIGNIN | self.NEWMSG | self.NEWCONVO | self.INITIALS) def addChum(self, chum): if chum.handle not in self.chums(): fp = open(self.filename) # what if we have two clients open?? @@ -689,18 +697,20 @@ class chumListing(QtGui.QTreeWidgetItem): def setMood(self, mood): if hasattr(self.mainwindow, "chumList") and self.mainwindow.chumList.notify: #print "%s -> %s" % (self.chum.mood.name(), mood.name()) - if mood.name() == "offline" and self.chum.mood.name() != "offline": + if self.mainwindow.config.notifyOptions() & self.mainwindow.config.SIGNOUT and \ + mood.name() == "offline" and self.chum.mood.name() != "offline": #print "OFFLINE NOTIFY: " + self.handle - uri = "file://" + os.path.abspath(os.path.curdir) + "/themes/enamel/distraught2.gif" + uri = self.mainwindow.theme["toasts/icon/signout"] n = self.mainwindow.tm.Toast(self.mainwindow.tm.appName, "%s is Offline" % (self.handle), uri) - #n.show() - elif mood.name() != "offline" and self.chum.mood.name() == "offline": + n.show() + elif self.mainwindow.config.notifyOptions() & self.mainwindow.config.SIGNIN and \ + mood.name() != "offline" and self.chum.mood.name() == "offline": #print "ONLINE NOTIFY: " + self.handle - uri = "file://" + os.path.abspath(os.path.curdir) + "/themes/enamel/chummy2.gif" + uri = self.mainwindow.theme["toasts/icon/signin"] n = self.mainwindow.tm.Toast(self.mainwindow.tm.appName, "%s is Online" % (self.handle), uri) - #n.show() + n.show() login = False logout = False if mood.name() == "offline" and self.chum.mood.name() != "offline": @@ -1596,11 +1606,12 @@ class PesterWindow(MovingWindow): themeWarning.exec_() self.theme = pesterTheme("pesterchum") + extraToasts = {'default': PesterToast} + if pytwmn.confExists(): + extraToasts['twmn'] = pytwmn.Notification self.tm = PesterToastMachine(self, lambda: self.theme["main/windowtitle"], on=self.config.notify(), - type=self.config.notifyType(), extras={'pester': PesterToast, 'twmn': pytwmn.Notification}) + type=self.config.notifyType(), extras=extraToasts) self.tm.run() - t = self.tm.Toast(self.tm.appName, "!!---Started up ToastMachine---!!") - t.show() self.chatlog = PesterLog(self.profile().handle, self) @@ -1856,6 +1867,25 @@ class PesterWindow(MovingWindow): #yeah suck on this self.sendMessage.emit("PESTERCHUM:BLOCKED", handle) return + # notify + if self.config.notifyOptions() & self.config.NEWMSG: + if not self.convos.has_key(handle): + t = self.tm.Toast("New Conversation", "From: %s" % handle) + t.show() + elif not self.config.notifyOptions() & self.config.NEWCONVO: + if msg[:11] != "PESTERCHUM:": + t = self.tm.Toast("From: %s" % handle, re.sub("", "", msg)) + t.show() + else: + if msg == "PESTERCHUM:CEASE": + t = self.tm.Toast("Closed Conversation", handle) + t.show() + elif msg == "PESTERCHUM:BLOCK": + t = self.tm.Toast("Blocked", handle) + t.show() + elif msg == "PESTERCHUM:UNBLOCK": + t = self.tm.Toast("Unblocked", handle) + t.show() if not self.convos.has_key(handle): if msg == "PESTERCHUM:CEASE": # ignore cease after we hang up return @@ -1902,6 +1932,9 @@ class PesterWindow(MovingWindow): m = m[m.find(":"):] for search in self.userprofile.getMentions(): if re.search(search, m): + if self.config.notifyOptions() & self.config.INITIALS: + t = self.tm.Toast(chan, re.sub("", "", msg)) + t.show() self.namesound.play() return if self.honk and re.search(r"\bhonk\b", convertTags(msg, "text"), re.I): @@ -2869,15 +2902,29 @@ class PesterWindow(MovingWindow): # Taskbar blink blinksetting = 0 if self.optionmenu.pesterBlink.isChecked(): - blinksetting = blinksetting | self.config.PBLINK + blinksetting |= self.config.PBLINK if self.optionmenu.memoBlink.isChecked(): - blinksetting = blinksetting | self.config.MBLINK + blinksetting |= self.config.MBLINK curblink = self.config.blink() if blinksetting != curblink: self.config.set('blink', blinksetting) # toast notifications self.tm.setEnabled(self.optionmenu.notifycheck.isChecked()) self.tm.setCurrentType(str(self.optionmenu.notifyOptions.currentText())) + notifysetting = 0 + if self.optionmenu.notifySigninCheck.isChecked(): + notifysetting |= self.config.SIGNIN + if self.optionmenu.notifySignoutCheck.isChecked(): + notifysetting |= self.config.SIGNOUT + if self.optionmenu.notifyNewMsgCheck.isChecked(): + notifysetting |= self.config.NEWMSG + if self.optionmenu.notifyNewConvoCheck.isChecked(): + notifysetting |= self.config.NEWCONVO + if self.optionmenu.notifyMentionsCheck.isChecked(): + notifysetting |= self.config.INITIALS + curnotify = self.config.notifyOptions() + if notifysetting != curnotify: + self.config.set('notifyOptions', notifysetting) # advanced ## user mode if self.advanced: diff --git a/themes/pesterchum/style.js b/themes/pesterchum/style.js index a38d1e6..a3139ae 100644 --- a/themes/pesterchum/style.js +++ b/themes/pesterchum/style.js @@ -319,5 +319,18 @@ "voice": { "icon": "$path/voice.png" }, "founder": { "icon": "$path/founder.png" }, "admin": { "icon": "$path/admin.png" } + }, + "toasts": + { + "width": 210, + "height": 100, + "style": "background: white;", + "icon": { "signin": "$path/../enamel/chummy2.gif", + "signout": "$path/../enamel/distraught2.gif", + "style": "border: 2px solid black; border-width: 2px 0px 0px 2px;" }, + "title": { "minimumheight": 50, + "style": "border: 2px solid black; border-width: 2px 2px 0px 0px; padding: 5px; font-weight:bold;" + }, + "content": { "style": "background: black; color: white; padding: 5px;" } } } diff --git a/themes/trollian/style.js b/themes/trollian/style.js index f04c4b7..f9c4a31 100644 --- a/themes/trollian/style.js +++ b/themes/trollian/style.js @@ -349,5 +349,18 @@ "op": { "icon": "$path/op.png" }, "halfop": { "icon": "$path/halfop.png" }, "voice": { "icon": "$path/voice.png" } + }, + "toasts": + { + "width": 210, + "height": 100, + "style": "background: white;", + "icon": { "signin": "$path/../enamel/ecstatic2.gif", + "signout": "$path/../enamel/discontent2.gif", + "style": "border: 2px solid black; border-width: 2px 0px 0px 2px;" }, + "title": { "minimumheight": 50, + "style": "border: 2px solid black; border-width: 2px 2px 0px 0px; padding: 5px; font-weight:bold;" + }, + "content": { "style": "background: black; color: white; padding: 5px;" } } } diff --git a/toast.py b/toast.py index 71b2347..f84e945 100644 --- a/toast.py +++ b/toast.py @@ -1,6 +1,6 @@ import inspect import threading -import time +import time, os from PyQt4 import QtGui, QtCore try: @@ -9,12 +9,20 @@ except: pynotify = None class DefaultToast(object): - def __init__(self, title, msg, icon): - self.title = title - self.msg = msg - self.icon = icon + def __init__(self, machine, title, msg, icon): + self.machine = machine + self.title = title + self.msg = msg + self.icon = icon def show(self): print self.title, self.msg, self.icon + self.done() + def done(self): + t = self.machine.toasts[0] + if t.title == self.title and t.msg == self.msg and t.icon == self.icon: + self.machine.toasts.pop(0) + self.machine.displaying = False + print "Done" class ToastMachine(object): class __Toast__(object): @@ -23,6 +31,8 @@ class ToastMachine(object): self.title = title self.msg = msg self.time = time + if icon: + icon = os.path.abspath(icon) self.icon = icon self.importance = importance if inspect.ismethod(self.title) or inspect.isfunction(self.title): @@ -59,10 +69,20 @@ class ToastMachine(object): self.realShow() def realShow(self): + self.machine.displaying = True t = None for (k,v) in self.machine.types.iteritems(): if self.machine.type == k: - t = v(self.title, self.msg, self.icon) + args = inspect.getargspec(v.__init__).args + extras = {} + if 'parent' in args: + extras['parent'] = self.machine.parent + if 'time' in args: + extras['time'] = self.time + if k == "libnotify" or k == "twmn": + t = v(self.title, self.msg, self.icon, **extras) + else: + t = v(self.machine, self.title, self.msg, self.icon, **extras) # Use libnotify's urgency setting if k == "libnotify": if self.importance < 0: @@ -74,17 +94,13 @@ class ToastMachine(object): break if not t: if 'default' in self.machine.types: - if 'parent' in inspect.getargspec(self.machine.types['default']).args: - t = self.machine.types['default'](self.title, self.msg, self.icon, self.machine.parent) + if 'parent' in inspect.getargspec(self.machine.types['default'].__init__).args: + t = self.machine.types['default'](self.machine, self.title, self.msg, self.icon, self.machine.parent) else: - t = self.machine.types['default'](self.title, self.msg, self.icon) + t = self.machine.types['default'](self.machine, self.title, self.msg, self.icon) else: t = DefaultToast(self.title, self.msg, self.icon) t.show() - print "SLEEPING" - #time.sleep(self.time/1000) - if self in self.machine.toasts: - self.machine.toasts.remove(self) def __init__(self, parent, name, on=True, type="default", types=({'default' : DefaultToast, @@ -99,13 +115,14 @@ class ToastMachine(object): self.types = types self.type = "default" self.quit = False + self.displaying = False self.setCurrentType(type) self.toasts = [] - def Toast(self, title, msg, icon=""): - return self.__Toast__(self, title, msg, time=0, icon=icon) + def Toast(self, title, msg, icon="", time=3000): + return self.__Toast__(self, title, msg, time=time, icon=icon) def setEnabled(self, on): self.on = (on is True) @@ -127,7 +144,7 @@ class ToastMachine(object): from libs import pytwmn try: pytwmn.init() - except pytwmn.ERROR,e: + except pytwmn.ERROR, e: print "Problem initilizing pytwmn: " + str(e) return #self.type = type = "default" @@ -140,18 +157,9 @@ class ToastMachine(object): return self.name def showNext(self): - high = filter(lambda x: x.importance < 0, self.toasts) - normal = filter(lambda x: x.importance == 0, self.toasts) - low = filter(lambda x: x.importance > 0, self.toasts) - - if high: - high.sort(key=lambda x: x.importance) - high[0].realShow() - elif normal: - normal[0].realShow() - elif low: - low.sort(key=lambda x: x.importance) - low[0].realShow() + if not self.displaying and self.toasts: + self.toasts.sort(key=lambda x: x.importance) + self.toasts[0].realShow() def showAll(self): while self.toasts: @@ -163,40 +171,180 @@ class ToastMachine(object): self.showNext() -class PesterToast(QtGui.QFrame, DefaultToast): - def __init__(self, title, msg, icon, parent=None): - QtGui.QFrame.__init__(self, parent, - (QtCore.Qt.CustomizeWindowHint | - QtCore.Qt.FramelessWindowHint)) - #self.setAttribute(QtCore.Qt.WA_QuitOnClose, False) - #self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True) - #self.setAttribute(QtCore.Qt.WA_NoSystemBackground, True) - self.setObjectName("toast") - self.setWindowTitle("toast") - #self.setFocusPolicy(QtCore.Qt.ClickFocus) +class PesterToast(QtGui.QWidget, DefaultToast): + def __init__(self, machine, title, msg, icon, time=3000, parent=None): + QtGui.QWidget.__init__(self, parent) + + self.machine = machine + self.time = time + + self.setWindowFlags(QtCore.Qt.ToolTip) + + self.m_animation = QtCore.QParallelAnimationGroup() + anim = QtCore.QPropertyAnimation(self) + anim.setTargetObject(self) + self.m_animation.addAnimation(anim) + anim.setEasingCurve(QtCore.QEasingCurve.OutBounce) + anim.setDuration(1000) + self.connect(anim, QtCore.SIGNAL('finished()'), + self, QtCore.SLOT('reverseTrigger()')) + + self.m_animation.setDirection(QtCore.QAnimationGroup.Forward) self.title = QtGui.QLabel(title, self) self.msg = QtGui.QLabel(msg, self) - - self.btn = QtGui.QPushButton("Push Me", self) - self.connect(self.btn, QtCore.SIGNAL('clicked()'), - self, QtCore.SLOT('close()')) + self.content = msg + if icon: + self.icon = QtGui.QLabel("") + self.icon.setPixmap(QtGui.QPixmap(icon).scaledToWidth(30)) + else: + self.icon = QtGui.QLabel("") + self.icon.setPixmap(QtGui.QPixmap(30, 30)) + self.icon.pixmap().fill(QtGui.QColor(0,0,0,0)) layout_0 = QtGui.QVBoxLayout() - layout_0.addWidget(self.title) - layout_0.addWidget(self.btn) + layout_0.setMargin(0) + layout_0.setContentsMargins(0, 0, 0, 0) + + if self.icon: + layout_1 = QtGui.QGridLayout() + layout_1.addWidget(self.icon, 0,0, 1,1) + layout_1.addWidget(self.title, 0,1, 1,7) + layout_1.setAlignment(self.msg, QtCore.Qt.AlignTop) + layout_0.addLayout(layout_1) + else: + layout_0.addWidget(self.title) layout_0.addWidget(self.msg) + self.setMaximumWidth(self.parent().theme["toasts/width"]) + self.msg.setMaximumWidth(self.parent().theme["toasts/width"]) + self.title.setMinimumHeight(self.parent().theme["toasts/title/minimumheight"]) + self.setLayout(layout_0) - print self.isWindow() + self.setGeometry(0,0, self.parent().theme["toasts/width"], self.parent().theme["toasts/height"]) + self.setStyleSheet(self.parent().theme["toasts/style"]) + self.title.setStyleSheet(self.parent().theme["toasts/title/style"]) + if self.icon: + self.icon.setStyleSheet(self.parent().theme["toasts/icon/style"]) + self.msg.setStyleSheet(self.parent().theme["toasts/content/style"]) + self.layout().setSpacing(0) + self.msg.setText(PesterToast.wrapText(self.msg.font(), str(self.msg.text()), self.parent().theme["toasts/width"], self.parent().theme["toasts/content/style"])) + + anim.setStartValue(0) + anim.setEndValue(100) + self.connect(anim, QtCore.SIGNAL('valueChanged(QVariant)'), + self, QtCore.SLOT('updateBottomLeftAnimation(QVariant)')) + + self.byebye = False + + @QtCore.pyqtSlot() def show(self): - QtGui.QFrame.setVisible(self, True) - print "SHOWING" - #~ themeWarning = QtGui.QMessageBox(self) - #~ themeWarning.setText("ASDFASD") - #~ themeWarning.exec_() + self.m_animation.start() + + @QtCore.pyqtSlot() + def done(self): + QtGui.QWidget.hide(self) + t = self.machine.toasts[0] + if t.title == str(self.title.text()) and \ + t.msg == str(self.content): + self.machine.toasts.pop(0) + self.machine.displaying = False + if self.machine.on: + self.machine.showNext() + del self + + @QtCore.pyqtSlot() + def reverseTrigger(self): + if self.time >= 0: + QtCore.QTimer.singleShot(self.time, self, QtCore.SLOT('reverseStart()')) + + @QtCore.pyqtSlot() + def reverseStart(self): + if not self.byebye: + self.byebye = True + anim = self.m_animation.animationAt(0) + self.m_animation.setDirection(QtCore.QAnimationGroup.Backward) + anim.setEasingCurve(QtCore.QEasingCurve.InCubic) + self.disconnect(anim, QtCore.SIGNAL('finished()'), + self, QtCore.SLOT('reverseTrigger()')) + self.connect(anim, QtCore.SIGNAL('finished()'), + self, QtCore.SLOT('done()')) + self.m_animation.start() + + @QtCore.pyqtSlot(QtCore.QVariant) + def updateBottomLeftAnimation(self, value): + p = QtGui.QApplication.desktop().availableGeometry(self).bottomRight() + val = float(self.height())/100 + self.move(p.x()-self.width(), p.y() - (value.toInt()[0] * val) +1) + self.layout().setSpacing(0) + self.raise_() + QtGui.QWidget.show(self) + + def mousePressEvent(self, event): + if event.button() == QtCore.Qt.RightButton: + self.reverseStart() + elif event.button() == QtCore.Qt.LeftButton: + pass + + @staticmethod + def wrapText(font, text, maxwidth, css=""): + ret = [] + metric = QtGui.QFontMetrics(font) + if "padding" in css: + if css[css.find("padding")+7] != "-": + colon = css.find(":", css.find("padding")) + semicolon = css.find(";", css.find("padding")) + if semicolon < 0: + stuff = css[colon+1:] + else: + stuff = css[colon+1:semicolon] + stuff = stuff.replace("px", "").lstrip().rstrip() + stuff = stuff.split(" ") + if len(stuff) == 1: + maxwidth -= int(stuff[0])*2 + elif len(stuff) == 2: + maxwidth -= int(stuff[1])*2 + elif len(stuff) == 3: + maxwidth -= int(stuff[1])*2 + elif len(stuff) == 4: + maxwidth -= int(stuff[1]) + int(stuff[3]) + else: + if "padding-left" in css: + colon = css.find(":", css.find("padding-left")) + semicolon = css.find(";", css.find("padding-left")) + if semicolon < 0: + stuff = css[colon+1:] + else: + stuff = css[colon+1:semicolon] + stuff = stuff.replace("px", "").lstrip().rstrip() + if stuff.isdigit(): + maxwidth -= int(stuff) + if "padding-right" in css: + colon = css.find(":", css.find("padding-right")) + semicolon = css.find(";", css.find("padding-right")) + if semicolon < 0: + stuff = css[colon+1:] + else: + stuff = css[colon+1:semicolon] + stuff = stuff.replace("px", "").lstrip().rstrip() + if stuff.isdigit(): + maxwidth -= int(stuff) + + if metric.width(text) < maxwidth: + return text + while metric.width(text) > maxwidth: + lastspace = text.find(" ") + curspace = lastspace + while metric.width(text, curspace) < maxwidth: + lastspace = curspace + curspace = text.find(" ", lastspace+1) + ret.append(text[:lastspace]) + text = text[lastspace+1:] + ret.append(text) + return "\n".join(ret) + class PesterToastMachine(ToastMachine, QtCore.QObject): def __init__(self, parent, name, on=True, type="default", @@ -229,9 +377,10 @@ class PesterToastMachine(ToastMachine, QtCore.QObject): ToastMachine.showNext(self) def run(self): - self.timer = QtCore.QTimer(self) - self.timer.setInterval(1000) - self.connect(self.timer, QtCore.SIGNAL('timeout()'), - self, QtCore.SLOT('showNext()')) - if self.on: - pass#self.timer.start() + pass + #~ self.timer = QtCore.QTimer(self) + #~ self.timer.setInterval(1000) + #~ self.connect(self.timer, QtCore.SIGNAL('timeout()'), + #~ self, QtCore.SLOT('showNext()')) + #~ if self.on: + #~ self.timer.start()