GUI added
This commit is contained in:
parent
c7b38a6506
commit
8da3143df3
77
forms.py
Normal file
77
forms.py
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import wx
|
||||||
|
import wx.propgrid as wxpg
|
||||||
|
|
||||||
|
ID_TEST = wx.NewId()
|
||||||
|
ID_DUPLICATE = wx.NewId()
|
||||||
|
ID_DUPLICATE_MODEL = wx.NewId()
|
||||||
|
ID_DELETE_MODEL = wx.NewId()
|
||||||
|
ID_PROCESS_MODEL = wx.NewId()
|
||||||
|
|
||||||
|
class MainFrame (wx.Frame):
|
||||||
|
|
||||||
|
def __init__(self, parent):
|
||||||
|
wx.Frame.__init__ (self, parent, title = 'Opal', size = wx.Size(873,594))
|
||||||
|
|
||||||
|
self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
|
||||||
|
|
||||||
|
bSizer3 = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
self.m_specs = wx.TreeCtrl(self, style = wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT)
|
||||||
|
self.m_specs.SetMinSize(wx.Size(150,-1))
|
||||||
|
|
||||||
|
bSizer3.Add(self.m_specs, 0, wx.ALL|wx.EXPAND, 1)
|
||||||
|
|
||||||
|
bSizer4 = wx.BoxSizer(wx.VERTICAL)
|
||||||
|
|
||||||
|
self.m_user_models = wx.TreeCtrl(self,
|
||||||
|
style = wx.TR_DEFAULT_STYLE | wx.TR_HIDE_ROOT | wx.TR_EDIT_LABELS)
|
||||||
|
self.m_user_models.SetMinSize(wx.Size(-1,200))
|
||||||
|
|
||||||
|
bSizer4.Add(self.m_user_models, 0, wx.ALL|wx.EXPAND, 1)
|
||||||
|
|
||||||
|
# WARNING: wxPython code generation isn't supported for this widget yet.
|
||||||
|
self.m_params = wxpg.PropertyGridManager(self,
|
||||||
|
style = wxpg.PG_TOOLBAR)
|
||||||
|
bSizer4.Add(self.m_params, 1, wx.EXPAND |wx.ALL, 1)
|
||||||
|
|
||||||
|
bSizer3.Add(bSizer4, 1, wx.EXPAND, 5)
|
||||||
|
|
||||||
|
self.m_job_list = wx.ListCtrl(self, style = wx.LC_LIST)
|
||||||
|
self.m_job_list.SetMinSize(wx.Size(150,-1))
|
||||||
|
|
||||||
|
bSizer3.Add(self.m_job_list, 0, wx.ALL|wx.EXPAND, 1)
|
||||||
|
|
||||||
|
sbar = wx.StatusBar(self)
|
||||||
|
self.SetStatusBar(sbar)
|
||||||
|
|
||||||
|
mbar = self.BuildMenu()
|
||||||
|
self.SetMenuBar(mbar)
|
||||||
|
|
||||||
|
self.SetSizer(bSizer3)
|
||||||
|
self.Layout()
|
||||||
|
|
||||||
|
self.Centre(wx.BOTH)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def BuildMenu(self):
|
||||||
|
menubar = wx.MenuBar()
|
||||||
|
|
||||||
|
menu = wx.Menu()
|
||||||
|
menu.Append(1, "&Open\tCtrl+O")
|
||||||
|
menubar.Append(menu, '&File')
|
||||||
|
|
||||||
|
menu = wx.Menu()
|
||||||
|
menu.Append(ID_TEST, "&Test\tCtrl+U")
|
||||||
|
menu.Append(ID_DUPLICATE, "&Duplicate\tCtrl+D")
|
||||||
|
menubar.Append(menu, '&Model')
|
||||||
|
|
||||||
|
menu = wx.Menu()
|
||||||
|
menu.Append(3, "&Log In\tCtrl+L")
|
||||||
|
menu.Append(2, "&Options\tCtrl+P")
|
||||||
|
menubar.Append(menu, '&Help')
|
||||||
|
|
||||||
|
return menubar
|
@ -112,7 +112,7 @@ ok
|
|||||||
|
|
||||||
Перед тем как перейти к описанию структуры, описывающей зачаду и ее модели, следует рассказать о типах данных, которые применяются в “Opal”. Далее будем говорить только о тех полях, которые встречаются в задачах, моделях и методах.
|
Перед тем как перейти к описанию структуры, описывающей зачаду и ее модели, следует рассказать о типах данных, которые применяются в “Opal”. Далее будем говорить только о тех полях, которые встречаются в задачах, моделях и методах.
|
||||||
|
|
||||||
Тип — очень важная часть описания данных. Хотя без него можно было бы обойтись, предоставив пользователям полный контроль над передаваемыми данными, этого лучше избежать. Все дело в том, что тип является мощным инструментом контроля целостности передаваемых данных, не позволяя использовать, скажем, строку там, где должно быть целое число.
|
Тип --- очень важная часть описания данных. Хотя без него можно было бы обойтись, предоставив пользователям полный контроль над передаваемыми данными, этого лучше избежать. Все дело в том, что тип является мощным инструментом контроля целостности передаваемых данных, не позволяя использовать, скажем, строку там, где должно быть целое число.
|
||||||
|
|
||||||
В описании поля используется следующий синтаксис:
|
В описании поля используется следующий синтаксис:
|
||||||
“name”: “type [choice list] [default value] [title title]
|
“name”: “type [choice list] [default value] [title title]
|
||||||
@ -151,14 +151,12 @@ ok
|
|||||||
Период
|
Период
|
||||||
[‘0:0:0’, ‘12:0:0’]
|
[‘0:0:0’, ‘12:0:0’]
|
||||||
|
|
||||||
\subsection{Логический тип}
|
\subsection{Логический тип \emph{bool}}
|
||||||
bool
|
|
||||||
Значения: true, false
|
Значения: true, false
|
||||||
Логический тип один из основополагающих типов данных. Он может принимать всего два значения: истина и ложь. Отлично подходит для создания выключателей (или переключателей) дополнительных опций модели.
|
Логический тип один из основополагающих типов данных. Он может принимать всего два значения: истина и ложь. Отлично подходит для создания выключателей (или переключателей) дополнительных опций модели.
|
||||||
Присутствует в JSON.
|
Присутствует в JSON.
|
||||||
|
|
||||||
\subsection{Целочисленный тип}
|
\subsection{Целочисленный тип \emph{int}}
|
||||||
int
|
|
||||||
Значения: от -231 до 231-1 (4 байта)
|
Значения: от -231 до 231-1 (4 байта)
|
||||||
Тип данных для хранения целых чисел со знаком. Пожалуй, еще более основной тип, чем логический. Если вы не собираетесь работать с большими целыми числами (к примеру, рассчитывать госдолг США) то представленного диапазона хватит для большинства задач.
|
Тип данных для хранения целых чисел со знаком. Пожалуй, еще более основной тип, чем логический. Если вы не собираетесь работать с большими целыми числами (к примеру, рассчитывать госдолг США) то представленного диапазона хватит для большинства задач.
|
||||||
Присутствует в JSON.
|
Присутствует в JSON.
|
||||||
@ -169,8 +167,7 @@ float
|
|||||||
Тип данных с плавающей точкой предназначен для хранения и обработки действительных чисел.
|
Тип данных с плавающей точкой предназначен для хранения и обработки действительных чисел.
|
||||||
Присутствует в JSON.
|
Присутствует в JSON.
|
||||||
|
|
||||||
\subsection{Строковый тип}
|
\subsection{Строковый тип \emph{string}}
|
||||||
string
|
|
||||||
Строковый тип служит для хранения символов. Отсутствует разделение на строки и символы как во многих языках программирования. Это сделано для того, чтобы упростить работу с данными. Строки можно использовать в качестве комментариев. В качестве нетривиального примера можно привести использование строк вместе с оператором выбора в качестве перечисляемого типа (аналог enum):
|
Строковый тип служит для хранения символов. Отсутствует разделение на строки и символы как во многих языках программирования. Это сделано для того, чтобы упростить работу с данными. Строки можно использовать в качестве комментариев. В качестве нетривиального примера можно привести использование строк вместе с оператором выбора в качестве перечисляемого типа (аналог enum):
|
||||||
string choice [‘a’, ‘b’, ‘c’]
|
string choice [‘a’, ‘b’, ‘c’]
|
||||||
При записи строк в определении поля данных нужно быть внимательным с использованием кавычек. Кавычки внутри описания поля нужно экранировать символом обратного слеша \\. Лучше это будет видно на примере:
|
При записи строк в определении поля данных нужно быть внимательным с использованием кавычек. Кавычки внутри описания поля нужно экранировать символом обратного слеша \\. Лучше это будет видно на примере:
|
||||||
@ -178,8 +175,7 @@ string
|
|||||||
Чтобы не запутаться надо просто помнить, что вы описываете строку в строке.
|
Чтобы не запутаться надо просто помнить, что вы описываете строку в строке.
|
||||||
Присутствует в JSON.
|
Присутствует в JSON.
|
||||||
|
|
||||||
\subsection{Тип момента времени}
|
\subsection{Тип момента времени \emph{time}}
|
||||||
time
|
|
||||||
Значения: от "1000-01-01 00:00:00" до "9999-12-31 23:59:59"
|
Значения: от "1000-01-01 00:00:00" до "9999-12-31 23:59:59"
|
||||||
Является аналогом типа данных timestamp. При описании значений этого типа можно описывать как все поле целиком, так и использовать его части отдельно (время и дату). Отсутствующая часть будет заменена значением по умолчанию. Примеры:
|
Является аналогом типа данных timestamp. При описании значений этого типа можно описывать как все поле целиком, так и использовать его части отдельно (время и дату). Отсутствующая часть будет заменена значением по умолчанию. Примеры:
|
||||||
“12:10:00”
|
“12:10:00”
|
||||||
|
116
opal.py
116
opal.py
@ -13,23 +13,109 @@
|
|||||||
|
|
||||||
import server
|
import server
|
||||||
import task
|
import task
|
||||||
|
import wx
|
||||||
|
import wx.propgrid as wxpg
|
||||||
|
import forms
|
||||||
|
|
||||||
class Project:
|
#-----------------------------------------------------------------------------
|
||||||
pass
|
# Главная форма
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
def main():
|
class MainFrame(forms.MainFrame):
|
||||||
import pprint
|
def __init__(self):
|
||||||
s = server.LocalServer()
|
forms.MainFrame.__init__(self, None)
|
||||||
s.LoadTasksDescriptions()
|
|
||||||
ds = s.GetTasksDescriptions()
|
|
||||||
ms = []
|
|
||||||
for d in ds:
|
|
||||||
ms.extend(d.GetModelsDescriptions())
|
|
||||||
|
|
||||||
m = ms[0]
|
s = server.LocalServer()
|
||||||
pprint.pprint(m.data)
|
s.LoadTasksDescriptions()
|
||||||
|
ds = s.GetTasksDescriptions()
|
||||||
|
models = []
|
||||||
|
for d in ds:
|
||||||
|
models.extend(d.GetModelsDescriptions())
|
||||||
|
|
||||||
print m.GetSpecifications()
|
model = models[0]
|
||||||
|
|
||||||
if __name__ == '__main__':
|
self.m_user_models.Bind(wx.EVT_TREE_ITEM_ACTIVATED,
|
||||||
main()
|
self.OnModelActivated)
|
||||||
|
self.m_params.Bind(wxpg.EVT_PG_CHANGING,
|
||||||
|
self.OnParamChanging)
|
||||||
|
|
||||||
|
self.Bind(wx.EVT_MENU, self.OnTest, id = forms.ID_TEST)
|
||||||
|
self.Bind(wx.EVT_MENU, self.OnDuplicate, id = forms.ID_DUPLICATE)
|
||||||
|
|
||||||
|
self.m_params.AddPage('fp')
|
||||||
|
|
||||||
|
self.NewProject(model)
|
||||||
|
|
||||||
|
def NewProject(self, project):
|
||||||
|
# 1. загрузить спецификации модели
|
||||||
|
# 2. создать одну модель по умолчанию
|
||||||
|
model = project
|
||||||
|
um = self.m_user_models
|
||||||
|
root = um.AddRoot('')
|
||||||
|
data = task.DataDefinition(model)
|
||||||
|
|
||||||
|
child = um.AppendItem(root, u'Обычная')
|
||||||
|
um.SetPyData(child, data)
|
||||||
|
|
||||||
|
def SelectUserModel(self, model_def):
|
||||||
|
msg = model_def.PackParams()
|
||||||
|
pg = self.m_params
|
||||||
|
pg.ClearPage(0)
|
||||||
|
#pg.Append(wxpg.PropertyCategory('Model properties'))
|
||||||
|
for k, v in model_def.params.iteritems():
|
||||||
|
p = model_def.DD[k]
|
||||||
|
title = p.GetTitle() or k
|
||||||
|
pid = pg.Append(wxpg.StringProperty(title, value=str(v)))
|
||||||
|
pg.SetPropertyClientData(pid, k)
|
||||||
|
pg.SetPropertyHelpString(pid, p.GetComment())
|
||||||
|
|
||||||
|
def OnModelActivated(self, event):
|
||||||
|
item = event.GetItem()
|
||||||
|
data = self.m_user_models.GetPyData(item)
|
||||||
|
self.SelectUserModel(data)
|
||||||
|
|
||||||
|
def OnParamChanging(self, event):
|
||||||
|
value = event.GetValue()
|
||||||
|
print repr(value)
|
||||||
|
#wx.MessageBox(value, 'changing')
|
||||||
|
#event.Veto()
|
||||||
|
|
||||||
|
def OnTest(self, event):
|
||||||
|
um = self.m_user_models
|
||||||
|
id = um.GetSelection()
|
||||||
|
md = um.GetItemPyData(id)
|
||||||
|
wx.MessageBox(md.PackParams())
|
||||||
|
md.Flush()
|
||||||
|
#wx.MessageBox('test')
|
||||||
|
|
||||||
|
def OnDuplicate(self, event):
|
||||||
|
um = self.m_user_models
|
||||||
|
id = um.GetSelection()
|
||||||
|
title = um.GetItemText(id)
|
||||||
|
parent = um.GetItemParent(id)
|
||||||
|
md = um.GetItemPyData(id)
|
||||||
|
child = um.AppendItem(parent, title + ' Copy')
|
||||||
|
um.SetPyData(child, md.Copy())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Приложение
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ThisApp(wx.App):
|
||||||
|
|
||||||
|
def OnInit(self):
|
||||||
|
# Создание главного окна
|
||||||
|
frame = MainFrame()
|
||||||
|
self.SetTopWindow(frame)
|
||||||
|
frame.Show(True)
|
||||||
|
return True
|
||||||
|
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
# Запуск приложения
|
||||||
|
#-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app = ThisApp(redirect = False)
|
||||||
|
app.MainLoop()
|
11
server.py
11
server.py
@ -196,7 +196,7 @@ class Job:
|
|||||||
self.result = data['result']
|
self.result = data['result']
|
||||||
# произошла ошибка
|
# произошла ошибка
|
||||||
elif ans == 'error':
|
elif ans == 'error':
|
||||||
WriteToLog('Error!')
|
WriteToLog('Error! ' + msg)
|
||||||
# недокументированный ответ приложения
|
# недокументированный ответ приложения
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
@ -243,17 +243,18 @@ class Job:
|
|||||||
def IsFinished(self):
|
def IsFinished(self):
|
||||||
return self.state == JOB_COMPLETED or self.state == JOB_STOPPED
|
return self.state == JOB_COMPLETED or self.state == JOB_STOPPED
|
||||||
|
|
||||||
|
def IsComplete(self):
|
||||||
|
return self.GetStatus() == JOB_COMPLETE
|
||||||
|
|
||||||
def Stop(self):
|
def Stop(self):
|
||||||
if self.proc and self.proc.poll() != None:
|
WriteToLog('Try to kill')
|
||||||
|
if self.proc and self.proc.poll() == None:
|
||||||
self.proc.kill()
|
self.proc.kill()
|
||||||
WriteToLog('Job killed')
|
WriteToLog('Job killed')
|
||||||
|
|
||||||
def GetState(self):
|
def GetState(self):
|
||||||
return self.state
|
return self.state
|
||||||
|
|
||||||
def IsComplete(self):
|
|
||||||
return self.GetStatus() == JOB_COMPLETE
|
|
||||||
|
|
||||||
def GetResult(self):
|
def GetResult(self):
|
||||||
return self.result
|
return self.result
|
||||||
|
|
||||||
|
10
task.py
10
task.py
@ -174,13 +174,17 @@ def main():
|
|||||||
p = mdef2.PackParams()
|
p = mdef2.PackParams()
|
||||||
pprint(p)
|
pprint(p)
|
||||||
|
|
||||||
mdef.Flush()
|
#mdef.Flush()
|
||||||
mdef2.Flush()
|
mdef2.Flush()
|
||||||
|
|
||||||
time.sleep(3)
|
time.sleep(1)
|
||||||
|
mdef2.job.Stop()
|
||||||
|
|
||||||
|
time.sleep(5)
|
||||||
|
print mdef2.job.GetState()
|
||||||
|
|
||||||
print 'RESULT'
|
print 'RESULT'
|
||||||
pprint(mdef.job.result)
|
#pprint(mdef.job.result)
|
||||||
pprint(mdef2.job.result)
|
pprint(mdef2.job.result)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -17,12 +17,14 @@
|
|||||||
"r": {
|
"r": {
|
||||||
"type": "double",
|
"type": "double",
|
||||||
"default": 6.28,
|
"default": 6.28,
|
||||||
|
"title": "Right edge",
|
||||||
"comment": "Right edge"
|
"comment": "Right edge"
|
||||||
},
|
},
|
||||||
|
|
||||||
"d": {
|
"d": {
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"default": 5,
|
"default": 5,
|
||||||
|
"title": "Serie deep",
|
||||||
"comment": "Number of members in taylor serie"
|
"comment": "Number of members in taylor serie"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
def write(msg):
|
def write(msg):
|
||||||
sys.stdout.write(str(msg) + '\n')
|
sys.stdout.write(str(msg) + '\n')
|
||||||
@ -80,11 +81,12 @@ def main():
|
|||||||
res.append([l, y])
|
res.append([l, y])
|
||||||
write(answer(round(l / r, 2)))
|
write(answer(round(l / r, 2)))
|
||||||
l += h
|
l += h
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
write(result(res))
|
write(result(res))
|
||||||
|
|
||||||
except:
|
except Exception, e:
|
||||||
write(error('Fatal error'))
|
write(error('Fatal error: ' + str(e)))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
Loading…
Reference in New Issue
Block a user