PageRenderTime 97ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/menus.py

https://github.com/602p/pesterchum
Python | 1810 lines | 1751 code | 43 blank | 16 comment | 75 complexity | f1d2daad42b17403a79dec42ee24badb MD5 | raw file
Possible License(s): GPL-3.0, Cube
  1. from PyQt4 import QtGui, QtCore
  2. import re, ostools
  3. from os import remove
  4. from generic import RightClickList, RightClickTree, MultiTextDialog
  5. from dataobjs import pesterQuirk, PesterProfile
  6. from memos import TimeSlider, TimeInput
  7. from version import _pcVersion
  8. _datadir = ostools.getDataDir()
  9. class PesterQuirkItem(QtGui.QTreeWidgetItem):
  10. def __init__(self, quirk):
  11. parent = None
  12. QtGui.QTreeWidgetItem.__init__(self, parent)
  13. self.quirk = quirk
  14. self.setText(0, unicode(quirk))
  15. def update(self, quirk):
  16. self.quirk = quirk
  17. self.setText(0, unicode(quirk))
  18. def __lt__(self, quirkitem):
  19. """Sets the order of quirks if auto-sorted by Qt. Obsolete now."""
  20. if self.quirk.type == "prefix":
  21. return True
  22. elif (self.quirk.type == "replace" or self.quirk.type == "regexp") and \
  23. quirkitem.type == "suffix":
  24. return True
  25. else:
  26. return False
  27. class PesterQuirkList(QtGui.QTreeWidget):
  28. def __init__(self, mainwindow, parent):
  29. QtGui.QTreeWidget.__init__(self, parent)
  30. self.resize(400, 200)
  31. # make sure we have access to mainwindow info like profiles
  32. self.mainwindow = mainwindow
  33. self.setStyleSheet("background:black; color:white;")
  34. self.connect(self, QtCore.SIGNAL('itemChanged(QTreeWidgetItem *, int)'),
  35. self, QtCore.SLOT('changeCheckState()'))
  36. for q in mainwindow.userprofile.quirks:
  37. item = PesterQuirkItem(q)
  38. self.addItem(item, False)
  39. self.changeCheckState()
  40. #self.setDragEnabled(True)
  41. #self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
  42. self.setDropIndicatorShown(True)
  43. self.setSortingEnabled(False)
  44. self.setIndentation(15)
  45. self.header().hide()
  46. def addItem(self, item, new=True):
  47. item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
  48. if item.quirk.on:
  49. item.setCheckState(0, 2)
  50. else:
  51. item.setCheckState(0, 0)
  52. if new:
  53. curgroup = self.currentItem()
  54. if curgroup:
  55. if curgroup.parent(): curgroup = curgroup.parent()
  56. item.quirk.quirk["group"] = item.quirk.group = curgroup.text(0)
  57. found = self.findItems(item.quirk.group, QtCore.Qt.MatchExactly)
  58. if len(found) > 0:
  59. found[0].addChild(item)
  60. else:
  61. child_1 = QtGui.QTreeWidgetItem([item.quirk.group])
  62. self.addTopLevelItem(child_1)
  63. child_1.setFlags(child_1.flags() | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
  64. child_1.setChildIndicatorPolicy(QtGui.QTreeWidgetItem.DontShowIndicatorWhenChildless)
  65. child_1.setCheckState(0,0)
  66. child_1.setExpanded(True)
  67. child_1.addChild(item)
  68. self.changeCheckState()
  69. def currentQuirk(self):
  70. if type(self.currentItem()) is PesterQuirkItem:
  71. return self.currentItem()
  72. else: return None
  73. @QtCore.pyqtSlot()
  74. def upShiftQuirk(self):
  75. found = self.findItems(self.currentItem().text(0), QtCore.Qt.MatchExactly)
  76. if len(found): # group
  77. i = self.indexOfTopLevelItem(found[0])
  78. if i > 0:
  79. expand = found[0].isExpanded()
  80. shifted_item = self.takeTopLevelItem(i)
  81. self.insertTopLevelItem(i-1, shifted_item)
  82. shifted_item.setExpanded(expand)
  83. self.setCurrentItem(shifted_item)
  84. else: # quirk
  85. found = self.findItems(self.currentItem().text(0), QtCore.Qt.MatchExactly | QtCore.Qt.MatchRecursive)
  86. for f in found:
  87. if not f.isSelected(): continue
  88. if not f.parent(): continue
  89. i = f.parent().indexOfChild(f)
  90. if i > 0: # keep in same group
  91. p = f.parent()
  92. shifted_item = f.parent().takeChild(i)
  93. p.insertChild(i-1, shifted_item)
  94. self.setCurrentItem(shifted_item)
  95. else: # move to another group
  96. j = self.indexOfTopLevelItem(f.parent())
  97. if j <= 0: continue
  98. shifted_item = f.parent().takeChild(i)
  99. self.topLevelItem(j-1).addChild(shifted_item)
  100. self.setCurrentItem(shifted_item)
  101. self.changeCheckState()
  102. @QtCore.pyqtSlot()
  103. def downShiftQuirk(self):
  104. found = self.findItems(self.currentItem().text(0), QtCore.Qt.MatchExactly)
  105. if len(found): # group
  106. i = self.indexOfTopLevelItem(found[0])
  107. if i < self.topLevelItemCount()-1 and i >= 0:
  108. expand = found[0].isExpanded()
  109. shifted_item = self.takeTopLevelItem(i)
  110. self.insertTopLevelItem(i+1, shifted_item)
  111. shifted_item.setExpanded(expand)
  112. self.setCurrentItem(shifted_item)
  113. else: # quirk
  114. found = self.findItems(self.currentItem().text(0), QtCore.Qt.MatchExactly | QtCore.Qt.MatchRecursive)
  115. for f in found:
  116. if not f.isSelected(): continue
  117. if not f.parent(): continue
  118. i = f.parent().indexOfChild(f)
  119. if i < f.parent().childCount()-1 and i >= 0:
  120. p = f.parent()
  121. shifted_item = f.parent().takeChild(i)
  122. p.insertChild(i+1, shifted_item)
  123. self.setCurrentItem(shifted_item)
  124. else:
  125. j = self.indexOfTopLevelItem(f.parent())
  126. if j >= self.topLevelItemCount()-1 or j < 0: continue
  127. shifted_item = f.parent().takeChild(i)
  128. self.topLevelItem(j+1).insertChild(0, shifted_item)
  129. self.setCurrentItem(shifted_item)
  130. self.changeCheckState()
  131. @QtCore.pyqtSlot()
  132. def removeCurrent(self):
  133. i = self.currentItem()
  134. found = self.findItems(i.text(0), QtCore.Qt.MatchExactly | QtCore.Qt.MatchRecursive)
  135. for f in found:
  136. if not f.isSelected(): continue
  137. if not f.parent(): # group
  138. msgbox = QtGui.QMessageBox()
  139. msgbox.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
  140. msgbox.setWindowTitle("WARNING!")
  141. msgbox.setInformativeText("Are you sure you want to delete the quirk group: %s" % (f.text(0)))
  142. msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
  143. ret = msgbox.exec_()
  144. if ret == QtGui.QMessageBox.Ok:
  145. self.takeTopLevelItem(self.indexOfTopLevelItem(f))
  146. else:
  147. f.parent().takeChild(f.parent().indexOfChild(f))
  148. self.changeCheckState()
  149. @QtCore.pyqtSlot()
  150. def addQuirkGroup(self):
  151. if not hasattr(self, 'addgroupdialog'):
  152. self.addgroupdialog = None
  153. if not self.addgroupdialog:
  154. (gname, ok) = QtGui.QInputDialog.getText(self, "Add Group", "Enter a name for the new quirk group:")
  155. if ok:
  156. gname = unicode(gname)
  157. if re.search("[^A-Za-z0-9_\s]", gname) is not None:
  158. msgbox = QtGui.QMessageBox()
  159. msgbox.setInformativeText("THIS IS NOT A VALID GROUP NAME")
  160. msgbox.setStandardButtons(QtGui.QMessageBox.Ok)
  161. ret = msgbox.exec_()
  162. self.addgroupdialog = None
  163. return
  164. found = self.findItems(gname, QtCore.Qt.MatchExactly)
  165. if found:
  166. msgbox = QtGui.QMessageBox()
  167. msgbox.setInformativeText("THIS QUIRK GROUP ALREADY EXISTS")
  168. msgbox.setStandardButtons(QtGui.QMessageBox.Ok)
  169. ret = msgbox.exec_()
  170. return
  171. child_1 = QtGui.QTreeWidgetItem([gname])
  172. self.addTopLevelItem(child_1)
  173. child_1.setFlags(child_1.flags() | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
  174. child_1.setChildIndicatorPolicy(QtGui.QTreeWidgetItem.DontShowIndicatorWhenChildless)
  175. child_1.setCheckState(0,0)
  176. child_1.setExpanded(True)
  177. self.addgroupdialog = None
  178. @QtCore.pyqtSlot()
  179. def changeCheckState(self):
  180. index = self.indexOfTopLevelItem(self.currentItem())
  181. if index == -1:
  182. for i in range(self.topLevelItemCount()):
  183. allChecked = True
  184. noneChecked = True
  185. for j in range(self.topLevelItem(i).childCount()):
  186. if self.topLevelItem(i).child(j).checkState(0):
  187. noneChecked = False
  188. else:
  189. allChecked = False
  190. if allChecked: self.topLevelItem(i).setCheckState(0, 2)
  191. elif noneChecked: self.topLevelItem(i).setCheckState(0, 0)
  192. else: self.topLevelItem(i).setCheckState(0, 1)
  193. else:
  194. state = self.topLevelItem(index).checkState(0)
  195. for j in range(self.topLevelItem(index).childCount()):
  196. self.topLevelItem(index).child(j).setCheckState(0, state)
  197. from copy import copy
  198. from convo import PesterInput, PesterText
  199. from parsetools import convertTags, lexMessage, splitMessage, mecmd, colorBegin, colorEnd, img2smiley, smiledict
  200. from dataobjs import pesterQuirks, PesterHistory
  201. class QuirkTesterWindow(QtGui.QDialog):
  202. def __init__(self, parent):
  203. QtGui.QDialog.__init__(self, parent)
  204. self.prnt = parent
  205. self.mainwindow = parent.mainwindow
  206. self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
  207. self.setWindowTitle("Quirk Tester")
  208. self.resize(350,300)
  209. self.textArea = PesterText(self.mainwindow.theme, self)
  210. self.textInput = PesterInput(self.mainwindow.theme, self)
  211. self.textInput.setFocus()
  212. self.connect(self.textInput, QtCore.SIGNAL('returnPressed()'),
  213. self, QtCore.SLOT('sentMessage()'))
  214. self.chumopen = True
  215. self.chum = self.mainwindow.profile()
  216. self.history = PesterHistory()
  217. layout_0 = QtGui.QVBoxLayout()
  218. layout_0.addWidget(self.textArea)
  219. layout_0.addWidget(self.textInput)
  220. self.setLayout(layout_0)
  221. def parent(self):
  222. return self.prnt
  223. def clearNewMessage(self):
  224. pass
  225. @QtCore.pyqtSlot()
  226. def sentMessage(self):
  227. text = unicode(self.textInput.text())
  228. if text == "" or text[0:11] == "PESTERCHUM:":
  229. return
  230. self.history.add(text)
  231. quirks = pesterQuirks(self.parent().testquirks())
  232. lexmsg = lexMessage(text)
  233. if type(lexmsg[0]) is not mecmd:
  234. try:
  235. lexmsg = quirks.apply(lexmsg)
  236. except Exception, e:
  237. msgbox = QtGui.QMessageBox()
  238. msgbox.setText("Whoa there! There seems to be a problem.")
  239. msgbox.setInformativeText("A quirk seems to be having a problem. (Possibly you're trying to capture a non-existant group?)\n\
  240. %s" % e)
  241. msgbox.exec_()
  242. return
  243. lexmsgs = splitMessage(lexmsg)
  244. for lm in lexmsgs:
  245. serverMsg = copy(lm)
  246. self.addMessage(lm, True)
  247. text = convertTags(serverMsg, "ctag")
  248. self.textInput.setText("")
  249. def addMessage(self, msg, me=True):
  250. if type(msg) in [str, unicode]:
  251. lexmsg = lexMessage(msg)
  252. else:
  253. lexmsg = msg
  254. if me:
  255. chum = self.mainwindow.profile()
  256. else:
  257. chum = self.chum
  258. self.textArea.addMessage(lexmsg, chum)
  259. def closeEvent(self, event):
  260. self.parent().quirktester = None
  261. class PesterQuirkTypes(QtGui.QDialog):
  262. def __init__(self, parent, quirk=None):
  263. QtGui.QDialog.__init__(self, parent)
  264. self.mainwindow = parent.mainwindow
  265. self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
  266. self.setWindowTitle("Quirk Wizard")
  267. self.resize(500,310)
  268. self.quirk = quirk
  269. self.pages = QtGui.QStackedWidget(self)
  270. self.next = QtGui.QPushButton("Next", self)
  271. self.next.setDefault(True)
  272. self.connect(self.next, QtCore.SIGNAL('clicked()'),
  273. self, QtCore.SLOT('nextPage()'))
  274. self.back = QtGui.QPushButton("Back", self)
  275. self.back.setEnabled(False)
  276. self.connect(self.back, QtCore.SIGNAL('clicked()'),
  277. self, QtCore.SLOT('backPage()'))
  278. self.cancel = QtGui.QPushButton("Cancel", self)
  279. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  280. self, QtCore.SLOT('reject()'))
  281. layout_2 = QtGui.QHBoxLayout()
  282. layout_2.setAlignment(QtCore.Qt.AlignRight)
  283. layout_2.addWidget(self.back)
  284. layout_2.addWidget(self.next)
  285. layout_2.addSpacing(5)
  286. layout_2.addWidget(self.cancel)
  287. vr = QtGui.QFrame()
  288. vr.setFrameShape(QtGui.QFrame.VLine)
  289. vr.setFrameShadow(QtGui.QFrame.Sunken)
  290. vr2 = QtGui.QFrame()
  291. vr2.setFrameShape(QtGui.QFrame.VLine)
  292. vr2.setFrameShadow(QtGui.QFrame.Sunken)
  293. self.funclist = QtGui.QListWidget(self)
  294. self.funclist.setStyleSheet("color: #000000; background-color: #FFFFFF;")
  295. self.funclist2 = QtGui.QListWidget(self)
  296. self.funclist2.setStyleSheet("color: #000000; background-color: #FFFFFF;")
  297. from parsetools import quirkloader
  298. funcs = [q+"()" for q in quirkloader.quirks.keys()]
  299. funcs.sort()
  300. self.funclist.addItems(funcs)
  301. self.funclist2.addItems(funcs)
  302. self.reloadQuirkFuncButton = QtGui.QPushButton("RELOAD FUNCTIONS", self)
  303. self.connect(self.reloadQuirkFuncButton, QtCore.SIGNAL('clicked()'),
  304. self, QtCore.SLOT('reloadQuirkFuncSlot()'))
  305. self.reloadQuirkFuncButton2 = QtGui.QPushButton("RELOAD FUNCTIONS", self)
  306. self.connect(self.reloadQuirkFuncButton2, QtCore.SIGNAL('clicked()'),
  307. self, QtCore.SLOT('reloadQuirkFuncSlot()'))
  308. self.funclist.setMaximumWidth(160)
  309. self.funclist.resize(160,50)
  310. self.funclist2.setMaximumWidth(160)
  311. self.funclist2.resize(160,50)
  312. layout_f = QtGui.QVBoxLayout()
  313. layout_f.addWidget(QtGui.QLabel("Available Regexp\nFunctions"))
  314. layout_f.addWidget(self.funclist)
  315. layout_f.addWidget(self.reloadQuirkFuncButton)
  316. layout_g = QtGui.QVBoxLayout()
  317. layout_g.addWidget(QtGui.QLabel("Available Regexp\nFunctions"))
  318. layout_g.addWidget(self.funclist2)
  319. layout_g.addWidget(self.reloadQuirkFuncButton2)
  320. # Pages
  321. # Type select
  322. widget = QtGui.QWidget()
  323. self.pages.addWidget(widget)
  324. layout_select = QtGui.QVBoxLayout(widget)
  325. layout_select.setAlignment(QtCore.Qt.AlignTop)
  326. self.radios = []
  327. self.radios.append(QtGui.QRadioButton("Prefix", self))
  328. self.radios.append(QtGui.QRadioButton("Suffix", self))
  329. self.radios.append(QtGui.QRadioButton("Simple Replace", self))
  330. self.radios.append(QtGui.QRadioButton("Regexp Replace", self))
  331. self.radios.append(QtGui.QRadioButton("Random Replace", self))
  332. self.radios.append(QtGui.QRadioButton("Mispeller", self))
  333. layout_select.addWidget(QtGui.QLabel("Select Quirk Type:"))
  334. for r in self.radios:
  335. layout_select.addWidget(r)
  336. # Prefix
  337. widget = QtGui.QWidget()
  338. self.pages.addWidget(widget)
  339. layout_prefix = QtGui.QVBoxLayout(widget)
  340. layout_prefix.setAlignment(QtCore.Qt.AlignTop)
  341. layout_prefix.addWidget(QtGui.QLabel("Prefix"))
  342. layout_3 = QtGui.QHBoxLayout()
  343. layout_3.addWidget(QtGui.QLabel("Value:"))
  344. layout_3.addWidget(QtGui.QLineEdit())
  345. layout_prefix.addLayout(layout_3)
  346. # Suffix
  347. widget = QtGui.QWidget()
  348. self.pages.addWidget(widget)
  349. layout_suffix = QtGui.QVBoxLayout(widget)
  350. layout_suffix.setAlignment(QtCore.Qt.AlignTop)
  351. layout_suffix.addWidget(QtGui.QLabel("Suffix"))
  352. layout_3 = QtGui.QHBoxLayout()
  353. layout_3.addWidget(QtGui.QLabel("Value:"))
  354. layout_3.addWidget(QtGui.QLineEdit())
  355. layout_suffix.addLayout(layout_3)
  356. # Simple Replace
  357. widget = QtGui.QWidget()
  358. self.pages.addWidget(widget)
  359. layout_replace = QtGui.QVBoxLayout(widget)
  360. layout_replace.setAlignment(QtCore.Qt.AlignTop)
  361. layout_replace.addWidget(QtGui.QLabel("Simple Replace"))
  362. layout_3 = QtGui.QHBoxLayout()
  363. layout_3.addWidget(QtGui.QLabel("Replace:"))
  364. layout_3.addWidget(QtGui.QLineEdit())
  365. layout_replace.addLayout(layout_3)
  366. layout_3 = QtGui.QHBoxLayout()
  367. layout_3.addWidget(QtGui.QLabel("With:"))
  368. layout_3.addWidget(QtGui.QLineEdit())
  369. layout_replace.addLayout(layout_3)
  370. # Regexp Replace
  371. widget = QtGui.QWidget()
  372. self.pages.addWidget(widget)
  373. layout_all = QtGui.QHBoxLayout(widget)
  374. layout_regexp = QtGui.QVBoxLayout()
  375. layout_regexp.setAlignment(QtCore.Qt.AlignTop)
  376. layout_regexp.addWidget(QtGui.QLabel("Regexp Replace"))
  377. layout_3 = QtGui.QHBoxLayout()
  378. layout_3.addWidget(QtGui.QLabel("Regexp:"))
  379. layout_3.addWidget(QtGui.QLineEdit())
  380. layout_regexp.addLayout(layout_3)
  381. layout_3 = QtGui.QHBoxLayout()
  382. layout_3.addWidget(QtGui.QLabel("Replace With:"))
  383. layout_3.addWidget(QtGui.QLineEdit())
  384. layout_regexp.addLayout(layout_3)
  385. layout_all.addLayout(layout_f)
  386. layout_all.addWidget(vr)
  387. layout_all.addLayout(layout_regexp)
  388. # Random Replace
  389. widget = QtGui.QWidget()
  390. self.pages.addWidget(widget)
  391. layout_all = QtGui.QHBoxLayout(widget)
  392. layout_random = QtGui.QVBoxLayout()
  393. layout_random.setAlignment(QtCore.Qt.AlignTop)
  394. layout_random.addWidget(QtGui.QLabel("Random Replace"))
  395. layout_5 = QtGui.QHBoxLayout()
  396. regexpl = QtGui.QLabel("Regexp:", self)
  397. self.regexp = QtGui.QLineEdit("", self)
  398. layout_5.addWidget(regexpl)
  399. layout_5.addWidget(self.regexp)
  400. replacewithl = QtGui.QLabel("Replace With:", self)
  401. layout_all.addLayout(layout_g)
  402. layout_all.addWidget(vr2)
  403. layout_all.addLayout(layout_random)
  404. layout_6 = QtGui.QVBoxLayout()
  405. layout_7 = QtGui.QHBoxLayout()
  406. self.replacelist = QtGui.QListWidget(self)
  407. self.replaceinput = QtGui.QLineEdit(self)
  408. addbutton = QtGui.QPushButton("ADD", self)
  409. self.connect(addbutton, QtCore.SIGNAL('clicked()'),
  410. self, QtCore.SLOT('addRandomString()'))
  411. removebutton = QtGui.QPushButton("REMOVE", self)
  412. self.connect(removebutton, QtCore.SIGNAL('clicked()'),
  413. self, QtCore.SLOT('removeRandomString()'))
  414. layout_7.addWidget(addbutton)
  415. layout_7.addWidget(removebutton)
  416. layout_6.addLayout(layout_5)
  417. layout_6.addWidget(replacewithl)
  418. layout_6.addWidget(self.replacelist)
  419. layout_6.addWidget(self.replaceinput)
  420. layout_6.addLayout(layout_7)
  421. layout_random.addLayout(layout_6)
  422. # Misspeller
  423. widget = QtGui.QWidget()
  424. self.pages.addWidget(widget)
  425. layout_mispeller = QtGui.QVBoxLayout(widget)
  426. layout_mispeller.setAlignment(QtCore.Qt.AlignTop)
  427. layout_mispeller.addWidget(QtGui.QLabel("Mispeller"))
  428. layout_1 = QtGui.QHBoxLayout()
  429. zero = QtGui.QLabel("1%", self)
  430. hund = QtGui.QLabel("100%", self)
  431. self.current = QtGui.QLabel("50%", self)
  432. self.current.setAlignment(QtCore.Qt.AlignHCenter)
  433. self.slider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
  434. self.slider.setMinimum(1)
  435. self.slider.setMaximum(100)
  436. self.slider.setValue(50)
  437. self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'),
  438. self, QtCore.SLOT('printValue(int)'))
  439. layout_1.addWidget(zero)
  440. layout_1.addWidget(self.slider)
  441. layout_1.addWidget(hund)
  442. layout_mispeller.addLayout(layout_1)
  443. layout_mispeller.addWidget(self.current)
  444. layout_0 = QtGui.QVBoxLayout()
  445. layout_0.addWidget(self.pages)
  446. layout_0.addLayout(layout_2)
  447. if quirk:
  448. types = ["prefix","suffix","replace","regexp","random","spelling"]
  449. for (i,r) in enumerate(self.radios):
  450. if i == types.index(quirk.quirk.type):
  451. r.setChecked(True)
  452. self.changePage(types.index(quirk.quirk.type)+1)
  453. page = self.pages.currentWidget().layout()
  454. q = quirk.quirk.quirk
  455. if q["type"] in ("prefix","suffix"):
  456. page.itemAt(1).layout().itemAt(1).widget().setText(q["value"])
  457. elif q["type"] == "replace":
  458. page.itemAt(1).layout().itemAt(1).widget().setText(q["from"])
  459. page.itemAt(2).layout().itemAt(1).widget().setText(q["to"])
  460. elif q["type"] == "regexp":
  461. page.itemAt(2).layout().itemAt(1).layout().itemAt(1).widget().setText(q["from"])
  462. page.itemAt(2).layout().itemAt(2).layout().itemAt(1).widget().setText(q["to"])
  463. elif q["type"] == "random":
  464. self.regexp.setText(q["from"])
  465. for v in q["randomlist"]:
  466. item = QtGui.QListWidgetItem(v, self.replacelist)
  467. elif q["type"] == "spelling":
  468. self.slider.setValue(q["percentage"])
  469. self.setLayout(layout_0)
  470. def closeEvent(self, event):
  471. self.parent().quirkadd = None
  472. def changePage(self, page):
  473. c = self.pages.count()
  474. if page >= c or page < 0: return
  475. self.back.setEnabled(page > 0)
  476. if page >= 1 and page <= 6:
  477. self.next.setText("Finish")
  478. else:
  479. self.next.setText("Next")
  480. self.pages.setCurrentIndex(page)
  481. @QtCore.pyqtSlot()
  482. def nextPage(self):
  483. if self.next.text() == "Finish":
  484. self.accept()
  485. return
  486. cur = self.pages.currentIndex()
  487. if cur == 0:
  488. for (i,r) in enumerate(self.radios):
  489. if r.isChecked():
  490. self.changePage(i+1)
  491. else:
  492. self.changePage(cur+1)
  493. @QtCore.pyqtSlot()
  494. def backPage(self):
  495. cur = self.pages.currentIndex()
  496. if cur >= 1 and cur <= 6:
  497. self.changePage(0)
  498. @QtCore.pyqtSlot(int)
  499. def printValue(self, value):
  500. self.current.setText(str(value)+"%")
  501. @QtCore.pyqtSlot()
  502. def addRandomString(self):
  503. text = unicode(self.replaceinput.text())
  504. item = QtGui.QListWidgetItem(text, self.replacelist)
  505. self.replaceinput.setText("")
  506. self.replaceinput.setFocus()
  507. @QtCore.pyqtSlot()
  508. def removeRandomString(self):
  509. if not self.replacelist.currentItem():
  510. return
  511. else:
  512. self.replacelist.takeItem(self.replacelist.currentRow())
  513. self.replaceinput.setFocus()
  514. @QtCore.pyqtSlot()
  515. def reloadQuirkFuncSlot(self):
  516. from parsetools import reloadQuirkFunctions, quirkloader
  517. reloadQuirkFunctions()
  518. funcs = [q+"()" for q in quirkloader.quirks.keys()]
  519. funcs.sort()
  520. self.funclist.clear()
  521. self.funclist.addItems(funcs)
  522. self.funclist2.clear()
  523. self.funclist2.addItems(funcs)
  524. class PesterChooseQuirks(QtGui.QDialog):
  525. def __init__(self, config, theme, parent):
  526. QtGui.QDialog.__init__(self, parent)
  527. self.setModal(False)
  528. self.config = config
  529. self.theme = theme
  530. self.mainwindow = parent
  531. self.setStyleSheet(self.theme["main/defaultwindow/style"])
  532. self.setWindowTitle("Set Quirks")
  533. self.quirkList = PesterQuirkList(self.mainwindow, self)
  534. self.addQuirkButton = QtGui.QPushButton("ADD QUIRK", self)
  535. self.connect(self.addQuirkButton, QtCore.SIGNAL('clicked()'),
  536. self, QtCore.SLOT('addQuirkDialog()'))
  537. self.upShiftButton = QtGui.QPushButton("^", self)
  538. self.downShiftButton = QtGui.QPushButton("v", self)
  539. self.upShiftButton.setToolTip("Move quirk up one")
  540. self.downShiftButton.setToolTip("Move quirk down one")
  541. self.connect(self.upShiftButton, QtCore.SIGNAL('clicked()'),
  542. self.quirkList, QtCore.SLOT('upShiftQuirk()'))
  543. self.connect(self.downShiftButton, QtCore.SIGNAL('clicked()'),
  544. self.quirkList, QtCore.SLOT('downShiftQuirk()'))
  545. self.newGroupButton = QtGui.QPushButton("*", self)
  546. self.newGroupButton.setToolTip("New Quirk Group")
  547. self.connect(self.newGroupButton, QtCore.SIGNAL('clicked()'),
  548. self.quirkList, QtCore.SLOT('addQuirkGroup()'))
  549. layout_quirklist = QtGui.QHBoxLayout() #the nude layout quirklist
  550. layout_shiftbuttons = QtGui.QVBoxLayout() #the shift button layout
  551. layout_shiftbuttons.addWidget(self.upShiftButton)
  552. layout_shiftbuttons.addWidget(self.newGroupButton)
  553. layout_shiftbuttons.addWidget(self.downShiftButton)
  554. layout_quirklist.addWidget(self.quirkList)
  555. layout_quirklist.addLayout(layout_shiftbuttons)
  556. layout_1 = QtGui.QHBoxLayout()
  557. layout_1.addWidget(self.addQuirkButton)
  558. self.editSelectedButton = QtGui.QPushButton("EDIT", self)
  559. self.connect(self.editSelectedButton, QtCore.SIGNAL('clicked()'),
  560. self, QtCore.SLOT('editSelected()'))
  561. self.removeSelectedButton = QtGui.QPushButton("REMOVE", self)
  562. self.connect(self.removeSelectedButton, QtCore.SIGNAL('clicked()'),
  563. self.quirkList, QtCore.SLOT('removeCurrent()'))
  564. layout_3 = QtGui.QHBoxLayout()
  565. layout_3.addWidget(self.editSelectedButton)
  566. layout_3.addWidget(self.removeSelectedButton)
  567. self.ok = QtGui.QPushButton("OK", self)
  568. self.ok.setDefault(True)
  569. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  570. self, QtCore.SLOT('accept()'))
  571. self.test = QtGui.QPushButton("TEST QUIRKS", self)
  572. self.connect(self.test, QtCore.SIGNAL('clicked()'),
  573. self, QtCore.SLOT('testQuirks()'))
  574. self.cancel = QtGui.QPushButton("CANCEL", self)
  575. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  576. self, QtCore.SLOT('reject()'))
  577. layout_ok = QtGui.QHBoxLayout()
  578. layout_ok.addWidget(self.cancel)
  579. layout_ok.addWidget(self.test)
  580. layout_ok.addWidget(self.ok)
  581. layout_0 = QtGui.QVBoxLayout()
  582. layout_0.addLayout(layout_quirklist)
  583. layout_0.addLayout(layout_1)
  584. #layout_0.addLayout(layout_2)
  585. layout_0.addLayout(layout_3)
  586. layout_0.addLayout(layout_ok)
  587. self.setLayout(layout_0)
  588. def quirks(self):
  589. u = []
  590. for i in range(self.quirkList.topLevelItemCount()):
  591. for j in range(self.quirkList.topLevelItem(i).childCount()):
  592. u.append(self.quirkList.topLevelItem(i).child(j).quirk)
  593. return u
  594. #return [self.quirkList.item(i).quirk for i in range(self.quirkList.count())]
  595. def testquirks(self):
  596. u = []
  597. for i in range(self.quirkList.topLevelItemCount()):
  598. for j in range(self.quirkList.topLevelItem(i).childCount()):
  599. item = self.quirkList.topLevelItem(i).child(j)
  600. if (item.checkState(0) == QtCore.Qt.Checked):
  601. u.append(item.quirk)
  602. return u
  603. @QtCore.pyqtSlot()
  604. def testQuirks(self):
  605. if not hasattr(self, 'quirktester'):
  606. self.quirktester = None
  607. if self.quirktester:
  608. return
  609. self.quirktester = QuirkTesterWindow(self)
  610. self.quirktester.show()
  611. @QtCore.pyqtSlot()
  612. def editSelected(self):
  613. q = self.quirkList.currentQuirk()
  614. if not q: return
  615. quirk = q.quirk
  616. self.addQuirkDialog(q)
  617. @QtCore.pyqtSlot()
  618. def addQuirkDialog(self, quirk=None):
  619. if not hasattr(self, 'quirkadd'):
  620. self.quirkadd = None
  621. if self.quirkadd:
  622. return
  623. self.quirkadd = PesterQuirkTypes(self, quirk)
  624. self.connect(self.quirkadd, QtCore.SIGNAL('accepted()'),
  625. self, QtCore.SLOT('addQuirk()'))
  626. self.connect(self.quirkadd, QtCore.SIGNAL('rejected()'),
  627. self, QtCore.SLOT('closeQuirk()'))
  628. self.quirkadd.show()
  629. @QtCore.pyqtSlot()
  630. def addQuirk(self):
  631. types = ["prefix","suffix","replace","regexp","random","spelling"]
  632. vdict = {}
  633. vdict["type"] = types[self.quirkadd.pages.currentIndex()-1]
  634. page = self.quirkadd.pages.currentWidget().layout()
  635. if vdict["type"] in ("prefix","suffix"):
  636. vdict["value"] = unicode(page.itemAt(1).layout().itemAt(1).widget().text())
  637. elif vdict["type"] == "replace":
  638. vdict["from"] = unicode(page.itemAt(1).layout().itemAt(1).widget().text())
  639. vdict["to"] = unicode(page.itemAt(2).layout().itemAt(1).widget().text())
  640. elif vdict["type"] == "regexp":
  641. vdict["from"] = unicode(page.itemAt(2).layout().itemAt(1).layout().itemAt(1).widget().text())
  642. vdict["to"] = unicode(page.itemAt(2).layout().itemAt(2).layout().itemAt(1).widget().text())
  643. elif vdict["type"] == "random":
  644. vdict["from"] = unicode(self.quirkadd.regexp.text())
  645. randomlist = [unicode(self.quirkadd.replacelist.item(i).text())
  646. for i in range(0,self.quirkadd.replacelist.count())]
  647. vdict["randomlist"] = randomlist
  648. elif vdict["type"] == "spelling":
  649. vdict["percentage"] = self.quirkadd.slider.value()
  650. if vdict["type"] in ("regexp", "random"):
  651. try:
  652. re.compile(vdict["from"])
  653. except re.error, e:
  654. quirkWarning = QtGui.QMessageBox(self)
  655. quirkWarning.setText("Not a valid regular expression!")
  656. quirkWarning.setInformativeText("H3R3S WHY DUMP4SS: %s" % (e))
  657. quirkWarning.exec_()
  658. self.quirkadd = None
  659. return
  660. quirk = pesterQuirk(vdict)
  661. if self.quirkadd.quirk is None:
  662. item = PesterQuirkItem(quirk)
  663. self.quirkList.addItem(item)
  664. else:
  665. self.quirkadd.quirk.update(quirk)
  666. self.quirkadd = None
  667. @QtCore.pyqtSlot()
  668. def closeQuirk(self):
  669. self.quirkadd = None
  670. class PesterChooseTheme(QtGui.QDialog):
  671. def __init__(self, config, theme, parent):
  672. QtGui.QDialog.__init__(self, parent)
  673. self.config = config
  674. self.theme = theme
  675. self.parent = parent
  676. self.setStyleSheet(self.theme["main/defaultwindow/style"])
  677. self.setWindowTitle("Pick a theme")
  678. instructions = QtGui.QLabel("Pick a theme:")
  679. avail_themes = config.availableThemes()
  680. self.themeBox = QtGui.QComboBox(self)
  681. for (i, t) in enumerate(avail_themes):
  682. self.themeBox.addItem(t)
  683. if t == theme.name:
  684. self.themeBox.setCurrentIndex(i)
  685. self.ok = QtGui.QPushButton("OK", self)
  686. self.ok.setDefault(True)
  687. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  688. self, QtCore.SLOT('accept()'))
  689. self.cancel = QtGui.QPushButton("CANCEL", self)
  690. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  691. self, QtCore.SLOT('reject()'))
  692. layout_ok = QtGui.QHBoxLayout()
  693. layout_ok.addWidget(self.cancel)
  694. layout_ok.addWidget(self.ok)
  695. layout_0 = QtGui.QVBoxLayout()
  696. layout_0.addWidget(instructions)
  697. layout_0.addWidget(self.themeBox)
  698. layout_0.addLayout(layout_ok)
  699. self.setLayout(layout_0)
  700. self.connect(self, QtCore.SIGNAL('accepted()'),
  701. parent, QtCore.SLOT('themeSelected()'))
  702. self.connect(self, QtCore.SIGNAL('rejected()'),
  703. parent, QtCore.SLOT('closeTheme()'))
  704. class PesterChooseProfile(QtGui.QDialog):
  705. def __init__(self, userprofile, config, theme, parent, collision=None):
  706. QtGui.QDialog.__init__(self, parent)
  707. self.userprofile = userprofile
  708. self.theme = theme
  709. self.config = config
  710. self.parent = parent
  711. self.setStyleSheet(self.theme["main/defaultwindow/style"])
  712. self.currentHandle = QtGui.QLabel("CHANGING FROM %s" % userprofile.chat.handle)
  713. self.chumHandle = QtGui.QLineEdit(self)
  714. self.chumHandle.setMinimumWidth(200)
  715. self.chumHandleLabel = QtGui.QLabel(self.theme["main/mychumhandle/label/text"], self)
  716. self.chumColorButton = QtGui.QPushButton(self)
  717. self.chumColorButton.resize(50, 20)
  718. self.chumColorButton.setStyleSheet("background: %s" % (userprofile.chat.colorhtml()))
  719. self.chumcolor = userprofile.chat.color
  720. self.connect(self.chumColorButton, QtCore.SIGNAL('clicked()'),
  721. self, QtCore.SLOT('openColorDialog()'))
  722. layout_1 = QtGui.QHBoxLayout()
  723. layout_1.addWidget(self.chumHandleLabel)
  724. layout_1.addWidget(self.chumHandle)
  725. layout_1.addWidget(self.chumColorButton)
  726. # available profiles?
  727. avail_profiles = self.config.availableProfiles()
  728. if avail_profiles:
  729. self.profileBox = QtGui.QComboBox(self)
  730. self.profileBox.addItem("Choose a profile...")
  731. for p in avail_profiles:
  732. self.profileBox.addItem(p.chat.handle)
  733. else:
  734. self.profileBox = None
  735. self.defaultcheck = QtGui.QCheckBox(self)
  736. self.defaultlabel = QtGui.QLabel("Set This Profile As Default", self)
  737. layout_2 = QtGui.QHBoxLayout()
  738. layout_2.addWidget(self.defaultlabel)
  739. layout_2.addWidget(self.defaultcheck)
  740. self.ok = QtGui.QPushButton("OK", self)
  741. self.ok.setDefault(True)
  742. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  743. self, QtCore.SLOT('validateProfile()'))
  744. self.cancel = QtGui.QPushButton("CANCEL", self)
  745. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  746. self, QtCore.SLOT('reject()'))
  747. if not collision and avail_profiles:
  748. self.delete = QtGui.QPushButton("DELETE", self)
  749. self.connect(self.delete, QtCore.SIGNAL('clicked()'),
  750. self, QtCore.SLOT('deleteProfile()'))
  751. layout_ok = QtGui.QHBoxLayout()
  752. layout_ok.addWidget(self.cancel)
  753. layout_ok.addWidget(self.ok)
  754. layout_0 = QtGui.QVBoxLayout()
  755. if collision:
  756. collision_warning = QtGui.QLabel("%s is taken already! Pick a new profile." % (collision))
  757. layout_0.addWidget(collision_warning)
  758. else:
  759. layout_0.addWidget(self.currentHandle, alignment=QtCore.Qt.AlignHCenter)
  760. layout_0.addLayout(layout_1)
  761. if avail_profiles:
  762. profileLabel = QtGui.QLabel("Or choose an existing profile:", self)
  763. layout_0.addWidget(profileLabel)
  764. layout_0.addWidget(self.profileBox)
  765. layout_0.addLayout(layout_ok)
  766. if not collision and avail_profiles:
  767. layout_0.addWidget(self.delete)
  768. layout_0.addLayout(layout_2)
  769. self.errorMsg = QtGui.QLabel(self)
  770. self.errorMsg.setStyleSheet("color:red;")
  771. layout_0.addWidget(self.errorMsg)
  772. self.setLayout(layout_0)
  773. self.connect(self, QtCore.SIGNAL('accepted()'),
  774. parent, QtCore.SLOT('profileSelected()'))
  775. self.connect(self, QtCore.SIGNAL('rejected()'),
  776. parent, QtCore.SLOT('closeProfile()'))
  777. @QtCore.pyqtSlot()
  778. def openColorDialog(self):
  779. self.colorDialog = QtGui.QColorDialog(self)
  780. color = self.colorDialog.getColor(initial=self.userprofile.chat.color)
  781. self.chumColorButton.setStyleSheet("background: %s" % color.name())
  782. self.chumcolor = color
  783. self.colorDialog = None
  784. @QtCore.pyqtSlot()
  785. def validateProfile(self):
  786. if not self.profileBox or self.profileBox.currentIndex() == 0:
  787. handle = unicode(self.chumHandle.text())
  788. if not PesterProfile.checkLength(handle):
  789. self.errorMsg.setText("PROFILE HANDLE IS TOO LONG")
  790. return
  791. if not PesterProfile.checkValid(handle)[0]:
  792. self.errorMsg.setText("NOT A VALID CHUMTAG. REASON:\n%s" % (PesterProfile.checkValid(handle)[1]))
  793. return
  794. self.accept()
  795. @QtCore.pyqtSlot()
  796. def deleteProfile(self):
  797. if self.profileBox and self.profileBox.currentIndex() > 0:
  798. handle = unicode(self.profileBox.currentText())
  799. if handle == self.parent.profile().handle:
  800. problem = QtGui.QMessageBox()
  801. problem.setStyleSheet(self.theme["main/defaultwindow/style"])
  802. problem.setWindowTitle("Problem!")
  803. problem.setInformativeText("You can't delete the profile you're currently using!")
  804. problem.setStandardButtons(QtGui.QMessageBox.Ok)
  805. problem.exec_()
  806. return
  807. msgbox = QtGui.QMessageBox()
  808. msgbox.setStyleSheet(self.theme["main/defaultwindow/style"])
  809. msgbox.setWindowTitle("WARNING!")
  810. msgbox.setInformativeText("Are you sure you want to delete the profile: %s" % (handle))
  811. msgbox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel)
  812. ret = msgbox.exec_()
  813. if ret == QtGui.QMessageBox.Ok:
  814. try:
  815. remove(_datadir+"profiles/%s.js" % (handle))
  816. except OSError:
  817. problem = QtGui.QMessageBox()
  818. problem.setStyleSheet(self.theme["main/defaultwindow/style"])
  819. problem.setWindowTitle("Problem!")
  820. problem.setInformativeText("There was a problem deleting the profile: %s" % (handle))
  821. problem.setStandardButtons(QtGui.QMessageBox.Ok)
  822. problem.exec_()
  823. class PesterMentions(QtGui.QDialog):
  824. def __init__(self, window, theme, parent):
  825. QtGui.QDialog.__init__(self, parent)
  826. self.setWindowTitle("Mentions")
  827. self.setModal(True)
  828. self.mainwindow = window
  829. self.theme = theme
  830. self.setStyleSheet(self.theme["main/defaultwindow/style"])
  831. self.mentionlist = QtGui.QListWidget(self)
  832. self.mentionlist.addItems(self.mainwindow.userprofile.getMentions())
  833. self.addBtn = QtGui.QPushButton("ADD MENTION", self)
  834. self.connect(self.addBtn, QtCore.SIGNAL('clicked()'),
  835. self, QtCore.SLOT('addMention()'))
  836. self.editBtn = QtGui.QPushButton("EDIT", self)
  837. self.connect(self.editBtn, QtCore.SIGNAL('clicked()'),
  838. self, QtCore.SLOT('editSelected()'))
  839. self.rmBtn = QtGui.QPushButton("REMOVE", self)
  840. self.connect(self.rmBtn, QtCore.SIGNAL('clicked()'),
  841. self, QtCore.SLOT('removeCurrent()'))
  842. layout_1 = QtGui.QHBoxLayout()
  843. layout_1.addWidget(self.editBtn)
  844. layout_1.addWidget(self.rmBtn)
  845. self.ok = QtGui.QPushButton("OK", self)
  846. self.ok.setDefault(True)
  847. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  848. self, QtCore.SLOT('accept()'))
  849. self.cancel = QtGui.QPushButton("CANCEL", self)
  850. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  851. self, QtCore.SLOT('reject()'))
  852. layout_2 = QtGui.QHBoxLayout()
  853. layout_2.addWidget(self.cancel)
  854. layout_2.addWidget(self.ok)
  855. layout_0 = QtGui.QVBoxLayout()
  856. layout_0.addWidget(self.mentionlist)
  857. layout_0.addWidget(self.addBtn)
  858. layout_0.addLayout(layout_1)
  859. layout_0.addLayout(layout_2)
  860. self.setLayout(layout_0)
  861. @QtCore.pyqtSlot()
  862. def editSelected(self):
  863. m = self.mentionlist.currentItem()
  864. if not m:
  865. return
  866. self.addMention(m)
  867. @QtCore.pyqtSlot()
  868. def addMention(self, mitem=None):
  869. d = {"label": "Mention:", "inputname": "value" }
  870. if mitem is not None:
  871. d["value"] = str(mitem.text())
  872. pdict = MultiTextDialog("ENTER MENTION", self, d).getText()
  873. if pdict is None:
  874. return
  875. try:
  876. re.compile(pdict["value"])
  877. except re.error, e:
  878. quirkWarning = QtGui.QMessageBox(self)
  879. quirkWarning.setText("Not a valid regular expression!")
  880. quirkWarning.setInformativeText("H3R3S WHY DUMP4SS: %s" % (e))
  881. quirkWarning.exec_()
  882. else:
  883. if mitem is None:
  884. self.mentionlist.addItem(pdict["value"])
  885. else:
  886. mitem.setText(pdict["value"])
  887. @QtCore.pyqtSlot()
  888. def removeCurrent(self):
  889. i = self.mentionlist.currentRow()
  890. if i >= 0:
  891. self.mentionlist.takeItem(i)
  892. class PesterOptions(QtGui.QDialog):
  893. def __init__(self, config, theme, parent):
  894. QtGui.QDialog.__init__(self, parent)
  895. self.setWindowTitle("Options")
  896. self.setModal(False)
  897. self.config = config
  898. self.theme = theme
  899. self.setStyleSheet(self.theme["main/defaultwindow/style"])
  900. layout_4 = QtGui.QVBoxLayout()
  901. hr = QtGui.QFrame()
  902. hr.setFrameShape(QtGui.QFrame.HLine)
  903. hr.setFrameShadow(QtGui.QFrame.Sunken)
  904. vr = QtGui.QFrame()
  905. vr.setFrameShape(QtGui.QFrame.VLine)
  906. vr.setFrameShadow(QtGui.QFrame.Sunken)
  907. self.tabs = QtGui.QButtonGroup(self)
  908. self.connect(self.tabs, QtCore.SIGNAL('buttonClicked(int)'),
  909. self, QtCore.SLOT('changePage(int)'))
  910. tabNames = ["Chum List", "Conversations", "Interface", "Sound", "Notifications", "Logging", "Idle/Updates", "Theme"]
  911. if parent.advanced: tabNames.append("Advanced")
  912. for t in tabNames:
  913. button = QtGui.QPushButton(t)
  914. self.tabs.addButton(button)
  915. layout_4.addWidget(button)
  916. button.setCheckable(True)
  917. self.tabs.button(-2).setChecked(True)
  918. self.pages = QtGui.QStackedWidget(self)
  919. self.bandwidthcheck = QtGui.QCheckBox("Low Bandwidth", self)
  920. if self.config.lowBandwidth():
  921. self.bandwidthcheck.setChecked(True)
  922. bandwidthLabel = QtGui.QLabel("(Stops you for receiving the flood of MOODS,\n"
  923. " though stops chumlist from working properly)")
  924. font = bandwidthLabel.font()
  925. font.setPointSize(8)
  926. bandwidthLabel.setFont(font)
  927. self.tabcheck = QtGui.QCheckBox("Tabbed Conversations", self)
  928. if self.config.tabs():
  929. self.tabcheck.setChecked(True)
  930. self.tabmemocheck = QtGui.QCheckBox("Tabbed Memos", self)
  931. if self.config.tabMemos():
  932. self.tabmemocheck.setChecked(True)
  933. self.hideOffline = QtGui.QCheckBox("Hide Offline Chums", self)
  934. if self.config.hideOfflineChums():
  935. self.hideOffline.setChecked(True)
  936. self.soundcheck = QtGui.QCheckBox("Sounds On", self)
  937. self.connect(self.soundcheck, QtCore.SIGNAL('stateChanged(int)'),
  938. self, QtCore.SLOT('soundChange(int)'))
  939. self.chatsoundcheck = QtGui.QCheckBox("Pester Sounds", self)
  940. self.chatsoundcheck.setChecked(self.config.chatSound())
  941. self.memosoundcheck = QtGui.QCheckBox("Memo Sounds", self)
  942. self.memosoundcheck.setChecked(self.config.memoSound())
  943. self.connect(self.memosoundcheck, QtCore.SIGNAL('stateChanged(int)'),
  944. self, QtCore.SLOT('memoSoundChange(int)'))
  945. self.memopingcheck = QtGui.QCheckBox("Memo Ping", self)
  946. self.memopingcheck.setChecked(self.config.memoPing())
  947. self.namesoundcheck = QtGui.QCheckBox("Memo Mention (initials)", self)
  948. self.namesoundcheck.setChecked(self.config.nameSound())
  949. if self.config.soundOn():
  950. self.soundcheck.setChecked(True)
  951. if not self.memosoundcheck.isChecked():
  952. self.memoSoundChange(0)
  953. else:
  954. self.chatsoundcheck.setEnabled(False)
  955. self.memosoundcheck.setEnabled(False)
  956. self.memoSoundChange(0)
  957. self.editMentions = QtGui.QPushButton("Edit Mentions", self)
  958. self.connect(self.editMentions, QtCore.SIGNAL('clicked()'),
  959. self, QtCore.SLOT('openMentions()'))
  960. self.editMentions2 = QtGui.QPushButton("Edit Mentions", self)
  961. self.connect(self.editMentions2, QtCore.SIGNAL('clicked()'),
  962. self, QtCore.SLOT('openMentions()'))
  963. self.volume = QtGui.QSlider(QtCore.Qt.Horizontal, self)
  964. self.volume.setMinimum(0)
  965. self.volume.setMaximum(100)
  966. self.volume.setValue(self.config.volume())
  967. self.connect(self.volume, QtCore.SIGNAL('valueChanged(int)'),
  968. self, QtCore.SLOT('printValue(int)'))
  969. self.currentVol = QtGui.QLabel(str(self.config.volume())+"%", self)
  970. self.currentVol.setAlignment(QtCore.Qt.AlignHCenter)
  971. self.timestampcheck = QtGui.QCheckBox("Time Stamps", self)
  972. if self.config.showTimeStamps():
  973. self.timestampcheck.setChecked(True)
  974. self.timestampBox = QtGui.QComboBox(self)
  975. self.timestampBox.addItem("12 hour")
  976. self.timestampBox.addItem("24 hour")
  977. if self.config.time12Format():
  978. self.timestampBox.setCurrentIndex(0)
  979. else:
  980. self.timestampBox.setCurrentIndex(1)
  981. self.secondscheck = QtGui.QCheckBox("Show Seconds", self)
  982. if self.config.showSeconds():
  983. self.secondscheck.setChecked(True)
  984. self.memomessagecheck = QtGui.QCheckBox("Show OP and Voice Messages in Memos", self)
  985. if self.config.opvoiceMessages():
  986. self.memomessagecheck.setChecked(True)
  987. if not ostools.isOSXBundle():
  988. self.animationscheck = QtGui.QCheckBox("Use animated smilies", self)
  989. if self.config.animations():
  990. self.animationscheck.setChecked(True)
  991. animateLabel = QtGui.QLabel("(Disable if you leave chats open for LOOOONG periods of time)")
  992. font = animateLabel.font()
  993. font.setPointSize(8)
  994. animateLabel.setFont(font)
  995. self.userlinkscheck = QtGui.QCheckBox("Disable #Memo and @User Links", self)
  996. self.userlinkscheck.setChecked(self.config.disableUserLinks())
  997. self.userlinkscheck.setVisible(False)
  998. # Will add ability to turn off groups later
  999. #self.groupscheck = QtGui.QCheckBox("Use Groups", self)
  1000. #self.groupscheck.setChecked(self.config.useGroups())
  1001. self.showemptycheck = QtGui.QCheckBox("Show Empty Groups", self)
  1002. self.showemptycheck.setChecked(self.config.showEmptyGroups())
  1003. self.showonlinenumbers = QtGui.QCheckBox("Show Number of Online Chums", self)
  1004. self.showonlinenumbers.setChecked(self.config.showOnlineNumbers())
  1005. sortLabel = QtGui.QLabel("Sort Chums")
  1006. self.sortBox = QtGui.QComboBox(self)
  1007. self.sortBox.addItem("Alphabetically")
  1008. self.sortBox.addItem("By Mood")
  1009. self.sortBox.addItem("Manually")
  1010. method = self.config.sortMethod()
  1011. if method >= 0 and method < self.sortBox.count():
  1012. self.sortBox.setCurrentIndex(method)
  1013. layout_3 = QtGui.QHBoxLayout()
  1014. layout_3.addWidget(sortLabel)
  1015. layout_3.addWidget(self.sortBox, 10)
  1016. self.logpesterscheck = QtGui.QCheckBox("Log all Pesters", self)
  1017. if self.config.logPesters() & self.config.LOG:
  1018. self.logpesterscheck.setChecked(True)
  1019. self.logmemoscheck = QtGui.QCheckBox("Log all Memos", self)
  1020. if self.config.logMemos() & self.config.LOG:
  1021. self.logmemoscheck.setChecked(True)
  1022. self.stamppestercheck = QtGui.QCheckBox("Log Time Stamps for Pesters", self)
  1023. if self.config.logPesters() & self.config.STAMP:
  1024. self.stamppestercheck.setChecked(True)
  1025. self.stampmemocheck = QtGui.QCheckBox("Log Time Stamps for Memos", self)
  1026. if self.config.logMemos() & self.config.STAMP:
  1027. self.stampmemocheck.setChecked(True)
  1028. self.idleBox = QtGui.QSpinBox(self)
  1029. self.idleBox.setStyleSheet("background:#FFFFFF")
  1030. self.idleBox.setRange(1, 1440)
  1031. self.idleBox.setValue(self.config.idleTime())
  1032. layout_5 = QtGui.QHBoxLayout()
  1033. layout_5.addWidget(QtGui.QLabel("Minutes before Idle:"))
  1034. layout_5.addWidget(self.idleBox)
  1035. self.updateBox = QtGui.QComboBox(self)
  1036. self.updateBox.addItem("Once a Day")
  1037. self.updateBox.addItem("Once a Week")
  1038. self.updateBox.addItem("Only on Start")
  1039. self.updateBox.addItem("Never")
  1040. check = self.config.checkForUpdates()
  1041. if check >= 0 and check < self.updateBox.count():
  1042. self.updateBox.setCurrentIndex(check)
  1043. layout_6 = QtGui.QHBoxLayout()
  1044. layout_6.addWidget(QtGui.QLabel("Check for\nPesterchum Updates:"))
  1045. layout_6.addWidget(self.updateBox)
  1046. if not ostools.isOSXLeopard():
  1047. self.mspaCheck = QtGui.QCheckBox("Check for MSPA Updates", self)
  1048. self.mspaCheck.setChecked(self.config.checkMSPA())
  1049. self.randomscheck = QtGui.QCheckBox("Receive Random Encounters")
  1050. self.randomscheck.setChecked(parent.userprofile.randoms)
  1051. if not parent.randhandler.running:
  1052. self.randomscheck.setEnabled(False)
  1053. avail_themes = self.config.availableThemes()
  1054. self.themeBox = QtGui.QComboBox(self)
  1055. notheme = (theme.name not in avail_themes)
  1056. for (i, t) in enumerate(avail_themes):
  1057. self.themeBox.addItem(t)
  1058. if (not notheme and t == theme.name) or (notheme and t == "pesterchum"):
  1059. self.themeBox.setCurrentIndex(i)
  1060. self.refreshtheme = QtGui.QPushButton("Refresh current theme", self)
  1061. self.connect(self.refreshtheme, QtCore.SIGNAL('clicked()'),
  1062. parent, QtCore.SLOT('themeSelectOverride()'))
  1063. self.ghostchum = QtGui.QCheckBox("Pesterdunk Ghostchum!!", self)
  1064. self.ghostchum.setChecked(self.config.ghostchum())
  1065. self.buttonOptions = ["Minimize to Taskbar", "Minimize to Tray", "Quit"]
  1066. self.miniBox = QtGui.QComboBox(self)
  1067. self.miniBox.addItems(self.buttonOptions)
  1068. self.miniBox.setCurrentIndex(self.config.minimizeAction())
  1069. self.closeBox = QtGui.QComboBox(self)
  1070. self.closeBox.addItems(self.buttonOptions)
  1071. self.closeBox.setCurrentIndex(self.config.closeAction())
  1072. layout_mini = QtGui.QHBoxLayout()
  1073. layout_mini.addWidget(QtGui.QLabel("Minimize"))
  1074. layout_mini.addWidget(self.miniBox)
  1075. layout_close = QtGui.QHBoxLayout()
  1076. layout_close.addWidget(QtGui.QLabel("Close"))
  1077. layout_close.addWidget(self.closeBox)
  1078. self.pesterBlink = QtGui.QCheckBox("Blink Taskbar on Pesters", self)
  1079. if self.config.blink() & self.config.PBLINK:
  1080. self.pesterBlink.setChecked(True)
  1081. self.memoBlink = QtGui.QCheckBox("Blink Taskbar on Memos", self)
  1082. if self.config.blink() & self.config.MBLINK:
  1083. self.memoBlink.setChecked(True)
  1084. self.notifycheck = QtGui.QCheckBox("Toast Notifications", self)
  1085. if self.config.notify():
  1086. self.notifycheck.setChecked(True)
  1087. self.connect(self.notifycheck, QtCore.SIGNAL('stateChanged(int)'),
  1088. self, QtCore.SLOT('notifyChange(int)'))
  1089. self.notifyOptions = QtGui.QComboBox(self)
  1090. types = self.parent().tm.availableTypes()
  1091. cur = self.parent().tm.currentType()
  1092. self.notifyOptions.addItems(types)
  1093. for (i,t) in enumerate(types):
  1094. if t == cur:
  1095. self.notifyOptions.setCurrentIndex(i)
  1096. break
  1097. self.notifyTypeLabel = QtGui.QLabel("Type", self)
  1098. layout_type = QtGui.QHBoxLayout()
  1099. layout_type.addWidget(self.notifyTypeLabel)
  1100. layout_type.addWidget(self.notifyOptions)
  1101. self.notifySigninCheck = QtGui.QCheckBox("Chum signs in", self)
  1102. if self.config.notifyOptions() & self.config.SIGNIN:
  1103. self.notifySigninCheck.setChecked(True)
  1104. self.notifySignoutCheck = QtGui.QCheckBox("Chum signs out", self)
  1105. if self.config.notifyOptions() & self.config.SIGNOUT:
  1106. self.notifySignoutCheck.setChecked(True)
  1107. self.notifyNewMsgCheck = QtGui.QCheckBox("New messages", self)
  1108. if self.config.notifyOptions() & self.config.NEWMSG:
  1109. self.notifyNewMsgCheck.setChecked(True)
  1110. self.notifyNewConvoCheck = QtGui.QCheckBox("Only new conversations", self)
  1111. if self.config.notifyOptions() & self.config.NEWCONVO:
  1112. self.notifyNewConvoCheck.setChecked(True)
  1113. self.notifyMentionsCheck = QtGui.QCheckBox("Memo Mentions (initials)", self)
  1114. if self.config.notifyOptions() & self.config.INITIALS:
  1115. self.notifyMentionsCheck.setChecked(True)
  1116. self.notifyChange(self.notifycheck.checkState())
  1117. if parent.advanced:
  1118. self.modechange = QtGui.QLineEdit(self)
  1119. layout_change = QtGui.QHBoxLayout()
  1120. layout_change.addWidget(QtGui.QLabel("Change:"))
  1121. layout_change.addWidget(self.modechange)
  1122. self.ok = QtGui.QPushButton("OK", self)
  1123. self.ok.setDefault(True)
  1124. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  1125. self, QtCore.SLOT('accept()'))
  1126. self.cancel = QtGui.QPushButton("CANCEL", self)
  1127. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  1128. self, QtCore.SLOT('reject()'))
  1129. layout_2 = QtGui.QHBoxLayout()
  1130. layout_2.addWidget(self.cancel)
  1131. layout_2.addWidget(self.ok)
  1132. # Tab layouts
  1133. # Chum List
  1134. widget = QtGui.QWidget()
  1135. layout_chumlist = QtGui.QVBoxLayout(widget)
  1136. layout_chumlist.setAlignment(QtCore.Qt.AlignTop)
  1137. layout_chumlist.addWidget(self.hideOffline)
  1138. #layout_chumlist.addWidget(self.groupscheck)
  1139. layout_chumlist.addWidget(self.showemptycheck)
  1140. layout_chumlist.addWidget(self.showonlinenumbers)
  1141. layout_chumlist.addLayout(layout_3)
  1142. layout_chumlist.addWidget(self.bandwidthcheck)
  1143. layout_chumlist.addWidget(bandwidthLabel)
  1144. self.pages.addWidget(widget)
  1145. # Conversations
  1146. widget = QtGui.QWidget()
  1147. layout_chat = QtGui.QVBoxLayout(widget)
  1148. layout_chat.setAlignment(QtCore.Qt.AlignTop)
  1149. layout_chat.addWidget(self.timestampcheck)
  1150. layout_chat.addWidget(self.timestampBox)
  1151. layout_chat.addWidget(self.secondscheck)
  1152. layout_chat.addWidget(self.memomessagecheck)
  1153. if not ostools.isOSXBundle():
  1154. layout_chat.addWidget(self.animationscheck)
  1155. layout_chat.addWidget(animateLabel)
  1156. layout_chat.addWidget(self.randomscheck)
  1157. # Re-enable these when it's possible to disable User and Memo links
  1158. #layout_chat.addWidget(hr)
  1159. #layout_chat.addWidget(QtGui.QLabel("User and Memo Links"))
  1160. #layout_chat.addWidget(self.userlinkscheck)
  1161. self.pages.addWidget(widget)
  1162. # Interface
  1163. widget = QtGui.QWidget()
  1164. layout_interface = QtGui.QVBoxLayout(widget)
  1165. layout_interface.setAlignment(QtCore.Qt.AlignTop)
  1166. layout_interface.addWidget(self.tabcheck)
  1167. layout_interface.addWidget(self.tabmemocheck)
  1168. layout_interface.addLayout(layout_mini)
  1169. layout_interface.addLayout(layout_close)
  1170. layout_interface.addWidget(self.pesterBlink)
  1171. layout_interface.addWidget(self.memoBlink)
  1172. self.pages.addWidget(widget)
  1173. # Sound
  1174. widget = QtGui.QWidget()
  1175. layout_sound = QtGui.QVBoxLayout(widget)
  1176. layout_sound.setAlignment(QtCore.Qt.AlignTop)
  1177. layout_sound.addWidget(self.soundcheck)
  1178. layout_indent = QtGui.QVBoxLayout()
  1179. layout_indent.addWidget(self.chatsoundcheck)
  1180. layout_indent.addWidget(self.memosoundcheck)
  1181. layout_doubleindent = QtGui.QVBoxLayout()
  1182. layout_doubleindent.addWidget(self.memopingcheck)
  1183. layout_doubleindent.addWidget(self.namesoundcheck)
  1184. layout_doubleindent.addWidget(self.editMentions)
  1185. layout_doubleindent.setContentsMargins(22,0,0,0)
  1186. layout_indent.addLayout(layout_doubleindent)
  1187. layout_indent.setContentsMargins(22,0,0,0)
  1188. layout_sound.addLayout(layout_indent)
  1189. layout_sound.addSpacing(15)
  1190. layout_sound.addWidget(QtGui.QLabel("Master Volume:", self))
  1191. layout_sound.addWidget(self.volume)
  1192. layout_sound.addWidget(self.currentVol)
  1193. self.pages.addWidget(widget)
  1194. # Notifications
  1195. widget = QtGui.QWidget()
  1196. layout_notify = QtGui.QVBoxLayout(widget)
  1197. layout_notify.setAlignment(QtCore.Qt.AlignTop)
  1198. layout_notify.addWidget(self.notifycheck)
  1199. layout_indent = QtGui.QVBoxLayout()
  1200. layout_indent.addLayout(layout_type)
  1201. layout_indent.setContentsMargins(22,0,0,0)
  1202. layout_indent.addWidget(self.notifySigninCheck)
  1203. layout_indent.addWidget(self.notifySignoutCheck)
  1204. layout_indent.addWidget(self.notifyNewMsgCheck)
  1205. layout_doubleindent = QtGui.QVBoxLayout()
  1206. layout_doubleindent.addWidget(self.notifyNewConvoCheck)
  1207. layout_doubleindent.setContentsMargins(22,0,0,0)
  1208. layout_indent.addLayout(layout_doubleindent)
  1209. layout_indent.addWidget(self.notifyMentionsCheck)
  1210. layout_indent.addWidget(self.editMentions2)
  1211. layout_notify.addLayout(layout_indent)
  1212. self.pages.addWidget(widget)
  1213. # Logging
  1214. widget = QtGui.QWidget()
  1215. layout_logs = QtGui.QVBoxLayout(widget)
  1216. layout_logs.setAlignment(QtCore.Qt.AlignTop)
  1217. layout_logs.addWidget(self.logpesterscheck)
  1218. layout_logs.addWidget(self.logmemoscheck)
  1219. layout_logs.addWidget(self.stamppestercheck)
  1220. layout_logs.addWidget(self.stampmemocheck)
  1221. self.pages.addWidget(widget)
  1222. # Idle/Updates
  1223. widget = QtGui.QWidget()
  1224. layout_idle = QtGui.QVBoxLayout(widget)
  1225. layout_idle.setAlignment(QtCore.Qt.AlignTop)
  1226. layout_idle.addLayout(layout_5)
  1227. layout_idle.addLayout(layout_6)
  1228. if not ostools.isOSXLeopard():
  1229. layout_idle.addWidget(self.mspaCheck)
  1230. self.pages.addWidget(widget)
  1231. # Theme
  1232. widget = QtGui.QWidget()
  1233. layout_theme = QtGui.QVBoxLayout(widget)
  1234. layout_theme.setAlignment(QtCore.Qt.AlignTop)
  1235. layout_theme.addWidget(QtGui.QLabel("Pick a Theme:"))
  1236. layout_theme.addWidget(self.themeBox)
  1237. layout_theme.addWidget(self.refreshtheme)
  1238. layout_theme.addWidget(self.ghostchum)
  1239. self.pages.addWidget(widget)
  1240. # Advanced
  1241. if parent.advanced:
  1242. widget = QtGui.QWidget()
  1243. layout_advanced = QtGui.QVBoxLayout(widget)
  1244. layout_advanced.setAlignment(QtCore.Qt.AlignTop)
  1245. layout_advanced.addWidget(QtGui.QLabel("Current User Mode: %s" % parent.modes))
  1246. layout_advanced.addLayout(layout_change)
  1247. self.pages.addWidget(widget)
  1248. layout_0 = QtGui.QVBoxLayout()
  1249. layout_1 = QtGui.QHBoxLayout()
  1250. layout_1.addLayout(layout_4)
  1251. layout_1.addWidget(vr)
  1252. layout_1.addWidget(self.pages)
  1253. layout_0.addLayout(layout_1)
  1254. layout_0.addSpacing(30)
  1255. layout_0.addLayout(layout_2)
  1256. self.setLayout(layout_0)
  1257. @QtCore.pyqtSlot(int)
  1258. def changePage(self, page):
  1259. self.tabs.button(page).setChecked(True)
  1260. # What is this, I don't even. qt, fuck
  1261. page = -page - 2
  1262. self.pages.setCurrentIndex(page)
  1263. @QtCore.pyqtSlot(int)
  1264. def notifyChange(self, state):
  1265. if state == 0:
  1266. self.notifyTypeLabel.setEnabled(False)
  1267. self.notifyOptions.setEnabled(False)
  1268. self.notifySigninCheck.setEnabled(False)
  1269. self.notifySignoutCheck.setEnabled(False)
  1270. self.notifyNewMsgCheck.setEnabled(False)
  1271. self.notifyNewConvoCheck.setEnabled(False)
  1272. self.notifyMentionsCheck.setEnabled(False)
  1273. else:
  1274. self.notifyTypeLabel.setEnabled(True)
  1275. self.notifyOptions.setEnabled(True)
  1276. self.notifySigninCheck.setEnabled(True)
  1277. self.notifySignoutCheck.setEnabled(True)
  1278. self.notifyNewMsgCheck.setEnabled(True)
  1279. self.notifyNewConvoCheck.setEnabled(True)
  1280. self.notifyMentionsCheck.setEnabled(True)
  1281. @QtCore.pyqtSlot(int)
  1282. def soundChange(self, state):
  1283. if state == 0:
  1284. self.chatsoundcheck.setEnabled(False)
  1285. self.memosoundcheck.setEnabled(False)
  1286. self.memoSoundChange(0)
  1287. else:
  1288. self.chatsoundcheck.setEnabled(True)
  1289. self.memosoundcheck.setEnabled(True)
  1290. if self.memosoundcheck.isChecked():
  1291. self.memoSoundChange(1)
  1292. @QtCore.pyqtSlot(int)
  1293. def memoSoundChange(self, state):
  1294. if state == 0:
  1295. self.memopingcheck.setEnabled(False)
  1296. self.namesoundcheck.setEnabled(False)
  1297. else:
  1298. self.memopingcheck.setEnabled(True)
  1299. self.namesoundcheck.setEnabled(True)
  1300. @QtCore.pyqtSlot(int)
  1301. def printValue(self, v):
  1302. self.currentVol.setText(str(v)+"%")
  1303. @QtCore.pyqtSlot()
  1304. def openMentions(self):
  1305. if not hasattr(self, 'mentionmenu'):
  1306. self.mentionmenu = None
  1307. if not self.mentionmenu:
  1308. self.mentionmenu = PesterMentions(self.parent(), self.theme, self)
  1309. self.connect(self.mentionmenu, QtCore.SIGNAL('accepted()'),
  1310. self, QtCore.SLOT('updateMentions()'))
  1311. self.connect(self.mentionmenu, QtCore.SIGNAL('rejected()'),
  1312. self, QtCore.SLOT('closeMentions()'))
  1313. self.mentionmenu.show()
  1314. self.mentionmenu.raise_()
  1315. self.mentionmenu.activateWindow()
  1316. @QtCore.pyqtSlot()
  1317. def closeMentions(self):
  1318. self.mentionmenu.close()
  1319. self.mentionmenu = None
  1320. @QtCore.pyqtSlot()
  1321. def updateMentions(self):
  1322. m = []
  1323. for i in range(self.mentionmenu.mentionlist.count()):
  1324. m.append(str(self.mentionmenu.mentionlist.item(i).text()))
  1325. self.parent().userprofile.setMentions(m)
  1326. self.mentionmenu = None
  1327. class PesterUserlist(QtGui.QDialog):
  1328. def __init__(self, config, theme, parent):
  1329. QtGui.QDialog.__init__(self, parent)
  1330. self.setModal(False)
  1331. self.config = config
  1332. self.theme = theme
  1333. self.mainwindow = parent
  1334. self.setStyleSheet(self.theme["main/defaultwindow/style"])
  1335. self.resize(200, 600)
  1336. self.searchbox = QtGui.QLineEdit(self)
  1337. #self.searchbox.setStyleSheet(theme["convo/input/style"]) # which style is better?
  1338. self.searchbox.setPlaceholderText("Search")
  1339. self.connect(self.searchbox, QtCore.SIGNAL("textChanged(QString)"), self, QtCore.SLOT("updateUsers()"))
  1340. self.label = QtGui.QLabel("USERLIST")
  1341. self.userarea = RightClickList(self)
  1342. self.userarea.setStyleSheet(self.theme["main/chums/style"])
  1343. self.userarea.optionsMenu = QtGui.QMenu(self)
  1344. self.addChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self)
  1345. self.connect(self.addChumAction, QtCore.SIGNAL('triggered()'),
  1346. self, QtCore.SLOT('addChumSlot()'))
  1347. self.pesterChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self)
  1348. self.connect(self.pesterChumAction, QtCore.SIGNAL('triggered()'),
  1349. self, QtCore.SLOT('pesterChumSlot()'))
  1350. self.userarea.optionsMenu.addAction(self.addChumAction)
  1351. self.userarea.optionsMenu.addAction(self.pesterChumAction)
  1352. self.ok = QtGui.QPushButton("OK", self)
  1353. self.ok.setDefault(True)
  1354. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  1355. self, QtCore.SLOT('accept()'))
  1356. layout_0 = QtGui.QVBoxLayout()
  1357. layout_0.addWidget(self.label)
  1358. layout_0.addWidget(self.userarea)
  1359. layout_0.addWidget(self.searchbox)
  1360. layout_0.addWidget(self.ok)
  1361. self.setLayout(layout_0)
  1362. self.connect(self.mainwindow, QtCore.SIGNAL('namesUpdated()'),
  1363. self, QtCore.SLOT('updateUsers()'))
  1364. self.connect(self.mainwindow,
  1365. QtCore.SIGNAL('userPresentSignal(QString, QString, QString)'),
  1366. self,
  1367. QtCore.SLOT('updateUserPresent(QString, QString, QString)'))
  1368. self.updateUsers()
  1369. self.searchbox.setFocus()
  1370. @QtCore.pyqtSlot()
  1371. def updateUsers(self):
  1372. names = self.mainwindow.namesdb["#pesterchum"]
  1373. self.userarea.clear()
  1374. for n in names:
  1375. if str(self.searchbox.text()) == "" or n.lower().find(str(self.searchbox.text()).lower()) != -1:
  1376. item = QtGui.QListWidgetItem(n)
  1377. item.setTextColor(QtGui.QColor(self.theme["main/chums/userlistcolor"]))
  1378. self.userarea.addItem(item)
  1379. self.userarea.sortItems()
  1380. @QtCore.pyqtSlot(QtCore.QString, QtCore.QString, QtCore.QString)
  1381. def updateUserPresent(self, handle, channel, update):
  1382. h = unicode(handle)
  1383. c = unicode(channel)
  1384. if update == "quit":
  1385. self.delUser(h)
  1386. elif update == "left" and c == "#pesterchum":
  1387. self.delUser(h)
  1388. elif update == "join" and c == "#pesterchum":
  1389. if str(self.searchbox.text()) == "" or h.lower().find(str(self.searchbox.text()).lower()) != -1:
  1390. self.addUser(h)
  1391. def addUser(self, name):
  1392. item = QtGui.QListWidgetItem(name)
  1393. item.setTextColor(QtGui.QColor(self.theme["main/chums/userlistcolor"]))
  1394. self.userarea.addItem(item)
  1395. self.userarea.sortItems()
  1396. def delUser(self, name):
  1397. matches = self.userarea.findItems(name, QtCore.Qt.MatchFlags(0))
  1398. for m in matches:
  1399. self.userarea.takeItem(self.userarea.row(m))
  1400. def changeTheme(self, theme):
  1401. self.theme = theme
  1402. self.setStyleSheet(theme["main/defaultwindow/style"])
  1403. self.userarea.setStyleSheet(theme["main/chums/style"])
  1404. self.addChumAction.setText(theme["main/menus/rclickchumlist/addchum"])
  1405. for item in [self.userarea.item(i) for i in range(0, self.userarea.count())]:
  1406. item.setTextColor(QtGui.QColor(theme["main/chums/userlistcolor"]))
  1407. @QtCore.pyqtSlot()
  1408. def addChumSlot(self):
  1409. cur = self.userarea.currentItem()
  1410. if not cur:
  1411. return
  1412. self.addChum.emit(cur.text())
  1413. @QtCore.pyqtSlot()
  1414. def pesterChumSlot(self):
  1415. cur = self.userarea.currentItem()
  1416. if not cur:
  1417. return
  1418. self.pesterChum.emit(cur.text())
  1419. addChum = QtCore.pyqtSignal(QtCore.QString)
  1420. pesterChum = QtCore.pyqtSignal(QtCore.QString)
  1421. class MemoListItem(QtGui.QTreeWidgetItem):
  1422. def __init__(self, channel, usercount):
  1423. QtGui.QTreeWidgetItem.__init__(self, [channel, str(usercount)])
  1424. self.target = channel
  1425. def __lt__(self, other):
  1426. column = self.treeWidget().sortColumn()
  1427. if str(self.text(column)).isdigit() and str(other.text(column)).isdigit():
  1428. return int(self.text(column)) < int(other.text(column))
  1429. return self.text(column) < other.text(column)
  1430. class PesterMemoList(QtGui.QDialog):
  1431. def __init__(self, parent, channel=""):
  1432. QtGui.QDialog.__init__(self, parent)
  1433. self.setModal(False)
  1434. self.theme = parent.theme
  1435. self.mainwindow = parent
  1436. self.setStyleSheet(self.theme["main/defaultwindow/style"])
  1437. self.resize(460, 300)
  1438. self.label = QtGui.QLabel("MEMOS")
  1439. self.channelarea = RightClickTree(self)
  1440. self.channelarea.setStyleSheet(self.theme["main/chums/style"])
  1441. self.channelarea.optionsMenu = QtGui.QMenu(self)
  1442. self.channelarea.setColumnCount(2)
  1443. self.channelarea.setHeaderLabels(["Memo", "Users"])
  1444. self.channelarea.setIndentation(0)
  1445. self.channelarea.setColumnWidth(0,200)
  1446. self.channelarea.setColumnWidth(1,10)
  1447. self.channelarea.setSortingEnabled(True)
  1448. self.channelarea.sortByColumn(0, QtCore.Qt.AscendingOrder)
  1449. self.connect(self.channelarea,
  1450. QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem *, int)'),
  1451. self, QtCore.SLOT('joinActivatedMemo()'))
  1452. self.orjoinlabel = QtGui.QLabel("OR MAKE A NEW MEMO:")
  1453. self.newmemo = QtGui.QLineEdit(channel, self)
  1454. self.secretChannel = QtGui.QCheckBox("HIDDEN CHANNEL?", self)
  1455. self.inviteChannel = QtGui.QCheckBox("INVITATION ONLY?", self)
  1456. self.timelabel = QtGui.QLabel("TIMEFRAME:")
  1457. self.timeslider = TimeSlider(QtCore.Qt.Horizontal, self)
  1458. self.timeinput = TimeInput(self.timeslider, self)
  1459. self.cancel = QtGui.QPushButton("CANCEL", self)
  1460. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  1461. self, QtCore.SLOT('reject()'))
  1462. self.join = QtGui.QPushButton("JOIN", self)
  1463. self.join.setDefault(True)
  1464. self.connect(self.join, QtCore.SIGNAL('clicked()'),
  1465. self, QtCore.SLOT('checkEmpty()'))
  1466. layout_ok = QtGui.QHBoxLayout()
  1467. layout_ok.addWidget(self.cancel)
  1468. layout_ok.addWidget(self.join)
  1469. layout_left = QtGui.QVBoxLayout()
  1470. layout_right = QtGui.QVBoxLayout()
  1471. layout_right.setAlignment(QtCore.Qt.AlignTop)
  1472. layout_0 = QtGui.QVBoxLayout()
  1473. layout_1 = QtGui.QHBoxLayout()
  1474. layout_left.addWidget(self.label)
  1475. layout_left.addWidget(self.channelarea)
  1476. layout_right.addWidget(self.orjoinlabel)
  1477. layout_right.addWidget(self.newmemo)
  1478. layout_right.addWidget(self.secretChannel)
  1479. layout_right.addWidget(self.inviteChannel)
  1480. layout_right.addWidget(self.timelabel)
  1481. layout_right.addWidget(self.timeslider)
  1482. layout_right.addWidget(self.timeinput)
  1483. layout_1.addLayout(layout_left)
  1484. layout_1.addLayout(layout_right)
  1485. layout_0.addLayout(layout_1)
  1486. layout_0.addLayout(layout_ok)
  1487. self.setLayout(layout_0)
  1488. def newmemoname(self):
  1489. return self.newmemo.text()
  1490. def selectedmemo(self):
  1491. return self.channelarea.currentItem()
  1492. def updateChannels(self, channels):
  1493. for c in channels:
  1494. item = MemoListItem(c[0][1:],c[1])
  1495. item.setTextColor(0, QtGui.QColor(self.theme["main/chums/userlistcolor"]))
  1496. item.setTextColor(1, QtGui.QColor(self.theme["main/chums/userlistcolor"]))
  1497. item.setIcon(0, QtGui.QIcon(self.theme["memos/memoicon"]))
  1498. self.channelarea.addTopLevelItem(item)
  1499. def updateTheme(self, theme):
  1500. self.theme = theme
  1501. self.setStyleSheet(theme["main/defaultwindow/style"])
  1502. for item in [self.userarea.item(i) for i in range(0, self.channelarea.count())]:
  1503. item.setTextColor(QtGui.QColor(theme["main/chums/userlistcolor"]))
  1504. item.setIcon(QtGui.QIcon(theme["memos/memoicon"]))
  1505. @QtCore.pyqtSlot()
  1506. def checkEmpty(self):
  1507. newmemo = self.newmemoname()
  1508. selectedmemo = self.selectedmemo()
  1509. if newmemo or selectedmemo:
  1510. self.accept()
  1511. @QtCore.pyqtSlot()
  1512. def joinActivatedMemo(self):
  1513. self.accept()
  1514. class LoadingScreen(QtGui.QDialog):
  1515. def __init__(self, parent=None):
  1516. QtGui.QDialog.__init__(self, parent, (QtCore.Qt.CustomizeWindowHint |
  1517. QtCore.Qt.FramelessWindowHint))
  1518. self.mainwindow = parent
  1519. self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
  1520. self.loadinglabel = QtGui.QLabel("CONN3CT1NG", self)
  1521. self.cancel = QtGui.QPushButton("QU1T >:?", self)
  1522. self.ok = QtGui.QPushButton("R3CONN3CT >:]", self)
  1523. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  1524. self, QtCore.SLOT('reject()'))
  1525. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  1526. self, QtCore.SIGNAL('tryAgain()'))
  1527. self.layout = QtGui.QVBoxLayout()
  1528. self.layout.addWidget(self.loadinglabel)
  1529. layout_1 = QtGui.QHBoxLayout()
  1530. layout_1.addWidget(self.cancel)
  1531. layout_1.addWidget(self.ok)
  1532. self.layout.addLayout(layout_1)
  1533. self.setLayout(self.layout)
  1534. def hideReconnect(self):
  1535. self.ok.hide()
  1536. def showReconnect(self):
  1537. self.ok.show()
  1538. tryAgain = QtCore.pyqtSignal()
  1539. class AboutPesterchum(QtGui.QDialog):
  1540. def __init__(self, parent=None):
  1541. QtGui.QDialog.__init__(self, parent)
  1542. self.mainwindow = parent
  1543. self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
  1544. self.title = QtGui.QLabel("P3ST3RCHUM V. %s" % (_pcVersion))
  1545. self.credits = QtGui.QLabel("Programming by:\n\
  1546. illuminatedwax (ghostDunk)\n\
  1547. Kiooeht (evacipatedBox)\n\
  1548. Lexi (lexicalNuance)\n\
  1549. oakwhiz\n\
  1550. alGore\n\
  1551. Cerxi (binaryCabalist)\n\
  1552. \n\
  1553. Art by:\n\
  1554. Grimlive (aquaMarinist)\n\
  1555. Cerxi (binaryCabalist)\n\
  1556. \n\
  1557. Special Thanks:\n\
  1558. ABT\n\
  1559. gamblingGenocider\n\
  1560. Eco-Mono")
  1561. self.ok = QtGui.QPushButton("OK", self)
  1562. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  1563. self, QtCore.SLOT('reject()'))
  1564. layout_0 = QtGui.QVBoxLayout()
  1565. layout_0.addWidget(self.title)
  1566. layout_0.addWidget(self.credits)
  1567. layout_0.addWidget(self.ok)
  1568. self.setLayout(layout_0)
  1569. class UpdatePesterchum(QtGui.QDialog):
  1570. def __init__(self, ver, url, parent=None):
  1571. QtGui.QDialog.__init__(self, parent)
  1572. self.url = url
  1573. self.mainwindow = parent
  1574. self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
  1575. self.setWindowTitle("Pesterchum v%s Update" % (ver))
  1576. self.setModal(False)
  1577. self.title = QtGui.QLabel("An update to Pesterchum is available!")
  1578. layout_0 = QtGui.QVBoxLayout()
  1579. layout_0.addWidget(self.title)
  1580. self.ok = QtGui.QPushButton("D0WNL04D 4ND 1NST4LL N0W", self)
  1581. self.ok.setDefault(True)
  1582. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  1583. self, QtCore.SLOT('accept()'))
  1584. self.cancel = QtGui.QPushButton("CANCEL", self)
  1585. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  1586. self, QtCore.SLOT('reject()'))
  1587. layout_2 = QtGui.QHBoxLayout()
  1588. layout_2.addWidget(self.cancel)
  1589. layout_2.addWidget(self.ok)
  1590. layout_0.addLayout(layout_2)
  1591. self.setLayout(layout_0)
  1592. class AddChumDialog(QtGui.QDialog):
  1593. def __init__(self, avail_groups, parent=None):
  1594. QtGui.QDialog.__init__(self, parent)
  1595. self.mainwindow = parent
  1596. self.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"])
  1597. self.setWindowTitle("Enter Chum Handle")
  1598. self.setModal(True)
  1599. self.title = QtGui.QLabel("Enter Chum Handle")
  1600. self.chumBox = QtGui.QLineEdit(self)
  1601. self.groupBox = QtGui.QComboBox(self)
  1602. avail_groups.sort()
  1603. avail_groups.pop(avail_groups.index("Chums"))
  1604. avail_groups.insert(0, "Chums")
  1605. for g in avail_groups:
  1606. self.groupBox.addItem(g)
  1607. self.newgrouplabel = QtGui.QLabel("Or make a new group:")
  1608. self.newgroup = QtGui.QLineEdit(self)
  1609. layout_0 = QtGui.QVBoxLayout()
  1610. layout_0.addWidget(self.title)
  1611. layout_0.addWidget(self.chumBox)
  1612. layout_0.addWidget(self.groupBox)
  1613. layout_0.addWidget(self.newgrouplabel)
  1614. layout_0.addWidget(self.newgroup)
  1615. self.ok = QtGui.QPushButton("OK", self)
  1616. self.ok.setDefault(True)
  1617. self.connect(self.ok, QtCore.SIGNAL('clicked()'),
  1618. self, QtCore.SLOT('accept()'))
  1619. self.cancel = QtGui.QPushButton("CANCEL", self)
  1620. self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
  1621. self, QtCore.SLOT('reject()'))
  1622. layout_2 = QtGui.QHBoxLayout()
  1623. layout_2.addWidget(self.cancel)
  1624. layout_2.addWidget(self.ok)
  1625. layout_0.addLayout(layout_2)
  1626. self.setLayout(layout_0)