seascope-0.8/000755 000000 000000 00000000000 12230074172 013137 5ustar00rootroot000000 000000 seascope-0.8/LICENSE000644 000000 000000 00000002554 12230074152 014150 0ustar00rootroot000000 000000 Copyright (c) 2010 Anil Kumar All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.seascope-0.8/MANIFEST.in000644 000000 000000 00000000020 12230074152 014663 0ustar00rootroot000000 000000 include LICENSE seascope-0.8/src/000755 000000 000000 00000000000 12230074152 013724 5ustar00rootroot000000 000000 seascope-0.8/src/view/000755 000000 000000 00000000000 12230074152 014676 5ustar00rootroot000000 000000 seascope-0.8/src/view/CodemarkView.py000644 000000 000000 00000005005 12230074152 017630 0ustar00rootroot000000 000000 #!/usr/bin/env python # Copyright (c) 2012 Anthony Liu # All rights reserved. # # License: BSD import sys from array import * class CodemarkManager(): def __init__(self, parent=None): self.haystack = [] def check(self, filename, line): if self.haystack.count((filename, line)): return 1 return 0 def append(self, filename, line): if self.check(filename, line) == 0: self.haystack.append((filename, line)) return self.haystack.index((filename, line)) def delete(self, filename, line): if self.haystack.count((filename, line)) == 0: return -1 else: self.haystack.remove((filename, line)) return 0 def delete_index(self, index): if self.count() <= index: return -1 elif index < 0: return -1 else: self.haystack.pop(index) return 0 def count(self): return len(self.haystack) def get(self, index): if self.count() <= index: return (None, None) elif index < 0: return (None, None) else: (filename, line) = self.haystack.pop(index) self.haystack.insert(index, (filename, line)) return (filename, line) def clear(self): del self.haystack[:] def codemarks(self): return self.haystack def dump(self): for i in range(len(self.haystack)): print >> sys.stderr, "cm index ", i, " ", self.haystack[i] ############################################################################# # # Basic unit test # ############################################################################# if __name__ == '__main__': cm = CodemarkManager() # # case 1, basic add, delete # print >> sys.stderr, "Initial empty" print >> sys.stderr, "cm has ", cm.count(), "items (0)" cm.append("file1", 100) cm.append("file2", 200) cm.append("file3", 300) print >> sys.stderr, "cm has " , cm.count(), "items (3) " cm.delete("file1", 100) print >> sys.stderr, "cm has " , cm.count(), "items (2)" cm.delete("file2", 100) # not existed print >> sys.stderr, "cm has " , cm.count(), "items (2)" cm.delete_index(1) print >> sys.stderr, "cm has " , cm.count(), "items (1)" # # case 2, dump # for i in range(cm.count()): (f, l) = cm.get(i) print >> sys.stderr, f, " (#", l, ")" # # case 3, duplicate # index = cm.append("file4", 400) print >> sys.stderr, "index for file4 #400 is " , index index = cm.append("file4", 400) print >> sys.stderr, "index for file4 #400 is " , index, " (again)" print >> sys.stderr, "cm has " , cm.count(), "items (2) " # # case 4, dump for eye examine # print >> sys.stderr, "cm dump for final check" cm.dump() seascope-0.8/src/view/filecontext/000755 000000 000000 00000000000 12230074152 017222 5ustar00rootroot000000 000000 seascope-0.8/src/view/filecontext/plugins/000755 000000 000000 00000000000 12230074152 020703 5ustar00rootroot000000 000000 seascope-0.8/src/view/filecontext/plugins/__init__.py000644 000000 000000 00000000112 12230074152 023006 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD seascope-0.8/src/view/filecontext/plugins/ctags_view/000755 000000 000000 00000000000 12230074152 023036 5ustar00rootroot000000 000000 seascope-0.8/src/view/filecontext/plugins/ctags_view/__init__.py000644 000000 000000 00000000416 12230074152 025150 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os def name(): return 'ctags' def run_plugin(filename, parent): import CtagsView CtagsView.run(filename, parent) def description(): d = 'ctags description' return d priority = 500 seascope-0.8/src/view/filecontext/plugins/ctags_view/CtagsView.py000644 000000 000000 00000014203 12230074152 025304 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * import CtagsManager # Search Result class SR: NONE = 0 LSKIP = 1 LUPD = 2 MATCH = 3 RUPD = 4 RSKIP = 5 def __init__(self, k): self.line = k self.left = 0 self.right = 1000000 self.item = None self.done = False class CtagsListItem(QTreeWidgetItem): def __init__(self, li): QTreeWidgetItem.__init__(self, li) if li[2] in [ 'class', 'interface', 'struct', 'type', 'enum', 'constrainer', '' ]: self.set_bold() if li[2] in [ 'reactor' ]: brush = self.foreground(0) brush.setColor(Qt.gray) self.setForeground(0, brush) def set_bold(self): f = self.font(0) f.setBold(True) self.setFont(0, f) def column_val(self, col): return str(self.data(col, Qt.DisplayRole).toString()) def line_val(self): return (int(self.column_val(1))) class CtagsList(QTreeWidget): def __init__(self, parent=None, isTree=False): QTreeWidget.__init__(self) self.setColumnCount(3) self.setHeaderLabels(['Name', 'Line', 'Type']) #self.setMinimumHeight(200) self.setMinimumWidth(50) self.setFont(QFont("San Serif", 8)) if isTree: self.setIndentation(12) self.setExpandsOnDoubleClick(False) #self.setAnimated(True) else: self.setIndentation(-2) self.setAllColumnsShowFocus(True) def add_ct_result(self, res): for line in res: item = CtagsListItem(line) self.addTopLevelItem(item) #self.sortItems(1, Qt.AscendingOrder) #self.resizeColumnsToContents(1) self.resizeColumnToContents(0) self.resizeColumnToContents(1) self.resizeColumnToContents(2) def recurseTreeAdd(self, t, p): for k, v in t.items(): if k == '+': continue if k == '*': for line in v: item = CtagsListItem(line) p.addChild(item) continue if '+' in v: item = CtagsListItem(v['+']) else: item = CtagsListItem([k, '', '', '']) p.addChild(item) self.recurseTreeAdd(v, item) self.setItemExpanded(p, True) def add_ctree_result(self, res): p = self.invisibleRootItem() self.recurseTreeAdd(res, p) #self.sortItems(1, Qt.AscendingOrder) #self.resizeColumnsToContents(1) self.resizeColumnToContents(0) self.resizeColumnToContents(1) self.resizeColumnToContents(2) def ed_cursor_changed(self, line, pos): line = line + 1 item = self.currentItem() if not item: item = self.topLevelItem(0) if not item: return if (item.line_val() == line): pass elif (item.line_val() < line): while True: next_item = self.itemBelow(item) if not next_item: break if (next_item.line_val() > line): break item = next_item else: while True: prev_item = self.itemAbove(item) if not prev_item: break item = prev_item if (item.line_val() <= line): break self.setCurrentItem(item) def search_item_check(self, item, sr): try: val = item.line_val() except: return SR.NONE if val < sr.left: return SR.LSKIP if val < sr.line: sr.left = val sr.item = item return SR.LUPD if val == sr.line: sr.left = val sr.item = item sr.done = True return SR.MATCH if val < sr.right: sr.right = val if not sr.item: sr.item = item return SR.RUPD return SR.RSKIP def search_recursive(self, p, sr): inx = 0; r = SR.NONE while inx < p.childCount(): item = p.child(inx) if not item.childCount(): break inx += 1 if r < SR.MATCH: r = self.search_item_check(item, sr) if r == SR.MATCH: return self.search_recursive(item, sr) if sr.done: return if not inx < p.childCount(): return last_item = p.child(p.childCount() - 1) r = self.search_item_check(last_item, sr) if r <= sr.MATCH: return r = SR.NONE while inx < p.childCount(): item = p.child(inx) inx += 1 r = self.search_item_check(item, sr) if r >= SR.MATCH: return def search_tree(self, line, pos): line = line + 1 sr = SR(line) p = self.invisibleRootItem() self.search_recursive(p, sr) self.setCurrentItem(sr.item) class CtagsListPage(QWidget): sig_goto_line = pyqtSignal(int) def __init__(self, parent=None): QWidget.__init__(self) self.le = QLineEdit() self.ct = CtagsList(self) vlay = QVBoxLayout() vlay.addWidget(self.le) vlay.addWidget(self.ct) self.setLayout(vlay) self.le.textChanged.connect(self.le_textChanged) self.le.returnPressed.connect(self.le_returnPressed) self.ct.itemActivated.connect(self.ct_itemActivated) def le_textChanged(self, text): #if (len(str(text)) == 1): #self.ct.keyboardSearch('') self.ct.keyboardSearch('') self.ct.keyboardSearch(text) def le_returnPressed(self): items = self.ct.selectedItems() if len(items) == 0: return self.ct.itemActivated.emit(items[0], 0) def ct_itemActivated(self, item): try: line = int(str(item.data(1, Qt.DisplayRole).toString())) except: return self.sig_goto_line.emit(line) self.le.clear() def keyPressEvent(self, ev): if ev.key() in [Qt.Key_Up, Qt.Key_Down, Qt.Key_PageUp or Qt.Key_PageDown]: self.ct.keyPressEvent(ev) return @staticmethod def do_ct_query(filename, parent): page = CtagsListPage(parent) res = CtagsManager.ct_query(filename) page.ct.add_ct_result(res) parent.add_page(page, 'C') parent.sig_ed_cursor_changed.connect(page.ct.ed_cursor_changed) class CtagsTreePage(QWidget): sig_goto_line = pyqtSignal(int) def __init__(self, parent=None): QWidget.__init__(self) self.ct = CtagsList(self, isTree=True) vlay = QVBoxLayout() vlay.addWidget(self.ct) self.setLayout(vlay) self.ct.itemActivated.connect(self.ct_itemActivated) def ct_itemActivated(self, item): try: line = int(str(item.data(1, Qt.DisplayRole).toString())) except: return self.sig_goto_line.emit(line) @staticmethod def do_ct_query(filename, parent): (res, isTree) = CtagsManager.ct_tree_query(filename) if not isTree: return page = CtagsTreePage(parent) page.ct.add_ctree_result(res) parent.add_page(page, 'T') parent.sig_ed_cursor_changed.connect(page.ct.search_tree) def run(filename, parent): CtagsListPage.do_ct_query(filename, parent) CtagsTreePage.do_ct_query(filename, parent) seascope-0.8/src/view/filecontext/plugins/ctags_view/CtagsManager.py000644 000000 000000 00000012172 12230074152 025747 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import subprocess import re, os def _eintr_retry_call(func, *args): while True: try: return func(*args) except OSError, e: if e.errno == errno.EINTR: continue raise def cmdForFile(f): suffix_cmd_map = [] custom_map = os.getenv('SEASCOPE_CTAGS_SUFFIX_CMD_MAP') if custom_map: custom_map = eval(custom_map) suffix_cmd_map += custom_map #args = 'ctags -n -u --fields=+K -f - --extra=+q' #args = 'ctags -n -u --fields=+Ki -f -' args = 'ctags -n -u --fields=+K -f -' suffix_cmd_map.append( ['', args] ) for (suffix, cmd) in suffix_cmd_map: if f.endswith(suffix): return cmd return None def ct_query(filename): args = cmdForFile(filename) args = args.split() args.append(filename) try: proc = subprocess.Popen(args, stdout=subprocess.PIPE) (out_data, err_data) = _eintr_retry_call(proc.communicate) out_data = out_data.split('\n') except Exception as e: out_data = [ 'Failed to run ctags cmd\tignore\t0;\t ', 'cmd: %s\tignore\t0;\t ' % ' '.join(args), 'error: %s\tignore\t0;\t ' % str(e), 'ctags not installed ?\tignore\t0;\t ', ] res = [] for line in out_data: if (line == ''): break line = line.split('\t') num = line[2].split(';', 1)[0] line = [line[0], num, line[3]] res.append(line) return res is_OrderedDict_available = False try: # OrderedDict available only in python >= 2.7 from collections import OrderedDict is_OrderedDict_available = True except: pass def emptyOrderedDict(): if is_OrderedDict_available: return OrderedDict({}) return {} class CtagsTreeBuilder: def __init__(self): self.symTree = emptyOrderedDict() def cmdForFile(self, f): suffix_cmd_map = [] custom_map = os.getenv('SEASCOPE_CTAGS_SUFFIX_CMD_MAP') if custom_map: custom_map = eval(custom_map) suffix_cmd_map += custom_map #args = 'ctags -n -u --fields=+K -f - --extra=+q' #args = 'ctags -n -u --fields=+Ki -f -' args = 'ctags -n -u --fields=+K-f-t -f -' suffix_cmd_map.append( ['', args] ) for (suffix, cmd) in suffix_cmd_map: if f.endswith(suffix): return cmd return None def runCtags(self, f): args = self.cmdForFile(f) args = args.split() args.append(f) # In python >= 2.7 can use subprocess.check_output # output = subprocess.check_output(args) # return output proc = subprocess.Popen(args, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate() return out_data def parseCtagsOutput(self, data): data = re.split('\r?\n', data) res = [] for line in data: if line == '': continue try: line = line.split('\t', 4) res.append(line) except: print 'bad line:', line return res def addToSymLayout(self, sc): t = self.symTree if sc and sc != '': for s in re.split('::|\.', sc): if s not in t: t[s] = emptyOrderedDict() t = t[s] def addToSymTree(self, sc, line): t = self.symTree if sc and sc != '': for s in re.split('::|\.', sc): assert s in t t = t[s] cline = [line[0], line[2].split(';')[0], line[3]] if line[0] in t: #print line[0], 'in', t x = t[line[0]] if '+' not in x: x['+'] = cline return if '*' not in t: t['*'] = [] t['*'].append(cline) #print '...', t, line def buildTree(self, data): type_list = [ 'namespace', 'class', 'interface', 'struct', 'union', 'enum', 'function' ] # build layout using 5th field for line in data: if len(line) == 4: continue try: sd = dict([ x.split(':', 1) for x in line[4].split('\t')]) except: print 'bad line', line continue line[4] = sd count = 0 for t in type_list: if t in sd: self.addToSymLayout(sd[t]) count = count + 1 if count != 1: print '******** count == 1 *********' print data print line #assert count == 1 if len(self.symTree) == 0: return (data, False) for line in data: if len(line) == 4: self.addToSymTree(None, line) continue sd = line[4] count = 0 for t in type_list: if t in sd: self.addToSymTree(sd[t], line) count = count + 1 if count != 1: print '******** count == 1 *********' print data print line #assert count == 1 return (self.symTree, True) def doQuery(self, filename): try: output = self.runCtags(filename) output = self.parseCtagsOutput(output) output = self.buildTree(output) except Exception as e: print str(e) output = [None, False] return output def ct_tree_query(filename): ct = CtagsTreeBuilder() output = ct.doQuery(filename) return output if __name__ == '__main__': import optparse import sys depth = 0 def recursePrint(t): global depth for k, v in t.items(): if k == '*': for line in v: print '%s%s' % (' ' * depth, line) continue if k == '+': continue if '+' in v: k = v['+'] print '%s%s' % (' ' * depth, k) depth = depth + 4 recursePrint(v) depth = depth - 4 op = optparse.OptionParser() (options, args) = op.parse_args() if len(args) != 1: print 'Please specify a file' sys.exit(-1) (output, isTree) = ct_tree_query(args[0]) if isTree: recursePrint(output) else: for line in output: print line seascope-0.8/src/view/filecontext/plugins/generic_view/000755 000000 000000 00000000000 12230074152 023351 5ustar00rootroot000000 000000 seascope-0.8/src/view/filecontext/plugins/generic_view/__init__.py000644 000000 000000 00000000565 12230074152 025470 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os def name(): return 'generic_cmd' def run_plugin(filename, parent, cmd=None): import GenericView GenericView.run(filename, parent, cmd=cmd) def description(): d = 'generic cmd description' return d def cmd_name(): import GenericView return GenericView.cmd_name() priority = 100 seascope-0.8/src/view/filecontext/plugins/generic_view/GenericView.py000644 000000 000000 00000004423 12230074152 026135 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * class GenericResItem(QTreeWidgetItem): def __init__(self, li): QTreeWidgetItem.__init__(self, li) def column_val(self, col): return str(self.data(col, Qt.DisplayRole).toString()) def line_val(self): return (int(self.column_val(1))) class GenericRes(QTreeWidget): def __init__(self, parent=None): QTreeWidget.__init__(self) self.setColumnCount(1) self.setHeaderLabels(['Result']) #self.setMinimumHeight(200) self.setMinimumWidth(50) self.setFont(QFont("San Serif", 8)) self.setIndentation(-2) self.setAllColumnsShowFocus(True) def add_result(self, res): for line in res: item = GenericResItem([line]) self.addTopLevelItem(item) class GenericFileCmdPage(QWidget): sig_goto_line = pyqtSignal(int) def __init__(self, parent=None): QWidget.__init__(self) self.ct = GenericRes(self) vlay = QVBoxLayout() #self.lbl = QLabel() #vlay.addWidget(self.lbl) vlay.addWidget(self.ct) self.setLayout(vlay) self.ct.itemActivated.connect(self.ct_itemActivated) def ct_itemActivated(self, item): try: line = int(str(item.data(1, Qt.DisplayRole).toString())) except: return self.sig_goto_line.emit(line) @staticmethod def run_plugin(cmd, filename, parent): if '%f' in cmd: args = cmd.replace('%f', filename) args = args.strip().split() else: args = cmd.strip().split() args.append(filename) import subprocess try: proc = subprocess.Popen(args, stdout=subprocess.PIPE) (res, err_data) = proc.communicate() except Exception as e: res = '%s\n%s' % (' '.join(args), str(e)) import re res = [ x.strip() for x in re.split('\r?\n', res.strip()) ] page = GenericFileCmdPage(parent) page.cmd = cmd #page.lbl.setText(' '.join(args)) page.ct.add_result(res) parent.add_page(page, cmd) def cmd_name(): cmd_list = [ #'stat', #'ls %f', #'ls %f %f' ] import os cmd = os.getenv('SEASCOPE_FC_CUSTOM_CMD') if cmd: cmd_list += [ x.strip() for x in cmd.split(';') ] return list(set(cmd_list)) def run(filename, parent, cmd=None): if cmd: cmd_list = [ cmd ] else: cmd_list = cmd_name() for cmd in cmd_list: GenericFileCmdPage.run_plugin(cmd, filename, parent) seascope-0.8/src/view/filecontext/__init__.py000644 000000 000000 00000002127 12230074152 021335 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import re, os from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * #import DialogManager #from plugins import PluginHelper fc_plugins = [] fc_dict = {} def _load_plugins(module, directory): pluginImports = __import__(module, globals(), locals()) print 'Scanning for view plugins...' plist = [] pdict = {} for i in sorted(os.listdir(directory)): path = os.path.join( directory, i, '__init__.py' ) if os.path.isfile( path ): p = __import__( '%s.%s' % (module, i), globals(), locals(), ['*'] ) plist.append(p) pdict[p.name()] = p if not hasattr(p, 'priority'): p.priority = 0 plist = sorted(plist, key=lambda p: p.priority, reverse=True) for p in plist: print '\t', p.name() return (plist, pdict) def load_plugins(): global fc_plugins, fc_dict (fc_plugins, fc_dict) = _load_plugins('view.filecontext.plugins', 'view/filecontext/plugins') def run_plugins(filename, parent): for p in fc_plugins: if not hasattr(p, 'cmd_name'): p.run_plugin(filename, parent) seascope-0.8/src/view/CallView.py000644 000000 000000 00000012371 12230074152 016762 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * class CallTreeWidgetItem(QTreeWidgetItem): def __init__(self, li): QTreeWidgetItem.__init__(self, li) func = li[0] if (func == ""): self.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicatorWhenChildless) else: self.setChildIndicatorPolicy(QTreeWidgetItem.ShowIndicator) self.is_done = False def set_no_children(self): self.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicatorWhenChildless) def column_val(self, col): return str(self.data(col, Qt.DisplayRole).toString()) def add_result(self, res): self.is_done = True res_list = [] ret_val = True for line in res: if (line[0] == ""): continue if (line[0] == self.column_val(0)): if (line [1] == self.column_val(1) and line[2] == self.column_val(2)): continue self.addChild(CallTreeWidgetItem(line)) if (self.childCount() == 0): self.set_no_children() # resize column self.treeWidget().resizeColumnToContents(0) self.treeWidget().resizeColumnToContents(1) self.treeWidget().resizeColumnToContents(2) self.treeWidget().resizeColumnToContents(3) # hdr #self.treeWidget().header().setDefaultAlignment(Qt.AlignRight) return ret_val class CallTreeWidget(QTreeWidget): sig_show_file_line = pyqtSignal(str, int) def __init__(self, parent, cmd_func, cmd_id, cmd_opt, hint_file): QTreeWidget.__init__(self, parent) self.is_busy = False self.cmd_func = cmd_func self.cmd_id = cmd_id self.cmd_opt = cmd_opt self.hint_file = hint_file self.itemExpanded.connect(self.ctree_itemExpanded) self.itemActivated.connect(self.ctree_itemActivated) self.setExpandsOnDoubleClick(False) self.setColumnCount(4) self.setHeaderLabels(['Tag', 'File', 'Line', 'Text']) self.setSelectionMode(QAbstractItemView.SingleSelection) #self.resize(QSize(800, 500)) self.setMinimumWidth(800) self.setMinimumHeight(500) ##sel behaviour #self.setSelectionBehavior(QAbstractItemView.SelectRows) ## set the font self.setFont(QFont("San Serif", 8)) #self.setTextElideMode(Qt.ElideLeft) self.setAllColumnsShowFocus(True) def add_root(self, name): parent = CallTreeWidgetItem([name, '', '', '']) self.addTopLevelItem(parent) parent.setExpanded(True) def mousePressEvent(self, m_ev): QTreeWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): self.last_minx = self.indexAt(m_ev.pos()) def ctree_itemActivated(self, item, col): filename = item.column_val(1) try: line = int(item.column_val(2)) except: return self.sig_show_file_line.emit(filename, line) def ctree_itemExpanded(self, item): if (item.is_done): return tag = str(item.data(0, Qt.DisplayRole).toString()) if str(item.data(1, Qt.DisplayRole).toString()) == '': opt = self.cmd_opt else: opt = None if (self.is_busy): return self.is_busy = True self.pbar = QProgressBar(self) self.pbar.setMinimum(0) self.pbar.setMaximum(0) self.pbar.show() ## add result rquery = {} rquery['cmd'] = self.cmd_id rquery['req'] = tag rquery['opt'] = opt hfile = str(item.data(1, Qt.DisplayRole).toString()) if hfile == '': hfile = self.hint_file rquery['hint_file'] = hfile sig_res = self.cmd_func(rquery) self.query_item = item sig_res[0].connect(self.ctree_add_result) def ctree_add_result(self, req, res): self.query_item.add_result(res) self.is_busy = False if self.pbar: self.pbar.setParent(None) self.pbar = None class CallTreeWindow(QMainWindow): sig_show_file_line = pyqtSignal(str, int) parent = None def __init__(self, req, cmd_func, cmd_args, cmd_opt, hint_file): QMainWindow.__init__(self, CallTreeWindow.parent) self.req = req self.setWindowTitle(req) self.setFont(QFont("San Serif", 8)) w = QWidget() self.setCentralWidget(w) self.vlay = QVBoxLayout() w.setLayout(self.vlay) self.sw = QStackedWidget() self.hlay = QHBoxLayout() self.vlay.addLayout(self.hlay) self.vlay.addWidget(self.sw) self.bgrp = QButtonGroup() self.bgrp.buttonClicked.connect(self.set_current) self.bgrp.setExclusive(True) self.btn = [] self.ctree = [] for inx in range(len(cmd_args)): # cmd format: [ cmd_id, cmd_str, cmd_tip ] cmd = cmd_args[inx] btn = QToolButton() btn.setText(cmd[1]) btn.setToolTip(cmd[2]) #btn.setFlat(True) btn.setCheckable(True) self.bgrp.addButton(btn, inx) self.hlay.addWidget(btn) ct = CallTreeWidget(self, cmd_func, cmd[0], cmd_opt, hint_file) ct.sig_show_file_line.connect(self.sig_show_file_line) self.sw.addWidget(ct) self.btn.append(btn) self.ctree.append(ct) self.hlay.addStretch(0) self.set_current(self.btn[0]) def set_current(self, btn): inx = self.bgrp.id(btn) self.btn[inx].setChecked(True) self.sw.setCurrentIndex(inx) ct = self.ctree[inx] if ct.topLevelItemCount() == 0: ct.add_root(self.req) ct.setFocus() def ctree_show_file_line(filename, line): parent = CallTreeWindow.parent parent.raise_() parent.activateWindow() parent.show_file_line(filename, line) def create_page(req, cmd_func, cmd_args, cmd_opt, hint_file): w = CallTreeWindow(req, cmd_func, cmd_args, cmd_opt, hint_file) w.sig_show_file_line.connect(ctree_show_file_line) w.show() seascope-0.8/src/view/__init__.py000644 000000 000000 00000000355 12230074152 017012 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD __all__ = ["CallView", "ClassGraphView", "FileFuncGraphView", "EdView", "FileView", "ResView"] def load_plugins(): import filecontext filecontext.load_plugins()seascope-0.8/src/view/FileContextView.py000644 000000 000000 00000004120 12230074152 020324 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * import filecontext class FileContextView(QTabWidget): sig_goto_line = pyqtSignal(int) sig_ed_cursor_changed = pyqtSignal(int, int) def __init__(self, parent=None): QTabWidget.__init__(self) self.setTabPosition(QTabWidget.South) def add_page(self, page, title): page.sig_goto_line.connect(self.sig_goto_line) self.addTab(page, title) self.setCurrentWidget(page) def run(self, filename): self.filename = filename filecontext.run_plugins(filename, self) def rerun(self, filename): inx = self.currentIndex() self.clear() self.run(filename) self.setCurrentIndex(inx) def focus_search_ctags(self): for inx in range(self.count()): page = self.widget(inx) if hasattr(page, 'le') and hasattr(page.le, 'setFocus'): self.setCurrentWidget(page) page.le.setFocus() break def get_already_opened_cmd_list(self): a_cmd_list = [] for inx in range(self.count()): page = self.widget(inx) if hasattr(page, 'cmd'): a_cmd_list.append(page.cmd) return a_cmd_list def get_plugin_cmd_list(self): a_cmd_list = self.get_already_opened_cmd_list() cmd_list = [] for p in filecontext.fc_plugins: if not hasattr(p, 'cmd_name'): continue cmd_name = p.cmd_name() if not cmd_name: continue if not isinstance(cmd_name, list): if cmd_name == '': continue cmd_name = [ cmd_name ] for cmd in cmd_name: if cmd in a_cmd_list: continue cmd_list.append((cmd, p)) return cmd_list def menu_act_triggered_cb(self, act): act.plugin.run_plugin(self.filename, self, cmd=act.cmd_name) def mousePressEvent(self, m_ev): cmd_list = self.get_plugin_cmd_list() if len(cmd_list) == 0: return if (m_ev.button() == Qt.RightButton): # setup popup menu pmenu = QMenu() pmenu.triggered.connect(self.menu_act_triggered_cb) for (cmd_name, p) in cmd_list: act = pmenu.addAction(cmd_name) act.plugin = p act.cmd_name = cmd_name pmenu.exec_(QCursor.pos()) pmenu = None seascope-0.8/src/view/FileView.py000644 000000 000000 00000016003 12230074152 016762 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os from PyQt4.QtGui import * from PyQt4.QtCore import * dir_prefix = None class DirTab(QWidget): sig_show_file = pyqtSignal(str) def __init__(self, parent=None): QWidget.__init__(self) self.is_ft = False # Tree view self.tmodel = QFileSystemModel() self.tmodel.setRootPath(QDir.rootPath()) self.tview = QTreeView() self.tview.setHeaderHidden(True) self.ted = QLineEdit() self.completer = QCompleter() self.completer.setCompletionMode(QCompleter.PopupCompletion) self.ted.setToolTip("Current folder") self.ted.setCompleter(self.completer) self.tdbtn = QPushButton() self.tdbtn.setIcon(QApplication.style().standardIcon(QStyle.SP_DirIcon)) self.tdbtn.setToolTip("Open folder for browsing") self.trbtn = QPushButton() self.trbtn.setIcon(QApplication.style().standardIcon(QStyle.SP_BrowserReload)) self.trbtn.setToolTip("Reset to common top-level folder of file in list") self.completer.setModel(self.tmodel) self.tview.setModel(self.tmodel) thlay = QHBoxLayout() thlay.addWidget(self.ted) thlay.addWidget(self.tdbtn) thlay.addWidget(self.trbtn) tvlay = QVBoxLayout() tvlay.addLayout(thlay) tvlay.addWidget(self.tview) self.setLayout(tvlay) self.tview.activated.connect(self.tview_itemActivated) self.tdbtn.clicked.connect(self.change_btn_cb) self.ted.editingFinished.connect(self.ted_editingFinished) self.trbtn.clicked.connect(self.reset_btn_cb) self.hide_view_columns(self.tview) def hide_view_columns(self, view): header = view.header() for col in range(header.count()): if col > 0: view.setColumnHidden(col, True) def tview_itemActivated(self): list = self.tview.selectionModel().selectedIndexes() for item in list: if self.tmodel.fileInfo(item).isFile(): self.sig_show_file.emit(self.tmodel.fileInfo(item).absoluteFilePath()) def set_tab_name(self, dirstr): # Set tab name inx = self.parent.indexOf(self) try: if dirstr != dir_prefix: name = os.path.split(dirstr)[1] else: name = '' self.parent.setTabText(inx, name) except: pass def dir_reset(self, dirstr): self.set_tab_name(dirstr) self.tview.setRootIndex(self.tmodel.index(dirstr)) self.ted.setText(dirstr) def ted_editingFinished(self): path = str(self.ted.text()) if not os.path.isdir(path): path = os.path.dirname(path) if os.path.isdir(path): self.dir_reset(path) else: self.dir_reset(dir_prefix) def change_btn_cb(self): fdlg = QFileDialog(None, "Choose directory to browse") fdlg.setFileMode(QFileDialog.Directory) fdlg.setOptions(QFileDialog.ShowDirsOnly) # and QFileDialog.HideNameFilterDetails) fdlg.setDirectory(self.ted.text()) if (fdlg.exec_()): browse_dir = fdlg.selectedFiles()[0] self.dir_reset(str(browse_dir)) def reset_btn_cb(self): self.dir_reset(dir_prefix) def resizeEvent(self, event): self.tdbtn.setMaximumHeight(self.ted.height()) self.trbtn.setMaximumHeight(self.ted.height()) class FileTab(QWidget): sig_show_file = pyqtSignal(str) def __init__(self, parent=None): QWidget.__init__(self) self.is_ft = True # List view self.le = QLineEdit() self.lview = QTreeWidget(self) self.lview.setColumnCount(2) self.lview.setHeaderLabels(['File', 'Path']) self.lview.setFont(QFont("San Serif", 8)) self.lview.setIndentation(-2) self.lview.setAllColumnsShowFocus(True) lvlay = QVBoxLayout() lvlay.addWidget(self.le) lvlay.addWidget(self.lview) self.setLayout(lvlay) self.le.textChanged.connect(self.le_textChanged) self.le.returnPressed.connect(self.le_returnPressed) self.lview.itemActivated.connect(self.lview_itemActivated) global dir_prefix dir_prefix = QDir.rootPath() def le_textChanged(self, text): if (text == ''): return self.lview.keyboardSearch('') self.lview.keyboardSearch(text) def le_returnPressed(self): self.le.clear() items = self.lview.selectedItems() if len(items) == 0: return self.lview.itemActivated.emit(items[0], 0) def lview_itemActivated(self, item): filename = str(item.data(1, Qt.DisplayRole).toString()) if self.is_rel_path: filename = filename.replace("...", dir_prefix, 1) self.sig_show_file.emit(filename) def keyPressEvent(self, ev): if ev.key() in [Qt.Key_Up, Qt.Key_Down, Qt.Key_PageUp or Qt.Key_PageDown]: self.lview.keyPressEvent(ev) return def search_file_cb(self): self.le.setFocus() self.le.selectAll() def clear(self): global dir_prefix dir_prefix = QDir.rootPath() self.is_rel_path = False self.le.clear() self.lview.clear() def add_files(self, flist): global dir_prefix self.clear() dir_prefix = os.path.dirname(os.path.commonprefix(flist)) if len(dir_prefix) > 16: self.is_rel_path = True for f in flist: if self.is_rel_path: f = f.replace(dir_prefix, "...", 1) item = QTreeWidgetItem([os.path.basename(f), f]) self.lview.addTopLevelItem(item) #if (self.lview.topLevelItemCount() > 0): #self.lview.resizeColumnToContents(0) #self.lview.resizeColumnToContents(1) self.lview.sortByColumn(0, Qt.AscendingOrder) class FileTree(QTabWidget): sig_show_file = pyqtSignal(str) def __init__(self, parent=None): QTabWidget.__init__(self) self.setMovable(True) t = FileTab() icon = QApplication.style().standardIcon(QStyle.SP_FileDialogDetailedView) self.addTab(t, icon, '') self.ft = t self.dlist = [] self.new_dir_tab_cb() self.clear() # setup popup menu self.pmenu = QMenu() self.pmenu.addAction("&New Dir View", self.new_dir_tab_cb) self.pmenu.addAction("&Close Active Dir View", self.close_active_dir_tab_cb) self.pmenu.addAction("&Close All Dir View", self.close_all_dir_tab_cb) def new_dir_tab_cb(self, d=None): t = DirTab() t.parent = self self.dlist.append(t) icon = QApplication.style().standardIcon(QStyle.SP_DirClosedIcon) self.addTab(t, icon, '') if d: t.dir_reset(d) else: t.reset_btn_cb() def close_all_dir_tab_cb(self): for t in self.dlist: inx = self.indexOf(t) self.removeTab(inx) self.dlist = [] # Always have atleast one dir view self.new_dir_tab_cb() def open_dir_view(self, filename): d = os.path.dirname(str(filename)) self.new_dir_tab_cb(d) def close_active_dir_tab_cb(self): inx = self.currentIndex() if inx < 0: return t = self.widget(inx) if t.is_ft: return if self.count() <= 2: self.close_all_dir_tab_cb() return self.dlist.remove(t) self.removeTab(inx) def addTab(self, t, icon, x): t.sig_show_file.connect(self.sig_show_file) QTabWidget.addTab(self, t, icon, x) if self.count() > 2: inx = self.indexOf(t) else: inx = 0 self.setCurrentIndex(inx) def mousePressEvent(self, m_ev): QTabWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): self.pmenu.exec_(QCursor.pos()) def search_file_cb(self): self.ft.search_file_cb() self.setCurrentWidget(self.ft) def clear(self): self.ft.clear() self.close_all_dir_tab_cb() def add_files(self, flist): self.ft.add_files(flist) for t in self.dlist: t.reset_btn_cb() seascope-0.8/src/view/EdViewRW.py000644 000000 000000 00000006664 12230074152 016720 0ustar00rootroot000000 000000 #!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import re from PyQt4 import QtGui from PyQt4.QtGui import * from PyQt4.QtCore import * from EdView import * # inherit from EditView, add editing support. class EditorViewRW(EditorView): sig_file_modified = pyqtSignal(bool) def __init__(self, parent=None): EditorView.__init__(self, parent) # use default settings. EditorView.ed_settings_1(self) def open_file(self, filename): self.open_file_begin(filename) ## Show this file in the editor data = open(filename).read() try: data = data.decode("UTF-8") except: pass self.setText(data) ## process for modifiled. self.setModified(False) self.modificationChanged.connect(self.modifiedChanged) ## support edit self.setReadOnly(False) self.open_file_end() def modifiedChanged(self): self.sig_file_modified.emit(self.isModified()) # FIXME: too simple for big files or remote files. def save_file(self, filename): if(self.isModified()): fobj = open(filename, 'w') if (not fobj.closed): fobj.write(str(self.text().toUtf8())) fobj.flush() fobj.close() self.setModified(False) class EditorPageRW(EditorPage): def new_editor_view(self): return EditorViewRW(self) class EditorBookRW(EditorBook): def new_editor_page(self): return EditorPageRW() def save_file_at_inx(self, inx): if inx < 0: return page = self.widget(inx) filename = page.get_filename() if filename: page.ev.save_file(filename) page.fcv.rerun(filename) def save_current_page(self): inx = self.currentIndex() self.save_file_at_inx(inx) def save_tab_list(self, inx_list): for inx in inx_list: self.save_file_at_inx(inx) def save_all_file(self): inx_list = range(self.count()) self.save_tab_list(inx_list) def page_modified_cb(self, isModifiled): inx = self.currentIndex() filename = self.tabText(inx) # Sign modified. if isModifiled: self.tabBar().setTabTextColor(inx, Qt.red) else: self.tabBar().setTabTextColor(inx, Qt.black) def close_cb(self, inx): page = self.widget(self.currentIndex()) if page.ev.isModified(): if DialogManager.show_yes_no("Do you want to save file ?"): self.save_current_page() self.removeTab(inx) def has_modified_file(self, inx_list): for i in inx_list: page = self.widget(i) if page.ev.isModified(): return True return False def close_list_common(self, type): inx_list = self.tab_list(self.currentIndex(), type) if len(inx_list) == 0: return if self.has_modified_file(inx_list): msg = 'Closing all %s.\nSave changes ?' % type if DialogManager.show_yes_no(msg): self.save_tab_list() self.remove_tab_list(inx_list) else: msg = 'Close all %s ?' % type if not DialogManager.show_yes_no(msg): return self.remove_tab_list(inx_list) def show_file_line(self, filename, line, hist=True): EditorBook.show_file_line(self, filename, line, hist=hist) page = self.currentWidget() # modified signal callback page.ev.sig_file_modified.connect(self.page_modified_cb) # redo editing callback def redo_edit_cb(self): ed = self.currentWidget() if ed: ed.ev.redo() # undo editing callback def undo_edit_cb(self): ed = self.currentWidget() if ed: ed.ev.undo() # edting callbacks def cut_edit_cb(self): ed = self.currentWidget() if ed: ed.ev.cut() def paste_edit_cb(self): ed = self.currentWidget() if ed: ed.ev.paste() seascope-0.8/src/view/FileFuncGraphView.py000644 000000 000000 00000016527 12230074152 020573 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * from PyQt4.QtSvg import * import os import sys if __name__ == '__main__': import sys import os app_dir = os.path.dirname(os.path.realpath(__file__)) os.chdir(app_dir) sys.path.insert(0, os.path.abspath('..')) os.chdir(os.path.abspath('..')) from backend.plugins.PluginBase import PluginProcess class FileFuncGraphProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir) self.name = 'call graph process' if rq == None: rq = ['', ''] self.cmd_str = rq[0] self.req = rq[1] def parse_result(self, text, sig): return [text] class FileFuncGraphWidget(QWidget): def __init__(self, parent, cmd_func, cmd_id, cmd_opt): QWidget.__init__(self, parent) self.is_busy = False self.is_done = False self.cmd_func = cmd_func self.cmd_id = cmd_id self.cmd_opt = cmd_opt self.is_debug = os.getenv('SEASCOPE_FILE_FUNC_GRAPH_VIEW_DEBUG') self.vlay1 = QVBoxLayout() self.setLayout(self.vlay1) #self.hlay1 = QHBoxLayout() #self.vlay1.addLayout(self.hlay1) #self.add_buttons(self.hlay1) self.lbl = QLabel() self.vlay1.addWidget(self.lbl) self.vlay2 = QVBoxLayout() self.scrolla = QScrollArea() self.scrolla.setLayout(self.vlay2) self.vlay1.addWidget(self.scrolla) self.warn_experimental_lbl = QLabel('Warning: this is an EXPERIMENTAL feature based on cscope, might not work on all files for now.') self.warn_experimental_lbl.setStyleSheet("QLabel { color : red; }") self.vlay1.addWidget(self.warn_experimental_lbl) def startQuery(self, req, dname, proj_dir, inx): if self.is_done: return name = req if req else dname labelList = [ 'File functions graph(%s)' % name, 'File functions and external graph(%s)' %name, 'Directory functions graph(%s)' % os.path.dirname(name), 'Directory functions and external graph(%s)' % os.path.dirname(name) ] self.lbl.setText(labelList[inx]) tool_path = os.path.join('tools', 'FileFuncGraph.py') pargs = [sys.executable, tool_path] if inx == 0: pass elif inx == 1: pargs += ['-e'] elif inx == 2: dname = os.path.dirname(name) elif inx == 3: pargs += ['-e'] dname = os.path.dirname(name) pargs += ['-d', dname] sig_res = FileFuncGraphProcess('.', None).run_query_process(pargs, req) sig_res[0].connect(self.clgraph_add_result) self.is_busy = True self.show_progress_bar() def set_current(self, btn): inx = self.bgrp.id(btn) #self.btn[inx].setChecked(True) #print 'inx clicked', inx if inx == 0: print self.svgw.renderer().defaultSize() self.svgw.setMinimumSize(0, 0) self.svgw.setMinimumSize(self.svgw.sizeHint()) #self.svgw.setMaximumSize(self.svgw.sizeHint()) print self.scrolla.sizeHint() if inx == 1: print self.svgw.renderer().defaultSize() self.svgw.setMinimumSize(0, 0) #self.svgw.setMaximumSize(self.svgw.sizeHint()) print self.scrolla.sizeHint() if inx == 2: print self.svgw.renderer().defaultSize() self.svgw.setMinimumSize(0, 0) self.svgw.resize(self.scrolla.size()) #self.svgw.setMaximumSize(self.svgw.sizeHint()) print self.scrolla.sizeHint() def add_buttons(self, hlay): self.bgrp = QButtonGroup() self.bgrp.buttonClicked.connect(self.set_current) self.bgrp.setExclusive(True) for inx in range(3): btn = QToolButton() btn.setText(str(inx)) btn.setToolTip(str(inx)) #btn.setFlat(True) btn.setCheckable(True) self.bgrp.addButton(btn, inx) hlay.addWidget(btn) def clgraph_add_result(self, req, res): if self.is_debug: print res self.is_busy = False self.is_done = True self.remove_progress_bar() self.svgw = QSvgWidget() self.scrolla.setWidget(self.svgw) self.svgw.load(QByteArray(res[0])) #print self.svgw.renderer().defaultSize() sz = self.svgw.sizeHint() scale = 1 if sz.width() > 1024: scale = 0.8 self.svgw.setMinimumSize(sz.width() * scale, sz.height() * scale) #self.svgw.setMaximumSize(self.svgw.sizeHint()) #print self.scrolla.sizeHint() def show_progress_bar(self): self.pbar = QProgressBar(self.scrolla) self.pbar.setMinimum(0) self.pbar.setMaximum(0) self.pbar.show() def remove_progress_bar(self): if self.pbar: self.pbar.hide() self.pbar.setParent(None) self.pbar = None class FileFuncGraphWindow(QMainWindow): parent = None def __init__(self, req, dname, proj_dir, cmd_func, cmd_args, cmd_opt): QMainWindow.__init__(self, FileFuncGraphWindow.parent) self.req = req self.dname = dname self.proj_dir = proj_dir if req: self.setWindowTitle(req) else: self.setWindowTitle(dname) self.setFont(QFont("San Serif", 8)) w = QWidget() self.setCentralWidget(w) self.vlay = QVBoxLayout() w.setLayout(self.vlay) self.sw = QStackedWidget() self.hlay = QHBoxLayout() self.vlay.addLayout(self.hlay) self.vlay.addWidget(self.sw) self.bgrp = QButtonGroup() self.bgrp.buttonClicked.connect(self.set_current) self.bgrp.setExclusive(True) self.btn = [] self.ctree = [] for inx in range(len(cmd_args)): # cmd format: [ cmd_id, cmd_str, cmd_tip ] cmd = cmd_args[inx] btn = QToolButton() btn.setText(cmd[1]) btn.setToolTip(cmd[2]) #btn.setFlat(True) btn.setCheckable(True) self.bgrp.addButton(btn, inx) self.hlay.addWidget(btn) ct = FileFuncGraphWidget(self, cmd_func, cmd[0], cmd_opt) self.sw.addWidget(ct) self.btn.append(btn) self.ctree.append(ct) self.hlay.addStretch(0) self.set_current(self.btn[0]) def set_current(self, btn): inx = self.bgrp.id(btn) self.btn[inx].setChecked(True) self.sw.setCurrentIndex(inx) ct = self.ctree[inx] ct.setFocus() ct.startQuery(self.req, self.dname, self.proj_dir, inx) def create_page(req, dname, proj_dir, cmd_func, cmd_args, cmd_opt): w = FileFuncGraphWindow(req, dname, proj_dir, cmd_func, cmd_args, cmd_opt) w.resize(900, 600) w.show() return w if __name__ == '__main__': import optparse usage = "usage: %prog (-d | -p ) [symbol]" op = optparse.OptionParser(usage=usage) op.add_option("-d", "--codedir", dest="code_dir", help="Code dir", metavar="CODE_DIR") op.add_option("-p", "--project", dest="id_path", help="Idutils project dir", metavar="PROJECT") (options, args) = op.parse_args() sym = '' dname = '' id_path = None if (not any([options.code_dir, options.id_path]) or all([options.code_dir, options.id_path])): print >> sys.stderr, 'Specify one among -d or -p' sys.exit(-1) if len(args): if len(args) != 1: print >> sys.stderr, 'Please specify a symbol' sys.exit(-4) sym = args[0] if options.code_dir: dname = options.code_dir if not os.path.exists(dname): print >> sys.stderr, '"%s": does not exist' % dname sys.exit(-2) if options.id_path: if not sym: print >> sys.stderr, '-p option needs a symbol' sys.exit(-3) id_path = os.path.normpath(options.id_path) if not os.path.exists(os.path.join(id_path, 'ID')): print >> sys.stderr, 'idutils project path does not exist' sys.exit(-4) app = QApplication(sys.argv) cmd_args = [ ['FFGRAPH', 'F', 'File functions graph'], ['FFGRAPH_E', 'F+E', 'File functions + external graph'], ['FFGRAPH_D', 'D', 'Directory functions graph'], ['FFGRAPH_DE', 'D+E', 'Directory functions + external graph'] ] w = create_page(sym, dname, id_path, None, cmd_args, None) sys.exit(app.exec_()) seascope-0.8/src/view/EdView.py000644 000000 000000 00000040033 12230074152 016433 0ustar00rootroot000000 000000 #!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import re import array from PyQt4 import QtGui from PyQt4.QtGui import * from PyQt4.QtCore import * try: from PyQt4.Qsci import QsciScintilla, QsciScintillaBase from PyQt4.Qsci import QsciLexerCPP, QsciLexerJava from PyQt4.Qsci import QsciLexerPython, QsciLexerRuby from PyQt4.Qsci import QsciLexerBash, QsciLexerDiff, QsciLexerMakefile from PyQt4.Qsci import QsciLexerLua, QsciLexerSQL, QsciLexerTCL, QsciLexerTeX from PyQt4.Qsci import QsciLexerHTML, QsciLexerCSS from PyQt4.Qsci import QsciLexerPerl, QsciLexerVHDL suffix_to_lexer = [ [['c', 'h', 'cpp', 'hpp', 'cc', 'hh', 'cxx', 'hxx', 'C', 'H', 'h++'], QsciLexerCPP], [['java'], QsciLexerJava], [['py', 'pyx', 'pxd', 'pxi', 'scons'], QsciLexerPython], [['rb', 'ruby'], QsciLexerRuby], [['sh', 'bash'], QsciLexerBash], [['diff', 'patch'], QsciLexerDiff], [['mak', 'mk'], QsciLexerMakefile], [['lua'], QsciLexerLua], [['sql'], QsciLexerSQL], [['tcl', 'tk', 'wish', 'itcl'], QsciLexerTCL], [['tex'], QsciLexerTeX], [['htm', 'html'], QsciLexerHTML], [['css'], QsciLexerCSS], [['pl', 'perl'], QsciLexerPerl], [['vhdl', 'vhd'], QsciLexerVHDL], ] filename_to_lexer = [ [['Makefile', 'makefile', 'Makefile.am', 'makefile.am', 'Makefile.in', 'makefile.in'], QsciLexerMakefile], ] except ImportError as e: print e print "Error: required qscintilla-python package not found" raise ImportError import DialogManager from FileContextView import * class EditorViewBase(QsciScintilla): def __init__(self, parent=None): QsciScintilla.__init__(self, parent) self.font = None self.lexer = None def set_font(self, font): if not font: return if not self.font: self.font = QtGui.QFont() self.font.fromString(font) # the font metrics here will help # building the margin width later self.fm = QtGui.QFontMetrics(self.font) ## set the default font of the editor ## and take the same font for line numbers self.setFont(self.font) self.setMarginsFont(self.font) self.lexer.setFont(self.font,-1) self.setLexer(self.lexer) def lpropChanged(self, prop, val): print 'lpropChanged', prop, val def setProperty(self, name, val): name_buff = array.array('c', name + "\0") val_buff = array.array("c", str(val) + "\0") address_name_buffer = name_buff.buffer_info()[0] address_val_buffer = val_buff.buffer_info()[0] self.SendScintilla(QsciScintillaBase.SCI_SETPROPERTY, address_name_buffer, address_val_buffer) def getProperty(self, name): name_buff = array.array('c', name + "\0") val_buff = array.array("c", str(0) + "\0") address_name_buffer = name_buff.buffer_info()[0] address_val_buffer = val_buff.buffer_info()[0] self.SendScintilla(QsciScintillaBase.SCI_GETPROPERTY, address_name_buffer, address_val_buffer) return ''.join(val_buff) def printPropertyAll(self): sz = self.SendScintilla(QsciScintillaBase.SCI_PROPERTYNAMES, 0, 0) if not sz: return val_buff = array.array("c", (' ' * sz) + "\0") address_val_buffer = val_buff.buffer_info()[0] self.SendScintilla(QsciScintillaBase.SCI_PROPERTYNAMES, 0, address_val_buffer) print '###>' for p in ''.join(val_buff).splitlines(): v = self.getProperty(p) print ' %s = %s' % (p, v) def lexer_for_file(self, filename): (prefix, ext) = os.path.splitext(filename) for (el, lxr) in suffix_to_lexer: if ext in el: return lxr for (el, lxr) in filename_to_lexer: if filename in el: return lxr return QsciLexerCPP def set_lexer(self, filename): if not self.lexer: lexerClass = self.lexer_for_file(filename) self.lexer = lexerClass() self.setLexer(self.lexer) self.setProperty("lexer.cpp.track.preprocessor", "0") is_debug = os.getenv("SEASCOPE_QSCI_LEXER_DEBUG", 0) if is_debug: self.lexer.propertyChanged.connect(self.lpropChanged) self.printPropertyAll() class EditorView(EditorViewBase): ev_popup = None sig_text_selected = pyqtSignal(str) def __init__(self, parent=None): EditorViewBase.__init__(self, parent) #self.setGeometry(300, 300, 400, 300) ## Editing line color self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QtGui.QColor("#d4feff")) # orig: EEF6FF #self.setCaretWidth(2) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.codemark_marker = self.markerDefine(self.Circle) def get_filename(self): return self.filename def ed_settings_1(self): ## Margins colors # line numbers margin self.setMarginsBackgroundColor(QtGui.QColor("#333333")) self.setMarginsForegroundColor(QtGui.QColor("#CCCCCC")) # folding margin colors (foreground,background) self.setFoldMarginColors(QtGui.QColor("#888888"),QtGui.QColor("#eeeeee")) ## Edge Mode shows a red vetical bar at 80 chars self.setEdgeMode(QsciScintilla.EdgeLine) self.setEdgeColumn(80) self.setEdgeColor(QtGui.QColor("#FF0000")) ## Editing line color self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QtGui.QColor("#CDA869")) def show_line_number_cb(self, val): if (val): width = self.fm.width( "00000" ) + 5 else: width = 0 self.setMarginWidth(0, width) self.setMarginLineNumbers(0, val) def show_folds_cb(self, val): if val: #self.setMarginsForegroundColor( QtGui.QColor("#404040") ) #self.setMarginsBackgroundColor( QtGui.QColor("#888888") ) ## Folding visual : we will use circled tree fold self.setFolding(QsciScintilla.CircledTreeFoldStyle) else: self.setFolding(QsciScintilla.NoFoldStyle) self.clearFolds() def toggle_folds_cb(self): self.foldAll() def codemark_add(self, line): self.markerAdd(line, self.codemark_marker) def codemark_del(self, line): self.markerDelete(line, self.codemark_marker) def goto_marker(self, is_next): (eline, inx) = self.getCursorPosition() if is_next: val = self.markerFindNext(eline + 1, -1) else: val = self.markerFindPrevious(eline - 1, -1) if val >= 0: self.setCursorPosition(val, 0) def open_file_begin(self, filename): self.filename = filename ## Choose a lexer self.set_lexer(filename) ## Braces matching self.setBraceMatching(QsciScintilla.SloppyBraceMatch) ## Render on screen self.show() def open_file_end(self): self.show() self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) #self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setFocus() def open_file(self, filename): self.open_file_begin(filename) ## Show this file in the editor self.setText(open(filename).read()) ## Mark read-only self.setReadOnly(True) self.open_file_end() def goto_line(self, line): line = line - 1 self.setCursorPosition(line, 0) self.ensureLineVisible(line) self.setFocus() def contextMenuEvent(self, ev): if not EditorView.ev_popup: return f = EditorView.ev_popup.font() EditorView.ev_popup.setFont(QFont("San Serif", 8)) EditorView.ev_popup.exec_(QCursor.pos()) EditorView.ev_popup.setFont(f) def mouseReleaseEvent(self, ev): super(EditorView, self).mouseReleaseEvent(ev) if(self.hasSelectedText()): self.query_text = self.selectedText() #print 'selectedText ----', self.query_text self.sig_text_selected.emit(self.query_text) class EditorPage(QSplitter): def __init__(self, parent=None): QSplitter.__init__(self) self.fcv = FileContextView(self) self.ev = self.new_editor_view() self.addWidget(self.fcv) self.addWidget(self.ev) self.setSizes([1, 300]) self.ev.cursorPositionChanged.connect(self.fcv.sig_ed_cursor_changed) self.fcv.sig_goto_line.connect(self.ev.goto_line) def new_editor_view(self): return EditorView(self) def open_file(self, filename): self.ev.open_file(filename); self.fcv.run(filename); def get_filename(self): return self.ev.get_filename() class EditorBook(QTabWidget): sig_file_closed = pyqtSignal(str) sig_history_update = pyqtSignal(str, int) sig_tab_changed = pyqtSignal(str) sig_open_dir_view = pyqtSignal(str) sig_editor_text_selected = pyqtSignal(str) def __init__(self, *args): apply(QTabWidget.__init__,(self, ) + args) self.setMovable(True) self.setTabsClosable(True) self.tabCloseRequested.connect(self.removeTab) self.currentChanged.connect(self.tab_change_cb) self.is_show_line = False self.is_show_folds = False self.f_text = None self.ev_font = "Monospace,10,-1,5,50,0,0,0,0,0" def new_editor_page(self): return EditorPage() def addFile(self, fileName): ed = self.new_editor_page() ed.open_file(fileName) ed.ev.set_font(self.ev_font) ed.ev.show_line_number_cb(self.is_show_line) ed.ev.show_folds_cb(self.is_show_folds) self.addTab(ed, os.path.basename(fileName)) return ed def search_already_opened_files(self, filename): for i in range(self.count()): page = self.widget(i) if (page.get_filename() == filename): return page return None def removeTab(self, inx): ed = self.widget(inx) f = ed.ev.get_filename() QTabWidget.removeTab(self, inx) self.sig_file_closed.emit(f) def clear(self): while self.count() != 0: self.removeTab(0) def remove_tab_list(self, inx_list): for inx in sorted(inx_list, reverse=True): self.removeTab(inx) def tab_list(self, inx, type): inx_list = [] if type == 'all' or type == 'files': return range(self.count()) if type == 'left': return range(inx) if type == 'right': return range(inx + 1, self.count()) if type == 'other': return self.tab_list(inx, 'left') + self.tab_list(inx, 'right') assert 0 def close_list_common(self, type): inx_list = self.tab_list(self.currentIndex(), type) if len(inx_list) == 0: return if not DialogManager.show_yes_no('Close all %s ?' % type): return self.remove_tab_list(inx_list) def close_all_left_cb(self): self.close_list_common('left') def close_all_right_cb(self): self.close_list_common('right') def close_all_other_cb(self): self.close_list_common('other') def close_all_cb(self): self.close_list_common('files') def get_current_word(self): ed = self.currentWidget() if not ed: return if ed.ev.hasSelectedText(): return ed.ev.selectedText() (line, index) = ed.ev.getCursorPosition() text = ed.ev.text(line) # Go left linx = index while linx > 0 and ed.ev.isWordCharacter(text[linx - 1]): linx = linx - 1 # Go right rinx = index while rinx < len(text) and ed.ev.isWordCharacter(text[rinx]): rinx = rinx + 1 text = text[linx:rinx] if text == '': return None return text def get_current_file_line(self): ed = self.currentWidget() if not ed: return (None, None) (line, inx) = ed.ev.getCursorPosition() return (ed.ev.filename, line + 1) def get_file_line_list(self): fl_list = [] tlist = range(self.count()) inx = self.currentIndex() if inx >= 0: tlist.append(inx) for inx in tlist: ed = self.widget(inx) (line, inx) = ed.ev.getCursorPosition() fl_list.append('%s:%d' % (ed.ev.filename, line + 1)) return fl_list def matching_brace_cb(self): ed = self.currentWidget() if ed: ed.ev.moveToMatchingBrace() #ed.ev.setFocus() def goto_line_cb(self): ed = self.currentWidget() if not ed: return (None, None) (line, inx) = ed.ev.getCursorPosition() #return (line + 1, ed.ev.lines()) line = DialogManager.show_goto_line_dialog(line + 1, ed.ev.lines()) if (line == None): return ed.ev.goto_line(line) def focus_editor(self): page = self.currentWidget() if page: page.ev.setFocus() def close_current_page(self): self.removeTab(self.currentIndex()) self.focus_editor() def focus_search_ctags(self): ed = self.currentWidget() if ed: ed.fcv.focus_search_ctags() def copy_edit_cb(self): ed = self.currentWidget() if ed: ed.ev.copy() def tab_change_cb(self, inx): if (inx == -1): fname = '' else: page = self.currentWidget() page.ev.setFocus() fname = page.get_filename() self.sig_tab_changed.emit(fname) def open_dir_cb(self): page = self.currentWidget() if page: fname = page.get_filename() self.sig_open_dir_view.emit(fname) def mousePressEvent(self, m_ev): QTabWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): # setup popup menu self.pmenu = QMenu() self.pmenu.addAction("Open dir", self.open_dir_cb) self.pmenu.addSeparator() self.pmenu.addAction("Close All &Left", self.close_all_left_cb) self.pmenu.addAction("Close All &Right", self.close_all_right_cb) self.pmenu.addAction("Close &Others", self.close_all_other_cb) self.pmenu.addSeparator() self.pmenu.addAction("Close &All", self.close_all_cb) self.pmenu.exec_(QCursor.pos()) def show_file_line(self, filename, line, hist=True): if line: (f, l) = self.get_current_file_line() if (f): if hist: self.sig_history_update.emit(f, l) filename = str(filename) if (not os.path.exists(filename)): return page = self.search_already_opened_files(filename) if page == None: page = self.addFile(filename) self.setCurrentWidget(page) if line: page.ev.goto_line(line) if hist: self.sig_history_update.emit(filename, line) page.ev.setFocus() # text selected callback: need to send out again. page.ev.sig_text_selected.connect(self.editor_text_selected) def editor_text_selected(self, text): self.sig_editor_text_selected.emit(text) def show_file(self, filename): self.show_file_line(filename, 0) def show_line(self, line): ed = self.currentWidget() if not ed: return ed.ev.goto_line(line) def find_cb(self): ed = self.currentWidget() if not ed: return res = DialogManager.show_find_dialog(self.get_current_word()) if (res == None): return (text, opt) = res if (text == None): return self.f_text = text self.f_opt = opt self.find_text(opt['cursor'], opt['fw']) def find_text(self, from_cursor, is_fw): if (self.f_text == None): return ed = self.currentWidget() if not ed: return text = self.f_text opt = self.f_opt if (from_cursor): if (is_fw): (line, inx) = (-1, -1) else: (line, inx) = ed.ev.getCursorPosition() if (ed.ev.hasSelectedText()): inx = inx - 1 if ed.ev.findFirst(text, opt['re'], opt['cs'], opt['wo'], False, is_fw, line, inx): return True if not DialogManager.show_yes_no('End of document reached. Continue from beginning?'): return False if (is_fw): (line, inx) = (0, 0) else: (line, inx) = (ed.ev.lines(), 0) if ed.ev.findFirst(text, opt['re'], opt['cs'], opt['wo'], False, is_fw, line, inx): return DialogManager.show_msg_dialog("Could not find " + "'" + text + "'") def find_next_cb(self): self.find_text(True, True) def find_prev_cb(self): self.find_text(True, False) def change_ev_font(self, font): if font == self.ev_font: return self.ev_font = font for inx in range(self.count()): ed = self.widget(inx) ed.ev.set_font(self.ev_font) def show_line_number_cb(self): val = self.m_show_line_num.isChecked() self.is_show_line = val for inx in range(self.count()): ed = self.widget(inx) ed.ev.show_line_number_cb(val) def show_line_number_pref(self, val): if val == self.m_show_line_num.isChecked(): return self.m_show_line_num.setChecked(val) self.show_line_number_cb() def show_folds_cb(self): val = self.m_show_folds.isChecked() self.is_show_folds = val for inx in range(self.count()): ed = self.widget(inx) ed.ev.show_folds_cb(val) def toggle_folds_cb(self): ed = self.currentWidget() if not ed: return if self.is_show_folds: ed.ev.toggle_folds_cb() def open_in_external_editor(self, cmd): if not cmd: DialogManager.show_msg_dialog('Please configure external editor') return (f, l) = self.get_current_file_line() if not f: return cmd = cmd.replace('%F', f).replace('%L', str(l)) if not QProcess.startDetached(cmd): DialogManager.show_msg_dialog('Failed to start: ' + cmd) def codemark_add(self, filename, line): ed = self.search_already_opened_files(filename) if ed: ed.ev.codemark_add(line) def codemark_del(self, filename, line): ed = self.search_already_opened_files(filename) if ed: ed.ev.codemark_del(line) def bookmark_prev_cb(self): ed = self.currentWidget() if ed: ed.ev.goto_marker(False) def bookmark_next_cb(self): ed = self.currentWidget() if ed: ed.ev.goto_marker(True) seascope-0.8/src/view/DebugView.py000644 000000 000000 00000003125 12230074152 017132 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys import os import string from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * class DebugInfoEntry(QFrame): def __init__(self, parent=None): QFrame.__init__(self) self.vlay = QVBoxLayout() self.setLayout(self.vlay) #def add_result_continue(self): #self.add_result(self.name, self.res) def add_result(self, cmd, out, err): #self.setFrameStyle(QFrame.StyledPanel | QFrame.Plain) self.cmd_lbl = QLabel() self.cmd_lbl.setText(cmd) self.vlay.addWidget(self.cmd_lbl) #if err != None and err != '': #self.err_lbl = QLabel() #self.err_lbl.setText('Error: ' + err) #self.vlay.addWidget(self.err_lbl) #self.res_lbl = QLabel() #self.res_lbl.setText(out) #self.vlay.addWidget(self.res_lbl) #self.res_lbl.hide() class DebugWindow(QMainWindow): dlg = None def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.ui = uic.loadUi('ui/debug.ui', self) self.vlay = self.ui.dbg_widget.layout() def append_widget(self, w): self.vlay.addWidget(w) def run_dialog(self): self.ui.show() vbar = self.ui.dbg_scroll_area.verticalScrollBar() vbar.setValue(vbar.maximum()) self.ui.show() def closeEvent(self, e): DebugWindow.dlg = None def show_dbg_dialog(parent): if (DebugWindow.dlg == None): DebugWindow.dlg = DebugWindow(parent) DebugWindow.dlg.run_dialog() def connect_to_sig(sig_res): if (DebugWindow.dlg == None): return entry = DebugInfoEntry() DebugWindow.dlg.append_widget(entry) sig_res.connect(entry.add_result) seascope-0.8/src/view/CodeContextView.py000644 000000 000000 00000011570 12230074152 020326 0ustar00rootroot000000 000000 #!/usr/bin/env python # Copyright (c) 2013 dangbinghoo # All rights reserved. # # License: BSD import os import re import array from PyQt4 import QtGui from PyQt4.QtGui import * from PyQt4.QtCore import * from EdView import EditorView # code context view class ContextEditorView(EditorView): sig_dblclick = pyqtSignal() def __init__(self, parent = None): EditorView.__init__(self, parent) self.setCaretLineBackgroundColor(QtGui.QColor("#ffaa7f")) def mouseReleaseEvent(self, ev): super(EditorView, self).mouseReleaseEvent(ev) def mousePressEvent(self, ev): pass def keyPressEvent(self, ev): pass def contextMenuEvent(self, ev): pass def mouseDoubleClickEvent(self, ev): self.sig_dblclick.emit() def show_file_line(self, fname, line): self.open_file(fname) self.goto_line(int(line)) self.show() class codeResultView(QTextBrowser): sig_result_view_openfile = pyqtSignal(str, int) def __init__(self, parent = None): QTextBrowser.__init__(self) self.setReadOnly(True) def showResultList(self, sym, res): self.res = res richstr = '
' richstr += 'Query of < ' richstr += str(sym) richstr += ' > list' richstr += '
' richstr += '
' for itm in res: filename = itm[1] linenum = itm[2] context = itm[3] richstr += 'Line ' richstr += str(linenum) richstr += ' of ' richstr += str(filename) richstr += '' richstr += '' richstr += '
'
			richstr += str(context)
			richstr += '
' richstr += '
' #print richstr self.setHtml(richstr) self.setReadOnly(True) self.anchorClicked.connect(self.anchorClicked_ev) def anchorClicked_ev(self, qurl): urlstr = qurl.toString() urlinfo = urlstr.split('#') fname = str(urlinfo[0]) linen = int(urlinfo[1]) self.sig_result_view_openfile.emit(fname, int(linen)) def setSource(self, qurl): self.setText('') self.anchorClicked.disconnect(self.anchorClicked_ev) # contextView Page class CodeContextViewPage(QFrame): def __init__(self, parent = None): QFrame.__init__(self) self.vlay = QVBoxLayout() self.cv_filetitle = QLabel() self.cv = ContextEditorView() self.resv = codeResultView() self.vlay.addWidget(self.cv_filetitle) self.vlay.addWidget(self.cv) self.vlay.addWidget(self.resv) #self.setSizes([1,1,1]) self.resv.show() self.cv.hide() self.cv_filetitle.hide() self.setLayout(self.vlay) def showFileView(self, fname, line, sym, font): self.filename = fname self.linenum = line t = '%s:%s %s' % (fname, line, sym) self.cv_filetitle.setText(t) self.cv_filetitle.show() cv = self.cv cv.set_lexer(fname) cv.set_font(font) cv.show_line_number_cb(True) cv.show_file_line(fname, line) cv.show() # ContextView Manager class CodeContextViewManager(QTabWidget): sig_codecontext_showfile = pyqtSignal(str, int) def __init__(self, *args): apply(QTabWidget.__init__,(self, ) + args) self.setMovable(True) self.setTabsClosable(True) self.newContextViewPage() self.cur_query = '' self.cvp_cv_openedFile = False self.cv_font = "Monospace,10,-1,5,50,0,0,0,0,0" self.cvp.cv.sig_dblclick.connect(self.contextViewPage_openfile) self.cvp.resv.sig_result_view_openfile.connect(self.resultViewPage_openfile) def change_ev_font(self, font): if font == self.cv_font: return self.cv_font = font for inx in range(self.count()): cvp = self.widget(inx) cvp.cv.set_font(self.cv_font) def newContextViewPage(self): self.cvp = CodeContextViewPage() self.addTab(self.cvp, 'Context View') def set_cur_query(self, text): if self.cur_query == text: return False self.cur_query = text return True def showResult(self, sym, res): if sym != self.cur_query: return self.cvp.cv.clear() # if queried one, show the file, or, list results. if (len(res) == 1): self.cvp.resv.hide() itm = res[0] self.cvp.showFileView(itm[1], itm[2], sym, self.cv_font) self.cvp_cv_openedFile = True else: self.cvp.cv.hide() self.cvp.cv_filetitle.hide() self.cvp.resv.showResultList(sym, res) self.cvp.resv.show() def contextViewPage_openfile(self): self.cvp.cv.clear() self.sig_codecontext_showfile.emit(self.cvp.filename, int(self.cvp.linenum)) def resultViewPage_openfile(self, filename, line): self.sig_codecontext_showfile.emit(filename, int(line)) def clear(self): self.cvp.cv_filetitle.clear() self.cvp.resv.clear() self.cvp.cv.clear() self.cvp.cv.hide() seascope-0.8/src/view/ClassGraphView.py000644 000000 000000 00000015711 12230074152 020137 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * from PyQt4.QtSvg import * import os import sys if __name__ == '__main__': import sys import os app_dir = os.path.dirname(os.path.realpath(__file__)) os.chdir(app_dir) sys.path.insert(0, os.path.abspath('..')) os.chdir(os.path.abspath('..')) from backend.plugins.PluginBase import PluginProcess class ClassGraphProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir) self.name = 'call graph process' if rq == None: rq = ['', ''] self.cmd_str = rq[0] self.req = rq[1] def parse_result(self, text, sig): return [text] class ClassGraphWidget(QWidget): def __init__(self, parent, cmd_func, cmd_id, cmd_opt): QWidget.__init__(self, parent) self.is_busy = False self.is_done = False self.cmd_func = cmd_func self.cmd_id = cmd_id self.cmd_opt = cmd_opt self.is_debug = os.getenv('SEASCOPE_CLASS_GRAPH_VIEW_DEBUG') self.vlay1 = QVBoxLayout() self.setLayout(self.vlay1) #self.hlay1 = QHBoxLayout() #self.vlay1.addLayout(self.hlay1) #self.add_buttons(self.hlay1) self.lbl = QLabel() self.vlay1.addWidget(self.lbl) self.vlay2 = QVBoxLayout() self.scrolla = QScrollArea() self.scrolla.setLayout(self.vlay2) self.vlay1.addWidget(self.scrolla) def startQuery(self, req, dname, proj_type, inx): if self.is_done: return name = req if req else dname self.lbl.setText(['derived', 'base'][inx] + '(' + name + ')') tool_path = os.path.join('tools', 'ClassGraph.py') pargs = [sys.executable, tool_path] if inx == 1: pargs += ['-b'] pargs += ['-d', dname] if proj_type: pargs += ['-t', proj_type] if req: pargs += [req] sig_res = ClassGraphProcess('.', None).run_query_process(pargs, req) sig_res[0].connect(self.clgraph_add_result) self.is_busy = True self.show_progress_bar() def set_current(self, btn): inx = self.bgrp.id(btn) #self.btn[inx].setChecked(True) #print 'inx clicked', inx if inx == 0: print self.svgw.renderer().defaultSize() self.svgw.setMinimumSize(0, 0) self.svgw.setMinimumSize(self.svgw.sizeHint()) #self.svgw.setMaximumSize(self.svgw.sizeHint()) print self.scrolla.sizeHint() if inx == 1: print self.svgw.renderer().defaultSize() self.svgw.setMinimumSize(0, 0) #self.svgw.setMaximumSize(self.svgw.sizeHint()) print self.scrolla.sizeHint() if inx == 2: print self.svgw.renderer().defaultSize() self.svgw.setMinimumSize(0, 0) self.svgw.resize(self.scrolla.size()) #self.svgw.setMaximumSize(self.svgw.sizeHint()) print self.scrolla.sizeHint() def add_buttons(self, hlay): self.bgrp = QButtonGroup() self.bgrp.buttonClicked.connect(self.set_current) self.bgrp.setExclusive(True) for inx in range(3): btn = QToolButton() btn.setText(str(inx)) btn.setToolTip(str(inx)) #btn.setFlat(True) btn.setCheckable(True) self.bgrp.addButton(btn, inx) hlay.addWidget(btn) def clgraph_add_result(self, req, res): if self.is_debug: print res self.is_busy = False self.is_done = True self.remove_progress_bar() self.svgw = QSvgWidget() self.scrolla.setWidget(self.svgw) self.svgw.load(QByteArray(res[0])) #print self.svgw.renderer().defaultSize() sz = self.svgw.sizeHint() scale = 1 if sz.width() > 1024: scale = 0.8 self.svgw.setMinimumSize(sz.width() * scale, sz.height() * scale) #self.svgw.setMaximumSize(self.svgw.sizeHint()) #print self.scrolla.sizeHint() def show_progress_bar(self): self.pbar = QProgressBar(self.scrolla) self.pbar.setMinimum(0) self.pbar.setMaximum(0) self.pbar.show() def remove_progress_bar(self): if self.pbar: self.pbar.hide() self.pbar.setParent(None) self.pbar = None class ClassGraphWindow(QMainWindow): parent = None def __init__(self, req, dname, proj_type, cmd_func, cmd_args, cmd_opt): QMainWindow.__init__(self, ClassGraphWindow.parent) self.req = req self.dname = dname self.proj_type = proj_type if req: self.setWindowTitle(req) else: self.setWindowTitle(dname) self.setFont(QFont("San Serif", 8)) w = QWidget() self.setCentralWidget(w) self.vlay = QVBoxLayout() w.setLayout(self.vlay) self.sw = QStackedWidget() self.hlay = QHBoxLayout() self.vlay.addLayout(self.hlay) self.vlay.addWidget(self.sw) self.bgrp = QButtonGroup() self.bgrp.buttonClicked.connect(self.set_current) self.bgrp.setExclusive(True) self.btn = [] self.ctree = [] for inx in range(len(cmd_args)): # cmd format: [ cmd_id, cmd_str, cmd_tip ] cmd = cmd_args[inx] btn = QToolButton() btn.setText(cmd[1]) btn.setToolTip(cmd[2]) #btn.setFlat(True) btn.setCheckable(True) self.bgrp.addButton(btn, inx) self.hlay.addWidget(btn) ct = ClassGraphWidget(self, cmd_func, cmd[0], cmd_opt) self.sw.addWidget(ct) self.btn.append(btn) self.ctree.append(ct) self.hlay.addStretch(0) self.set_current(self.btn[0]) def set_current(self, btn): inx = self.bgrp.id(btn) self.btn[inx].setChecked(True) self.sw.setCurrentIndex(inx) ct = self.ctree[inx] ct.setFocus() ct.startQuery(self.req, self.dname, self.proj_type, inx) def create_page(req, dname, proj_type, cmd_func, cmd_args, cmd_opt): w = ClassGraphWindow(req, dname, proj_type, cmd_func, cmd_args, cmd_opt) w.resize(900, 600) w.show() return w if __name__ == '__main__': import optparse usage = "usage: %prog (-d | -t ) [symbol]" op = optparse.OptionParser(usage=usage) op.add_option("-d", "--codedir", dest="code_dir", help="Code dir", metavar="CODE_DIR") op.add_option("-t", "--type", dest="prj_type", help="project type: idutils|gtags|cscope", metavar="PRJ_TYPE") (options, args) = op.parse_args() # dname if not options.code_dir: print >> sys.stderr, 'Specify -d' sys.exit(-1) dname = options.code_dir if not os.path.exists(dname): print >> sys.stderr, '"%s": does not exist' % dname sys.exit(-2) wdir = dname if not os.path.isdir(wdir): wdir = os.path.dirname(wdir) # sym sym = None if len(args): if len(args) != 1: print >> sys.stderr, 'Please specify only one symbol' sys.exit(-3) sym = args[0] # ptype ptype = options.prj_type if ptype: if not sym: print >> sys.stderr, '-t option needs sepficfying symbol' sys.exit(-4) if not os.path.isdir(dname): print >> sys.stderr, '-t option needs codedir to be a directory' sys.exit(-5) pcmd = None if ptype and os.path.isdir(dname): prj_list = [ ['idutils', 'ID' ], ['gtags', 'GRTAGS' ], ['cscope', 'cscope.out' ], ['grep', '' ], ] for p in prj_list: if p[0] == ptype: if not os.path.exists(os.path.join(dname, p[1])): print >> sys.stderr, 'Failed to find "%s" in directory "%s"' % (p[1], dname) sys.exit(-6) app = QApplication(sys.argv) cmd_args = [ ['CLGRAPH', 'D', 'Derived classes'], ['CLGRAPH', 'B', 'Base classes'] ] w = create_page(sym, dname, ptype, None, cmd_args, None) sys.exit(app.exec_()) seascope-0.8/src/view/ResView.py000644 000000 000000 00000017250 12230074152 016641 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import re from PyQt4.QtGui import * from PyQt4.QtCore import * import DialogManager class ResultPageItem(QTreeWidgetItem): def __init__(self, li): QTreeWidgetItem.__init__(self, li) def column_val(self, col): try: val = str(self.data(col, Qt.DisplayRole).toString()) except: return None return val class ResultPage(QTreeWidget): sig_show_file_line = pyqtSignal(str, int) is_history_call = False def __init__(self, parent): QTreeWidget.__init__(self) self.is_history = False self.pbar = None self.parent = parent self.setColumnCount(4) self.cmd_items = ['Tag', 'File', 'Line', 'Text'] self.setHeaderLabels(self.cmd_items) self.setColumnWidth(0, 200) self.setColumnWidth(1, 300) self.setColumnWidth(2, 40) # setup popup menu self.pmenu = QMenu() self.pmenu.addAction("&Filter", self.filter_cb) self.pmenu.addAction("&Show All", self.show_all_cb) self.pmenu.addSeparator() self.pmenu.addAction("&Remove Item", self.remove_item_cb) #self.setMinimumHeight(200) #self.setMinimumWidth(600) ## set column width to fit contents ##self.resizeColumnsToContents() ##self.resizeRowsToContents() ## set row height #nrows = len(result) #for row in xrange(nrows): #self.setRowHeight(row, 14) #self.setTextElideMode(Qt.ElideLeft) self.setIndentation(-2) self.setAllColumnsShowFocus(True) self.activated.connect(self.activated_cb) def activated_cb(self, minx): (filename, line) = self.get_file_line(minx) if (not filename): return if (self.is_history): ResultPage.is_history_call = True self.sig_show_file_line.emit(filename, line) ResultPage.is_history_call = False def filter_cb(self): filtered = False cmd_sel = self.cmd_items[self.last_minx.column()] res = DialogManager.show_filter_dialog(self.cmd_items,cmd_sel) if res == None: return (filter_text, is_regex, is_negate, is_ignorecase, cmd_sel) = res cmd_idx = self.cmd_items.index(cmd_sel) if cmd_idx == -1: return for inx in range(self.topLevelItemCount()): item = self.topLevelItem(inx) text = item.column_val(cmd_idx) if (text == None): continue matched = False if (is_regex): if (is_ignorecase): if (re.search(filter_text, text, re.I) != None): matched = True else: if (re.search(filter_text, text) != None): matched = True else: if (is_ignorecase): if (text.upper().find(filter_text.upper()) != -1): matched = True else: if (text.find(filter_text) != -1): matched = True if (is_negate): matched = not matched if not matched: self.setItemHidden(item, True) filtered = True if filtered: self.mark_tab_filtered(True) def mark_tab_filtered(self, mark): tabIndex = self.parent.indexOf(self) label = self.parent.tabText(tabIndex) if mark and label[0] != "*": self.parent.setTabText(tabIndex, "*" + label) elif not mark and label[0] == "*": self.parent.setTabText(tabIndex, label.remove(0,1)) def show_all_cb(self): for inx in range(self.topLevelItemCount()): item = self.topLevelItem(inx) self.setItemHidden(item, False) self.mark_tab_filtered(False) def remove_item_cb(self): self.setItemHidden(self.itemFromIndex(self.last_minx), True) self.mark_tab_filtered(True) def get_file_line(self, minx): model = minx.model() row = minx.row() if (not model): return (None, None) filename = str(model.data(model.index(row, 1)).toString()) try: line = model.data(model.index(row, 2)).toString() line = int(line) except: line = 0 return (filename, line) def add_result_continue(self): self.add_result(self.name, self.res) def add_result(self, name, res): res_list = [] ret_val = True root = self.invisibleRootItem() count = 0 for line in res: item = ResultPageItem(line) #self.addTopLevelItem(item) if (self.is_history): root.insertChild(0, item) else: root.addChild(item) count = count + 1 if (count == 1000): self.name = name self.res = res[count:] QTimer.singleShot(100, self.add_result_continue) return self.remove_progress_bar() if (self.topLevelItemCount() < 5000): self.resizeColumnToContents(0) self.resizeColumnToContents(1) self.resizeColumnToContents(2) self.resizeColumnToContents(3) if (self.topLevelItemCount() == 1): item = self.topLevelItem(0) item.setSelected(True) minx = self.indexFromItem(item) self.activated_cb(minx) return ret_val def mousePressEvent(self, m_ev): QTreeWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): self.last_minx = self.indexAt(m_ev.pos()) self.pmenu.exec_(QCursor.pos()) def show_progress_bar(self): self.pbar = QProgressBar(self) self.pbar.setMinimum(0) self.pbar.setMaximum(0) self.pbar.show() def remove_progress_bar(self): if (self.pbar): self.pbar.setParent(None) self.pbar = None class ResultManager(QTabWidget): book = None sig_show_file_line = pyqtSignal(str, int) def __init__(self, *args): apply(QTabWidget.__init__,(self, ) + args) self.setMovable(True) self.setTabsClosable(True) self.tabCloseRequested.connect(self.close_cb) self.h_page = None self.setFont(QFont("San Serif", 8)) ResultManager.book = self def go_next_res_common(self, page, inc): if page == None: return if (inc == 1): minx = page.moveCursor(QAbstractItemView.MoveDown, Qt.NoModifier) else: minx = page.moveCursor(QAbstractItemView.MoveUp, Qt.NoModifier) page.setCurrentItem(page.itemFromIndex(minx)) page.activated.emit(minx) def go_next_res(self, inc): self.go_next_res_common(self.currentWidget(), inc) def go_next_history(self, inc): self.go_next_res_common(self.h_page, -inc) def show_history(self): if (self.h_page): self.setCurrentWidget(self.h_page) def new_cb(self): print "new_cb" def refresh_cb(self): print "refresh_cb" def close_cb(self, inx): if (self.widget(inx) == self.h_page): self.h_page = None self.removeTab(inx) def close_all_cb(self): if DialogManager.show_yes_no("Close all query results ?"): self.clear() self.h_page = None def mousePressEvent(self, m_ev): QTabWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): # setup popup menu self.pmenu = QMenu() #self.pmenu.addAction("&New", self.new_cb) #self.pmenu.addAction("&Refresh", self.refresh_cb) #self.pmenu.addSeparator() self.pmenu.addAction("Close &All", self.close_all_cb) self.pmenu.exec_(QCursor.pos()) def history_create(self): self.h_page = ResultManager.create_result_page(self, None) assert self.h_page.is_history self.h_page.hideColumn(0) self.h_page.hideColumn(3) def history_update(self, filename, line): if (ResultPage.is_history_call): return if (self.h_page == None): self.history_create() for idx in range(self.h_page.indexOfTopLevelItem(self.h_page.currentItem())): self.h_page.invisibleRootItem().removeChild(self.h_page.topLevelItem(0)) if self.h_page.topLevelItemCount(): item = self.h_page.topLevelItem(0) minx = self.h_page.indexFromItem(item) (f, l) = self.h_page.get_file_line(minx) if (filename and f == filename and l == line): return self.h_page.add_result('History', [['', filename, str(line), '']]) if self.h_page.topLevelItemCount(): self.h_page.setCurrentItem(self.h_page.topLevelItem(0)) def create_result_page(self, name): page = ResultPage(self) if not name: name = 'History' page.is_history = True self.addTab(page, name) if not page.is_history: self.setCurrentWidget(page) page.sig_show_file_line.connect(self.sig_show_file_line) page.show_progress_bar() return page def create_result_page_single(self): return ResultPage(self) seascope-0.8/src/ui/000755 000000 000000 00000000000 12230074152 014341 5ustar00rootroot000000 000000 seascope-0.8/src/ui/proj_new.ui000644 000000 000000 00000004447 12230074152 016534 0ustar00rootroot000000 000000 ProjNewDialog 0 0 600 360 Project new Choose backend 110 16777215 -1 true QFrame::NoFrame true Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() ProjNewDialog accept() 248 254 157 274 buttonBox rejected() ProjNewDialog reject() 316 260 286 274 seascope-0.8/src/ui/filter.ui000644 000000 000000 00000007726 12230074152 016201 0ustar00rootroot000000 000000 Dialog 0 0 345 222 Filter Filter in Qt::Horizontal 40 20 Filter for true Qt::AlignCenter 50 16777215 Regex Negate search Case insensitive Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok fd_filter_inp fd_regex_chkbox fd_negate_chkbox fd_icase_chkbox buttonBox fd_cmd_inp buttonBox accepted() Dialog accept() 248 254 157 274 buttonBox rejected() Dialog reject() 316 260 286 274 seascope-0.8/src/ui/preferences.ui000644 000000 000000 00000013734 12230074152 017211 0ustar00rootroot000000 000000 PrefDialog 0 0 400 300 Seascope Preferences Qt::TabFocus QTabWidget::North QTabWidget::Rounded 0 Style Font Application Application Font Qt::Horizontal 40 20 Editor Editor Font Qt::Vertical 20 40 Option Ask before exit if there is open project Format: %F - filename, %L - line External Editor Enable internal editor editting support Show line number in editor by default Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() PrefDialog accept() 248 254 157 274 buttonBox rejected() PrefDialog reject() 316 260 286 274 seascope-0.8/src/ui/proj_open.ui000644 000000 000000 00000005007 12230074152 016675 0ustar00rootroot000000 000000 ProjOpenDlg Qt::NonModal 0 0 400 300 Project Open 40 16777215 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok pod_proj_name pod_open_btn pod_proj_list buttonBox buttonBox accepted() ProjOpenDlg accept() 257 290 157 274 buttonBox rejected() ProjOpenDlg reject() 325 290 286 274 pod_proj_list doubleClicked(QModelIndex) ProjOpenDlg accept() 199 150 199 149 seascope-0.8/src/ui/find.ui000644 000000 000000 00000006137 12230074152 015627 0ustar00rootroot000000 000000 FindDialog 0 0 301 183 Find Text true Case sensitive Regex Whole words only Find backwards From cursor Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok ft_text_inp ft_cs ft_re ft_wo ft_bw ft_from_cursor buttonBox buttonBox accepted() FindDialog accept() 248 254 157 274 buttonBox rejected() FindDialog reject() 316 260 286 274 seascope-0.8/src/ui/debug.ui000644 000000 000000 00000003751 12230074152 015774 0ustar00rootroot000000 000000 dbg_main_window 0 0 514 394 Debug info... QTabWidget::Rounded 0 Info true 0 0 472 323 Version Not implemented yet seascope-0.8/src/ui/goto_line.ui000644 000000 000000 00000005204 12230074152 016660 0ustar00rootroot000000 000000 Dialog 0 0 194 103 Goto line Goto line Qt::Horizontal Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok gl_spinbox buttonBox gl_hslider buttonBox accepted() Dialog accept() 184 93 157 274 buttonBox rejected() Dialog reject() 184 93 286 274 gl_hslider sliderMoved(int) gl_spinbox setValue(int) 79 46 148 48 gl_spinbox valueChanged(int) gl_hslider setValue(int) 142 51 90 49 seascope-0.8/src/ui/about.ui000644 000000 000000 00000033671 12230074152 016024 0ustar00rootroot000000 000000 AboutDialog 0 0 501 296 About Seascope 0 About Qt::Vertical 20 40 Qt::Horizontal 40 20 ImageHere Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600;">Seascope 0.8</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A graphical user interface for idutils, cscope and gtags.</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Copyright © 2010-2013 Anil Kumar</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://seascope.googlecode.com"><span style=" text-decoration: underline; color:#0000ff;">http://seascope.googlecode.com</span></a></p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Qt::Horizontal 40 20 Qt::Vertical 20 40 Author QTextEdit::AutoNone true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anil Kumar</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> anil.omkar@gmail.com</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Developer</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Shu Shen</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> shu.shen@gmail.com</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Developer</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Binghoo Dang</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> dangbinghoo@gmail.com</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Developer</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Code-Context-View feature</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anthony Liu</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> antliu@gmail.com</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Developer</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ratnesh Singh</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> tratneshsingh@gmail.com</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Developer</p></body></html> true Thanks true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Ritesh Raj Sarraf</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> rrs@debian.org</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Debian packaging</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Bug fixes</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> xuhdev@gmail.com</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> tuomas.tuurala@gmail.com</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> License true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">BSD License</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> <a href="http://www.opensource.org/licenses/bsd-license.php"><span style=" text-decoration: underline; color:#0000ff;">http://www.debian.org/misc/bsd.license</span></a></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> Qt::Horizontal QDialogButtonBox::Close ad_buttonbox accepted() AboutDialog accept() 248 254 157 274 ad_buttonbox rejected() AboutDialog reject() 316 260 286 274 seascope-0.8/src/ui/project_settings.ui000644 000000 000000 00000010636 12230074152 020274 0ustar00rootroot000000 000000 ProjectDialog 0 0 351 168 Project Settings Qt::Vertical 20 40 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Project Information</span></p></body></html> Qt::Horizontal 10 20 path: TextLabel type: TextLabel Qt::Horizontal 40 20 Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Ok buttonBox buttonBox accepted() ProjectDialog accept() 257 579 157 274 buttonBox rejected() ProjectDialog reject() 325 579 286 274 seascope-0.8/src/Seascope.py000755 000000 000000 00000050632 12230074152 016051 0ustar00rootroot000000 000000 #!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys import os import string try: from PyQt4 import QtGui, QtCore except ImportError: print 'Error: PyQt4 package not found\nError: required packages: PyQt4 (>4.5) and qscintilla-python\nError: program aborted.' sys.exit(-1) try: from PyQt4.QtGui import * from PyQt4.QtCore import * from view import EdView, EdViewRW, ResView, FileView, CallView, ClassGraphView, FileFuncGraphView, DebugView, CodemarkView, CodeContextView import backend from backend.plugins import PluginHelper import DialogManager import view except ImportError: print "Error: failed to import supporting packages.\nError: program aborted." sys.exit(-1) class SeascopeApp(QMainWindow): def file_preferences_cb(self): ev_font = QFont() ev_font.fromString(self.edit_book.ev_font) res = DialogManager.show_preferences_dialog(self.app_style, self.edit_ext_cmd, ev_font, self.exit_dont_ask, self.inner_editing, self.eb_is_show_line) (self.app_style, self.app_font, self.edit_ext_cmd, ev_font, self.exit_dont_ask, self.inner_editing_conf, self.eb_is_show_line) = res if self.edit_ext_cmd != None: self.edit_ext_cmd = str(self.edit_ext_cmd).strip() if (self.edit_ext_cmd == None or self.edit_ext_cmd == ''): self.edit_ext_cmd = 'x-terminal-emulator -e vim %F +%L' self.edit_book.change_ev_font(ev_font.toString()) self.code_ctx_view.change_ev_font(ev_font.toString()) self.edit_book.show_line_number_pref(self.eb_is_show_line) self.app_write_config() def file_close_cb(self): self.edit_book.close_current_page() def closeEvent(self, ev): if not self.exit_dont_ask and backend.proj_is_open(): ret = DialogManager.show_yes_no_dontask('Close project and quit?') if ret == 1: ev.ignore() return if ret == 2: self.exit_dont_ask = True # extra proc for editing enabled if self.inner_editing: self.edit_book.close_all_cb() self.app_write_config() ev.accept() def file_restart_cb(self): if not DialogManager.show_yes_no('Restart ?'): return hint = self.edit_book.get_file_line_list() if backend.proj_is_open(): self.proj_close_cb() QApplication.quit() os.environ['SEASCOPE_RESTART_HINT'] = '%s' % str(hint) QProcess.startDetached(sys.executable, QApplication.arguments(), self.seascope_start_dir); def file_restarted_cb(self): try: hint = os.environ['SEASCOPE_RESTART_HINT'] #del os.environ['SEASCOPE_RESTART_HINT'] fll = eval(hint) for fl in fll: try: (f, l) = fl.rsplit(':', 1) l = int(l) self.edit_book.show_file_line(f, l, hist=False) except Exception as e: print e pass except: pass def codemark_add(self, f, l): self.cm_mgr.append(f, l) self.edit_book.codemark_add(f, l - 1) actionText = QString(f + " : " + str(l)) act = QAction(actionText, self) self.cm_actionGroup.addAction(act) self.m_cm.addAction(act) def codemark_delete(self, f, l): self.cm_mgr.delete(f, l) self.edit_book.codemark_del(f, l - 1) actionText = QString(f + " : " + str(l)) actions = self.cm_actionGroup.actions() for act in actions: if actionText == act.text(): self.cm_actionGroup.removeAction(act) def codemark_toggle_cb(self): (f, l) = self.edit_book.get_current_file_line() if self.cm_mgr.check(f, l) == 0: self.codemark_add(f, l) else: self.codemark_delete(f, l) def codemark_del_file_cb(self, filename): if filename == '': return for f, l in reversed(self.cm_mgr.codemarks()): if f == filename: self.codemark_delete(f, l) def codemark_del_all_cb(self): if not self.cm_mgr.count(): return if not DialogManager.show_yes_no('Delete all codemarks ?'): return for f, l in reversed(self.cm_mgr.codemarks()): self.codemark_delete(f, l) def codemark_go(self, action): for f, l in self.cm_mgr.codemarks(): if action.text() == QString(f + " : " + str(l)): self.edit_book.show_file_line(f, l) def go_prev_res_cb(self): self.res_book.go_next_res(-1) def go_next_res_cb(self): self.res_book.go_next_res(+1) def go_prev_pos_cb(self): self.res_book.go_next_history(-1) def go_next_pos_cb(self): self.res_book.go_next_history(+1) def go_pos_history_cb(self): self.res_book.show_history() def go_search_file_list_cb(self): self.file_view.search_file_cb() def go_search_ctags_cb(self): self.edit_book.focus_search_ctags() def help_about_cb(self): DialogManager.show_about_dialog() def external_editor_cb(self): self.edit_book.open_in_external_editor(self.edit_ext_cmd) def show_dbg_dialog(self): DebugView.show_dbg_dialog(self) def create_mbar(self): menubar = self.menuBar() m_file = menubar.addMenu('&File') m_file.addAction('&Preferences', self.file_preferences_cb) m_file.addAction('&Debug', self.show_dbg_dialog, 'Ctrl+D') m_file.addSeparator() if self.inner_editing: m_file.addAction('&Save', self.edit_book.save_current_page, 'Ctrl+S') m_file.addAction('&Close', self.file_close_cb, QKeySequence.Close) m_file.addSeparator() m_file.addAction('&Restart', self.file_restart_cb, QKeySequence.Quit) m_file.addAction('&Quit', self.close, QKeySequence.Quit) m_edit = menubar.addMenu('&Edit') if self.inner_editing: m_edit.addAction('Undo', self.edit_book.undo_edit_cb, 'Ctrl+Z') m_edit.addAction('Rebo', self.edit_book.redo_edit_cb, 'Ctrl+Y') m_edit.addSeparator() m_edit.addAction('Copy', self.edit_book.copy_edit_cb, 'Ctrl+C') if self.inner_editing: m_edit.addAction('Paste', self.edit_book.paste_edit_cb, 'Ctrl+V') m_edit.addAction('Cut', self.edit_book.cut_edit_cb, 'Ctrl+X') m_edit.addSeparator() m_edit.addAction('&Find...', self.edit_book.find_cb, 'Ctrl+F') m_edit.addAction('Find &Next', self.edit_book.find_next_cb, 'F3') m_edit.addAction('Find &Previous', self.edit_book.find_prev_cb, 'Shift+F3') m_edit.addSeparator() self.edit_book.m_show_line_num = m_edit.addAction('Show line number', self.edit_book.show_line_number_cb, 'F11') self.edit_book.m_show_line_num.setCheckable(True) self.edit_book.m_show_line_num.setChecked(True) self.show_toolbar = m_edit.addAction('Show toolbar', self.show_toolbar_cb, 'F4') self.show_toolbar.setCheckable(True) m_edit.addSeparator() self.edit_book.m_show_folds = m_edit.addAction('Show folds', self.edit_book.show_folds_cb) self.edit_book.m_show_folds.setCheckable(True) self.toggle_folds = m_edit.addAction('Toggle folds', self.edit_book.toggle_folds_cb) m_edit.addSeparator() m_edit.addAction('Matching brace', self.edit_book.matching_brace_cb, 'Ctrl+6') m_edit.addAction('Goto line', self.edit_book.goto_line_cb, 'Ctrl+G') m_edit.addAction('External editor', self.external_editor_cb, 'Ctrl+E'); m_prj = menubar.addMenu('&Project') m_prj.addAction('&New Project', self.proj_new_cb) m_prj.addAction('&Open Project', self.proj_open_cb) m_prj.addSeparator() act = m_prj.addAction('&Settings', self.proj_settings_cb) act.setDisabled(True) backend.prj_actions.append(act) act = m_prj.addAction('&Close Project', self.proj_close_cb) act.setDisabled(True) backend.prj_actions.append(act) self.backend_menu = menubar.addMenu('') self.m_cm = menubar.addMenu('&Codemark') self.m_cm.addAction('Toggle codemark', self.codemark_toggle_cb, 'Ctrl+B') self.m_cm.addAction('Delete all codemarks', self.codemark_del_all_cb, '') self.m_cm.addSeparator() self.m_cm.addAction('Previous bookmark', self.edit_book.bookmark_prev_cb, 'Alt+PgUp') self.m_cm.addAction('Next bookmark', self.edit_book.bookmark_next_cb, 'Alt+PgDown') self.m_cm.addSeparator() self.cm_actionGroup = QActionGroup(self, triggered=self.codemark_go) m_go = menubar.addMenu('&Go') m_go.addAction('Previous Result', self.go_prev_res_cb, 'Alt+Up') m_go.addAction('Next Result', self.go_next_res_cb, 'Alt+Down') m_go.addSeparator() m_go.addAction('Previous Position', self.go_prev_pos_cb, 'Alt+Left') m_go.addAction('Next Position', self.go_next_pos_cb, 'Alt+Right') m_go.addAction('Position History', self.go_pos_history_cb, 'Ctrl+H') m_go.addSeparator() m_go.addAction('Search file list', self.go_search_file_list_cb, 'Ctrl+Shift+O') m_go.addAction('Search ctags', self.go_search_ctags_cb, 'Ctrl+Shift+T') m_help = menubar.addMenu('&Help') m_help.addAction('About Seascope', self.help_about_cb) m_help.addAction('About Qt', QApplication.aboutQt) def create_toolbar(self): self.toolbar = self.addToolBar('Toolbar') self.toolbar.setIconSize(QSize(16,16)) self.toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly) si = QApplication.style().standardIcon #(QStyle.SP_DirClosedIcon) # exit self.toolbar.addAction(si(QStyle.SP_TitleBarCloseButton), 'Quit', self.close) # edit related # if need editing support if self.inner_editing: self.toolbar.addSeparator() self.toolbar.addAction(si(QStyle.SP_DialogSaveButton), 'Save', self.edit_book.save_current_page) self.toolbar.addSeparator() self.toolbar.addAction(QIcon('icons/undo.png'), 'Undo', self.edit_book.undo_edit_cb) self.toolbar.addAction(QIcon('icons/redo.png'), 'Redo', self.edit_book.redo_edit_cb) self.toolbar.addSeparator() self.toolbar.addAction(QIcon('icons/cut.png'), 'Cut', self.edit_book.cut_edit_cb) self.toolbar.addAction(QIcon('icons/copy.png'), 'Copy', self.edit_book.copy_edit_cb) self.toolbar.addAction(QIcon('icons/paste.png'), 'Paste', self.edit_book.paste_edit_cb) self.toolbar.addSeparator() self.toolbar.addAction(QIcon('icons/find-replace.png'), 'Find & Replace', self.edit_book.find_cb) # find self.toolbar.addSeparator() self.toolbar.addAction(si(QStyle.SP_FileDialogContentsView), 'Find', self.edit_book.find_cb) self.toolbar.addAction(si(QStyle.SP_ArrowDown), 'Find Next', self.edit_book.find_next_cb) self.toolbar.addAction(si(QStyle.SP_ArrowUp), 'Find Previous', self.edit_book.find_prev_cb) self.toolbar.addSeparator() # goto self.toolbar.addAction(QIcon('icons/go-jump.png'), 'Go to line', self.edit_book.goto_line_cb) self.toolbar.addSeparator() # code view self.toolbar.addAction(si(QStyle.SP_FileDialogListView), 'Search ctags', self.go_search_ctags_cb) self.toolbar.addAction(si(QStyle.SP_FileDialogDetailedView), 'Search file list', self.go_search_file_list_cb) self.toolbar.addSeparator() self.toolbar.addAction(si(QStyle.SP_MediaSeekBackward), 'Previous Result', self.go_prev_res_cb) self.toolbar.addAction(si(QStyle.SP_MediaSeekForward), 'Next Result', self.go_next_res_cb) self.toolbar.addSeparator() self.toolbar.addAction(si(QStyle.SP_MediaSkipBackward), 'Previous Position', self.go_prev_pos_cb) self.toolbar.addAction(si(QStyle.SP_MediaSkipForward), 'Next Position', self.go_next_pos_cb) self.toolbar.addSeparator() self.code_ctx_view_act = self.toolbar.addAction(QIcon('icons/codeview.png'), 'Code Quick View', self.code_ctx_view_act_cb) self.code_ctx_view_act.setCheckable(True) self.code_ctx_view_act.setChecked(self.is_show_code_ctx_view) # app config def app_get_config_file(self): config_file = '~/.seascoperc' return os.path.expanduser(config_file) def app_read_config(self): self.recent_projects = [] self.app_style = None self.app_font = None self.ev_font = None self.exit_dont_ask = False self.inner_editing_conf = False self.inner_editing = False self.is_show_toolbar = False self.is_show_code_ctx_view = False self.edit_ext_cmd = 'x-terminal-emulator -e vim %F +%L' self.eb_is_show_line = False path = self.app_get_config_file() if (not os.path.exists(path)): return cf = open(path, 'r') for line in cf: line = line.split('=', 1) key = line[0].strip() if (key == 'recent_projects'): for path in line[1].split(','): path=path.strip() if (os.path.isdir(path)): self.recent_projects.append(path) if (key == 'app_style'): self.app_style = line[1].split('\n')[0] if (key == 'app_font'): self.app_font = line[1].split('\n')[0] if (key == 'edit_font'): self.ev_font = line[1].split('\n')[0] if (key == 'edit_show_line_num'): if ('true' == line[1].split('\n')[0]): self.eb_is_show_line = True if (key == 'show_toolbar'): if ('true' == line[1].split('\n')[0]): self.is_show_toolbar = True else: self.is_show_toolbar = False if (key == 'edit_ext_cmd'): self.edit_ext_cmd = line[1] if (key == 'exit_dont_ask'): if ('true' == line[1].split('\n')[0]): self.exit_dont_ask = True if (key == 'inner_editing'): if ('true' == line[1].split('\n')[0]): self.inner_editing_conf = True else: self.inner_editing_conf = False if os.getenv("SEASCOPE_EDIT"): self.inner_editing = True else: self.inner_editing = self.inner_editing_conf cf.close() def app_write_config(self): cf = open(self.app_get_config_file(), 'w') cf.write('recent_projects' + '=' + string.join(self.recent_projects, ',')+ '\n') if (self.app_style): cf.write('app_style' + '=' + self.app_style + '\n') if (self.app_font): cf.write('app_font' + '=' + self.app_font + '\n') if (self.ev_font): cf.write('edit_font' + '=' + self.ev_font + '\n') if (self.inner_editing_conf): cf.write('inner_editing' + '=' + 'true' + '\n') else: cf.write('inner_editing' + '=' + 'false' + '\n') if (self.eb_is_show_line): cf.write('edit_show_line_num' + '=' + 'true' + '\n') if (self.is_show_toolbar): cf.write('show_toolbar' + '=' + 'true' + '\n') if (self.exit_dont_ask): cf.write('exit_dont_ask' + '=' + 'true' + '\n') if (self.edit_ext_cmd): cf.write('edit_ext_cmd' + '=' + self.edit_ext_cmd + '\n') cf.close() def update_recent_projects(self, path): if (path == None or path == ""): return new_list = [path] for ele in self.recent_projects: if ele != path: new_list.append(ele) self.recent_projects = new_list self.app_write_config() # project menu functions def proj_new_or_open(self): self.editor_tab_changed_cb(None) self.update_recent_projects(backend.proj_dir()) def proj_new_cb(self): if (backend.proj_is_open()): if (not DialogManager.show_proj_close()): return self.proj_close_cb() if backend.proj_new(): self.proj_new_or_open() def proj_open(self, proj_path): rc = backend.proj_open(proj_path) if not rc: print 'proj_open', proj_path, 'failed' return self.proj_new_or_open() def proj_open_cb(self): proj_path = DialogManager.show_project_open_dialog(self.recent_projects) if (proj_path != None): if backend.proj_is_open(): self.proj_close_cb() self.proj_open(proj_path) def proj_close_cb(self): self.update_recent_projects(backend.proj_dir()) self.setWindowTitle("Seascope") backend.proj_close() if self.inner_editing: self.edit_book.close_all_cb() else: self.edit_book.clear() self.res_book.clear() self.file_view.clear() self.cm_mgr.clear() self.code_ctx_view.clear() def proj_settings_cb(self): backend.proj_settings_trigger() def editor_tab_changed_cb(self, fname): #title = backend.proj_name() prj_dir = backend.proj_dir() if prj_dir: parent = prj_dir home_dir = os.path.expanduser('~') for i in range(2): parent = os.path.dirname(parent) if parent == home_dir: break title = os.path.relpath(prj_dir, parent) if not prj_dir: title = 'Seascope' if fname and fname != '': fname = str(fname) #if fname.startswith(prj_dir): #fname = os.path.relpath(fname, prj_dir) title = title + ' - ' + fname else: fname = 'Seascope' title = title + ' - ' + fname self.setWindowTitle(title) def show_file_line(self, filename, line): self.edit_book.show_file_line(filename, line) def show_toolbar_cb(self): self.is_show_toolbar = self.show_toolbar.isChecked() if self.is_show_toolbar: self.create_toolbar() else: self.removeToolBar(self.toolbar) def code_ctx_view_act_cb(self): self.is_show_code_ctx_view = self.code_ctx_view_act.isChecked() if self.is_show_code_ctx_view: self.code_ctx_view.show() else: self.code_ctx_view.hide() def connect_signals(self): self.edit_book.sig_history_update.connect(self.res_book.history_update) self.edit_book.sig_tab_changed.connect(self.editor_tab_changed_cb) self.res_book.sig_show_file_line.connect(self.edit_book.show_file_line) self.file_view.sig_show_file.connect(self.edit_book.show_file) self.edit_book.sig_open_dir_view.connect(self.file_view.open_dir_view) self.edit_book.sig_file_closed.connect(self.codemark_del_file_cb) self.edit_book.sig_editor_text_selected.connect(self.editor_text_selected) self.code_ctx_view.sig_codecontext_showfile.connect(self.code_context_showfile_cb) def editor_text_selected(self, text): if self.is_show_code_ctx_view: if not self.code_ctx_view.set_cur_query(text): return rquery = {} rquery['cmd'] = 'DEF' rquery['req'] = str(text) rquery['opt'] = None sig_res = backend.prj.qry.query(rquery) sig_res[0].connect(self.code_ctx_view_query_res_cb) def code_ctx_view_query_res_cb(self, sym, res): self.code_ctx_view.showResult(sym, res) def code_context_showfile_cb(self, filename, line): self.show_file_line(filename, line) def setup_widget_tree(self): self.hsp = QSplitter(); self.hsp.addWidget(self.edit_book) self.hsp.addWidget(self.file_view) self.hsp.setSizes([700, 1]) self.vsp = QSplitter(); self.vsp.setOrientation(Qt.Vertical) self.vsp.addWidget(self.hsp) self.vsp.addWidget(self.res_book) self.hsp_res = QSplitter(); self.hsp_res.addWidget(self.res_book) self.hsp_res.addWidget(self.code_ctx_view) self.vsp.addWidget(self.hsp_res) self.hsp_res.setSizes([200, 1]) self.vsp.setSizes([1, 60]) self.setCentralWidget(self.vsp) self.setWindowTitle('Seascope') self.setGeometry(300, 100, 800, 600) #self.showMaximized() QApplication.setWindowIcon(QIcon('icons/seascope.svg')) # update checked menu item self.edit_book.is_show_line = self.eb_is_show_line self.edit_book.m_show_line_num.setChecked(self.edit_book.is_show_line) if (self.ev_font): self.edit_book.ev_font = self.ev_font self.code_ctx_view.ev_font = self.ev_font self.show_toolbar.setChecked(self.is_show_toolbar) def create_widgets(self): if self.inner_editing: self.edit_book = EdViewRW.EditorBookRW() else: self.edit_book = EdView.EditorBook() self.res_book = ResView.ResultManager() self.file_view = FileView.FileTree() self.cm_mgr = CodemarkView.CodemarkManager() self.code_ctx_view = CodeContextView.CodeContextViewManager() self.code_ctx_view.hide() self.sbar = self.statusBar() self.create_mbar() if self.is_show_toolbar: self.create_toolbar() def setup_widget_hints(self): if self.inner_editing: EdViewRW.EditorView.ev_popup = self.backend_menu else: EdView.EditorView.ev_popup = self.backend_menu CallView.CallTreeWindow.parent = self ClassGraphView.ClassGraphWindow.parent = self FileFuncGraphView.FileFuncGraphWindow.parent = self PluginHelper.backend_menu = self.backend_menu PluginHelper.edit_book = self.edit_book PluginHelper.res_book = self.res_book PluginHelper.call_view = CallView PluginHelper.class_graph_view = ClassGraphView PluginHelper.file_func_graph_view = FileFuncGraphView PluginHelper.file_view = self.file_view PluginHelper.dbg_view = DebugView def setup_style_and_font(self): if self.app_style: QApplication.setStyle(self.app_style) if self.app_font: font = QFont() font.fromString(self.app_font) QApplication.setFont(font) def __init__(self, parent=None, app_start_dir=None): QMainWindow.__init__(self) self.seascope_start_dir = app_start_dir self.app_read_config() self.create_widgets() self.setup_widget_hints() self.connect_signals() self.setup_widget_tree() self.setup_style_and_font() prj_path = None args = QApplication.arguments() if len(args) == 2: prj_path = str(args[1]) if not os.path.isabs(prj_path): dname = self.seascope_start_dir prj_path = os.path.join(dname, prj_path) if not prj_path or os.getenv('SEASCOPE_RESTART_HINT'): if len(self.recent_projects): prj_path = self.recent_projects[0] if prj_path: self.proj_open(prj_path) #else: #self.proj_open_cb() self.file_restarted_cb() if __name__ == "__main__": # pyqt version 4.5 is required pyqt_required_version = 0x40500 if not QtCore.PYQT_VERSION >= pyqt_required_version: print 'Needs pyqt version > 4.5' sys.exit(-1) # change working dir to the script dir so that we can run this script anywhere else app_start_dir = os.getcwd() app_dir = os.path.dirname(os.path.realpath(__file__)) os.chdir(app_dir) # load plugins backend.load_plugins() view.load_plugins() # start app app = QApplication(sys.argv) ma = SeascopeApp(app_start_dir=app_start_dir) ma.show() ret = app.exec_() sys.exit(ret) seascope-0.8/src/tools/000755 000000 000000 00000000000 12230074152 015064 5ustar00rootroot000000 000000 seascope-0.8/src/tools/ClassGraph.py000644 000000 000000 00000022563 12230074152 017475 0ustar00rootroot000000 000000 #!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys import subprocess import os import re class CtagsInhCache: def __init__(self, is_base, is_fq, is_debug): self.cit_cache = {} self.is_base = is_base self.is_fq = is_fq self.is_debug = False map = os.getenv('SEASCOPE_CTAGS_SUFFIX_CMD_MAP', 0) if map: try: map = eval(map) except: print 'SEASCOPE_CTAGS_SUFFIX_CMD_MAP has errors' map = None self.ct_custom_map = map def _filterCtInherits(self, data, sym=None): res = {} for line in data: if line == '': continue line = line.split('\t', 4) if len(line) == 4: continue _sd = dict([ x.split(':', 1) for x in line[4].split('\t')]) if 'inherits' not in _sd: continue sd = _sd['inherits'].strip() if sd == '': continue if 'class' in _sd: cls = _sd['class'].strip() else: cls = None if line[1] not in res: res[line[1]] = [] res[line[1]].append([line[0], sd, cls]) if self.is_debug: print line[0], line[1], sd, cls return res def _runCtagsCustom(self, fl): if not self.ct_custom_map: return [] cmd_list = [] for (suffix, cmd) in self.ct_custom_map: _fl = [ f for f in fl if f.endswith(suffix) ] args = cmd.split() args += _fl cmd_list.append(args) if not len(cmd_list): return [] out_data_all = [] for args in cmd_list: proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate('\n'.join(fl)) out_data = re.split('\r?\n', out_data) out_data_all += out_data return out_data_all def _runCtags(self, fl): cmd = 'ctags -n -u --fields=+i -L - -f -' args = cmd.split() proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate('\n'.join(fl)) out_data = re.split('\r?\n', out_data) out_data += self._runCtagsCustom(fl) return out_data def runCtagsInh(self, fl): data = self._runCtags(fl) ct_dict = self._filterCtInherits(data, None) for f in fl: if f not in ct_dict: ct_dict[f] = [] return ct_dict def ctInhInfo(self, flist): fl = [ f for f in flist if f not in self.cit_cache ] #print len(fl), len(flist), len(self.cit_cache) if len(fl): ct_dict = self.runCtagsInh(fl) self.cit_cache.update(ct_dict) res = [] for f in flist: res += self.cit_cache[f] return res class ClassGraphGenerator: def __init__(self, d, pcmd=None, wlimit=5000, is_base=False): self.wdir = d; self.pcmd = pcmd self.width_limit = wlimit; self.dname = None self.dirCtInhInfo = None self.graphRules = [] self.visitedRules = {} self.visitedSym = {} if is_base: self.visitedSym = {'object' : 1} if os.getenv('SEASCOPE_CTAGS_SUFFIX_CMD_MAP', 0): for c in [ 'Entity', 'Type', 'PtrInterFace','Enum','Nominal' ]: self.visitedSym[c] = 1 self.visitedSym['Tac::' + c] = 1 self.is_base = is_base self.is_fq = False self.is_debug = os.getenv('SEASCOPE_CLASS_GRAPH_DEBUG', 0) self.cic = CtagsInhCache(self.is_base, self.is_fq, self.is_debug) def addGraphRule(self, sym, d): if (sym, d) in self.visitedRules: return self.visitedRules[(sym, d)] = True self.graphRules.append([sym, d]) def refFiles(self, sym): args = list(self.pcmd) + [sym] try: # In python >= 2.7 can use subprocess.check_output # output = subprocess.check_output(args, cwd=self.wdir) proc = subprocess.Popen(args, cwd=self.wdir, stdout=subprocess.PIPE) (output, err_data) = proc.communicate() output = re.split('\r?\n', output) except Exception as e: print >> sys.stderr, 'dir:', self.wdir, ':cmd:', args, ':', e, '\n' sys.exit(-1) res = set() for line in output: if line == '': continue f = line.split(':', 1)[0] f = os.path.normpath(os.path.join(self.wdir, f)) res.add(f) return res def parseCtagsInherits(self, data, sym=None): res = [] for line in data: sd = line[1] if sd == '': continue sd = sd.split(',') if self.is_fq: dd = [ x.strip() for x in sd ] cls = line[2] else: dd = [ re.split('::|\.', x.strip())[-1] for x in sd ] cls = None if not sym: res.append([line[0], dd]) continue if self.is_base: if cls: if sym == cls + "::" + line[0]: res += dd if sym == cls + "." + line[0]: res += dd else: if sym == line[0]: res += dd else: if sym in dd: if cls: sep = '::' if '.' in cls: sep = '.' res.append(cls + sep + line[0]) else: res.append(line[0]) if self.is_debug: if sym: print sym, res return res def classHierarchy(self, sym): if self.is_fq: subSym = re.split('::|\.', sym)[-1] else: subSym = sym if self.pcmd: fl = self.refFiles(subSym) data = self.cic.ctInhInfo(fl) else: data = self.dirCtInhInfo res = self.parseCtagsInherits(data, sym) return res def runCtInhForDir(self, dname): self.dname = dname fl = [] for root, dirs, files in os.walk(dname, followlinks=True): fl += [os.path.join(root, f) for f in files] self.dirCtInhInfo = self.cic.ctInhInfo(fl) def classHierarchyRecursive(self, symList): for sym in symList: if sym in self.visitedSym: continue self.visitedSym[sym] = 1 dclasses = self.classHierarchy(sym) if len(dclasses): if len(dclasses) > self.width_limit: if is_base: s = 'base' else: s= 'derived' print >> sys.stderr, 'num %s classes(%s) = %d, truncating to %d.\n' % (s, sym, len(dclasses), self.width_limit) dclasses = dclasses[0:self.width_limit] self.addGraphRule(sym, '...(%s)' % sym) for d in dclasses: self.addGraphRule(sym, d) self.classHierarchyRecursive(dclasses) def classHierarchyForDir(self, dname): res = self.parseCtagsInherits(self.dirCtInhInfo) for (d, blist) in res: for b in blist: self.addGraphRule(b, d) def prepareDotInput(self, sym_or_dname): if len(self.graphRules) == 0: if is_base: s = 'base' else: s= 'derived' print >> sys.stderr, 'No %s classes for %s\n' % (s, sym_or_dname) sys.exit(0) dotInput = 'digraph "%s" {\n' % sym_or_dname if not sym_or_dname: dotInput += '\t"%s" [style=bold];\n' % sym_or_dname for r in self.graphRules: if not self.is_base: dotInput += '\t"%s" -> "%s";\n' % (r[0], r[1]) else: dotInput += '\t"%s" -> "%s";\n' % (r[1], r[0]) dotInput += '}\n' return dotInput def saveDotFile(self, sym, dotInput): f = open(sym + '.dot', 'w') f.write(dotInput) f.close() def saveSvgFile(sym, svg_data): dot_svg = sym + '.svg' f = open(dot_svg, 'w') f.write(svg_data) f.close() print >> sys.stderr, 'saved', dot_svg, '\n' def generateGraph(self, dname, sym=None): if not self.pcmd: self.runCtInhForDir(dname) if sym: if sym == '::' or sym == '.': return if re.search('::|\.', sym): self.is_fq = True if sym.startswith('::') or sym.startswith('.'): sym = re.split('::|\.', sym, maxsplit=1)[-1] self.classHierarchyRecursive([sym]) dotInput = self.prepareDotInput(sym) else: self.classHierarchyForDir(dname) dotInput = self.prepareDotInput(dname) if self.is_debug: print dotInput return '' #self.saveDotFile(sym, dotInput) args = ['dot', '-Tsvg'] try: p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (svg_data, err_data) = p.communicate(dotInput) if err_data and err_data != '': print >> sys.stderr, err_data, '\n' #self.saveSvgFile(sym, svg_data) return svg_data except Exception as e: print >> sys.stderr, 'Failed to run:', ' '.join(args), '\n' print >> sys.stderr, e, '\n' if __name__ == '__main__': import optparse usage = "usage: %prog [options] (-d | -t ) [symbol]" op = optparse.OptionParser(usage=usage) op.add_option("-b", action="store_true", dest="is_base", help="Show base classes") op.add_option("-d", "--codedir", dest="code_dir", help="Code dir", metavar="CODE_DIR") op.add_option("-t", "--type", dest="prj_type", help="project type: idutils|gtags|cscope", metavar="PRJ_TYPE") (options, args) = op.parse_args() # dname if not options.code_dir: print >> sys.stderr, 'Specify -d' sys.exit(-1) dname = options.code_dir if not os.path.exists(dname): print >> sys.stderr, '"%s": does not exist' % dname sys.exit(-2) wdir = dname if not os.path.isdir(wdir): wdir = os.path.dirname(wdir) # sym sym = None if len(args): if len(args) != 1: print >> sys.stderr, 'Please specify only one symbol' sys.exit(-3) sym = args[0] # ptype ptype = options.prj_type if ptype: if not sym: print >> sys.stderr, '-t option needs sepficfying symbol' sys.exit(-4) if not os.path.isdir(dname): print >> sys.stderr, '-t option needs codedir to be a directory' sys.exit(-5) pcmd = None if ptype and os.path.isdir(dname): prj_list = [ ['idutils', 'ID', ['lid', '-R', 'grep', '--'] ], ['gtags', 'GRTAGS', ['global', '-a', '--result=grep', '-x', '-r', '--'] ], ['cscope', 'cscope.out', ['cscope', '-L', '-d', '-0', '--'] ], ['grep', '', ['grep', '-R', '-n', '-I', '--',] ], ] for p in prj_list: if p[0] == ptype: if os.path.exists(os.path.join(dname, p[1])): pcmd = p[2] break # is_base is_base = options.is_base # run cgg = ClassGraphGenerator(wdir, pcmd=pcmd, is_base=is_base) svg_data = cgg.generateGraph(dname, sym) print svg_data seascope-0.8/src/tools/FileFuncGraph.py000755 000000 000000 00000016351 12230074152 020124 0ustar00rootroot000000 000000 #!/usr/bin/python import os, sys, re import subprocess import shutil import tempfile GRAPH_ON_TYPES = ['function', 'macro'] def _eintr_retry_call(func, *args): while True: try: return func(*args) except OSError, e: if e.errno == errno.EINTR: continue raise def ct_cmdForFile(f): #ct_args = 'ctags -n -u --fields=+K -f - --extra=+q' #ct_args = 'ctags -n -u --fields=+Ki -f -' ct_args = 'ctags -n -u --fields=+K -f -' if os.path.isdir(f): cmd = ct_args + ' -R' return cmd suffix_cmd_map = [] custom_map = os.getenv('SEASCOPE_CTAGS_SUFFIX_CMD_MAP') if custom_map: custom_map = eval(custom_map) suffix_cmd_map += custom_map suffix_cmd_map.append( ['', ct_args] ) for (suffix, cmd) in suffix_cmd_map: if f.endswith(suffix): return cmd return None def ct_query(filename): args = ct_cmdForFile(filename) args = args.split() args.append(filename) try: proc = subprocess.Popen(args, stdout=subprocess.PIPE) (out_data, err_data) = _eintr_retry_call(proc.communicate) out_data = out_data.split('\n') except Exception as e: out_data = [ 'Failed to run ctags cmd\tignore\t0;\t ', 'cmd: %s\tignore\t0;\t ' % ' '.join(args), 'error: %s\tignore\t0;\t ' % str(e), 'ctags not installed ?\tignore\t0;\t ', ] res = [] for line in out_data: if (line == ''): break line = line.split('\t') num = line[2].split(';', 1)[0] line = [line[0], num, line[3]] res.append(line) return res class FFgraph: def __init__(self): self.cs_cmd_base = None def parse_cs_result(self, text): text = re.split('\r?\n', text) res = [] for line in text: if line == '': continue line = line.split(' ', 3) line = [line[1], line[0], line[2], line[3]] res.append(line) return res def findCalleeList(self, caller, srcFile): try: cmd = self.cs_cmd_base + [ '-2', caller ] if os.path.isdir(srcFile): cmd = cmd + [ '-s' ] cmd = cmd + [ srcFile ] # In python >= 2.7 can use subprocess.check_output # output = subprocess.check_output(cmd) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) (output, err_data) = proc.communicate() #print 'cmd =', cmd #print 'output =', output res = self.parse_cs_result(output) res = set([ e[0] for e in res ]) except Exception as e: print >> sys.stderr, 'failed cmd:', cmd, ':', e res = [] return res def generateDotHeader(self, name): out = 'digraph "%s" {\n' % name #out += '\tconcentrate=true;\n' return out def generateDotFooter(self): out = '}\n\n' return out def generateSubgraphHeader(self, name): out = '\tsubgraph "%s" {\n' % name return out def generateSubgraphFooter(self): out = '\t}\n\n' return out def generateClusterInfoLocal(self, localSym): out = '' # local out += self.generateSubgraphHeader('cluster_local_sym') for sym in localSym: out += '\t\t%s;\n' % sym out += self.generateSubgraphFooter() return out def generateClusterInfoExternal(self, externalSym): out = '' # extern out += self.generateSubgraphHeader('cluster_external_sym') for sym in externalSym: out += '\t\t%s;\n' % sym out += self.generateSubgraphFooter() return out def generateClusterInfo(self, localSym, externalSym): out = '' #out += self.generateClusterInfoLocal(localSym) out += self.generateClusterInfoExternal(externalSym) return out def generateDotInput(self, f, callerCalleInfo, is_extern): dotInput = '' dotInput += self.generateDotHeader(f) (localSym, externalSym, callerCalleInfo) = callerCalleInfo if is_extern: dotInput += self.generateClusterInfo(localSym, externalSym) # nodes for (caller, localCalleeList, externCalleeList) in callerCalleInfo: for callee in localCalleeList: dotInput += '\t"%s" -> "%s";\n' % (caller, callee) if not is_extern: continue for callee in externCalleeList: style = '[style=dotted]' dotInput += '\t"%s" -> "%s" %s;\n' % (caller, callee, style) dotInput += self.generateDotFooter() return dotInput def _generateDotGraph(self, f, is_extern, gOut): try: res = self.getCallerCalleeInfo(f, is_extern) dotInput = self.generateDotInput(f, res, is_extern) except Exception as e: print >> sys.stderr, e if not gOut: print dotInput return None args = ['dot', '-Tsvg'] try: p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (svg_data, err_data) = p.communicate(dotInput) if err_data and err_data != '': print >> sys.stderr, err_data, '\n' #self.saveSvgFile(sym, svg_data) return svg_data except Exception as e: print >> sys.stderr, 'Failed to run:', ' '.join(args), '\n' print >> sys.stderr, 'dotInput:', dotInput, '\n' print >> sys.stderr, e, '\n' def generateDotGraph(self, f, is_extern, gOut): tmp_cs_dir = tempfile.mkdtemp(prefix='ffgraph_') if not tmp_cs_dir: print 'generateDotGraph: failed to create tmp dir' return self.cs_cmd_base = [ 'cscope', '-L', '-f', os.path.join(tmp_cs_dir, 'cscope.out') ] svg_data = None try: svg_data = self._generateDotGraph(f, is_extern, gOut) except: print 'generateDotGraph: failed' shutil.rmtree(tmp_cs_dir) return svg_data def getCallerCalleeInfo(self, f, is_extern): ct_out = ct_query(f) localSym = dict([ (e[0], e[2]) for e in ct_out ]) lSym = [] eSym = [] res = [] visitedCaller = dict() for e in ct_out: if e[2] in GRAPH_ON_TYPES: caller = e[0] if caller in visitedCaller: continue visitedCaller[caller] = True calleeList = self.findCalleeList(caller, f) localCalleeList = [] externCalleeList = [] for c in calleeList: if c in localSym and localSym[c] in GRAPH_ON_TYPES: localCalleeList.append(c) continue if is_extern: externCalleeList.append(c) res.append([caller, localCalleeList, externCalleeList]) if is_extern: if len(localCalleeList) or len(externCalleeList): lSym += [caller] + localCalleeList eSym += externCalleeList else: if len(localCalleeList): lSym += [caller] + localCalleeList return [lSym, eSym, res] def ff_graph(f, is_extern, gOut=True): #if not os.path.isfile(f): #return None ffg = FFgraph() #gOut = False svg_data = ffg.generateDotGraph(f, is_extern, gOut) return svg_data if __name__ == '__main__': import optparse usage = "usage: %prog [options] (-d | -p ) (-e) [symbol]" op = optparse.OptionParser(usage=usage) op.add_option("-e", action="store_true", dest="is_extern", help="include external sym") op.add_option("-d", "--codedir", dest="code_dir", help="Code dir", metavar="CODE_DIR") op.add_option("-p", "--project", dest="id_path", help="Idutils project dir", metavar="PROJECT") (options, args) = op.parse_args() if (not any([options.code_dir, options.id_path]) or all([options.code_dir, options.id_path])): print >> sys.stderr, 'Specify one among -d or -p' sys.exit(-1) sym = None dname = None is_extern = False if options.is_extern: is_extern = True if len(args): if len(args) != 1: print >> sys.stderr, 'Please specify only one symbol' sys.exit(-2) sym = args[0] svg_data = None if options.code_dir: dname = options.code_dir if not os.path.exists(dname): print >> sys.stderr, '"%s": does not exist' % dname sys.exit(-3) svg_data = ff_graph(dname, is_extern=is_extern) print svg_data seascope-0.8/src/icons/000755 000000 000000 00000000000 12230074152 015037 5ustar00rootroot000000 000000 seascope-0.8/src/icons/save.png000644 000000 000000 00000001060 12230074152 016500 0ustar00rootroot000000 000000 ‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<­IDAT8“1‹Q…¿;ÉJ&…ň,b³I5ÃQlü©l[‚àÿ`·XÇÒBHc•RdAa‹‘ Ûˆà²n¥6Ë2ÝÝ‹™ÑÇ$ 8<ç¾óî½ï>“Ô®WcN€ŸÀùª*mA° ?Öð8‚]I›’¨Ó$u<Ï{#颼­3³Ær¹||qbÐLRh>Ÿ¿ Ãð¬:™¦éFE$YYÞ–cœßÔö€=IÛ’ÕÝ='(Ç7(Õ¶Ê}^™Hz[±*Á$u|ß–çùWœ ~i«Õ:[,/ÌìµSÂC೜Äq|àûþ)°|p¸ïûþiÇå9W+ÚRŽòm ¢˜‹:Î)žîÈÌ;¼„bˆêÍ«ãæh4z2™LîIzÿ7Øìþp8üè\†pw6›…ƒÁàz–ev»}1N¿÷ûýtås\B“%I²Óëõž&I²#)’dÿ“‹[ÀŠfüýŸ®-ê•IEND®B`‚seascope-0.8/src/icons/copy.png000644 000000 000000 00000001025 12230074152 016515 0ustar00rootroot000000 000000 ‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<’IDAT8…“½nQ…¿YmÀkK)‹ˆŽÂIe+-Ï@KAEA“b‘eÉt.x^€‚7 ¢‹hì"î¢H¸H¤ÜÅŠ³‡‚»ÑõÕ#fFçΙsÿL‘¥À#`°\k`‹¤Øò<Ÿ—ÀÏ¿Ìó|.é@)0 —$É'I•Ÿ›™YRUÕK`•6É–TZ,ûýþmݹ\.÷ƒÁkIv¿½Zv·Û}|—tœ§’Ž%%’ÌÇã;’d©gÚ_¯×/€ ?lãcé·¡ ®±{éxÙW@4Y#€ ò_ÿ ØÁB‚Í_r‹âŽ‚$jÚ„ùp8|ô€C çëpæ¯äÐÌÞHš·Û퓲,÷€ð0²È²ìÖ9÷X5*(Šâ<˲à øøY–e7EQœóç9+Tð`4}žÍf€§ÑÕ¶À7`[ô:Î+ç\ <Zq—™m«ªz ¬žxê‹ëÉdr1N;ç¾ÄÍ­Vën<ÿ¨eïûÏ”Ïü¡ýWvü¹.Òdo½;3IEND®B`‚seascope-0.8/src/icons/go-jump.png000644 000000 000000 00000001123 12230074152 017120 0ustar00rootroot000000 000000 ‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<ÐIDAT8¥“AˆRQ†¿÷žútz•TS‹aÀv…Caꈋ6‚¸±p¶nÛÊ•àÖM» wB [Iƒn¢‡ŒÑìd“äÕIãx™ÓB›Õ‹~¸ðîåç|‡s5áäqùî2paágÀ8N7g 8Ž4Mûlšæ›|>ÿ@DÖ5—[š¦½^x0ý~ÿþx<~¦»D;Žó¢Ùl¾J§Óo_J©ín·k¹E@D|"r±Ñh¤=`ïààà–Û!Li"‘8€Ïç“ XJ“eáfç”R7€3!êlÀ`Ú¢öײÙì®eYÏu@/‹W—^¯wŽ ”ÚŒD" €V«õ.œÔëõë¹\îñp8Üú¶m›•Je·Z­Þ&º®ŸZ–…X‹F£ñv»ý ‹Îf3½Óé<‘cà# ápø%óA~¾&“É~0{B¡ÐoÛ¶?-½aƒÁ`ßqc± `YÖ4ÿ, ‡Àå&Þ®Õjw2™Ìû9•Ú)•JçËåò¥”g4}0MsbFÑÙ·ÕEÙ‘›"¢­,ν^¯÷$•J=‘mÑWîÜü…KÀ]àÂÿ/ý°ËbXà,IEND®B`‚seascope-0.8/src/icons/seascope.svg000644 000000 000000 00000007505 12230074152 017371 0ustar00rootroot000000 000000 Seascope image/svg+xml Seascope Anil Kumar Seascope logo http://seascope.googlecode.com S seascope-0.8/src/icons/undo.png000644 000000 000000 00000001053 12230074152 016511 0ustar00rootroot000000 000000 ‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<¨IDAT8Õ“1hZaÇß÷¤O¾‡!ÄfÉPt©Ðºuynqê–¥ƒà Ý\:9tt;Û¡H ]; éh)fh²”F*’AHòj«¾´¦ëò•vê’¥ýß;¸»?wÇn}£êB blÔð À-Àl㯀o@`ø"‚ˆds¹Ü#Ù‘MÏóÄb±}¥Ô⬉ÖzF÷=ÏÛ‘Û"¢Mˆˆêõz;À‡L&óØqœ.p ¼†ÀcS×uŸŽF£;"”ˆØ•Jew0ÔMà˜™QˆÇã‹ ¦a¤‰Ä»ù|þ˜jÀžL&ëfþÀXkí×ëõƒÙlör¹\¾šN§/ÆÖÚ>-‹íZ­vˆiÀö}ß¾þ¢RêG2™¼r]÷x–N§Ÿw»Ý×ívûÐäœõûý]`#ØA¬™aÎ;Î}ÇqNZ­ÖÈlþm³Ùd<ëB¡°ªV«×ÀJ‰Èv*•z˜Ïç?‹Åïår9,•J’ÍfC˲Ž# 4Ú6p¸΀@‰Èà¾á9pñÇMüêÿ¦Ÿ¥E´Ý³l2IEND®B`‚seascope-0.8/src/icons/cut.png000644 000000 000000 00000001344 12230074152 016342 0ustar00rootroot000000 000000 ‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<aIDAT8u“ÁK“qÇ?¿÷uàtó7ó –¬¹ Ád0ËË A˜I„°þžúJ"‘n£C Ü¡ƒÐ›ƒÂ×ì¢Õa b l4„X°¹“ž.ïd.{à¹<ßçûåû}àQ"‚S.à2p ìg€SÊÁ›¼ `Ô-´Ösápxèäßò‡ÃáI­õ8›ŠH­Ã¦if”R[ÉdrHDšë°æd29¤”Ú2M3#"áV/ ) ëv»—D¤WD”Ó½n·{ È×"¬ñê#æçç×r¥R¹FG€ #ŽT*•~¥Tiaaá#P¸(‚‘ÁX,ö X5 cÝ¶íµµµë†a¬«cccODd ŽsNiÉf³w].ײRêýôôtÜëõ¾>´¶¶¾ÉårwnCSåˑH$;33Ó·½½íÓZ·‹Å~à×ìììF(Ê¿Ï1 "®B¡0jYÖ½¶¶¶§@: =¯V«·DÄlÜ¿HéÈçó7•RiÓ4_f2™"â»h×hˆ > 3‹Ýƒ?vvv¾äóùŸ@—ƒéÿEð%‰QÃ0V€M`yqqñáøøø#à°iÆJ"‘­wSïÀ›J¥¦&&&6Òéô+`¯X,憇‡¿Ÿãñøc¿ßÿ.•JMÞIÕ=SŸÇ㹉DNwww»NNN ‡‡‡oº»»ã"ÒæñxöËå².•Ji 矩dYVþøø¸Ãçó•lÛ>ÐZi­lÛ>èéé©´··_²,+”.r €«À #üøî`W€À` ØÃy÷¿ }úê®IEND®B`‚seascope-0.8/src/icons/paste.png000644 000000 000000 00000001007 12230074152 016657 0ustar00rootroot000000 000000 ‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<„IDAT8•’AKã@…¿‰-Øé¥´°¯‚©°¨Ù=ïÍûþÿB)äxñxô ì}ñh@؃‚â¡!–e ]ÐÆ6jž'5ôÁ#óæ%oÞÌIHªHjGQ´†á:ð¯È0 ×£(Z“´$©ê¾7øÔjµvßÀ_àBÒNFàÂÍÆž¤v`$¬xžw¨g!ž±Ì þ¸§1ÆTÓ4ý\TœáIºÍi€kJ )<ÇÔËy`úNšÍæ°”o€3Ó²U‹F_€z1 áeÿôûýŸ¾ïÏBƒ×ét¶ÿ€™ 0ÆL%Í5ð}ÿ8Ïé à[þbƒâîJôô#eHÞ ˜ï˜k]cZ«ÕƼ¾²·f^pÓív¯­µw®b$½^¯ ¬ft:óf¿ò° lÕz½ÞŽã¸|s«O€_ÖÚ‡ñx|\e S`øÁÐZÇÀQŽÇÖÚ8‚!p“oP<—-à3P-9ƒ{à8žDôÂZC~ÚìIEND®B`‚seascope-0.8/src/icons/redo.png000644 000000 000000 00000001056 12230074152 016500 0ustar00rootroot000000 000000 ‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<«IDAT8Å“?kZq†Ÿ{½þÁ.RÚ¯‰E›[S(qÉà*‚ v° àV E©›_@DŠ‹`Àݵ’ÁîR‘@’El¥`[)m¥&ü’rO—kÉ%Xè‡÷<Ëy&"¬SúZÛÿ`ÜÀë¼WäÎVð;¦Ÿ€íÌ]ÀÆb±ðçóù‡ý~ÿñ|>)¥¢çör¹|‚ˆÜ«V«{‘HäU x#"÷EGþJ¥òÌ0Œ0FÀ)p …Ú"BDÂáp¸ï-Ëz!""b8V«õÒår½WŠÇã¯EäŽÌ›Íæ®ë#àÃx<~jšæó^¯÷H)µ].—7kµZ¸+E£ÑO€2€ót:=Èf³[NÇ~Íf³d*•Ú×4íBD¼ÀWà ð74Édòó 0i·ÛÇÁ`P5-Û¶šˆ¸ Ã0ìb±85Mów¡PxËå¾—Ú•$º½Á`°S¯×}ÃáÐ;N}–e% U*•Îc±Ø) Ýnw7“ɼ&Ú5Q6mà.pË9ë7àÄé5À>ê:ÀêÿÿÂÚ€?”;·ŒÒ 9IEND®B`‚seascope-0.8/src/icons/find-replace.png000644 000000 000000 00000001362 12230074152 020100 0ustar00rootroot000000 000000 ‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<oIDAT8u’ßKÓQÆ?g;ÎoßEµl kk).»$Ì A¢‹.²+‚ òJºíÆØ`Pý¼0FWÔ†å…`VR¶ÈR(‰`nÐzº™±Lx9œ÷|à¼Ïk$Q¡-ÀfÀ€<ð“$ IVR´©©éœµö¹1fÎóÑZû4™Lž’T+ÉWîý§VM4 ^欵/ëëëïÅãñ´µö50‡SeȺ€­---½ÀÛ†††³³³g%tjzzú|$Io»ººŽK ®Øe­­®®~433sZRMEC|||¼Ï“u]÷ФÈZ€pJ¥Ò¦x<žkll||¯Ñ§ŽŽŽWápøs±XÜÖÎÐr]wiaa¡¬¬¹7ÅbñG>Ÿÿ …–ÊÉü#P¨­­Í-//Ǻ»»!À”k»çyÉB¡°-‘H|(Çú_ŒÁt:}ÒçóÝñûý<Ï;½¸¸¸/—Ë5¶µµõcwGFFº$mÚ(ƺT*uÁï÷ßžc²Æ˜qàp¸F/·I WLy}À©©©ƒCCC¡ÉÉÉ®ë–Z[[¿õ÷÷/ŽŽ:ƒƒƒG€P{{ûÈÄÄÄcà+ð°ª°Øü¾ïæç盉ı••¨ëì켕ÍfŸ_‘äHŠIÚ-isù¬ô1I{2™LŸëº)à2p?™Lž”Tƒ¤X ¸®IÚ·IJd2™3Žã\«ªªnJÚkš››¿¬þa#¼÷<ÏŒêé驸,Ipø <—¬zð°b@+ðxýí³9t9»IEND®B`‚seascope-0.8/src/icons/codeview.png000644 000000 000000 00000001072 12230074152 017352 0ustar00rootroot000000 000000 ‰PNG  IHDRóÿasBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<·IDAT8“1‹Q…¿—Dœd`3Å Ûµ™Âba›ÒmbþA •aþˆl©…ÙB™V [ˆ†Àfw…;ÍI0섉³Éµy“!)ôÀ…Çyçžwî…§D„Ä>°§Ï7}È6`¹kà7°§”:‘'‰mÛö«étzÜÝa°,—Ë'“Éä21°f³ÙsàØ5“Òšc`™5È‰È °F'Žãܦ;}ß/T«Õ#I£ä.=ïˆÇù¼Þ÷ûý³b±øTs‘Ö$Q:©Xp¿Ùlöz½×«Õ ‘Nç`Û±*•Js<¿Ð;Y*¥>¦t€KÃ0–Àz«A­VËAð#Žã¼¦¾§wbFÜn·Ïù¶ð<¯?gFãa÷D䛈s`²50¨×ë×¾ï?kµZÀg¥Ô[i‰0—1ˆºÝî>ð0-Ëxž÷Ss§º6 ô_x`šæËÅbQFF_K¥Òm†ï€_Ùs×u¯LÓ õ+Ÿ2ujšfèºî0ß– 5àN6¦F²¸°Êü7þ­j²“‰î÷BIEND®B`‚seascope-0.8/src/backend/000755 000000 000000 00000000000 12230074152 015313 5ustar00rootroot000000 000000 seascope-0.8/src/backend/plugins/000755 000000 000000 00000000000 12230074152 016774 5ustar00rootroot000000 000000 seascope-0.8/src/backend/plugins/cscope/000755 000000 000000 00000000000 12230074152 020250 5ustar00rootroot000000 000000 seascope-0.8/src/backend/plugins/cscope/ui/000755 000000 000000 00000000000 12230074152 020665 5ustar00rootroot000000 000000 seascope-0.8/src/backend/plugins/cscope/ui/cs_project_settings.ui000644 000000 000000 00000016403 12230074152 025303 0ustar00rootroot000000 000000 ProjectDialog 0 0 602 589 Project Settings <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Project Path &amp; Name</span></p></body></html> QFrame::StyledPanel QFrame::Plain ... 140 16777215 Qt::Vertical QSizePolicy::Fixed 20 10 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Cscope files</span></p></body></html> QFrame::StyledPanel QFrame::Plain Qt::Horizontal 40 20 Add Remove <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Cscope options</span></p></body></html> QFrame::StyledPanel QFrame::Plain Inverted index (-q) Kernel project (-k) Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok pd_path_inp pd_path_tbtn pd_name_inp pd_src_list pd_add_btn pd_rem_btn pd_invert_chkbox pd_kernel_chkbox buttonBox buttonBox accepted() ProjectDialog accept() 257 579 157 274 buttonBox rejected() ProjectDialog reject() 325 579 286 274 seascope-0.8/src/backend/plugins/cscope/ui/cs_query.ui000644 000000 000000 00000007020 12230074152 023055 0ustar00rootroot000000 000000 QueryDialog Qt::ApplicationModal 0 0 357 171 Cscope Query 40 16777215 Type false Symbol true 10 50 16777215 Substring Case Insensitive Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qd_sym_inp qd_substr_chkbox qd_icase_chkbox buttonBox qd_cmd_inp buttonBox accepted() QueryDialog accept() 248 254 157 274 buttonBox rejected() QueryDialog reject() 316 260 286 274 seascope-0.8/src/backend/plugins/cscope/__init__.py000644 000000 000000 00000000653 12230074152 022365 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os def name(): return 'cscope' def is_your_prj(path): f = os.path.join(path, 'cscope.files') return os.path.exists(f) def project_class(): from CscopeProject import ProjectCscope return ProjectCscope def description(): d = 'Cscope supports C, lex, yacc files.\n' d += 'Support for C++ and Java is limited.' return d priority = 500 seascope-0.8/src/backend/plugins/cscope/CscopeProjectUi.py000644 000000 000000 00000020167 12230074152 023671 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase from ..PluginBase import QueryUiBase from .. import PluginBase, PluginHelper cmd_table = [ [ ['REF', '0'], ['&References', 'Ctrl+0'], ['References to' ] ], [ ['DEF', '1'], ['&Definitions', 'Ctrl+1'], ['Definition of' ] ], [ ['<--', '2'], ['&Called Functions', 'Ctrl+2'], ['Functions called by' ] ], [ ['-->', '3'], ['C&alling Functions', 'Ctrl+3'], ['Functions calling' ] ], [ ['TXT', '4'], ['Find &Text', 'Ctrl+4'], ['Find text' ] ], [ ['GREP','5'], ['Find &Egrep', 'Ctrl+5'], ['Find egrep pattern' ] ], [ ['FIL', '7'], ['Find &File', 'Ctrl+7'], ['Find files' ] ], [ ['INC', '8'], ['&Including Files', 'Ctrl+8'], ['Find #including' ] ], [ ['---', None], [None ] ], [ ['QDEF', '11'], ['&Quick Definition', 'Ctrl+]'], [None ] ], [ ['CTREE','12'], ['Call Tr&ee', 'Ctrl+\\'], ['Call tree' ] ], [ ['---', None], [None ], ], [ ['CLGRAPH', '13'], ['Class &Graph', 'Ctrl+:'], ['Class graph' ] ], [ ['CLGRAPHD', '14'], ['Class Graph Dir', 'Ctrl+;'], ['Class graph dir' ] ], [ ['FFGRAPH', '14'], ['File Func Graph', 'Ctrl+^'], ['File Func graph dir' ] ], [ ['---', None], [None ], ], [ ['UPD', '25'], ['Re&build Database', None ], [None ] ], ] menu_cmd_list = [ [c[0][0]] + c[1] for c in cmd_table ] cmd_str2id = {} cmd_str2qstr = {} cmd_qstr2str = {} for c in cmd_table: if c[0][1] != None: cmd_str2id[c[0][0]] = c[0][1] cmd_str2qstr[c[0][0]] = c[2][0] cmd_qstr2str[c[2][0]] = c[0][0] # python 2.7 #cmd_str2id = { c[0][0]:c[0][1] for c in cmd_table if c[0][1] != None } #cmd_str2qstr = { c[0][0]:c[2][0] for c in cmd_table if c[0][1] != None } #cmd_qstr2str = { c[2][0]:c[0][0] for c in cmd_table if c[0][1] != None } cmd_qstrlist = [ c[2][0] for c in cmd_table if c[0][1] != None and c[2][0] != None ] ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], ['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] class QueryDialog(QDialog): dlg = None def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('backend/plugins/cscope/ui/cs_query.ui', self) self.qd_sym_inp.setAutoCompletion(False) self.qd_sym_inp.setInsertPolicy(QComboBox.InsertAtTop) self.qd_cmd_inp.addItems(cmd_qstrlist) def run_dialog(self, cmd_str, req): s = cmd_str2qstr[cmd_str] inx = self.qd_cmd_inp.findText(s) self.qd_cmd_inp.setCurrentIndex(inx) if (req == None): req = '' self.qd_sym_inp.setFocus() self.qd_sym_inp.setEditText(req) self.qd_sym_inp.lineEdit().selectAll() self.qd_substr_chkbox.setChecked(False) self.qd_icase_chkbox.setChecked(False) self.show() if (self.exec_() == QDialog.Accepted): req = str(self.qd_sym_inp.currentText()) s = str(self.qd_cmd_inp.currentText()) cmd_str = cmd_qstr2str[s] #self.qd_sym_inp.addItem(req) if (req != '' and self.qd_substr_chkbox.isChecked()): req = '.*' + req + '.*' opt = None if (self.qd_icase_chkbox.isChecked()): opt = '-C' res = (cmd_str, req, opt) return res return None @staticmethod def show_dlg(cmd_str, req): if (QueryDialog.dlg == None): QueryDialog.dlg = QueryDialog() return QueryDialog.dlg.run_dialog(cmd_str, req) def show_msg_dialog(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) def dir_scan_csope_files(rootdir): file_list = [] if (not os.path.isdir(rootdir)): print "Not a directory:", rootdir return file_list for root, subFolders, files in os.walk(rootdir): for f in files: f = os.path.join(root, f) if (re.search('\.(h|c|H|C|hh|cc|hpp|cpp|hxx|cxx||l|y|s|S|pl|pm|java)$', f) != None): file_list.append(f) return file_list class QueryUiCscope(QueryUiBase): def __init__(self, qry): self.menu_cmd_list = menu_cmd_list QueryUiBase.__init__(self) self.query = qry self.ctree_args = ctree_query_args def query_cb(self, cmd_str): if (not self.query.cs_is_open()): return if (not self.query.cs_is_ready()): show_msg_dialog('\nProject has no source files') return if cmd_str == 'CLGRAPHD': f = PluginHelper.editor_current_file() if f: d = os.path.dirname(f) self.query_class_graph_dir(d) return if cmd_str == 'FFGRAPH': f = PluginHelper.editor_current_file() if f: self.query_file_func_graph(f) return req = PluginHelper.editor_current_word() if (req != None): req = str(req).strip() opt = None if (cmd_str != 'QDEF'): val = QueryDialog.show_dlg(cmd_str, req) if (val == None): return (cmd_str, req, opt) = val if (req == None or req == ''): return if cmd_str == 'QDEF': self.query_qdef(req, opt) elif cmd_str == 'CTREE': self.query_ctree(req, opt) elif cmd_str == 'CLGRAPH': self.query_class_graph(req, opt) else: self.do_query(cmd_str, req, opt) def prepare_menu(self): QueryUiBase.prepare_menu(self) menu = PluginHelper.backend_menu menu.setTitle('&Cscope') @staticmethod def prj_show_settings_ui(proj_args): dlg = ProjectSettingsCscopeDialog() return dlg.run_dialog(proj_args) class ProjectSettingsCscopeDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('backend/plugins/cscope/ui/cs_project_settings.ui', self) self.pd_path_tbtn.setIcon(QFileIconProvider().icon(QFileIconProvider.Folder)) self.pd_src_list.setSelectionMode(QAbstractItemView.ExtendedSelection) QObject.connect(self.pd_path_tbtn, SIGNAL("clicked()"), self.path_open_cb) QObject.connect(self.pd_add_btn, SIGNAL("clicked()"), self.src_add_cb) QObject.connect(self.pd_rem_btn, SIGNAL("clicked()"), self.src_rem_cb) QObject.connect(self, SIGNAL("accepted()"), self.ok_btn_cb) def path_open_cb(self): fdlg = QFileDialog(None, "Choose directory") fdlg.setFileMode(QFileDialog.Directory); fdlg.setDirectory(self.pd_path_inp.text()) if (fdlg.exec_()): path_dir = fdlg.selectedFiles()[0]; self.pd_path_inp.setText(str(path_dir)) def src_add_cb(self): fdlg = QFileDialog(None, "Choose directory") fdlg.setFileMode(QFileDialog.Directory); fdlg.setDirectory(self.pd_path_inp.text()) if (fdlg.exec_()): d = fdlg.selectedFiles()[0]; d = str(d) d = d.strip() if (d == None): return d = os.path.normpath(d) if (d == '' or not os.path.isabs(d)): return self.src_add_files(d) def src_rem_cb(self): li = self.pd_src_list for item in li.selectedItems(): row = li.row(item) li.takeItem(row) def src_add_files(self, src_dir): file_list = dir_scan_csope_files(src_dir) self.pd_src_list.addItems(file_list) def ok_btn_cb(self): proj_dir = os.path.join(str(self.pd_path_inp.text()), str(self.pd_name_inp.text())) proj_dir = os.path.normpath(proj_dir) if (self.is_new_proj): if (proj_dir == '' or not os.path.isabs(proj_dir)): return if (os.path.exists(proj_dir)): show_msg_dialog("\nProject already exists") return os.mkdir(proj_dir) # File list cs_list = [] for inx in range(self.pd_src_list.count()): val = str(self.pd_src_list.item(inx).text()) cs_list.append(val) cs_list = list(set(cs_list)) # Cscope opt cs_opt = [] if self.pd_invert_chkbox.isChecked(): cs_opt.append('-q') if self.pd_kernel_chkbox.isChecked(): cs_opt.append('-k') self.res = [proj_dir, cs_opt, cs_list] def set_proj_args(self, proj_args): (proj_dir, cs_opt, cs_list) = proj_args (proj_base, proj_name) = os.path.split(proj_dir) self.pd_path_inp.setText(proj_base) self.pd_name_inp.setText(proj_name) # File list fl = cs_list self.pd_src_list.addItems(fl) # Cscope opt for opt in cs_opt: if (opt == '-q'): self.pd_invert_chkbox.setChecked(True) if (opt == '-k'): self.pd_kernel_chkbox.setChecked(True) def run_dialog(self, proj_args): self.pd_src_list.clear() if (proj_args == None): self.is_new_proj = True self.pd_invert_chkbox.setChecked(True) else: self.is_new_proj = False self.set_proj_args(proj_args) self.res = None self.pd_path_frame.setEnabled(self.is_new_proj) while True: ret = self.exec_() if (ret == QDialog.Accepted or ret == QDialog.Rejected): break return self.res seascope-0.8/src/backend/plugins/cscope/CscopeProject.py000644 000000 000000 00000012710 12230074152 023366 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, string, re from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase import CscopeProjectUi from CscopeProjectUi import QueryUiCscope from .. import PluginHelper class ConfigCscope(ConfigBase): def __init__(self): ConfigBase.__init__(self, 'cscope') self.cs_dir = '' self.cs_opt = [] self.cs_list = [] def get_proj_name(self): return os.path.split(self.cs_dir)[1] def get_proj_src_files(self): fl = self.cs_list return fl def read_cs_files_common(self, filename): fl = [] config_file = os.path.join(self.cs_dir, filename) if (os.path.exists(config_file)): cf = open(config_file, 'r') for f in cf: f = f[:-1] fl.append(f) cf.close() return fl def read_cs_files(self): self.cs_list = self.read_cs_files_common('cscope.files') def write_cs_files_common(self, filename, fl): if (len(fl) <= 0): return config_file = os.path.join(self.cs_dir, filename) cf = open(config_file, 'w') for f in fl: cf.write(f + '\n') cf.close() def write_cs_files(self): self.write_cs_files_common("cscope.files", self.cs_list) def get_config_file(self): config_file = 'seascope.opt' return os.path.join(self.cs_dir, config_file) def read_seascope_opt(self): config_file = self.get_config_file() if (not os.path.exists(config_file)): return cf = open(config_file, 'r') for line in cf: line = line.split('=', 1) key = line[0].strip() if (key == 'cs_opt'): self.cs_opt = line[1].split() cf.close() def write_seascope_opt(self): config_file = self.get_config_file() cf = open(config_file, 'w') cf.write('cs_opt' + '=' + string.join(self.cs_opt)+ '\n') cf.close() def read_config(self): self.read_seascope_opt() self.read_cs_files() def write_config(self): self.write_seascope_opt() self.write_cs_files() def proj_start(self): cs_args = string.join(self.cs_opt) def proj_open(self, proj_path): self.cs_dir = proj_path self.read_config() self.proj_start() def proj_update(self, proj_args): self.proj_new(proj_args) def proj_new(self, proj_args): self.proj_args = proj_args (self.cs_dir, self.cs_opt, self.cs_list) = proj_args self.write_config() self.proj_start() def proj_close(self): pass def get_proj_conf(self): self.read_cs_files() return (self.cs_dir, self.cs_opt, self.cs_list) def is_ready(self): return len(self.cs_list) > 0 class ProjectCscope(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectCscope() prj.conf = conf prj.qry = QueryCscope(prj.conf) prj.qryui = QueryUiCscope(prj.qry) PluginHelper.file_view_update(prj.conf.get_proj_src_files()) return (prj) @staticmethod def prj_new(): proj_args = QueryUiCscope.prj_show_settings_ui(None) if (proj_args == None): return None conf = ConfigCscope() conf.proj_new(proj_args) prj = ProjectCscope._prj_new_or_open(conf) return (prj) @staticmethod def prj_open(proj_path): conf = ConfigCscope() conf.proj_open(proj_path) prj = ProjectCscope._prj_new_or_open(conf) return (prj) def prj_close(self): if (self.conf != None): self.conf.proj_close() self.conf = None def prj_dir(self): return self.conf.cs_dir def prj_name(self): return self.conf.get_proj_name() def prj_src_files(self): return self.conf.get_proj_src_files() def prj_is_open(self): return self.conf != None def prj_is_ready(self): return self.conf.is_ready() def prj_conf(self): return self.conf.get_proj_conf() def prj_update_conf(self, proj_args): self.conf.proj_update(proj_args) def prj_settings_trigger(self): proj_args = self.prj_conf() proj_args = QueryUiCscope.prj_show_settings_ui(proj_args) if (proj_args == None): return False self.prj_update_conf(proj_args) PluginHelper.file_view_update(self.conf.get_proj_src_files()) return True from ..PluginBase import PluginProcess class CsProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir) self.name = 'cscope process' if rq == None: rq = ['', ''] self.cmd_str = rq[0] self.req = rq[1] def parse_result(self, text, sig): text = re.split('\r?\n', text) if self.cmd_str == 'FIL': res = [ ['', line[0], '', ''] for line in text if line != '' ] return res res = [] for line in text: if line == '': continue line = line.split(' ', 3) line = [line[1], line[0], line[2], line[3]] res.append(line) return res class QueryCscope(QueryBase): def __init__(self, conf): QueryBase.__init__(self) self.conf = conf def query(self, rquery): if (not self.conf or not self.conf.is_ready()): print "pm_query not is_ready" return None cmd_str = rquery['cmd'] req = rquery['req'] opt = rquery['opt'] cmd_id = CscopeProjectUi.cmd_str2id[cmd_str] if opt == None or opt == '': opt = [] else: opt = opt.split() pargs = [ 'cscope' ] + self.conf.cs_opt + opt + [ '-L', '-d', '-' + str(cmd_id), req ] qsig = CsProcess(self.conf.cs_dir, [cmd_str, req]).run_query_process(pargs, req, rquery) return qsig def rebuild(self): if (not self.conf.is_ready()): print "pm_query not is_ready" return None pargs = [ 'cscope' ] + self.conf.cs_opt + [ '-L' ] qsig = CsProcess(self.conf.cs_dir, None).run_rebuild_process(pargs) return qsig def cs_is_open(self): return self.conf != None def cs_is_ready(self): return self.conf.is_ready() seascope-0.8/src/backend/plugins/PluginBase.py000644 000000 000000 00000020700 12230074152 021376 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtCore import * from PyQt4.QtGui import * import os, re def msg_box(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) class ProjectBase(QObject): prj = None qry = None def __init__(self): QObject.__init__(self) def prj_close(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_get_dir(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_get_name(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_get_src_files(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_is_open(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_is_ready(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_get_conf(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_update_conf(self, proj_args): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_show_settings(self, proj_args): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_settings(self, proj_args): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) class ConfigBase(QObject): def __init__(self, ptype): self.prj_type = ptype @staticmethod def prepare_menu(menubar): pass class QueryBase(QObject): @staticmethod def prepare_menu(menubar): pass def query(self, rquery): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def rebuild(): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) import PluginHelper class QueryUiBase(QObject): def __init__(self): QObject.__init__(self) self.prepare_menu() def menu_cb(self, act): if act.cmd_str != None: self.query_cb(act.cmd_str) def prepare_menu(self): menu = PluginHelper.backend_menu menu.triggered.connect(self.menu_cb) for c in self.menu_cmd_list: if c[0] == '---': menu.addSeparator() continue if c[2] == None: if c[0] == 'UPD': func = self.rebuild_cb act = menu.addAction(c[1], func) act.cmd_str = None else: act = menu.addAction(c[1]) act.setShortcut(c[2]) act.cmd_str = c[0] def query_ctree(self, req, opt): PluginHelper.call_view_page_new(req, self.query.query, self.ctree_args, opt) def query_class_graph(self, req, opt): (prj_dir, dummy1, dummy2) = self.query.conf.get_proj_conf() prj_type = self.query.conf.prj_type PluginHelper.class_graph_view_page_new(req, prj_dir, prj_type, self.query.query, opt) def query_class_graph_dir(self, dname): opt = [] PluginHelper.class_graph_view_page_new('', dname, None, self.query.query, opt) def query_file_func_graph(self, fname): opt = [] PluginHelper.file_func_graph_view_page_new('', fname, '', self.query.query, opt) def _prepare_rquery(self, cmd_str, req, opt): rquery = {} rquery['cmd'] = cmd_str rquery['req'] = req rquery['opt'] = opt # add current file info rquery['hint_file'] = PluginHelper.editor_current_file() return rquery def query_qdef(self, req, opt): rquery = {} rquery = self._prepare_rquery('DEF', req, opt) sig_res = self.query.query(rquery) PluginHelper.quick_def_page_new(sig_res) def do_query(self, cmd_str, req, opt): ## create page name = cmd_str + ' ' + req rquery = self._prepare_rquery(cmd_str, req, opt) sig_res = self.query.query(rquery) PluginHelper.result_page_new(name, sig_res) def do_rebuild(self): sig_rebuild = self.query.rebuild() if not sig_rebuild: return dlg = QProgressDialog() dlg.setWindowTitle('Seascope rebuild') dlg.setLabelText('Rebuilding database...') dlg.setCancelButton(None) dlg.setMinimum(0) dlg.setMaximum(0) sig_rebuild.connect(dlg.accept) while dlg.exec_() != QDialog.Accepted: pass def rebuild_cb(self): self.do_rebuild() from PyQt4.QtGui import QMessageBox class QuerySignal(QObject): sig_result = pyqtSignal(str, list) sig_result_dbg = pyqtSignal(str, str, str) sig_rebuild = pyqtSignal() def __init__(self): QObject.__init__(self) def _relevancy_sort(self, hfile, res): pt = [] pd = {} p = hfile (pre, ext) = os.path.splitext(hfile) c = None while p != c: e = [p, [], []] pt += [e] pd[p] = e c = p p = os.path.dirname(p) for line in res: f = line[1] d = os.path.dirname(f) p = f while p not in pd: p = os.path.dirname(p) e = pd[p] if p in [f, d]: e[1].append(line) else: e[2].append(line) for e in pt: e[1] = sorted(e[1], key=lambda li: li[1]) e[2] = sorted(e[2], key=lambda li: li[1]) pre = pre + '.*' e0 = [] e1 = [] for e in pt[1][1]: if re.match(pre, e[1]): e0 += [e] else: e1 += [e] pt[0][1] += e0 pt[1][1] = e1 res1 = [] res2 = [] for e in pt: res1 += e[1] res2 += e[2] res = res1 + res2 return res def relevancy_sort(self, res): if os.getenv('RELEVANCY_SORT', 1) == 0: return res hint_file = None try: hint_file = self.rquery['hint_file'] except: pass if not hint_file: return res if not os.path.isabs(hint_file): print 'BUG: relevancy_sort: not abs path:', hint_file return res if len(res) > 10000: return res return self._relevancy_sort(hint_file, res) def emit_result(self, res): res = self.relevancy_sort(res) self.sig_result.emit(self.sym, res) class PluginProcess(QObject): proc_list = [] def __init__(self, wdir): QObject.__init__(self) PluginProcess.proc_list.append(self) self.is_rebuild = False self.sig = QuerySignal() self.proc = QProcess() self.proc.finished.connect(self._finished_cb) self.proc.error.connect(self._error_cb) self.proc.setWorkingDirectory(wdir) self.wdir = wdir def _cleanup(self): PluginProcess.proc_list.remove(self) if self.err_str != '': s = '' + self.p_cmd + '

' + '

'.join(self.err_str.splitlines()) QMessageBox.warning(None, "Seascope", s, QMessageBox.Ok) if self.res != '': s = '' + self.p_cmd + '

Summary

' + self.res QMessageBox.information(None, "Seascope", s, QMessageBox.Ok) def _error_cb(self, err): err_dict = { QProcess.FailedToStart: 'FailedToStart', QProcess.Crashed: 'Crashed', QProcess.Timedout: 'The last waitFor...() function timed out', QProcess.WriteError: 'An error occurred when attempting to write to the process', QProcess.ReadError: 'An error occurred when attempting to read from the process', QProcess.UnknownError: 'An unknown error occurred', } self.err_str = '' + self.p_cmd + '

' + err_dict[err] self._cleanup() def _finished_cb(self, ret): res = str(self.proc.readAllStandardOutput()) self.err_str = str(self.proc.readAllStandardError()) #print 'output', res #print 'cmd:', self.p_cmd if self.is_rebuild: self.res = res self.sig.sig_rebuild.emit() else: self.res = '' self.sig.sig_result_dbg.emit(self.p_cmd, res, self.err_str) try: res = self.parse_result(res, self.sig) except Exception as e: print e res = [['', '', '', 'error while parsing output of: ' + self.p_cmd]] if res != None: self.sig.emit_result(res) self._cleanup() def run_query_process(self, pargs, sym, rquery=None): self.sig.sym = sym self.sig.rquery = rquery self.p_cmd = ' '.join(pargs) if os.getenv('SEASCOPE_DEBUG'): print self.p_cmd self.proc.start(pargs[0], pargs[1:]) if self.proc.waitForStarted() == False: return None self.proc.closeWriteChannel() return [self.sig.sig_result, self.sig.sig_result_dbg] def run_rebuild_process(self, pargs): self.is_rebuild = True self.p_cmd = ' '.join(pargs) self.proc.start(pargs[0], pargs[1:]) if self.proc.waitForStarted() == False: return None #print 'cmd:', pargs import CtagsCache self.sig.sig_rebuild.connect(CtagsCache.flush) return self.sig.sig_rebuild def parse_result(self, text, sig): print 'parse_result not implemented' if text == '': text = ['Empty output'] else: text = text.strip().split('\n') return text if __name__ == '__main__': import sys def slot_result(sym, res): print 'slot_result: ', [str(sym), res] sys.exit(0) def slot_result_dbg(cmd, res, err_str): print 'slot_result_dbg:', [str(cmd), str(res).strip().split('\n'), str(err_str)] def slot_rebuild(): print 'slot_rebuild' app = QCoreApplication(sys.argv) qsig = PluginProcess('.').run_query_process(['ls'], 'ls') #qsig = PluginProcess('/home/anil/prj/ss/lin').run_query_process(['cscope', '-q', '-k', '-L', '-d', '-0', 'vdso'], 'ls') if qsig == None: sys.exit(-1) qsig[0].connect(slot_result) qsig[1].connect(slot_result_dbg) app.exec_() seascope-0.8/src/backend/plugins/idutils/000755 000000 000000 00000000000 12230074152 020451 5ustar00rootroot000000 000000 seascope-0.8/src/backend/plugins/idutils/ui/000755 000000 000000 00000000000 12230074152 021066 5ustar00rootroot000000 000000 seascope-0.8/src/backend/plugins/idutils/ui/id_query.ui000644 000000 000000 00000007021 12230074152 023246 0ustar00rootroot000000 000000 QueryDialog Qt::ApplicationModal 0 0 357 171 Idutils Query 40 16777215 Type false Symbol true 10 50 16777215 Substring Case Insensitive Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qd_sym_inp qd_substr_chkbox qd_icase_chkbox buttonBox qd_cmd_inp buttonBox accepted() QueryDialog accept() 248 254 157 274 buttonBox rejected() QueryDialog reject() 316 260 286 274 seascope-0.8/src/backend/plugins/idutils/__init__.py000644 000000 000000 00000001737 12230074152 022572 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os def name(): return 'idutils' def is_your_prj(path): f = os.path.join(path, 'ID') return os.path.exists(f) def project_class(): from IdutilsProject import ProjectIdutils return ProjectIdutils def description(): d = 'Preferred backend of seascope.\n' d += 'Some advanced features of seascope are available only with this backend\n' d += '\n' d += 'It\'s really "idutils + ctags" backend.\n' d += ' - idutils provides the indexing facility\n' d += ' - ctags provides the language intelligence\n' d += 'This backend combines both of these intelligently to provide superior source code browsing facility\n' d += '\n' d += 'A wide variety of languages are supported (ctags --list-languages)\n' d += 'For example C, C++, Java, Python etc\n' d += '\n' d += 'If your source files are not being indexed by idutils then configure it using /usr/share/id-lang.map\n' return d priority = 800 seascope-0.8/src/backend/plugins/idutils/IdutilsProject.py000644 000000 000000 00000013506 12230074152 023774 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys, os, string, re from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase from IdutilsProjectUi import QueryUiIdutils class ConfigIdutils(ConfigBase): def __init__(self): ConfigBase.__init__(self, 'idutils') self.id_dir = '' self.id_opt = '' self.id_list = [] def get_proj_name(self): return os.path.split(self.id_dir)[1] def get_proj_src_files(self): return [] def proj_start(self): id_args = string.join(self.id_opt) def proj_open(self, proj_path): self.id_dir = proj_path self.proj_start() def proj_update(self, proj_args): self.proj_new(proj_args) def proj_new(self, proj_args): self.proj_args = proj_args (self.id_dir, self.id_opt, self.id_list) = proj_args self.proj_start() def proj_close(self): pass def get_proj_conf(self): return (self.id_dir, self.id_opt, self.id_list) def is_ready(self): return True class ProjectIdutils(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectIdutils() prj.conf = conf prj.qry = QueryIdutils(prj.conf) prj.qryui = QueryUiIdutils(prj.qry) return (prj) @staticmethod def prj_new(): from PyQt4.QtGui import QFileDialog fdlg = QFileDialog(None, "Choose source code directory") fdlg.setFileMode(QFileDialog.Directory); #fdlg.setDirectory(self.pd_path_inp.text()) if fdlg.exec_(): d = fdlg.selectedFiles()[0]; d = str(d) if not d: return None d = os.path.normpath(d) if d == '' or not os.path.isabs(d): return None prj = ProjectIdutils.prj_open(d) prj.qryui.do_rebuild() return prj return None @staticmethod def prj_open(proj_path): conf = ConfigIdutils() conf.proj_open(proj_path) prj = ProjectIdutils._prj_new_or_open(conf) return (prj) def prj_close(self): if (self.conf != None): self.conf.proj_close() self.conf = None def prj_dir(self): return self.conf.id_dir def prj_name(self): return self.conf.get_proj_name() def prj_src_files(self): return self.conf.get_proj_src_files() def prj_is_open(self): return self.conf != None def prj_is_ready(self): return self.conf.is_ready() def prj_conf(self): return self.conf.get_proj_conf() def prj_update_conf(self, proj_args): self.conf.proj_update(proj_args) def prj_settings_trigger(self): proj_args = self.prj_conf() proj_args = QueryUiIdutils.prj_show_settings_ui(proj_args) #if (proj_args == None): #return False #self.prj_update_conf(proj_args) #return True return False from ..PluginBase import PluginProcess from .. import PluginHelper from ..CtagsCache import CtagsThread class IdCtagsThread(CtagsThread): def __init__(self, sig): CtagsThread.__init__(self, sig) def ctags_bsearch(self, ct, n): m = CtagsThread.ctags_bsearch(self, ct, n) return m def parse_result(self, res, sig): res = self._filter_res(res, sig) return res class IdProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir) self.name = 'idutils process' if rq == None: rq = ['', ''] self.cmd_str = rq[0] self.req = rq[1] def parse_result(self, text, sig): #from datetime import datetime #t1 = datetime.now() text = re.split('\r?\n', text) #t2 = datetime.now() #print 'parse-split', t2 - t1 if self.cmd_str == 'FIL': res = [ ['', os.path.join(self.wdir, line), '', '' ] for line in text if line != '' ] return res res = [] if self.cmd_str == 'GREP': for line in text: if line == '': continue line = [''] + line.split(':', 2) res.append(line) else: for line in text: if line == '': continue line = line.split(':', 2) line = ['', os.path.join(self.wdir, line[0]), line[1], line[2]] res.append(line) #t3 = datetime.now() #print 'parse-loop', t3 - t2 IdCtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return None class QueryIdutils(QueryBase): def __init__(self, conf): QueryBase.__init__(self) self.conf = conf self.id_file_list_update() def query(self, rquery): if (not self.conf): #or not self.conf.is_ready()): print "pm_query not is_ready" return None cmd_str = rquery['cmd'] req = rquery['req'] opt = rquery['opt'] if opt == None: opt = [] pargs = ['lid', '-R', 'grep'] if cmd_str == 'FIL': pargs = ['fnid', '-S', 'newline'] elif cmd_str == 'GREP': pargs = ['grep', '-E', '-R', '-n', '-I'] #elif cmd_str == 'TXT': #pargs += ['-l'] elif 'substring' in opt: #req = '.*' + req + '.*' #pargs += ' -s' pass elif cmd_str in ['-->', '<--']: pargs += ['-l'] if cmd_str != 'FIL': if 'ignorecase' in opt: pargs += ['-i'] pargs += [ '--', req ] if cmd_str == 'GREP': pargs += [self.conf.id_dir] qsig = IdProcess(self.conf.id_dir, [cmd_str, req]).run_query_process(pargs, req, rquery) return qsig def rebuild(self): if (not self.conf.is_ready()): print "pm_query not is_ready" return None pargs = [ 'mkid', '-s' ] qsig = IdProcess(self.conf.id_dir, None).run_rebuild_process(pargs) qsig.connect(self.id_file_list_update) return qsig def id_file_list_update(self): wdir = self.conf.id_dir if not os.path.exists(os.path.join(wdir, 'ID')): return fl = [] try: import subprocess pargs = [ 'fnid', '-S', 'newline', '-f', 'ID' ] proc = subprocess.Popen(pargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=wdir) (out_data, err_data) = proc.communicate() fl = [] for f in re.split('\r?\n', out_data.strip()): if f == '': continue fl.append(os.path.join(wdir, f)) PluginHelper.file_view_update(fl) except: import sys e = sys.exc_info()[1] print ' '.join(pargs) print e def id_is_open(self): return self.conf != None def id_is_ready(self): return self.conf.is_ready() seascope-0.8/src/backend/plugins/idutils/IdutilsProjectUi.py000644 000000 000000 00000012425 12230074152 024271 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase from ..PluginBase import QueryUiBase from .. import PluginBase, PluginHelper cmd_table = [ [ ['REF', ''], ['&References', 'Ctrl+0'], ['References to' ] ], [ ['DEF', ''], ['&Definitions', 'Ctrl+1'], ['Definition of' ] ], #[ ['<--', '2'], ['&Called Functions', 'Ctrl+2'], ['Functions called by' ] ], [ ['-->', '3'], ['C&alling Functions', 'Ctrl+3'], ['Functions calling' ] ], #[ ['TXT', '4'], ['Find &Text', 'Ctrl+4'], ['Find text' ] ], [ ['GREP',''], ['Find &Egrep', 'Ctrl+5'], ['Find egrep pattern' ] ], [ ['FIL', ''], ['Find &File', 'Ctrl+7'], ['Find files' ] ], [ ['INC', '8'], ['&Include/Import', 'Ctrl+8'], ['Find include/import' ] ], [ ['---', None], [None ] ], [ ['QDEF', ''], ['&Quick Definition', 'Ctrl+]'], [None ] ], [ ['CTREE','12'], ['Call Tr&ee', 'Ctrl+\\'], ['Call tree' ] ], [ ['---', None], [None ], ], [ ['CLGRAPH', '13'], ['Class &Graph', 'Ctrl+:'], ['Class graph' ] ], [ ['CLGRAPHD', '14'], ['Class Graph Dir', 'Ctrl+;'], ['Class graph dir' ] ], [ ['FFGRAPH', '14'], ['File Func Graph', 'Ctrl+^'], ['File Func graph dir' ] ], [ ['---', None], [None ], ], [ ['UPD', '25'], ['Re&build Database', None ], [None ] ], ] menu_cmd_list = [ [c[0][0]] + c[1] for c in cmd_table ] cmd_str2id = {} cmd_str2qstr = {} cmd_qstr2str = {} for c in cmd_table: if c[0][1] != None: cmd_str2id[c[0][0]] = c[0][1] cmd_str2qstr[c[0][0]] = c[2][0] cmd_qstr2str[c[2][0]] = c[0][0] # python 2.7 #cmd_str2id = { c[0][0]:c[0][1] for c in cmd_table if c[0][1] != None } #cmd_str2qstr = { c[0][0]:c[2][0] for c in cmd_table if c[0][1] != None } #cmd_qstr2str = { c[2][0]:c[0][0] for c in cmd_table if c[0][1] != None } cmd_qstrlist = [ c[2][0] for c in cmd_table if c[0][1] != None and c[2][0] != None ] ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], #['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] clgraph_query_args = [ ['CLGRAPH', 'D', 'Derived classes' ], ['CLGRAPH', 'B', 'Base classes' ], ] class QueryDialog(QDialog): dlg = None def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('backend/plugins/idutils/ui/id_query.ui', self) self.qd_sym_inp.setAutoCompletion(False) self.qd_sym_inp.setInsertPolicy(QComboBox.InsertAtTop) self.qd_cmd_inp.addItems(cmd_qstrlist) def run_dialog(self, cmd_str, req): s = cmd_str2qstr[cmd_str] inx = self.qd_cmd_inp.findText(s) self.qd_cmd_inp.setCurrentIndex(inx) if (req == None): req = '' self.qd_sym_inp.setFocus() self.qd_sym_inp.setEditText(req) self.qd_sym_inp.lineEdit().selectAll() self.qd_substr_chkbox.setChecked(False) self.qd_icase_chkbox.setChecked(False) self.show() if (self.exec_() == QDialog.Accepted): req = str(self.qd_sym_inp.currentText()) s = str(self.qd_cmd_inp.currentText()) cmd_str = cmd_qstr2str[s] #self.qd_sym_inp.addItem(req) opt = [] if cmd_str != 'TXT' and req != '' and self.qd_substr_chkbox.isChecked(): opt.append('substring') if cmd_str == 'FIL': req = '*' + req + '*' else: req = '.*' + req + '.*' if (self.qd_icase_chkbox.isChecked()): opt.append('ignorecase') res = (cmd_str, req, opt) return res return None @staticmethod def show_dlg(cmd_str, req): if (QueryDialog.dlg == None): QueryDialog.dlg = QueryDialog() return QueryDialog.dlg.run_dialog(cmd_str, req) def show_msg_dialog(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) class QueryUiIdutils(QueryUiBase): def __init__(self, qry): self.menu_cmd_list = menu_cmd_list QueryUiBase.__init__(self) self.query = qry self.ctree_args = ctree_query_args def query_cb(self, cmd_str): if (not self.query.id_is_open()): return if (not self.query.id_is_ready()): show_msg_dialog('\nProject has no source files') return if cmd_str == 'CLGRAPHD': f = PluginHelper.editor_current_file() if f: d = os.path.dirname(f) self.query_class_graph_dir(d) return if cmd_str == 'FFGRAPH': f = PluginHelper.editor_current_file() if f: self.query_file_func_graph(f) return req = PluginHelper.editor_current_word() if (req != None): req = str(req).strip() opt = None if cmd_str not in [ 'QDEF' ]: val = QueryDialog.show_dlg(cmd_str, req) if (val == None): return (cmd_str, req, opt) = val if (req == None or req == ''): return if cmd_str == 'QDEF': self.query_qdef(req, opt) elif cmd_str == 'CTREE': self.query_ctree(req, opt) elif cmd_str == 'CLGRAPH': self.query_class_graph(req, opt) else: self.do_query(cmd_str, req, opt) def prepare_menu(self): QueryUiBase.prepare_menu(self) menu = PluginHelper.backend_menu menu.setTitle('&Idutils') @staticmethod def prj_show_settings_ui(proj_args): dlg = ProjectSettingsIdutilsDialog() return dlg.run_dialog(proj_args) class ProjectSettingsIdutilsDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('ui/project_settings.ui', self) def run_dialog(self, proj_args): self.pi_path_lbl.setText(proj_args[0]) self.pi_type_lbl.setText('idutils') self.exec_() return proj_args seascope-0.8/src/backend/plugins/__init__.py000644 000000 000000 00000000112 12230074152 021077 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD seascope-0.8/src/backend/plugins/gtags/000755 000000 000000 00000000000 12230074152 020101 5ustar00rootroot000000 000000 seascope-0.8/src/backend/plugins/gtags/ui/000755 000000 000000 00000000000 12230074152 020516 5ustar00rootroot000000 000000 seascope-0.8/src/backend/plugins/gtags/ui/gt_query.ui000644 000000 000000 00000007017 12230074152 022721 0ustar00rootroot000000 000000 QueryDialog Qt::ApplicationModal 0 0 357 171 gtags query 40 16777215 Type false Symbol true 10 50 16777215 Substring Case Insensitive Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qd_sym_inp qd_substr_chkbox qd_icase_chkbox buttonBox qd_cmd_inp buttonBox accepted() QueryDialog accept() 248 254 157 274 buttonBox rejected() QueryDialog reject() 316 260 286 274 seascope-0.8/src/backend/plugins/gtags/__init__.py000644 000000 000000 00000000721 12230074152 022212 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os def name(): return 'gtags' def is_your_prj(path): f = os.path.join(path, 'GTAGS') return os.path.exists(f) def project_class(): from GtagsProject import ProjectGtags return ProjectGtags def description(): d = 'GNU global/gtags supports C, C++, Yacc, Java, PHP and Assembly source files.\n' d += '\nSeascope uses ctags to enhance the results.' return d #priority = 200 seascope-0.8/src/backend/plugins/gtags/GtagsProjectUi.py000644 000000 000000 00000012062 12230074152 023346 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase from ..PluginBase import QueryUiBase from .. import PluginBase, PluginHelper cmd_table = [ [ ['REF', '-r'], ['&References', 'Ctrl+0'], ['References to' ] ], [ ['DEF', ''], ['&Definitions', 'Ctrl+1'], ['Definition of' ] ], #[ ['<--', '2'], ['&Called Functions', 'Ctrl+2'], ['Functions called by' ] ], [ ['-->', '-r'], ['C&alling Functions', 'Ctrl+3'], ['Functions calling' ] ], #[ ['TXT', '4'], ['Find &Text', 'Ctrl+4'], ['Find text' ] ], [ ['GREP','-g'], ['Find &Egrep', 'Ctrl+5'], ['Find egrep pattern' ] ], [ ['FIL', '-P'], ['Find &File', 'Ctrl+7'], ['Find files' ] ], [ ['INC', '-g'], ['&Include/Import', 'Ctrl+8'], ['Find include/import' ] ], [ ['---', None], [None ] ], [ ['QDEF', ''], ['&Quick Definition', 'Ctrl+]'], [None ] ], [ ['CTREE','12'], ['Call Tr&ee', 'Ctrl+\\'], ['Call tree' ] ], [ ['---', None], [None ], ], [ ['CLGRAPH', '13'], ['Class &Graph', 'Ctrl+:'], ['Class graph' ] ], [ ['CLGRAPHD', '14'], ['Class Graph Dir', 'Ctrl+;'], ['Class graph dir' ] ], [ ['FFGRAPH', '14'], ['File Func Graph', 'Ctrl+^'], ['File Func graph dir' ] ], [ ['---', None], [None ], ], [ ['UPD', '25'], ['Re&build Database', None ], [None ] ], ] menu_cmd_list = [ [c[0][0]] + c[1] for c in cmd_table ] cmd_str2id = {} cmd_str2qstr = {} cmd_qstr2str = {} for c in cmd_table: if c[0][1] != None: cmd_str2id[c[0][0]] = c[0][1] cmd_str2qstr[c[0][0]] = c[2][0] cmd_qstr2str[c[2][0]] = c[0][0] # python 2.7 #cmd_str2id = { c[0][0]:c[0][1] for c in cmd_table if c[0][1] != None } #cmd_str2qstr = { c[0][0]:c[2][0] for c in cmd_table if c[0][1] != None } #cmd_qstr2str = { c[2][0]:c[0][0] for c in cmd_table if c[0][1] != None } cmd_qstrlist = [ c[2][0] for c in cmd_table if c[0][1] != None and c[2][0] != None ] ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], #['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] class QueryDialog(QDialog): dlg = None def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('backend/plugins/gtags/ui/gt_query.ui', self) self.qd_sym_inp.setAutoCompletion(False) self.qd_sym_inp.setInsertPolicy(QComboBox.InsertAtTop) self.qd_cmd_inp.addItems(cmd_qstrlist) def run_dialog(self, cmd_str, req): s = cmd_str2qstr[cmd_str] inx = self.qd_cmd_inp.findText(s) self.qd_cmd_inp.setCurrentIndex(inx) if (req == None): req = '' self.qd_sym_inp.setFocus() self.qd_sym_inp.setEditText(req) self.qd_sym_inp.lineEdit().selectAll() self.qd_substr_chkbox.setChecked(False) self.qd_icase_chkbox.setChecked(False) self.show() if (self.exec_() == QDialog.Accepted): req = str(self.qd_sym_inp.currentText()) s = str(self.qd_cmd_inp.currentText()) cmd_str = cmd_qstr2str[s] #self.qd_sym_inp.addItem(req) if (req != '' and self.qd_substr_chkbox.isChecked()): req = '.*' + req + '.*' opt = None if (self.qd_icase_chkbox.isChecked()): opt = '-i' res = (cmd_str, req, opt) return res return None @staticmethod def show_dlg(cmd_str, req): if (QueryDialog.dlg == None): QueryDialog.dlg = QueryDialog() return QueryDialog.dlg.run_dialog(cmd_str, req) def show_msg_dialog(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) class QueryUiGtags(QueryUiBase): def __init__(self, qry): self.menu_cmd_list = menu_cmd_list QueryUiBase.__init__(self) self.query = qry self.ctree_args = ctree_query_args def query_cb(self, cmd_str): if (not self.query.gt_is_open()): return if (not self.query.gt_is_ready()): show_msg_dialog('\nProject has no source files') return if cmd_str == 'CLGRAPHD': f = PluginHelper.editor_current_file() if f: d = os.path.dirname(f) self.query_class_graph_dir(d) return if cmd_str == 'FFGRAPH': f = PluginHelper.editor_current_file() if f: self.query_file_func_graph(f) return req = PluginHelper.editor_current_word() if (req != None): req = str(req).strip() opt = None if (cmd_str != 'QDEF'): val = QueryDialog.show_dlg(cmd_str, req) if (val == None): return (cmd_str, req, opt) = val if (req == None or req == ''): return if cmd_str == 'QDEF': self.query_qdef(req, opt) elif cmd_str == 'CTREE': self.query_ctree(req, opt) elif cmd_str == 'CLGRAPH': self.query_class_graph(req, opt) else: self.do_query(cmd_str, req, opt) def prepare_menu(self): QueryUiBase.prepare_menu(self) menu = PluginHelper.backend_menu menu.setTitle('G&tags') @staticmethod def prj_show_settings_ui(proj_args): dlg = ProjectSettingsGtagsDialog() return dlg.run_dialog(proj_args) class ProjectSettingsGtagsDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('ui/project_settings.ui', self) def run_dialog(self, proj_args): self.pi_path_lbl.setText(proj_args[0]) self.pi_type_lbl.setText('GNU global/gtags') self.exec_() return proj_args seascope-0.8/src/backend/plugins/gtags/GtagsProject.py000644 000000 000000 00000012357 12230074152 023057 0ustar00rootroot000000 000000 #!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, string, re from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase import GtagsProjectUi from GtagsProjectUi import QueryUiGtags from .. import PluginHelper class ConfigGtags(ConfigBase): def __init__(self): ConfigBase.__init__(self, 'gtags') self.gt_dir = '' self.gt_opt = '' self.gt_list = [] def get_proj_name(self): return os.path.split(self.gt_dir)[1] def get_proj_src_files(self): fl = self.gt_list return fl def proj_start(self): gt_args = string.join(self.gt_opt) def proj_open(self, proj_path): self.gt_dir = proj_path self.proj_start() def proj_update(self, proj_args): self.proj_new(proj_args) def proj_new(self, proj_args): self.proj_args = proj_args (self.gt_dir, self.gt_opt, self.gt_list) = proj_args self.proj_start() def proj_close(self): pass def get_proj_conf(self): return (self.gt_dir, self.gt_opt, self.gt_list) def is_ready(self): return True class ProjectGtags(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectGtags() prj.conf = conf prj.qry = QueryGtags(prj.conf) prj.qryui = QueryUiGtags(prj.qry) return (prj) @staticmethod def prj_new(): from PyQt4.QtGui import QFileDialog fdlg = QFileDialog(None, "Choose source code directory") fdlg.setFileMode(QFileDialog.Directory); #fdlg.setDirectory(self.pd_path_inp.text()) if fdlg.exec_(): d = fdlg.selectedFiles()[0]; d = str(d) if not d: return None d = os.path.normpath(d) if d == '' or not os.path.isabs(d): return None prj = ProjectGtags.prj_open(d) prj.qryui.do_rebuild() return prj return None @staticmethod def prj_open(proj_path): conf = ConfigGtags() conf.proj_open(proj_path) prj = ProjectGtags._prj_new_or_open(conf) return (prj) def prj_close(self): if (self.conf != None): self.conf.proj_close() self.conf = None def prj_dir(self): return self.conf.gt_dir def prj_name(self): return self.conf.get_proj_name() def prj_src_files(self): return self.conf.get_proj_src_files() def prj_is_open(self): return self.conf != None def prj_is_ready(self): return self.conf.is_ready() def prj_conf(self): return self.conf.get_proj_conf() def prj_update_conf(self, proj_args): self.conf.proj_update(proj_args) def prj_settings_trigger(self): proj_args = self.prj_conf() proj_args = QueryUiGtags.prj_show_settings_ui(proj_args) #if (proj_args == None): #return False #self.prj_update_conf(proj_args) #return True return False from ..PluginBase import PluginProcess from .. import PluginHelper from ..CtagsCache import CtagsThread class GtCtagsThread(CtagsThread): def __init__(self, sig): CtagsThread.__init__(self, sig) def ctags_bsearch(self, ct, n): m = CtagsThread.ctags_bsearch(self, ct, n) return m def parse_result(self, res, sig): res = self._filter_res(res, sig) return res class GtProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir) self.name = 'gtags process' if rq == None: rq = ['', ''] self.cmd_str = rq[0] self.req = rq[1] def parse_result(self, text, sig): text = re.split('\r?\n', text) if self.cmd_str == 'FIL': res = [ ['', line.split(' ')[0], '', '' ] for line in text if line != '' ] return res res = [] for line in text: if line == '': continue line = line.split(' ', 3) line = ['', line[0], line[2], line[3]] res.append(line) GtCtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return None class QueryGtags(QueryBase): def __init__(self, conf): QueryBase.__init__(self) self.conf = conf self.gt_file_list_update() def query(self, rquery): if (not self.conf): #or not self.conf.is_ready()): print "pm_query not is_ready" return None cmd_str = rquery['cmd'] req = rquery['req'] opt = rquery['opt'] if opt == None or opt == '': opt = [] else: opt = opt.split() cmd_opt = GtagsProjectUi.cmd_str2id[cmd_str] pargs = [ 'global', '-a', '--result=cscope', '-x' ] + opt if cmd_opt != '': pargs += [ cmd_opt ] pargs += [ '--', req ] qsig = GtProcess(self.conf.gt_dir, [cmd_str, req]).run_query_process(pargs, req, rquery) return qsig def rebuild(self): if (not self.conf.is_ready()): print "pm_query not is_ready" return None if (os.path.exists(os.path.join(self.conf.gt_dir, 'GTAGS'))): pargs = [ 'global', '-u' ] else: pargs = [ 'gtags', '-i' ] qsig = GtProcess(self.conf.gt_dir, None).run_rebuild_process(pargs) qsig.connect(self.gt_file_list_update) return qsig def gt_file_list_update(self): wdir = self.conf.gt_dir if not os.path.exists(os.path.join(wdir, 'GTAGS')): return fl = [] try: import subprocess pargs = [ 'global', '-P', '-a' ] proc = subprocess.Popen(pargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=wdir) (out_data, err_data) = proc.communicate() fl = re.split('\r?\n', out_data.strip()) PluginHelper.file_view_update(fl) except: import sys e = sys.exc_info()[1] print ' '.join(pargs) print e def gt_is_open(self): return self.conf != None def gt_is_ready(self): return self.conf.is_ready() seascope-0.8/src/backend/plugins/CtagsCache.py000644 000000 000000 00000015220 12230074152 021333 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtCore import * from datetime import datetime import os, re, subprocess #class CtagsInfo: #def __init__(self): #pass #@staticmethod #def lang_suffixes(): #cmd = 'ctags --list-maps' #args = cmd.split() #import subprocess #proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) #(out_data, err_data) = proc.communicate() #res = re.split('\r?\n', out_data) # res = out_data #res = [ line.split(None, 1) for line in res if line != '' ] #d = {} #for line in res: #import fnmatch #fn_pats = line[1] .split() #print line[0], fn_pats #re_pats = '|'.join(fnmatch.translate(p) for p in fn_pats) #print line[0], re_pats #d[line[0]] = re_pats #print d #print 'ctag.lang' #CtagsInfo.lang_suffixes() class CtagsThread(QThread): thread_list = [] def __init__(self, sig): QThread.__init__(self) self.sig = sig self.ct_dict = {} self.finished.connect(self._finished_cb) CtagsThread.thread_list.append(self) def _finished_cb(self): #print 'CtagsThread.finished', len(self.ct_dict) CtagsThread.thread_list.remove(self) for k in self.ct_dict: ct_cache[k] = self.ct_dict[k] self.res = self.parse_result(self.res, self.sig) if self.res != None: self.sig.emit_result(self.res) def ctags_bsearch(self, ct, n): x = -1 y = len(ct) - 1 #print f, n while x < y: m = (x + y + 1) / 2 #print '(', x, y, m, ')' if ct[m][1] > n: #print 'y: m -1', ct[m][1] m = m - 1 y = m continue if ct[m][1] < n: #print 'x: m', ct[m][1] x = m continue break if y == -1: return y #assert x == m or y == m or ct[m][1] == n return m def _ctags_fix(self, line): f = line[1] n = int(line[2]) ct = self.ct_dict[f] m = self.ctags_bsearch(ct, n) if m == -1: return True if ct[m][1] != n: if ct[m][2] in ['variable']: #line[0] = '***** SMART *****' #print line return True if f.endswith('.py'): while m > 0 and (ct[m][2] in ['namespace']): m = m - 1 if m == - 1: return True if ct[m][1] == n: if self.cmd_str == 'DEF': x = m y = m while x > 1 and ct[x - 1][1] == n: x = x - 1 while y < len(ct) - 1 and ct[y + 1][1] == n: y = y + 1 if x > y: return False for m in range(x, y + 1): reqPat = self.sig.sym + '$' if re.match(reqPat, ct[m][0]): line[0] = ct[m][0] return True return False else: if self.cmd_str == 'DEF': return False if self.cmd_str == '-->': if f.endswith('.tac'): if ct[m][2] in ['reactor']: line[0] = ct[m][0].split('=>')[0].strip() + "Is" return True line[0] = ct[m][0] return True def runCtagsCustom(self, fl): custom_map = os.getenv('SEASCOPE_CTAGS_SUFFIX_CMD_MAP') if not custom_map: return [] try: custom_map = eval(custom_map) except: print 'SEASCOPE_CTAGS_SUFFIX_CMD_MAP has errors' return [] cmd_list = [] for (suffix, cmd) in custom_map: _fl = [ f for f in fl if f.endswith(suffix) ] args = cmd.split() args += _fl cmd_list.append(args) if not len(cmd_list): return [] out_data_all = [] for args in cmd_list: proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate('\n'.join(fl)) out_data = re.split('\r?\n', out_data) out_data_all += out_data return out_data_all def _run_ctags(self): cmd = 'ctags -n -u --fields=+K -L - -f -' args = cmd.split() proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate('\n'.join(self.file_list)) out_data = re.split('\r?\n', out_data) out_data += self.runCtagsCustom(self.file_list) for line in out_data: if line == '': continue line = line.split('\t') f = line[1] num = line[2].split(';', 1)[0] line = [line[0], int(num), line[3]] self.ct_dict[f].append(line) def prepare_file_list(self): #t1 = datetime.now() flist = set() for line in self.res: if line[0] in self.cond_list: if line[1] not in ct_cache: flist.add(line[1]) else: self.ct_dict[line[1]] = ct_cache[line[1]] for f in flist: self.ct_dict[f] = [] #t2 = datetime.now() #print ' ', len(flist), 'flist', t2 - t1 self.file_list = flist def apply_fix(self, cmd_str, res, cond_list): self.cmd_str = cmd_str self.res = res self.cond_list = cond_list self.prepare_file_list() self.start() def run(self): #t2 = datetime.now() self._run_ctags() #t3 = datetime.now() #print ' ct', t3 - t2 res = [] for line in self.res: if line[0] not in self.cond_list: continue if not self._ctags_fix(line): continue res.append(line) self.res = res #t4 = datetime.now() #print ' fix', t4 - t3 #print ' total', t4 - t2 def _filter_res(self, res, sig): req = sig.sym out_res = [] if self.cmd_str == 'DEF': import_re = re.compile('^\s*import\s+') for line in res: reqPat = req + '$' if not re.match(reqPat, line[0]): continue if import_re.search(line[3]) and line[1].endswith('.py'): continue out_res.append(line) return out_res if self.cmd_str == '-->': call_re = re.compile('\\b%s\\b\s*\(' % req) extern_re = re.compile('^\s*extern\s+') reactor_re = re.compile('\\b(\w+::)*(\w+)\s*=>.*\\b%s\\b' % req) comment_re = re.compile('^\s*(\*\s|/\*|\*/|//\s|# )') func_ptr_re = re.compile('\\b(\w+)\s*(=|:)\s*%s\s*[,;:)]' % req) func_as_arg_re = re.compile('(^\s*|[(,]\s*)(\w+(\.|->))*%s\s*[,)]' % req); def _check_line(): if line[1].endswith('.tac'): if '=>' in line[3]: grp = reactor_re.search(line[3]) if grp: line[0] = grp.group(2) + "Is" return True # fallthru if line[0] == req: if not re.search('(\.|->)%s\\b' % req, line[3]): return False return True if call_re.search(line[3]): if extern_re.search(line[3]): return False return True grp = func_ptr_re.search(line[3]) if grp: line[0] = grp.group(1) return True if not func_as_arg_re.search(line[3]): False return True for line in res: if not _check_line(): continue if line[0] == '': continue if comment_re.search(line[3]): continue out_res.append(line) return out_res if self.cmd_str == '<--': return res if self.cmd_str == 'INC': inc_re = re.compile('^\s*(#\s*include|(from\s+[^\s]+\s+)?import)\s+.*%s.*' % req) for line in res: if not inc_re.search(line[3]): continue out_res.append(line) return out_res return res ct_cache = {} def flush(): #print 'flushing ctags cache...' global ct_cache ct_cache = {} seascope-0.8/src/backend/plugins/PluginHelper.py000644 000000 000000 00000004366 12230074152 021755 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtCore import * from PyQt4.QtGui import * backend_menu = None edit_book = None res_book = None call_view = None class_graph_view = None file_func_graph_view = None file_view = None dbg_view = None def editor_current_file(): (f, l) = edit_book.get_current_file_line() return f def editor_current_word(): return edit_book.get_current_word() def result_page_new(name, sig_res): if sig_res == None: return page = res_book.create_result_page(name) ## add result sig_res[0].connect(page.add_result) #page.add_result(req, res) dbg_view.connect_to_sig(sig_res[1]) def _quick_def_result(req, res): count = len(res) if count > 1: page = res_book.create_result_page_single() page.add_result(req, res) dlg = QDialog() dlg.setWindowTitle('Quick Definition: ' + req) vlay = QVBoxLayout(dlg) vlay.addWidget(page) page.sig_show_file_line.connect(edit_book.show_file_line) page.activated.connect(dlg.accept) page.setMinimumWidth(800) page.setMinimumHeight(100) dlg.exec_() return if (count == 1): filename = res[0][1] try: line = int(res[0][2]) except: return edit_book.show_file_line(filename, line) def quick_def_page_new(sig_res): if sig_res == None: return sig_res[0].connect(_quick_def_result) dbg_view.connect_to_sig(sig_res[1]) def call_view_page_new(req, query_func, ctree_query_args, opt): hint_file = editor_current_file() call_view.create_page(req, query_func, ctree_query_args, opt, hint_file) def class_graph_view_page_new(req, dname, prj_type, query_func, opt): clgraph_query_args = [ ['CLGRAPH', 'D', 'Derived classes' ], ['CLGRAPH', 'B', 'Base classes' ], ] class_graph_view.create_page(req, dname, prj_type, query_func, clgraph_query_args, opt) def file_func_graph_view_page_new(req, dname, proj_dir, query_func, opt): ffgraph_query_args = [ ['FFGRAPH', 'F', 'File functions graph'], ['FFGRAPH_E', 'F+E', 'File functions + external graph'], ['FFGRAPH_D', 'D', 'Directory functions graph'], ['FFGRAPH_DE', 'D+E', 'Directory functions + external graph'] ] file_func_graph_view.create_page(req, dname, proj_dir, query_func, ffgraph_query_args, opt) def file_view_update(flist): file_view.add_files(flist) seascope-0.8/src/backend/__init__.py000644 000000 000000 00000006474 12230074152 017437 0ustar00rootroot000000 000000 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * import DialogManager from plugins import PluginHelper backend_plugins = [] backend_dict = {} def _load_plugins(module, directory): pluginImports = __import__(module, globals(), locals()) print 'Scanning for backend plugins...' plist = [] pdict = {} for i in sorted(os.listdir(directory)): path = os.path.join( directory, i, '__init__.py' ) if os.path.isfile( path ): p = __import__( '%s.%s' % (module, i), globals(), locals(), ['*'] ) plist.append(p) pdict[p.name()] = p if not hasattr(p, 'priority'): p.priority = 0 plist = sorted(plist, key=lambda p: p.priority, reverse=True) for p in plist: print '\t', p.name() return (plist, pdict) def load_plugins(): global backend_plugins, backend_dict (backend_plugins, backend_dict) = _load_plugins('backend.plugins', 'backend/plugins') from plugins.PluginBase import ProjectBase, ConfigBase, QueryBase, QueryUiBase prj_actions = [] prj = None def _proj_new_open(): for act in prj_actions: act.setEnabled(True) class ProjectNewDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('ui/proj_new.ui', self) self.backend_lw.currentRowChanged.connect(self.currentRowChanged_cb) def currentRowChanged_cb(self, row): if row == -1: return bname = str(self.backend_lw.currentItem().text()) b = backend_dict[bname] try: self.descr_te.setText(b.description()) except: self.descr_te.setText('') def run_dialog(self): bi = [ b.name() for b in backend_plugins] self.backend_lw.addItems(bi) self.backend_lw.setCurrentRow(0) if self.exec_() == QDialog.Accepted: bname = str(self.backend_lw.currentItem().text()) return (backend_dict[bname]) return None def msg_box(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) def proj_new(): if len(backend_plugins) == 0: msg_box('No backends are available/usable') dlg = ProjectNewDialog() b = dlg.run_dialog() if b == None: return global prj assert not prj prj = b.project_class().prj_new() if prj: _proj_new_open() return prj != None def proj_open(proj_path): be = [] for p in backend_plugins: if p.is_your_prj(proj_path): be.append(p) if len(be) == 0: msg = "Project '%s': No backend is interested" % proj_path msg_box(msg) return if len(be) > 1: msg = "Project '%s': Many backends interested" % proj_path for b in be: msg += '\n\t' + b.name() msg += '\n\nGoing ahead with: ' + be[0].name() msg_box(msg) b = be[0] print "Project '%s': using '%s' backend" % (proj_path, b.name()) global prj prj = b.project_class().prj_open(proj_path) if prj: _proj_new_open() return prj != None def proj_close(): global prj prj.prj_close() prj = None PluginHelper.backend_menu.clear() PluginHelper.backend_menu.setTitle('') for act in prj_actions: act.setEnabled(False) from plugins import CtagsCache CtagsCache.flush() def proj_is_open(): return prj != None def proj_name(): return prj.prj_name() if prj else None def proj_dir(): return prj.prj_dir() if prj else None def proj_src_files(): return prj.prj_src_files() def proj_conf(): return prj.prj_conf() def proj_settings_trigger(): return prj.prj_settings_trigger()seascope-0.8/src/DialogManager.py000644 000000 000000 00000016461 12230074152 017000 0ustar00rootroot000000 000000 #!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys import os import string from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * def show_msg_dialog(msg): QMessageBox.information(None, "Seascope", msg, QMessageBox.Ok) def show_yes_no(msg): ret = QMessageBox.question(None, "Seascope", msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) return ret == QMessageBox.Yes def show_yes_no_dontask(msg): return QMessageBox.question(None, "Seascope", msg, "Yes", "No", "Yes, Don't ask again") def show_proj_close(): return show_yes_no("\nClose current project?") class ProjectOpenDialog(QObject): def __init__(self): QObject.__init__(self) self.dlg = uic.loadUi('ui/proj_open.ui') self.dlg.pod_open_btn.setIcon(QFileIconProvider().icon(QFileIconProvider.Folder)) QObject.connect(self.dlg.pod_open_btn, SIGNAL("clicked()"), self.open_btn_cb) QObject.connect(self.dlg, SIGNAL("accepted()"), self.ok_btn_cb) QObject.connect(self.dlg.pod_proj_list, SIGNAL("itemSelectionChanged()"), self.proj_list_change_cb) def proj_list_change_cb(self): item = self.dlg.pod_proj_list.selectedItems()[0] proj_dir = str(item.text()) self.dlg.pod_proj_name.setText(str(proj_dir)) self.path = proj_dir def open_btn_cb(self): fdlg = QFileDialog(None, "Choose project directory") fdlg.setFileMode(QFileDialog.Directory); fdlg.setDirectory(self.dlg.pod_proj_name.text()) if (fdlg.exec_()): proj_dir = fdlg.selectedFiles()[0]; self.dlg.pod_proj_name.setText(str(proj_dir)) def ok_btn_cb(self): p = str(self.dlg.pod_proj_name.text()).strip() if (p == ''): self.dlg.setResult(2) return p = os.path.normpath(p) if (not os.path.isabs(p)): show_msg_dialog("\nProject path is not absolute") self.dlg.setResult(2) return if (not os.path.isdir(p)): show_msg_dialog("\nProject path is not a directory") self.dlg.setResult(2) return self.path = p def run_dialog(self, path_list): self.path = None self.dlg.pod_proj_name.setText('') self.dlg.pod_proj_list.addItems(path_list) while True: ret = self.dlg.exec_() if (ret == QDialog.Accepted or ret == QDialog.Rejected): break return self.path def show_project_open_dialog(path_list): d = ProjectOpenDialog() return d.run_dialog(path_list) class FilePreferencesDialog(QObject): def __init__(self, app_style, edit_ext_cmd, ev_font, dontask, innered, ln_nr): QObject.__init__(self) self.dlg = uic.loadUi('ui/preferences.ui') self.dlg.prd_style_lw.addItems(QStyleFactory.keys()) self.dlg.prd_style_lw.itemSelectionChanged.connect(self.style_changed_cb) self.dlg.prd_font_app_btn.clicked.connect(self.font_app_btn_cb) self.dlg.prd_font_ev_btn.clicked.connect(self.font_ev_btn_cb) self.set_btn_text_and_font(self.dlg.prd_font_app_btn, QApplication.font()) self.set_btn_text_and_font(self.dlg.prd_font_ev_btn, ev_font) self.app_style = app_style self.ev_font = ev_font self.edit_ext_cmd = edit_ext_cmd self.exit_dontask = dontask self.inner_editing = innered self.show_ln_nr = ln_nr if self.exit_dontask: self.dlg.prd_opt_ask_chkb.setCheckState(Qt.Unchecked) else: self.dlg.prd_opt_ask_chkb.setCheckState(Qt.Checked) if self.inner_editing: self.dlg.prd_opt_inner_ed.setCheckState(Qt.Checked) else: self.dlg.prd_opt_inner_ed.setCheckState(Qt.Unchecked) if self.show_ln_nr: self.dlg.prd_opt_show_ln_nr.setCheckState(Qt.Checked) else: self.dlg.prd_opt_show_ln_nr.setCheckState(Qt.Unchecked) if (self.edit_ext_cmd): self.dlg.prd_edit_ext_inp.setText(self.edit_ext_cmd) def set_btn_text_and_font(self, btn, font): ftext = font.family() + ' ' + str(font.pointSize()) btn.setFont(font) btn.setText(ftext) def style_changed_cb(self): item = self.dlg.prd_style_lw.currentItem() self.app_style = item.text() QApplication.setStyle(self.app_style) def font_app_btn_cb(self): (font, ok) = QFontDialog().getFont(QApplication.font()) if (ok): self.set_btn_text_and_font(self.dlg.prd_font_app_btn, font) def font_ev_btn_cb(self): (font, ok) = QFontDialog().getFont(self.ev_font) if (ok): self.set_btn_text_and_font(self.dlg.prd_font_ev_btn, font) def run_dialog(self): ret = self.dlg.exec_() if (ret == QDialog.Accepted): QApplication.setFont(self.dlg.prd_font_app_btn.font()) self.ev_font = self.dlg.prd_font_ev_btn.font() self.edit_ext_cmd = self.dlg.prd_edit_ext_inp.text() self.exit_dontask = self.dlg.prd_opt_ask_chkb.checkState() == Qt.Unchecked self.inner_editing = self.dlg.prd_opt_inner_ed.checkState() == Qt.Checked self.show_ln_nr = self.dlg.prd_opt_show_ln_nr.checkState() == Qt.Checked return (self.app_style, self.dlg.prd_font_app_btn.font().toString(), self.edit_ext_cmd, self.ev_font, self.exit_dontask, self.inner_editing, self.show_ln_nr) def show_preferences_dialog(app_style, edit_ext_cmd, ev_font, dontask, innered, ln_nr): d = FilePreferencesDialog(app_style, edit_ext_cmd, ev_font, dontask, innered, ln_nr) return d.run_dialog() def show_about_dialog(): d = uic.loadUi('ui/about.ui') p = QApplication.windowIcon().pixmap(128) d.ad_logo_lbl.setPixmap(p) d.exec_() def show_goto_line_dialog(line, max_line): d = uic.loadUi('ui/goto_line.ui') d.gl_spinbox.setMaximum(max_line) d.gl_hslider.setMaximum(max_line) d.gl_spinbox.setValue(line) d.gl_spinbox.lineEdit().selectAll() if (d.exec_() == QDialog.Accepted): return d.gl_spinbox.value() return None class FindDialog: dlg = None def __init__(self): self.dlg = uic.loadUi('ui/find.ui') self.dlg.ft_text_inp.setAutoCompletion(False) self.dlg.ft_text_inp.setInsertPolicy(QComboBox.InsertAtTop) def run_dlg(self, text): if (text == None): text = '' d = self.dlg d.ft_text_inp.lineEdit().setText(text) d.ft_text_inp.lineEdit().selectAll() d.ft_text_inp.lineEdit().setFocus() d.ft_from_cursor.setChecked(True) while True: ret = d.exec_() if (ret != QDialog.Accepted): return None text = d.ft_text_inp.currentText() text = str(text).strip() if (text != ''): break opt = { 'cs' : d.ft_cs.isChecked(), 're' : d.ft_re.isChecked(), 'wo' : d.ft_wo.isChecked(), 'fw' : not d.ft_bw.isChecked(), 'cursor' : d.ft_from_cursor.isChecked(), } return (text, opt) def show_find_dialog(text): if (FindDialog.dlg == None): FindDialog.dlg = FindDialog() return FindDialog.dlg.run_dlg(text) class FilterDialog: def __init__(self, cmd_items, cmd_sel): self.dlg = uic.loadUi('ui/filter.ui') self.dlg.fd_cmd_inp.addItems(cmd_items) self.dlg.fd_cmd_inp.setCurrentIndex(cmd_items.index(cmd_sel)) self.dlg.fd_regex_err_lbl.setVisible(False) def run_dialog(self): while True: ret = self.dlg.exec_() if ret != QDialog.Accepted: return None is_regex = self.dlg.fd_regex_chkbox.isChecked() text = str(self.dlg.fd_filter_inp.text()) if is_regex == True: try: import re re.compile(text) except: e = str(sys.exc_info()[1]) lbl = self.dlg.fd_regex_err_lbl lbl.setVisible(True) lbl.setText("regex: " + e + '') continue res = [ text, is_regex, self.dlg.fd_negate_chkbox.isChecked(), self.dlg.fd_icase_chkbox.isChecked(), str(self.dlg.fd_cmd_inp.currentText()) ] return res def show_filter_dialog(cmd_items, cmd_sel): dlg = FilterDialog(cmd_items,cmd_sel) return dlg.run_dialog() seascope-0.8/src/EdViewTest.py000755 000000 000000 00000002317 12230074152 016327 0ustar00rootroot000000 000000 #!/usr/bin/python if __name__ == '__main__': import sys, os, optparse usage = "usage: %prog filename" op = optparse.OptionParser(usage=usage) (options, args) = op.parse_args() if len(args) != 1: print >> sys.stderr, 'Please specify a filename' sys.exit(-1) filename = args[0] filename = os.path.abspath(filename) if not os.access(filename, os.R_OK): print 'Failed to read the file:', filename sys.exit(-2) app_dir = os.path.dirname(os.path.realpath(__file__)) os.chdir(app_dir) from PyQt4 import QtGui, QtCore from PyQt4.QtGui import * from PyQt4.QtCore import * from view import EdView, EdViewRW import view view.load_plugins() app = QApplication(sys.argv) w = QMainWindow() if os.getenv("SEASCOPE_EDIT", 0): book = EdViewRW.EditorBookRW() else: book = EdView.EditorBook() actDescr = [ [ book.find_cb, 'Ctrl+F' ], [ book.find_next_cb, 'F3' ], [ book.find_prev_cb, 'Shift+F3' ], ] for ad in actDescr: act = QAction(w) act.setShortcut(ad[1]) act.triggered.connect(ad[0]) w.addAction(act) w.setCentralWidget(book) w.resize(900, 600) w.show() book.show_file(filename) w.setWindowTitle(filename) sys.exit(app.exec_()) seascope-0.8/README000644 000000 000000 00000000371 12230074152 014016 0ustar00rootroot000000 000000 version: 0.8 Seascope is a GUI frontend for cscope, idutils. * Running the application cd src python Seascope.py * Generating source distribution package python setup.py sdist * Generating RPM distribution package python setup.py bdist_rpm seascope-0.8/setup.py000755 000000 000000 00000003342 12230074152 014654 0ustar00rootroot000000 000000 #!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import textwrap from distutils.core import setup setup(name='Seascope', version='0.8', description='A multi-platform multi-language source code browsing tool', long_description= textwrap.dedent("""A pyQt GUI front-end for idutils, cscope and gtags. Written in python using pyQt, QScintilla libraries."""), url='http://seascope.googlecode.com', packages=['Seascope', 'Seascope.backend', 'Seascope.backend.plugins', 'Seascope.backend.plugins.idutils', 'Seascope.backend.plugins.cscope', 'Seascope.backend.plugins.gtags', 'Seascope.view', 'Seascope.view.filecontext', 'Seascope.view.filecontext.plugins', 'Seascope.view.filecontext.plugins.ctags_view', 'Seascope.view.filecontext.plugins.generic_view', ], package_dir={'Seascope': 'src'}, package_data={'Seascope': ['icons/*.svg','tools/*.py', 'ui/*.ui', 'backend/plugins/*/ui/*.ui']}, license="BSD License", classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: X11 Applications :: Qt', 'Environment :: Win32 (MS Windows)', 'Intended Audience :: End Users/Desktop', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Programming Language :: Python', 'Topic :: Software Development', ], options= {'bdist_rpm':{'requires': 'PyQt4,qscintilla-python,idutils,cscope,global,ctags,graphviz', 'group': 'Development Tools', 'vendor': 'The Seascope Team'}} )