Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling of multiple open files #4

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 95 additions & 3 deletions xdot.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
import re
import optparse

import gi
gi.require_version('PangoCairo', '1.0')
gi.require_version('Gtk', '3.0')
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Gtk
Expand Down Expand Up @@ -226,6 +229,9 @@ def draw(self, cr, highlight=False):
def search_text(self, regexp):
return regexp.search(self.t) is not None

def __repr__(self):
return "<TextShape t=%s>"%self.t


class ImageShape(Shape):

Expand Down Expand Up @@ -477,6 +483,12 @@ def get_jump(self, x, y):
return Jump(self, self.src.x, self.src.y, highlight=set([self, self.src]))
return None

def search_text(self, text):
for shape in self.shapes:
if shape.search_text(text):
return True
return False

def __repr__(self):
return "<Edge %s -> %s>" % (self.src, self.dst)

Expand Down Expand Up @@ -1929,7 +1941,10 @@ class DotWindow(Gtk.Window):
ui = '''
<ui>
<toolbar name="ToolBar">
<toolitem action="NextFile"/>
<toolitem action="PrevFile"/>
<toolitem action="Open"/>
<toolitem action="CloseFile"/>
<toolitem action="Reload"/>
<toolitem action="Print"/>
<separator/>
Expand All @@ -1945,7 +1960,7 @@ class DotWindow(Gtk.Window):

base_title = 'Dot Viewer'

def __init__(self, widget=None):
def __init__(self, command_line_files, widget=None):
Gtk.Window.__init__(self)

self.graph = Graph()
Expand Down Expand Up @@ -1973,12 +1988,15 @@ def __init__(self, widget=None):
# Create actions
actiongroup.add_actions((
('Open', Gtk.STOCK_OPEN, None, None, None, self.on_open),
('CloseFile', Gtk.STOCK_CLOSE, None, None, "Close File", self.on_close_file),
('Reload', Gtk.STOCK_REFRESH, None, None, None, self.on_reload),
('Print', Gtk.STOCK_PRINT, None, None, "Prints the currently visible part of the graph", self.dotwidget.on_print),
('ZoomIn', Gtk.STOCK_ZOOM_IN, None, None, None, self.dotwidget.on_zoom_in),
('ZoomOut', Gtk.STOCK_ZOOM_OUT, None, None, None, self.dotwidget.on_zoom_out),
('ZoomFit', Gtk.STOCK_ZOOM_FIT, None, None, None, self.dotwidget.on_zoom_fit),
('Zoom100', Gtk.STOCK_ZOOM_100, None, None, None, self.dotwidget.on_zoom_100),
('NextFile', Gtk.STOCK_GO_BACK, None, None, None, self.on_go_back),
('PrevFile', Gtk.STOCK_GO_FORWARD, None, None, None, self.on_go_forward),
))

find_action = FindMenuToolAction("Find", None,
Expand All @@ -1997,6 +2015,20 @@ def __init__(self, widget=None):

vbox.pack_start(self.dotwidget, True, True, 0)

# Check whether the files from the command line exist
self.open_files = []
for filename in command_line_files:
if not os.path.exists(filename):
sys.stderr.write('Could not open file, ignore it: %st\n' % filename)
self.open_files.append(os.path.abspath(filename))
self.open_file_idx = 0

# Connect the Button click event of the drawing menu, in order
# to display a file menu
self.dotwidget.connect("button-press-event", self.on_file_menu)

self.connect('key-press-event', self.on_key_press_event)

self.last_open_dir = "."

self.set_focus(self.dotwidget)
Expand All @@ -2017,6 +2049,9 @@ def find_text(self, entry_text):
found_items = []
dot_widget = self.dotwidget
regexp = re.compile(entry_text)
for edge in dot_widget.graph.edges:
if edge.search_text(regexp):
found_items.append(edge)
for node in dot_widget.graph.nodes:
if node.search_text(regexp):
found_items.append(node)
Expand Down Expand Up @@ -2065,6 +2100,14 @@ def update_title(self, filename=None):

def open_file(self, filename):
try:
filename = os.path.abspath(filename)
if filename in self.open_files:
self.open_file_idx = self.open_files.index(filename)
else:
idx = self.open_file_idx
self.open_files = self.open_files[:idx] + [filename] \
+ self.open_files[idx:]

fp = file(filename, 'rt')
self.set_dotcode(fp.read(), filename)
fp.close()
Expand Down Expand Up @@ -2104,6 +2147,53 @@ def on_open(self, action):
def on_reload(self, action):
self.dotwidget.reload()

def on_close_file(self, action):
"""Close the currently displayed file"""
if len(self.open_files) == 1:
dlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR,
message_format="Cannot close last open file",
buttons=gtk.BUTTONS_OK)
dlg.set_title(self.base_title)
dlg.run()
dlg.destroy()
return

del self.open_files[self.open_file_idx]
self.open_file_idx = min(len(self.open_files)-1, self.open_file_idx)
self.open_file(self.open_files[self.open_file_idx])

def on_go_forward(self, action = None):
"""Display the next file"""
self.open_file_idx = min(self.open_file_idx + 1, len(self.open_files) - 1)
self.open_file(self.open_files[self.open_file_idx])

def on_go_back(self, action = None):
"""Display the previous file"""
self.open_file_idx = max(0, self.open_file_idx - 1)
self.open_file(self.open_files[self.open_file_idx])

def on_file_menu(self, widget, event):
if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3:
menu = Gtk.Menu()
for filename in self.open_files:
label = os.path.basename(filename)
item = Gtk.MenuItem()
item.set_label(label)
item.connect("activate", lambda _, f: self.open_file(f), filename)
menu.append(item)
menu.show_all()
self.menu = menu
menu.popup(None, None, None, None,
event.button, event.time)
return True

def on_key_press_event(self, widget, event):
if event.keyval == Gdk.KEY_bracketleft:
self.on_go_back()
return True
if event.keyval == Gdk.KEY_bracketright:
self.on_go_forward()
return True

class OptionParser(optparse.OptionParser):

Expand All @@ -2122,6 +2212,8 @@ def main():
Up, Down, Left, Right scroll
PageUp, +, = zoom in
PageDown, - zoom out
[ previous open file
] next open file
R reload dot file
F find
Q quit
Expand All @@ -2142,10 +2234,10 @@ def main():
help='assume input is already filtered into xdot format (use e.g. dot -Txdot)')

(options, args) = parser.parse_args(sys.argv[1:])
if len(args) > 1:
if len(args) == 0:
parser.error('incorrect number of arguments')

win = DotWindow()
win = DotWindow(args)
win.connect('delete-event', Gtk.main_quit)
win.set_filter(options.filter)
if len(args) >= 1:
Expand Down