merge
This commit is contained in:
commit
427eefb383
15 changed files with 1238 additions and 471 deletions
18
CHANGELOG.mkdn
Normal file
18
CHANGELOG.mkdn
Normal file
|
@ -0,0 +1,18 @@
|
|||
Pesterchum 3.14
|
||||
===============
|
||||
|
||||
Visit http://nova.xzibition.com/~illuminatedwax/help.html for tutorial.
|
||||
|
||||
Visit https://github.com/illuminatedwax/pesterchum for git access and source code.
|
||||
|
||||
CHANGELOG
|
||||
---------
|
||||
### 3.14b (idk on version number scheme)
|
||||
* Pesterchum 3.14 - illuminatedwax [ghostDunk]
|
||||
* Art - Grimlive [aquaMarinist]
|
||||
* Quirks lower() function - Kiooeht [evacipatedBox]
|
||||
* Quirks scrabble() function - Kiooeht [evacipatedBox]
|
||||
* Timestamps - Kiooeht [evacipatedBox]
|
||||
* Logviewer - Kiooeht [evacipatedBox]
|
||||
* Chum list groups - Kiooeht [evacipatedBox]
|
||||
* Chum list bug fixes - Kiooeht [evacipatedBox]
|
3
TODO
3
TODO
|
@ -19,10 +19,7 @@ SS: and the arrows next to the time thing overlap the CLOSE button
|
|||
Features:
|
||||
* copy quirks between profiles?
|
||||
* help button on quirks menu?
|
||||
* chum list groups
|
||||
* More complex quirks: by-sound
|
||||
* log viewer
|
||||
* time codes
|
||||
* Theme checking
|
||||
* Spy mode
|
||||
* Animated
|
||||
|
|
16
convo.py
16
convo.py
|
@ -2,6 +2,7 @@ from string import Template
|
|||
import re
|
||||
import platform
|
||||
import httplib, urllib
|
||||
from time import strftime
|
||||
from copy import copy
|
||||
from datetime import datetime, timedelta
|
||||
from PyQt4 import QtGui, QtCore
|
||||
|
@ -221,6 +222,17 @@ class PesterText(QtGui.QTextEdit):
|
|||
parent = self.parent()
|
||||
window = parent.mainwindow
|
||||
me = window.profile()
|
||||
if self.parent().mainwindow.config.showTimeStamps():
|
||||
if self.parent().mainwindow.config.time12Format():
|
||||
time = strftime("[%I:%M")
|
||||
else:
|
||||
time = strftime("[%H:%M")
|
||||
if self.parent().mainwindow.config.showSeconds():
|
||||
time += strftime(":%S] ")
|
||||
else:
|
||||
time += "] "
|
||||
else:
|
||||
time = ""
|
||||
if lexmsg[0] == "PESTERCHUM:BEGIN":
|
||||
parent.setChumOpen(True)
|
||||
pmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
|
||||
|
@ -253,7 +265,7 @@ class PesterText(QtGui.QTextEdit):
|
|||
window.chatlog.log(parent.chum.handle, memsg)
|
||||
else:
|
||||
window.chatlog.log(chum.handle, memsg)
|
||||
self.append(convertTags(memsg))
|
||||
self.append(time + convertTags(memsg))
|
||||
else:
|
||||
if not parent.chumopen and chum is not me:
|
||||
beginmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"])
|
||||
|
@ -264,7 +276,7 @@ class PesterText(QtGui.QTextEdit):
|
|||
lexmsg[0:0] = [colorBegin("<c=%s>" % (color), color),
|
||||
"%s: " % (initials)]
|
||||
lexmsg.append(colorEnd("</c>"))
|
||||
self.append(convertTags(lexmsg))
|
||||
self.append(time + convertTags(lexmsg))
|
||||
if chum is me:
|
||||
window.chatlog.log(parent.chum.handle, lexmsg)
|
||||
else:
|
||||
|
|
25
dataobjs.py
25
dataobjs.py
|
@ -8,6 +8,8 @@ from parsetools import timeDifference, convertTags, lexMessage
|
|||
from mispeller import mispeller
|
||||
|
||||
_upperre = re.compile(r"upper\(([\w\\]+)\)")
|
||||
_lowerre = re.compile(r"lower\(([\w\\]+)\)")
|
||||
_scramblere = re.compile(r"scramble\(([\w\\]+)\)")
|
||||
|
||||
class Mood(object):
|
||||
moods = ["chummy", "rancorous", "offline", "pleasant", "distraught",
|
||||
|
@ -62,7 +64,13 @@ class pesterQuirk(object):
|
|||
to = self.quirk["to"]
|
||||
def upperrep(m):
|
||||
return mo.expand(m.group(1)).upper()
|
||||
def lowerrep(m):
|
||||
return mo.expand(m.group(1)).lower()
|
||||
def scramblerep(m):
|
||||
return "".join(random.sample(mo.expand(m.group(1)), len(mo.expand(m.group(1)))))
|
||||
to = _upperre.sub(upperrep, to)
|
||||
to = _lowerre.sub(lowerrep, to)
|
||||
to = _scramblere.sub(scramblerep, to)
|
||||
return mo.expand(to)
|
||||
return re.sub(fr, regexprep, string)
|
||||
elif self.type == "random":
|
||||
|
@ -77,6 +85,12 @@ class pesterQuirk(object):
|
|||
choice = random.choice(self.quirk["randomlist"])
|
||||
def upperrep(m):
|
||||
return mo.expand(m.group(1)).upper()
|
||||
def lowerrep(m):
|
||||
return mo.expand(m.group(1)).lower()
|
||||
def scramblerep(m):
|
||||
return "".join(random.sample(mo.expand(m.group(1)), len(mo.expand(m.group(1)))))
|
||||
choice = _upperre.sub(upperrep, choice)
|
||||
choice = _lowerre.sub(lowerrep, choice)
|
||||
choice = _upperre.sub(upperrep, choice)
|
||||
return mo.expand(choice)
|
||||
return re.sub(self.quirk["from"], randomrep, string)
|
||||
|
@ -167,7 +181,7 @@ class pesterQuirks(object):
|
|||
yield q
|
||||
|
||||
class PesterProfile(object):
|
||||
def __init__(self, handle, color=None, mood=Mood("offline"), chumdb=None):
|
||||
def __init__(self, handle, color=None, mood=Mood("offline"), group=None, chumdb=None):
|
||||
self.handle = handle
|
||||
if color is None:
|
||||
if chumdb:
|
||||
|
@ -176,6 +190,12 @@ class PesterProfile(object):
|
|||
color = QtGui.QColor("black")
|
||||
self.color = color
|
||||
self.mood = mood
|
||||
if group is None:
|
||||
if chumdb:
|
||||
group = chumdb.getGroup(handle, "Chums")
|
||||
else:
|
||||
group = "Chums"
|
||||
self.group = group
|
||||
def initials(self, time=None):
|
||||
handle = self.handle
|
||||
caps = [l for l in handle if l.isupper()]
|
||||
|
@ -205,7 +225,8 @@ class PesterProfile(object):
|
|||
def plaindict(self):
|
||||
return (self.handle, {"handle": self.handle,
|
||||
"mood": self.mood.name(),
|
||||
"color": unicode(self.color.name())})
|
||||
"color": unicode(self.color.name()),
|
||||
"group": unicode(self.group)})
|
||||
def blocked(self, config):
|
||||
return self.handle in config.getBlocklist()
|
||||
|
||||
|
|
|
@ -37,6 +37,13 @@ class RightClickList(QtGui.QListWidget):
|
|||
self.setCurrentItem(listing)
|
||||
self.optionsMenu.popup(event.globalPos())
|
||||
|
||||
class RightClickTree(QtGui.QTreeWidget):
|
||||
def contextMenuEvent(self, event):
|
||||
if event.reason() == QtGui.QContextMenuEvent.Mouse:
|
||||
listing = self.itemAt(event.pos())
|
||||
self.setCurrentItem(listing)
|
||||
self.optionsMenu.popup(event.globalPos())
|
||||
|
||||
class MultiTextDialog(QtGui.QDialog):
|
||||
def __init__(self, title, parent, *queries):
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
|
|
233
logviewer.py
Normal file
233
logviewer.py
Normal file
|
@ -0,0 +1,233 @@
|
|||
import os, sys
|
||||
import codecs
|
||||
import re
|
||||
from time import strftime, strptime
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from generic import RightClickList, RightClickTree
|
||||
from parsetools import convertTags
|
||||
from convo import PesterText
|
||||
|
||||
class PesterLogUserSelect(QtGui.QDialog):
|
||||
def __init__(self, config, theme, parent):
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setModal(False)
|
||||
self.config = config
|
||||
self.theme = theme
|
||||
self.parent = parent
|
||||
self.handle = parent.profile().handle
|
||||
if sys.platform != "darwin":
|
||||
self.logpath = "logs"
|
||||
else:
|
||||
self.logpath = _datadir+"logs"
|
||||
|
||||
self.setStyleSheet(self.theme["main/defaultwindow/style"])
|
||||
self.setWindowTitle("Pesterlogs")
|
||||
|
||||
instructions = QtGui.QLabel("Pick a memo or chumhandle:")
|
||||
|
||||
if os.path.exists("%s/%s" % (self.logpath, self.handle)):
|
||||
chumMemoList = os.listdir("%s/%s/" % (self.logpath, self.handle))
|
||||
else:
|
||||
chumMemoList = []
|
||||
chumslist = config.chums()
|
||||
for c in chumslist:
|
||||
if not c in chumMemoList:
|
||||
chumMemoList.append(c)
|
||||
chumMemoList.sort()
|
||||
|
||||
self.chumsBox = RightClickList(self)
|
||||
self.chumsBox.setStyleSheet(self.theme["main/chums/style"])
|
||||
self.chumsBox.optionsMenu = QtGui.QMenu(self)
|
||||
|
||||
for (i, t) in enumerate(chumMemoList):
|
||||
item = QtGui.QListWidgetItem(t)
|
||||
item.setTextColor(QtGui.QColor(self.theme["main/chums/userlistcolor"]))
|
||||
self.chumsBox.addItem(item)
|
||||
|
||||
self.cancel = QtGui.QPushButton("CANCEL", self)
|
||||
self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
|
||||
self, QtCore.SLOT('reject()'))
|
||||
self.ok = QtGui.QPushButton("OK", self)
|
||||
self.ok.setDefault(True)
|
||||
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
|
||||
self, QtCore.SLOT('viewActivatedLog()'))
|
||||
layout_ok = QtGui.QHBoxLayout()
|
||||
layout_ok.addWidget(self.cancel)
|
||||
layout_ok.addWidget(self.ok)
|
||||
|
||||
layout_0 = QtGui.QVBoxLayout()
|
||||
layout_0.addWidget(instructions)
|
||||
layout_0.addWidget(self.chumsBox)
|
||||
layout_0.addLayout(layout_ok)
|
||||
|
||||
self.setLayout(layout_0)
|
||||
|
||||
def selectedchum(self):
|
||||
return self.chumsBox.currentItem()
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def viewActivatedLog(self):
|
||||
selectedchum = self.selectedchum().text()
|
||||
if not hasattr(self, 'pesterlogviewer'):
|
||||
self.pesterlogviewer = None
|
||||
if not self.pesterlogviewer:
|
||||
self.pesterlogviewer = PesterLogViewer(selectedchum, self.config, self.theme, self.parent)
|
||||
self.connect(self.pesterlogviewer, QtCore.SIGNAL('rejected()'),
|
||||
self, QtCore.SLOT('closeActiveLog()'))
|
||||
self.pesterlogviewer.show()
|
||||
self.pesterlogviewer.raise_()
|
||||
self.pesterlogviewer.activateWindow()
|
||||
self.accept()
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def closeActiveLog(self):
|
||||
self.pesterlogviewer.close()
|
||||
self.pesterlogviewer = None
|
||||
|
||||
class PesterLogViewer(QtGui.QDialog):
|
||||
def __init__(self, chum, config, theme, parent):
|
||||
QtGui.QDialog.__init__(self, parent)
|
||||
self.setModal(False)
|
||||
self.config = config
|
||||
self.theme = theme
|
||||
self.parent = parent
|
||||
global _datadir
|
||||
self.handle = parent.profile().handle
|
||||
self.chum = chum
|
||||
self.convos = {}
|
||||
if sys.platform != "darwin":
|
||||
self.logpath = "logs"
|
||||
else:
|
||||
self.logpath = _datadir+"logs"
|
||||
|
||||
self.setStyleSheet(self.theme["main/defaultwindow/style"])
|
||||
self.setWindowTitle("Pesterlogs with " + self.chum)
|
||||
|
||||
self.format = "bbcode"
|
||||
if os.path.exists("%s/%s/%s/%s" % (self.logpath, self.handle, chum, self.format)):
|
||||
self.logList = os.listdir("%s/%s/%s/%s/" % (self.logpath, self.handle, self.chum, self.format))
|
||||
else:
|
||||
self.logList = []
|
||||
|
||||
if not os.path.exists("%s/%s/%s/%s" % (self.logpath, self.handle, chum, self.format)) or len(self.logList) == 0:
|
||||
instructions = QtGui.QLabel("No Pesterlogs were found")
|
||||
|
||||
self.ok = QtGui.QPushButton("CLOSE", self)
|
||||
self.ok.setDefault(True)
|
||||
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
|
||||
self, QtCore.SLOT('reject()'))
|
||||
layout_ok = QtGui.QHBoxLayout()
|
||||
layout_ok.addWidget(self.ok)
|
||||
|
||||
layout_0 = QtGui.QVBoxLayout()
|
||||
layout_0.addWidget(instructions)
|
||||
layout_0.addLayout(layout_ok)
|
||||
|
||||
self.setLayout(layout_0)
|
||||
else:
|
||||
self.instructions = QtGui.QLabel("Pesterlog with " +self.chum+ " on")
|
||||
|
||||
self.textArea = PesterLogText(theme, self.parent)
|
||||
self.textArea.setReadOnly(True)
|
||||
self.textArea.setFixedWidth(600)
|
||||
if theme.has_key("convo/scrollbar"):
|
||||
self.textArea.setStyleSheet("QTextEdit { width:500px; %s } QScrollBar:vertical { %s } QScrollBar::handle:vertical { %s } QScrollBar::add-line:vertical { %s } QScrollBar::sub-line:vertical { %s } QScrollBar:up-arrow:vertical { %s } QScrollBar:down-arrow:vertical { %s }" % (theme["convo/textarea/style"], theme["convo/scrollbar/style"], theme["convo/scrollbar/handle"], theme["convo/scrollbar/downarrow"], theme["convo/scrollbar/uparrow"], theme["convo/scrollbar/uarrowstyle"], theme["convo/scrollbar/darrowstyle"] ))
|
||||
else:
|
||||
self.textArea.setStyleSheet("QTextEdit { width:500px; %s }" % (theme["convo/textarea/style"]))
|
||||
|
||||
self.logList.sort()
|
||||
self.logList.reverse()
|
||||
|
||||
self.tree = RightClickTree()
|
||||
self.tree.optionsMenu = QtGui.QMenu(self)
|
||||
self.tree.setFixedSize(260, 300)
|
||||
self.tree.header().hide()
|
||||
if theme.has_key("convo/scrollbar"):
|
||||
self.tree.setStyleSheet("QTreeWidget { %s } QScrollBar:vertical { %s } QScrollBar::handle:vertical { %s } QScrollBar::add-line:vertical { %s } QScrollBar::sub-line:vertical { %s } QScrollBar:up-arrow:vertical { %s } QScrollBar:down-arrow:vertical { %s }" % (theme["convo/textarea/style"], theme["convo/scrollbar/style"], theme["convo/scrollbar/handle"], theme["convo/scrollbar/downarrow"], theme["convo/scrollbar/uparrow"], theme["convo/scrollbar/uarrowstyle"], theme["convo/scrollbar/darrowstyle"] ))
|
||||
else:
|
||||
self.tree.setStyleSheet("%s" % (theme["convo/textarea/style"]))
|
||||
self.connect(self.tree, QtCore.SIGNAL('itemSelectionChanged()'),
|
||||
self, QtCore.SLOT('loadSelectedLog()'))
|
||||
self.tree.setSortingEnabled(False)
|
||||
|
||||
child_1 = None
|
||||
last = ["",""]
|
||||
for (i,l) in enumerate(self.logList):
|
||||
my = self.fileToMonthYear(l)
|
||||
if my[0] != last[0]:
|
||||
child_1 = QtGui.QTreeWidgetItem(["%s %s" % (my[0], my[1])])
|
||||
self.tree.addTopLevelItem(child_1)
|
||||
if i == 0:
|
||||
child_1.setExpanded(True)
|
||||
child_1.addChild(QtGui.QTreeWidgetItem([self.fileToTime(l)]))
|
||||
last = self.fileToMonthYear(l)
|
||||
|
||||
if len(self.logList) > 0: self.loadLog(self.logList[0])
|
||||
|
||||
self.ok = QtGui.QPushButton("CLOSE", self)
|
||||
self.ok.setDefault(True)
|
||||
self.ok.setFixedWidth(80)
|
||||
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
|
||||
self, QtCore.SLOT('reject()'))
|
||||
layout_ok = QtGui.QHBoxLayout()
|
||||
layout_ok.addWidget(self.ok)
|
||||
layout_ok.setAlignment(self.ok, QtCore.Qt.AlignRight)
|
||||
|
||||
layout_logs = QtGui.QHBoxLayout()
|
||||
layout_logs.addWidget(self.tree)
|
||||
layout_logs.addWidget(self.textArea)
|
||||
|
||||
layout_0 = QtGui.QVBoxLayout()
|
||||
layout_0.addWidget(self.instructions)
|
||||
layout_0.addLayout(layout_logs)
|
||||
layout_0.addLayout(layout_ok)
|
||||
|
||||
self.setLayout(layout_0)
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def loadSelectedLog(self):
|
||||
if len(self.tree.currentItem().text(0)) > len("September 2011"):
|
||||
self.loadLog(self.timeToFile(self.tree.currentItem().text(0)))
|
||||
|
||||
def loadLog(self, fname):
|
||||
fp = codecs.open("%s/%s/%s/%s/%s" % (self.logpath, self.handle, self.chum, self.format, fname), encoding='utf-8', mode='r')
|
||||
self.textArea.clear()
|
||||
for line in fp:
|
||||
cline = line.replace("\r\n", "").replace("[/color]","</c>").replace("[url]","").replace("[/url]","")
|
||||
cline = re.sub("\[color=(#.{6})]", r"<c=\1>", cline)
|
||||
self.textArea.append(convertTags(cline))
|
||||
textCur = self.textArea.textCursor()
|
||||
textCur.movePosition(1)
|
||||
self.textArea.setTextCursor(textCur)
|
||||
self.instructions.setText("Pesterlog with " +self.chum+ " on " + self.fileToTime(str(fname)))
|
||||
|
||||
def fileToMonthYear(self, fname):
|
||||
time = strptime(fname[(fname.index(".")+1):fname.index(".txt")], "%Y-%m-%d.%H.%M")
|
||||
return [strftime("%B", time), strftime("%Y", time)]
|
||||
def fileToTime(self, fname):
|
||||
timestr = fname[(fname.index(".")+1):fname.index(".txt")]
|
||||
return strftime("%a %d %b %Y %H %M", strptime(timestr, "%Y-%m-%d.%H.%M"))
|
||||
def timeToFile(self, time):
|
||||
return self.chum + strftime(".%Y-%m-%d.%H.%M.txt", strptime(str(time), "%a %d %b %Y %H %M"))
|
||||
|
||||
class PesterLogText(PesterText):
|
||||
def __init__(self, theme, parent=None):
|
||||
PesterText.__init__(self, theme, parent)
|
||||
|
||||
def focusInEvent(self, event):
|
||||
QtGui.QTextEdit.focusInEvent(self, event)
|
||||
def mousePressEvent(self, event):
|
||||
url = self.anchorAt(event.pos())
|
||||
if url != "":
|
||||
if url[0] != "#":
|
||||
QtGui.QDesktopServices.openUrl(QtCore.QUrl(url, QtCore.QUrl.TolerantMode))
|
||||
QtGui.QTextEdit.mousePressEvent(self, event)
|
||||
def mouseMoveEvent(self, event):
|
||||
QtGui.QTextEdit.mouseMoveEvent(self, event)
|
||||
if self.anchorAt(event.pos()):
|
||||
if self.viewport().cursor().shape != QtCore.Qt.PointingHandCursor:
|
||||
url = self.anchorAt(event.pos())
|
||||
if url != "" and url[0] != "#":
|
||||
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
|
||||
else:
|
||||
self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))
|
38
menus.py
38
menus.py
|
@ -22,11 +22,7 @@ class PesterQuirkItem(QtGui.QListWidgetItem):
|
|||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
class PesterQuirkList(QtGui.QListWidget): #the quirklist
|
||||
#todo make an add function to insert quirks after selected quirk -- not done
|
||||
#todo function to shift selected quirk up and down, should keep selection the quirk being shifted -- done
|
||||
#todo maybe a click and drag? -- not done
|
||||
class PesterQuirkList(QtGui.QListWidget):
|
||||
def __init__(self, mainwindow, parent):
|
||||
QtGui.QListWidget.__init__(self, parent)
|
||||
self.resize(400, 200)
|
||||
|
@ -548,6 +544,10 @@ class PesterOptions(QtGui.QDialog):
|
|||
self.theme = theme
|
||||
self.setStyleSheet(self.theme["main/defaultwindow/style"])
|
||||
|
||||
hr = QtGui.QFrame()
|
||||
hr.setFrameShape(QtGui.QFrame.HLine)
|
||||
hr.setFrameShadow(QtGui.QFrame.Sunken)
|
||||
|
||||
self.tabcheck = QtGui.QCheckBox("Tabbed Conversations", self)
|
||||
if self.config.tabs():
|
||||
self.tabcheck.setChecked(True)
|
||||
|
@ -558,6 +558,28 @@ class PesterOptions(QtGui.QDialog):
|
|||
self.soundcheck = QtGui.QCheckBox("Sounds On", self)
|
||||
if self.config.soundOn():
|
||||
self.soundcheck.setChecked(True)
|
||||
|
||||
self.timestampcheck = QtGui.QCheckBox("Time Stamps", self)
|
||||
if self.config.showTimeStamps():
|
||||
self.timestampcheck.setChecked(True)
|
||||
|
||||
self.timestampBox = QtGui.QComboBox(self)
|
||||
self.timestampBox.addItem("12 hour")
|
||||
self.timestampBox.addItem("24 hour")
|
||||
if self.config.time12Format():
|
||||
self.timestampBox.setCurrentIndex(0)
|
||||
else:
|
||||
self.timestampBox.setCurrentIndex(1)
|
||||
self.secondscheck = QtGui.QCheckBox("Show Seconds", self)
|
||||
if self.config.showSeconds():
|
||||
self.secondscheck.setChecked(True)
|
||||
|
||||
# Will add ability to turn off groups later
|
||||
#self.groupscheck = QtGui.QCheckBox("Use Groups", self)
|
||||
#self.groupscheck.setChecked(self.config.useGroups())
|
||||
self.showemptycheck = QtGui.QCheckBox("Show Empty Groups", self)
|
||||
self.showemptycheck.setChecked(self.config.showEmptyGroups())
|
||||
|
||||
self.ok = QtGui.QPushButton("OK", self)
|
||||
self.ok.setDefault(True)
|
||||
self.connect(self.ok, QtCore.SIGNAL('clicked()'),
|
||||
|
@ -573,6 +595,12 @@ class PesterOptions(QtGui.QDialog):
|
|||
layout_0.addWidget(self.tabcheck)
|
||||
layout_0.addWidget(self.soundcheck)
|
||||
layout_0.addWidget(self.hideOffline)
|
||||
#layout_0.addWidget(self.groupscheck)
|
||||
layout_0.addWidget(self.showemptycheck)
|
||||
layout_0.addWidget(hr)
|
||||
layout_0.addWidget(self.timestampcheck)
|
||||
layout_0.addWidget(self.timestampBox)
|
||||
layout_0.addWidget(self.secondscheck)
|
||||
layout_0.addLayout(layout_2)
|
||||
|
||||
self.setLayout(layout_0)
|
||||
|
|
467
pesterchum.py
467
pesterchum.py
|
@ -12,16 +12,18 @@ import socket
|
|||
import platform
|
||||
from PyQt4 import QtGui, QtCore
|
||||
import pygame
|
||||
from time import strftime
|
||||
|
||||
from menus import PesterChooseQuirks, PesterChooseTheme, \
|
||||
PesterChooseProfile, PesterOptions, PesterUserlist, PesterMemoList, \
|
||||
LoadingScreen, AboutPesterchum
|
||||
from dataobjs import PesterProfile, Mood, pesterQuirk, pesterQuirks
|
||||
from generic import PesterIcon, RightClickList, MultiTextDialog, PesterList
|
||||
from generic import PesterIcon, RightClickList, RightClickTree, MultiTextDialog, PesterList
|
||||
from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo
|
||||
from parsetools import convertTags, addTimeInitial
|
||||
from memos import PesterMemo, MemoTabWindow, TimeTracker
|
||||
from irc import PesterIRC
|
||||
from logviewer import PesterLogUserSelect, PesterLogViewer
|
||||
|
||||
_datadir = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.DataLocation)+"Pesterchum/"
|
||||
|
||||
|
@ -76,9 +78,10 @@ class PesterLog(object):
|
|||
self.logpath = _datadir+"logs"
|
||||
|
||||
def log(self, handle, msg):
|
||||
bbcodemsg = convertTags(msg, "bbcode")
|
||||
html = convertTags(msg, "html")+"<br />"
|
||||
msg = convertTags(msg, "text")
|
||||
time = strftime("[%H:%M:%S] ")
|
||||
bbcodemsg = time + convertTags(msg, "bbcode")
|
||||
html = time + convertTags(msg, "html")+"<br />"
|
||||
msg = time + convertTags(msg, "text")
|
||||
modes = {"bbcode": bbcodemsg, "html": html, "text": msg}
|
||||
if not self.convos.has_key(handle):
|
||||
time = datetime.now().strftime("%Y-%m-%d.%H.%M")
|
||||
|
@ -128,7 +131,14 @@ class PesterProfileDB(dict):
|
|||
json.dump(chumdict, fp)
|
||||
fp.close()
|
||||
|
||||
converted = dict([(handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']))) for (handle, c) in chumdict.iteritems()])
|
||||
u = []
|
||||
for (handle, c) in chumdict.iteritems():
|
||||
try:
|
||||
g = c['group']
|
||||
u.append((handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']), group=g)))
|
||||
except KeyError:
|
||||
u.append((handle, PesterProfile(handle, color=QtGui.QColor(c['color']), mood=Mood(c['mood']))))
|
||||
converted = dict(u)
|
||||
self.update(converted)
|
||||
|
||||
def save(self):
|
||||
|
@ -149,6 +159,17 @@ class PesterProfileDB(dict):
|
|||
self[handle].color = color
|
||||
else:
|
||||
self[handle] = PesterProfile(handle, color)
|
||||
def getGroup(self, handle, default="Chums"):
|
||||
if not self.has_key(handle):
|
||||
return default
|
||||
else:
|
||||
return self[handle].group
|
||||
def setGroup(self, handle, theGroup):
|
||||
if self.has_key(handle):
|
||||
self[handle].group = theGroup
|
||||
else:
|
||||
self[handle] = PesterProfile(handle, group=theGroup)
|
||||
self.save()
|
||||
def __setitem__(self, key, val):
|
||||
dict.__setitem__(self, key, val)
|
||||
self.save()
|
||||
|
@ -249,6 +270,30 @@ class userConfig(object):
|
|||
return None
|
||||
def tabs(self):
|
||||
return self.config.get("tabs", True)
|
||||
def showTimeStamps(self):
|
||||
if not self.config.has_key('showTimeStamps'):
|
||||
self.set("showTimeStamps", True)
|
||||
return self.config.get('showTimeStamps', True)
|
||||
def time12Format(self):
|
||||
if not self.config.has_key('time12Format'):
|
||||
self.set("time12Format", True)
|
||||
return self.config.get('time12Format', True)
|
||||
def showSeconds(self):
|
||||
if not self.config.has_key('showSeconds'):
|
||||
self.set("showSeconds", False)
|
||||
return self.config.get('showSeconds', False)
|
||||
def useGroups(self):
|
||||
if not self.config.has_key('useGroups'):
|
||||
self.set("useGroups", False)
|
||||
return self.config.get('useGroups', False)
|
||||
def openDefaultGroup(self):
|
||||
if not self.config.has_key('openDefaultGroup'):
|
||||
self.set("openDefaultGroup", True)
|
||||
return self.config.get('openDefaultGroup', True)
|
||||
def showEmptyGroups(self):
|
||||
if not self.config.has_key('emptyGroups'):
|
||||
self.set("emptyGroups", False)
|
||||
return self.config.get('emptyGroups', False)
|
||||
def addChum(self, chum):
|
||||
if chum.handle not in self.chums():
|
||||
fp = open(self.filename) # what if we have two clients open??
|
||||
|
@ -276,6 +321,25 @@ class userConfig(object):
|
|||
l = self.getBlocklist()
|
||||
l.pop(l.index(handle))
|
||||
self.set('block', l)
|
||||
def getGroups(self):
|
||||
if not self.config.has_key('groups'):
|
||||
self.set('groups', [])
|
||||
return self.config.get('groups', [])
|
||||
def addGroup(self, group, open=False):
|
||||
l = self.getGroups()
|
||||
if group not in l:
|
||||
l.append([group,open])
|
||||
l.sort()
|
||||
self.set('groups', l)
|
||||
def delGroup(self, group):
|
||||
l = self.getGroups()
|
||||
i = 0
|
||||
for g in l:
|
||||
if g[0] == group: break
|
||||
i = i+1
|
||||
l.pop(i)
|
||||
l.sort()
|
||||
self.set('groups', l)
|
||||
def server(self):
|
||||
return self.config.get('server', 'irc.mindfang.org')
|
||||
def port(self):
|
||||
|
@ -389,9 +453,9 @@ class WMButton(QtGui.QPushButton):
|
|||
self.setStyleSheet("QPushButton { padding: 0px; }")
|
||||
self.setAutoDefault(False)
|
||||
|
||||
class chumListing(QtGui.QListWidgetItem):
|
||||
class chumListing(QtGui.QTreeWidgetItem):
|
||||
def __init__(self, chum, window):
|
||||
QtGui.QListWidgetItem.__init__(self, chum.handle)
|
||||
QtGui.QTreeWidgetItem.__init__(self, [chum.handle])
|
||||
self.mainwindow = window
|
||||
self.chum = chum
|
||||
self.handle = chum.handle
|
||||
|
@ -405,32 +469,44 @@ class chumListing(QtGui.QListWidgetItem):
|
|||
mood = self.chum.mood
|
||||
self.mood = mood
|
||||
icon = self.mood.icon(self.mainwindow.theme)
|
||||
self.setIcon(icon)
|
||||
self.setIcon(0, icon)
|
||||
try:
|
||||
self.setTextColor(QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
|
||||
self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
|
||||
except KeyError:
|
||||
self.setTextColor(QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"]))
|
||||
self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"]))
|
||||
def changeTheme(self, theme):
|
||||
icon = self.mood.icon(theme)
|
||||
self.setIcon(icon)
|
||||
self.setIcon(0, icon)
|
||||
try:
|
||||
self.setTextColor(QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
|
||||
self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
|
||||
except KeyError:
|
||||
self.setTextColor(QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"]))
|
||||
self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"]))
|
||||
def __lt__(self, cl):
|
||||
h1 = self.handle.lower()
|
||||
h2 = cl.handle.lower()
|
||||
return (h1 < h2)
|
||||
|
||||
class chumArea(RightClickList):
|
||||
class chumArea(RightClickTree):
|
||||
def __init__(self, chums, parent=None):
|
||||
QtGui.QListWidget.__init__(self, parent)
|
||||
QtGui.QTreeWidget.__init__(self, parent)
|
||||
self.mainwindow = parent
|
||||
theme = self.mainwindow.theme
|
||||
self.chums = chums
|
||||
gTemp = self.mainwindow.config.getGroups()
|
||||
self.groups = [g[0] for g in gTemp]
|
||||
self.openGroups = [g[1] for g in gTemp]
|
||||
# quick hack to sort saved groups
|
||||
self.mainwindow.config.addGroup("f3rskv9dssag[%3ffvsla09iv34G#$v")
|
||||
self.mainwindow.config.delGroup("f3rskv9dssag[%3ffvsla09iv34G#$v")
|
||||
# end quick hack
|
||||
self.showAllGroups()
|
||||
if not self.mainwindow.config.hideOfflineChums():
|
||||
self.showAllChums()
|
||||
self.optionsMenu = QtGui.QMenu(self)
|
||||
if not self.mainwindow.config.showEmptyGroups():
|
||||
self.hideEmptyGroups()
|
||||
self.chumoptions = QtGui.QMenu(self)
|
||||
self.groupoptions = QtGui.QMenu(self)
|
||||
self.optionsMenu = self.chumoptions
|
||||
self.pester = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self)
|
||||
self.connect(self.pester, QtCore.SIGNAL('triggered()'),
|
||||
self, QtCore.SLOT('activateChum()'))
|
||||
|
@ -440,12 +516,86 @@ class chumArea(RightClickList):
|
|||
self.blockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
|
||||
self.connect(self.blockchum, QtCore.SIGNAL('triggered()'),
|
||||
self, QtCore.SLOT('blockChum()'))
|
||||
self.optionsMenu.addAction(self.pester)
|
||||
self.optionsMenu.addAction(self.blockchum)
|
||||
self.optionsMenu.addAction(self.removechum)
|
||||
self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
|
||||
self.connect(self.logchum, QtCore.SIGNAL('triggered()'),
|
||||
self, QtCore.SLOT('openChumLogs()'))
|
||||
|
||||
self.removegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/removegroup"], self)
|
||||
self.connect(self.removegroup, QtCore.SIGNAL('triggered()'),
|
||||
self, QtCore.SLOT('removeGroup()'))
|
||||
self.renamegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/renamegroup"], self)
|
||||
self.connect(self.renamegroup, QtCore.SIGNAL('triggered()'),
|
||||
self, QtCore.SLOT('renameGroup()'))
|
||||
self.chumoptions.addAction(self.pester)
|
||||
self.chumoptions.addAction(self.logchum)
|
||||
self.chumoptions.addAction(self.blockchum)
|
||||
self.chumoptions.addAction(self.removechum)
|
||||
self.moveMenu = QtGui.QMenu(self.mainwindow.theme["main/menus/rclickchumlist/movechum"], self)
|
||||
self.chumoptions.addMenu(self.moveMenu)
|
||||
self.moveGroupMenu()
|
||||
|
||||
self.groupoptions.addAction(self.renamegroup)
|
||||
self.groupoptions.addAction(self.removegroup)
|
||||
|
||||
self.initTheme(theme)
|
||||
self.sortItems()
|
||||
#self.sortItems()
|
||||
#self.sortItems(1, QtCore.Qt.AscendingOrder)
|
||||
self.setSortingEnabled(False)
|
||||
self.header().hide()
|
||||
self.setDropIndicatorShown(False)
|
||||
self.setIndentation(0)
|
||||
self.setDragEnabled(True)
|
||||
self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
|
||||
|
||||
self.connect(self, QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem *, int)'),
|
||||
self, QtCore.SLOT('expandGroup()'))
|
||||
|
||||
def dropEvent(self, event):
|
||||
item = self.itemAt(event.pos())
|
||||
if item:
|
||||
if item.text(0) == "Chums" or item.text(0) in self.groups:
|
||||
group = item.text(0)
|
||||
else:
|
||||
group = item.parent().text(0)
|
||||
chumLabel = event.source().currentItem()
|
||||
chumLabel.chum.group = group
|
||||
self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, group)
|
||||
self.takeItem(chumLabel)
|
||||
self.addItem(chumLabel)
|
||||
|
||||
def chumoptionsmenu(self):
|
||||
self.optionsMenu = self.chumoptions
|
||||
def groupoptionsmenu(self):
|
||||
self.optionsMenu = self.groupoptions
|
||||
def moveGroupMenu(self):
|
||||
currentGroup = self.currentItem()
|
||||
if currentGroup:
|
||||
currentGroup = currentGroup.parent().text(0)
|
||||
self.moveMenu.clear()
|
||||
actGroup = QtGui.QActionGroup(self)
|
||||
|
||||
groups = self.groups[:]
|
||||
groups.insert(0, "Chums")
|
||||
for gtext in groups:
|
||||
if gtext == currentGroup:
|
||||
continue
|
||||
movegroup = self.moveMenu.addAction(gtext)
|
||||
actGroup.addAction(movegroup)
|
||||
self.connect(actGroup, QtCore.SIGNAL('triggered(QAction *)'),
|
||||
self, QtCore.SLOT('moveToGroup(QAction *)'))
|
||||
def contextMenuEvent(self, event):
|
||||
#fuckin Qt
|
||||
if event.reason() == QtGui.QContextMenuEvent.Mouse:
|
||||
listing = self.itemAt(event.pos())
|
||||
self.setCurrentItem(listing)
|
||||
if self.currentItem().text(0) == "Chums" or \
|
||||
self.currentItem().text(0) in self.groups:
|
||||
self.groupoptionsmenu()
|
||||
else:
|
||||
self.chumoptionsmenu()
|
||||
self.moveGroupMenu()
|
||||
self.optionsMenu.popup(event.globalPos())
|
||||
|
||||
def addChum(self, chum):
|
||||
if len([c for c in self.chums if c.handle == chum.handle]) != 0:
|
||||
return
|
||||
|
@ -454,29 +604,95 @@ class chumArea(RightClickList):
|
|||
chum.mood.name() == "offline"):
|
||||
chumLabel = chumListing(chum, self.mainwindow)
|
||||
self.addItem(chumLabel)
|
||||
self.sortItems()
|
||||
#self.topLevelItem(0).addChild(chumLabel)
|
||||
#self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
|
||||
|
||||
def getChums(self, handle):
|
||||
chums = self.findItems(handle, QtCore.Qt.MatchFlags(0))
|
||||
chums = self.findItems(handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive)
|
||||
return chums
|
||||
|
||||
def showAllChums(self):
|
||||
for c in self.chums:
|
||||
chandle = c.handle
|
||||
if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)):
|
||||
if not len(self.findItems(chandle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive)):
|
||||
chumLabel = chumListing(c, self.mainwindow)
|
||||
self.addItem(chumLabel)
|
||||
self.sortItems()
|
||||
#self.sortItems()
|
||||
def hideOfflineChums(self):
|
||||
for j in range(self.topLevelItemCount()):
|
||||
i = 0
|
||||
listing = self.item(i)
|
||||
listing = self.topLevelItem(j).child(i)
|
||||
while listing is not None:
|
||||
if listing.chum.mood.name() == "offline":
|
||||
self.takeItem(i)
|
||||
self.topLevelItem(j).takeChild(i)
|
||||
else:
|
||||
i += 1
|
||||
listing = self.item(i)
|
||||
self.sortItems()
|
||||
listing = self.topLevelItem(j).child(i)
|
||||
self.topLevelItem(j).sortChildren(0, QtCore.Qt.AscendingOrder)
|
||||
def showAllGroups(self):
|
||||
curgroups = []
|
||||
for i in range(self.topLevelItemCount()):
|
||||
curgroups.append(self.topLevelItem(i).text(0))
|
||||
if "Chums" not in curgroups:
|
||||
child_1 = QtGui.QTreeWidgetItem(["Chums"])
|
||||
self.addTopLevelItem(child_1)
|
||||
if self.mainwindow.config.openDefaultGroup():
|
||||
child_1.setExpanded(True)
|
||||
for i,g in enumerate(self.groups):
|
||||
if g not in curgroups:
|
||||
child_1 = QtGui.QTreeWidgetItem(["%s" % (g)])
|
||||
self.addTopLevelItem(child_1)
|
||||
if self.openGroups[i]:
|
||||
child_1.setExpanded(True)
|
||||
def hideEmptyGroups(self):
|
||||
i = 0
|
||||
listing = self.topLevelItem(i)
|
||||
while listing is not None:
|
||||
if listing.childCount() == 0:
|
||||
self.takeTopLevelItem(i)
|
||||
else:
|
||||
i += 1
|
||||
listing = self.topLevelItem(i)
|
||||
@QtCore.pyqtSlot()
|
||||
def expandGroup(self):
|
||||
item = self.currentItem()
|
||||
if item.text(0) in self.groups:
|
||||
self.mainwindow.config.delGroup(str(item.text(0)))
|
||||
expand = item.isExpanded()
|
||||
self.mainwindow.config.addGroup(str(item.text(0)), not expand)
|
||||
elif item.text(0) == "Chums":
|
||||
self.mainwindow.config.set("openDefaultGroup", not item.isExpanded())
|
||||
def addItem(self, chumLabel):
|
||||
if hasattr(self, 'groups'):
|
||||
if chumLabel.chum.group not in self.groups:
|
||||
self.topLevelItem(0).addChild(chumLabel)
|
||||
self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
|
||||
else:
|
||||
if not self.findItems(chumLabel.handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive):
|
||||
if not self.findItems(chumLabel.chum.group, QtCore.Qt.MatchFlags(0)):
|
||||
child_1 = QtGui.QTreeWidgetItem(["%s" % (chumLabel.chum.group)])
|
||||
self.addTopLevelItem(child_1)
|
||||
if self.openGroups[self.groups.index("%s" % (chumLabel.chum.group))]:
|
||||
child_1.setExpanded(True)
|
||||
for i in range(self.topLevelItemCount()):
|
||||
if self.topLevelItem(i).text(0) == chumLabel.chum.group:
|
||||
break
|
||||
self.topLevelItem(i).addChild(chumLabel)
|
||||
self.topLevelItem(i).sortChildren(0, QtCore.Qt.AscendingOrder)
|
||||
else: # usually means this is now the trollslum
|
||||
if not self.findItems(chumLabel.handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive):
|
||||
self.topLevelItem(0).addChild(chumLabel)
|
||||
self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
|
||||
def takeItem(self, chumLabel):
|
||||
r = None
|
||||
for i in range(self.topLevelItemCount()):
|
||||
for j in range(self.topLevelItem(i).childCount()):
|
||||
if self.topLevelItem(i).child(j).text(0) == chumLabel.chum.handle:
|
||||
r = self.topLevelItem(i).takeChild(j)
|
||||
break
|
||||
if not self.mainwindow.config.showEmptyGroups():
|
||||
self.hideEmptyGroups()
|
||||
return r
|
||||
def updateMood(self, handle, mood):
|
||||
hideoff = self.mainwindow.config.hideOfflineChums()
|
||||
chums = self.getChums(handle)
|
||||
|
@ -487,7 +703,7 @@ class chumArea(RightClickList):
|
|||
handle in [p.handle for p in self.chums]:
|
||||
newLabel = chumListing([p for p in self.chums if p.handle == handle][0], self.mainwindow)
|
||||
self.addItem(newLabel)
|
||||
self.sortItems()
|
||||
#self.sortItems()
|
||||
chums = [newLabel]
|
||||
elif mood.name() == "offline" and \
|
||||
len(chums) > 0:
|
||||
|
@ -512,14 +728,28 @@ class chumArea(RightClickList):
|
|||
self.pester.setText(theme["main/menus/rclickchumlist/pester"])
|
||||
self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
|
||||
self.blockchum.setText(theme["main/menus/rclickchumlist/blockchum"])
|
||||
self.logchum.setText(theme["main/menus/rclickchumlist/viewlog"])
|
||||
self.removegroup.setText(theme["main/menus/rclickchumlist/removegroup"])
|
||||
self.renamegroup.setText(theme["main/menus/rclickchumlist/renamegroup"])
|
||||
self.moveMenu.setTitle(theme["main/menus/rclickchumlist/movechum"])
|
||||
def changeTheme(self, theme):
|
||||
self.initTheme(theme)
|
||||
chumlistings = [self.item(i) for i in range(0, self.count())]
|
||||
chumlistings = []
|
||||
for i in range(self.topLevelItemCount()):
|
||||
for j in range(self.topLevelItem(i).childCount()):
|
||||
chumlistings.append(self.topLevelItem(i).child(j))
|
||||
#chumlistings = [self.item(i) for i in range(0, self.count())]
|
||||
for c in chumlistings:
|
||||
c.changeTheme(theme)
|
||||
|
||||
def count(self):
|
||||
c = 0
|
||||
for i in range(self.topLevelItemCount()):
|
||||
c = c + self.topLevelItem(i).childCount()
|
||||
return c
|
||||
@QtCore.pyqtSlot()
|
||||
def activateChum(self):
|
||||
self.itemActivated.emit(self.currentItem())
|
||||
self.itemActivated.emit(self.currentItem(), 0)
|
||||
@QtCore.pyqtSlot()
|
||||
def removeChum(self, handle = None):
|
||||
if handle:
|
||||
|
@ -530,8 +760,8 @@ class chumArea(RightClickList):
|
|||
return
|
||||
currentChum = self.currentItem().chum
|
||||
self.chums = [c for c in self.chums if c.handle != currentChum.handle]
|
||||
self.removeChumSignal.emit(self.currentItem())
|
||||
oldlist = self.takeItem(self.currentRow())
|
||||
self.removeChumSignal.emit(self.currentItem().chum.handle)
|
||||
oldlist = self.takeItem(self.currentItem())
|
||||
del oldlist
|
||||
@QtCore.pyqtSlot()
|
||||
def blockChum(self):
|
||||
|
@ -539,8 +769,78 @@ class chumArea(RightClickList):
|
|||
if not currentChum:
|
||||
return
|
||||
self.blockChumSignal.emit(self.currentItem().chum.handle)
|
||||
@QtCore.pyqtSlot()
|
||||
def openChumLogs(self):
|
||||
currentChum = self.currentItem().text(0)
|
||||
if not currentChum:
|
||||
return
|
||||
self.pesterlogviewer = PesterLogViewer(currentChum, self.mainwindow.config, self.mainwindow.theme, self.mainwindow)
|
||||
self.connect(self.pesterlogviewer, QtCore.SIGNAL('rejected()'),
|
||||
self, QtCore.SLOT('closeActiveLog()'))
|
||||
self.pesterlogviewer.show()
|
||||
self.pesterlogviewer.raise_()
|
||||
self.pesterlogviewer.activateWindow()
|
||||
@QtCore.pyqtSlot()
|
||||
def closeActiveLog(self):
|
||||
self.pesterlogviewer.close()
|
||||
self.pesterlogviewer = None
|
||||
@QtCore.pyqtSlot()
|
||||
def renameGroup(self):
|
||||
if not hasattr(self, 'renamegroupdialog'):
|
||||
self.renamegroupdialog = None
|
||||
if not self.renamegroupdialog:
|
||||
(gname, ok) = QtGui.QInputDialog.getText(self, "Rename Group", "Enter a new name for the group:")
|
||||
if ok:
|
||||
gname = unicode(gname)
|
||||
currentGroup = self.currentItem()
|
||||
if not currentGroup:
|
||||
return
|
||||
index = self.indexOfTopLevelItem(currentGroup)
|
||||
if index != -1:
|
||||
expanded = currentGroup.isExpanded()
|
||||
self.mainwindow.config.delGroup(str(currentGroup.text(0)))
|
||||
self.mainwindow.config.addGroup(gname, expanded)
|
||||
gTemp = self.mainwindow.config.getGroups()
|
||||
self.groups = [g[0] for g in gTemp]
|
||||
self.openGroups = [g[1] for g in gTemp]
|
||||
for i in range(currentGroup.childCount()):
|
||||
currentGroup.child(i).chum.group = gname
|
||||
self.mainwindow.chumdb.setGroup(currentGroup.child(i).chum.handle, gname)
|
||||
currentGroup.setText(0, gname)
|
||||
self.renamegroupdialog = None
|
||||
@QtCore.pyqtSlot()
|
||||
def removeGroup(self):
|
||||
currentGroup = self.currentItem()
|
||||
if not currentGroup:
|
||||
return
|
||||
self.mainwindow.config.delGroup(currentGroup.text(0))
|
||||
gTemp = self.mainwindow.config.getGroups()
|
||||
self.groups = [g[0] for g in gTemp]
|
||||
self.openGroups = [g[1] for g in gTemp]
|
||||
for i in range(self.topLevelItemCount()):
|
||||
if self.topLevelItem(i).text(0) == currentGroup.text(0):
|
||||
break
|
||||
while self.topLevelItem(i) and self.topLevelItem(i).child(0):
|
||||
chumLabel = self.topLevelItem(i).child(0)
|
||||
chumLabel.chum.group = "Chums"
|
||||
self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, "Chums")
|
||||
self.takeItem(chumLabel)
|
||||
self.addItem(chumLabel)
|
||||
self.takeTopLevelItem(i)
|
||||
@QtCore.pyqtSlot(QtGui.QAction)
|
||||
def moveToGroup(self, item):
|
||||
if not item:
|
||||
return
|
||||
group = str(item.text())
|
||||
chumLabel = self.currentItem()
|
||||
if not chumLabel:
|
||||
return
|
||||
chumLabel.chum.group = group
|
||||
self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, group)
|
||||
self.takeItem(chumLabel)
|
||||
self.addItem(chumLabel)
|
||||
|
||||
removeChumSignal = QtCore.pyqtSignal(QtGui.QListWidgetItem)
|
||||
removeChumSignal = QtCore.pyqtSignal(QtCore.QString)
|
||||
blockChumSignal = QtCore.pyqtSignal(QtCore.QString)
|
||||
|
||||
class trollSlum(chumArea):
|
||||
|
@ -550,19 +850,34 @@ class trollSlum(chumArea):
|
|||
theme = self.mainwindow.theme
|
||||
self.setStyleSheet(theme["main/trollslum/chumroll/style"])
|
||||
self.chums = trolls
|
||||
child_1 = QtGui.QTreeWidgetItem([""])
|
||||
self.addTopLevelItem(child_1)
|
||||
child_1.setExpanded(True)
|
||||
for c in self.chums:
|
||||
chandle = c.handle
|
||||
if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)):
|
||||
chumLabel = chumListing(c, self.mainwindow)
|
||||
self.addItem(chumLabel)
|
||||
|
||||
self.setSortingEnabled(False)
|
||||
self.header().hide()
|
||||
self.setDropIndicatorShown(False)
|
||||
self.setIndentation(0)
|
||||
|
||||
self.optionsMenu = QtGui.QMenu(self)
|
||||
self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
|
||||
self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'),
|
||||
self, QtCore.SIGNAL('unblockChumSignal()'))
|
||||
self.optionsMenu.addAction(self.unblockchum)
|
||||
|
||||
self.sortItems()
|
||||
#self.sortItems()
|
||||
def contextMenuEvent(self, event):
|
||||
#fuckin Qt
|
||||
if event.reason() == QtGui.QContextMenuEvent.Mouse:
|
||||
listing = self.itemAt(event.pos())
|
||||
self.setCurrentItem(listing)
|
||||
if self.currentItem().text(0) != "":
|
||||
self.optionsMenu.popup(event.globalPos())
|
||||
def changeTheme(self, theme):
|
||||
self.setStyleSheet(theme["main/trollslum/chumroll/style"])
|
||||
self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
|
||||
|
@ -775,6 +1090,14 @@ class PesterWindow(MovingWindow):
|
|||
|
||||
self.move(100, 100)
|
||||
|
||||
logv = QtGui.QAction(self.theme["main/menus/client/logviewer"], self)
|
||||
self.logv = logv
|
||||
self.connect(logv, QtCore.SIGNAL('triggered()'),
|
||||
self, QtCore.SLOT('openLogv()'))
|
||||
grps = QtGui.QAction(self.theme["main/menus/client/addgroup"], self)
|
||||
self.grps = grps
|
||||
self.connect(grps, QtCore.SIGNAL('triggered()'),
|
||||
self, QtCore.SLOT('addGroupWindow()'))
|
||||
opts = QtGui.QAction(self.theme["main/menus/client/options"], self)
|
||||
self.opts = opts
|
||||
self.connect(opts, QtCore.SIGNAL('triggered()'),
|
||||
|
@ -808,8 +1131,10 @@ class PesterWindow(MovingWindow):
|
|||
self.filemenu = filemenu
|
||||
filemenu.addAction(opts)
|
||||
filemenu.addAction(memoaction)
|
||||
filemenu.addAction(logv)
|
||||
filemenu.addAction(userlistaction)
|
||||
filemenu.addAction(self.idleaction)
|
||||
filemenu.addAction(grps)
|
||||
filemenu.addAction(self.importaction)
|
||||
filemenu.addAction(self.reconnectAction)
|
||||
filemenu.addAction(exitaction)
|
||||
|
@ -870,13 +1195,13 @@ class PesterWindow(MovingWindow):
|
|||
chums = [PesterProfile(c, chumdb=self.chumdb) for c in set(self.config.chums())]
|
||||
self.chumList = chumArea(chums, self)
|
||||
self.connect(self.chumList,
|
||||
QtCore.SIGNAL('itemActivated(QListWidgetItem *)'),
|
||||
QtCore.SIGNAL('itemActivated(QTreeWidgetItem *, int)'),
|
||||
self,
|
||||
QtCore.SLOT('newConversationWindow(QListWidgetItem *)'))
|
||||
QtCore.SLOT('pesterSelectedChum()'))
|
||||
self.connect(self.chumList,
|
||||
QtCore.SIGNAL('removeChumSignal(QListWidgetItem *)'),
|
||||
QtCore.SIGNAL('removeChumSignal(QString)'),
|
||||
self,
|
||||
QtCore.SLOT('removeChum(QListWidgetItem *)'))
|
||||
QtCore.SLOT('removeChum(QString)'))
|
||||
self.connect(self.chumList,
|
||||
QtCore.SIGNAL('blockChumSignal(QString)'),
|
||||
self,
|
||||
|
@ -1105,6 +1430,8 @@ class PesterWindow(MovingWindow):
|
|||
self.miniButton.move(*theme["main/minimize/loc"])
|
||||
# menus
|
||||
self.menu.move(*theme["main/menu/loc"])
|
||||
self.logv.setText(theme["main/menus/client/logviewer"])
|
||||
self.grps.setText(theme["main/menus/client/addgroup"])
|
||||
self.opts.setText(theme["main/menus/client/options"])
|
||||
self.exitaction.setText(theme["main/menus/client/exit"])
|
||||
self.userlistaction.setText(theme["main/menus/client/userlist"])
|
||||
|
@ -1259,6 +1586,8 @@ class PesterWindow(MovingWindow):
|
|||
def pesterSelectedChum(self):
|
||||
curChum = self.chumList.currentItem()
|
||||
if curChum:
|
||||
if curChum.text(0) not in self.chumList.groups and \
|
||||
curChum.text(0) != "Chums":
|
||||
self.newConversationWindow(curChum)
|
||||
@QtCore.pyqtSlot(QtGui.QListWidgetItem)
|
||||
def newConversationWindow(self, chumlisting):
|
||||
|
@ -1388,9 +1717,9 @@ class PesterWindow(MovingWindow):
|
|||
chum = PesterProfile(handle, chumdb=self.chumdb)
|
||||
self.addChum(chum)
|
||||
self.addchumdialog = None
|
||||
@QtCore.pyqtSlot(QtGui.QListWidgetItem)
|
||||
@QtCore.pyqtSlot(QtCore.QString)
|
||||
def removeChum(self, chumlisting):
|
||||
self.config.removeChum(chumlisting.chum)
|
||||
self.config.removeChum(chumlisting)
|
||||
@QtCore.pyqtSlot(QtCore.QString)
|
||||
def blockChum(self, handle):
|
||||
h = unicode(handle)
|
||||
|
@ -1584,6 +1913,42 @@ class PesterWindow(MovingWindow):
|
|||
def closeQuirks(self):
|
||||
self.quirkmenu = None
|
||||
@QtCore.pyqtSlot()
|
||||
def openLogv(self):
|
||||
if not hasattr(self, 'logusermenu'):
|
||||
self.logusermenu = None
|
||||
if not self.logusermenu:
|
||||
self.logusermenu = PesterLogUserSelect(self.config, self.theme, self)
|
||||
self.connect(self.logusermenu, QtCore.SIGNAL('accepted()'),
|
||||
self, QtCore.SLOT('closeLogUsers()'))
|
||||
self.connect(self.logusermenu, QtCore.SIGNAL('rejected()'),
|
||||
self, QtCore.SLOT('closeLogUsers()'))
|
||||
self.logusermenu.show()
|
||||
self.logusermenu.raise_()
|
||||
self.logusermenu.activateWindow()
|
||||
@QtCore.pyqtSlot()
|
||||
def closeLogUsers(self):
|
||||
self.logusermenu.close()
|
||||
self.logusermenu = None
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def addGroupWindow(self):
|
||||
if not hasattr(self, 'addgroupdialog'):
|
||||
self.addgroupdialog = None
|
||||
if not self.addgroupdialog:
|
||||
(gname, ok) = QtGui.QInputDialog.getText(self, "Add Group", "Enter a name for the new group:")
|
||||
if ok:
|
||||
gname = unicode(gname)
|
||||
self.config.addGroup(gname)
|
||||
gTemp = self.config.getGroups()
|
||||
self.chumList.groups = [g[0] for g in gTemp]
|
||||
self.chumList.openGroups = [g[1] for g in gTemp]
|
||||
self.chumList.showAllGroups()
|
||||
if not self.config.showEmptyGroups():
|
||||
self.chumList.hideEmptyGroups()
|
||||
|
||||
self.addgroupdialog = None
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def openOpts(self):
|
||||
if not hasattr(self, 'optionmenu'):
|
||||
self.optionmenu = None
|
||||
|
@ -1654,6 +2019,26 @@ class PesterWindow(MovingWindow):
|
|||
# sound
|
||||
soundsetting = self.optionmenu.soundcheck.isChecked()
|
||||
self.config.set("soundon", soundsetting)
|
||||
# timestamps
|
||||
timestampsetting = self.optionmenu.timestampcheck.isChecked()
|
||||
self.config.set("showTimeStamps", timestampsetting)
|
||||
timeformatsetting = unicode(self.optionmenu.timestampBox.currentText())
|
||||
if timeformatsetting == "12 hour":
|
||||
self.config.set("time12Format", True)
|
||||
else:
|
||||
self.config.set("time12Format", False)
|
||||
secondssetting = self.optionmenu.secondscheck.isChecked()
|
||||
self.config.set("showSeconds", secondssetting)
|
||||
# groups
|
||||
#groupssetting = self.optionmenu.groupscheck.isChecked()
|
||||
#self.config.set("useGroups", groupssetting)
|
||||
emptygroupssetting = self.optionmenu.showemptycheck.isChecked()
|
||||
curemptygroup = self.config.showEmptyGroups()
|
||||
if curemptygroup and not emptygroupssetting:
|
||||
self.chumList.hideEmptyGroups()
|
||||
elif emptygroupssetting and not curemptygroup:
|
||||
self.chumList.showAllGroups()
|
||||
self.config.set("emptyGroups", emptygroupssetting)
|
||||
self.optionmenu = None
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
|
|
35
readme.txt
35
readme.txt
|
@ -36,11 +36,15 @@ style.js file will be documented soon, but feel free to poke at it.
|
|||
allow you to appear at multiple times in one chat.
|
||||
- Quirks: Prefix, suffix, simple replace, regexp replace (like in
|
||||
2.5), random replacement, and an auto-mispeller :P
|
||||
- Chum groups. Organize your chums into collapsible groups for easy
|
||||
management.
|
||||
- Block/user list
|
||||
- Add/block chums directly from a conversation, the userlist, or memo
|
||||
userlist.
|
||||
- Timestamps saved in logs and shown in conversations if wanted.
|
||||
- Logging. Logs are output in bbcode (for easy forum posting), html,
|
||||
and plain text.
|
||||
- Logviewer for easy log reading inside Pesterchum
|
||||
- Idling. You can set yourself idle manually, and the computer will
|
||||
set it for you after 10 minutes.
|
||||
- Improved /me. Any letters immediately following /me will be
|
||||
|
@ -226,6 +230,15 @@ Sounds On: Uncheck to shut it the fuck up.
|
|||
Hide Offline Chums: Turning this option on will hide all offline chums
|
||||
off your chumroll.
|
||||
|
||||
Show Empty Groups: Turning this option of will show empty groups.
|
||||
|
||||
Time Stamps: Turning this on will show timestamps in your chats.
|
||||
|
||||
12/24 hour: Formatting for timestamps. Whether you want them in 12 or
|
||||
24 hour time.
|
||||
|
||||
Show Seconds: Turning this on will show the seconds in your timestamps.
|
||||
|
||||
MEMOS: Opens the Memo list as above.
|
||||
|
||||
USERLIST: Shows a list of all the users that are currently logged onto
|
||||
|
@ -385,6 +398,28 @@ either "a" or "A" will be matched and replaced with "4," and likewise,
|
|||
"i" and "I" will be replaced with "1", and "e" and "E" will be
|
||||
replaced with "3."
|
||||
|
||||
Just like there is an "upper()" function, there is also a "lower()"
|
||||
function. It acts just like "upper()" but instead makes everything
|
||||
inside the parentheses lowercase. This allows you to do things like:
|
||||
|
||||
Regexp: "(.)" Replace with: "lower(\1)"
|
||||
You type: "I AM YELLING"
|
||||
Result:
|
||||
GD: i am yelling
|
||||
|
||||
Along with the upper and lower functions is a "scramble()" function.
|
||||
The purpose of this function is to randomly scramble anything inside
|
||||
the parentheses.
|
||||
|
||||
Regexp: "(\w)(\w*)(\w)" Replace with: "\1scramble(\2)\3"
|
||||
You type: "hello there"
|
||||
Result:
|
||||
GD: hlelo trhee
|
||||
|
||||
This particular regular expression scrambles all of the letters in
|
||||
the middle of a word. Notice that the "h" and "o" at the beginning
|
||||
and end of hello remain in place while the other letters are scrambled.
|
||||
|
||||
You should also know that "^" is a special character in brackets. If
|
||||
placed immediately after the opening bracket (like "[^"), then the
|
||||
brackets instead match every character *except* the ones in the
|
||||
|
|
|
@ -18,7 +18,9 @@
|
|||
"menus": {"client": {"_name": "Client",
|
||||
"options": "Options",
|
||||
"memos": "Memos",
|
||||
"logviewer": "Pesterlogs",
|
||||
"userlist": "Userlist",
|
||||
"addgroup": "Add Group",
|
||||
"import": "Import",
|
||||
"reconnect": "Reconnect",
|
||||
"idle": "Idle",
|
||||
|
@ -35,7 +37,11 @@
|
|||
"removechum": "Remove Chum",
|
||||
"blockchum": "Block",
|
||||
"addchum": "Add Chum",
|
||||
"viewlog": "View Pesterlog",
|
||||
"unblockchum": "Unblock",
|
||||
"removegroup": "Remove Group",
|
||||
"renamegroup": "Rename Group",
|
||||
"movechum": "Move To",
|
||||
"banuser": "Ban User",
|
||||
"opuser": "Make OP",
|
||||
"quirksoff": "Quirks Off"
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
"menus": {"client": {"_name": "Client",
|
||||
"options": "Options",
|
||||
"memos": "Memos",
|
||||
"logviewer": "Pesterlogs",
|
||||
"userlist": "Userlist",
|
||||
"addgroup": "Add Group",
|
||||
"import": "Import",
|
||||
"reconnect": "Reconnect",
|
||||
"idle": "Idle",
|
||||
|
@ -37,7 +39,11 @@
|
|||
"removechum": "Remove Chum",
|
||||
"blockchum": "Block",
|
||||
"addchum": "Add Chum",
|
||||
"viewlog": "View Pesterlog",
|
||||
"unblockchum": "Unblock",
|
||||
"removegroup": "Remove Group",
|
||||
"renamegroup": "Rename Group",
|
||||
"movechum": "Move To",
|
||||
"banuser": "Ban User",
|
||||
"opuser": "Make OP",
|
||||
"quirksoff": "Quirks Off"
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
"menus": {"client": {"_name": "CLIENT",
|
||||
"options": "OPTIONS",
|
||||
"memos": "MEMOS",
|
||||
"logviewer": "PESTERLOGS",
|
||||
"userlist": "USERLIST",
|
||||
"addgroup": "ADD GROUP",
|
||||
"import": "IMPORT",
|
||||
"reconnect": "RECONNECT",
|
||||
"idle": "IDLE",
|
||||
|
@ -37,7 +39,11 @@
|
|||
"removechum": "REMOVE CHUM",
|
||||
"blockchum": "BLOCK",
|
||||
"addchum": "ADD CHUM",
|
||||
"viewlog": "VIEW PESTERLOG",
|
||||
"unblockchum": "UNBLOCK",
|
||||
"removegroup": "REMOVE GROUP",
|
||||
"renamegroup": "RENAME GROUP",
|
||||
"movechum": "MOVE TO",
|
||||
"banuser": "BAN USER",
|
||||
"opuser": "MAKE OP",
|
||||
"quirksoff": "QUIRKS OFF"
|
||||
|
|
|
@ -19,8 +19,11 @@
|
|||
"menus": {"client": {"_name": "Trollian",
|
||||
"options": "Options",
|
||||
"memos": "Memos",
|
||||
"logviewer": "Pesterlogs",
|
||||
"userlist": "Fresh Targets",
|
||||
"addgroup": "Add Group",
|
||||
"import": "import U2;",
|
||||
"reconnect": "Reconnect",
|
||||
"idle": "Idle",
|
||||
"exit": "Abscond"},
|
||||
"profile": {"_name": "View",
|
||||
|
@ -35,7 +38,11 @@
|
|||
"removechum": "Trash",
|
||||
"blockchum": "Block",
|
||||
"addchum": "Add Chump",
|
||||
"viewlog": "View Pesterlog",
|
||||
"unblockchum": "Mercy",
|
||||
"removegroup": "Remove Group",
|
||||
"renamegroup": "Rename Group",
|
||||
"movechum": "Move To",
|
||||
"banuser": "Ban",
|
||||
"opuser": "Promote",
|
||||
"quirksoff": "Quirks Off" }
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
"menus": {"client": {"_name": "Typewriter",
|
||||
"options": "Preferences",
|
||||
"memos": "Bulletin Boards",
|
||||
"logviewer": "Pesterlogs",
|
||||
"userlist": "Userlist",
|
||||
"addgroup": "Add Group",
|
||||
"import": "Import",
|
||||
"idle": "Idle",
|
||||
"reconnect": "Reconnect",
|
||||
|
@ -37,7 +39,11 @@
|
|||
"removechum": "Erase User",
|
||||
"blockchum": "Condemn",
|
||||
"addchum": "Add User",
|
||||
"viewlog": "View Pesterlog",
|
||||
"unblockchum": "Forgive",
|
||||
"removegroup": "Remove Group",
|
||||
"renamegroup": "Rename Group",
|
||||
"movechum": "Move To",
|
||||
"banuser": "Expel User",
|
||||
"opuser": "Promote",
|
||||
"quirksoff": "Quirks Off"
|
||||
|
|
Loading…
Reference in a new issue