############################################################################################################################################
#           mainIrcClientFrame
############################################################################################################################################
from qt import *
from ProgxIrcTabWidget import *
from IrcServerConnection import *
from IrcClientChannelFolderDialog import *
from IrcClientOptionsDialog import *
import os.path
from threading import *
from time import *
import sys
from socket import htonl, ntohl
from struct import pack, unpack

class MainIrcClientFrame(QMainWindow):

  def __init__( self, parent = None, name = None ):

    QMainWindow.__init__(self, None,'PROGXRC', Qt.WDestructiveClose)

    #chargement des icones
    self.progxrcIcone = QPixmap("png/mainIcone.png")
    self.couleurIcone = QPixmap("png/couleurs.png")
    self.connectIcone = QPixmap("png/connection.png")
    self.deconIcone = QPixmap("png/disconnect.png")
    self.chanelFolderIcone = QPixmap("png/chanelFolder.png")
    self.chanelListIcone = QPixmap("png/chanelListe.png")
    self.saveTalkIcone = QPixmap("png/saveTalk.png")
    self.sendDccIcone = QPixmap("png/sendDCC.png")
    self.aboutIcone = QPixmap("png/about.png")
    self.dccOptionIcone = QPixmap("png/dccOptns.png")
    self.optionsIcone = QPixmap("png/options.png")
    self.closeCurrentIcone = QPixmap("png/closeCurrent.png")

    self.file = QPopupMenu()
    self.file.insertTearOffHandle()
    self.idConnec = self.file.insertItem( "&Connection", self.connection, Qt.CTRL+Qt.Key_C )
    self.idDeconnec = self.file.insertItem( "&Disconnection", self.connection, Qt.CTRL+Qt.Key_D )

    self.file.insertSeparator()
    self.file.insertItem( "Opt&ions ...", self.option, Qt.CTRL+Qt.Key_O )
    self.file.insertSeparator()
    self.file.insertItem( "&Quit", self.quitter, Qt.CTRL+Qt.Key_Q)

    self.dcc = QPopupMenu(self)
    self.dcc.insertTearOffHandle()
    self.idDccSend = self.dcc.insertItem( "&Send...", self.sendDCC, Qt.ALT+Qt.Key_S )
    self.idDccChat = self.dcc.insertItem( "&Chat...", self.chatDCC, Qt.ALT+Qt.Key_C )
    self.dcc.insertSeparator()
    self.dcc.insertItem( "Optio&n", self.optionDCC, Qt.ALT+Qt.Key_N )

    self.CTCP = QPopupMenu(self)
    self.CTCP.insertTearOffHandle()
    self.CTCP.insertItem( "Ping", self.ping)
    self.CTCP.insertItem( "Time", self.time)
    self.CTCP.insertItem( "Version", self.version)

    self.away = QPopupMenu(self)
    self.away.insertTearOffHandle()
    self.idAwayOn = self.away.insertItem( "On", self.awayOn)
    self.idAwayOff = self.away.insertItem( "Off", self.awayOff)
    self.away.setItemEnabled(self.idAwayOff, FALSE)

    self.commandes = QPopupMenu( self)
    self.commandes.insertTearOffHandle()
    self.idCmdeJoin = self.commandes.insertItem( "Join channel", self.join)
    self.idCmdePart = self.commandes.insertItem( "Part channel", self.part)
    self.idCmdeQuery = self.commandes.insertItem( "Query user", self.query)
    self.idCmdeSendNot = self.commandes.insertItem( "Send notice", self.notice)
    self.idCmdeWhois = self.commandes.insertItem( "Whois user", self.whois)
    self.idCmdeCTCP = self.commandes.insertItem( "Send CTCP", self.CTCP)
    self.idCmdeAway = self.commandes.insertItem( "Set away", self.away)
    self.idCmdeInvite = self.commandes.insertItem( "Invite user", self.invite)
    self.idCmdeBan = self.commandes.insertItem( "Ban user", self.ban)
    self.idCmdeKick = self.commandes.insertItem( "Kick user", self.kick)
    self.idCmdeIgnore = self.commandes.insertItem( "Ignore user", self.ignore)
    self.idCmdeUnignore = self.commandes.insertItem( "Unignore user", self.unignore)
    self.idCmdeNick = self.commandes.insertItem( "Change nick", self.changeNick)
    self.idCmdeQuit = self.commandes.insertItem( "Quit IRC", self.quit)
    
    self.windows = QPopupMenu( self )
    self.idWindowsOptn = self.windows.insertItem( "Options...", self.optionsWindow)
    self.windows.insertSeparator()
    self.idWindowClose = self.windows.insertItem( "Close...", self.closeCurrentTab, Qt.ALT+Qt.Key_Z)
    self.windows.insertSeparator()

    self.About = QPopupMenu( self )
    self.About.insertItem( "About ProgXRC...", self.about)

    self.menu = QMenuBar( self )

    self.menu.insertItem( "&File", self.file )
    self.menu.insertItem( "&DCC", self.dcc )
    self.menu.insertSeparator()
    self.menu.insertItem( "&Commands", self.commandes )
    self.menu.insertItem( "&Windows", self.windows )
    self.menu.insertItem( "&About", self.About )

    self.commandesPop= QPopupMenu()
    
    self.commandesPop.insertTearOffHandle()
    self.commandesPop.insertItem( "Send notice", self.notice)
    self.commandesPop.insertItem( "Invite user", self.invite)
    self.commandesPop.insertItem( "Op user", self.op)
    self.commandesPop.insertItem( "DeOp user", self.deOp)
    self.commandesPop.insertItem( "Voice user", self.voice)
    self.commandesPop.insertItem( "DeVoice user", self.unVoice)
    self.commandesPop.insertItem( "Kick user", self.kick)
    self.commandesPop.insertItem( "Ban user", self.ban)
    self.commandesPop.insertItem( "Unban user", self.unBan)
    self.commandesPop.insertItem( "Ignore user", self.ignore)
    self.commandesPop.insertItem( "Unignore user", self.unignore) 
    
    #####################
    #######################
    ##QpopupMenu pour clike droit :
    self.popUp = QPopupMenu()
    self.popUp.insertTearOffHandle()  
    self.popUp.insertItem( "Whois user", self.whois)
    self.popUp.insertItem( "Query user", self.query)
    self.popUp.insertSeparator()    
    self.popUp.insertItem( "Control", self.commandesPop)
    self.popUp.insertSeparator()    
    self.popUp.insertItem( "CTCP", self.CTCP)   
    self.popUp.insertSeparator()
    self.popUp.insertItem( "DCC", self.dcc)
    ########################
    ########################
    
    self.nickSelected = None 

    self.toolBar = QToolBar("Toolbar", self, QMainWindow.Left)
    self.toolBar.setOrientation(Qt.Vertical)

    self.connectBtn = QToolButton(self.connectIcone, 'Connect', QString.null, self.connection, self.toolBar, 'Connection')
    self.optionBtn = QToolButton(self.optionsIcone, 'Options', QString.null, self.option, self.toolBar,'Options')
    self.chanelFolderBtn = QToolButton(self.chanelFolderIcone, 'Channel folder', QString.null, self.chanFolder, self.toolBar,'Chanel folder')
    self.listChanelBtn = QToolButton(self.chanelListIcone, 'Channel List', QString.null, self.chanList, self.toolBar,'chanel List')
    self.colorsBtn = QToolButton(self.couleurIcone, 'Colors', QString.null, self.couleurs, self.toolBar, 'Colors')
    self.dccSendBtn = QToolButton(self.sendDccIcone, 'DCC Send', QString.null, self.sendDCC, self.toolBar, 'DCC Send')
    self.dccOptnsBtn = QToolButton(self.dccOptionIcone, 'DCC Options', QString.null, self.optionDCC, self.toolBar, 'DCC Options')
    self.aboutBtn = QToolButton(self.aboutIcone, 'About', QString.null, self.about, self.toolBar, 'About')
    self.closeCurrentTabBtn = QToolButton(self.closeCurrentIcone, 'Close current window', QString.null, self.closeCurrentTab, self.toolBar, 'Close current window')

    self.tabWidget = ProgxTabWidget(self)
    self.setCentralWidget(self.tabWidget)

    self.setCaption( "Qt ProgXRC" )
    self.statusBar().message('Ready', 2000)
    self.resize(700, 600)

    #état de la connection 0 = deconnecté 1 = connecté
    self.connected = 0

# à modifier --->
    self.con = IrcServerConnection(self, "localhost", 6667, "Romain GUY", "rguy")
# ---->
    self.dicoMethode = { "privmsg" : self.con.privMsg,    "msg"     : self.temp,           "topic"   : self.con.topic,
                          "kick"   : self.con.kick,       "join"    : self.con.join,       "quit"    : self.connection,
                          "nick"   : self.con.changeNick, "part"    : self.con.part,
                          "mode"   : (self.con.modeChan, self.con.modeUser),
                          "nick"   : self.con.changeNick, "me"      : self.temp,           "notice"  : self.con.notice,
                          "ping"   : self.con.ctcpPing,   "who"     : self.con.who,        "dns"     : self.temp,
                          "sound"  : self.processSound,   "version" : self.con.ctcpVersion,
                          "time"   : self.con.ctcpTime,   "ping"    : self.con.ctcpPing,
                          "image"  : self.processImage,   "whois"   : self.con.whoIs }

    self.queueProcessing = {  "PRIVATE"         : self.processPrivateMessage,
                              "JOIN"            : self.processJoinChannel,
                              "ADDUSER"         : self.processAddUser,
                              "MESSAGE"         : self.processMessage,
                              "WELCOME"         : self.processWelcomeMessage,
                              "IDENTD-REQUEST"  : self.processIdentdRequest,
                              "IDENTD-RESPONSE" : self.processIdentdResponse,
                              "NICK"            : self.processNickChange,
                              "NAMES"           : self.processNames,
                              "SERVER-NOTICE"   : self.processServerNotice,
                              "CHANNEL-NOTICE"  : self.processChannelNotice,
                              "NOTICE"          : self.processNotice,
                              "JOIN-TOPIC"      : self.processJoinTopic,
                              "CHANNEL-TOPIC"   : self.processChannelTopic,
                              "PING"            : self.processPing,
                              "ERROR"           : self.processError,
                              "PART"            : self.processPart,
                              "QUIT"            : self.processQuit,
                              "END-NAMES"       : self.processEndNames,
                              "KICK"            : self.processKick,
                              "AWAY"            : self.processAway,
                              "SET-AWAY"        : self.processSetAway,
                              "CHANGEMODE"      : self.processChangeMode,
                              "SET-BY"          : self.processSetBy,
                              "WHOIS-IS"        : self.processWhoisIs,
                              "WHOIS-CHANS"     : self.processWhoisChans,
                              "WHOIS-SERVER"    : self.processWhoisServer,
                              "WHOIS-TIME"      : self.processWhoisTime,
                              "END-WAITING"     : self.processEndWaiting,
                              "NICK-TAKEN"      : self.processNickTaken
                           }

    self.chans = { "General" : Channel("General", "Status") }

    self.namesListEnded = 1

    #on crée 2 dictionnaire pour pouvoir ajouter et suprimé les canaux dans la menu windows
    self.dicoWindows = {}
    self.dicoWindowsInv = {}

    self.colors = {  0: "#FFFFFF",
                     1: "#000000",
                     2: "#000080",
                     3: "#008000",
                     4: "#FF0000",
                     5: "#870F0F",
                     6: "#C000C0",
                     7: "#FFA313",
                     8: "#FFFF00",
                     9: "#00FF00",
                    10: "#00C0C0",
                    11: "#40FFFF",
                    12: "#0000FF",
                    13: "#FF00FF",
                    14: "#808080",
                    15: "#C0C0C0"  }

    # REGEX
    self.regexTag        = re.compile('(<[^>]+>)')
    self.regexWhiteSpace = re.compile('( {2,})')
    self.regexColor      = re.compile('(\d+)(,\d+)?(.*)')
    self.regexWelcome1   = re.compile(":[^:]+:(.*)")
    self.regexWelcome2   = re.compile(":(\S+)\s+([A-Z]+)\s+(\S+)\s+:(.*)")
    self.regexWelcome3   = re.compile(":\S+\s+\d\d\d\s+\S+\s+([^:]*):(.*)")
    self.regexWelcome4   = re.compile(":(\S+)\s+(\d\d\d)\s+(\S+)\s+(.*)")
    # FIN REGEX

    self.tabWidget.newPrivateTab("General")
    #on ajoute "General" au  menu Windows
    id = self.windows.insertItem( "General")
    QObject.connect(self.windows, SIGNAL("activated (int)"), self.setCurrent)
    self.dicoWindows[id] = "General";
    self.dicoWindowsInv["General"] = id;

    self.connect(self.getLineEdit("General"), SIGNAL("returnPressed()"), self.returnPressed)
    self.connect(self.tabWidget, SIGNAL("currentChanged(QWidget *)"), self.changeTopic)
    #on met les fonction non accessible hors connection en grisée
    self.setProgXrcItemEnabledDisconnect()
    
#------->méthode temporaire pour morceau dico non gérés
  def temp(self):
    pass
#------>

  def quitting(self):
    if self.connected:
      self.connection()
      qApp.quit()

  def tabPressed(self):
    name = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
    edit = self.getLineEdit(name)

    token = ""
    list = re.split('\s*(\S+)\s*', edit.text().latin1())
    list.reverse()
    for token in list:
      if len(token) > 0: break

    if len(token) > 0:
      subList = filter(lambda x: x.startswith(token), [user.name for user in self.chans[name].names])
      if len(subList) > 0:
        edit.setText(edit.text().latin1() + subList[0][len(token):] + " ")

  def returnPressed(self):
    name = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
    text = self.getLineEdit(name).text().latin1()
    if text == "":
      return

    self.getLineEdit(name).setText("")

    if name != "General" :
      if text[0] != "/":
        self.con.privMsg([name], text)
        self.processMessage((self.con.getNick(), name, text))
      else:
        self.sendCommand(text)
    else:
      if text[0] != "/":
        self.getTextView("General").append( """<font color="#FF0000">** You are not on a channel **</font><br>""")
      else:
        self.sendCommand(text)

#---->chgmt   
  def sendCommand(self, cmde):
    #on enlève '/'
    cmde = cmde[1:]
    
    liste = cmde.split(' ')
    if (liste[0]).lower() not in self.dicoMethode.keys(): return

    #utilisation du dico self.dicoMethode
    if (liste[0]).upper() == "MODE":
      if liste[1][0] == '#':
        if len(liste)<4 : return
        fonc = self.dicoMethode[(liste[0]).lower()]
        fonc = fonc[0]
        
        if liste[2][0] not in ['+','-']:return
        
        modeList=[]
        for i in liste[2]:
          modeList.append(i)
          
        userList=[]
        for i in liste[3:]:
          userList.append(i)
        
        fonc(liste[1], modeList, userList, "", "")
        
      else:
        fonc = self.dicoMethode[(liste[0]).lower()]
        fonc = fonc [1]
        if len(liste)<3 : return

        modeList=[]
        for i in liste[2:]:
          if i[0] not in ['+','-']:return
          modeList.append(i)
        
        fonc(liste[1], modeList)
          
    else:
      fonc = self.dicoMethode[(liste[0]).lower()]

      #1 argument
      if (liste[0]).upper() in ["NICK", "VERSION", "TIME", "PING", "SOUND", "IMAGE", "WHOIS"]:
        if len(liste)<2 : return
        fonc(liste[1])
      
      #1 argument liste
      if (liste[0]).upper() in ["JOIN", "PART"]:
        if len(liste)<2 : return
        argList =[]
        for i in liste[1:]:
          if i[0] != '#': i = '#'+i
          argList.append(i)
        
        fonc(argList)
      
      #1argument +facul
      
      if (liste[0]).upper() in ["QUIT"]:
        if len(liste)<1 : return
        why = ' '.join(liste[1:])
        fonc(why)
        #self.connection()
        
      if (liste[0]).upper() in ["TOPIC"]:
        if len(liste)<3 : return
        topic = ' '.join(liste[2:])
        fonc(liste[1], topic)
      
      #2args 1er est une liste
      if (liste[0]).upper() in ["PRIVMSG", "NOTICE"]:
        if len(liste)<3 : return
        argList =[]
        for i in liste[1:-1]:
          argList.append(i)
        fonc(argList, liste[-1])
        
      #2args 2eme est une liste
      if (liste[0]).upper() in ["WHO"]:
        if len(liste)<3 : return
        for i in liste[2:]:
          argList.append(i)
        fonc(liste[1], argList)

  def getTime(self):
     return strftime("[%H:%M:%S] ", localtime())

  def getColor(self, index):
    if index in self.colors:
      return self.colors[index]
    else:
      return "#000000"

  def colorize(self, text):
    colorized = ""

    if '\3' in text:
      lastWasColorized = 0
      for token in re.split('(\3)', text):
        if token == '\3':
          lastWasColorized = 1
        elif lastWasColorized:
          match = self.regexColor.search(token)
          if match is not None:
            colorized += "<font color=\"" + self.getColor(int(match.group(1))) + "\">"
            if match.group(2) is not None:
              colorized += token[len(match.group(1)) + len(match.group(2)):]
            else:
              colorized += token[len(match.group(1)):]
            colorized += "</font>"
          else:
            colorized += token
          lastWasColorized = 0
        else:
          colorized += token
    else:
      colorized = text

    text = ""
    if '\2' in colorized:
      lastWasBold = 0
      for token in re.split('(\2)', colorized):
        if token == '\2':
          if not lastWasBold:
            lastWasBold = 1
            text += "<b>"
          else:
            lastWasBold = 0
            text += "</b>"
        else:
          text += token
    else:
      text = colorized

    colorized = ""
    if 31 in map(ord, text):
      lastWasUnderlined = 0
      for token in re.split('(' + chr(31) + ')', text):
        if token == chr(31):
          if not lastWasUnderlined:
            lastWasUnderlined = 1
            colorized += "<u>"
          else:
            lastWasUnderlined = 0
            colorized += "</u>"
        else:
          colorized += token
    else:
      colorized = text

    return "".join([self.regexTag.match(token) and token or self.regexWhiteSpace.sub(self.whiteSpaceToNonBreakSpace, token) for token in self.regexTag.split(colorized)])

  def whiteSpaceToNonBreakSpace(self, match):
    return "&nbsp;" * len(match.group(0))

  ########################################################################################
  ## GERE LA FILE DE MESSAGES D'ACTIONS
  ########################################################################################

  def processIncoming(self):
    while self.queue.qsize():
      try:
        args = self.queue.get(0)
        msgType = args[0]

        if msgType in self.queueProcessing:
          self.queueProcessing[msgType](args[1:])
      except Queue.Empty:
        pass

  def processPrivateMessage(self, args):
    nick, text = args
    logText = self.getTime() + "<" + nick + "> " + text +'\n'
    
    if ord(text[0]) == 1 and ord(text[-1]) == 1:
      self.processCTCP((nick, nick, text[1:-1]))
    else:
      if not self.tabWidget.contains(nick):
        self.chans[nick.lower()] = Channel(nick, "Private chat")
        self.tabWidget.newPrivateTab(nick)
        self.connect(self.getLineEdit(nick), SIGNAL("returnPressed()"), self.returnPressed)
        
        #on ajoute au menu windows
        val = self.windows.insertItem(nick, 0)
        self.dicoWindows[val] = nick
        self.dicoWindowsInv[nick] = val

      text = text.replace("<", "&lt;")
      text = text.replace(">", "&gt;")
  
      area = self.getTextView(nick)
      match = re.search("(\W|^)" + self.con.getNick() + "(\W|$)", text)
      if match is not None:
        area.append("""<font color="#FF0000">""" + self.getTime() + "<b>&lt;" + nick + "&gt;</b> " + self.colorize(text) + "</font>")
      else:
        area.append(self.getTime() + "<b>&lt;" + nick + "&gt;</b> " + self.colorize(text))
      area.ensureVisible(0, area.contentsHeight())
      
      #ecriture des logs
      fich = open("./logs/" + nick + '.txt','a')
      fich.write(logText)
      fich.close()

  def processCTCP(self, args):
    source, nick, text = args
    if text == "VERSION":
      self.append("General", """<font color="#FF0000">""" + self.getTime() + " [" + nick + " " + text + "]</font>")
      self.con.notice([nick], chr(1) + "VERSION ProgXRC v1.0 Helix-Team" + chr(1))
    elif text == "TIME":
      self.append("General", """<font color="#FF0000">""" + self.getTime() + " [" + nick + " " + text + "]</font>")
      self.con.notice([nick], chr(1) + "TIME " + strftime("%a %b %d %H:%M:%S %Y", localtime()) + chr(1))
    else:
      text, reply = text.split(' ', 1)
      if text == "PING":
        self.append("General", """<font color="#FF0000">""" + self.getTime() + " [" + nick + " " + text + "]</font>")
        self.con.notice([nick], chr(1) + "PING " + reply + chr(1))
      elif text == "ACTION":
        self.append(source, """<font color="#AA00AA">""" + self.getTime() + "* " + nick + " " + reply + "</font>")
      elif text == "SOUND":
        reply += ' '
        file, reply = reply.split(' ', 1)
        if not os.path.exists("./sounds/" + file):
          self.append(source, """<font color="#0000BB">""" + self.getTime() + "* /sound: no such file '" + file + "'</font>")
        else:
          QSound.play("./sounds/" + file)
          self.append(source, """<font color="#FF0000">""" + self.getTime() + "[SOUND]</font>")
          if len(reply) > 0:
            self.append(source, """<font color="#AA00AA">""" + self.getTime() + "* " + nick + " " + reply + "</font>")
      elif text == "IMAGE":
        reply += ' '
        file, reply = reply.split(' ', 1)
        if not os.path.exists("./images/" + file):
          self.append(source, """<font color="#0000BB">""" + self.getTime() + "* /image: no such file '" + file + "'</font>")
        else:
          self.append(source, """<font color="#FF0000">""" + self.getTime() + "[IMAGE]</font>")
          self.getTextView(source).mimeSourceFactory().setFilePath(QStringList("./images/"))
          self.append(source, "<img src=\"" + file + "\"><br>")
          if len(reply) > 0:
            self.append(source, """<font color="#AA00AA">""" + self.getTime() + "* " + nick + " " + reply + "</font>")
      elif text == "DCC":
        type, argument, address, strPort, strSize = reply.split(' ')
        if type == "SEND":
          port     = int(strPort)
          fileSize = long(strSize)
          ipnumber = long(address)
          ip = str((ipnumber >> 24) & 0xFF) + '.' + str((ipnumber >> 16) & 0xFF) + '.' + \
               str((ipnumber >> 8)  & 0xFF) + '.' + str((ipnumber >>  0) & 0xFF)
          box = QMessageBox("Qt -DCC Send-", "Do you accept %s (%d bytes) coming from %s ?" % (argument, fileSize, ip), \
                            QMessageBox.Information, QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton, self)

          dccAccept = DCCAccept(ip, port, argument, size = fileSize)
          dccThread = None

          if box.exec_loop() == QMessageBox.Yes:

            if os.path.exists("./dcc/" + argument):
              obox = QMessageBox("Qt -DCC Send-", "A file called %s already exists. Overwrite it ?" % (argument), \
                                 QMessageBox.Warning, QMessageBox.Yes, QMessageBox.No, QMessageBox.NoButton, self)
              if obox.exec_loop() != QMessageBox.Yes:
                dccThread = threading.Thread(target = dccAccept.abort)

            dccThread = threading.Thread(target = dccAccept.accept)
          else:
            dccThread = threading.Thread(target = dccAccept.abort)

          dccThread.setDaemon(1)
          dccThread.start()

  def processJoinChannel(self, args):
    nick, chan = args
    chan = chan.lower()
    if not self.tabWidget.contains(chan):
      self.chans[chan] = Channel(chan)
      self.tabWidget.newChannelTab(chan)
      self.connect(self.getLineEdit(chan), SIGNAL("returnPressed()"), self.returnPressed)
      self.connect(self.getLineEdit(chan), PYSIGNAL("tabPressed"), self.tabPressed)
      self.connect(self.getUsersList(chan), SIGNAL("rightButtonClicked ( QListBoxItem *, const QPoint & )"), self.rightClickOnList)
      self.connect(self.getUsersList(chan), SIGNAL("selected (const QString&)"), self.preOpenPrivateMessageWin)
    if nick != self.con.getNick():
    #quelqu'un joint le canal
      self.processAddUser((chan, nick))
      self.append(chan, """<font color="#00BB00">""" + self.getTime() + "*** " + nick + " has joined " + chan + """</font>""")
    else:
    #l'utilisateur joint le canal
      if chan[0] == '#': chan = chan[1:]
      val = self.windows.insertItem(chan)
      self.dicoWindows[val] = '#' + chan
      self.dicoWindowsInv['#' + chan] = val;

  def processAddUser(self, args):
    chan, nick = args
    if len(nick) == 0:
      return

    mode = ""
    if nick[0] == "@":
      mode = nick[0]
      nick = nick[1:]
    elif nick[0] == "+":
      mode = nick[0]
      nick = nick[1:]

    list = self.chans[chan.lower()].names
    list.append(User(nick, mode))
    list = list.sort()

    self.displayUsers(chan)

  def processMessage(self, args):
    nick, source, text = args
    logText = self.getTime() + "<" + nick + "> " + text + '\n'

    if ord(text[0]) == 1 and ord(text[-1]) == 1:
      logText = text[1:-1] + '\n'
      self.processCTCP((source, nick, text[1:-1]))
    else:
      text = text.replace("<", "&lt;")
      text = text.replace(">", "&gt;")

      area = self.getTextView(source)
      match = re.search("(\W|^)" + self.con.getNick() + "(\W|$)", text)
      if match is not None:
        area.append("""<font color="#FF0000">""" + self.getTime() + "<b>&lt;" + nick + "&gt;</b> " + self.colorize(text) + "</font>")
      else:
        area.append(self.getTime() + "<b>&lt;" + nick + "&gt;</b> " + self.colorize(text))
      area.ensureVisible(0, area.contentsHeight())
    
    #ecriture des logs
    fich = open("./logs/" + source + '.txt','a')
    fich.write(logText)
    fich.close()

  def processWelcomeMessage(self, args):
    line = args[0]
    area = self.getTextView("General")
    splitter = ""

    if line.find("NOTICE AUTH :") == 0:
      splitter = """<font color="#FF0000">""" + self.getTime() + line[14:] + "</font>"
    elif line.find('PING') == 0:
      match = re.search("^PING :(\d+)", line)
      splitter = """<font color="#00BB00">""" + self.getTime() + "PING ? PONG !</font>"
      self.con.send('PONG ' + match.group(1) + '\r\n')
    else:
      match = self.regexWelcome1.search(line)
      if match is not None:
        match2 = self.regexWelcome2.search(line)
        if match2 is not None:
          if match2.group(2) == "NOTICE":
            splitter = """<font color="#AA00AA">""" + self.getTime() + "-" + match2.group(1) + "- " + match2.group(4) + """</font>"""
        else:
          match2 = self.regexWelcome3.search(line)
          if match2 is not None:
            splitter = match2.group(1) + match2.group(2)
          else:
            splitter = match.group(1)
      else:
        match = self.regexWelcome4.search(line)
        if match is not None:
          splitter = match.group(4)
        else:
          splitter = line

    area.append(self.colorize(splitter))
    area.ensureVisible(0, area.contentsHeight())

  def processIdentdRequest(self, args):
    host = args[0]
    self.append("General", """<font color="#650099">*** Identd request from """ + host[0] + """</font>""")

  def processIdentdResponse(self, args):
    response = args[0]
    self.append("General", """<font color="#650099">*** Identd replied: """ + response + """</font>""")

  def processNames(self, args):
    if self.namesListEnded:
      chan = args[0].lower()
      self.getUsersList(chan).clear()
      self.chans[chan].names = []
      self.namesListEnded = 0

  def processNickChange(self, args):
    oldNick, nick = args
    if oldNick == self.con.getNick():
      self.con.setNick(nick)

    for key in self.tabWidget.dicoTab.keys():
      # si la longueur vaut 2, c'est l'onglet "General" ou un query
      if len(self.tabWidget.dicoTab[key]) > 2:
        list = self.chans[key].names
        for user in list:
          if user.name == oldNick:
            user.name = nick
        list = list.sort()

        self.displayUsers(key)
      self.append(key, """<font color="#00BB00">""" + self.getTime() + "*** " + oldNick + " is now known as " + nick + """</font>""")

  def processServerNotice(self, args):
    server, text = args
    self.append("General", """<font color="#AA00AA">""" + self.getTime() + "-" + server + "- " + text + """</font>""")

  def processChannelNotice(self, args):
    nick, source, message = args
    self.append(source, """<font color="#AA00AA">""" + self.getTime() +  "-" + nick + ":" + source + "- " + message + """</font>""")

  def processNotice(self, args):
    nick, source, message = args
    chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
    if message[0] == chr(1) and message[-1] == chr(1):
      message = message[1:-1]
      index = message.find(' ')
      ctcp = message[:index]
      data = message[index + 1:]
      if ctcp == "VERSION" or ctcp == "TIME":
        self.append(chan, """<font color="#FF0000">""" + self.getTime() +  "[" + nick + " " + ctcp + " reply]: " + data + """</font>""")
      elif ctcp == "PING":
        self.append(chan, """<font color="#FF0000">""" + self.getTime() +  "[" + nick + " " + ctcp + " reply]: " + str(int(time()) - int(data)) + "secs" + """</font>""")
    else:
      self.append(chan, """<font color="#AA00AA">""" + self.getTime() +  "-" + nick + "- " + message + """</font>""")

  def processJoinTopic(self, args):
    chan, topic = args
    chan = chan.lower()
    self.chans[chan].topic = topic
    self.setCaption("Qt ProgXRC - " + chan + " - " + topic)
    self.getTextView(chan).append("""<font color="#00BB00">""" + self.getTime() + """*** Now talking in """ + chan + """</font>""")
    self.append(chan, """<font color="#00BB00">""" + self.getTime() + """*** Topic is '""" + topic + """'</font>""")

  def processChannelTopic(self, args):
    nick, source, topic = args
    source = source.lower()
    self.chans[source].topic = topic
    self.setCaption("Qt ProgXRC - " + source + " - " + topic)
    self.append(source, """<font color="#00BB00">""" + nick + " changes topic to '" + topic + """'</font>""")

  def processPing(self, args):
    text = args[0]
    self.con.send('PONG ' + text + '\r\n')
    self.append("General", """<font color="#00BB00">""" + self.getTime() + "PING ? PONG !</font>")

  def processError(self, args):
    self.append("General", """<font color="#FF0000">[ERROR] The connection is in a wrong state !</font>""")

  def processPart(self, args):
    nick, source = args
    if nick != self.con.getNick():
      source = source.lower()
      self.chans[source].names.remove(User(nick))
      self.displayUsers(source)
      self.append(source, """<font color="#00BB00">""" + self.getTime() + "*** " + nick + " has left " + source + """</font>""")

  def processQuit(self, args):
    nick, text = args
    if nick != self.con.getNick():
      for chan in self.chans.keys():
        list = self.chans[chan].names
        try:
          index = list.index(User(nick))
          del list[index]
          self.displayUsers(chan)
          self.append(chan, """<font color="#0000BB">""" + self.getTime() + "*** " + nick + " has quit IRC" + (len(text) == 0 and " " or (" (" + text + ")")) + """</font>""")
        except:
          pass

  def processEndNames(self, args):
    self.namesListEnded = 1

  def processSound(self, sound):
    chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
    if not os.path.exists("./sounds/" + sound):
      self.append(chan, """<font color="#0000BB">""" + self.getTime() + "* /sound: no such file '" + sound + "'</font>")
    else:
      QSound.play("./sounds/" + sound)
      self.con.ctcpSound(chan, sound)
      self.append(chan, """<font color="#FF0000">""" + self.getTime() + "[SOUND]</font>")

  def processImage(self, image):
    chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
    if not os.path.exists("./images/" + image):
      self.append(chan, """<font color="#0000BB">""" + self.getTime() + "* /image: no such file '" + image + "'</font>")
    else:
      self.con.ctcpImage(chan, image)
      self.append(chan, """<font color="#FF0000">""" + self.getTime() + "[IMAGE]</font>")
      self.getTextView(chan).mimeSourceFactory().setFilePath(QStringList("./images/"))
      self.append(chan, "<img src=\"" + image + "\"><br>")

  def processKick(self, args):
    nick, source, arg, text = args
    self.append(source, """<font color="#0000BB">""" + self.getTime() + "*** " + arg + " was kicked by " + nick + (len(text) == 0 and " " or (" (" + text + ")")) + "</font>")
    if arg == self.con.getNick():
      chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
      self.tabWidget.showPage(self.getTextView(chan).parentWidget().parentWidget())
      self.closeCurrentTab()
    else:
      self.processQuit((arg, "kicked"))

  def processAway(self, args):
    nick, text = args
    chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
    self.append(chan, "* " + nick + " is away: " + text)

  def processSetAway(self, args):
    text = args[0]
    self.append("General", """<font color="#0000BB">""" + self.getTime() + "*** " + text + "</font>")

  def processChangeMode(self, args):
    sourceNick, source, arg = args
    modes, nicks = arg.split(' ', 1)
    modeChangeType = modes[0]
    modes = modes[1:]

    i = 0
    source = source.lower()
    list = self.chans[source].names

    for nick in nicks.split(' '):
      try:
        index = list.index(User(nick))
        if modeChangeType == '+':
          if modes[i] == 'v':
            list[index].mode = "+"
          elif modes[i] == 'o':
            list[index].mode = "@"
        else:
          list[index].mode = ""
        i += 1
      except:
        pass

    self.chans[source].names.sort()
    self.displayUsers(source)
    self.append(source, """<font color="#00BB00">""" + self.getTime() + "*** " + sourceNick + " sets mode: " + arg + "</font>")

  def processSetBy(self, args):
    source, nick, secs = args
    self.append(source, """<font color="#00BB00">""" + self.getTime() + "*** Set by " + nick + " on " + ctime(int(secs)) + "</font>")

  def processWhoisIs(self, args):
    nick, identd, host, star, text = args
    self.append("General", """<font color="#00BB00">""" + self.getTime() + nick + " is " + identd + "@" + host + " " + star + " " + text + "</font>")

  def processWhoisChans(self, args):
    nick, chans = args
    self.append("General", """<font color="#00BB00">""" + self.getTime() + nick + " on " + chans + "</font>")

  def processWhoisServer(self, args):
    nick, server, version = args
    self.append("General", """<font color="#00BB00">""" + self.getTime() + nick + " using " + server + " " + version + "</font>")

  def processWhoisTime(self, args):
    nick, idle, arrival, text = args
    minutes = str(int(int(idle) / 60))
    seconds = str(int(idle) % 60)
    self.append("General", """<font color="#00BB00">""" + self.getTime() + nick + " has been idle " + minutes + "mins " + seconds + "secs " + ", signed on " + ctime(int(arrival)) + "</font>")

  def processEndWaiting(self, args):
    self.append("General", """<font color="#00BB00">""" + self.getTime() + "You can now try another connection attempt...</font>")

  def processNickTaken(self, args):
    nick, message = args
    chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
    self.append(chan, """<font color="#FF0000">""" + self.getTime() + "*** " + nick + " " + message + "</font>")

  ########################################################################################
  ## FIN DE LA GESTION DE QUEUE
  ########################################################################################

  ########################################################################################
  ## ACCESSEURS GUI
  ########################################################################################

  def getTextView(self, source):
    return self.tabWidget.dicoTab[source.lower()][0]

  def getLineEdit(self, source):
    return self.tabWidget.dicoTab[source.lower()][1]

  def getUsersList(self, source):
    return self.tabWidget.dicoTab[source.lower()][2]

  def displayUsers(self, chan):
    list = self.getUsersList(chan)
    list.clear()

    for user in self.chans[chan].names:
      if user.mode == "@":
        list.insertItem(ProgxOperatorListItem(user.mode + user.name))
      elif user.mode == "+":
        list.insertItem(ProgxVoiceListItem(user.mode + user.name))
      else:
        list.insertItem(user.mode + user.name)

  def append(self, target, text):
    view = self.getTextView(target)
    view.append(self.colorize(text))
    view.ensureVisible(0, view.contentsHeight())

  ########################################################################################
  ## FIN DES ACCESSEURS GUI
  ########################################################################################

  def preOpenPrivateMessageWin(self, nick):
    nick = nick.latin1()
    if nick[0] == '+' or nick[0] == '@':
      nick = nick[1:]
    self.openPrivateMessageWin(nick)

  def openPrivateMessageWin(self, nick):
    self.tabWidget.newPrivateTab(nick)

    if not nick.lower() in self.chans.keys():
      self.connect(self.getLineEdit(nick), SIGNAL("returnPressed()"), self.returnPressed)
      self.chans[nick] = Channel(nick, "Private chat")

      #on ajoute au menu windows
      val = self.windows.insertItem(nick)
      self.dicoWindows[val] = nick
      self.dicoWindowsInv[nick] = val

    self.changeTopic(None)

  def rightClickOnList(self, boxItem, Qpoint):
    if boxItem != None :
      self.nickSelected = boxItem.text()

    self.popUp.popup(Qpoint) 

  def changeTopic(self, widget):
    key = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
    if key in self.chans:
      self.setCaption("Qt ProgXRC - " + key + " - " + self.chans[key].topic)
      
  def setProgXrcItemEnabledConnect(self):
      self.file.setItemEnabled( self.idConnec, FALSE )
      self.file.setItemEnabled( self.idDeconnec, TRUE)
      self.dcc.setItemEnabled(self.idDccSend, TRUE)
      self.dcc.setItemEnabled(self.idDccChat, TRUE)
      self.commandes.setItemEnabled(self.idCmdeJoin, TRUE)
      self.commandes.setItemEnabled(self.idCmdePart , TRUE)
      self.commandes.setItemEnabled(self.idCmdeQuery , TRUE)
      self.commandes.setItemEnabled(self.idCmdeSendNot , TRUE)
      self.commandes.setItemEnabled(self.idCmdeWhois , TRUE)
      self.commandes.setItemEnabled(self.idCmdeCTCP , TRUE)
      self.commandes.setItemEnabled(self.idCmdeAway , TRUE)
      self.commandes.setItemEnabled(self.idCmdeInvite , TRUE)
      self.commandes.setItemEnabled(self.idCmdeBan , TRUE)
      self.commandes.setItemEnabled(self.idCmdeKick , TRUE)
      self.commandes.setItemEnabled(self.idCmdeIgnore , TRUE)
      self.commandes.setItemEnabled(self.idCmdeUnignore , TRUE)
      self.commandes.setItemEnabled(self.idCmdeNick , TRUE)
      self.commandes.setItemEnabled(self.idCmdeQuit, TRUE)
      self.windows.setItemEnabled(self.idWindowClose, TRUE)
      
  def setProgXrcItemEnabledDisconnect(self):
      self.file.setItemEnabled( self.idDeconnec, FALSE )
      self.file.setItemEnabled( self.idConnec, TRUE )
      self.dcc.setItemEnabled(self.idDccSend, FALSE)
      self.dcc.setItemEnabled(self.idDccChat, FALSE)
      self.commandes.setItemEnabled(self.idCmdeJoin, FALSE)
      self.commandes.setItemEnabled(self.idCmdePart , FALSE)
      self.commandes.setItemEnabled(self.idCmdeQuery , FALSE)
      self.commandes.setItemEnabled(self.idCmdeSendNot , FALSE)
      self.commandes.setItemEnabled(self.idCmdeWhois , FALSE)
      self.commandes.setItemEnabled(self.idCmdeCTCP , FALSE)
      self.commandes.setItemEnabled(self.idCmdeAway , FALSE)
      self.commandes.setItemEnabled(self.idCmdeInvite , FALSE)
      self.commandes.setItemEnabled(self.idCmdeBan , FALSE)
      self.commandes.setItemEnabled(self.idCmdeKick , FALSE)
      self.commandes.setItemEnabled(self.idCmdeIgnore , FALSE)
      self.commandes.setItemEnabled(self.idCmdeUnignore , FALSE)
      self.commandes.setItemEnabled(self.idCmdeNick , FALSE)
      self.commandes.setItemEnabled(self.idCmdeQuit, FALSE)
      self.windows.setItemEnabled(self.idWindowClose, FALSE)

  def connection(self, msg = ""):
    if self.con.isWaitingFor():
      self.getTextView("General").append("""<font color="#00BB00">""" + self.getTime() + "Still waiting...</font>""")
      self.getTextView("General").ensureVisible(0, self.getTextView("General").contentsHeight())
    else:
      if not self.connected:
        self.getTextView("General").append("""<br><font color="#BB00BB">""" + self.getTime() + "Attempting to connect to server...</font>""")
        self.getTextView("General").ensureVisible(0, self.getTextView("General").contentsHeight())
        if self.con.connectIrc():
          self.connectBtn.setPixmap(self.deconIcone)
          self.connected = 1
          self.setProgXrcItemEnabledConnect()
        elif self.con.isWaitingFor():
          self.getTextView("General").append("""<font color="#00BB00">""" + self.getTime() + "Waiting for 30 seconds...</font>""")
          self.getTextView("General").ensureVisible(0, self.getTextView("General").contentsHeight())
        else:
          self.getTextView("General").append("""<font color="#FF0000">[ERROR] The connection is in a wrong state !</font>""")
          self.getTextView("General").ensureVisible(0, self.getTextView("General").contentsHeight())
      else:
        self.append("General", """<br><font color="#BB00BB">""" + self.getTime() + "Disconnected</font>")
        self.con.quit(str(msg))
        # le message QUIT :message provoque la fermeture du socket par le serveur
        # nous ne devons pas le faire nous même
        # self.con.closeConnection()
        self.connectBtn.setPixmap(self.connectIcone)
        self.connected = 0
        self.setProgXrcItemEnabledDisconnect()

        for chan in self.chans.keys():
          if chan != "General":
            self.tabWidget.showPage(self.getTextView(chan).parentWidget().parentWidget())
            self.closeCurrentTab(part = 0)

  def option(self):
    options = IrcClientOptionsDialog(self)

  def quitter(self):
    pass
  def adresses(self):
    pass
  def couleurs(self):
    pass
  def police(self):
    pass
  def alias(self):
    pass
  def sendDCC(self):
    pass
  def chatDCC(self):
    pass
  def optionDCC(self):
    pass
  def popups(self):
    pass
  def windows(self):
    pass

  def ping(self):
    if self.nickSelected == None :
    
      tuple = QInputDialog.getText("Qt -Ping-", "Enter Nickname", None, self)
      if tuple[1]:#on a cliqué sur ok
        self.con.ctcpPing(tuple[0].latin1())
    else:
      nick = self.nickSelected.latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      self.nickSelected = None
      self.con.ctcpPing(nick)
      
  def time(self):
    if self.nickSelected == None :

      tuple = QInputDialog.getText("Qt -Time-", "Enter Nickname", None, self)
      if tuple[1]:#on a cliqué sur ok
        self.con.ctcpTime(tuple[0].latin1())
    else:
      nick = self.nickSelected.latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      self.nickSelected = None
      self.con.ctcpTime(nick)

  def version(self):
    if self.nickSelected == None :

      tuple = QInputDialog.getText("Qt -Version-", "Enter Nickname", None, self)
      if tuple[1]:#on a cliqué sur ok
        self.con.ctcpVersion(tuple[0].latin1())
    else:
      nick = self.nickSelected.latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      self.nickSelected = None
      self.con.ctcpVersion(nick) 

  def awayOn(self):
    tuple = QInputDialog.getText("Qt -Away-", "Enter reason", None, self)
    if tuple[1]:#on a cliqué sur ok
      self.con.away(tuple[0].latin1())
      self.away.setItemEnabled(self.idAwayOn, FALSE)
      self.away.setItemEnabled(self.idAwayOff, TRUE)

  def awayOff(self):
    self.con.back()
    self.away.setItemEnabled(self.idAwayOn, TRUE)
    self.away.setItemEnabled(self.idAwayOff, FALSE)

  def join(self):
    tuple = QInputDialog.getText("Qt -Join a Channel-", "Enter channel name", None, self)
    if tuple[1]:
      self.con.join([e[0] == "#" and e or "#" + e for e in string.split(tuple[0].latin1().lower(), ", ")])

  def setCurrent(self, id) :
    if (id != self.idWindowClose and id != self.idWindowsOptn):
      #on entre ici uniquement si lon a cliké sur un chanel et non option ou quitter
      #on récupère le label de la page courrante
      current = self.tabWidget.tabLabel(self.tabWidget.currentPage())
      
      #on affiche la page voulu en affichant la fenetre grand mère ...
      self.tabWidget.showPage(self.getTextView(self.dicoWindows[id]).parentWidget().parentWidget())
      #Si la page était un dialogue en privé il ne faut affiché que la fenetre mère
      #cf construction fenetre dialogue privé
      #Donc si le nom de la fentre courante n'a pas changé on affiche la fenetre mère :
      
      if (current != self.dicoWindows[id]):
        self.tabWidget.showPage(self.getTextView(self.dicoWindows[id]).parentWidget())
    
  def part(self):
    tuple = QInputDialog.getText("Qt -Part a Channel-", "Enter channel name", None, self)
    if tuple[1]:
      teuteu = [e[0] == "#" and e or "#" + e for e in string.split(tuple[0].latin1().lower(), ", ")]
      lowerchans = map(lambda s: s.lower(), self.chans.keys())
      for miniteuteu in teuteu:
        if miniteuteu in lowerchans:
          self.tabWidget.showPage(self.getTextView(miniteuteu).parentWidget().parentWidget())
          self.closeCurrentTab()
          #closeCurrent() le fait pour nous
          #self.con.part([miniteuteu])
        else:
          self.errorBox = QMessageBox("Qt -Error !-", "Unkown channel name : " + miniteuteu, QMessageBox.Warning, QMessageBox.Ok, QMessageBox.NoButton, QMessageBox.NoButton, self)
          self.errorBox.show()

  def query(self):
    nick = ""

    if self.nickSelected == None :
      tuple = QInputDialog.getText("Qt -Query user-", "Enter nickname and message", None, self)
      i = 0
      for j in (tuple[0]).latin1():
        if j == ' ':
          break
        i = i + 1
        
      nick = ((tuple[0]).latin1())[:i]
      msg = ((tuple[0]).latin1())[i + 1:]
      if nick[0] == '+' or nick[0] == '@':
        nick = nick[1:]
    else:
      nick = (self.nickSelected).latin1()
      if nick[0] == '@' or nick[0] == '+':
        nick = nick[1:]
      tuple = QInputDialog.getText("Qt -Query user-", "Enter message for " + nick, None, self)
      msg = ((tuple[0]).latin1())

    self.nickSelected = None

    if tuple[1]:
      self.con.privMsg([nick], msg)
      msg = self.getTime() + '<b>&lt;' + self.con.getNick() + '&gt;</b> ' + msg
      self.openPrivateMessageWin(nick)
      self.append(nick, msg) 
        
  def notice(self):
    if  self.nickSelected == None:

      tuple = QInputDialog.getText("Qt -Notice-", "Enter nickname and message", None, self)
      i = 0
      for j in str(tuple[0]):
        if j == ' ':break
        i = i+1
        
      nick = str(tuple[0])[:i]
      msg = str(tuple[0])[i+1:]
    else:
      nick = (self.nickSelected).latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      tuple = QInputDialog.getText("Qt -Notice-", "Enter message for " + nick, None, self)
      msg = ((tuple[0]).latin1())

    self.nickSelected = None      
    
    if tuple[1]:
      self.con.notice([nick], msg)
      
  def whois(self):
    if self.nickSelected == None :    
      tuple = QInputDialog.getText("Qt -Whois-", "Enter nick", None, self)
      if tuple[1]:
        l=((tuple[0]).latin1()).split(' ')
        nick = l[0] 
    else:
      nick = (self.nickSelected).latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      
        
    self.con.whoIs(nick)
    self.nickSelected = None

  def invite(self):
    pass
    
  def op(self):
    if self.nickSelected == None:
      tuple = QInputDialog.getText("Qt -Op user-", "Enter nick and channel", None, self)
      if tuple[1]:
        l = ((tuple[0]).latin1()).split(' ')
        nick = l[0]
        chan = l[1]
        if chan[0] != '#': chan = '#' + chan
        self.con.modeChan(chan,['+o'],[nick])
    else:
      nick = (self.nickSelected).latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
      self.nickSelected = None
      self.con.modeChan(chan,['+o'],[nick])
    
  def deOp(self):
    if self.nickSelected == None:
      tuple = QInputDialog.getText("Qt -DeOp user-", "Enter nick and channel", None, self)
      if tuple[1]:
        l=((tuple[0]).latin1()).split(' ')
        nick = l[0]
        chan = l[1]
        if chan[0] != '#': chan = '#' + chan
        self.con.modeChan(chan,['-o'],[nick])
    else:
      nick = (self.nickSelected).latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
      self.nickSelected = None
      self.con.modeChan(chan,['-o'],[nick])

  def ban(self):
    if self.nickSelected == None:
      tuple = QInputDialog.getText("Qt -Ban user-", "Enter nick and channel", None, self)
      if tuple[1]:
        l=((tuple[0]).latin1()).split(' ')
        nick = l[0]
        chan = l[1]
        if chan[0] != '#': chan = '#' + chan
        self.con.modeChan(chan,['+b'],[nick])
    else:
      nick = (self.nickSelected).latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
      self.nickSelected = None
      self.con.modeChan(chan,['+b'],[nick])
      
  def unBan(self):
    if self.nickSelected == None:
      tuple = QInputDialog.getText("Qt -unBan user-", "Enter nick and channel", None, self)
      if tuple[1]:
        l=((tuple[0]).latin1()).split(' ')
        nick = l[0]
        chan = l[1]
        if chan[0] != '#': chan = '#' + chan
        self.con.modeChan(chan,['-b'],[nick])
    else:
      nick = (self.nickSelected).latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
      self.nickSelected = None
      self.con.modeChan(chan,['-b'],[nick])
          
  def voice(self):
    if self.nickSelected == None:
      tuple = QInputDialog.getText("Qt -Voice user-", "Enter nick and channel", None, self)
      if tuple[1]:
        l=((tuple[0]).latin1()).split(' ')
        nick = l[0]
        chan = l[1]
        if chan[0] != '#': chan = '#' + chan
        
        self.con.modeChan(chan,['+v'],[nick])
    else:
      nick = (self.nickSelected).latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
      self.nickSelected = None
      self.con.modeChan(chan,['+v'],[nick])
      
  def unVoice(self):
    if self.nickSelected == None:
      tuple = QInputDialog.getText("Qt -unVoice user-", "Enter nick and channel", None, self)
      if tuple[1]:
        l=((tuple[0]).latin1()).split(' ')
        nick = l[0]
        chan = l[1]
        if chan[0] != '#': chan = '#' + chan
        self.con.modeChan(chan,['-v'],[nick])
        
    else:
      nick = (self.nickSelected).latin1()
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
      self.con.modeChan(chan,['-v'],[nick])
      self.nickSelected = None

  def kick(self):
    if self.nickSelected == None:
    
      tuple = QInputDialog.getText("Qt -Kick user-", "Enter nick, channel and comment", None, self)
      if tuple[1]:
        comment = ""  
        l=((tuple[0]).latin1()).split(' ')
        nick = l[0]
        chan = l[1]
        for word in l[2:]: comment += word +' '
        comment = comment[:-1]
    else:
      nick = self.nickSelected.latin1()
      chan = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
      
      self.nickSelected = None
      if nick[0] == '@' or nick[0] == '+': nick = nick[1:]
      
      tuple = QInputDialog.getText("Qt -Kick "+ nick + " from "+ chan + "-", "Enter comment", None, self)
      if tuple[1]:
        comment = tuple[0].latin1()
        
    if tuple[1]:    
      if chan[0] != '#': chan = '#' + chan
      self.con.kick(chan, nick, comment) 

  def ignore(self):
    pass
  def unignore(self):
    pass
  def changeNick(self):
    tuple = QInputDialog.getText("Qt -Change nick-", "Enter your new nickname", None, self)
    if tuple[1] and self.connected:
      self.con.changeNick(tuple[0].latin1())
      
  def quit(self):
    tuple = QInputDialog.getText("Qt -Quitting IRC-", "Enter reason", None, self)
    if tuple[1] and self.connected:
      self.connection(tuple[0].latin1())

  def optionsWindow(self):
    pass
  
  def about(self):
    splash = ProgxSplashScreen(self)
    splash.show()

  def chanFolder(self):
    channelFolderDialog = IrcClientChannelFolderDialog(self, self.con)

  def chanList(self):
    pass

  def closeCurrentTab(self, part = 1):
    key = self.tabWidget.tabLabel(self.tabWidget.currentPage()).latin1()
    if part:
      self.con.part([key])
    if key != 'General':
      del self.chans[key]
      
      id = self.dicoWindowsInv[key]
      del self.dicoWindowsInv[key]
      del self.dicoWindows[id]
      self.windows.removeItem(id)

      self.tabWidget.closeCurrentTab()

class ProgxOperatorListItem(QListBoxText):
  def __init__(self, text):
    QListBoxText.__init__(self, text)

  def paint(self, painter):
    painter.setPen(QColor(255, 0, 0))
    QListBoxText.paint(self, painter)

class ProgxVoiceListItem(QListBoxText):
  def __init__(self, text):
    QListBoxText.__init__(self, text)

  def paint(self, painter):
    painter.setPen(QColor(0, 160, 30))
    QListBoxText.paint(self, painter)

class Channel:
  def __init__(self, name, topic = ""):
    self.name  = name
    self.names = []
    self.topic = topic

class User:
  def __init__(self, name, mode = ""):
    self.name = name
    self.mode = mode

  def __eq__(self, item):
    return self.name == item.name

  def __lt__(self, item):
    if self.mode != "" and item.mode != "" and self.mode != item.mode:
      return self.mode == '@'
    else:
      return (self.mode + self.name) < (item.mode + item.name)

  def __gt__(self, item):
    if self.mode != "" and item.mode != "" and self.mode != item.mode:
      return self.mode == '+'
    else:
      return (self.mode + self.name) > (item.mode + item.name)

class ProgxSplashScreen(QDialog):
  def __init__(self, parent):
    QDialog.__init__(self, parent, "", TRUE, Qt.WStyle_Customize | Qt.WStyle_NoBorderEx)
    self.image = QLabel(self)
    self.image.setPixmap(QPixmap("./png/aboutLogo.png"))
    self.image.setMinimumSize(250, 250)
    self.image.setMaximumSize(250, 250)
    self.showHelix = 0
    self.parent = parent

  def focusOutEvent(self, event):
    self.close()

  def keyPressEvent(self, event):
    if not self.showHelix:
      self.image.setPixmap(QPixmap("./png/HelixTeam.png"))
      self.image.setMinimumSize(600, 453)
      self.image.setMaximumSize(600, 453)
      self.setGeometry(self.parent.x() + (self.parent.width() - 600) / 2, \
                       self.parent.y() + (self.parent.height() - 453) / 2, \
                       600, 453)
      self.showHelix = 1
    else:
      self.close()

class DCCAccept:
  def __init__(self, ip, port, fileName, size = -1):
    self.ip       = ip
    self.port     = port
    self.fileName = fileName
    self.fileSize = size

  def struct2long(self, val):
    return unpack('l', val)[0]

  def long2struct(self, val):
    return pack('l', val)

  def struct2bytes(self, val):
    val = map(None, unpack('b' * 4, val))
    val.reverse()
    return val

  def bytes2struct(self, val):
    val = map(None, val)
    val.reverse()
    return pack('b' * 4, val[0], val[1], val[2], val[3])

  def abort(self):
    dcc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    dcc.connect((self.ip, self.port))
    dcc.close()

  def accept(self):
    dcc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    dcc.connect((self.ip, self.port))

    count = 0
    file = open("./dcc/" + self.fileName, "wb")

    progress = QProgressDialog("Receiving file...", "&Abort DCC", self.fileSize, None, "progress", FALSE)

    while 1:
      data = dcc.recv(4096)
      if not data: break
      count += len(data)
      progress.setProgress(count)
      qApp.processEvents()
      if progress.wasCancelled(): break
      dcc.send(self.long2struct(htonl(count)))
      file.write(data)

    progress.setProgress(self.fileSize)

    file.close()
    dcc.close()