PageRenderTime 87ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/pesterchum.py

https://github.com/602p/pesterchum
Python | 3030 lines | 2959 code | 37 blank | 34 comment | 184 complexity | 47506ef152ea949f18334b2aa8c08a2e MD5 | raw file
Possible License(s): GPL-3.0, Cube

Large files files are truncated, but you can click here to view the full file

  1. # pesterchum
  2. import os, shutil, sys, getopt
  3. if os.path.dirname(sys.argv[0]):
  4. os.chdir(os.path.dirname(sys.argv[0]))
  5. import version
  6. version.pcVerCalc()
  7. import logging
  8. from datetime import *
  9. import random
  10. import re
  11. from time import time
  12. import threading, Queue
  13. reqmissing = []
  14. optmissing = []
  15. try:
  16. from PyQt4 import QtGui, QtCore
  17. except ImportError, e:
  18. module = str(e)
  19. if module.startswith("No module named ") or \
  20. module.startswith("cannot import name "):
  21. reqmissing.append(module[module.rfind(" ")+1:])
  22. else: print e
  23. try:
  24. import pygame
  25. except ImportError, e:
  26. pygame = None
  27. module = str(e)
  28. if module[:16] == "No module named ": optmissing.append(module[16:])
  29. else: print e
  30. if reqmissing:
  31. print "ERROR: The following modules are required for Pesterchum to run and are missing on your system:"
  32. for m in reqmissing: print "* "+m
  33. exit()
  34. vnum = QtCore.qVersion()
  35. major = int(vnum[:vnum.find(".")])
  36. if vnum.find(".", vnum.find(".")+1) != -1:
  37. minor = int(vnum[vnum.find(".")+1:vnum.find(".", vnum.find(".")+1)])
  38. else:
  39. minor = int(vnum[vnum.find(".")+1:])
  40. if not ((major > 4) or (major == 4 and minor >= 6)):
  41. print "ERROR: Pesterchum requires Qt version >= 4.6"
  42. print "You currently have version " + vnum + ". Please ungrade Qt"
  43. exit()
  44. import ostools
  45. # Placed here before importing the rest of pesterchum, since bits of it need
  46. # OSX's data directory and it doesn't hurt to have everything set up before
  47. # plowing on. :o)
  48. # ~Lex
  49. _datadir = ostools.getDataDir()
  50. # See, what I've done here is that _datadir is '' if we're not on OSX, so the
  51. # concatination is the same as if it wasn't there.
  52. # UPDATE 2011-11-28 <Kiooeht>:
  53. # Now using data directory as defined by QDesktopServices on all platforms
  54. # (on Linux, same as using xdg). To stay safe with older versions, copy any
  55. # data (profiles, logs, etc) from old location to new data directory.
  56. if _datadir:
  57. if not os.path.exists(_datadir):
  58. os.makedirs(_datadir)
  59. if not os.path.exists(_datadir+"profiles/") and os.path.exists("profiles/"):
  60. shutil.move("profiles/", _datadir+"profiles/")
  61. if not os.path.exists(_datadir+"pesterchum.js") and os.path.exists("pesterchum.js"):
  62. shutil.move("pesterchum.js", _datadir+"pesterchum.js")
  63. if not os.path.exists(_datadir+"logs/") and os.path.exists("logs/"):
  64. shutil.move("logs/", _datadir+"logs/")
  65. if not os.path.exists(_datadir+"profiles"):
  66. os.mkdir(_datadir+"profiles")
  67. if not os.path.exists(_datadir+"pesterchum.js"):
  68. f = open(_datadir+"pesterchum.js", 'w')
  69. f.write("{}")
  70. f.close()
  71. if not os.path.exists(_datadir+"logs"):
  72. os.mkdir(_datadir+"logs")
  73. from menus import PesterChooseQuirks, PesterChooseTheme, \
  74. PesterChooseProfile, PesterOptions, PesterUserlist, PesterMemoList, \
  75. LoadingScreen, AboutPesterchum, UpdatePesterchum, AddChumDialog
  76. from mood import Mood, PesterMoodAction, PesterMoodHandler, PesterMoodButton
  77. from dataobjs import PesterProfile, pesterQuirk, pesterQuirks
  78. from generic import PesterIcon, RightClickList, RightClickTree, \
  79. MultiTextDialog, PesterList, CaseInsensitiveDict, MovingWindow, \
  80. NoneSound, WMButton
  81. from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo
  82. from parsetools import convertTags, addTimeInitial, themeChecker, ThemeException
  83. from memos import PesterMemo, MemoTabWindow, TimeTracker
  84. from irc import PesterIRC
  85. from logviewer import PesterLogUserSelect, PesterLogViewer
  86. from bugreport import BugReporter
  87. from randomer import RandomHandler
  88. # Rawr, fuck you OSX leopard
  89. if not ostools.isOSXLeopard():
  90. from updatecheck import MSPAChecker
  91. from toast import PesterToastMachine, PesterToast
  92. from libs import pytwmn
  93. from profile import *
  94. canon_handles = ["apocalypseArisen", "arsenicCatnip", "arachnidsGrip", "adiosToreador", \
  95. "caligulasAquarium", "cuttlefishCuller", "carcinoGeneticist", "centaursTesticle", \
  96. "grimAuxiliatrix", "gallowsCalibrator", "gardenGnostic", "ectoBiologist", \
  97. "twinArmageddons", "terminallyCapricious", "turntechGodhead", "tentacleTherapist"]
  98. class waitingMessageHolder(object):
  99. def __init__(self, mainwindow, **msgfuncs):
  100. self.mainwindow = mainwindow
  101. self.funcs = msgfuncs
  102. self.queue = msgfuncs.keys()
  103. if len(self.queue) > 0:
  104. self.mainwindow.updateSystemTray()
  105. def waitingHandles(self):
  106. return self.queue
  107. def answerMessage(self):
  108. func = self.funcs[self.queue[0]]
  109. func()
  110. def messageAnswered(self, handle):
  111. if handle not in self.queue:
  112. return
  113. self.queue = [q for q in self.queue if q != handle]
  114. del self.funcs[handle]
  115. if len(self.queue) == 0:
  116. self.mainwindow.updateSystemTray()
  117. def addMessage(self, handle, func):
  118. if not self.funcs.has_key(handle):
  119. self.queue.append(handle)
  120. self.funcs[handle] = func
  121. if len(self.queue) > 0:
  122. self.mainwindow.updateSystemTray()
  123. def __len__(self):
  124. return len(self.queue)
  125. class chumListing(QtGui.QTreeWidgetItem):
  126. def __init__(self, chum, window):
  127. QtGui.QTreeWidgetItem.__init__(self, [chum.handle])
  128. self.mainwindow = window
  129. self.chum = chum
  130. self.handle = chum.handle
  131. self.setMood(Mood("offline"))
  132. self.status = None
  133. self.setToolTip(0, "%s: %s" % (chum.handle, window.chumdb.getNotes(chum.handle)))
  134. def setMood(self, mood):
  135. if hasattr(self.mainwindow, "chumList") and self.mainwindow.chumList.notify:
  136. #print "%s -> %s" % (self.chum.mood.name(), mood.name())
  137. if self.mainwindow.config.notifyOptions() & self.mainwindow.config.SIGNOUT and \
  138. mood.name() == "offline" and self.chum.mood.name() != "offline":
  139. #print "OFFLINE NOTIFY: " + self.handle
  140. uri = self.mainwindow.theme["toasts/icon/signout"]
  141. n = self.mainwindow.tm.Toast(self.mainwindow.tm.appName,
  142. "%s is Offline" % (self.handle), uri)
  143. n.show()
  144. elif self.mainwindow.config.notifyOptions() & self.mainwindow.config.SIGNIN and \
  145. mood.name() != "offline" and self.chum.mood.name() == "offline":
  146. #print "ONLINE NOTIFY: " + self.handle
  147. uri = self.mainwindow.theme["toasts/icon/signin"]
  148. n = self.mainwindow.tm.Toast(self.mainwindow.tm.appName,
  149. "%s is Online" % (self.handle), uri)
  150. n.show()
  151. login = False
  152. logout = False
  153. if mood.name() == "offline" and self.chum.mood.name() != "offline":
  154. logout = True
  155. elif mood.name() != "offline" and self.chum.mood.name() == "offline":
  156. login = True
  157. self.chum.mood = mood
  158. self.updateMood(login=login, logout=logout)
  159. def setColor(self, color):
  160. self.chum.color = color
  161. def updateMood(self, unblock=False, login=False, logout=False):
  162. mood = self.chum.mood
  163. self.mood = mood
  164. icon = self.mood.icon(self.mainwindow.theme)
  165. if login:
  166. self.login()
  167. elif logout:
  168. self.logout()
  169. else:
  170. self.setIcon(0, icon)
  171. try:
  172. self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
  173. except KeyError:
  174. self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"]))
  175. def changeTheme(self, theme):
  176. icon = self.mood.icon(theme)
  177. self.setIcon(0, icon)
  178. try:
  179. self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods"][self.mood.name()]["color"]))
  180. except KeyError:
  181. self.setTextColor(0, QtGui.QColor(self.mainwindow.theme["main/chums/moods/chummy/color"]))
  182. def login(self):
  183. self.setIcon(0, PesterIcon("themes/arrow_right.png"))
  184. self.status = "in"
  185. QtCore.QTimer.singleShot(5000, self.doneLogin)
  186. def doneLogin(self):
  187. icon = self.mood.icon(self.mainwindow.theme)
  188. self.setIcon(0, icon)
  189. def logout(self):
  190. self.setIcon(0, PesterIcon("themes/arrow_left.png"))
  191. self.status = "out"
  192. QtCore.QTimer.singleShot(5000, self.doneLogout)
  193. def doneLogout(self):
  194. hideoff = self.mainwindow.config.hideOfflineChums()
  195. icon = self.mood.icon(self.mainwindow.theme)
  196. self.setIcon(0, icon)
  197. if hideoff and self.status and self.status == "out":
  198. self.mainwindow.chumList.takeItem(self)
  199. def __lt__(self, cl):
  200. h1 = self.handle.lower()
  201. h2 = cl.handle.lower()
  202. return (h1 < h2)
  203. class chumArea(RightClickTree):
  204. def __init__(self, chums, parent=None):
  205. QtGui.QTreeWidget.__init__(self, parent)
  206. self.notify = False
  207. QtCore.QTimer.singleShot(30000, self, QtCore.SLOT('beginNotify()'))
  208. self.mainwindow = parent
  209. theme = self.mainwindow.theme
  210. self.chums = chums
  211. gTemp = self.mainwindow.config.getGroups()
  212. self.groups = [g[0] for g in gTemp]
  213. self.openGroups = [g[1] for g in gTemp]
  214. self.showAllGroups(True)
  215. if not self.mainwindow.config.hideOfflineChums():
  216. self.showAllChums()
  217. if not self.mainwindow.config.showEmptyGroups():
  218. self.hideEmptyGroups()
  219. self.groupMenu = QtGui.QMenu(self)
  220. self.canonMenu = QtGui.QMenu(self)
  221. self.optionsMenu = QtGui.QMenu(self)
  222. self.pester = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self)
  223. self.connect(self.pester, QtCore.SIGNAL('triggered()'),
  224. self, QtCore.SLOT('activateChum()'))
  225. self.removechum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/removechum"], self)
  226. self.connect(self.removechum, QtCore.SIGNAL('triggered()'),
  227. self, QtCore.SLOT('removeChum()'))
  228. self.blockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self)
  229. self.connect(self.blockchum, QtCore.SIGNAL('triggered()'),
  230. self, QtCore.SLOT('blockChum()'))
  231. self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self)
  232. self.connect(self.logchum, QtCore.SIGNAL('triggered()'),
  233. self, QtCore.SLOT('openChumLogs()'))
  234. self.reportchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self)
  235. self.connect(self.reportchum, QtCore.SIGNAL('triggered()'),
  236. self, QtCore.SLOT('reportChum()'))
  237. self.findalts = QtGui.QAction("Find Alts", self)
  238. self.connect(self.findalts, QtCore.SIGNAL('triggered()'),
  239. self, QtCore.SLOT('findAlts()'))
  240. self.removegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/removegroup"], self)
  241. self.connect(self.removegroup, QtCore.SIGNAL('triggered()'),
  242. self, QtCore.SLOT('removeGroup()'))
  243. self.renamegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/renamegroup"], self)
  244. self.connect(self.renamegroup, QtCore.SIGNAL('triggered()'),
  245. self, QtCore.SLOT('renameGroup()'))
  246. self.notes = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/notes"], self)
  247. self.connect(self.notes, QtCore.SIGNAL('triggered()'),
  248. self, QtCore.SLOT('editNotes()'))
  249. self.optionsMenu.addAction(self.pester)
  250. self.optionsMenu.addAction(self.logchum)
  251. self.optionsMenu.addAction(self.notes)
  252. self.optionsMenu.addAction(self.blockchum)
  253. self.optionsMenu.addAction(self.removechum)
  254. self.moveMenu = QtGui.QMenu(self.mainwindow.theme["main/menus/rclickchumlist/movechum"], self)
  255. self.optionsMenu.addMenu(self.moveMenu)
  256. self.optionsMenu.addAction(self.reportchum)
  257. self.moveGroupMenu()
  258. self.groupMenu.addAction(self.renamegroup)
  259. self.groupMenu.addAction(self.removegroup)
  260. self.canonMenu.addAction(self.pester)
  261. self.canonMenu.addAction(self.logchum)
  262. self.canonMenu.addAction(self.blockchum)
  263. self.canonMenu.addAction(self.removechum)
  264. self.canonMenu.addMenu(self.moveMenu)
  265. self.canonMenu.addAction(self.reportchum)
  266. self.canonMenu.addAction(self.findalts)
  267. self.initTheme(theme)
  268. #self.sortItems()
  269. #self.sortItems(1, QtCore.Qt.AscendingOrder)
  270. self.setSortingEnabled(False)
  271. self.header().hide()
  272. self.setDropIndicatorShown(True)
  273. self.setIndentation(4)
  274. self.setDragEnabled(True)
  275. self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
  276. self.setAnimated(True)
  277. self.setRootIsDecorated(False)
  278. self.connect(self, QtCore.SIGNAL('itemDoubleClicked(QTreeWidgetItem *, int)'),
  279. self, QtCore.SLOT('expandGroup()'))
  280. @QtCore.pyqtSlot()
  281. def beginNotify(self):
  282. print "BEGIN NOTIFY"
  283. self.notify = True
  284. def getOptionsMenu(self):
  285. if not self.currentItem():
  286. return None
  287. text = unicode(self.currentItem().text(0))
  288. if text.rfind(" (") != -1:
  289. text = text[0:text.rfind(" (")]
  290. if text == "Chums":
  291. return None
  292. elif text in self.groups:
  293. return self.groupMenu
  294. else:
  295. currenthandle = self.currentItem().chum.handle
  296. if currenthandle in canon_handles:
  297. return self.canonMenu
  298. else:
  299. return self.optionsMenu
  300. def startDrag(self, dropAction):
  301. # create mime data object
  302. mime = QtCore.QMimeData()
  303. mime.setData('application/x-item', '???')
  304. # start drag
  305. drag = QtGui.QDrag(self)
  306. drag.setMimeData(mime)
  307. drag.start(QtCore.Qt.MoveAction)
  308. def dragMoveEvent(self, event):
  309. if event.mimeData().hasFormat("application/x-item"):
  310. event.setDropAction(QtCore.Qt.MoveAction)
  311. event.accept()
  312. else:
  313. event.ignore()
  314. def dragEnterEvent(self, event):
  315. if (event.mimeData().hasFormat('application/x-item')):
  316. event.accept()
  317. else:
  318. event.ignore()
  319. def dropEvent(self, event):
  320. if (event.mimeData().hasFormat('application/x-item')):
  321. event.acceptProposedAction()
  322. else:
  323. event.ignore()
  324. return
  325. thisitem = str(event.source().currentItem().text(0))
  326. if thisitem.rfind(" (") != -1:
  327. thisitem = thisitem[0:thisitem.rfind(" (")]
  328. # Drop item is a group
  329. thisitem = unicode(event.source().currentItem().text(0))
  330. if thisitem.rfind(" (") != -1:
  331. thisitem = thisitem[0:thisitem.rfind(" (")]
  332. if thisitem == "Chums" or thisitem in self.groups:
  333. droppos = self.itemAt(event.pos())
  334. if not droppos: return
  335. droppos = unicode(droppos.text(0))
  336. if droppos.rfind(" ") != -1:
  337. droppos = droppos[0:droppos.rfind(" ")]
  338. if droppos == "Chums" or droppos in self.groups:
  339. saveOpen = event.source().currentItem().isExpanded()
  340. saveDrop = self.itemAt(event.pos())
  341. saveItem = self.takeTopLevelItem(self.indexOfTopLevelItem(event.source().currentItem()))
  342. self.insertTopLevelItems(self.indexOfTopLevelItem(saveDrop)+1, [saveItem])
  343. if saveOpen:
  344. saveItem.setExpanded(True)
  345. gTemp = []
  346. for i in range(self.topLevelItemCount()):
  347. text = unicode(self.topLevelItem(i).text(0))
  348. if text.rfind(" (") != -1:
  349. text = text[0:text.rfind(" (")]
  350. gTemp.append([unicode(text), self.topLevelItem(i).isExpanded()])
  351. self.mainwindow.config.saveGroups(gTemp)
  352. # Drop item is a chum
  353. else:
  354. item = self.itemAt(event.pos())
  355. if item:
  356. text = unicode(item.text(0))
  357. # Figure out which group to drop into
  358. if text.rfind(" (") != -1:
  359. text = text[0:text.rfind(" (")]
  360. if text == "Chums" or text in self.groups:
  361. group = text
  362. gitem = item
  363. else:
  364. ptext = unicode(item.parent().text(0))
  365. if ptext.rfind(" ") != -1:
  366. ptext = ptext[0:ptext.rfind(" ")]
  367. group = ptext
  368. gitem = item.parent()
  369. chumLabel = event.source().currentItem()
  370. chumLabel.chum.group = group
  371. self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, group)
  372. self.takeItem(chumLabel)
  373. # Using manual chum reordering
  374. if self.mainwindow.config.sortMethod() == 2:
  375. insertIndex = gitem.indexOfChild(item)
  376. if insertIndex == -1:
  377. insertIndex = 0
  378. gitem.insertChild(insertIndex, chumLabel)
  379. chums = self.mainwindow.config.chums()
  380. if item == gitem:
  381. item = gitem.child(0)
  382. inPos = chums.index(str(item.text(0)))
  383. if chums.index(thisitem) < inPos:
  384. inPos -= 1
  385. chums.remove(thisitem)
  386. chums.insert(inPos, unicode(thisitem))
  387. self.mainwindow.config.setChums(chums)
  388. else:
  389. self.addItem(chumLabel)
  390. if self.mainwindow.config.showOnlineNumbers():
  391. self.showOnlineNumbers()
  392. def moveGroupMenu(self):
  393. currentGroup = self.currentItem()
  394. if currentGroup:
  395. if currentGroup.parent():
  396. text = unicode(currentGroup.parent().text(0))
  397. else:
  398. text = unicode(currentGroup.text(0))
  399. if text.rfind(" (") != -1:
  400. text = text[0:text.rfind(" (")]
  401. currentGroup = text
  402. self.moveMenu.clear()
  403. actGroup = QtGui.QActionGroup(self)
  404. groups = self.groups[:]
  405. for gtext in groups:
  406. if gtext == currentGroup:
  407. continue
  408. movegroup = self.moveMenu.addAction(gtext)
  409. actGroup.addAction(movegroup)
  410. self.connect(actGroup, QtCore.SIGNAL('triggered(QAction *)'),
  411. self, QtCore.SLOT('moveToGroup(QAction *)'))
  412. def addChum(self, chum):
  413. if len([c for c in self.chums if c.handle == chum.handle]) != 0:
  414. return
  415. self.chums.append(chum)
  416. if not (self.mainwindow.config.hideOfflineChums() and
  417. chum.mood.name() == "offline"):
  418. chumLabel = chumListing(chum, self.mainwindow)
  419. self.addItem(chumLabel)
  420. #self.topLevelItem(0).addChild(chumLabel)
  421. #self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
  422. def getChums(self, handle):
  423. chums = self.findItems(handle, QtCore.Qt.MatchExactly | QtCore.Qt.MatchRecursive)
  424. return chums
  425. def showAllChums(self):
  426. for c in self.chums:
  427. chandle = c.handle
  428. if not len(self.findItems(chandle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive)):
  429. chumLabel = chumListing(c, self.mainwindow)
  430. self.addItem(chumLabel)
  431. self.sort()
  432. def hideOfflineChums(self):
  433. for j in range(self.topLevelItemCount()):
  434. i = 0
  435. listing = self.topLevelItem(j).child(i)
  436. while listing is not None:
  437. if listing.chum.mood.name() == "offline":
  438. self.topLevelItem(j).takeChild(i)
  439. else:
  440. i += 1
  441. listing = self.topLevelItem(j).child(i)
  442. self.sort()
  443. def showAllGroups(self, first=False):
  444. if first:
  445. for i,g in enumerate(self.groups):
  446. child_1 = QtGui.QTreeWidgetItem(["%s" % (g)])
  447. self.addTopLevelItem(child_1)
  448. if self.openGroups[i]:
  449. child_1.setExpanded(True)
  450. return
  451. curgroups = []
  452. for i in range(self.topLevelItemCount()):
  453. text = unicode(self.topLevelItem(i).text(0))
  454. if text.rfind(" (") != -1:
  455. text = text[0:text.rfind(" (")]
  456. curgroups.append(text)
  457. for i,g in enumerate(self.groups):
  458. if g not in curgroups:
  459. child_1 = QtGui.QTreeWidgetItem(["%s" % (g)])
  460. j = 0
  461. for h in self.groups:
  462. if h == g:
  463. self.insertTopLevelItem(j, child_1)
  464. break
  465. if h in curgroups:
  466. j += 1
  467. if self.openGroups[i]:
  468. child_1.setExpanded(True)
  469. if self.mainwindow.config.showOnlineNumbers():
  470. self.showOnlineNumbers()
  471. def showOnlineNumbers(self):
  472. if hasattr(self, 'groups'):
  473. self.hideOnlineNumbers()
  474. totals = {'Chums': 0}
  475. online = {'Chums': 0}
  476. for g in self.groups:
  477. totals[unicode(g)] = 0
  478. online[unicode(g)] = 0
  479. for c in self.chums:
  480. yes = c.mood.name() != "offline"
  481. if c.group == "Chums":
  482. totals[unicode(c.group)] = totals[unicode(c.group)]+1
  483. if yes:
  484. online[unicode(c.group)] = online[unicode(c.group)]+1
  485. elif c.group in totals:
  486. totals[unicode(c.group)] = totals[unicode(c.group)]+1
  487. if yes:
  488. online[unicode(c.group)] = online[unicode(c.group)]+1
  489. else:
  490. totals["Chums"] = totals["Chums"]+1
  491. if yes:
  492. online["Chums"] = online["Chums"]+1
  493. for i in range(self.topLevelItemCount()):
  494. text = unicode(self.topLevelItem(i).text(0))
  495. if text.rfind(" (") != -1:
  496. text = text[0:text.rfind(" (")]
  497. if text in online:
  498. self.topLevelItem(i).setText(0, "%s (%i/%i)" % (text, online[text], totals[text]))
  499. def hideOnlineNumbers(self):
  500. for i in range(self.topLevelItemCount()):
  501. text = unicode(self.topLevelItem(i).text(0))
  502. if text.rfind(" (") != -1:
  503. text = text[0:text.rfind(" (")]
  504. self.topLevelItem(i).setText(0, "%s" % (text))
  505. def hideEmptyGroups(self):
  506. i = 0
  507. listing = self.topLevelItem(i)
  508. while listing is not None:
  509. if listing.childCount() == 0:
  510. self.takeTopLevelItem(i)
  511. else:
  512. i += 1
  513. listing = self.topLevelItem(i)
  514. @QtCore.pyqtSlot()
  515. def expandGroup(self):
  516. item = self.currentItem()
  517. text = unicode(item.text(0))
  518. if text.rfind(" (") != -1:
  519. text = text[0:text.rfind(" (")]
  520. if text in self.groups:
  521. expand = item.isExpanded()
  522. self.mainwindow.config.expandGroup(text, not expand)
  523. def addItem(self, chumLabel):
  524. if hasattr(self, 'groups'):
  525. if chumLabel.chum.group not in self.groups:
  526. chumLabel.chum.group = "Chums"
  527. if "Chums" not in self.groups:
  528. self.mainwindow.config.addGroup("Chums")
  529. curgroups = []
  530. for i in range(self.topLevelItemCount()):
  531. text = unicode(self.topLevelItem(i).text(0))
  532. if text.rfind(" (") != -1:
  533. text = text[0:text.rfind(" (")]
  534. curgroups.append(text)
  535. if not self.findItems(chumLabel.handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive):
  536. if chumLabel.chum.group not in curgroups:
  537. child_1 = QtGui.QTreeWidgetItem(["%s" % (chumLabel.chum.group)])
  538. i = 0
  539. for g in self.groups:
  540. if g == chumLabel.chum.group:
  541. self.insertTopLevelItem(i, child_1)
  542. break
  543. if g in curgroups:
  544. i += 1
  545. if self.openGroups[self.groups.index("%s" % (chumLabel.chum.group))]:
  546. child_1.setExpanded(True)
  547. for i in range(self.topLevelItemCount()):
  548. text = unicode(self.topLevelItem(i).text(0))
  549. if text.rfind(" (") != -1:
  550. text = text[0:text.rfind(" (")]
  551. if text == chumLabel.chum.group:
  552. break
  553. # Manual sorting
  554. if self.mainwindow.config.sortMethod() == 2:
  555. chums = self.mainwindow.config.chums()
  556. if chumLabel.chum.handle in chums:
  557. fi = chums.index(chumLabel.chum.handle)
  558. else:
  559. fi = 0
  560. c = 1
  561. # TODO: Rearrange chums list on drag-n-drop
  562. bestj = 0
  563. bestname = ""
  564. if fi > 0:
  565. while not bestj:
  566. for j in xrange(self.topLevelItem(i).childCount()):
  567. if chums[fi-c] == str(self.topLevelItem(i).child(j).text(0)):
  568. bestj = j
  569. bestname = chums[fi-c]
  570. break
  571. c += 1
  572. if fi-c < 0:
  573. break
  574. if bestname:
  575. self.topLevelItem(i).insertChild(bestj+1, chumLabel)
  576. else:
  577. self.topLevelItem(i).insertChild(bestj, chumLabel)
  578. #sys.exit(0)
  579. self.topLevelItem(i).addChild(chumLabel)
  580. else: # All other sorting
  581. self.topLevelItem(i).addChild(chumLabel)
  582. self.sort()
  583. if self.mainwindow.config.showOnlineNumbers():
  584. self.showOnlineNumbers()
  585. else: # usually means this is now the trollslum
  586. if not self.findItems(chumLabel.handle, QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive):
  587. self.topLevelItem(0).addChild(chumLabel)
  588. self.topLevelItem(0).sortChildren(0, QtCore.Qt.AscendingOrder)
  589. def takeItem(self, chumLabel):
  590. r = None
  591. if not hasattr(chumLabel, 'chum'):
  592. return r
  593. for i in range(self.topLevelItemCount()):
  594. for j in range(self.topLevelItem(i).childCount()):
  595. if self.topLevelItem(i).child(j).text(0) == chumLabel.chum.handle:
  596. r = self.topLevelItem(i).takeChild(j)
  597. break
  598. if not self.mainwindow.config.showEmptyGroups():
  599. self.hideEmptyGroups()
  600. if self.mainwindow.config.showOnlineNumbers():
  601. self.showOnlineNumbers()
  602. return r
  603. def updateMood(self, handle, mood):
  604. hideoff = self.mainwindow.config.hideOfflineChums()
  605. chums = self.getChums(handle)
  606. oldmood = None
  607. if hideoff:
  608. if mood.name() != "offline" and \
  609. len(chums) == 0 and \
  610. handle in [p.handle for p in self.chums]:
  611. newLabel = chumListing([p for p in self.chums if p.handle == handle][0], self.mainwindow)
  612. self.addItem(newLabel)
  613. #self.sortItems()
  614. chums = [newLabel]
  615. elif mood.name() == "offline" and \
  616. len(chums) > 0:
  617. for c in chums:
  618. if (hasattr(c, 'mood')):
  619. c.setMood(mood)
  620. #self.takeItem(c)
  621. chums = []
  622. for c in chums:
  623. if (hasattr(c, 'mood')):
  624. oldmood = c.mood
  625. c.setMood(mood)
  626. if self.mainwindow.config.sortMethod() == 1:
  627. for i in range(self.topLevelItemCount()):
  628. saveCurrent = self.currentItem()
  629. self.moodSort(i)
  630. self.setCurrentItem(saveCurrent)
  631. if self.mainwindow.config.showOnlineNumbers():
  632. self.showOnlineNumbers()
  633. return oldmood
  634. def updateColor(self, handle, color):
  635. chums = self.findItems(handle, QtCore.Qt.MatchFlags(0))
  636. for c in chums:
  637. c.setColor(color)
  638. def initTheme(self, theme):
  639. self.resize(*theme["main/chums/size"])
  640. self.move(*theme["main/chums/loc"])
  641. if theme.has_key("main/chums/scrollbar"):
  642. self.setStyleSheet("QListWidget { %s } QScrollBar { %s } QScrollBar::handle { %s } QScrollBar::add-line { %s } QScrollBar::sub-line { %s } QScrollBar:up-arrow { %s } QScrollBar:down-arrow { %s }" % (theme["main/chums/style"], theme["main/chums/scrollbar/style"], theme["main/chums/scrollbar/handle"], theme["main/chums/scrollbar/downarrow"], theme["main/chums/scrollbar/uparrow"], theme["main/chums/scrollbar/uarrowstyle"], theme["main/chums/scrollbar/darrowstyle"] ))
  643. else:
  644. self.setStyleSheet(theme["main/chums/style"])
  645. self.pester.setText(theme["main/menus/rclickchumlist/pester"])
  646. self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
  647. self.blockchum.setText(theme["main/menus/rclickchumlist/blockchum"])
  648. self.logchum.setText(theme["main/menus/rclickchumlist/viewlog"])
  649. self.reportchum.setText(theme["main/menus/rclickchumlist/report"])
  650. self.notes.setText(theme["main/menus/rclickchumlist/notes"])
  651. self.removegroup.setText(theme["main/menus/rclickchumlist/removegroup"])
  652. self.renamegroup.setText(theme["main/menus/rclickchumlist/renamegroup"])
  653. self.moveMenu.setTitle(theme["main/menus/rclickchumlist/movechum"])
  654. def changeTheme(self, theme):
  655. self.initTheme(theme)
  656. chumlistings = []
  657. for i in range(self.topLevelItemCount()):
  658. for j in range(self.topLevelItem(i).childCount()):
  659. chumlistings.append(self.topLevelItem(i).child(j))
  660. #chumlistings = [self.item(i) for i in range(0, self.count())]
  661. for c in chumlistings:
  662. c.changeTheme(theme)
  663. def count(self):
  664. c = 0
  665. for i in range(self.topLevelItemCount()):
  666. c = c + self.topLevelItem(i).childCount()
  667. return c
  668. def sort(self):
  669. if self.mainwindow.config.sortMethod() == 2:
  670. pass # Do nothing!!!!! :OOOOOOO It's manual, bitches
  671. elif self.mainwindow.config.sortMethod() == 1:
  672. for i in range(self.topLevelItemCount()):
  673. self.moodSort(i)
  674. else:
  675. for i in range(self.topLevelItemCount()):
  676. self.topLevelItem(i).sortChildren(0, QtCore.Qt.AscendingOrder)
  677. def moodSort(self, group):
  678. scrollPos = self.verticalScrollBar().sliderPosition()
  679. chums = []
  680. listing = self.topLevelItem(group).child(0)
  681. while listing is not None:
  682. chums.append(self.topLevelItem(group).takeChild(0))
  683. listing = self.topLevelItem(group).child(0)
  684. chums.sort(key=lambda x: ((999 if x.chum.mood.value() == 2 else x.chum.mood.value()), x.chum.handle), reverse=False)
  685. for c in chums:
  686. self.topLevelItem(group).addChild(c)
  687. self.verticalScrollBar().setSliderPosition(scrollPos)
  688. @QtCore.pyqtSlot()
  689. def activateChum(self):
  690. self.itemActivated.emit(self.currentItem(), 0)
  691. @QtCore.pyqtSlot()
  692. def removeChum(self, handle = None):
  693. if handle:
  694. clistings = self.getChums(handle)
  695. if len(clistings) <= 0: return
  696. for c in clistings:
  697. self.setCurrentItem(c)
  698. if not self.currentItem():
  699. return
  700. currentChum = self.currentItem().chum
  701. self.chums = [c for c in self.chums if c.handle != currentChum.handle]
  702. self.removeChumSignal.emit(self.currentItem().chum.handle)
  703. oldlist = self.takeItem(self.currentItem())
  704. del oldlist
  705. @QtCore.pyqtSlot()
  706. def blockChum(self):
  707. currentChum = self.currentItem()
  708. if not currentChum:
  709. return
  710. self.blockChumSignal.emit(self.currentItem().chum.handle)
  711. @QtCore.pyqtSlot()
  712. def reportChum(self):
  713. currentChum = self.currentItem()
  714. if not currentChum:
  715. return
  716. self.mainwindow.reportChum(self.currentItem().chum.handle)
  717. @QtCore.pyqtSlot()
  718. def findAlts(self):
  719. currentChum = self.currentItem()
  720. if not currentChum:
  721. return
  722. self.mainwindow.sendMessage.emit("ALT %s" % (currentChum.chum.handle) , "calSprite")
  723. @QtCore.pyqtSlot()
  724. def openChumLogs(self):
  725. currentChum = self.currentItem()
  726. if not currentChum:
  727. return
  728. currentChum = currentChum.text(0)
  729. self.pesterlogviewer = PesterLogViewer(currentChum, self.mainwindow.config, self.mainwindow.theme, self.mainwindow)
  730. self.connect(self.pesterlogviewer, QtCore.SIGNAL('rejected()'),
  731. self, QtCore.SLOT('closeActiveLog()'))
  732. self.pesterlogviewer.show()
  733. self.pesterlogviewer.raise_()
  734. self.pesterlogviewer.activateWindow()
  735. @QtCore.pyqtSlot()
  736. def closeActiveLog(self):
  737. self.pesterlogviewer.close()
  738. self.pesterlogviewer = None
  739. @QtCore.pyqtSlot()
  740. def editNotes(self):
  741. currentChum = self.currentItem()
  742. if not currentChum:
  743. return
  744. (notes, ok) = QtGui.QInputDialog.getText(self, "Notes", "Enter your notes...")
  745. if ok:
  746. notes = unicode(notes)
  747. self.mainwindow.chumdb.setNotes(currentChum.handle, notes)
  748. currentChum.setToolTip(0, "%s: %s" % (currentChum.handle, notes))
  749. @QtCore.pyqtSlot()
  750. def renameGroup(self):
  751. if not hasattr(self, 'renamegroupdialog'):
  752. self.renamegroupdialog = None
  753. if not self.renamegroupdialog:
  754. (gname, ok) = QtGui.QInputDialog.getText(self, "Rename Group", "Enter a new name for the group:")
  755. if ok:
  756. gname = unicode(gname)
  757. if re.search("[^A-Za-z0-9_\s]", gname) is not None:
  758. msgbox = QtGui.QMessageBox()
  759. msgbox.setInformativeText("THIS IS NOT A VALID GROUP NAME")
  760. msgbox.setStandardButtons(QtGui.QMessageBox.Ok)
  761. ret = msgbox.exec_()
  762. self.addgroupdialog = None
  763. return
  764. currentGroup = self.currentItem()
  765. if not currentGroup:
  766. return
  767. index = self.indexOfTopLevelItem(currentGroup)
  768. if index != -1:
  769. expanded = currentGroup.isExpanded()
  770. text = unicode(currentGroup.text(0))
  771. if text.rfind(" (") != -1:
  772. text = text[0:text.rfind(" (")]
  773. self.mainwindow.config.delGroup(text)
  774. self.mainwindow.config.addGroup(gname, expanded)
  775. gTemp = self.mainwindow.config.getGroups()
  776. self.groups = [g[0] for g in gTemp]
  777. self.openGroups = [g[1] for g in gTemp]
  778. for i in range(currentGroup.childCount()):
  779. currentGroup.child(i).chum.group = gname
  780. self.mainwindow.chumdb.setGroup(currentGroup.child(i).chum.handle, gname)
  781. currentGroup.setText(0, gname)
  782. if self.mainwindow.config.showOnlineNumbers():
  783. self.showOnlineNumbers()
  784. self.renamegroupdialog = None
  785. @QtCore.pyqtSlot()
  786. def removeGroup(self):
  787. currentGroup = self.currentItem()
  788. if not currentGroup:
  789. return
  790. text = unicode(currentGroup.text(0))
  791. if text.rfind(" (") != -1:
  792. text = text[0:text.rfind(" (")]
  793. self.mainwindow.config.delGroup(text)
  794. gTemp = self.mainwindow.config.getGroups()
  795. self.groups = [g[0] for g in gTemp]
  796. self.openGroups = [g[1] for g in gTemp]
  797. for c in self.chums:
  798. if c.group == text:
  799. c.group = "Chums"
  800. self.mainwindow.chumdb.setGroup(c.handle, "Chums")
  801. for i in range(self.topLevelItemCount()):
  802. if self.topLevelItem(i).text(0) == currentGroup.text(0):
  803. break
  804. while self.topLevelItem(i) and self.topLevelItem(i).child(0):
  805. chumLabel = self.topLevelItem(i).child(0)
  806. self.takeItem(chumLabel)
  807. self.addItem(chumLabel)
  808. self.takeTopLevelItem(i)
  809. @QtCore.pyqtSlot(QtGui.QAction)
  810. def moveToGroup(self, item):
  811. if not item:
  812. return
  813. group = unicode(item.text())
  814. chumLabel = self.currentItem()
  815. if not chumLabel:
  816. return
  817. chumLabel.chum.group = group
  818. self.mainwindow.chumdb.setGroup(chumLabel.chum.handle, group)
  819. self.takeItem(chumLabel)
  820. self.addItem(chumLabel)
  821. removeChumSignal = QtCore.pyqtSignal(QtCore.QString)
  822. blockChumSignal = QtCore.pyqtSignal(QtCore.QString)
  823. class trollSlum(chumArea):
  824. def __init__(self, trolls, mainwindow, parent=None):
  825. QtGui.QListWidget.__init__(self, parent)
  826. self.mainwindow = mainwindow
  827. theme = self.mainwindow.theme
  828. self.setStyleSheet(theme["main/trollslum/chumroll/style"])
  829. self.chums = trolls
  830. child_1 = QtGui.QTreeWidgetItem([""])
  831. self.addTopLevelItem(child_1)
  832. child_1.setExpanded(True)
  833. for c in self.chums:
  834. chandle = c.handle
  835. if not self.findItems(chandle, QtCore.Qt.MatchFlags(0)):
  836. chumLabel = chumListing(c, self.mainwindow)
  837. self.addItem(chumLabel)
  838. self.setSortingEnabled(False)
  839. self.header().hide()
  840. self.setDropIndicatorShown(False)
  841. self.setIndentation(0)
  842. self.optionsMenu = QtGui.QMenu(self)
  843. self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self)
  844. self.connect(self.unblockchum, QtCore.SIGNAL('triggered()'),
  845. self, QtCore.SIGNAL('unblockChumSignal()'))
  846. self.optionsMenu.addAction(self.unblockchum)
  847. #self.sortItems()
  848. def contextMenuEvent(self, event):
  849. #fuckin Qt
  850. if event.reason() == QtGui.QContextMenuEvent.Mouse:
  851. listing = self.itemAt(event.pos())
  852. self.setCurrentItem(listing)
  853. if self.currentItem().text(0) != "":
  854. self.optionsMenu.popup(event.globalPos())
  855. def changeTheme(self, theme):
  856. self.setStyleSheet(theme["main/trollslum/chumroll/style"])
  857. self.removechum.setText(theme["main/menus/rclickchumlist/removechum"])
  858. self.unblockchum.setText(theme["main/menus/rclickchumlist/blockchum"])
  859. chumlistings = [self.item(i) for i in range(0, self.count())]
  860. for c in chumlistings:
  861. c.changeTheme(theme)
  862. unblockChumSignal = QtCore.pyqtSignal(QtCore.QString)
  863. class TrollSlumWindow(QtGui.QFrame):
  864. def __init__(self, trolls, mainwindow, parent=None):
  865. QtGui.QFrame.__init__(self, parent)
  866. self.mainwindow = mainwindow
  867. theme = self.mainwindow.theme
  868. self.slumlabel = QtGui.QLabel(self)
  869. self.initTheme(theme)
  870. self.trollslum = trollSlum(trolls, self.mainwindow, self)
  871. self.connect(self.trollslum, QtCore.SIGNAL('unblockChumSignal()'),
  872. self, QtCore.SLOT('removeCurrentTroll()'))
  873. layout_1 = QtGui.QHBoxLayout()
  874. self.addButton = QtGui.QPushButton("ADD", self)
  875. self.connect(self.addButton, QtCore.SIGNAL('clicked()'),
  876. self, QtCore.SLOT('addTrollWindow()'))
  877. self.removeButton = QtGui.QPushButton("REMOVE", self)
  878. self.connect(self.removeButton, QtCore.SIGNAL('clicked()'),
  879. self, QtCore.SLOT('removeCurrentTroll()'))
  880. layout_1.addWidget(self.addButton)
  881. layout_1.addWidget(self.removeButton)
  882. layout_0 = QtGui.QVBoxLayout()
  883. layout_0.addWidget(self.slumlabel)
  884. layout_0.addWidget(self.trollslum)
  885. layout_0.addLayout(layout_1)
  886. self.setLayout(layout_0)
  887. def initTheme(self, theme):
  888. self.resize(*theme["main/trollslum/size"])
  889. self.setStyleSheet(theme["main/trollslum/style"])
  890. self.slumlabel.setText(theme["main/trollslum/label/text"])
  891. self.slumlabel.setStyleSheet(theme["main/trollslum/label/style"])
  892. if not self.parent():
  893. self.setWindowTitle(theme["main/menus/profile/block"])
  894. self.setWindowIcon(self.mainwindow.windowIcon())
  895. def changeTheme(self, theme):
  896. self.initTheme(theme)
  897. self.trollslum.changeTheme(theme)
  898. # move unblocked trolls from slum to chumarea
  899. def closeEvent(self, event):
  900. self.mainwindow.closeTrollSlum()
  901. def updateMood(self, handle, mood):
  902. self.trollslum.updateMood(handle, mood)
  903. def addTroll(self, chum):
  904. self.trollslum.addChum(chum)
  905. def removeTroll(self, handle):
  906. self.trollslum.removeChum(handle)
  907. @QtCore.pyqtSlot()
  908. def removeCurrentTroll(self):
  909. currentListing = self.trollslum.currentItem()
  910. if not currentListing or not hasattr(currentListing, 'chum'):
  911. return
  912. self.unblockChumSignal.emit(currentListing.chum.handle)
  913. @QtCore.pyqtSlot()
  914. def addTrollWindow(self):
  915. if not hasattr(self, 'addtrolldialog'):
  916. self.addtrolldialog = None
  917. if self.addtrolldialog:
  918. return
  919. self.addtrolldialog = QtGui.QInputDialog(self)
  920. (handle, ok) = self.addtrolldialog.getText(self, "Add Troll", "Enter Troll Handle:")
  921. if ok:
  922. handle = unicode(handle)
  923. if not (PesterProfile.checkLength(handle) and
  924. PesterProfile.checkValid(handle)[0]):
  925. errormsg = QtGui.QErrorMessage(self)
  926. errormsg.showMessage("THIS IS NOT A VALID CHUMTAG!")
  927. self.addchumdialog = None
  928. return
  929. self.blockChumSignal.emit(handle)
  930. self.addtrolldialog = None
  931. blockChumSignal = QtCore.pyqtSignal(QtCore.QString)
  932. unblockChumSignal = QtCore.pyqtSignal(QtCore.QString)
  933. class PesterWindow(MovingWindow):
  934. def __init__(self, options, parent=None):
  935. MovingWindow.__init__(self, parent,
  936. (QtCore.Qt.CustomizeWindowHint |
  937. QtCore.Qt.FramelessWindowHint))
  938. self.convos = CaseInsensitiveDict()
  939. self.memos = CaseInsensitiveDict()
  940. self.tabconvo = None
  941. self.tabmemo = None
  942. if "advanced" in options:
  943. self.advanced = options["advanced"]
  944. else: self.advanced = False
  945. if "server" in options:
  946. self.serverOverride = options["server"]
  947. if "port" in options:
  948. self.portOverride = options["port"]
  949. if "honk" in options:
  950. self.honk = options["honk"]
  951. else: self.honk = True
  952. self.setAutoFillBackground(True)
  953. self.setObjectName("main")
  954. self.config = userConfig(self)
  955. if self.config.defaultprofile():
  956. self.userprofile = userProfile(self.config.defaultprofile())
  957. self.theme = self.userprofile.getTheme()
  958. else:
  959. self.userprofile = userProfile(PesterProfile("pesterClient%d" % (random.randint(100,999)), QtGui.QColor("black"), Mood(0)))
  960. self.theme = self.userprofile.getTheme()
  961. self.modes = ""
  962. self.randhandler = RandomHandler(self)
  963. try:
  964. themeChecker(self.theme)
  965. except ThemeException, (inst):
  966. print "Caught: "+inst.parameter
  967. themeWarning = QtGui.QMessageBox(self)
  968. themeWarning.setText("Theme Error: %s" % (inst))
  969. themeWarning.exec_()
  970. self.theme = pesterTheme("pesterchum")
  971. extraToasts = {'default': PesterToast}
  972. if pytwmn.confExists():
  973. extraToasts['twmn'] = pytwmn.Notification
  974. self.tm = PesterToastMachine(self, lambda: self.theme["main/windowtitle"], on=self.config.notify(),
  975. type=self.config.notifyType(), extras=extraToasts)
  976. self.tm.run()
  977. self.chatlog = PesterLog(self.profile().handle, self)
  978. self.move(100, 100)
  979. talk = QtGui.QAction(self.theme["main/menus/client/talk"], self)
  980. self.talk = talk
  981. self.connect(talk, QtCore.SIGNAL('triggered()'),
  982. self, QtCore.SLOT('openChat()'))
  983. logv = QtGui.QAction(self.theme["main/menus/client/logviewer"], self)
  984. self.logv = logv
  985. self.connect(logv, QtCore.SIGNAL('triggered()'),
  986. self, QtCore.SLOT('openLogv()'))
  987. grps = QtGui.QAction(self.theme["main/menus/client/addgroup"], self)
  988. self.grps = grps
  989. self.connect(grps, QtCore.SIGNAL('triggered()'),
  990. self, QtCore.SLOT('addGroupWindow()'))
  991. self.rand = QtGui.QAction(self.theme["main/menus/client/randen"], self)
  992. self.connect(self.rand, QtCore.SIGNAL('triggered()'),
  993. self.randhandler, QtCore.SLOT('getEncounter()'))
  994. opts = QtGui.QAction(self.theme["main/menus/client/options"], self)
  995. self.opts = opts
  996. self.connect(opts, QtCore.SIGNAL('triggered()'),
  997. self, QtCore.SLOT('openOpts()'))
  998. exitaction = QtGui.QAction(self.theme["main/menus/client/exit"], self)
  999. self.exitaction = exitaction
  1000. self.connect(exitaction, QtCore.SIGNAL('triggered()'),
  1001. self, QtCore.SLOT('close()'))
  1002. userlistaction = QtGui.QAction(self.theme["main/menus/client/userlist"], self)
  1003. self.userlistaction = userlistaction
  1004. self.connect(userlistaction, QtCore.SIGNAL('triggered()'),
  1005. self, QtCore.SLOT('showAllUsers()'))
  1006. memoaction = QtGui.QAction(self.theme["main/menus/client/memos"], self)
  1007. self.memoaction = memoaction
  1008. self.connect(memoaction, QtCore.SIGNAL('triggered()'),
  1009. self, QtCore.SLOT('showMemos()'))
  1010. self.importaction = QtGui.QAction(self.theme["main/menus/client/import"], self)
  1011. self.connect(self.importaction, QtCore.SIGNAL('triggered()'),
  1012. self, QtCore.SLOT('importExternalConfig()'))
  1013. self.idleaction = QtGui.QAction(self.theme["main/menus/client/idle"], self)
  1014. self.idleaction.setCheckable(True)
  1015. self.connect(self.idleaction, QtCore.SIGNAL('toggled(bool)'),
  1016. self, QtCore.SLOT('toggleIdle(bool)'))
  1017. self.reconnectAction = QtGui.QAction(self.theme["main/menus/client/reconnect"], self)
  1018. self.connect(self.reconnectAction, QtCore.SIGNAL('triggered()'),
  1019. self, QtCore.SIGNAL('reconnectIRC()'))
  1020. self.menu = QtGui.QMenuBar(self)
  1021. self.menu.setNativeMenuBar(False)
  1022. filemenu = self.menu.addMenu(self.theme["main/menus/client/_name"])
  1023. self.filemenu = filemenu
  1024. filemenu.addAction(opts)
  1025. filemenu.addAction(memoaction)
  1026. filemenu.addAction(logv)
  1027. filemenu.addAction(self.rand)
  1028. if not self.randhandler.running:
  1029. self.rand.setEnabled(False)
  1030. filemenu.addAction(userlistaction)
  1031. filemenu.addAction(talk)
  1032. filemenu.addAction(self.idleaction)
  1033. filemenu.addAction(grps)
  1034. filemenu.addAction(self.importaction)
  1035. filemenu.addAction(self.reconnectAction)
  1036. filemenu.addAction(exitaction)
  1037. changequirks = QtGui.QAction(self.theme["main/menus/profile/quirks"], self)
  1038. self.changequirks = changequirks
  1039. self.connect(changequirks, QtCore.SIGNAL('triggered()'),
  1040. self, QtCore.SLOT('openQuirks()'))
  1041. loadslum = QtGui.QAction(self.theme["main/menus/profile/block"], self)
  1042. self.loadslum = loadslum
  1043. self.connect(loadslum, QtCore.SIGNAL('triggered()'),
  1044. self, QtCore.SLOT('showTrollSlum()'))
  1045. changecoloraction = QtGui.QAction(self.theme["main/menus/profile/color"], self)
  1046. self.changecoloraction = changecoloraction
  1047. self.connect(changecoloraction, QtCore.SIGNAL('triggered()'),
  1048. self, QtCore.SLOT('changeMyColor()'))
  1049. switch = QtGui.QAction(self.theme["main/menus/profile/switch"], self)
  1050. self.switch = switch
  1051. self.connect(switch, QtCore.SIGNAL('triggered()'),
  1052. self, QtCore.SLOT('switchProfile()'))
  1053. profilemenu = self.menu.addMenu(self.theme["main/menus/profile/_name"])
  1054. self.profilemenu = profilemenu
  1055. profilemenu.addAction(changequirks)
  1056. profilemenu.addAction(loadslum)
  1057. profilemenu.addAction(changecoloraction)
  1058. profilemenu.addAction(switch)
  1059. self.helpAction = QtGui.QAction(self.theme["main/menus/help/help"], self)
  1060. self.connect(self.helpAction, QtCore.SIGNAL('triggered()'),
  1061. self, QtCore.SLOT('launchHelp()'))
  1062. self.botAction = QtGui.QAction(self.theme["main/menus/help/calsprite"], self)
  1063. self.connect(self.botAction, QtCore.SIGNAL('triggered()'),
  1064. self, QtCore.SLOT('loadCalsprite()'))
  1065. self.nickServAction = QtGui.QAction(self.theme["main/menus/help/nickserv"], self)
  1066. self.connect(self.nickServAction, QtCore.SIGNAL('triggered()'),

Large files files are truncated, but you can click here to view the full file