示例#1
0
 def NextStep(self):
  self.DebugClientSocket = socket.socket()
  self.DebugClientSocket.connect(("127.0.0.1",self.port))    
  self.DebugClientSocket.send("s".encode("cp1251"))
  a = self.DebugClientSocket.recv(self.bufsize)  # Получаем путь текущего исходника.
  sourcename = a.decode("cp1251")
  self.DebugClientSocket.send("recieved".encode("cp1251"))  
  a = self.DebugClientSocket.recv(self.bufsize)  # Получаем номер строки.
  line = a.decode("cp1251")
  self.DebugClientSocket.send("recieved".encode("cp1251"))
  self.DebugClientSocket.close()

  if self.wLocalVars is not None and self.wLocalVars.isVisible():
   self.wLocalVars.GetCurrentStateLocalVars()

  if self.StackWindow is not None and self.StackWindow.isVisible():
   self.StackWindow.GetCurrentStack()

  if self.WatchWindow is not None and self.WatchWindow.isVisible():
   self.WatchWindow.GetCurrentStateWatchedVars()

  if sourcename == "fail":
   w = WaitBreakpoint(self)
   w.start()
   return

  found = False
  for i in range(len(self.tabs.paths)):
   if self.tabs.paths[i] == sourcename:
    self.tabs.setCurrentIndex(i)
    sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                      sci.SCI_MARKERDELETEALL,1,0)
    self.tabs.editors[self.tabs.currentIndex()].editor.setCursorPosition(int(line)-1,1)
    sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                      sci.SCI_MARKERADD,int(line)-1,1)
    found = True

  if not os.access(sourcename,os.F_OK):
   self.StopDebug()
   return

  if found == False:
   sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                     sci.SCI_MARKERDELETEALL,1,0)
   project.TabWithEditor(self,sourcename,int(line)-1,1)
示例#2
0
 def GoOn(self):
  self.waitbreak = WaitBreakpoint(self)
  self.waitbreak.start()
示例#3
0
 def SetOrUnsetBreakpoint(self):
  global sci

  if self.tabs.count() > 0:
   line,index = self.tabs.editors[self.tabs.currentIndex()].editor.getCursorPosition()
   # В данном файле точек останова еще не было.
   if self.tabs.paths[self.tabs.currentIndex()] not in self.tabs.breakpoints.keys():
    if self.isdebug:
     self.DebugClientSocket = socket.socket()
     self.DebugClientSocket.connect(("127.0.0.1",self.port))
     self.DebugClientSocket.send("bp".encode("cp1251"))
     a = self.DebugClientSocket.recv(self.bufsize)
     p = self.tabs.paths[self.tabs.currentIndex()]
     self.DebugClientSocket.send(p.encode("cp1251"))
     a = self.DebugClientSocket.recv(self.bufsize)
     p = str(line+1)
     self.DebugClientSocket.send(p.encode("cp1251"))

     a = self.DebugClientSocket.recv(self.bufsize)
     line = int(a.decode("cp1251"))
     self.DebugClientSocket.send("ok".encode("cp1251"))

     # Работа программы должна возобновляться программно, но
     # не из редактора, а из сервера отладки kdbg.exe!
     # Очень странно. Пока с этим не разобрался.
     a = self.DebugClientSocket.recv(self.bufsize)
     self.DebugClientSocket.send("ok".encode("cp1251"))
     a = a.decode("cp1251")
     if a == "go":
      w = WaitBreakpoint(self)
      w.start()
     else:
      self.DebugClientSocket.close()

    self.tabs.breakpoints[self.tabs.paths[self.tabs.currentIndex()]] = [line]
    sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                      sci.SCI_MARKERADD,line,0)
    return
   else:
    # В данном файле точки останова были, но в текущей строке их нет.
    if line not in self.tabs.breakpoints[self.tabs.paths[self.tabs.currentIndex()]]:
     if self.isdebug:
      self.DebugClientSocket = socket.socket()
      self.DebugClientSocket.connect(("127.0.0.1",self.port))
      self.DebugClientSocket.send("bp".encode("cp1251"))
      a = self.DebugClientSocket.recv(self.bufsize)
      p = self.tabs.paths[self.tabs.currentIndex()]
      self.DebugClientSocket.send(p.encode("cp1251"))
      a = self.DebugClientSocket.recv(self.bufsize)
      p = str(line+1)
      self.DebugClientSocket.send(p.encode("cp1251"))

      a = self.DebugClientSocket.recv(self.bufsize)
      line = int(a.decode("cp1251"))
      self.DebugClientSocket.send("ok".encode("cp1251"))

      # Работа программы должна возобновляться программно, но
      # из редактора, а из сервера отладки kdbg.exe!
      # Очень странно. Пока с этим не разобрался.
      a = self.DebugClientSocket.recv(self.bufsize)
      self.DebugClientSocket.send("ok".encode("cp1251"))
      a = a.decode("cp1251")
      if a == "go":
       w = WaitBreakpoint(self)
       w.start()
      else:
       self.DebugClientSocket.close()

     self.tabs.breakpoints[self.tabs.paths[self.tabs.currentIndex()]].append(line)
     sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                       sci.SCI_MARKERADD,line,0)
    else:
     # В данной строке точка останова уже есть.
     sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                       sci.SCI_MARKERDELETE,line,0)
     self.tabs.breakpoints[self.tabs.paths[self.tabs.currentIndex()]].remove(line)

     if self.isdebug:
      self.DebugClientSocket = socket.socket()
      self.DebugClientSocket.connect(("127.0.0.1",self.port))
      self.DebugClientSocket.send("dbp".encode("cp1251"))
      a = self.DebugClientSocket.recv(self.bufsize)

      p = self.tabs.paths[self.tabs.currentIndex()]
      self.DebugClientSocket.send(p.encode("cp1251"))
      a = self.DebugClientSocket.recv(self.bufsize)
      p = str(line+1)
      self.DebugClientSocket.send(p.encode("cp1251"))
      self.DebugClientSocket.close()
示例#4
0
class MainWindow(QtGui.QMainWindow): 
 tabs             = None  # Вкладки с открытыми файлами
 ListOfFiles      = None  # Окно со списком файлов
 ArgList          = None  # Окно аргументов командной строки
 wLocalVars       = None  # Окно локальных переменных
 StackWindow      = None  # Окно стека вызовов
 WatchWindow      = None  # Окно с отслеживаемыми переменными
 OutputWindow     = None  # Лог компиляции и сообщений
 ProcessWindow    = None  # Окно, означающее начало компиляции или теста
 SetWindow        = None  # Окно общих настроек
 PrjSetWindow     = None  # Окно настроек проекта
 BplWindow        = None  # Окно со списком точек останова

 # Пункты меню
 NewPrjItem            = None
 OpenPrjItem           = None
 ExitItem              = None
 ListOfFilesItem       = None
 ArgListItem           = None
 LocalVarListItem      = None
 WatchVarListItem      = None
 AddToWatchVarListItem = None
 StackItem             = None
 BuildFileItem         = None
 BuildPrjItem          = None
 TestFileItem          = None
 TestPrjItem           = None
 EditorItem            = None
 CompilerItem          = None
 RunItem               = None
 SetupItem             = None
 StartDebugItem        = None
 StopDebugItem         = None
 BreakpointItem        = None
 NextStepItem          = None
 GoOnItem              = None
 BplItem               = None
 SettingsItem          = None

 SettingsMenu          = None
 FileMenu              = None

 ProjectType     = None
 ProjectVersion  = None
 CurrentFile     = None

 Timer           = None

 ProjectTypeGroup    = None
 ProjectVersionGroup = None

 CuiItem = None
 GuiItem = None
 DllItem = None
 LibItem = None
 ObjItem = None

 DebugPrjItem   = None
 ReleasePrjItem = None

 test_process    = None 
 compile_process = None
 
 DebugClientSocket = None
 port = 42282

 bufsize = 1024

 # waitbreak используется для ожидания срабатывания точки останова.
 # Отдельный объект нужен для того, чтобы избежать блокировки редактора.
 waitbreak = None

 isdebug = False # Сейчас отладка?

 def __init__(self):
  QtGui.QMainWindow.__init__(self)
  config.LoadConfigFile()
  self.setGeometry(40,80,500,400)
  self.setWindowTitle("Kwinta")

  # Код странный. GetSysColor возвращает цвет в перевернутом виде.
  # Впечатление такое, что компоненты цвета меняются порядком два раза
  # потому и работает. Вобщем, работает, н оя не очень понимаю как. :)
  color = win32api.GetSysColor(win32con.COLOR_BTNFACE)
  hexstr = hex(color)[2:]
  b = int(hexstr[4:],16)
  g = int(hexstr[2:4],16)
  r = int(hexstr[:2],16)
  color = win32api.RGB(r,g,b)

  MainMenu = self.menuBar();
  self.InitMainMenu(MainMenu)

  self.SetNewColor((48,84,120))
  statusbar = self.statusBar()

  self.ProjectType = QtGui.QLabel()
  self.ProjectVersion = QtGui.QLabel()
  self.CurrentFile = QtGui.QLabel()

  statusbar.addWidget(self.ProjectType)
  statusbar.addWidget(self.ProjectVersion)
  statusbar.addWidget(self.CurrentFile)
  hexstr = hex(color)
  hexstr = hexstr[2:]
  t = "background-color: #"+hexstr+";"
  statusbar.setStyleSheet(str(t))

  self.tabs = Tabs(self)
  self.tabs.hide()

  self.wLocalVars = LocalVarsListWindow(self)
  self.StackWindow = StackWindow(self)
  self.WatchWindow = WatchedVarsWindow(self)

  self.setCentralWidget(self.tabs)

  self.show()
  self.repaint()
  if config.MainWindowSize == "maximized":
   self.showMaximized()
  elif config.MainWindowSize == "minimized":
   self.showMinimized()
  elif config.MainWindowSize == "":
   desktop_rect = QtGui.QDesktopWidget().screenGeometry()
   top = desktop_rect.height() // 6
   left = desktop_rect.width() // 7
   self.setGeometry(left,top,left*5,top*4)
  else:
   left,top,width,height = config.MainWindowSize.split(",",3)
   self.setGeometry(int(left),int(top),int(width),int(height))

  self.Timer = QtCore.QTimer(self)
  self.connect(self.Timer,QtCore.SIGNAL("timeout()"),self.TimeEvent)
  self.Timer.setInterval(3000)
  self.Timer.stop()

 def SaveSizeWindows(self):
  root_dir = ""
  if config.build_type == "dist":
   root_dir = os.getcwd()

  if config.build_type == "source":
   root_dir = os.path.split(os.path.realpath(inspect.stack()[-1][1]))[0]

  if not os.path.exists(root_dir+"\\"+config.config_file):
   return
  cfg = configparser.ConfigParser()
  cfg.read(root_dir+"\\"+config.config_file)
  if self.isMaximized():
   data = "maximized"
  elif self.isMinimized():
   data = "minimized"
  else:
   r = self.geometry()
   data = str(r.left())+","+str(r.top())+","+str(r.width())+","+str(r.height())
  if "Sizes" in cfg:
   if "MainWindow" in cfg["Sizes"]:
    cfg["Sizes"]["MainWindow"] = data
   else:
    cfg["Sizes"].setdefault("MainWindow",data)
  else:
   cfg.setdefault("Sizes",{"MainWindow":data})
  f = open(root_dir+"\\"+config.config_file,"w",encoding=config.default_charset)
  cfg.write(f)
  f.close()

 def contextMenuEvent (self, event):
  pass

 def TimeEvent(self):
  self.Timer.stop()
  project.SaveFiles(self)
  self.Timer.start()

 def SetNewColor(self,c):
  p = self.palette()
  p.setColor(QtGui.QPalette.Normal,QtGui.QPalette.Background,QtGui.QColor(*c))
  p.setColor(QtGui.QPalette.Inactive,QtGui.QPalette.Background,QtGui.QColor(*c))
  self.setPalette(p)

 def resizeEvent(self,e):
  self.tabs.resize(e.size().width()+1,e.size().height()-40)
  QtGui.QWidget.resizeEvent(self,e)

 def OpenListOfFilesWindow(self):
  if self.ListOfFiles is None:
   self.ListOfFiles = ListOfFilesWindow(self)
  self.ListOfFiles.show()
  self.Timer.stop()

 def OpenArgListWindow(self):
  self.ArgList = ArgListWindow(self)

 def OpenLocalVarList(self):
  if self.wLocalVars is None:
   self.wLocalVars = LocalVarsListWindow(self)
  else:
   self.wLocalVars.show()
  if self.isdebug:
   self.wLocalVars.GetCurrentStateLocalVars()

 def OpenStackWindow(self):
  if self.StackWindow is None:
   self.StackWindow = StackWindow(self)
  else:
   self.StackWindow.show()
  if self.isdebug:
   self.StackWindow.GetCurrentStack()

 def OpenWatchVarList(self):
  if self.WatchWindow is None:
   self.WatchWindow = WatchedVarsWindow(self)
  else:
   self.WatchWindow.GetCurrentStateWatchedVars()
   self.WatchWindow.show()

 def OpenBplWindow(self):
  self.BplWindow = BreakpointsListWindow(self)

 def AddWatchVar(self):
  s = self.tabs.editors[self.tabs.currentIndex()].editor.selectedText()
  if s != "":
   try:
    i = self.tabs.watches.index(s)
   except ValueError:
    self.tabs.watches = [s] + self.tabs.watches
   else:
    win32api.MessageBox(0,"Переменная \""+s+"\" уже есть в списке","Ошибка",
                        win32con.MB_ICONERROR+win32con.MB_OK)
    return
  if self.isdebug:
   self.WatchWindow.AddWatchVar(s)
  self.WatchWindow.GetCurrentStateWatchedVars()

 def StartDebug(self):
  if self.ProcessWindow is None:
   self.ProcessWindow = CompileOrTestProcessWindow(self)
  self.ProcessWindow.setTypeOperation("compile")
  if self.OutputWindow is None:
   self.OutputWindow = ErrorAndMessagesWindow(self)
  else:
   self.OutputWindow.ClearAll()
  self.compile_process = CompileProcess(self,False,False)
  self.compile_process.start()

  while not self.compile_process.isFinished():
   pass

  if self.compile_process.err_cnt > 0:
   return

  self.isdebug = True
  self.Timer.stop()
  self.DebugClientSocket = socket.socket()     
  try:
   self.DebugClientSocket.connect(("127.0.0.1",self.port))
  except OSError:
   if config.build_type == "dist":
    kdbg_folder = os.getcwd()

   if config.build_type == "source":
    kdbg_folder = os.path.split(os.path.realpath(inspect.stack()[-1][1]))[0]
   if os.access(kdbg_folder+"\\kdbg.exe",os.F_OK):
    win32api.ShellExecute(0,"open",kdbg_folder+"\\kdbg.exe","","",1)
    self.DebugClientSocket.connect(("127.0.0.1",self.port))
   else:
    win32api.MessageBox(0,"Не удалось найти сервер отладки!","Ошибка",\
                        win32con.MB_OK+win32con.MB_ICONERROR)
    return
    
  self.DebugClientSocket.send("o".encode("cp1251"))
  a = self.DebugClientSocket.recv(self.bufsize)

  # Папка с бинарными файлами
  data = project.projectfolder+"\\"+project.debug_folder    
  self.DebugClientSocket.send(data.encode("cp1251")) 
  a = self.DebugClientSocket.recv(self.bufsize)

  # Путь к исполняемому файлу
  data = project.projectfolder+"\\"+project.debug_folder+"\\"+project.projectname+".exe"
  data += " "+config.debug_args
  self.DebugClientSocket.send(data.encode("cp1251")) 
  a = self.DebugClientSocket.recv(self.bufsize)

  # Передача списка исходных файлов
  # Заголовочные файлы тоже надо загружать: хотя обычно в них
  # только определения, никто не мешает поместить туда код.
  # Это тоже надо обработать.
  files = comp.GetFileList(project.projectfolder,["cpp","c","cxx","h","hpp"])
  for i in files:
   self.DebugClientSocket.send(i.encode("cp1251"))
   a = self.DebugClientSocket.recv(self.bufsize)
  self.DebugClientSocket.send("end".encode("cp1251"))

  # Передача имени стартовой функции
  index = config.LinkerOptionsState[text.Subsystem][0]   
  if config.LinkerOptions[text.Subsystem][index][0] == "Windows":
   self.DebugClientSocket.send("WinMain".encode("cp1251"))
  else:
   self.DebugClientSocket.send("main".encode("cp1251"))   
  a = self.DebugClientSocket.recv(self.bufsize)   # Получено Done

  # Передаем список отслеживаемых переменных
  for i in self.tabs.watches:
   self.DebugClientSocket.send(i.encode("cp1251"))
   a = self.DebugClientSocket.recv(self.bufsize)
  self.DebugClientSocket.send("end".encode("cp1251"))
  a = self.DebugClientSocket.recv(self.bufsize)

  # Передача имеющихся точек останова
  for source_path in self.tabs.breakpoints.keys():
   points_list = self.tabs.breakpoints[source_path]
   for point in points_list:
    self.DebugClientSocket.send(source_path.encode("cp1251"))
    a = self.DebugClientSocket.recv(self.bufsize)
    self.DebugClientSocket.send(str(point+1).encode("cp1251"))
    a = self.DebugClientSocket.recv(self.bufsize)
  self.DebugClientSocket.send("end".encode("cp1251"))  # Конец передачи

  # Ждем передачи списка скорректированных точек
  sfile = ""
  while sfile != "end":
   a = self.DebugClientSocket.recv(self.bufsize)  # Получаем имя файла
   sfile = a.decode("cp1251")
   self.DebugClientSocket.send("ok".encode("cp1251"))
   if sfile == "end":
    break
   a = self.DebugClientSocket.recv(self.bufsize)  # Получаем старый номер строки
   old_line = int(a.decode("cp1251"))
   self.DebugClientSocket.send("ok".encode("cp1251"))
   a = self.DebugClientSocket.recv(self.bufsize)  # Получаем новый номер строки
   new_line = int(a.decode("cp1251"))
   self.DebugClientSocket.send("ok".encode("cp1251"))

   try:
    index = self.tabs.paths.index(sfile)
   except ValueError:
    project.TabWithEditor(self,sfile,1,1)
    index = self.tabs.paths.index(sfile)
    self.tabs.breakpoints[self.tabs.paths[index]].remove(old_line-1)
    self.tabs.breakpoints[self.tabs.paths[index]].append(new_line-1)
    sci.SendScintilla(self.tabs.editors[index].editor,\
                      sci.SCI_MARKERDELETE,old_line-1,0)
    sci.SendScintilla(self.tabs.editors[index].editor,\
                      sci.SCI_MARKERADD,new_line-1,0)
   else:
    self.tabs.breakpoints[self.tabs.paths[index]].remove(old_line-1)
    self.tabs.breakpoints[self.tabs.paths[index]].append(new_line-1)
    sci.SendScintilla(self.tabs.editors[index].editor,\
                      sci.SCI_MARKERDELETE,old_line-1,0)
    sci.SendScintilla(self.tabs.editors[index].editor,\
                      sci.SCI_MARKERADD,new_line-1,0)

  a = self.DebugClientSocket.recv(self.bufsize)   # Получен путь к исходнику в котором находится
                                                  # стартовая точка отлаживаемой программы.
  sourcename = a.decode("cp1251")
  self.DebugClientSocket.send("recieved".encode("cp1251"))
  a = self.DebugClientSocket.recv(self.bufsize)   # Получен номер строки стартовой точки.
  line = a.decode("cp1251")
  self.DebugClientSocket.send("recieved".encode("cp1251"))
  self.DebugClientSocket.close()

  found = False
  for i in range(len(self.tabs.paths)):
   self.tabs.editors[i].editor.setReadOnly(True)
   if self.tabs.paths[i] == sourcename:
    self.tabs.setCurrentIndex(i)
    self.tabs.editors[self.tabs.currentIndex()].editor.setCursorPosition(int(line)-1,1)
    sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                      sci.SCI_MARKERADD,int(line)-1,1)
    found = True

  if not os.access(sourcename,os.F_OK):
   self.StopDebug()
   win32api.MessageBox(0,"Файл \""+sourcename+"\" не найден! Отладка остановлена.")

  if found == False:
   project.TabWithEditor(self,sourcename,int(line)-1,1)

  if self.wLocalVars is not None and self.wLocalVars.isVisible():
   self.wLocalVars.GetCurrentStateLocalVars()

  if self.StackWindow is not None and self.StackWindow.isVisible():
   self.StackWindow.GetCurrentStack()

  if self.WatchWindow is not None and self.StackWindow.isVisible():
   self.WatchWindow.GetCurrentStateWatchedVars()

 def StopDebug(self):
  self.isdebug = False

  if self.waitbreak is not None:
   self.waitbreak.terminate()
   self.waitbreak = None

  self.DebugClientSocket = socket.socket()
  self.DebugClientSocket.connect(("127.0.0.1",self.port))    
  self.DebugClientSocket.send("sd".encode("cp1251"))
  self.DebugClientSocket.close()
  for i in range(len(self.tabs.paths)):
   self.tabs.editors[i].editor.setReadOnly(False)
   sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                     sci.SCI_MARKERDELETEALL,1,0)
  self.Timer.start()

  if self.wLocalVars is not None and self.wLocalVars.isVisible():
   self.wLocalVars.VarList.clear()

  if self.StackWindow is not None and self.StackWindow.isVisible():
   self.StackWindow.FuncList.clear()

  if self.WatchWindow is not None and self.WatchWindow.isVisible():
   self.WatchWindow.VarList.clear()
   for i in self.tabs.watches:
    it = QtGui.QTreeWidgetItem(self.WatchWindow.VarList)
    it.setText(0,i)

 def NextStep(self):
  self.DebugClientSocket = socket.socket()
  self.DebugClientSocket.connect(("127.0.0.1",self.port))    
  self.DebugClientSocket.send("s".encode("cp1251"))
  a = self.DebugClientSocket.recv(self.bufsize)  # Получаем путь текущего исходника.
  sourcename = a.decode("cp1251")
  self.DebugClientSocket.send("recieved".encode("cp1251"))  
  a = self.DebugClientSocket.recv(self.bufsize)  # Получаем номер строки.
  line = a.decode("cp1251")
  self.DebugClientSocket.send("recieved".encode("cp1251"))
  self.DebugClientSocket.close()

  if self.wLocalVars is not None and self.wLocalVars.isVisible():
   self.wLocalVars.GetCurrentStateLocalVars()

  if self.StackWindow is not None and self.StackWindow.isVisible():
   self.StackWindow.GetCurrentStack()

  if self.WatchWindow is not None and self.WatchWindow.isVisible():
   self.WatchWindow.GetCurrentStateWatchedVars()

  if sourcename == "fail":
   w = WaitBreakpoint(self)
   w.start()
   return

  found = False
  for i in range(len(self.tabs.paths)):
   if self.tabs.paths[i] == sourcename:
    self.tabs.setCurrentIndex(i)
    sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                      sci.SCI_MARKERDELETEALL,1,0)
    self.tabs.editors[self.tabs.currentIndex()].editor.setCursorPosition(int(line)-1,1)
    sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                      sci.SCI_MARKERADD,int(line)-1,1)
    found = True

  if not os.access(sourcename,os.F_OK):
   self.StopDebug()
   return

  if found == False:
   sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                     sci.SCI_MARKERDELETEALL,1,0)
   project.TabWithEditor(self,sourcename,int(line)-1,1)

 def SetOrUnsetBreakpoint(self):
  global sci

  if self.tabs.count() > 0:
   line,index = self.tabs.editors[self.tabs.currentIndex()].editor.getCursorPosition()
   # В данном файле точек останова еще не было.
   if self.tabs.paths[self.tabs.currentIndex()] not in self.tabs.breakpoints.keys():
    if self.isdebug:
     self.DebugClientSocket = socket.socket()
     self.DebugClientSocket.connect(("127.0.0.1",self.port))
     self.DebugClientSocket.send("bp".encode("cp1251"))
     a = self.DebugClientSocket.recv(self.bufsize)
     p = self.tabs.paths[self.tabs.currentIndex()]
     self.DebugClientSocket.send(p.encode("cp1251"))
     a = self.DebugClientSocket.recv(self.bufsize)
     p = str(line+1)
     self.DebugClientSocket.send(p.encode("cp1251"))

     a = self.DebugClientSocket.recv(self.bufsize)
     line = int(a.decode("cp1251"))
     self.DebugClientSocket.send("ok".encode("cp1251"))

     # Работа программы должна возобновляться программно, но
     # не из редактора, а из сервера отладки kdbg.exe!
     # Очень странно. Пока с этим не разобрался.
     a = self.DebugClientSocket.recv(self.bufsize)
     self.DebugClientSocket.send("ok".encode("cp1251"))
     a = a.decode("cp1251")
     if a == "go":
      w = WaitBreakpoint(self)
      w.start()
     else:
      self.DebugClientSocket.close()

    self.tabs.breakpoints[self.tabs.paths[self.tabs.currentIndex()]] = [line]
    sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                      sci.SCI_MARKERADD,line,0)
    return
   else:
    # В данном файле точки останова были, но в текущей строке их нет.
    if line not in self.tabs.breakpoints[self.tabs.paths[self.tabs.currentIndex()]]:
     if self.isdebug:
      self.DebugClientSocket = socket.socket()
      self.DebugClientSocket.connect(("127.0.0.1",self.port))
      self.DebugClientSocket.send("bp".encode("cp1251"))
      a = self.DebugClientSocket.recv(self.bufsize)
      p = self.tabs.paths[self.tabs.currentIndex()]
      self.DebugClientSocket.send(p.encode("cp1251"))
      a = self.DebugClientSocket.recv(self.bufsize)
      p = str(line+1)
      self.DebugClientSocket.send(p.encode("cp1251"))

      a = self.DebugClientSocket.recv(self.bufsize)
      line = int(a.decode("cp1251"))
      self.DebugClientSocket.send("ok".encode("cp1251"))

      # Работа программы должна возобновляться программно, но
      # из редактора, а из сервера отладки kdbg.exe!
      # Очень странно. Пока с этим не разобрался.
      a = self.DebugClientSocket.recv(self.bufsize)
      self.DebugClientSocket.send("ok".encode("cp1251"))
      a = a.decode("cp1251")
      if a == "go":
       w = WaitBreakpoint(self)
       w.start()
      else:
       self.DebugClientSocket.close()

     self.tabs.breakpoints[self.tabs.paths[self.tabs.currentIndex()]].append(line)
     sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                       sci.SCI_MARKERADD,line,0)
    else:
     # В данной строке точка останова уже есть.
     sci.SendScintilla(self.tabs.editors[self.tabs.currentIndex()].editor,\
                       sci.SCI_MARKERDELETE,line,0)
     self.tabs.breakpoints[self.tabs.paths[self.tabs.currentIndex()]].remove(line)

     if self.isdebug:
      self.DebugClientSocket = socket.socket()
      self.DebugClientSocket.connect(("127.0.0.1",self.port))
      self.DebugClientSocket.send("dbp".encode("cp1251"))
      a = self.DebugClientSocket.recv(self.bufsize)

      p = self.tabs.paths[self.tabs.currentIndex()]
      self.DebugClientSocket.send(p.encode("cp1251"))
      a = self.DebugClientSocket.recv(self.bufsize)
      p = str(line+1)
      self.DebugClientSocket.send(p.encode("cp1251"))
      self.DebugClientSocket.close()

 def GoOn(self):
  self.waitbreak = WaitBreakpoint(self)
  self.waitbreak.start()

 def StartCompileFile(self):
  if len(self.tabs.pages) > 0:
   project.SaveFiles(self)
   if self.OutputWindow is None:
    self.OutputWindow = ErrorAndMessagesWindow(self)
   else:
    self.OutputWindow.ClearAll()
   if self.tabs.paths[self.tabs.currentIndex()].endswith(".h") or \
      self.tabs.paths[self.tabs.currentIndex()].endswith(".hpp"):
    win32api.MessageBox(0,"Заголовочные файлы компилировать нельзя!","Ошибка",
                        win32con.MB_ICONERROR+win32con.MB_OK)
    return
   err_cnt,warn_cnt = comp.CompileFile(self,self.tabs.paths[self.tabs.currentIndex()])
   if err_cnt == 0 and warn_cnt == 0:
    win32api.MessageBox(0,self.tabs.paths[self.tabs.currentIndex()]+
                        ":\nОшибок и предупреждений нет.","Результат компиляции",
                        win32con.MB_OK+win32con.MB_ICONINFORMATION) 
   else:
    self.OutputWindow.tabs.setTabText(0,"Ошибки ("+str(err_cnt)+")")
    self.OutputWindow.tabs.setTabText(1,"Предупреждения ("+str(warn_cnt)+")")
    self.OutputWindow.show()

 def StartCompileProject(self):
  if len(self.tabs.pages) > 0:
   project.SaveFiles(self)
  self.Timer.stop()  
  if self.ProcessWindow is None:
   self.ProcessWindow = CompileOrTestProcessWindow(self)
  self.ProcessWindow.setTypeOperation("compile")
  if self.OutputWindow is None:
   self.OutputWindow = ErrorAndMessagesWindow(self)
  else:
   self.OutputWindow.ClearAll()
  self.ProcessWindow.show()
  self.compile_process = CompileProcess(self)
  self.compile_process.IsShowSuccessWindow = True
  self.compile_process.IsShowSuccessOutput = True
  self.compile_process.start()

 def StartTestProject(self):
  if len(self.tabs.pages) > 0:
   project.SaveFiles(self)
  self.Timer.stop()
  if self.ProcessWindow is None:
   self.ProcessWindow = CompileOrTestProcessWindow(self)
  self.ProcessWindow.setTypeOperation("check")
  if self.OutputWindow is None:
   self.OutputWindow = ErrorAndMessagesWindow(self)
  else:
   self.OutputWindow.ClearAll()
  self.ProcessWindow.show()
  self.test_process = TestProcess(self)
  self.test_process.start()
 
 def StartTestFile(self):
  if len(self.tabs.pages) > 0:
   project.SaveFiles(self)
   if self.OutputWindow is None:
    self.OutputWindow = ErrorAndMessagesWindow(self)
   else:
    self.OutputWindow.ClearAll()
   err_cnt,warn_cnt = comp.SyntaxCheckFile(self,self.tabs.paths[self.tabs.currentIndex()])
   if err_cnt == 0 and warn_cnt == 0:
    win32api.MessageBox(0,self.tabs.paths[self.tabs.currentIndex()]+
                        ":\nОшибок и предупреждений нет.","Результат проверки",
                        win32con.MB_OK+win32con.MB_ICONINFORMATION) 
   else:
    self.OutputWindow.tabs.setTabText(0,"Ошибки ("+str(err_cnt)+")")
    self.OutputWindow.tabs.setTabText(1,"Предупреждения ("+str(warn_cnt)+")")
    self.OutputWindow.show()
 
 def OpenSettingsWindow(self):
  self.SetWindow = SettingsWindow(self)

 def OpenProjectSettingsWindow(self):
  self.PrjSetWindow = ProjectSettingsWindow(self)

 def CreateProject(self):
  if self.ListOfFiles is not None:
   self.ListOfFiles.Refresh()
  project.CreateProject(self)

 def OpenProject(self):
  project.OpenProject(self)

 def SelectedPrjType(self,item):
  if item is self.AppItem:
   project.projecttype = "app"
   self.ProjectType.setText("  APP  ")
  elif item is self.DllItem:
   project.projecttype = "dll"
   self.ProjectType.setText("  DLL  ")
  elif item is self.LibItem:
   project.projecttype = "lib"
   self.ProjectType.setText("  LIB  ")
  elif item is self.ObjItem:
   project.projecttype = "obj"
   self.ProjectType.setText("  OBJ  ")
  else:
   project.projecttype = "app"
   self.ProjectType.setText("  APP  ")

 def SelectedVerProj(self,item):
  if item is self.DebugPrjItem:
   project.compilemode = "debug"
   self.ProjectVersion.setText("  Отладочная версия  ")
  elif item is self.ReleasePrjItem:
   project.compilemode = "release"
   self.ProjectVersion.setText("  Финальная версия  ")

 def RunProgram(self):
  if project.projecttype == "dll" or  project.projecttype == "lib" or \
     project.projecttype == "obj":
   win32api.MessageBox(0,"Запустить можно только приложение!","Ошибка",win32con.MB_ICONERROR+win32con.MB_OK)
   return

  if len(self.tabs.pages) > 0:
   project.SaveFiles(self)
  self.Timer.stop()  
  if self.ProcessWindow is None:
   self.ProcessWindow = CompileOrTestProcessWindow(self)
  self.ProcessWindow.setTypeOperation("compile")
  if self.OutputWindow is None:
   self.OutputWindow = ErrorAndMessagesWindow(self)
  else:
   self.OutputWindow.ClearAll()
  self.compile_process = CompileProcess(self,False,False)
  self.compile_process.start()

  while not self.compile_process.isFinished():
   pass

  if self.compile_process.err_cnt > 0:
   return

  if project.compilemode == "debug":
   s = project.projectfolder+"\\"+project.debug_folder+"\\"+project.projectname+".exe"
   if os.path.exists(s):
    win32api.ShellExecute(0,"open",s,"","",1)
   else:
    win32api.MessageBox(0,"Программа "+s+" не найдена!","Ошибка",win32con.MB_ICONERROR+win32con.MB_OK)
    return
  if project.compilemode == "release":
   s = project.projectfolder+"\\"+project.release_folder+"\\"+project.projectname+".exe"
   if os.path.exists(s):
    win32api.ShellExecute(0,"open",s,"","",1)
   else:
    win32api.MessageBox(0,"Программа "+s+" не найдена!","Ошибка",win32con.MB_ICONERROR+win32con.MB_OK)

 def closeEvent(self,e):
  if self.waitbreak is not None:
   self.waitbreak.terminate()
   self.waitbreak = None

  self.SaveSizeWindows()
  if self.OutputWindow is not None:
   self.OutputWindow.close()
  if self.ListOfFiles is not None:
   self.ListOfFiles.close()
  if self.WatchWindow is not None:
   self.WatchWindow.close()

  if project.projectname is not None:
   project.SaveProject(self)
   project.SaveFiles(self)
   self.Timer.stop()

  self.DebugClientSocket = socket.socket()
  try:
   self.DebugClientSocket.connect(("127.0.0.1",self.port))
  except OSError:
   QtGui.QWidget.closeEvent(self,e)
  else:
   self.DebugClientSocket.send("q".encode("cp1251"))
   self.DebugClientSocket.close()
   QtGui.QWidget.closeEvent(self,e)

 def Quit(self):
  if self.waitbreak is not None:
   self.waitbreak.terminate()
   self.waitbreak = None

  self.SaveSizeWindows()
  if self.OutputWindow is not None:
   self.OutputWindow.close()
  if self.ListOfFiles is not None:
   self.ListOfFiles.close()
  if self.WatchWindow is not None:
   self.WatchWindow.close()

  if project.projectname is not None:
   project.SaveProject(self)
   project.SaveFiles(self)
   self.Timer.stop()

  self.DebugClientSocket = socket.socket()
  try:
   self.DebugClientSocket.connect(("127.0.0.1",self.port))   
  except OSError:
   QtGui.qApp.quit()
  else:
   self.DebugClientSocket.send("q".encode("cp1251"))
   self.DebugClientSocket.close()
   QtGui.qApp.quit()
                        
 def InitMainMenu(self, menu):
  # Меню верхнего уровня

  self.FileMenu = menu.addMenu(text.ProjectMenu)
  CompileMenu = menu.addMenu(text.CompileMenu)
  DebugMenu = menu.addMenu(text.DebugMenu)
  self.SettingsMenu = menu.addMenu(text.SettingsMenu)
  HelpMenu = menu.addMenu(text.HelpMenu)

  # Элементы меню "Проект"

  self.NewPrjItem = QtGui.QAction(text.NewProject, self)
  self.NewPrjItem.setShortcut(config.NewProject)
  self.connect(self.NewPrjItem,QtCore.SIGNAL("triggered()"),self.CreateProject)
  self.FileMenu.addAction(self.NewPrjItem)

  self.OpenPrjItem = QtGui.QAction(text.OpenProject, self)        
  self.OpenPrjItem.setShortcut(config.OpenProject)
  self.connect(self.OpenPrjItem,QtCore.SIGNAL("triggered()"),self.OpenProject)
  self.FileMenu.addAction(self.OpenPrjItem)

  self.FileMenu.addSeparator()

  self.ListOfFilesItem = QtGui.QAction(text.ListOfFiles, self)        
  self.ListOfFilesItem.setShortcut(config.ListOfFiles)
  self.ListOfFilesItem.triggered.connect(self.OpenListOfFilesWindow)
  self.FileMenu.addAction(self.ListOfFilesItem)

  self.SettingsItem = QtGui.QAction(text.Settings, self)
  self.SettingsItem.setShortcut(config.Settings)
  self.SettingsItem.triggered.connect(self.OpenProjectSettingsWindow)
  self.FileMenu.addAction(self.SettingsItem)

  self.FileMenu.addSeparator()

  self.ExitItem = QtGui.QAction(text.Exit, self)        
  self.ExitItem.setShortcut(config.Exit)
  self.ExitItem.triggered.connect(self.Quit)
  self.FileMenu.addAction(self.ExitItem)

  # Элементы меню "Компиляция"

  self.BuildPrjItem = QtGui.QAction(text.BuildProject, self)
  self.BuildPrjItem.setShortcut(config.BuildProject)
  self.connect(self.BuildPrjItem,QtCore.SIGNAL("triggered()"),self.StartCompileProject)
  CompileMenu.addAction(self.BuildPrjItem)

  self.BuildFileItem = QtGui.QAction(text.CompileFile, self)        
  self.BuildFileItem.setShortcut(config.CompileFile)
  self.connect(self.BuildFileItem,QtCore.SIGNAL("triggered()"),self.StartCompileFile)
  CompileMenu.addAction(self.BuildFileItem)
  
  CompileMenu.addSeparator()

  self.TestPrjItem = QtGui.QAction(text.TestProject, self)        
  self.TestPrjItem.setShortcut(config.TestProject)
  self.connect(self.TestPrjItem,QtCore.SIGNAL("triggered()"),self.StartTestProject)
  CompileMenu.addAction(self.TestPrjItem)

  self.TestFileItem = QtGui.QAction(text.TestFile, self)        
  self.TestFileItem.setShortcut(config.TestFile)
  self.connect(self.TestFileItem,QtCore.SIGNAL("triggered()"),self.StartTestFile)
  CompileMenu.addAction(self.TestFileItem)

  CompileMenu.addSeparator()

  self.RunItem = QtGui.QAction(text.Run,self)        
  self.connect(self.RunItem,QtCore.SIGNAL("triggered()"),self.RunProgram)
  CompileMenu.addAction(self.RunItem)

  # Элементы меню "Отладка"

  self.StartDebugItem = QtGui.QAction(text.StartDebug, self)        
  self.StartDebugItem.setShortcut(config.StartDebug)
  self.connect(self.StartDebugItem,QtCore.SIGNAL("triggered()"),self.StartDebug)
  DebugMenu.addAction(self.StartDebugItem)

  self.StopDebugItem = QtGui.QAction(text.StopDebug, self)        
  self.StopDebugItem.setShortcut(config.StopDebug)
  self.StopDebugItem.setShortcutContext(QtCore.Qt.ApplicationShortcut)
  self.connect(self.StopDebugItem,QtCore.SIGNAL("triggered()"),self.StopDebug)
  DebugMenu.addAction(self.StopDebugItem)

  DebugMenu.addSeparator()

  self.BreakpointItem = QtGui.QAction(text.Breakpoint, self)
  self.BreakpointItem.setShortcut(config.Breakpoint)
  self.connect(self.BreakpointItem,QtCore.SIGNAL("triggered()"),self.SetOrUnsetBreakpoint)
  DebugMenu.addAction(self.BreakpointItem)

  self.NextStepItem = QtGui.QAction(text.NextStep, self)        
  self.NextStepItem.setShortcut(config.NextStep)
  self.NextStepItem.setShortcutContext(QtCore.Qt.ApplicationShortcut)
  self.connect(self.NextStepItem,QtCore.SIGNAL("triggered()"),self.NextStep) 
  DebugMenu.addAction(self.NextStepItem)

  self.GoOnItem = QtGui.QAction(text.GoOn, self)
  self.GoOnItem.setShortcut(config.GoOn)
  self.connect(self.GoOnItem,QtCore.SIGNAL("triggered()"),self.GoOn)
  DebugMenu.addAction(self.GoOnItem)

  DebugMenu.addSeparator()

  self.WatchVarListItem = QtGui.QAction(text.WatchVarList, self)
  self.WatchVarListItem.setShortcut(config.WatchVarList)
  self.connect(self.WatchVarListItem,QtCore.SIGNAL("triggered()"),self.OpenWatchVarList)
  DebugMenu.addAction(self.WatchVarListItem)

  self.AddToWatchVarListItem = QtGui.QAction(text.AddToWatchVarList, self)
  self.AddToWatchVarListItem.setShortcut(config.AddToWatchVarList)
  self.connect(self.AddToWatchVarListItem,QtCore.SIGNAL("triggered()"),self.AddWatchVar)
  DebugMenu.addAction(self.AddToWatchVarListItem)

  DebugMenu.addSeparator()

  self.StackItem = QtGui.QAction(text.Stack, self)
  self.connect(self.StackItem,QtCore.SIGNAL("triggered()"),self.OpenStackWindow)
  DebugMenu.addAction(self.StackItem)

  self.LocalVarListItem = QtGui.QAction(text.LocalVarList, self)
  self.connect(self.LocalVarListItem,QtCore.SIGNAL("triggered()"),self.OpenLocalVarList)
  DebugMenu.addAction(self.LocalVarListItem)

  self.BplItem = QtGui.QAction(text.BreakpointsList, self)
  self.connect(self.BplItem,QtCore.SIGNAL("triggered()"),self.OpenBplWindow)
  DebugMenu.addAction(self.BplItem)

  self.ArgsItem = QtGui.QAction(text.Args, self)        
  self.connect(self.ArgsItem,QtCore.SIGNAL("triggered()"),self.OpenArgListWindow)
  DebugMenu.addAction(self.ArgsItem)

  # Элементы меню "Настройки"

  self.SetupItem = QtGui.QAction(text.SettingsWindow, self)        
  self.connect(self.SetupItem,QtCore.SIGNAL("triggered()"),self.OpenSettingsWindow)
  self.SettingsMenu.addAction(self.SetupItem)

  # Элементы меню "Помощь"

  AboutItem = QtGui.QAction(text.About, self)        
  AboutItem.setShortcut(config.Help)
  HelpMenu.addAction(AboutItem)