mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Update IDE
* Add save template * Misc UI fixes
This commit is contained in:
parent
2142219e20
commit
e8a44ae066
@ -4,6 +4,120 @@
|
||||
<!-- interface-requires gtksourceview 0.0 -->
|
||||
<!-- interface-requires vte 0.0 -->
|
||||
<!-- interface-naming-policy project-wide -->
|
||||
<object class="GtkMenu" id="da_menu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="da_menu_copy_color">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="label" translatable="yes">Copy Color</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuItem" id="da_menu_save_template">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="label" translatable="yes">Save Template</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_save_template_activate" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkDialog" id="save_template_dialog">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Save Template</property>
|
||||
<property name="window_position">center-on-parent</property>
|
||||
<property name="destroy_with_parent">True</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child internal-child="vbox">
|
||||
<object class="GtkVBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">1</property>
|
||||
<child internal-child="action_area">
|
||||
<object class="GtkHButtonBox" id="dialog-action_area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="layout_style">end</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button1">
|
||||
<property name="label">gtk-ok</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button2">
|
||||
<property name="label">gtk-cancel</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_stock">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">end</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage" id="template">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="stock">gtk-missing-image</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="template_entry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="invisible_char">•</property>
|
||||
<property name="text" translatable="yes">template.pgm</property>
|
||||
<property name="primary_icon_activatable">False</property>
|
||||
<property name="secondary_icon_activatable">False</property>
|
||||
<property name="primary_icon_sensitive">True</property>
|
||||
<property name="secondary_icon_sensitive">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<action-widgets>
|
||||
<action-widget response="-5">button1</action-widget>
|
||||
<action-widget response="-6">button2</action-widget>
|
||||
</action-widgets>
|
||||
</object>
|
||||
<object class="GtkWindow" id="top_window">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK</property>
|
||||
@ -359,23 +473,19 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkEventBox" id="eventbox1">
|
||||
<object class="GtkDrawingArea" id="drawingarea">
|
||||
<property name="width_request">200</property>
|
||||
<property name="height_request">200</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
|
||||
<signal name="button-press-event" handler="on_button_press" swapped="no"/>
|
||||
<signal name="button-release-event" handler="on_button_release" swapped="no"/>
|
||||
<signal name="motion-notify-event" handler="on_motion_notify" swapped="no"/>
|
||||
<child>
|
||||
<object class="GtkImage" id="framebuffer_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="stock">gtk-missing-image</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
@ -63,7 +63,19 @@ class OMVGtk:
|
||||
self.terminal.set_size(80,24)
|
||||
self.terminal.set_pty(self.fd)
|
||||
|
||||
self.framebuffer = self.builder.get_object("framebuffer_image")
|
||||
# get drawingarea
|
||||
self.pixbuf = None
|
||||
self.drawingarea = self.builder.get_object("drawingarea")
|
||||
self.da_menu = self.builder.get_object("da_menu")
|
||||
|
||||
# selection coords
|
||||
self.x1 =0
|
||||
self.y1 =0
|
||||
self.x2 =0
|
||||
self.y2 =0
|
||||
self.selection_started=False
|
||||
self.sel_ended=False
|
||||
|
||||
|
||||
#connect signals
|
||||
signals = {
|
||||
@ -72,9 +84,11 @@ class OMVGtk:
|
||||
"on_stop_clicked" : self.stop_clicked,
|
||||
"on_motion_notify" : self.motion_notify,
|
||||
"on_button_press" : self.button_pressed,
|
||||
"on_button_release" : self.button_released,
|
||||
"on_open_file" : self.open_file,
|
||||
"on_save_file" : self.save_file,
|
||||
"on_save_file_as" : self.save_file_as,
|
||||
"on_save_template_activate" : self.save_template,
|
||||
}
|
||||
self.builder.connect_signals(signals)
|
||||
|
||||
@ -93,43 +107,60 @@ class OMVGtk:
|
||||
def stop_clicked(self, widget):
|
||||
openmv.stop_script();
|
||||
|
||||
def button_pressed(self, widget, event):
|
||||
self.x1 = int(event.x)
|
||||
self.y1 = int(event.y)
|
||||
self.x2 = int(event.x)
|
||||
self.y2 = int(event.y)
|
||||
self.selection_started = True
|
||||
|
||||
def button_released(self, widget, event):
|
||||
self.x2 = int(event.x)
|
||||
self.y2 = int(event.y)
|
||||
self.selection_started = False
|
||||
self.da_menu.popup(None, None, None, event.button, event.time, None)
|
||||
self.da_menu.show_all()
|
||||
|
||||
def motion_notify(self, widget, event):
|
||||
x = int(event.x)
|
||||
y = int(event.y)
|
||||
pixbuf = self.framebuffer.get_pixbuf()
|
||||
if x < pixbuf.get_width() and y < pixbuf.get_height():
|
||||
pixel = pixbuf.get_pixels_array()[y][x]
|
||||
rgb = "(%d, %d, %d)" %(pixel[0], pixel[1], pixel[2])
|
||||
self.statusbar.pop(self.statusbar_ctx)
|
||||
self.statusbar.push(self.statusbar_ctx, rgb)
|
||||
self.x2 = int(event.x)
|
||||
self.y2 = int(event.y)
|
||||
# if x < self.pixbuf.get_width() and y < self.pixbuf.get_height():
|
||||
# pixel = self.pixbuf.get_pixels_array()[y][x]
|
||||
# rgb = "(%d, %d, %d)" %(pixel[0], pixel[1], pixel[2])
|
||||
# self.statusbar.pop(self.statusbar_ctx)
|
||||
# self.statusbar.push(self.statusbar_ctx, rgb)
|
||||
|
||||
def button_pressed(self, widget, event):
|
||||
x = int(event.x)
|
||||
y = int(event.y)
|
||||
pixbuf = self.framebuffer.get_pixbuf()
|
||||
if x < pixbuf.get_width() and y < pixbuf.get_height():
|
||||
pixel = pixbuf.get_pixels_array()[y][x]
|
||||
print (pixel[0], pixel[1], pixel[2])
|
||||
|
||||
def update_fb(self):
|
||||
# read framebuffer
|
||||
def update_drawing(self):
|
||||
# read drawingarea
|
||||
fb = openmv.dump_fb()
|
||||
|
||||
# convert to RGB888 and blit
|
||||
pixbuf = gtk.gdk.pixbuf_new_from_array(fb[2].reshape((fb[1], fb[0], 3)), gtk.gdk.COLORSPACE_RGB, 8)
|
||||
pixbuf = pixbuf.scale_simple(fb[0]*2, fb[1]*2, gtk.gdk.INTERP_BILINEAR)
|
||||
self.framebuffer.set_from_pixbuf(pixbuf)
|
||||
gobject.idle_add(omvgtk.update_fb);
|
||||
self.pixbuf = gtk.gdk.pixbuf_new_from_array(fb[2].reshape((fb[1], fb[0], 3)), gtk.gdk.COLORSPACE_RGB, 8)
|
||||
self.pixbuf = self.pixbuf.scale_simple(fb[0]*2, fb[1]*2, gtk.gdk.INTERP_BILINEAR)
|
||||
|
||||
self.drawingarea.realize();
|
||||
cm = self.drawingarea.window.get_colormap()
|
||||
gc = self.drawingarea.window.new_gc(foreground=cm.alloc_color('#FFFFFF',True,False))
|
||||
|
||||
self.drawingarea.set_size_request(fb[0]*2, fb[1]*2)
|
||||
self.drawingarea.window.draw_pixbuf(gc, self.pixbuf, 0, 0, 0, 0)
|
||||
if self.selection_started or self.da_menu.flags() & gtk.MAPPED:
|
||||
self.drawingarea.window.draw_rectangle(gc, False, self.x1, self.y1, self.x2-self.x1, self.y2-self.y1)
|
||||
|
||||
# reschedule callback
|
||||
gobject.idle_add(omvgtk.update_drawing);
|
||||
|
||||
def open_file(self, widget):
|
||||
dialog = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
|
||||
dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
dialog.set_current_folder("./examples/")
|
||||
filter = gtk.FileFilter()
|
||||
filter.set_name("python")
|
||||
filter.add_pattern("*.py")
|
||||
dialog.add_filter(filter)
|
||||
ff = gtk.FileFilter()
|
||||
ff.set_name("python")
|
||||
ff.add_pattern("*.py")
|
||||
dialog.add_filter(ff)
|
||||
|
||||
if dialog.run() == gtk.RESPONSE_OK:
|
||||
with open(dialog.get_filename(), "r") as file:
|
||||
@ -140,6 +171,24 @@ class OMVGtk:
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
def save_template(self, widget):
|
||||
self.da_menu.hide()
|
||||
x = self.x1
|
||||
y = self.y1
|
||||
w = self.x2-self.x1
|
||||
h = self.y2-self.y1
|
||||
|
||||
entry = self.builder.get_object("template_entry")
|
||||
template = self.builder.get_object("template")
|
||||
dialog = self.builder.get_object("save_template_dialog")
|
||||
dialog.set_transient_for(self.window);
|
||||
|
||||
template.set_from_pixbuf(self.pixbuf.subpixbuf(x, y, w, h))
|
||||
dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
if dialog.run() == gtk.RESPONSE_OK:
|
||||
openmv.save_template(x/2, y/2, w/2, h/2, entry.get_text()) #Use Scale
|
||||
dialog.hide()
|
||||
|
||||
def save_file(self, widget):
|
||||
with open(self.file_path, "w") as file:
|
||||
file.write(self.buffer.get_text(self.buffer.get_start_iter(), self.buffer.get_end_iter()))
|
||||
@ -149,10 +198,10 @@ class OMVGtk:
|
||||
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
|
||||
dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
dialog.set_current_folder("./examples/")
|
||||
filter = gtk.FileFilter()
|
||||
filter.set_name("python")
|
||||
filter.add_pattern("*.py")
|
||||
dialog.add_filter(filter)
|
||||
ff = gtk.FileFilter()
|
||||
ff.set_name("python")
|
||||
ff.add_pattern("*.py")
|
||||
dialog.add_filter(ff)
|
||||
|
||||
if dialog.run() == gtk.RESPONSE_OK:
|
||||
with open(dialog.get_filename(), "w") as file:
|
||||
@ -180,5 +229,5 @@ class OMVGtk:
|
||||
if __name__ == "__main__":
|
||||
omvgtk = OMVGtk()
|
||||
omvgtk.window.show_all()
|
||||
gobject.idle_add(omvgtk.update_fb);
|
||||
gobject.idle_add(omvgtk.update_drawing);
|
||||
gtk.main()
|
||||
|
||||
@ -15,7 +15,7 @@ __INTERFACE = 0
|
||||
__ALTSETTING= 1
|
||||
__IN_EP =0x81
|
||||
__OUT_EP =0x01
|
||||
__TIMEOUT =1000
|
||||
__TIMEOUT =5000
|
||||
|
||||
|
||||
# USB Debug commands
|
||||
@ -25,6 +25,7 @@ __USBDBG_EXEC_SCRIPT=3
|
||||
__USBDBG_READ_SCRIPT=4
|
||||
__USBDBG_WRITE_SCRIPT=5
|
||||
__USBDBG_STOP_SCRIPT=6
|
||||
__USBDBG_SAVE_TEMPLATE=7
|
||||
|
||||
def init():
|
||||
global __dev
|
||||
@ -89,6 +90,11 @@ def exec_script(buf):
|
||||
def stop_script():
|
||||
__dev.ctrl_transfer(0x41, __USBDBG_STOP_SCRIPT, 0, __INTERFACE, None, __TIMEOUT)
|
||||
|
||||
def save_template(x, y, w, h, name):
|
||||
buf = struct.pack("IIII", x, y, w, h)
|
||||
__dev.ctrl_transfer(0x41, __USBDBG_SAVE_TEMPLATE, len(buf), __INTERFACE, None, __TIMEOUT)
|
||||
__dev.write(__OUT_EP, buf, __INTERFACE, __TIMEOUT)
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv)!= 2:
|
||||
print 'usage: openmv.py <script>'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user