not stable! begin to realize save/open

This commit is contained in:
anwinged 2012-05-06 18:02:06 +00:00
parent 8a93d853af
commit 9e29e5f9c8
8 changed files with 235 additions and 34 deletions

View File

@ -186,7 +186,7 @@ class MainFrame(wx.Frame):
menubar.Append(menu, '&Run') menubar.Append(menu, '&Run')
menu = wx.Menu() menu = wx.Menu()
menu.Append(ID_SHOW_RESULT, 'Show numbers\tF7') menu.Append(ID_SHOW_RESULT, 'Show report\tF7')
menu.AppendSeparator() menu.AppendSeparator()
menu.Append(ID_SHOW_PLOT, 'Show plot\tF8') menu.Append(ID_SHOW_PLOT, 'Show plot\tF8')
menu.Append(ID_ADD_PLOT, 'Add plot') menu.Append(ID_ADD_PLOT, 'Add plot')
@ -228,7 +228,7 @@ class MainFrame(wx.Frame):
tb1.SetToolBitmapSize(wx.Size(16, 16)) tb1.SetToolBitmapSize(wx.Size(16, 16))
tb1.AddSimpleTool(ID_ADD_MODEL_SELECTED, "model-new", wx.Bitmap('share/model-add.png'), tb1.AddSimpleTool(ID_ADD_MODEL_SELECTED, "model-new", wx.Bitmap('share/model-add.png'),
'Add spacification to selected model') 'Add specification to selected model')
tb1.AddSimpleTool(ID_DUPLICATE_MODEL, "model-dup", wx.Bitmap('share/model-dup.png'), tb1.AddSimpleTool(ID_DUPLICATE_MODEL, "model-dup", wx.Bitmap('share/model-dup.png'),
'Duplicate selected model') 'Duplicate selected model')
tb1.AddSimpleTool(ID_DUPLICATE_TREE, "model-dup-tree", wx.Bitmap('share/model-dup-tree.png'), tb1.AddSimpleTool(ID_DUPLICATE_TREE, "model-dup-tree", wx.Bitmap('share/model-dup-tree.png'),

158
opal.py
View File

@ -13,14 +13,19 @@
import server import server
import task import task
import wx import wx
import wx.propgrid as wxpg
import wx.lib.plot as wxplot
import forms import forms
wxpg = forms.wxpg
wxplot = forms.wxplot
from wx.lib.embeddedimage import PyEmbeddedImage
import time import time
import threading import threading
import re import re
from wx.lib.embeddedimage import PyEmbeddedImage import json
import zlib
from pprint import pprint
class ModelData: class ModelData:
def __init__(self, server, model, parent_data = None): def __init__(self, server, model, parent_data = None):
@ -38,9 +43,9 @@ class ModelData:
self.res = None self.res = None
LINE_CURVE = 1 LINE_CURVE = 1
LINE_MARKER = 2 LINE_MARKER = 2
LINE_HISTOGRAM = 3 LINE_HISTOGRAM = 3
class LineData: class LineData:
""" """
@ -63,6 +68,10 @@ class LineData:
self.colour = colour # цвет: если не задан выбирается из списка self.colour = colour # цвет: если не задан выбирается из списка
self.style = style # стиль: если не задан, еспользуется по умолчанию self.style = style # стиль: если не задан, еспользуется по умолчанию
def GetModelTitle(self):
container, item = self.ums_ptr
return container.GetItemText(item)
def GetTitle(self): def GetTitle(self):
# если есть указатель на компонент с графиками, # если есть указатель на компонент с графиками,
# извлекаем оттуда название # извлекаем оттуда название
@ -98,6 +107,7 @@ class MainFrame(forms.MainFrame):
def __init__(self): def __init__(self):
forms.MainFrame.__init__(self, None) forms.MainFrame.__init__(self, None)
self.model = None
self.name_id = 1 self.name_id = 1
s = server.LocalServer() s = server.LocalServer()
@ -129,6 +139,10 @@ class MainFrame(forms.MainFrame):
self.Bind(wx.EVT_MENU, self.OnNewProject, self.Bind(wx.EVT_MENU, self.OnNewProject,
id = forms.ID_NEW) id = forms.ID_NEW)
self.Bind(wx.EVT_MENU, self.OnOpenProject,
id = forms.ID_OPEN)
self.Bind(wx.EVT_MENU, self.OnSaveProject,
id = forms.ID_SAVE)
self.Bind(wx.EVT_MENU, self.OnTest, self.Bind(wx.EVT_MENU, self.OnTest,
id = forms.ID_TEST) id = forms.ID_TEST)
@ -283,7 +297,7 @@ class MainFrame(forms.MainFrame):
""" """
def DoItem(item, model): def DoItem(item, model):
sp.SetPyData(item, model) sp.SetPyData(item, model)
for spec in model.GetSpecs(): for label, spec in model.GetSpecs().iteritems():
child = sp.AppendItem(item, spec.GetTitle()) child = sp.AppendItem(item, spec.GetTitle())
DoItem(child, spec) DoItem(child, spec)
@ -294,7 +308,7 @@ class MainFrame(forms.MainFrame):
sp.ExpandAll() sp.ExpandAll()
sp.SortChildren(root) sp.SortChildren(root)
def NewProject(self, model): def NewProject(self, model, create_default = True):
""" """
Начать новый проект: Начать новый проект:
0. Очичтить все компоненты 0. Очичтить все компоненты
@ -307,6 +321,8 @@ class MainFrame(forms.MainFrame):
self.m_params.Clear() self.m_params.Clear()
self.m_quick_result.Clear() self.m_quick_result.Clear()
self.m_plots.DeleteAllItems() self.m_plots.DeleteAllItems()
# фиксируем выбранную модель
self.model = model
# Строим спецификации # Строим спецификации
self.BuildSpecs(model) self.BuildSpecs(model)
# Очищаем окно пользовательских моделей # Очищаем окно пользовательских моделей
@ -314,7 +330,8 @@ class MainFrame(forms.MainFrame):
um = self.m_user_models um = self.m_user_models
um.DeleteAllItems() um.DeleteAllItems()
um.AddRoot('root') um.AddRoot('root')
self.AddModelToRoot(model) if create_default:
self.AddModelToRoot(model)
# Создаем корневой элемент для окна с графиками # Создаем корневой элемент для окна с графиками
self.m_plots.AddRoot('root') self.m_plots.AddRoot('root')
@ -329,8 +346,123 @@ class MainFrame(forms.MainFrame):
model = f.GetSelectedModel() model = f.GetSelectedModel()
if model: if model:
self.NewProject(model) self.NewProject(model)
self.do_nothing = False self.do_nothing = False
def OnOpenProject(self, event):
def WalkModels(source, root, models, model_def = None):
for key, value in source.iteritems():
label = value['model']
if label not in models:
raise KeyError, 'no "{}"'.format(label)
data = ModelData(self.server, models[label], model_def)
data.mdef.params = value['data']
if 'result' in value:
data.res = task.ResultData(value['result'])
# тут надо проверить все добавленные параметры
item = um.AppendItem(root, key)
um.SetPyData(item, data)
model_items[key] = item
WalkModels(value['um'], item, models[label].GetSpecs(), data)
try:
infile = 'data.opl'
data = {}
with open(infile, 'rb') as f:
data = json.loads(zlib.decompress(f.read()))
pprint(data)
tid = data['tid']
model_label = data['model']
model = self.server.CheckModel(tid, model_label)
if not model:
raise ValueError
self.NewProject(model, False)
um = self.m_user_models
model_items = {}
root = um.GetRootItem()
WalkModels(data['um'], root, {model.GetLabel(): model})
# except KeyError, e:
# wx.MessageBox("Can't parse saved file!", 'Error!')
# except ValueError, e:
# wx.MessageBox("Can't parse saved file!", 'Error!')
except Exception, e:
print 'Oops', type(e), e
def OnSaveProject(self, event):
def WalkModels(item, dest):
if item != um.GetRootItem():
data = um.GetPyData(item)
title = um.GetItemText(item)
mdef = data.mdef
dest[title] = {
'model': mdef.DD.GetLabel(),
'data': mdef.params,
'um': {}
}
if data.res:
dest[title]['result'] = data.res.DumpData()
dest = dest[title]['um']
child, _ = um.GetFirstChild(item)
while child.IsOk():
WalkModels(child, dest)
child = um.GetNextSibling(child)
def WalkPlots(root, dest):
# по всеи элементам первого уровня
item1, _ = self.m_plots.GetFirstChild(root)
while item1.IsOk():
# по всем элементам второго уровня
item2, _ = self.m_plots.GetFirstChild(item1)
lines = []
while item2.IsOk():
line = self.m_plots.GetPyData(item2)
data = {
'title': self.m_plots.GetItemText(item2),
'colx': line.columns[0],
'coly': line.columns[1],
'model': line.GetModelTitle(),
'type': line.type,
}
lines.append(data)
item2 = self.m_plots.GetNextSibling(item2)
title = self.m_plots.GetItemText(item1)
dest.append([title, lines])
item1 = self.m_plots.GetNextSibling(item1)
wx.BeginBusyCursor()
data = {}
data['tid'] = self.model.GetTaskId()
data['model'] = self.model.GetLabel()
um = self.m_user_models
data['um'] = {}
WalkModels(um.GetRootItem(), data['um'])
data['plots'] = []
WalkPlots(self.m_plots.GetRootItem(), data['plots'])
# pprint(data)
dump = json.dumps(data, indent = 2)
with open('data.opl', 'wb') as f:
f.write(zlib.compress(dump, 9))
# f.write(dump)
wx.EndBusyCursor()
# Функции непосредственной работы с моделями: # Функции непосредственной работы с моделями:
# создание, изменение, дублирование и прочее # создание, изменение, дублирование и прочее
@ -502,7 +634,6 @@ class MainFrame(forms.MainFrame):
# то все субмодели должны быть пересчитаны # то все субмодели должны быть пересчитаны
Walk(item) Walk(item)
def OnTest(self, event): def OnTest(self, event):
def Walk(item): def Walk(item):
@ -955,6 +1086,9 @@ class ThisApp(wx.App):
# Запуск приложения # Запуск приложения
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
if __name__ == "__main__": def main():
app = ThisApp(redirect = False) app = ThisApp(redirect = False)
app.MainLoop() app.MainLoop()
if __name__ == "__main__":
main()

2
opal.pyw Normal file
View File

@ -0,0 +1,2 @@
from opal import main
main()

View File

@ -17,6 +17,7 @@ import time
import datetime import datetime
import threading import threading
import subprocess import subprocess
import hashlib
import task import task
@ -47,8 +48,6 @@ class LocalServer:
self.queue_lock = threading.Lock() self.queue_lock = threading.Lock()
# init actions # init actions
self.log = open('log.txt', 'w')
self.WriteToLog('local server initialized') self.WriteToLog('local server initialized')
def Close(self): def Close(self):
@ -61,7 +60,7 @@ class LocalServer:
def WriteToLog(self, msg): def WriteToLog(self, msg):
tm = str(datetime.datetime.now()) tm = str(datetime.datetime.now())
msg = tm + ' ' + msg msg = tm + ' ' + msg
self.log.write(msg + '\n') # self.log.write(msg + '\n')
print msg print msg
def TestTaskData(self, data): def TestTaskData(self, data):
@ -86,13 +85,14 @@ class LocalServer:
self.TestTaskData(data) self.TestTaskData(data)
# вычисляем псевдоуникальный идентификатор модели # вычисляем псевдоуникальный идентификатор модели
tid = hash(data['meta']) tid = hashlib.md5(data['meta']).hexdigest()
# сохраняем описание задачи # сохраняем описание задачи
self.tasks_meta[tid] = { self.tasks_meta[tid] = {
'title': data.get('title', ''), 'title': data.get('title', ''),
'author': data.get('author', ''), 'author': data.get('author', ''),
'meta': data['meta'], 'meta': data['meta'],
'exec': line 'exec': line,
'models': []
} }
# выделяем описания моделей # выделяем описания моделей
@ -101,6 +101,7 @@ class LocalServer:
model_descr = task.DataDescription(None, label, data, tid) model_descr = task.DataDescription(None, label, data, tid)
# добавляем в список описаний # добавляем в список описаний
self.models.append(model_descr) self.models.append(model_descr)
self.tasks_meta[tid]['models'].append(model_descr)
self.WriteToLog('Task from "{}" asked'.format(line)) self.WriteToLog('Task from "{}" asked'.format(line))
except IOError, e: except IOError, e:
@ -116,6 +117,13 @@ class LocalServer:
def GetTaskMeta(self, tid): def GetTaskMeta(self, tid):
return self.tasks_meta.get(tid) return self.tasks_meta.get(tid)
def CheckModel(self, tid, model_label):
models = self.tasks_meta[tid]['models']
for model in models:
if model_label == model.GetLabel():
return model
return None
#-------------------------------------------------------------------------- #--------------------------------------------------------------------------
def CreateJob(self): def CreateJob(self):

18
setup.py Normal file
View File

@ -0,0 +1,18 @@
from distutils.core import setup
import py2exe
excludes = ['_gtkagg', '_tkagg', 'bsddb', 'curses', 'email', 'pywin.debugger',
'pywin.debugger.dbgcon', 'pywin.dialogs', 'tcl',
'Tkconstants', 'Tkinter']
setup(
name = 'Opal',
windows = ['opal.pyw'],
options = { "py2exe": {
"compressed": 2,
"optimize": 2,
"bundle_files": 1,
"excludes": excludes,
} },
zipfile = None,
)

65
task.py
View File

@ -42,6 +42,17 @@ class Parameter:
def Test(self, value): def Test(self, value):
return True return True
def DumpData(self):
"""
Возвращает данные в стандартных контейнерах
READ ONLY!!!
"""
return self.data
def LoadData(self, data):
self.data = data
class Value(Parameter): class Value(Parameter):
def __init__(self, label, value): def __init__(self, label, value):
if isinstance(value, dict): if isinstance(value, dict):
@ -70,6 +81,13 @@ class Column(Parameter):
except: except:
pass pass
def DumpData(self):
return [
self.GetLabel(),
self.GetType(),
self.GetTitle(),
]
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
class DataDescription: class DataDescription:
@ -86,10 +104,12 @@ class DataDescription:
par = Parameter(label, self.pdata[label]) par = Parameter(label, self.pdata[label])
self.pdata[label] = par self.pdata[label] = par
self.specs = []
# рекурсивное создание описаний спецификаций # рекурсивное создание описаний спецификаций
for label, data in self.data.get('spec', {}).iteritems(): self.specs = { label: DataDescription(self, label, data, self.tid)
self.specs.append(DataDescription(self, label, data, self.tid)) for label, data in self.data.get('spec', {}).iteritems() }
# for label, data in self.data.get('spec', {}).iteritems():
# self.specs.append(DataDescription(self, label, data, self.tid))
def GetLabel(self): def GetLabel(self):
return self.label return self.label
@ -115,6 +135,9 @@ class DataDescription:
def GetImage(self): def GetImage(self):
return self.data.get('img') return self.data.get('img')
def GetTaskId(self):
return self.tid
def __getitem__(self, label): def __getitem__(self, label):
return self.pdata.get(label) return self.pdata.get(label)
@ -158,16 +181,7 @@ class DataDefinition:
class ResultData: class ResultData:
def __init__(self, data): def __init__(self, data):
self.data = {} self.LoadData(data)
for key, value in data.get('data', {}).iteritems():
self.data[key] = Value(key, value)
table = data.get('table', [])
self.head = {}
self.table = []
if table:
self.head = [ Column(item) for item in table[0] ]
self.table = table[1:]
def GetColumns(self): def GetColumns(self):
return self.head return self.head
@ -187,3 +201,28 @@ class ResultData:
def Zip(self, col1, col2): def Zip(self, col1, col2):
return [ (row[col1], row[col2]) for row in self.rows ] return [ (row[col1], row[col2]) for row in self.rows ]
def DumpData(self):
data = {}
if self.data:
data['data'] = { key: self.data[key].DumpData()
for key in self.data }
if self.head:
head = [ col.DumpData() for col in self.columns ]
body = self.table
data['table'] = [head] + body
return data
def LoadData(self, data):
self.data = {}
for key, value in data.get('data', {}).iteritems():
self.data[key] = Value(key, value)
table = data.get('table', [])
self.head = []
self.table = []
if table:
self.head = [ Column(item) for item in table[0] ]
self.table = table[1:]

View File

@ -33,7 +33,7 @@
"n": { "n": {
"type": "int", "type": "int",
"default": 100, "default": 10,
"title": "Steps", "title": "Steps",
"comment": "Number of steps for algorithm" "comment": "Number of steps for algorithm"
} }

View File

@ -52,7 +52,7 @@ def serie(n, d, h, l = 0):
y = sin_taylor(l, d) y = sin_taylor(l, d)
yield (l, y) yield (l, y)
l += h l += h
time.sleep(0.01) # time.sleep(0.002)
def main(): def main():