NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

petition.py (55246B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\neocom\petition.py
      2 import sys
      3 import blue
      4 import carbonui.const as uiconst
      5 import localization
      6 import uthread
      7 import utillib
      8 from carbon.common.script.sys.crowset import CRowset
      9 from carbon.common.script.sys.service import Service
     10 from carbon.common.script.sys.serviceConst import ROLE_GML, ROLE_PETITIONEE
     11 from carbon.common.script.util.format import FmtDate
     12 from carbonui.button.group import ButtonGroup
     13 from carbonui.control.radioButton import RadioButton
     14 from carbonui.control.scrollentries import SE_BaseClassCore
     15 from carbonui.control.tabGroup import TabGroup
     16 from carbonui.control.window import Window
     17 from carbonui.fontconst import EVE_SMALL_FONTSIZE
     18 from carbonui.primitives.container import Container
     19 from carbonui.primitives.fill import Fill
     20 from carbonui.primitives.frame import Frame
     21 from eve.client.script.ui.control import eveIcon, eveLabel, eveScroll
     22 from eve.client.script.ui.control.entries.generic import Generic
     23 from eve.client.script.ui.control.entries.util import GetFromClass
     24 from eve.client.script.ui.control.eveEditPlainText import EditPlainText
     25 from eve.client.script.ui.control.themeColored import SpriteThemeColored
     26 from eve.client.script.ui.shared.neocom.petitionWindow import PetitionWindow
     27 from eve.client.script.ui.util import uix
     28 from eve.client.script.ui.util.form import FormWnd
     29 from eve.common.lib import appConst as const
     30 from eveexceptions import UserError
     31 from evepetitions.data import get_petition_event_texts
     32 from eveservices.xmppchat import GetChatService
     33 from menu import MenuLabel
     34 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     35 
     36 class PetitionSvc(Service):
     37     __guid__ = 'svc.petition'
     38     __notifyevents__ = ['ProcessSessionChange',
     39      'OnNewPetition',
     40      'OnPetitionCreated',
     41      'OnClosePetition',
     42      'OnAssignPetition',
     43      'OnPetitionMessage']
     44     __servicename__ = 'petition'
     45     __displayname__ = 'Petition Client Service'
     46     __dependencies__ = []
     47     __update_on_reload__ = 0
     48 
     49     def Run(self, memStream = None):
     50         self.LogInfo('Starting Petitions')
     51         self.Reset()
     52 
     53     def Stop(self, memStream = None):
     54         wnd = self.GetWnd()
     55         if wnd is not None and not wnd.destroyed:
     56             wnd.Close()
     57         self.Reset()
     58 
     59     def ProcessSessionChange(self, isremote, session, change):
     60         if session.charid is None:
     61             wnd = self.GetWnd()
     62             if wnd is not None and not wnd.destroyed:
     63                 wnd.Close()
     64                 self.mine = None
     65 
     66     def OnNewPetition(self, petitionid):
     67         if session.charid is None:
     68             return
     69         uthread.pool('PetitionSvc::OnNewPetition', self._OnNewPetition, petitionid)
     70 
     71     def _OnNewPetition(self, petitionid):
     72         self.LogInfo('OnNewPetition')
     73         sm.GetService('neocom').Blink('help')
     74         self._ReloadVisible()
     75 
     76     def OnClosePetition(self, *args):
     77         if session.charid is None:
     78             return
     79         uthread.pool('PetitionSvc::OnClosePetition', self._OnClosePetition, *args)
     80 
     81     def _OnClosePetition(self, *args):
     82         self.LogInfo('OnClosePetition')
     83         sm.GetService('neocom').Blink('help')
     84         self._ReloadVisible()
     85 
     86     def OnAssignPetition(self, petitionID, assigneeid):
     87         if session.charid is None:
     88             return
     89         uthread.pool('PetitionSvc::OnAssignPetition', self._OnAssignPetition, petitionID, assigneeid)
     90 
     91     def _OnAssignPetition(self, petitionID, assigneeid):
     92         self.LogInfo('OnAssignPetition')
     93         self._ReloadVisible()
     94 
     95     def OnPetitionCreated(self, *args):
     96         if session.charid is None:
     97             return
     98         uthread.pool('PetitionSvc::OnPetitionCreated', self._OnPetitionCreated)
     99 
    100     def _OnPetitionCreated(self):
    101         self.LogInfo('OnPetitionCreated')
    102         self._ReloadVisible()
    103 
    104     def CheckNewMessages(self):
    105         newMessages = sm.RemoteSvc('petitioner').GetUnreadMessages()
    106         if len(newMessages) == 1 and not localization.util.AmOnChineseServer():
    107             self.NewMessage(newMessages[0].petitionID, newMessages[0].text, newMessages[0].messageID)
    108         elif len(newMessages) >= 1:
    109             if prompt_player_fsd_dialog('PetitionQuestion1', {'messages': len(newMessages)}, uiconst.YESNO) == uiconst.ID_YES:
    110                 self.Show()
    111 
    112     def MarkAsRead(self, messageID):
    113         if messageID in self.read:
    114             return
    115         self.read.append(messageID)
    116         sm.RemoteSvc('petitioner').MarkAsRead(messageID)
    117 
    118     def NewMessage(self, petitionID, message, messageID):
    119         self.MarkAsRead(messageID)
    120         prompt_player_fsd_dialog('PetPetitionResponse')
    121         sm.GetService('neocom').Blink('help')
    122 
    123     def Reset(self):
    124         self.wnd = None
    125         self.mine = None
    126         self.petitionee = None
    127         self.categories = None
    128         self.queues = None
    129         self.claimedpetitions = None
    130         self.loadingmessages = 0
    131         self.loadinglogs = 0
    132         self.read = []
    133 
    134     def Show(self):
    135         wnd = self.GetWnd(1)
    136         if wnd is not None and not wnd.destroyed:
    137             wnd.Maximize()
    138 
    139     def Load(self, args):
    140         if not session.charid:
    141             return
    142         if args in ('generic', 'rating'):
    143             viewwnd = self.GetViewWnd()
    144             if viewwnd is not None and viewwnd.sr.viewmessageform:
    145                 viewwnd.sr.viewmessageform.state = uiconst.UI_HIDDEN
    146                 if args == 'rating':
    147                     self.ShowRating()
    148         elif args == 'messages':
    149             self.LoadMessages()
    150         elif args == 'logs':
    151             self.LoadLogs()
    152         elif args == 'mypetitions':
    153             uthread.new(self.ShowMyPetitions)
    154         elif args == 'claimedpetitions':
    155             self.ShowClaimedPetitions()
    156         elif args in range(6):
    157             self.ShowPetitionQueue(args)
    158         self.SelectionChange([])
    159 
    160     def GetWnd(self, new = 0):
    161         wnd = Window.GetIfOpen(windowID='petitions')
    162         if not wnd and new:
    163             wnd = Window.Open(windowID='petitions')
    164             wnd.scope = uiconst.SCOPE_INGAME
    165             wnd.SetCaption(localization.GetByLabel('UI/Neocom/Petition/Petitions'))
    166             wnd.SetMinSize([400, 256])
    167             wnd.icon = 'res:/ui/Texture/WindowIcons/help.png'
    168             topParent = Container(name='topParent', parent=wnd.GetMainArea(), align=uiconst.TOTOP, height=60, clipChildren=True)
    169             SpriteThemeColored(name='mainicon', parent=topParent, state=uiconst.UI_DISABLED, pos=(0, -3, 64, 64), texturePath='res:/ui/Texture/WindowIcons/help.png', colorType=uiconst.COLORTYPE_UIHILIGHTGLOW)
    170             wnd.sr.scroll = eveScroll.Scroll(parent=wnd.sr.main, padding=(const.defaultPadding,
    171              const.defaultPadding,
    172              const.defaultPadding,
    173              const.defaultPadding))
    174             wnd.sr.scroll.sr.id = 'petitionScroll'
    175             wnd.sr.scroll.OnSelectionChange = self.SelectionChange
    176             wnd.sr.scroll.multiSelect = 0
    177             btns = [(localization.GetByLabel('UI/Generic/View'),
    178               self.ShowPetitionClicked,
    179               (),
    180               84),
    181              (localization.GetByLabel('UI/Generic/Claim'),
    182               self.ClaimPetitionClicked,
    183               (),
    184               84),
    185              (localization.GetByLabel('UI/Common/Delete'),
    186               self.DeletePetitionClicked,
    187               (),
    188               84),
    189              (localization.GetByLabel('UI/Generic/Cancel'),
    190               self.CancelPetitionClicked,
    191               (),
    192               84),
    193              (localization.GetByLabel('UI/Neocom/Petition/Rate'),
    194               self.RatePetitionClicked,
    195               (),
    196               84)]
    197             wnd.sr.buttons = ButtonGroup(btns=btns, parent=wnd.sr.main, idx=0)
    198             petitioner = sm.RemoteSvc('petitioner')
    199             if petitioner.IsSerenity() or not petitioner.IsZendeskSwapEnabled():
    200                 ButtonGroup(btns=[[localization.GetByLabel('UI/Neocom/Petition/CreateNew'),
    201                   self.NewPetition,
    202                   None,
    203                   None]], parent=topParent)
    204             wnd.MouseDown = self.OnWndMouseDown
    205             tabs = [[localization.GetByLabel('UI/Neocom/Petition/MyPetitions'),
    206               wnd.sr.scroll,
    207               self,
    208               'mypetitions']]
    209             if self.GetIsPetitionee():
    210                 tabs.append([localization.GetByLabel('UI/Neocom/Petition/ClaimedPetitions'),
    211                  wnd.sr.scroll,
    212                  self,
    213                  'claimedpetitions'])
    214                 for each in self.GetQueues():
    215                     tabs.append([each.queueName,
    216                      wnd.sr.scroll,
    217                      self,
    218                      each.queueID])
    219 
    220             maintabs = TabGroup(name='tabparent', parent=wnd.sr.main, idx=topParent.GetOrder() + 1)
    221             maintabs.Startup(tabs, 'petitionspanel')
    222             wnd.SetMinSize([500, 256])
    223             wnd.sr.tabs = maintabs
    224         return wnd
    225 
    226     def SetHint(self, hintstr = None):
    227         wnd = self.GetWnd()
    228         if wnd is not None:
    229             wnd.sr.scroll.ShowHint(hintstr)
    230 
    231     def OnWndMouseDown(self, *args):
    232         sm.GetService('neocom').BlinkOff('help')
    233 
    234     def RefreshSize(self, *args):
    235         pass
    236 
    237     def GetMyPetitions(self):
    238         if not self.mine:
    239             self.mine = sm.RemoteSvc('petitioner').GetMyPetitionsEx()
    240         return self.mine
    241 
    242     def ShowMyPetitions(self, *args):
    243         self.LogInfo('ShowMyPetitions')
    244         self.SetHint()
    245         groupid = 'mypetitions'
    246         tmplst = []
    247         mp = self.GetMyPetitions()
    248         owners = []
    249         for p in mp:
    250             if p.petitionerID not in owners:
    251                 owners.append(p.petitionerID)
    252 
    253         if len(owners):
    254             cfg.eveowners.Prime(owners)
    255         seenPetitions = {}
    256         scrolllist = []
    257         for p in mp:
    258             if p.petitionID not in seenPetitions:
    259                 data = self.GetPetitionData('my', p)
    260                 data.groupID = groupid
    261                 data.p = p
    262                 data.type = 'my'
    263                 scrolllist.append(GetFromClass(PetitionField, data))
    264                 seenPetitions[p.petitionID] = None
    265 
    266         wnd = self.GetWnd()
    267         if wnd:
    268             wnd.sr.scroll.Load(contentList=scrolllist, headers=[localization.GetByLabel('UI/Common/Date'),
    269              localization.GetByLabel('UI/Neocom/Petition/Subject'),
    270              localization.GetByLabel('UI/Neocom/Petition/Status'),
    271              localization.GetByLabel('UI/Neocom/Petition/Rating'),
    272              localization.GetByLabel('UI/Common/Category'),
    273              localization.GetByLabel('UI/Neocom/Petition/LastUpdate')])
    274             if not len(scrolllist):
    275                 self.SetHint(localization.GetByLabel('UI/Neocom/Petition/YouHaveNoPetitions'))
    276 
    277     def ShowClaimedPetitions(self, *args):
    278         self.LogInfo('ShowClaimedPetitions')
    279         self.SetHint()
    280         groupid = 'claimedpetitions'
    281         mp = sm.RemoteSvc('petitioner').GetClaimedPetitions()
    282         owners = []
    283         for p in mp:
    284             if p.petitionerID not in owners:
    285                 owners.append(p.petitionerID)
    286 
    287         if len(owners):
    288             cfg.eveowners.Prime(owners)
    289         scrolllist = []
    290         for p in mp:
    291             data = self.GetPetitionData('claimed', p)
    292             data.groupID = groupid
    293             data.p = p
    294             data.type = 'claimed'
    295             scrolllist.append(GetFromClass(PetitionField, data))
    296 
    297         wnd = self.GetWnd()
    298         if wnd:
    299             wnd.sr.scroll.Load(contentList=scrolllist, headers=[localization.GetByLabel('UI/Common/Date'),
    300              localization.GetByLabel('UI/Neocom/Petition/Subject'),
    301              localization.GetByLabel('UI/Common/Name'),
    302              localization.GetByLabel('UI/Neocom/Petition/Status'),
    303              localization.GetByLabel('UI/Common/Updated'),
    304              localization.GetByLabel('UI/Common/Category'),
    305              localization.GetByLabel('UI/Neocom/Petition/LastUpdate')])
    306             if not len(scrolllist):
    307                 self.SetHint(localization.GetByLabel('UI/Neocom/Petition/YouHaveNoClaimedPetitions'))
    308 
    309     def ShowRating(self, *args):
    310         wnd = self.GetViewWnd()
    311         if not wnd or wnd.destroyed:
    312             return
    313         p = wnd.sr.p
    314         main = wnd.sr.ratingparent
    315         main.Flush()
    316         captionPar = Container(name='captionPar', parent=main, align=uiconst.TOTOP, width=const.defaultPadding)
    317         mainCaption = eveLabel.EveCaptionMedium(text=localization.GetByLabel('UI/Neocom/Petition/RateHeader'), parent=captionPar, align=uiconst.RELATIVE, left=const.defaultPadding, top=8)
    318         captionPar.height = mainCaption.textheight + 16
    319         Container(name='push', parent=main, align=uiconst.TOLEFT, width=const.defaultPadding)
    320         Container(name='push', parent=main, align=uiconst.TORIGHT, width=const.defaultPadding)
    321         t1 = eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Neocom/Petition/RateScale'), parent=main, align=uiconst.TOTOP, state=uiconst.UI_NORMAL)
    322         currentRating = settings.user.ui.Get('petition_rating', None)
    323         currentResponseTimeRating = settings.user.ui.Get('petition_responseTimeRating', None)
    324         currentHelpfulnessRating = settings.user.ui.Get('petition_helpfulnessRating', None)
    325         currentAttitudeRating = settings.user.ui.Get('petition_attitudeRating', None)
    326         currentComment = settings.user.ui.Get('petition_ratingcomment', '')
    327         currentDateTime = getattr(p, 'ratingDateTime', None)
    328         cbParents = []
    329         if currentRating is not None:
    330             eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Neocom/Petition/RateYourRating'), parent=main, align=uiconst.TOTOP, state=uiconst.UI_NORMAL)
    331             cbParent = Container(name='cbParent', parent=main, align=uiconst.TOTOP, height=32)
    332             left = 0
    333             for i in xrange(11):
    334                 cb = RadioButton(text='', parent=cbParent, settingsKey='rating', retval=i * 10, checked=currentRating == i * 10, groupname='rating', align=uiconst.CENTERLEFT, pos=(left,
    335                  0,
    336                  20,
    337                  18))
    338                 cbtext = eveLabel.EveLabelMedium(text='%s' % i, parent=cbParent, align=uiconst.CENTERLEFT, state=uiconst.UI_NORMAL)
    339                 cbtext.left = cb.left + cb.width
    340                 left = cbtext.left + cbtext.width + 4
    341 
    342             cbParents.append(cbParent)
    343         else:
    344             eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Neocom/Petition/RateResponseTime'), parent=main, align=uiconst.TOTOP, state=uiconst.UI_NORMAL)
    345             cbParent = Container(name='cbResponseTimeParent', parent=main, align=uiconst.TOTOP, height=32)
    346             left = 0
    347             wnd.sr.responseTimeRatingCBs = []
    348             for i in xrange(11):
    349                 cb = RadioButton(text='', parent=cbParent, settingsKey='currentResponseTimeRating', retval=i * 10, checked=currentResponseTimeRating == i * 10, groupname='currentResponseTimeRating', align=uiconst.CENTERLEFT, pos=(left,
    350                  0,
    351                  20,
    352                  18), callback=self.OnCheckboxChange)
    353                 cbtext = eveLabel.EveLabelMedium(text='%s' % i, parent=cbParent, state=uiconst.UI_NORMAL, align=uiconst.CENTERLEFT)
    354                 cbtext.left = cb.left + cb.width
    355                 left = cbtext.left + cbtext.width + 4
    356                 wnd.sr.responseTimeRatingCBs.append(cb)
    357 
    358             cbParents.append(cbParent)
    359             eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Neocom/Petition/RateHelpfulness'), parent=main, align=uiconst.TOTOP, state=uiconst.UI_NORMAL)
    360             cbParent = Container(name='cbtHelpfulnessParent', parent=main, align=uiconst.TOTOP, height=32)
    361             left = 0
    362             wnd.sr.helpfulnessRatingCBs = []
    363             for i in xrange(11):
    364                 cb = RadioButton(text='', parent=cbParent, settingsKey='currentHelpfulnessRating', retval=i * 10, checked=currentHelpfulnessRating == i * 10, groupname='currentHelpfulnessRating', align=uiconst.CENTERLEFT, pos=(left,
    365                  0,
    366                  20,
    367                  18), callback=self.OnCheckboxChange)
    368                 cbtext = eveLabel.EveLabelMedium(text='%s' % i, parent=cbParent, state=uiconst.UI_NORMAL, align=uiconst.CENTERLEFT)
    369                 cbtext.left = cb.left + cb.width
    370                 left = cbtext.left + cbtext.width + 4
    371                 wnd.sr.helpfulnessRatingCBs.append(cb)
    372 
    373             cbParents.append(cbParent)
    374             eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Neocom/Petition/RateAttitude'), parent=main, align=uiconst.TOTOP, state=uiconst.UI_NORMAL)
    375             cbParent = Container(name='cbAttitudeParent', parent=main, align=uiconst.TOTOP, height=32)
    376             left = 0
    377             wnd.sr.attitudeRatingCBs = []
    378             for i in xrange(11):
    379                 cb = RadioButton(text='', parent=cbParent, settingsKey='currentAttitudeRating', retval=i * 10, checked=currentAttitudeRating == i * 10, groupname='currentAttitudeRating', align=uiconst.CENTERLEFT, pos=(left,
    380                  0,
    381                  20,
    382                  18), callback=self.OnCheckboxChange)
    383                 cbtext = eveLabel.EveLabelMedium(text='%s' % i, parent=cbParent, align=uiconst.CENTERLEFT, state=uiconst.UI_NORMAL)
    384                 cbtext.left = cb.left + cb.width
    385                 left = cbtext.left + cbtext.width + 4
    386                 wnd.sr.attitudeRatingCBs.append(cb)
    387 
    388             cbParents.append(cbParent)
    389         wnd.sr.ratinghinttext = eveLabel.EveLabelMedium(text='', parent=main, align=uiconst.TOTOP)
    390         t2 = eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Neocom/Petition/RateComment'), parent=main, align=uiconst.TOTOP, state=uiconst.UI_NORMAL)
    391         wnd.sr.ratingcomment = EditPlainText(setvalue=currentComment, parent=main, align=uiconst.TOALL, name='ratingcomment', maxLength=1000, padding=(-const.defaultPadding,
    392          4,
    393          -const.defaultPadding,
    394          0))
    395         w, h = wnd.minsize
    396         wnd.SetMinSize([max(w, left + 12), 428], 1)
    397         if currentDateTime is None:
    398             wnd.sr.ratingcomment.OnFocusLost = self.OnTextEditChange
    399             ButtonGroup(btns=[[localization.GetByLabel('UI/Generic/Submit'),
    400               self.SetRating,
    401               None,
    402               None]], parent=main, idx=0)
    403         else:
    404             for cbParent in cbParents:
    405                 cbParent.state = uiconst.UI_DISABLED
    406 
    407             wnd.sr.ratingcomment.readonly = 1
    408             eveLabel.EveLabelMedium(text=localization.GetByLabel('UI/Neocom/Petition/RateThanks'), parent=main, align=uiconst.TOBOTTOM, idx=0, state=uiconst.UI_NORMAL)
    409             t1.state = uiconst.UI_HIDDEN
    410             t2.text = localization.GetByLabel('UI/Neocom/Petition/RateYourComments')
    411         wnd.sr.ratingtime = blue.os.GetWallclockTime()
    412 
    413     def OnCheckboxChange(self, *args):
    414         if not args:
    415             return
    416         wnd = self.GetViewWnd()
    417         if wnd and not wnd.destroyed:
    418             settings.user.ui.Set('petition_%s' % args[0].name, args[0].data['value'])
    419 
    420     def OnTextEditChange(self, *args):
    421         if not args:
    422             return
    423         wnd = self.GetViewWnd()
    424         if wnd and not wnd.destroyed:
    425             settings.user.ui.Set('petition_%s' % args[0].name, args[0].GetValue())
    426 
    427     def SetRating(self, *args):
    428         wnd = self.GetViewWnd()
    429         if not wnd or wnd.destroyed:
    430             return
    431         p = wnd.sr.p
    432         currentRating = getattr(p, 'rating', None)
    433         currentComment = getattr(p, 'ratingComment', '')
    434         cbResponseTimeValue = [ cb for cb in wnd.sr.responseTimeRatingCBs if cb.checked ]
    435         if not cbResponseTimeValue:
    436             wnd.sr.ratinghinttext.text = localization.GetByLabel('UI/Neocom/Petition/RateNotValid')
    437             return
    438         responseTimeRating = cbResponseTimeValue[0].data['value']
    439         cbHelpfulnessValue = [ cb for cb in wnd.sr.helpfulnessRatingCBs if cb.checked ]
    440         if not cbHelpfulnessValue:
    441             wnd.sr.ratinghinttext.text = localization.GetByLabel('UI/Neocom/Petition/RateNotValid')
    442             return
    443         helpfulnessRating = cbHelpfulnessValue[0].data['value']
    444         cbAttitudeValue = [ cb for cb in wnd.sr.attitudeRatingCBs if cb.checked ]
    445         if not cbAttitudeValue:
    446             wnd.sr.ratinghinttext.text = localization.GetByLabel('UI/Neocom/Petition/RateNotValid')
    447             return
    448         attitudeRating = cbAttitudeValue[0].data['value']
    449         newComment = wnd.sr.ratingcomment.GetValue()
    450         if getattr(p, 'ratingDateTime', None):
    451             if currentRating != newRating or currentComment != newComment:
    452                 sm.RemoteSvc('petitioner').UpdatePetitionRating(p.petitionID, responseTimeRating, helpfulnessRating, attitudeRating, newComment)
    453             else:
    454                 return
    455         else:
    456             sm.RemoteSvc('petitioner').AddPetitionRating(p.petitionID, responseTimeRating, helpfulnessRating, attitudeRating, newComment, wnd.sr.ratingtime)
    457         setattr(p, 'responseTimeRating', responseTimeRating)
    458         setattr(p, 'helpfulnessRating', helpfulnessRating)
    459         setattr(p, 'attitudeRating', attitudeRating)
    460         setattr(p, 'ratingComment', newComment)
    461         setattr(p, 'ratingDateTime', wnd.sr.ratingtime)
    462         settings.user.ui.Set('petition_responseTimeRating', responseTimeRating)
    463         settings.user.ui.Set('petition_helpfulnessRating', helpfulnessRating)
    464         settings.user.ui.Set('petition_attitudeRating', attitudeRating)
    465         settings.user.ui.Set('petition_ratingComment', newComment)
    466         self._ReloadVisible()
    467         uthread.new(self.ShowRating)
    468 
    469     def ShowPetitionQueue(self, queueID):
    470         if not self.GetIsPetitionee():
    471             return
    472         self.LogInfo('ShowPetitionQueue %s' % queueID)
    473         self.SetHint()
    474         groupid = 'quequedpetitions%d' % queueID
    475         mp = sm.RemoteSvc('petitioner').GetPetitionQueue(queueID)
    476         owners = []
    477         for p in mp:
    478             if p.petitionerID and p.petitionerID not in owners:
    479                 owners.append(p.petitionerID)
    480 
    481         if len(owners):
    482             cfg.eveowners.Prime(owners)
    483         scrolllist = []
    484         for p in mp:
    485             data = self.GetPetitionData('queue', p)
    486             data.groupID = groupid
    487             data.p = p
    488             data.type = 'queue'
    489             scrolllist.append(GetFromClass(PetitionField, data))
    490 
    491         wnd = self.GetWnd()
    492         if wnd:
    493             wnd.sr.scroll.Load(contentList=scrolllist, headers=[localization.GetByLabel('UI/Common/Date'),
    494              localization.GetByLabel('UI/Neocom/Petition/Subject'),
    495              localization.GetByLabel('UI/Common/Name'),
    496              localization.GetByLabel('UI/Neocom/Petition/Status'),
    497              localization.GetByLabel('UI/Common/Updated'),
    498              localization.GetByLabel('UI/Common/Category'),
    499              localization.GetByLabel('UI/Neocom/Petition/LastUpdate')])
    500             if not len(scrolllist):
    501                 self.SetHint(localization.GetByLabel('UI/Neocom/Petition/ThisQueueHasNoPetitions'))
    502 
    503     def GetPetitionData(self, type, p):
    504         data = utillib.KeyVal()
    505         data.menu = []
    506         data.cstring = self.GetC_String(p.categoryID)
    507         label = FmtDate(p.createDate, 'ls')
    508         label += '<t>' + p.subject
    509         if type == 'queue' or type == 'claimed':
    510             if p.petitionerID:
    511                 label += '<t>%s' % cfg.eveowners.Get(p.petitionerID).name
    512             else:
    513                 label += '<t>%s' % p.email
    514             if p.claimed:
    515                 label += '<t>' + localization.GetByLabel('UI/Neocom/Petition/Claimed')
    516                 label += '<t>' + [localization.GetByLabel('UI/Common/Updated'), localization.GetByLabel('UI/Neocom/Petition/Waiting')][p.updated]
    517                 data.menu.append((MenuLabel('UI/Neocom/Petition/ClosePetition'), self.ClosePetition, (p.petitionID,)))
    518                 data.menu.append((MenuLabel('UI/Neocom/Petition/UnclaimPetition'), self.UnClaimPetition, (p.petitionID,)))
    519                 if getattr(p, 'escalatesTo', None):
    520                     data.menu.append((MenuLabel('UI/Neocom/Petition/Escalate'), self.EscalatePetition, (p.petitionID, p.escalatesTo)))
    521             else:
    522                 label += '<t>' + localization.GetByLabel('UI/Neocom/Petition/Unclaimed')
    523                 label += '<t>-'
    524                 if not p.closed and not p.deleted:
    525                     if p.petitionerID != session.charid:
    526                         data.menu.append((MenuLabel('UI/Neocom/Petition/ClaimPetition'), self.ClaimPetition, (p,)))
    527         elif type == 'my':
    528             if p.closed:
    529                 label += '<t>' + localization.GetByLabel('UI/Neocom/Petition/Closed')
    530                 rating = getattr(p, 'rating', None)
    531                 if rating is not None:
    532                     label += '<t>%s' % (int(rating) / 10)
    533                 else:
    534                     responseTimeRating = getattr(p, 'responseTimeRating', None)
    535                     helpfulnessRating = getattr(p, 'helpfulnessRating', None)
    536                     attitudeRating = getattr(p, 'attitudeRating', None)
    537                     if responseTimeRating is not None and helpfulnessRating is not None and attitudeRating is not None:
    538                         label += '<t>%s' % (int((responseTimeRating + helpfulnessRating + attitudeRating) / 3) / 10)
    539                     else:
    540                         rateable = getattr(p, 'rateable', 0)
    541                         if rateable:
    542                             label += '<t>' + localization.GetByLabel('UI/Neocom/Petition/NotRated')
    543                         else:
    544                             label += '<t>-'
    545                 data.menu.append((MenuLabel('UI/Neocom/Petition/Delete'), self.DeletePetition, (p.petitionID,)))
    546                 rateable = getattr(p, 'rateable', 0)
    547                 if rateable:
    548                     currentDateTime = getattr(p, 'ratingDateTime', None)
    549                     if currentDateTime is None or currentDateTime + const.WEEK > blue.os.GetWallclockTime():
    550                         data.menu.append((MenuLabel('UI/Neocom/Petition/Rate'), self.RatePetition, (p,)))
    551             else:
    552                 if not p.claimed:
    553                     label += '<t>' + localization.GetByLabel('UI/Neocom/Petition/StatusOpen')
    554                     data.menu.append((MenuLabel('UI/Neocom/Petition/CancelPetition'), self.CancelPetition, (p.petitionID,)))
    555                 else:
    556                     label += '<t>' + localization.GetByLabel('UI/Neocom/Petition/InAction')
    557                 label += '<t>-'
    558         data.menu.insert(0, None)
    559         data.menu.insert(0, (MenuLabel('UI/Neocom/Petition/View'), self.ShowPetition, (p,)))
    560         if type == 'my':
    561             label += '<t>%s<t>%s' % (data.cstring, FmtDate(p.touchDate, 'ls'))
    562         else:
    563             label += '<t>%s<t>-' % data.cstring
    564         data.label = label
    565         return data
    566 
    567     def RatePetition(self, p):
    568         viewwnd = self.ShowPetition(p)
    569         if viewwnd.sr.maintabs.GetSelectedArgs() != 'rating':
    570             uthread.new(viewwnd.sr.maintabs.ShowPanelByName, localization.GetByLabel('UI/Neocom/Petition/Rating'))
    571 
    572     def GetQueues(self):
    573         if self.queues is None:
    574             if self.GetIsPetitionee():
    575                 queues = sm.RemoteSvc('petitioner').GetQueues()
    576                 self.queues = queues
    577         return self.queues
    578 
    579     def GetCategories(self):
    580         if self.categories is None:
    581             self.categories = sm.RemoteSvc('petitioner').GetCategories()
    582         return self.categories
    583 
    584     def GetCategory(self, id):
    585         for each in self.GetCategories():
    586             if each.categoryID == id:
    587                 return each
    588 
    589     def GetC_String(self, id):
    590         cat = self.GetCategory(id)
    591         if cat:
    592             return cat.displayName
    593         return localization.GetByLabel('UI/Common/Unknown')
    594 
    595     def GetIsPetitionee(self):
    596         if self.petitionee is None:
    597             role = session.role
    598             if role & ROLE_PETITIONEE == ROLE_PETITIONEE:
    599                 self.petitionee = 1
    600                 if role & ROLE_GML == ROLE_GML:
    601                     self.petitionee = 2
    602             else:
    603                 self.petitionee = 0
    604         return self.petitionee
    605 
    606     def GetStatusName(self, p):
    607         status = ''
    608         if getattr(p, 'closed', 0) == 0:
    609             status = localization.GetByLabel('UI/Neocom/Petition/StatusOpen')
    610             if p.claimed:
    611                 status = localization.GetByLabel('UI/Neocom/Petition/InAction')
    612         else:
    613             status = localization.GetByLabel('UI/Neocom/Petition/Closed')
    614         return status
    615 
    616     def NewPetition(self, *args):
    617         wnd = PetitionWindow.GetIfOpen()
    618         if wnd is not None and not wnd.destroyed:
    619             wnd.Maximize()
    620         else:
    621             wnd = PetitionWindow.Open()
    622 
    623     def OpenBrowser(self, *args):
    624         if args:
    625             blue.os.ShellExecute(args[0])
    626 
    627     def SelectionChange(self, selected):
    628         wnd = self.GetWnd()
    629         if wnd is None or wnd.destroyed:
    630             return
    631         btnparent = wnd.sr.buttons.children[0]
    632         for btn in btnparent.children:
    633             btn.state = uiconst.UI_HIDDEN
    634 
    635         if selected:
    636             p = selected[0].p
    637             tab = wnd.sr.tabs.GetSelectedTab()
    638             btnparent.children[0].state = uiconst.UI_NORMAL
    639             if tab.sr.args == 'claimedpetitions' or tab.sr.args in range(6):
    640                 if not p.claimed and (p.closed or p.deleted or p.petitionerID != session.charid):
    641                     btnparent.children[1].state = uiconst.UI_NORMAL
    642             if tab.sr.args == 'mypetitions':
    643                 if p.closed:
    644                     btnparent.children[2].state = uiconst.UI_NORMAL
    645                     rateable = getattr(p, 'rateable', 0)
    646                     if rateable:
    647                         currentDateTime = getattr(p, 'ratingDateTime', None)
    648                         if currentDateTime is None or currentDateTime + const.WEEK > blue.os.GetWallclockTime():
    649                             btnparent.children[4].state = uiconst.UI_NORMAL
    650                 elif not p.claimed:
    651                     btnparent.children[3].state = uiconst.UI_NORMAL
    652 
    653     def ShowPetitionClicked(self, *args):
    654         wnd = self.GetWnd()
    655         if wnd is None or wnd.destroyed:
    656             return
    657         selected = wnd.sr.scroll.GetSelected()
    658         if selected:
    659             self.ShowPetition(selected[0].p)
    660 
    661     def ClaimPetitionClicked(self, *args):
    662         wnd = self.GetWnd()
    663         if wnd is None or wnd.destroyed:
    664             return
    665         selected = wnd.sr.scroll.GetSelected()
    666         if selected:
    667             self.ClaimPetition(selected[0].p)
    668 
    669     def DeletePetitionClicked(self, *args):
    670         wnd = self.GetWnd()
    671         if wnd is None or wnd.destroyed:
    672             return
    673         selected = wnd.sr.scroll.GetSelected()
    674         if selected:
    675             self.DeletePetition(selected[0].p.petitionID)
    676 
    677     def CancelPetitionClicked(self, *args):
    678         wnd = self.GetWnd()
    679         if wnd is None or wnd.destroyed:
    680             return
    681         selected = wnd.sr.scroll.GetSelected()
    682         if selected:
    683             self.CancelPetition(selected[0].p.petitionID)
    684 
    685     def RatePetitionClicked(self, *args):
    686         wnd = self.GetWnd()
    687         if wnd is None or wnd.destroyed:
    688             return
    689         selected = wnd.sr.scroll.GetSelected()
    690         if selected:
    691             viewwnd = self.ShowPetition(selected[0].p)
    692             uthread.new(self.OpenRateView, viewwnd)
    693 
    694     def OpenRateView(self, viewwnd):
    695         if viewwnd and viewwnd.sr.maintabs.GetSelectedArgs() != 'rating':
    696             viewwnd.sr.maintabs.ShowPanelByName(localization.GetByLabel('UI/Neocom/Petition/Rating'))
    697 
    698     def CreatePetition(self, subject, petition, categoryID, retval, OocCharacterID):
    699         self.LogInfo('CreatePetition')
    700         combatLog = None
    701         chatLog = None
    702         chatLog = GetChatService().GetChannelMessages()
    703         if chatLog:
    704             chatLog = chatLog[-const.petitionMaxChatLogSize:]
    705         combatLog = sm.GetService('logger').GetLog()
    706         if not sm.RemoteSvc('petitioner').CreatePetition(subject, petition, categoryID, retval, OocCharacterID, combatLog=combatLog, chatLog=chatLog):
    707             prompt_player_fsd_dialog('CannotPostPetition', {'text': localization.GetByLabel('UI/Neocom/Petition/CannotPostPetition4')})
    708             return
    709         self.mine = None
    710         if session.charid:
    711             self._ShowPanelByName(localization.GetByLabel('UI/Neocom/Petition/MyPetitions'))
    712         else:
    713             prompt_player_fsd_dialog('PetitionSuccess', {'text': ''})
    714 
    715     def GetViewWnd(self, new = 0):
    716         wnd = Window.GetIfOpen(windowID='petitionview')
    717         if not wnd and new:
    718             wnd = Window.Open(windowID='petitionview')
    719             wnd.sr.main = wnd.GetChild('main')
    720             wnd.scope = uiconst.SCOPE_ALL
    721             wnd.SetCaption(localization.GetByLabel('UI/Neocom/Petition/View'))
    722             wnd.SetMinSize([340, 300])
    723             wnd.icon = 'res:/ui/Texture/WindowIcons/help.png'
    724             wnd.sr.scroll = eveScroll.Scroll(parent=wnd.sr.main, padding=(const.defaultPadding,
    725              const.defaultPadding,
    726              const.defaultPadding,
    727              const.defaultPadding))
    728             wnd.OnScale_ = self.OnViewScale
    729         return wnd
    730 
    731     def ShowPetition(self, p, *args):
    732         self.LogInfo('ShowPetition')
    733         viewwnd = self.GetViewWnd()
    734         if viewwnd and not viewwnd.destroyed:
    735             viewwnd.Close()
    736         viewwnd = self.GetViewWnd(1)
    737         buttons = []
    738         status = self.GetStatusName(p)
    739         if self.GetIsPetitionee():
    740             if p.claimed:
    741                 buttons.append({'caption': localization.GetByLabel('UI/Accessories/Log/Message'),
    742                  'function': self.SendMessage,
    743                  'args': p.petitionID})
    744                 buttons.append({'caption': localization.GetByLabel('UI/Neocom/Petition/Unclaim'),
    745                  'function': self.UnClaimPetition,
    746                  'args': p.petitionID})
    747                 if getattr(p, 'escalatesTo', None):
    748                     buttons.append({'caption': localization.GetByLabel('UI/Neocom/Petition/Escalate'),
    749                      'function': self.EscalatePetition,
    750                      'args': (p.petitionID, p.escalatesTo)})
    751                 buttons.append({'caption': localization.GetByLabel('UI/Generic/Close'),
    752                  'function': self.ClosePetition,
    753                  'args': p.petitionID})
    754             elif not p.deleted:
    755                 if not p.closed:
    756                     if p.petitionerID != session.charid:
    757                         buttons.append({'caption': localization.GetByLabel('UI/Generic/Claim'),
    758                          'function': self.ClaimPetition,
    759                          'args': p})
    760                     else:
    761                         buttons.append({'caption': localization.GetByLabel('UI/Neocom/Petition/AddMessage'),
    762                          'size': 'large',
    763                          'function': self.SendMessage,
    764                          'args': p.petitionID})
    765                 else:
    766                     buttons.append({'caption': localization.GetByLabel('UI/Common/Delete'),
    767                      'function': self.DeletePetition,
    768                      'args': p.petitionID})
    769         elif not p.closed:
    770             buttons.append({'caption': localization.GetByLabel('UI/Neocom/Petition/AddMessage'),
    771              'size': 'large',
    772              'function': self.SendMessage,
    773              'args': p.petitionID})
    774         else:
    775             buttons.append({'caption': localization.GetByLabel('UI/Common/Delete'),
    776              'function': self.DeletePetition,
    777              'args': p.petitionID})
    778         pet = ''
    779         if getattr(p, 'petition', None):
    780             pet = p.petition
    781         format = [{'type': 'push'},
    782          {'type': 'labeltext',
    783           'label': localization.GetByLabel('UI/Common/Category'),
    784           'text': self.GetC_String(p.categoryID),
    785           'frame': 0},
    786          {'type': 'labeltext',
    787           'label': localization.GetByLabel('UI/Neocom/Petition/Status'),
    788           'text': status,
    789           'frame': 0},
    790          {'type': 'labeltext',
    791           'label': localization.GetByLabel('UI/Neocom/Petition/Subject'),
    792           'text': p.subject,
    793           'frame': 0,
    794           'refreshheight': 1},
    795          {'type': 'push',
    796           'width': 20,
    797           'frame': 0},
    798          {'type': 'push',
    799           'width': 20,
    800           'frame': 0},
    801          {'type': 'textedit',
    802           'label': '_hide',
    803           'text': pet.replace('\n', '<br>'),
    804           'readonly': 1,
    805           'height': 120,
    806           'frame': 0},
    807          {'type': 'push',
    808           'width': 20,
    809           'frame': 0}]
    810         if p.properties is not None:
    811             for propertyNameID in p.properties.iterkeys():
    812                 for kv in p.properties[propertyNameID]:
    813                     format.append({'type': 'labeltext',
    814                      'label': localization.GetByMessageID(propertyNameID),
    815                      'labelwidth': 140,
    816                      'text': p.properties[propertyNameID][kv],
    817                      'frame': 1})
    818 
    819         if len(buttons):
    820             format.append({'type': 'btnonly',
    821              'buttons': buttons,
    822              'uniSize': 0})
    823             format.append({'type': 'push',
    824              'height': 8})
    825         _form, retfields, reqresult, panels, errorcheck, refresh = sm.GetService('form').GetForm(format, FormWnd(name='form', align=uiconst.TOTOP, parent=viewwnd.sr.main))
    826         _form.children.insert(0, Container(name='push', align=uiconst.TOLEFT, width=7))
    827         _form.children.insert(0, Container(name='push', align=uiconst.TORIGHT, width=7))
    828         viewformat = [{'type': 'push'},
    829          {'type': 'btnonly',
    830           'buttons': [{'caption': localization.GetByLabel('UI/Neocom/Petition/Reply'),
    831                        'align': 'left',
    832                        'function': self.SendMessage,
    833                        'args': p.petitionID}]},
    834          {'type': 'push'},
    835          {'type': 'push'},
    836          {'type': 'textedit',
    837           'label': '_hide',
    838           'key': 'body',
    839           'readonly': 1,
    840           'height': 120}]
    841         viewformparent = FormWnd(name='form', align=uiconst.TOBOTTOM)
    842         viewwnd.sr.main.children.insert(0, viewformparent)
    843         _viewform, viewretfields, viewreqresult, viewpanels, viewerrorcheck, viewrefresh = sm.GetService('form').GetForm(viewformat, viewformparent)
    844         _viewform.children.insert(0, Container(name='push', align=uiconst.TOLEFT, width=const.defaultPadding))
    845         _viewform.children.insert(0, Container(name='push', align=uiconst.TORIGHT, width=const.defaultPadding))
    846         _viewform.height += const.defaultPadding
    847         viewwnd.sr.viewmessageform = _viewform
    848         viewwnd.sr.viewmessageform.state = uiconst.UI_HIDDEN
    849         viewwnd.sr.refreshitems = viewrefresh
    850         viewwnd.sr.p = p
    851         viewwnd.SetMinSize([340, _form.top + _form.height + 100], 1)
    852         tabs = [[localization.GetByLabel('UI/Notepad/GeneralInformation'),
    853           _form,
    854           self,
    855           'generic'], [localization.GetByLabel('UI/Neocom/Petition/Messages'),
    856           viewwnd.sr.scroll,
    857           self,
    858           'messages']]
    859         if p.closed:
    860             viewwnd.sr.ratingparent = Container(name='ratingparent', parent=viewwnd.sr.main, align=uiconst.TOALL, left=const.defaultPadding, top=const.defaultPadding, width=const.defaultPadding, height=const.defaultPadding)
    861             Frame(parent=viewwnd.sr.ratingparent, color=(1.0, 1.0, 1.0, 0.5))
    862             tabs.append([localization.GetByLabel('UI/Neocom/Petition/Rating'),
    863              viewwnd.sr.ratingparent,
    864              self,
    865              'rating'])
    866         if self.GetIsPetitionee():
    867             tabs.append([localization.GetByLabel('UI/Accessories/Log/Log'),
    868              viewwnd.sr.scroll,
    869              self,
    870              'logs'])
    871         viewwnd.sr.maintabs = TabGroup(name='tabparent', parent=viewwnd.sr.main, idx=0)
    872         viewwnd.sr.maintabs.Startup(tabs, 'viewpetition')
    873         settings.user.ui.Set('petition_rating', getattr(p, 'rating', None))
    874         settings.user.ui.Set('petition_responseTimeRating', getattr(p, 'responseTimeRating', None))
    875         settings.user.ui.Set('petition_helpfulnessRating', getattr(p, 'helpfulnessRating', None))
    876         settings.user.ui.Set('petition_attitudeRating', getattr(p, 'attitudeRating', None))
    877         settings.user.ui.Set('petition_ratingcomment', getattr(p, 'ratingComment', ''))
    878         return viewwnd
    879 
    880     def OnViewScale(self, *args):
    881         viewwnd = self.GetViewWnd()
    882         if viewwnd is None or viewwnd.destroyed:
    883             return
    884         for each in viewwnd.sr.refreshitems:
    885             if hasattr(each, 'RefreshSize'):
    886                 each.RefreshSize()
    887 
    888     def LoadLogs(self):
    889         if not self.GetIsPetitionee():
    890             return
    891         viewwnd = self.GetViewWnd()
    892         if viewwnd is None or viewwnd.destroyed or self.loadinglogs:
    893             return
    894         if viewwnd is not None and viewwnd.sr.viewmessageform:
    895             viewwnd.sr.viewmessageform.state = uiconst.UI_HIDDEN
    896         p = viewwnd.sr.p
    897         self.loadinglogs = 1
    898         plogs = sm.RemoteSvc('petitioner').GetLog(p.petitionID)
    899         textDict = get_petition_event_texts()
    900         rowDescriptor = blue.DBRowDescriptor((('logDateTime', const.DBTYPE_FILETIME),
    901          ('characterID', const.DBTYPE_I4),
    902          ('userName', const.DBTYPE_WSTR),
    903          ('eventID', const.DBTYPE_UI1),
    904          ('eventText', const.DBTYPE_STR)))
    905         rowset = CRowset(rowDescriptor, [])
    906         owners = []
    907         for pl in plogs:
    908             if pl.characterID is not None and pl.characterID not in owners:
    909                 owners.append(pl.characterID)
    910             rowset.InsertNew([pl.logDateTime,
    911              pl.characterID,
    912              pl.userName,
    913              pl.eventID,
    914              textDict[pl.eventID]])
    915 
    916         if len(owners):
    917             cfg.eveowners.Prime(owners)
    918         scrolllist = []
    919         for pl in rowset:
    920             data = utillib.KeyVal()
    921             data.log = pl
    922             data.p = p
    923             scrolllist.append(GetFromClass(LogField, data=data))
    924 
    925         viewwnd.sr.scroll.Load(fixedEntryHeight=24, contentList=scrolllist)
    926         self.loadinglogs = 0
    927 
    928     def LoadMessages(self):
    929         viewwnd = self.GetViewWnd()
    930         if viewwnd is None or viewwnd.destroyed or self.loadingmessages:
    931             return
    932         p = viewwnd.sr.p
    933         viewwnd.sr.lastSender = 0
    934         self.loadingmessages = 1
    935         pmsgs = sm.RemoteSvc('petitioner').GetPetitionMessages(p.petitionID)
    936         owners = []
    937         for pm in pmsgs:
    938             if pm.senderID is not None and pm.senderID not in owners:
    939                 owners.append(pm.senderID)
    940 
    941         if len(owners):
    942             cfg.eveowners.Prime(owners)
    943         scrolllist = []
    944         for pm in pmsgs:
    945             if viewwnd.sr.lastSender == 0:
    946                 viewwnd.sr.lastSender = pm.senderID
    947             data = utillib.KeyVal()
    948             data.msg = pm
    949             data.p = p
    950             scrolllist.append(GetFromClass(MessageField, data))
    951 
    952         viewwnd.sr.scroll.Load(contentList=scrolllist)
    953         self.loadingmessages = 0
    954 
    955     def ShowMessage(self, msg, p):
    956         viewwnd = self.GetViewWnd()
    957         if viewwnd is None or viewwnd.destroyed:
    958             return
    959         viewwnd.ShowLoad()
    960         if viewwnd.sr.lastSender == session.charid or p.closed == 1:
    961             viewwnd.sr.viewmessageform.children[3].state = uiconst.UI_HIDDEN
    962         viewwnd.sr.viewmessageform.sr.body.SetValue(msg.text.replace('\n', '<br>'), scrolltotop=1)
    963         viewwnd.sr.viewmessageform.state = uiconst.UI_PICKCHILDREN
    964         self.MarkAsRead(msg.messageID)
    965         viewwnd.HideLoad()
    966 
    967     def SendMessage(self, petitionid, *args):
    968         format = [{'type': 'textedit',
    969           'height': 128,
    970           'label': '_hide',
    971           'key': 'message',
    972           'frame': 0,
    973           'maxlength': 1000}, {'type': 'push',
    974           'height': 14}]
    975         if self.GetIsPetitionee():
    976             format.append({'type': 'checkbox',
    977              'required': 0,
    978              'height': 32,
    979              'setvalue': 0,
    980              'key': 'comment',
    981              'label': '',
    982              'text': localization.GetByLabel('UI/Neocom/Petition/AddThisMessageAsComment')})
    983         retval = uix.HybridWnd(format, caption=localization.GetByLabel('UI/Neocom/Petition/SendMessage'), windowID='sendMessage', modal=1, buttons=None, location=None, minW=340, minH=256, blockconfirm=1)
    984         if retval is not None:
    985             message = retval['message']
    986             if message == '':
    987                 return
    988             if self.GetIsPetitionee():
    989                 comment = retval['comment']
    990                 try:
    991                     sm.RemoteSvc('petitioner').PetitioneeChat(petitionid, message, comment)
    992                 except UserError as e:
    993                     if e.msg != 'PetitionClosed':
    994                         raise
    995                     prompt_player_fsd_dialog('MessageNotSentPetitionAlreadyClosed')
    996                     sys.exc_clear()
    997 
    998             else:
    999                 try:
   1000                     sm.RemoteSvc('petitioner').PetitionerChat(petitionid, message)
   1001                 except UserError as e:
   1002                     if e.msg != 'PetitionClosed':
   1003                         raise
   1004                     prompt_player_fsd_dialog('MessageNotSentPetitionAlreadyClosed')
   1005                     sys.exc_clear()
   1006 
   1007     def OnPetitionMessage(self, petitionID, charID, messageText, messageID):
   1008         if session.charid is None:
   1009             return
   1010         viewwnd = self.GetViewWnd()
   1011         self.mine = None
   1012         if charID != session.charid and (viewwnd is None or viewwnd.destroyed):
   1013             if self.GetIsPetitionee():
   1014                 prompt_player_fsd_dialog('PetPetioneeGotResposne', {'player': charID})
   1015             else:
   1016                 self.NewMessage(petitionID, messageText.replace('\n', '<br>'), messageID)
   1017         else:
   1018             self.LoadMessages()
   1019         sm.GetService('neocom').Blink('help')
   1020 
   1021     def SendMessageOpen(self, sender, *args):
   1022         self.LogInfo('SendMessageOpen')
   1023         message = sender.text
   1024         if message != '':
   1025             sender.text = ''
   1026             petitionid = sender.data['key']
   1027             try:
   1028                 sm.RemoteSvc('petitioner').PetitionerChat(petitionid, message)
   1029             except UserError as e:
   1030                 if e.msg != 'PetitionClosed':
   1031                     raise
   1032                 prompt_player_fsd_dialog('MessageNotSentPetitionAlreadyClosed')
   1033                 sys.exc_clear()
   1034 
   1035     def SendMessageClaimed(self, sender, *args):
   1036         self.LogInfo('SendMessageClaimed')
   1037         message = sender.text
   1038         if message != '':
   1039             sender.text = ''
   1040             petitionid = sender.data['key']
   1041             try:
   1042                 sm.RemoteSvc('petitioner').PetitioneeChat(petitionid, message)
   1043             except UserError as e:
   1044                 if e.msg != 'PetitionClosed':
   1045                     raise
   1046                 prompt_player_fsd_dialog('MessageNotSentPetitionAlreadyClosed')
   1047                 sys.exc_clear()
   1048 
   1049     def CloseViewWindow(self, *args):
   1050         viewwnd = self.GetViewWnd()
   1051         if viewwnd is None or viewwnd.destroyed:
   1052             return
   1053         viewwnd.Close()
   1054 
   1055     def DeletePetition(self, petitionid, *args):
   1056         self.LogInfo('DeletePetition')
   1057         if prompt_player_fsd_dialog('PetitionQuestion2', {}, uiconst.YESNO) == uiconst.ID_YES:
   1058             ret = sm.RemoteSvc('petitioner').DeletePetition(petitionid)
   1059             self._ShowPanelByName(localization.GetByLabel('UI/Neocom/Petition/MyPetitions'))
   1060             viewwnd = self.GetViewWnd()
   1061             if viewwnd is None or viewwnd.destroyed:
   1062                 return
   1063             viewwnd.Close()
   1064 
   1065     def CancelPetition(self, petitionid, *args):
   1066         self.LogInfo('CancelPetition')
   1067         if prompt_player_fsd_dialog('PetitionQuestion3', {}, uiconst.YESNO) == uiconst.ID_YES:
   1068             sm.RemoteSvc('petitioner').CancelPetition(petitionid)
   1069             self.mine = None
   1070             self._ShowPanelByName(localization.GetByLabel('UI/Neocom/Petition/MyPetitions'))
   1071             viewwnd = self.GetViewWnd()
   1072             if viewwnd is None or viewwnd.destroyed:
   1073                 return
   1074             viewwnd.Close()
   1075 
   1076     def ClosePetition(self, petitionid, *args):
   1077         self.LogInfo('ClosePetition')
   1078         sm.RemoteSvc('petitioner').ClosePetition(petitionid)
   1079         self._ShowPanelByName(localization.GetByLabel('UI/Neocom/Petition/ClaimedPetitions'))
   1080         viewwnd = self.GetViewWnd()
   1081         if viewwnd is None or viewwnd.destroyed:
   1082             return
   1083         viewwnd.Close()
   1084 
   1085     def UnClaimPetition(self, petitionid, *args):
   1086         self.LogInfo('UnClaimPetition')
   1087         sm.RemoteSvc('petitioner').UnClaimPetition(petitionid)
   1088         self._ShowPanelByName(localization.GetByLabel('UI/Neocom/Petition/ClaimedPetitions'))
   1089         viewwnd = self.GetViewWnd()
   1090         if viewwnd is None or viewwnd.destroyed:
   1091             return
   1092         viewwnd.Close()
   1093 
   1094     def EscalatePetition(self, postArgs, *args):
   1095         if type(postArgs) != type(()):
   1096             postArgs = (postArgs,) + args
   1097         petitionid, escalatesTo = postArgs
   1098         self.LogInfo('UnClaimPetition')
   1099         sm.RemoteSvc('petitioner').EscalatePetition(petitionid, escalatesTo)
   1100         self._ShowPanelByName(localization.GetByLabel('UI/Neocom/Petition/ClaimedPetitions'))
   1101         viewwnd = self.GetViewWnd()
   1102         if viewwnd is None or viewwnd.destroyed:
   1103             return
   1104         viewwnd.Close()
   1105 
   1106     def ClaimPetition(self, p, *args):
   1107         self.LogInfo('ClaimPetition')
   1108         if sm.RemoteSvc('petitioner').ClaimPetition(p.petitionID) > 0:
   1109             viewwnd = self.GetViewWnd()
   1110             if viewwnd is not None and not viewwnd.destroyed:
   1111                 viewwnd.Close()
   1112             p.claimed = 1
   1113             self.ShowPetition(p)
   1114             self._ShowPanelByName(localization.GetByLabel('UI/Neocom/Petition/ClaimedPetitions'))
   1115         else:
   1116             prompt_player_fsd_dialog('PetitionInfo1')
   1117 
   1118     def _ShowPanelByName(self, panelName, *args):
   1119         self.mine = None
   1120         wnd = self.GetWnd()
   1121         if wnd is not None and not wnd.destroyed:
   1122             wnd.sr.tabs.ShowPanelByName(panelName)
   1123 
   1124     def _ReloadVisible(self, *args):
   1125         self.mine = None
   1126         wnd = self.GetWnd()
   1127         if wnd is not None and not wnd.destroyed:
   1128             wnd.sr.tabs.ReloadVisible()
   1129 
   1130 
   1131 class LogField(SE_BaseClassCore):
   1132     __guid__ = 'listentry.Logfield'
   1133 
   1134     def Startup(self, *args):
   1135         self.sr.icon = eveIcon.Icon(parent=self, pos=(-2, -1, 26, 26), name='icon', state=uiconst.UI_DISABLED, icon='res:/ui/Texture/WindowIcons/personallocations.png', ignoreSize=True, align=uiconst.RELATIVE)
   1136         self.selection = None
   1137         self.sr.subject = eveLabel.EveLabelSmall(text='', parent=self, left=26, top=2, state=uiconst.UI_DISABLED, tabs=[200, 500])
   1138         self.state = uiconst.UI_NORMAL
   1139 
   1140     def Load(self, node):
   1141         self.sr.node = node
   1142         data = node
   1143         self.log = data.log
   1144         self.p = data.p
   1145         charName = ''
   1146         if self.log.characterID:
   1147             charName = cfg.eveowners.Get(self.log.characterID).name
   1148         self.sr.subject.text = '%s<t>%s<br>%s<t>%s' % (FmtDate(self.log.logDateTime),
   1149          charName,
   1150          self.log.eventText,
   1151          self.log.userName)
   1152         if node.Get('selected', 0):
   1153             self.Select()
   1154         else:
   1155             self.Deselect()
   1156 
   1157     def GetHeight(_self, *args):
   1158         node, width = args
   1159         theight = uix.GetTextHeight('X<br>X', fontsize=EVE_SMALL_FONTSIZE, hspace=1, uppercase=1)
   1160         node.height = max(24, theight + 4)
   1161         return node.height
   1162 
   1163 
   1164 class MessageField(SE_BaseClassCore):
   1165     __guid__ = 'listentry.MessageField'
   1166 
   1167     def Startup(self, *args):
   1168         self.sr.icon = eveIcon.Icon(parent=self, pos=(-2, -1, 26, 26), name='icon', state=uiconst.UI_DISABLED, icon='res:/ui/Texture/WindowIcons/chatchannel.png', ignoreSize=True, align=uiconst.RELATIVE)
   1169         self.selection = None
   1170         self.sr.subject = eveLabel.EveLabelSmall(text='', parent=self, left=26, top=2, state=uiconst.UI_DISABLED, tabs=[120, 500])
   1171         self.state = uiconst.UI_NORMAL
   1172 
   1173     def Load(self, node):
   1174         self.sr.node = node
   1175         data = node
   1176         self.msg = data.msg
   1177         self.p = data.p
   1178         sender = '%s<br>' % cfg.eveowners.Get(self.msg.senderID).name if self.msg.senderID is not None else ''
   1179         self.sr.subject.text = '%s%s' % (sender, FmtDate(self.msg.sentDate))
   1180         if node.Get('selected', 0):
   1181             self.Select()
   1182         if self.msg.senderID == session.charid:
   1183             self.sr.icon.LoadIcon('res:/UI/Texture/WindowIcons/help.png', True)
   1184         else:
   1185             self.sr.icon.LoadIcon('res:/UI/Texture/WindowIcons/attention.png', True)
   1186         if self.msg.comment == 1:
   1187             self.sr.icon.LoadIcon('res:/ui/Texture/WindowIcons/chatchannel.png', True)
   1188 
   1189     def GetHeight(self, *args):
   1190         node, width = args
   1191         theight = uix.GetTextHeight('X<br>X', fontsize=EVE_SMALL_FONTSIZE, hspace=1, uppercase=1)
   1192         node.height = max(24, theight + 4)
   1193         return node.height
   1194 
   1195     def _OnClose(self):
   1196         self.msg = None
   1197         self.p = None
   1198         self.selection = None
   1199 
   1200     def OnClick(self, *args):
   1201         self.sr.node.scroll.SelectNode(self.sr.node)
   1202         sm.StartService('petition').ShowMessage(self.msg, self.p)
   1203 
   1204     def GetMenu(self):
   1205         return [(MenuLabel('UI/Neocom/Petition/ViewMessage'), sm.StartService('petition').ShowMessage, (self.msg, self.p))]
   1206 
   1207 
   1208 class PetitionField(Generic):
   1209     __guid__ = 'listentry.PetitionField'
   1210     __notifyevents__ = ['OnContactLoggedOn', 'OnContactLoggedOff', 'OnClientContactChange']
   1211 
   1212     def OnContactLoggedOn(self, charID):
   1213         if self.sr.node and charID == self.sr.node.p.petitionerID:
   1214             self.SetOnline(1)
   1215 
   1216     def OnContactLoggedOff(self, charID):
   1217         if self.sr.node and charID == self.sr.node.p.petitionerID:
   1218             self.SetOnline(0)
   1219 
   1220     def OnClientContactChange(self, charID, online):
   1221         if online:
   1222             self.OnContactLoggedOn(charID)
   1223         else:
   1224             self.OnContactLoggedOff(charID)
   1225 
   1226     def Load(self, node):
   1227         Generic.Load(self, node)
   1228         if node.type != 'my':
   1229             self.SetOnline(getattr(node.p, 'isOnline', 0))
   1230         elif self.sr.Get('onlinestatus', None):
   1231             self.sr.onlinestatus.state = uiconst.UI_HIDDEN
   1232 
   1233     def GetMenu(self):
   1234         self.OnClick()
   1235         return self.sr.node.menu
   1236 
   1237     def SetOnline(self, online):
   1238         if not self.sr.Get('onlinestatus', None):
   1239             self.sr.onlinestatus = Fill(parent=self, width=8, align=uiconst.TORIGHT, color=(1.0, 1.0, 1.0, 0.75), idx=4)
   1240         color = (0.5, 0.0, 0.0)
   1241         if online == 1:
   1242             color = (0.0, 0.5, 0.0)
   1243         if online == 2:
   1244             color = (0.5, 0.25, 0.0)
   1245         self.sr.onlinestatus.SetRGB(*color)
   1246         self.sr.onlinestatus.state = uiconst.UI_DISABLED
   1247 
   1248     def OnDblClick(self, *args):
   1249         p = self.sr.node.p
   1250         sm.StartService('petition').ShowPetition(p)
   1251 
   1252     def GetHeight(_self, *args):
   1253         node, width = args
   1254         node.height = max(24, uix.GetTextHeight(node.label, maxLines=1) + 4)
   1255         return node.height