From 5fceb3421e137b08f12f8546e19fb1bc6a4396d4 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 7 Jun 2013 11:13:31 -0600 Subject: [PATCH] move to pygobject and glade This ports the code to PyGObject, and also changes it to use Glade to edit the user interface elements. --- README | 10 +- gui/__init__.py | 18 +++ gui/icons/README | 1 + gui/icons/breakpoint-disabled-marker.png | Bin 0 -> 586 bytes gui/icons/breakpoint-marker.png | Bin 0 -> 710 bytes gui/icons/countpoint-marker.png | Bin 0 -> 241 bytes gui/icons/line-pointer.png | Bin 0 -> 601 bytes gui/icons/run-to-cursor.xpm | 40 +++++++ gui/icons/set-breakpoint.xpm | 52 +++++++++ gui/icons/step-into.xpm | 28 +++++ gui/icons/step-out.xpm | 28 +++++ gui/icons/step-over.xpm | 28 +++++ gui/icons/throbber.gif | Bin 0 -> 1542 bytes gui/invoker.py | 31 ++++++ gui/source.py | 39 +++---- gui/sourcewindow.xml | 135 +++++++++++++++++++++++ gui/startup.py | 12 +- 17 files changed, 393 insertions(+), 29 deletions(-) create mode 100644 gui/icons/README create mode 100644 gui/icons/breakpoint-disabled-marker.png create mode 100644 gui/icons/breakpoint-marker.png create mode 100644 gui/icons/countpoint-marker.png create mode 100644 gui/icons/line-pointer.png create mode 100644 gui/icons/run-to-cursor.xpm create mode 100644 gui/icons/set-breakpoint.xpm create mode 100644 gui/icons/step-into.xpm create mode 100644 gui/icons/step-out.xpm create mode 100644 gui/icons/step-over.xpm create mode 100644 gui/icons/throbber.gif create mode 100644 gui/invoker.py create mode 100644 gui/sourcewindow.xml diff --git a/README b/README index 125187e..28e6e05 100644 --- a/README +++ b/README @@ -15,14 +15,14 @@ GUIs in a few ways: To get started, install the prerequisites. You'll need a -Python-enabled gdb, PyGtk, and PyGktSourceView. (And maybe more -- if -you trip across something, let me know.) You'll need the Python +Python-enabled gdb, PyGObject, and PyGktSourceView. (And maybe more +-- if you trip across something, let me know.) You'll need the Python development package to compile the small C module that is included here. On Fedora I think this suffices: - sudo yum install gdb python-devel pygtksourceview pygtk2 + sudo yum install gdb python-devel gtksourceview3 pygobject3 After you install this, type "make". Now, start gdb and source the "SourceMe.py" file. This sets everything up. @@ -31,3 +31,7 @@ This adds a new "gui" command to gdb. Currently the only subcommand is "gui source", which pops up a source window. The source window will automatically track your progress when debugging. You can make multiple source windows; they will be reused in an LRU fashion. + +If you want to hack on this, you will need Glade to edit the UI +elements. For Fedora 18, you'll need a special hack to make the +gtksourceview widget visible to Glade. diff --git a/gui/__init__.py b/gui/__init__.py index e69de29..73e0db8 100644 --- a/gui/__init__.py +++ b/gui/__init__.py @@ -0,0 +1,18 @@ +# Copyright (C) 2013 Tom Tromey + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os.path + +self_dir = os.path.abspath(os.path.dirname(__file__)) diff --git a/gui/icons/README b/gui/icons/README new file mode 100644 index 0000000..6ad3eaf --- /dev/null +++ b/gui/icons/README @@ -0,0 +1 @@ +These icons were shamelessly taken from nemiver. diff --git a/gui/icons/breakpoint-disabled-marker.png b/gui/icons/breakpoint-disabled-marker.png new file mode 100644 index 0000000000000000000000000000000000000000..569c982498d4da24da468dc1cdbc872d12ea904e GIT binary patch literal 586 zcmV-Q0=4~#P)7HagrD> zH6{k7YD@QZ)rEgV1fk&0g@U$<^+vSj_D#x+I5Xe(y)F_nnK&-Q0|(9w@AE9?oM{0- zuPMLR%hC7o_4|7>?Ft53Gn>DDe0>rI;OY@2wmLJA(b?sH@Cv{yK;e`j*7sQ-R;HGk z^R9<*Q2mk|NE_t~2X2(a`xf+(CW!+p>hkm_Z@4ZwVTgqmj7A9oph!^7CO$42<@1Us zXloL7S;8(z6b>2Up_CEsR$yh28zezQvL>$8o5z6_wJQ7==GBHkeI`K!4q|!DEocn{ z=2z8k2Fq&>EE?e23=S&&E7RKYcf;@V&AJXLtVC0ZP)aWzX|S#ZtSbTQT)_G(V4iT8 zzd3R{w}^h2GlsgN3GYMdRYSWt&bN5|jgeq%%`~k{<6`_i|M=$a#?R)gr{E>^ Y08aGnfFqkISO5S307*qoM6N<$f<`O?2mk;8 literal 0 HcmV?d00001 diff --git a/gui/icons/breakpoint-marker.png b/gui/icons/breakpoint-marker.png new file mode 100644 index 0000000000000000000000000000000000000000..70eb997de8e57d775f35c5a6866a3f6ad3468b13 GIT binary patch literal 710 zcmV;%0y+JOP)E_(0f!EO zIEbsz+LnSMg%)a+wts{U=2fIqLt9HhL>vS~ba9LdqG$;9#rKk!_rB91rkXUJ`oUf9 zJ?GrZ{mvDV_@8H1N`9)YexZGT{%%ewH66+4KmG+KSrV3MK3f|c%=pL0)aU19GD-jN zkgMUaW0~g5a(p@Y>Cb_IjGsu5+uP*E2D!OO?(fr2B>1DR&#_E%>Mlo$JFu#%o;(bP z=Z9jk`|9EXux&u8;+Q~P9dttj)}m22xx4!|lF!cpC)Yn6|v|xRF+`ZV@c^C1#Ss{s-VO&4n+Nv^+j=)6QWJW197bSDI9#CrLdobv@D=V}|N0|zR znCk9ks;i5s&Q986V{~FMer;`aEv4R6Hj>EeZ^5ABSQdYcj4&ApFxlM9%V?BWi;Ij0 z0Yq-$5t&_WZ+G0~W#-~>=HhW)EiCX$QlE^&(QoOk+nX82R4eGzNa=#o>od5s;07*qoM6N<$f|@%<*#H0l literal 0 HcmV?d00001 diff --git a/gui/icons/countpoint-marker.png b/gui/icons/countpoint-marker.png new file mode 100644 index 0000000000000000000000000000000000000000..3700e55f6dfeb024478b023bdd0f8c44eb53e1f3 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=f!eQwFr$;k>VoV=XIQl&gV-2mm^Pdc$-njQYiIZd6R!xCy4b{{PgY*ldA-?ABWT8YS@+U)DU5js dcGrF>QU6)4d)#v!pA*n>22WQ%mvv4FO#l|?Rz3g# literal 0 HcmV?d00001 diff --git a/gui/icons/line-pointer.png b/gui/icons/line-pointer.png new file mode 100644 index 0000000000000000000000000000000000000000..ca8d86d4d44454fdcc18a8e0bf9fd385b70ba0fb GIT binary patch literal 601 zcmV-f0;c_mP)*8O|pfiP!;hDcoVUB^B|)5=Ol`B z5us87B0@j~=|S*Np$Kh2t34@J2&MT3+G;?NegkhF)lvzS>}+CQbeD(>13nC4GwJk6)m?qKAGBR_Nu;H>ccUMJ0c(zp0pSytPH^*#oX`Obk zj&MALNMX@nBCKg(^-qkhlX8!tf;`p74^$L{=Te=wSZgq?uSE3)FcDyOZz2&wcH>Ia zd%TH}VmK_>W%Yl4z4K80#}bPY>>_=tF?C7S|d) zqbcZwiJk3s4neQ^V#mB2p8e-uoO0~emy&%klWi c #F4F3F3", +", c #FEFEFE", +"' c #B72618", +" ", +" ", +" ", +" ........... ", +" .++++++++@.# ", +" .+++++@@@@.## ", +" .++@@$$@%%.... ", +" .@@@%$$%&&*==. ", +" .%%%%$$&*==--. ", +" .%&&*$$=---;;. ", +" .&*==$$;;;;>;. ", +" .=-$$$$$$>>,,. ", +" .;;;$$$$>,,,,. ", +" .;;>>$$,,,,,,. ", +" .>'''''''''',. ", +" .,'''''''''',. ", +" .,,,,,,,,,,,,. ", +" .,,,,,,,,,,,,. ", +" .............. ", +" ", +" ", +" "}; diff --git a/gui/icons/set-breakpoint.xpm b/gui/icons/set-breakpoint.xpm new file mode 100644 index 0000000..f3141f9 --- /dev/null +++ b/gui/icons/set-breakpoint.xpm @@ -0,0 +1,52 @@ +/* XPM */ +static char * breakpoint_xpm[] = { +"22 22 27 1", +" c None", +". c #394248", +"+ c #B1B5B8", +"@ c #B6B9BC", +"# c #B8BBBE", +"$ c #C0C0C0", +"% c #C6C9CB", +"& c #CBCED0", +"* c #D1D3D5", +"= c #BBBEC1", +"- c #BDC1C3", +"; c #C3C7C8", +"> c #C9CBCD", +", c #D4D6D8", +"' c #D6D8DA", +") c #0C1115", +"! c #DADCDD", +"~ c #DEE0E1", +"{ c #E2E3E5", +"] c #E6E7E8", +"^ c #E7E8E9", +"/ c #EBECED", +"( c #FF0000", +"_ c #000000", +": c #F3F4F4", +"< c #F7F8F9", +"[ c #FDFDFD", +" ", +" ", +" ", +" ................ ", +" .++++++@#$$%%&*. ", +" .++++@#=-;%>&,'. ", +" .++))))))))))'!. ", +" .+@#=-;>&*,'!~{. ", +" .#=))))&,,!~{]^. ", +" .-;;;,,/////^//. ", +" .;(((((/)))__::. ", +" .>(((((/////:<[. ", +" .*(((((/))))<[[. ", +" .'(((((/:<<[[[[. ", +" .!(((((:_____[[. ", +" .{]/:::<[[[[[[[. ", +" .//))))))[[[[[[. ", +" .::<<[[[[[[[[[[. ", +" ................ ", +" ", +" ", +" "}; diff --git a/gui/icons/step-into.xpm b/gui/icons/step-into.xpm new file mode 100644 index 0000000..e168c80 --- /dev/null +++ b/gui/icons/step-into.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * step_in_xpm[] = { +"22 22 3 1", +" c None", +". c #FF0000", +"+ c #000000", +" ", +" ", +" ", +" ", +" ......... ", +" ......... ", +" .. ", +" ++ .. ++ ", +" ++......++ ", +" ++ .... ++ ", +" ++ .. ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ", +" ", +" ", +" "}; diff --git a/gui/icons/step-out.xpm b/gui/icons/step-out.xpm new file mode 100644 index 0000000..1f10cf6 --- /dev/null +++ b/gui/icons/step-out.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * step_out_xpm[] = { +"22 22 3 1", +" c None", +". c #FF0000", +"+ c #000000", +" ", +" ", +" . ", +" .. ", +" ......... ", +" ......... ", +" .. .. ", +" ++ .. ++ . ", +" ++ .. ++ ", +" ++ .. ++ ", +" ++ .. ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ", +" ", +" ", +" "}; diff --git a/gui/icons/step-over.xpm b/gui/icons/step-over.xpm new file mode 100644 index 0000000..5b68cc5 --- /dev/null +++ b/gui/icons/step-over.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * step_over_xpm[] = { +"22 22 3 1", +" c None", +". c #FF0000", +"+ c #000000", +" ", +" ", +" ", +" . ", +" .. ", +" ................ ", +" ................ ", +" .. ", +" ++ ++ . ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ++ ++ ", +" ", +" ", +" "}; diff --git a/gui/icons/throbber.gif b/gui/icons/throbber.gif new file mode 100644 index 0000000000000000000000000000000000000000..529e72f45a2395e2eddb0487edbe79b306c92c3a GIT binary patch literal 1542 zcma)+ZA?>F7{_}rw{MqAdn^?TGVN^(w7}TqO{+3&F9nJ+R*E<<0&OXdX^es|GZF{4 zEl^%(9lp{U!Tk6YH4YyudgpHEiEi8)M~XPNk&IU z<2VigpuIfr-T(i>=Y2DhH)SO$HOVnigb(Dsi9bi^OfNlh;gy9lX!QL;2?>26z1K#P zV&uBmc3ztB!JQGe3%xin-RaY+qK3d98fkvdQN;t{oK0gq+21S5uC5%{i0Rkv4w<&D zJMjZD7~PJ7Ws}GES&9V@nF^RLDT|DSF@(;5sRA*CvH-&fm&e1b*w01Co_GW)!WWmq zeOZb@C}{*uR%lI>L5yacs>LSc&yub>OO|tgQr{&M!Pxk;eM1c&ROwWXCzb>?PAMLC z1GC6JXDUc(-m@u3aTC6;$74tGFI<-5LO#4LoR#vKh>|j7m0)u&+#r4f3us)g0tH^I zt;E*mux|86(!S&sVn}Jx(E{rR@KAZe3V3OQgh*I9umtZKPs|XRegw&V z*XWil!;da!)+BwsQ-QH9Pg^G5XT1P$nS_y40Tsy z{=wwwR=Ec@H0)=_Eu4eUa{DduV&e41fhwT}-kHt$uA zb}g8vv`P8=DavZKF<526AnGep^efD4R7poT41ZImDN+S_C?KFCwamgWUZJk`!~ zT#=Z`F1h2n%sgVJokp-VKc_!QT=Ag>&W4N}ZVs1IETePLkb?bUKWr#oNjnpyd9k)?!4M?%;92?~PwtjZ=-!&#>4sNe7_}r$O zson-Y-4)nvlJpZQC&U&6uKs?SCVNj09n8wAFu|P76)3h_vPe_N8`*{Q?^VX)r(?M%vvE=b?K;_!f8 z85)&S&2)|t3TrI%&F?Itlg^Dg1pG215&^1RM0`E5g%-D^w{1v;Ej@GFf#$mhQ?td50gdL-SzT{X6={H?<9MQh zTO&IDmziQe=nz0T8Ju01Xm47?mb69O*PU)%;OZFgx!P8>>(A#M=fWq3vBN`3q^FtF zv|HfcX=>^}AYVq9-PJrn@MXK6`Md#U4{x3jGJ<^XDaW#fs!Er#ODIP}1U_W7@EKVI zd^M_Eg2^QQ6DZ*yoe{9k_B%akiPtknp;_KPPaEMp_N?@h(ODHk$K`ainr|-+$frDT zQKU?@eheS0B!m-{o=?N*C;UFVSv* literal 0 HcmV?d00001 diff --git a/gui/invoker.py b/gui/invoker.py new file mode 100644 index 0000000..9fa21e8 --- /dev/null +++ b/gui/invoker.py @@ -0,0 +1,31 @@ +# Copyright (C) 2013 Tom Tromey + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import gdb + +class Invoker(object): + """A simple class that can invoke a gdb command. + This is suitable for use as an event handler in Gtk.""" + + def __init__(self, cmd): + self.cmd = cmd + + # This is invoked in the gdb thread to run the command. + def do_call(self): + gdb.execute(self.cmd, from_tty = True, to_string = True) + + # The object itself is the Gtk event handler. + def __call__(self, *args): + gdb.post_event(self.do_call) diff --git a/gui/source.py b/gui/source.py index d8bf176..9f9e7f8 100644 --- a/gui/source.py +++ b/gui/source.py @@ -16,9 +16,11 @@ # Source view. import gdb +from gui.invoker import Invoker import gui.startup -import gtksourceview2 as gtksourceview -import gtk +import os.path + +from gi.repository import Gtk, GtkSource, GObject class BufferManager: def __init__(self): @@ -32,7 +34,7 @@ class BufferManager: if filename in self.buffers: return self.buffers[filename] - buff = gtksourceview.Buffer() + buff = GtkSource.Buffer() buff.begin_not_undoable_action() try: contents = open(filename).read() @@ -142,30 +144,25 @@ class SourceWindow: def __init__(self): self.frame = None - # FIXME: set the size - # stuff in margins - self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.window.set_border_width(0) - self.window.set_title('GDB Source') - self.window.set_size_request(600, 400) + self.do_step = Invoker("step") + self.do_next = Invoker("next") + self.do_continue = Invoker("continue") - vbox = gtk.VBox(0, False) - swin = gtk.ScrolledWindow() - self.view = gtksourceview.View() - self.view.set_editable(False) - self.view.set_cursor_visible(False) - self.view.set_highlight_current_line(True) - self.window.add(vbox) - vbox.pack_start(swin, True, True, 0) - swin.add(self.view) + builder = Gtk.Builder() + builder.add_from_file(os.path.join(gui.self_dir, 'sourcewindow.xml')) - vbox.show_all() + builder.connect_signals(self) + self.window = builder.get_object("sourcewindow") + self.view = builder.get_object("view") - self.window.connect("delete-event", self.deleted) lru_handler.add(self) self.window.show() + def do_stop(self, *args): + # FIXME. + pass + def deleted(self, widget, event): lru_handler.remove(self) @@ -180,5 +177,5 @@ class SourceWindow: old_buffer = self.view.get_buffer() self.view.set_buffer(buff) buffer_manager.release_buffer(old_buffer) - gtk.idle_add(self._do_scroll, buff, srcline - 1) + GObject.idle_add(self._do_scroll, buff, srcline - 1) # self.view.scroll_to_iter(buff.get_iter_at_line(srcline), 0.0) diff --git a/gui/sourcewindow.xml b/gui/sourcewindow.xml new file mode 100644 index 0000000..635e8ed --- /dev/null +++ b/gui/sourcewindow.xml @@ -0,0 +1,135 @@ + + + + + + True + False + icons/run-to-cursor.xpm + + + True + False + icons/step-over.xpm + + + True + False + icons/step-into.xpm + + + False + Source + 600 + 400 + + + + True + False + vertical + + + True + False + + + True + False + Continue execution + Continue + True + image1 + + + + + False + True + + + + + True + False + Execute one line, stepping over function calls + Next + True + image2 + + + + False + True + + + + + True + False + Execute one line, stepping into function calls + Step + True + image3 + + + + + False + True + + + + + True + False + Interrupt the program + Stop + True + gtk-stop + + + + + False + True + + + + + False + True + 0 + + + + + True + True + in + + + True + True + True + False + 2 + 2 + False + 4 + True + True + False + + + + + True + True + 1 + + + + + + diff --git a/gui/startup.py b/gui/startup.py index 47b86c9..0f384d6 100644 --- a/gui/startup.py +++ b/gui/startup.py @@ -20,8 +20,8 @@ import Queue import fix_signals fix_signals.save() -import gtk -import glib +from gi.repository import Gtk, Gdk, GObject, GtkSource + import os (read_pipe, write_pipe) = os.pipe() @@ -43,15 +43,17 @@ class _GtkThread(threading.Thread): def run(self): global read_pipe - glib.io_add_watch(read_pipe, glib.IO_IN, self.handle_queue) - gtk.main() + GObject.io_add_watch(read_pipe, GObject.IO_IN, self.handle_queue) + GObject.type_register(GtkSource.View) + Gtk.main() _t = None def start_gtk(): global _t if _t is None: - gtk.gdk.threads_init() + GObject.threads_init() + Gdk.threads_init() _t = _GtkThread() _t.setDaemon(True) _t.start()