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')
menu = wx.Menu()
menu.Append(ID_SHOW_RESULT, 'Show numbers\tF7')
menu.Append(ID_SHOW_RESULT, 'Show report\tF7')
menu.AppendSeparator()
menu.Append(ID_SHOW_PLOT, 'Show plot\tF8')
menu.Append(ID_ADD_PLOT, 'Add plot')
@ -228,7 +228,7 @@ class MainFrame(wx.Frame):
tb1.SetToolBitmapSize(wx.Size(16, 16))
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'),
'Duplicate selected model')
tb1.AddSimpleTool(ID_DUPLICATE_TREE, "model-dup-tree", wx.Bitmap('share/model-dup-tree.png'),

148
opal.py
View File

@ -13,14 +13,19 @@
import server
import task
import wx
import wx.propgrid as wxpg
import wx.lib.plot as wxplot
import forms
wxpg = forms.wxpg
wxplot = forms.wxplot
from wx.lib.embeddedimage import PyEmbeddedImage
import time
import threading
import re
from wx.lib.embeddedimage import PyEmbeddedImage
import json
import zlib
from pprint import pprint
class ModelData:
def __init__(self, server, model, parent_data = None):
@ -63,6 +68,10 @@ class LineData:
self.colour = colour # цвет: если не задан выбирается из списка
self.style = style # стиль: если не задан, еспользуется по умолчанию
def GetModelTitle(self):
container, item = self.ums_ptr
return container.GetItemText(item)
def GetTitle(self):
# если есть указатель на компонент с графиками,
# извлекаем оттуда название
@ -98,6 +107,7 @@ class MainFrame(forms.MainFrame):
def __init__(self):
forms.MainFrame.__init__(self, None)
self.model = None
self.name_id = 1
s = server.LocalServer()
@ -129,6 +139,10 @@ class MainFrame(forms.MainFrame):
self.Bind(wx.EVT_MENU, self.OnNewProject,
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,
id = forms.ID_TEST)
@ -283,7 +297,7 @@ class MainFrame(forms.MainFrame):
"""
def DoItem(item, model):
sp.SetPyData(item, model)
for spec in model.GetSpecs():
for label, spec in model.GetSpecs().iteritems():
child = sp.AppendItem(item, spec.GetTitle())
DoItem(child, spec)
@ -294,7 +308,7 @@ class MainFrame(forms.MainFrame):
sp.ExpandAll()
sp.SortChildren(root)
def NewProject(self, model):
def NewProject(self, model, create_default = True):
"""
Начать новый проект:
0. Очичтить все компоненты
@ -307,6 +321,8 @@ class MainFrame(forms.MainFrame):
self.m_params.Clear()
self.m_quick_result.Clear()
self.m_plots.DeleteAllItems()
# фиксируем выбранную модель
self.model = model
# Строим спецификации
self.BuildSpecs(model)
# Очищаем окно пользовательских моделей
@ -314,6 +330,7 @@ class MainFrame(forms.MainFrame):
um = self.m_user_models
um.DeleteAllItems()
um.AddRoot('root')
if create_default:
self.AddModelToRoot(model)
# Создаем корневой элемент для окна с графиками
self.m_plots.AddRoot('root')
@ -329,8 +346,123 @@ class MainFrame(forms.MainFrame):
model = f.GetSelectedModel()
if model:
self.NewProject(model)
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)
def OnTest(self, event):
def Walk(item):
@ -955,6 +1086,9 @@ class ThisApp(wx.App):
# Запуск приложения
#-----------------------------------------------------------------------------
if __name__ == "__main__":
def main():
app = ThisApp(redirect = False)
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 threading
import subprocess
import hashlib
import task
@ -47,8 +48,6 @@ class LocalServer:
self.queue_lock = threading.Lock()
# init actions
self.log = open('log.txt', 'w')
self.WriteToLog('local server initialized')
def Close(self):
@ -61,7 +60,7 @@ class LocalServer:
def WriteToLog(self, msg):
tm = str(datetime.datetime.now())
msg = tm + ' ' + msg
self.log.write(msg + '\n')
# self.log.write(msg + '\n')
print msg
def TestTaskData(self, data):
@ -86,13 +85,14 @@ class LocalServer:
self.TestTaskData(data)
# вычисляем псевдоуникальный идентификатор модели
tid = hash(data['meta'])
tid = hashlib.md5(data['meta']).hexdigest()
# сохраняем описание задачи
self.tasks_meta[tid] = {
'title': data.get('title', ''),
'author': data.get('author', ''),
'meta': data['meta'],
'exec': line
'exec': line,
'models': []
}
# выделяем описания моделей
@ -101,6 +101,7 @@ class LocalServer:
model_descr = task.DataDescription(None, label, data, tid)
# добавляем в список описаний
self.models.append(model_descr)
self.tasks_meta[tid]['models'].append(model_descr)
self.WriteToLog('Task from "{}" asked'.format(line))
except IOError, e:
@ -116,6 +117,13 @@ class LocalServer:
def GetTaskMeta(self, 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):

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):
return True
def DumpData(self):
"""
Возвращает данные в стандартных контейнерах
READ ONLY!!!
"""
return self.data
def LoadData(self, data):
self.data = data
class Value(Parameter):
def __init__(self, label, value):
if isinstance(value, dict):
@ -70,6 +81,13 @@ class Column(Parameter):
except:
pass
def DumpData(self):
return [
self.GetLabel(),
self.GetType(),
self.GetTitle(),
]
#-------------------------------------------------------------------------------
class DataDescription:
@ -86,10 +104,12 @@ class DataDescription:
par = Parameter(label, self.pdata[label])
self.pdata[label] = par
self.specs = []
# рекурсивное создание описаний спецификаций
for label, data in self.data.get('spec', {}).iteritems():
self.specs.append(DataDescription(self, label, data, self.tid))
self.specs = { label: 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):
return self.label
@ -115,6 +135,9 @@ class DataDescription:
def GetImage(self):
return self.data.get('img')
def GetTaskId(self):
return self.tid
def __getitem__(self, label):
return self.pdata.get(label)
@ -158,16 +181,7 @@ class DataDefinition:
class ResultData:
def __init__(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:]
self.LoadData(data)
def GetColumns(self):
return self.head
@ -187,3 +201,28 @@ class ResultData:
def Zip(self, col1, col2):
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": {
"type": "int",
"default": 100,
"default": 10,
"title": "Steps",
"comment": "Number of steps for algorithm"
}

View File

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