pax_global_header00006660000000000000000000000064136324577710014531gustar00rootroot0000000000000052 comment=8a669e0e333801477c4624883bd1ab1823b71bbb seascope-0.9+8a669e0e/000077500000000000000000000000001363245777100143465ustar00rootroot00000000000000seascope-0.9+8a669e0e/.hgignore000066400000000000000000000000061363245777100161450ustar00rootroot00000000000000.pyc$ seascope-0.9+8a669e0e/LICENSE000066400000000000000000000025541363245777100153610ustar00rootroot00000000000000Copyright (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.9+8a669e0e/MANIFEST.in000066400000000000000000000000201363245777100160740ustar00rootroot00000000000000include LICENSE seascope-0.9+8a669e0e/README000066400000000000000000000003711363245777100152270ustar00rootroot00000000000000version: 0.9 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.9+8a669e0e/setup.py000077500000000000000000000033511363245777100160650ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import textwrap from distutils.core import setup setup(name='Seascope', version='0.9', 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='https://github.com/anilFree/seascope' 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': 'PyQt5,python3-pyqt5.qsci,idutils,cscope,global,ctags,graphviz', 'group': 'Development Tools', 'vendor': 'The Seascope Team'}} ) seascope-0.9+8a669e0e/src/000077500000000000000000000000001363245777100151355ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/DialogManager.py000066400000000000000000000170621363245777100202070ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys import os import string from PyQt5 import QtWidgets, QtGui, QtCore, uic from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.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): mb = QMessageBox(None) mb.setIcon(QMessageBox.Question) mb.setWindowTitle("Seascope") mb.setText(msg) mb.addButton('Yes', QMessageBox.YesRole) mb.addButton('No', QMessageBox.NoRole) mb.addButton("Yes, Don't ask again", QMessageBox.YesRole) return mb.exec() 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)) self.dlg.pod_open_btn.clicked.connect(self.open_btn_cb) self.dlg.accepted.connect(self.ok_btn_cb) self.dlg.pod_proj_list.itemSelectionChanged.connect(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(list(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() d.gl_spinbox.lineEdit().setFocus() 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.setCompleter(None) self.dlg.ft_text_inp.setInsertPolicy(QComboBox.InsertAtTop) self.dlg.ft_text_inp.setFocus() 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_filter_inp.setFocus() 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.9+8a669e0e/src/EdViewTest.py000077500000000000000000000023731363245777100175420ustar00rootroot00000000000000#!/usr/bin/env python3 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('Please specify a filename', file=sys.stderr) 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 PyQt5 import QtWidgets, QtGui, QtCore from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.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.9+8a669e0e/src/Seascope.py000077500000000000000000001005611363245777100172570ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys sys.dont_write_bytecode = True import os import string try: from PyQt5 import QtWidgets, QtGui, QtCore except ImportError: print('Error: PyQt5 package not found\nError: required packages: PyQt5 and python3-pyqt5.qsci\nError: program aborted.') sys.exit(-1) try: from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5 import uic from view import EdView, EdViewRW, ResView, FileView, CallView, ClassGraphView, FileFuncGraphView from view import DebugView, CodemarkView, CodeContextView from view import ProjectUi import backend import DialogManager import view except ImportError as e: print(str(e)) print("Error: failed to import supporting packages.\nError: program aborted.") sys.exit(-1) def msg_box(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) class BackendChooserDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('ui/proj_new.ui', self) self.backend_lw.currentRowChanged.connect(self.currentRowChanged_cb) self.backend = backend def currentRowChanged_cb(self, row): if row == -1: return bname = str(self.backend_lw.currentItem().text()) desc = '' for b in self.backend.plugin_list(): if b.name() == bname: desc = b.description() self.descr_te.setText(desc) def run_dialog(self): blist = self.backend.plugin_list() if len(blist) == 0: msg_box('No backends are available/usable') return None bi = [ b.name() for b in blist ] self.backend_lw.addItems(bi) self.backend_lw.setCurrentRow(0) if self.exec_() == QDialog.Accepted: bname = str(self.backend_lw.currentItem().text()) return bname return None class QueryUiHelper: def __init__(self): self.edit_book = None self.res_book = None self.call_view = None self.class_graph_view = None self.file_func_graph_view = None self.dbg_view = None self.file_view = None def editor_current_file(self): (f, l) = self.edit_book.get_current_file_line() return f def editor_current_word(self): return self.edit_book.get_current_word() def result_page_new(self, name, sig_res): if sig_res == None: return page = self.res_book.create_result_page(name) ## add result sig_res[0].connect(page.add_result) #page.add_result(req, res) self.dbg_view.connect_to_sig(sig_res[1]) def file_view_update(self, flist): self.file_view.add_files(flist) def _quick_def_result(self, req, res): count = len(res) if count > 1: page = self.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(self.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 self.edit_book.show_file_line(filename, line) def quick_def_page_new(self, sig_res): if sig_res == None: return sig_res[0].connect(self._quick_def_result) self.dbg_view.connect_to_sig(sig_res[1]) def call_view_page_new(self, req, query_func, ctree_query_args, opt): hint_file = self.editor_current_file() self.call_view.create_page(req, query_func, ctree_query_args, opt, hint_file) def class_graph_view_page_new(self, req, dname, prj_type, query_func, clgraph_query_args, opt): self.class_graph_view.create_page(req, dname, prj_type, query_func, clgraph_query_args, opt) def file_func_graph_view_page_new(self, req, dname, proj_dir, query_func, ffgraph_query_args, opt): self.file_func_graph_view.create_page(req, dname, proj_dir, query_func, ffgraph_query_args, opt) class QueryDialogUi(QDialog): def __init__(self, title, feat): QDialog.__init__(self) self.feat = feat self.ui = uic.loadUi('ui/query.ui', self) self.qd_sym_inp.setCompleter(None) self.qd_sym_inp.setInsertPolicy(QComboBox.InsertAtTop) self.setWindowTitle(title) self.qd_cmd_inp.addItems(self.feat.cmd_qstrlist) def run_dialog(self, cmd_str, req): qstr = self.feat.cmd_str2qstr[cmd_str] inx = self.qd_cmd_inp.findText(qstr) 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()) cmd = str(self.qd_cmd_inp.currentText()) cmd_str = self.feat.cmd_qstr2str[cmd] #self.qd_sym_inp.addItem(req) in_opt = { 'substring' : self.qd_substr_chkbox.isChecked(), 'ignorecase' : self.qd_icase_chkbox.isChecked(), } res = self.feat.query_dlg_cb(req, cmd_str, in_opt) return res return None def show_dlg(self, cmd_str, req): return self.run_dialog(cmd_str, req) class QueryUi(QObject): def __init__(self, h): QObject.__init__(self) self.qui_h = h self.backend = backend self.backend_menu = None self.prj_actions = [] self.feat = None self.qry_ui = None def set_backend_menu(self, menu): self.backend_menu = menu self.backend_menu.triggered.connect(self.menu_cb) def setup(self): self.prepare_menu() for act in self.prj_actions: act.setEnabled(True) self.feat = self.backend.proj_feature() t = backend.proj_type().title() + ' Query' self.qry_ui = QueryDialogUi(t, self.feat) self.query_file_list() def reset(self): self.backend_menu.clear() self.backend_menu.setTitle('') for act in self.prj_actions: act.setEnabled(False) self.feat = None self.qry_ui = None def editor_current_file(self): return self.qui_h.editor_current_file() def editor_current_word(self): return self.qui_h.editor_current_word() def prepare_menu(self): td = { 'idutils' : '&Idutils', 'gtags' : 'G&tags', 'cscope' : '&Cscope', } t = td[self.backend.proj_type()] menu = self.backend_menu menu.setTitle(t) feat = self.backend.proj_feature() for c in feat.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 menu_cb(self, act): if act.cmd_str != None: self.query_cb(act.cmd_str) def query_cb(self, cmd_str): if not backend.proj_conf(): return if not backend.proj_is_ready(): show_msg_dialog('\nProject has no source files') return if cmd_str == 'CLGRAPHD': f = self.editor_current_file() if f: d = os.path.dirname(f) self.query_class_graph_dir(d) return if cmd_str == 'FFGRAPH': f = self.editor_current_file() if f: self.query_file_func_graph(f) return req = self.editor_current_word() if (req != None): req = str(req).strip() opt = None if cmd_str not in [ 'QDEF' ]: val = self.qry_ui.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 do_proj_query(self, rquery): print('do_proj_query', rquery) sig_res = self.backend.proj_query(rquery) return sig_res def query_ctree(self, req, opt): self.qui_h.call_view_page_new(req, self.do_proj_query, self.feat.ctree_query_args, opt) def query_class_graph(self, req, opt): prj_type = self.backend.proj_type() prj_dir = self.backend.proj_dir() self.qui_h.class_graph_view_page_new(req, prj_dir, prj_type, self.do_proj_query, self.feat.clgraph_query_args, opt) def query_class_graph_dir(self, dname): opt = [] self.qui_h.class_graph_view_page_new('', dname, None, self.do_proj_query, self.feat.clgraph_query_args, opt) def query_file_func_graph(self, fname): opt = [] self.qui_h.file_func_graph_view_page_new('', fname, '', self.do_proj_query, self.feat.ffgraph_query_args, 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'] = self.editor_current_file() return rquery def query_qdef(self, req, opt): rquery = {} rquery = self._prepare_rquery('DEF', req, opt) sig_res = self.do_proj_query(rquery) self.qui_h.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.do_proj_query(rquery) self.qui_h.result_page_new(name, sig_res) def do_rebuild(self): sig_rebuild = self.backend.proj_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 self.query_file_list() def rebuild_cb(self): self.do_rebuild() def query_file_list(self): sig_res = self.backend.proj_query_fl() if sig_res == None: return if isinstance(sig_res , list): fl = sig_res self.qui_h.file_view_update(fl) return sig_res.connect(self.qui_h.file_view_update) 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() if backend.proj_is_open(): self.app_gui_state_save(backend.proj_dir()) 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) 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, 'Ctrl+W') m_file.addSeparator() m_file.addAction('&Restart', self.file_restart_cb, QKeySequence.Quit) m_file.addAction('&Quit', self.close, 'Ctrl+Q') 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('Refresh file', self.edit_book.refresh_file_cb, 'F5') 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) self.qui.prj_actions.append(act) act = m_prj.addAction('&Close Project', self.proj_close_cb) act.setDisabled(True) self.qui.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' + '=' + ','.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 app_gui_state_file(self): return os.path.expanduser('~/.seascopeguirc') def app_gui_state_read(self): f = self.app_gui_state_file() data = None try: if os.path.exists(f): with open(f, 'rb') as fp: import json data = json.load(fp) except Exception as e: print('app_gui_state_read:', e) return data def app_gui_state_write(self, data): f = self.app_gui_state_file() try: import io import json sp = io.StringIO() json.dump(data, sp) with open(f, 'wb') as fp: fp.write(sp.getvalue().encode()) except Exception as e: print('app_gui_state_write:', e) def app_gui_get_geometry(self): rect = self.geometry() return (rect.x(), rect.y(), rect.width(), rect.height()) def app_gui_set_geometry(self, geometry): x = geometry[0] y = geometry[1] w = geometry[2] h = geometry[3] self.setGeometry(x, y, w, h) def app_gui_state_save(self, proj_path): pd = {} pd ['file_line_list'] = self.edit_book.get_file_line_list() pd ['dir_view_list'] = self.file_view.get_dir_view_list() pd ['geometry'] = self.app_gui_get_geometry() try: data = self.app_gui_state_read() if data == None: data = {} if 'proj_gui_state' not in data: data['proj_gui_state'] = {} data['proj_gui_state'][proj_path] = pd self.app_gui_state_write(data) except Exception as e: print('app_gui_state_save:', e) def app_gui_state_restore(self, proj_path): try: data = self.app_gui_state_read() if data == None: return pgs = data.pop('proj_gui_state', {}) pd = pgs.pop(proj_path, {}) for fl in pd.pop('file_line_list', []): try: (f, l) = fl.rsplit(':', 1) l = int(l) if os.path.isabs(f) and f.startswith(proj_path) and os.path.isfile(f): self.edit_book.show_file_line(f, l, hist=False) except: pass for d in pd.pop('dir_view_list', []): if os.path.isabs(d) and f.startswith(proj_path) and os.path.isdir(d): self.file_view.open_dir_view(d) try: self.app_gui_set_geometry(pd ['geometry']) except Exception as e: print('Geometry configuration not restored') except Exception as e: print('app_gui_state_restore:', e) 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.qui.setup() self.editor_tab_changed_cb(None) proj_path = backend.proj_dir() self.update_recent_projects(proj_path) self.app_gui_state_restore(proj_path) def proj_new_cb(self): if backend.proj_is_open(): if not DialogManager.show_proj_close(): return self.proj_close_cb() dlg = BackendChooserDialog() bname = dlg.run_dialog() if bname == None: return proj_args = ProjectUi.show_settings_ui(bname, None) if not proj_args: return if not backend.proj_new(bname, proj_args): return # XXX FIXIT self.qui.do_rebuild() self.proj_new_or_open() def proj_open(self, proj_path): bl = backend.plugin_guess(proj_path) if len(bl) == 0: msg = "Project '%s': No backend is interested" % proj_path msg_box(msg) return proj_type = bl[0] if len(bl) > 1: msg = "Project '%s': Many backends interested" % proj_path for b in be: msg += '\n\t' + b.name() msg += '\n\nGoing ahead with: ' + proj_type msg_box(msg) print("Project '%s': using '%s' backend" % (proj_path, proj_type)) rc = backend.proj_open(proj_path, proj_type) 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): proj_path = backend.proj_dir() self.update_recent_projects(proj_path) self.app_gui_state_save(proj_path) self.setWindowTitle("Seascope") backend.proj_close() self.qui.reset() 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): proj_args = backend.proj_settings_get() proj_args = ProjectUi.show_settings_ui(backend.proj_type(), proj_args) if proj_args: backend.proj_settings_update(proj_args) 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): self.qui_h = QueryUiHelper() self.qui = QueryUi(self.qui_h) 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 self.qui.set_backend_menu(self.backend_menu) self.qui_h.edit_book = self.edit_book self.qui_h.res_book = self.res_book self.qui_h.call_view = CallView self.qui_h.class_graph_view = ClassGraphView self.qui_h.file_func_graph_view = FileFuncGraphView self.qui_h.dbg_view = DebugView self.qui_h.file_view = self.file_view 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.9+8a669e0e/src/backend/000077500000000000000000000000001363245777100165245ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/backend/__init__.py000066400000000000000000000044641363245777100206450ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re 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') def plugin_list(): return backend_plugins prj = None def proj_new_open_app_cb(): prj.prj_feature_setup() def proj_close_app_cb(): pass def _proj_new_open(): proj_new_open_app_cb() def proj_new(bname, proj_args): b = backend_dict[bname] global prj assert not prj prj = b.project_class().prj_new(proj_args) if prj: _proj_new_open() return prj != None def plugin_guess(proj_path): bi = [] for p in backend_plugins: if p.is_your_prj(proj_path): bi.append(p.name()) return bi def proj_open(proj_path, proj_type): b = backend_dict[proj_type] 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 from .plugins import CtagsCache CtagsCache.flush() proj_close_app_cb 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_get(): return prj.prj_settings_get() def proj_settings_update(proj_args): return prj.prj_settings_update(proj_args) def proj_is_ready(): return prj.prj_is_ready() def proj_query(rquery): return prj.prj_query(rquery) def proj_rebuild(): return prj.prj_rebuild() def proj_query_fl(): return prj.prj_query_fl() def proj_type(): return prj.prj_type() def proj_feature(): return prj.prj_feature() seascope-0.9+8a669e0e/src/backend/plugins/000077500000000000000000000000001363245777100202055ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/backend/plugins/CtagsCache.py000066400000000000000000000160021363245777100225430ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, re, subprocess from datetime import datetime from PyQt5.QtCore import QThread #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() #out_data = out_data.decode() #err_data = err_data.decode() #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).encode()) out_data = out_data.decode() 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 -' opt_I_file = os.getenv('SEASCOPE_CTAGS_OPT_I_FILE') if opt_I_file and os.path.isfile(opt_I_file): cmd += ' -I ' + opt_I_file args = cmd.split() proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate('\n'.join(self.file_list).encode()) out_data = out_data.decode() 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 def parse_result(self, res, sig): res = self._filter_res(res, sig) return res ct_cache = {} def flush(): #print 'flushing ctags cache...' global ct_cache ct_cache = {} seascope-0.9+8a669e0e/src/backend/plugins/PluginBase.py000066400000000000000000000263311363245777100226150ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, re import copy from PyQt5.QtCore import QObject, pyqtSignal, QProcess def NOT_IMPLEMENTED(n, f): msg = '%s: %s: Not implemeted' % (n, f) from PyQt5.QtWidgets import QMessageBox QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) from . import CtagsCache cmd_table_master = [ [ 'REF', ['&References', 'Ctrl+0'], ['References to' ] ], [ 'DEF', ['&Definitions', 'Ctrl+1'], ['Definition of' ] ], [ '<--', ['&Called Functions', 'Ctrl+2'], ['Functions called by' ] ], [ '-->', ['C&alling Functions', 'Ctrl+3'], ['Functions calling' ] ], [ 'TXT', ['Find &Text', 'Ctrl+4'], ['Find text' ] ], [ 'GREP', ['Find &Egrep', 'Ctrl+5'], ['Find egrep pattern' ] ], [ 'FIL', ['Find &File', 'Ctrl+7'], ['Find files' ] ], [ 'INC', ['&Include/Import', 'Ctrl+8'], ['Find include/import' ] ], [ '---', [None, ], None ], [ 'QDEF', ['&Quick Definition', 'Ctrl+]'], None ], [ 'CTREE', ['Call Tr&ee', 'Ctrl+\\'], ['Call tree' ] ], [ '---', [None, ], None ], [ 'CLGRAPH', ['Class &Graph', 'Ctrl+:'], ['Class graph' ] ], [ 'CLGRAPHD', ['Class Graph Dir', 'Ctrl+;'], ['Class graph dir' ] ], [ 'FFGRAPH', ['File Func Graph', 'Ctrl+^'], ['File Func graph dir' ] ], [ '---', [None, ], None ], [ 'UPD', ['Re&build Database', None ], None ], ] class PluginFeatureBase: def __init__(self): self.clgraph_query_args = [ ['CLGRAPH', 'D', 'Derived classes' ], ['CLGRAPH', 'B', 'Base classes' ], ] self.clgraph_query_args = [ ['CLGRAPH', 'D', 'Derived classes' ], ['CLGRAPH', 'B', 'Base classes' ], ] self.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'] ] def setup(self): feat_cmds = [ d[0] for d in self.feat_desc ] ct = copy.deepcopy(cmd_table_master) self.cmd_table = [ t for t in ct if t[0] in feat_cmds or t[0] == '---' ] self.menu_cmd_list = [ [c[0]] + c[1] for c in self.cmd_table ] self.cmd_str2id = {} self.cmd_str2qstr = {} self.cmd_qstr2str = {} for c in self.feat_desc: self.cmd_str2id[c[0]] = c[1] for c in self.cmd_table: if c[2] != None: self.cmd_str2qstr[c[0]] = c[2][0] self.cmd_qstr2str[c[2][0]] = c[0] # python 2.7 #self.cmd_str2id = { c[0]:c[1] for c in self.feat_desc } #self.cmd_str2qstr = { c[0]:c[2][0] for c in self.cmd_table if c[1] } #self.cmd_qstr2str = { c[2][0]:c[0] for c in self.cmd_table if c[1] } self.cmd_qstrlist = [ c[2][0] for c in self.cmd_table if c[2] ] class ProjectBase(QObject): prj = None qry = None def __init__(self): QObject.__init__(self) self.feat = None def prj_close(self): if (self.conf != None): self.conf.proj_close() self.conf = None def prj_dir(self): return self.conf.c_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_show_settings(self, proj_args): NOT_IMPLEMENTED(__name__, __func__) def prj_settings(self, proj_args): NOT_IMPLEMENTED(__name__, __func__) def prj_feature_setup(self): self.feat.setup() def prj_query(self, rquery): return self.qry.query(rquery) def prj_rebuild(self): return self.qry.rebuild() def prj_query_fl(self): return self.qry.query_fl() def prj_type(self): return self.conf.prj_type def prj_feature(self): return self.feat def prj_settings_get(self): proj_args = self.prj_conf() return proj_args def prj_settings_update(self, proj_args): NOT_IMPLEMENTED(__name__, __func__) return class ConfigBase(QObject): def __init__(self, ptype): self.prj_type = ptype self.c_dir = '' self.c_opt = '' self.c_flist = [] def get_proj_name(self): return os.path.split(self.c_dir)[1] def get_proj_src_files(self): fl = self.c_flist return fl def get_proj_conf(self): return (self.c_dir, self.c_opt, self.c_flist) def read_config(self): pass def write_config(self): pass def proj_start(self): pass def proj_open(self, proj_path): self.c_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.c_dir, self.c_opt, self.c_flist) = proj_args self.write_config() self.proj_start() def proj_close(self): pass def is_ready(self): return True @staticmethod def prepare_menu(menubar): pass class QueryBase(QObject): @staticmethod def prepare_menu(menubar): pass def query(self, rquery): cmd_str = rquery['cmd'] req = rquery['req'] opt = rquery['opt'] if opt == None: opt = [] pargs = [] if cmd_str == 'GREP': pargs = ['grep', '-E', '-R', '-n', '-I'] pargs += [ '--', req ] pargs += [self.conf.c_dir] else: assert(false) return None qsig = PluginProcess(self.conf.c_dir, [cmd_str, req]).run_query_process(pargs, req, rquery) return qsig def rebuild(): NOT_IMPLEMENTED(__name__, __func__) def conf_is_open(self): return self.conf != None def conf_is_ready(self): return self.conf.is_ready() class QueryUiBase(QObject): def __init__(self): QObject.__init__(self) from PyQt5.QtWidgets import QMessageBox class QuerySignal(QObject): sig_result = pyqtSignal(str, list) sig_result_dbg = pyqtSignal(str, str, str) sig_rebuild = pyqtSignal() sig_query_fl = pyqtSignal(list) 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 PluginProcessBase(QObject): proc_list = [] def __init__(self, wdir): QObject.__init__(self) PluginProcess.proc_list.append(self) self.is_rebuild = False self.is_query_fl = 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 = self.proc.readAllStandardOutput().data().decode() self.err_str = self.proc.readAllStandardError().data().decode() #print 'output', res #print 'cmd:', self.p_cmd if self.is_rebuild: self.res = res self.sig.sig_rebuild.emit() elif self.is_query_fl: self.res = '' res = self.parse_query_fl(res) self.sig.sig_query_fl.emit(res) 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 self.sig.sig_rebuild.connect(CtagsCache.flush) return self.sig.sig_rebuild def run_query_fl(self, pargs): self.is_query_fl = True self.p_cmd = ' '.join(pargs) self.proc.start(pargs[0], pargs[1:]) if self.proc.waitForStarted() == False: return None return self.sig.sig_query_fl def parse_query_fl(self, text): fl = [] for f in re.split('\r?\n', text.strip()): if f == '': continue fl.append(os.path.join(self.wdir, f)) return fl class PluginProcess(PluginProcessBase): def __init__(self, wdir, rq): PluginProcessBase.__init__(self, wdir) 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) res = [] if self.cmd_str == 'GREP': for line in text: if line == '': continue line = [''] + line.split(':', 2) res.append(line) else: assert(false) res.append(['', '', '', 'PluginProcess.parse_result: FAILED']) return res qsig = CtagsCache.CtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return qsig 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): err_str = err_str.decode() print('slot_result_dbg:', [str(cmd), str(res).strip().split('\n'), str(err_str)]) def slot_rebuild(): print('slot_rebuild') from PyQt5.QtCore import QCoreApplication 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.9+8a669e0e/src/backend/plugins/__init__.py000066400000000000000000000001121363245777100223100ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD seascope-0.9+8a669e0e/src/backend/plugins/cscope/000077500000000000000000000000001363245777100214615ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/backend/plugins/cscope/CscopeProject.py000066400000000000000000000112021363245777100245720ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, string, re from ..PluginBase import PluginFeatureBase, ProjectBase, ConfigBase, QueryBase from ..PluginBase import PluginProcess class CscopeFeature(PluginFeatureBase): def __init__(self): PluginFeatureBase.__init__(self) self.feat_desc = [ ['REF', '0'], ['DEF', '1'], ['<--', '2'], ['-->', '3'], ['TXT', '4'], ['GREP','5'], ['FIL', '7'], ['INC', '8'], ['QDEF', '11'], ['CTREE','12'], ['CLGRAPH', '13'], ['CLGRAPHD', '14'], ['FFGRAPH', '14'], ['UPD', '25'], ] self.ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], ['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] def query_dlg_cb(self, req, cmd_str, in_opt): if req != '' and in_opt['substring']: req = '.*' + req + '.*' opt = None if in_opt['ignorecase']: opt = '-C' res = (cmd_str, req, opt) return res class ConfigCscope(ConfigBase): def __init__(self): ConfigBase.__init__(self, 'cscope') self.c_opt = [] def read_cs_files_common(self, filename): fl = [] config_file = os.path.join(self.c_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.c_flist = 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.c_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.c_flist) def get_config_file(self): config_file = 'seascope.opt' return os.path.join(self.c_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 == 'c_opt'): self.c_opt = line[1].split() cf.close() def write_seascope_opt(self): config_file = self.get_config_file() cf = open(config_file, 'w') cf.write('c_opt' + '=' + ' '.join(self.c_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 is_ready(self): return len(self.c_flist) > 0 class ProjectCscope(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectCscope() prj.feat = CscopeFeature() prj.conf = conf prj.qry = QueryCscope(prj.conf, prj.feat) return (prj) @staticmethod def prj_new(proj_args): 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_settings_update(self, proj_args): assert proj_args self.prj_update_conf(proj_args) return True class CsProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir, rq) self.name = 'cscope process' 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, feat): QueryBase.__init__(self) self.conf = conf self.feat = feat 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 = self.feat.cmd_str2id[cmd_str] if opt == None or opt == '': opt = [] else: opt = opt.split() pargs = [ 'cscope' ] + self.conf.c_opt + opt + [ '-L', '-d', '-' + str(cmd_id), req ] qsig = CsProcess(self.conf.c_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.c_opt + [ '-L' ] qsig = CsProcess(self.conf.c_dir, None).run_rebuild_process(pargs) return qsig def query_fl(self): fl = self.conf.get_proj_src_files() return fl def cs_is_open(self): return self.conf != None def cs_is_ready(self): return self.conf.is_ready() seascope-0.9+8a669e0e/src/backend/plugins/cscope/__init__.py000066400000000000000000000006541363245777100235770ustar00rootroot00000000000000# 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.9+8a669e0e/src/backend/plugins/gtags/000077500000000000000000000000001363245777100213125ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/backend/plugins/gtags/GtagsProject.py000066400000000000000000000067141363245777100242700ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, string, re from ..PluginBase import PluginFeatureBase, ProjectBase, ConfigBase, QueryBase from ..PluginBase import PluginProcess from ..CtagsCache import CtagsThread class GtagsFeature(PluginFeatureBase): def __init__(self): PluginFeatureBase.__init__(self) self.feat_desc = [ ['REF', '-r'], ['DEF', ''], #['<--', '2'], ['-->', '-r'], #[ ['TXT', '4'], ['GREP','-g'], ['FIL', '-P'], ['INC', '-g'], ['QDEF', ''], ['CTREE','12'], ['CLGRAPH', '13'], ['CLGRAPHD', '14'], ['FFGRAPH', '14'], ['UPD', '25'], ] self.ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], #['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] def query_dlg_cb(self, req, cmd_str, in_opt): if req != '' and in_opt['substring']: req = '.*' + req + '.*' opt = None if in_opt['ignorecase']: opt = '-i' res = (cmd_str, req, opt) return res class ConfigGtags(ConfigBase): def __init__(self): ConfigBase.__init__(self, 'gtags') class ProjectGtags(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectGtags() prj.feat = GtagsFeature() prj.conf = conf prj.qry = QueryGtags(prj.conf, prj.feat) return (prj) @staticmethod def prj_new(proj_args): d = proj_args[0] prj = ProjectGtags.prj_open(d) return None @staticmethod def prj_open(proj_path): conf = ConfigGtags() conf.proj_open(proj_path) prj = ProjectGtags._prj_new_or_open(conf) return (prj) class GtProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir, rq) self.name = 'gtags process' 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) CtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return None class QueryGtags(QueryBase): def __init__(self, conf, feat): QueryBase.__init__(self) self.conf = conf self.feat = feat 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 = self.feat.cmd_str2id[cmd_str] pargs = [ 'global', '-a', '--result=cscope', '-x' ] + opt if cmd_opt != '': pargs += [ cmd_opt ] pargs += [ '--', req ] qsig = GtProcess(self.conf.c_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.c_dir, 'GTAGS'))): pargs = [ 'global', '-u' ] else: pargs = [ 'gtags', '-i' ] qsig = GtProcess(self.conf.c_dir, None).run_rebuild_process(pargs) return qsig def query_fl(self): if not os.path.exists(os.path.join(self.conf.c_dir, 'GTAGS')): return [] pargs = [ 'global', '-P', '-a' ] qsig = GtProcess(self.conf.c_dir, None).run_query_fl(pargs) return qsig def gt_is_open(self): return self.conf != None def gt_is_ready(self): return self.conf.is_ready() seascope-0.9+8a669e0e/src/backend/plugins/gtags/__init__.py000066400000000000000000000007221363245777100234240ustar00rootroot00000000000000# 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.9+8a669e0e/src/backend/plugins/idutils/000077500000000000000000000000001363245777100216625ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/backend/plugins/idutils/IdutilsProject.py000066400000000000000000000101751363245777100252040ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys, os, string, re from ..PluginBase import PluginFeatureBase, ProjectBase, ConfigBase, QueryBase from ..PluginBase import PluginProcess from ..CtagsCache import CtagsThread class IdutilsFeature(PluginFeatureBase): def __init__(self): PluginFeatureBase.__init__(self) self.feat_desc = [ ['REF', ''], ['DEF', ''], #['<--', '2'], ['-->', '3'], #['TXT', '4'], ['GREP', ''], ['FIL', ''], ['INC', '8'], ['QDEF', ''], ['CTREE', '12'], ['CLGRAPH', '13'], ['CLGRAPHD','14'], ['FFGRAPH', '14'], ['UPD', '25'], ] self.ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], #['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] def query_dlg_cb(self, req, cmd_str, in_opt): opt = [] if cmd_str != 'TXT' and req != '' and in_opt['substring']: opt.append('substring') if cmd_str == 'FIL': req = '*' + req + '*' else: req = '.*' + req + '.*' if in_opt['ignorecase']: opt.append('ignorecase') res = (cmd_str, req, opt) return res class ConfigIdutils(ConfigBase): def __init__(self): ConfigBase.__init__(self, 'idutils') class ProjectIdutils(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectIdutils() prj.feat = IdutilsFeature() prj.conf = conf prj.qry = QueryIdutils(prj.conf, prj.feat) return (prj) @staticmethod def prj_new(proj_args): d = proj_args[0] prj = ProjectIdutils.prj_open(d) return prj @staticmethod def prj_open(proj_path): conf = ConfigIdutils() conf.proj_open(proj_path) prj = ProjectIdutils._prj_new_or_open(conf) return (prj) class IdProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir, rq) self.name = 'idutils process' def parse_result(self, text, sig): if self.cmd_str in ['GREP']: return PluginProcess.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 = [] 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 CtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return None class QueryIdutils(QueryBase): def __init__(self, conf, feat): QueryBase.__init__(self) self.conf = conf self.feat = feat 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'] if cmd_str in ['GREP']: return QueryBase.query(self, rquery) 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 == '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 ] qsig = IdProcess(self.conf.c_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 = os.getenv('SEASCOPE_IDUTILS_MKID_CMD', '').strip().split() if not len(pargs): pargs = [ 'mkid', '-s' ] qsig = IdProcess(self.conf.c_dir, None).run_rebuild_process(pargs) return qsig def query_fl(self): if not os.path.exists(os.path.join(self.conf.c_dir, 'ID')): return [] pargs = [ 'fnid', '-S', 'newline', '-f', 'ID' ] qsig = IdProcess(self.conf.c_dir, None).run_query_fl(pargs) return qsig def id_is_open(self): return self.conf != None def id_is_ready(self): return self.conf.is_ready() seascope-0.9+8a669e0e/src/backend/plugins/idutils/__init__.py000066400000000000000000000017401363245777100237750ustar00rootroot00000000000000# 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.9+8a669e0e/src/icons/000077500000000000000000000000001363245777100162505ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/icons/codeview.png000066400000000000000000000010721363245777100205630ustar00rootroot00000000000000‰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.9+8a669e0e/src/icons/copy.png000066400000000000000000000010251363245777100177260ustar00rootroot00000000000000‰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.9+8a669e0e/src/icons/cut.png000066400000000000000000000013441363245777100175530ustar00rootroot00000000000000‰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.9+8a669e0e/src/icons/find-replace.png000066400000000000000000000013621363245777100213110ustar00rootroot00000000000000‰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.9+8a669e0e/src/icons/go-jump.png000066400000000000000000000011231363245777100203310ustar00rootroot00000000000000‰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.9+8a669e0e/src/icons/paste.png000066400000000000000000000010071363245777100200700ustar00rootroot00000000000000‰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.9+8a669e0e/src/icons/redo.png000066400000000000000000000010561363245777100177110ustar00rootroot00000000000000‰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.9+8a669e0e/src/icons/save.png000066400000000000000000000010601363245777100177110ustar00rootroot00000000000000‰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.9+8a669e0e/src/icons/seascope.svg000066400000000000000000000075051363245777100206020ustar00rootroot00000000000000 Seascope image/svg+xml Seascope Anil Kumar Seascope logo http://seascope.googlecode.com S seascope-0.9+8a669e0e/src/icons/undo.png000066400000000000000000000010531363245777100177220ustar00rootroot00000000000000‰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.9+8a669e0e/src/tools/000077500000000000000000000000001363245777100162755ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/tools/ClassGraph.py000066400000000000000000000234371363245777100207070ustar00rootroot00000000000000#!/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 self.ct_opt_I_file = os.getenv('SEASCOPE_CTAGS_OPT_I_FILE') if self.ct_opt_I_file: if not os.path.isfile(self.ct_opt_I_file): self.ct_opt_I_file = None 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).encode()) out_data = out_data.decode() 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 -' if self.ct_opt_I_file: cmd += ' -I ' + self.ct_opt_I_file args = cmd.split() proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate('\n'.join(fl).encode()) out_data = out_data.decode() 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 = output.decode() output = re.split('\r?\n', output) except Exception as e: print('dir:', self.wdir, ':cmd:', args, ':', e, '\n', file=sys.stderr) 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('num %s classes(%s) = %d, truncating to %d.\n' % (s, sym, len(dclasses), self.width_limit), file=sys.stderr) 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('No %s classes for %s\n' % (s, sym_or_dname), file=sys.stderr) 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('saved', dot_svg, '\n', file=sys.stderr) 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.encode()) svg_data = svg_data.decode() if err_data and err_data.decode() != '': print(err_data, '\n', file=sys.stderr) #self.saveSvgFile(sym, svg_data) return svg_data except Exception as e: print('Failed to run:', ' '.join(args), '\n', file=sys.stderr) print(e, '\n', file=sys.stderr) 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('Specify -d', file=sys.stderr) sys.exit(-1) dname = options.code_dir if not os.path.exists(dname): print('"%s": does not exist' % dname, file=sys.stderr) 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('Please specify only one symbol', file=sys.stderr) sys.exit(-3) sym = args[0] # ptype ptype = options.prj_type if ptype: if not sym: print('-t option needs sepficfying symbol', file=sys.stderr) sys.exit(-4) if not os.path.isdir(dname): print('-t option needs codedir to be a directory', file=sys.stderr) 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.9+8a669e0e/src/tools/FileFuncGraph.py000077500000000000000000000167641363245777100213450ustar00rootroot00000000000000#!/usr/bin/env python3 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 as 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 -' opt_I_file = os.getenv('SEASCOPE_CTAGS_OPT_I_FILE') if opt_I_file and os.path.isfile(opt_I_file): ct_args += ' -I ' + opt_I_file 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.decode() 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() output = output.decode() #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('failed cmd:', cmd, ':', e, file=sys.stderr) 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(e, file=sys.stderr) 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.encode()) svg_data = svg_data.decode() if err_data and err_data.decode() != '': print(err_data, '\n', file=sys.stderr) #self.saveSvgFile(sym, svg_data) return svg_data except Exception as e: print('Failed to run:', ' '.join(args), '\n', file=sys.stderr) print('dotInput:', dotInput, '\n', file=sys.stderr) print(e, '\n', file=sys.stderr) 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('Specify one among -d or -p', file=sys.stderr) 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('Please specify only one symbol', file=sys.stderr) sys.exit(-2) sym = args[0] svg_data = None if options.code_dir: dname = options.code_dir if not os.path.exists(dname): print('"%s": does not exist' % dname, file=sys.stderr) sys.exit(-3) svg_data = ff_graph(dname, is_extern=is_extern) print(svg_data) seascope-0.9+8a669e0e/src/ui/000077500000000000000000000000001363245777100155525ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/ui/about.ui000066400000000000000000000337051363245777100172330ustar00rootroot00000000000000 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.9</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-2020 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="https://github.com/anilFree/seascope"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/anilFree/seascope</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.9+8a669e0e/src/ui/cscope_prj_settings.ui000066400000000000000000000164031363245777100221640ustar00rootroot00000000000000 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.9+8a669e0e/src/ui/debug.ui000066400000000000000000000037511363245777100172050ustar00rootroot00000000000000 dbg_main_window 0 0 514 394 Debug info... QTabWidget::Rounded 0 Info true 0 0 472 323 Version Not implemented yet seascope-0.9+8a669e0e/src/ui/filter.ui000066400000000000000000000077261363245777100174120ustar00rootroot00000000000000 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.9+8a669e0e/src/ui/find.ui000066400000000000000000000061371363245777100170400ustar00rootroot00000000000000 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.9+8a669e0e/src/ui/goto_line.ui000066400000000000000000000052041363245777100200710ustar00rootroot00000000000000 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.9+8a669e0e/src/ui/preferences.ui000066400000000000000000000137341363245777100204220ustar00rootroot00000000000000 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.9+8a669e0e/src/ui/proj_new.ui000066400000000000000000000044471363245777100177450ustar00rootroot00000000000000 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.9+8a669e0e/src/ui/proj_open.ui000066400000000000000000000050071363245777100201060ustar00rootroot00000000000000 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.9+8a669e0e/src/ui/project_settings.ui000066400000000000000000000106361363245777100215050ustar00rootroot00000000000000 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.9+8a669e0e/src/ui/query.ui000066400000000000000000000070111363245777100172550ustar00rootroot00000000000000 QueryDialog Qt::ApplicationModal 0 0 357 171 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.9+8a669e0e/src/view/000077500000000000000000000000001363245777100161075ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/view/CallView.py000066400000000000000000000123601363245777100201710ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.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)) 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)) if str(item.data(1, Qt.DisplayRole)) == '': 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)) 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.9+8a669e0e/src/view/ClassGraphView.py000066400000000000000000000157061363245777100213540ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.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, rq) self.name = 'call graph process' 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].encode())) #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('Specify -d', file=sys.stderr) sys.exit(-1) dname = options.code_dir if not os.path.exists(dname): print('"%s": does not exist' % dname, file=sys.stderr) 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('Please specify only one symbol', file=sys.stderr) sys.exit(-3) sym = args[0] # ptype ptype = options.prj_type if ptype: if not sym: print('-t option needs sepficfying symbol', file=sys.stderr) sys.exit(-4) if not os.path.isdir(dname): print('-t option needs codedir to be a directory', file=sys.stderr) 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('Failed to find "%s" in directory "%s"' % (p[1], dname), file=sys.stderr) 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.9+8a669e0e/src/view/CodeContextView.py000066400000000000000000000116351363245777100215410ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2013 dangbinghoo # All rights reserved. # # License: BSD import os import re import array from PyQt5 import QtWidgets, QtGui from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.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): 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.9+8a669e0e/src/view/CodemarkView.py000066400000000000000000000050511363245777100210420ustar00rootroot00000000000000#!/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("cm index ", i, " ", self.haystack[i], file=sys.stderr) ############################################################################# # # Basic unit test # ############################################################################# if __name__ == '__main__': cm = CodemarkManager() # # case 1, basic add, delete # print("Initial empty", file=sys.stderr) print("cm has ", cm.count(), "items (0)", file=sys.stderr) cm.append("file1", 100) cm.append("file2", 200) cm.append("file3", 300) print("cm has " , cm.count(), "items (3) ", file=sys.stderr) cm.delete("file1", 100) print("cm has " , cm.count(), "items (2)", file=sys.stderr) cm.delete("file2", 100) # not existed print("cm has " , cm.count(), "items (2)", file=sys.stderr) cm.delete_index(1) print("cm has " , cm.count(), "items (1)", file=sys.stderr) # # case 2, dump # for i in range(cm.count()): (f, l) = cm.get(i) print(f, " (#", l, ")", file=sys.stderr) # # case 3, duplicate # index = cm.append("file4", 400) print("index for file4 #400 is " , index, file=sys.stderr) index = cm.append("file4", 400) print("index for file4 #400 is " , index, " (again)", file=sys.stderr) print("cm has " , cm.count(), "items (2) ", file=sys.stderr) # # case 4, dump for eye examine # print("cm dump for final check", file=sys.stderr) cm.dump() seascope-0.9+8a669e0e/src/view/CscopeProjectUi.py000066400000000000000000000071671363245777100215350ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt5 import QtWidgets, QtGui, QtCore, uic from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * 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 CscopeProjectSettingsDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('ui/cscope_prj_settings.ui', self) self.pd_path_tbtn.setIcon(QFileIconProvider().icon(QFileIconProvider.Folder)) self.pd_src_list.setSelectionMode(QAbstractItemView.ExtendedSelection) self.pd_path_tbtn.clicked.connect(self.path_open_cb) self.pd_add_btn.clicked.connect(self.src_add_cb) self.pd_rem_btn.clicked.connect(self.src_rem_cb) self.accepted.connect(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, prj_type, proj_args): assert prj_type == 'cscope' 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.9+8a669e0e/src/view/DebugView.py000066400000000000000000000031761363245777100203510ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys import os import string from PyQt5 import QtWidgets, QtGui, QtCore, uic from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.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.9+8a669e0e/src/view/EdView.py000066400000000000000000000414351363245777100176530ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import re import array from PyQt5 import QtWidgets, QtGui from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * try: from PyQt5.Qsci import QsciScintilla, QsciScintillaBase from PyQt5.Qsci import QsciLexerCPP, QsciLexerJava from PyQt5.Qsci import QsciLexerPython, QsciLexerRuby from PyQt5.Qsci import QsciLexerBash, QsciLexerDiff, QsciLexerMakefile from PyQt5.Qsci import QsciLexerLua, QsciLexerSQL, QsciLexerTCL, QsciLexerTeX from PyQt5.Qsci import QsciLexerHTML, QsciLexerCSS from PyQt5.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], ] seascope_editor_tab_width = None try: seascope_editor_tab_width = int(os.getenv('SEASCOPE_EDITOR_TAB_WIDTH')) except: pass 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('b', (name + "\0").encode()) val_buff = array.array("b", (str(val) + "\0").encode()) 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('b', (name + "\0").encode()) val_buff = array.array("b", (str(0) + "\0").encode()) 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("b", ((' ' * sz) + "\0").encode()) 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")) ## set tab width if seascope_editor_tab_width: self.setTabWidth(seascope_editor_tab_width) 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 refresh_file(self, filename): assert filename == self.filename pos = self.getCursorPosition() self.open_file(filename) self.setCursorPosition(*pos) self.cursorPositionChanged.emit(*pos) 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 refresh_file(self): filename = self.get_filename() self.fcv.rerun(filename) self.ev.refresh_file(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): 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 list(range(self.count())) if type == 'left': return list(range(inx)) if type == 'right': return list(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 = list(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 refresh_file_cb(self): ed = self.currentWidget() if not ed: return ed.refresh_file() 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.9+8a669e0e/src/view/EdViewRW.py000066400000000000000000000072521363245777100201230ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import re from PyQt5 import QtWidgets, QtGui from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.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 refresh_file(self, filename): if self.isModified(): msg = 'Save changes before refresh ?' if DialogManager.show_yes_no(msg): self.save_file(self.filename) EditorView.refresh_file(self, filename) 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(self.text()) 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 = 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.9+8a669e0e/src/view/FileContextView.py000066400000000000000000000041721363245777100215440ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * from . 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.9+8a669e0e/src/view/FileFuncGraphView.py000066400000000000000000000165041363245777100217770ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.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, rq) self.name = 'call graph process' 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].encode())) #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('Specify one among -d or -p', file=sys.stderr) sys.exit(-1) if len(args): if len(args) != 1: print('Please specify a symbol', file=sys.stderr) sys.exit(-4) sym = args[0] if options.code_dir: dname = options.code_dir if not os.path.exists(dname): print('"%s": does not exist' % dname, file=sys.stderr) sys.exit(-2) if options.id_path: if not sym: print('-p option needs a symbol', file=sys.stderr) sys.exit(-3) id_path = os.path.normpath(options.id_path) if not os.path.exists(os.path.join(id_path, 'ID')): print('idutils project path does not exist', file=sys.stderr) 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.9+8a669e0e/src/view/FileView.py000066400000000000000000000176741363245777100202120ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.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 self.d = None # Tree view self.tmodel = QFileSystemModel() self.tmodel.directoryLoaded.connect(self.tmodel_dir_loaded) self.tmodel.setRootPath(QDir.rootPath()) self.tview = QTreeView() self.tview.setHeaderHidden(True) # For proper horizaontal scroll bar self.tview.setTextElideMode(Qt.ElideNone) self.tview.expanded.connect(self.tview_expanded_or_collapsed) self.tview.collapsed.connect(self.tview_expanded_or_collapsed) 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 tmodel_dir_loaded(self, path): self.tview.resizeColumnToContents(0) def tview_expanded_or_collapsed(self, inx): self.tview.resizeColumnToContents(0) def dir_name(self): return self.d 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.d = 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)) 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) self.lview.resizeColumnToContents(0) 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 set_tab_dir(self, t, d): if d == None or d == dir_prefix: t.reset_btn_cb() else: t.dir_reset(d) 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, '') self.set_tab_dir(t, d) 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 get_dir_view_list(self): dv_list = [] for t in self.dlist: d = t.dir_name() if d != dir_prefix: dv_list.append(d) return dv_list def open_dir_view(self, filename): d = filename if not os.path.isdir(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): old_dir_prefix = dir_prefix self.ft.add_files(flist) for t in self.dlist: d = t.dir_name() if d == old_dir_prefix: d = dir_prefix self.set_tab_dir(t, d) seascope-0.9+8a669e0e/src/view/ProjectUi.py000066400000000000000000000022721363245777100203700ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt5 import QtWidgets, QtGui, QtCore, uic from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * class ProjectSettingsDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('ui/project_settings.ui', self) def run_dialog(self, prj_type, prj_args): if prj_args: prj_dir = prj_args[0] self.pi_type_lbl.setText(prj_type) self.pi_path_lbl.setText(prj_dir) self.exec_() return None 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 proj_args = [d, None, None] return proj_args return None def show_settings_ui(prj_type, proj_args): dlg = None if prj_type == 'cscope': from . import CscopeProjectUi dlg = CscopeProjectUi.CscopeProjectSettingsDialog() else: dlg = ProjectSettingsDialog() return dlg.run_dialog(prj_type, proj_args) seascope-0.9+8a669e0e/src/view/ResView.py000066400000000000000000000172171363245777100200550ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import re from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.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)) 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: item.setHidden(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[1:]) def show_all_cb(self): for inx in range(self.topLevelItemCount()): item = self.topLevelItem(inx) item.setHidden(False) self.mark_tab_filtered(False) def remove_item_cb(self): item = self.itemFromIndex(self.last_minx) item.setHidden(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))) try: line = model.data(model.index(row, 2)) 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): 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.9+8a669e0e/src/view/__init__.py000066400000000000000000000004011363245777100202130ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD __all__ = ["CallView", "ClassGraphView", "FileFuncGraphView", "EdView", "FileView", "ResView", "ProjectUi"] def load_plugins(): from . import filecontext filecontext.load_plugins()seascope-0.9+8a669e0e/src/view/filecontext/000077500000000000000000000000001363245777100204335ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/view/filecontext/__init__.py000066400000000000000000000021111363245777100225370ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import re, os from PyQt5 import QtWidgets, QtGui, QtCore, uic from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * 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.9+8a669e0e/src/view/filecontext/plugins/000077500000000000000000000000001363245777100221145ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/view/filecontext/plugins/__init__.py000066400000000000000000000001121363245777100242170ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD seascope-0.9+8a669e0e/src/view/filecontext/plugins/ctags_view/000077500000000000000000000000001363245777100242475ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/view/filecontext/plugins/ctags_view/CtagsManager.py000066400000000000000000000127301363245777100271600ustar00rootroot00000000000000# 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 as e: if e.errno == errno.EINTR: continue raise def cmdForFile(f): #args = 'ctags -n -u --fields=+K -f - --extra=+q' #args = 'ctags -n -u --fields=+Ki -f -' args = 'ctags -n -u --fields=+K -f -' opt_I_file = os.getenv('SEASCOPE_CTAGS_OPT_I_FILE') if opt_I_file and os.path.isfile(opt_I_file): args += ' -I ' + opt_I_file 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( ['', 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.decode() 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): #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 -' opt_I_file = os.getenv('SEASCOPE_CTAGS_OPT_I_FILE') if opt_I_file and os.path.isfile(opt_I_file): args += ' -I ' + opt_I_file 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( ['', 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() out_data = out_data.decode() 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 list(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.9+8a669e0e/src/view/filecontext/plugins/ctags_view/CtagsView.py000066400000000000000000000141631363245777100265220ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.QtCore import * from . 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)) 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 list(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) p.setExpanded(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))) 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))) 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.9+8a669e0e/src/view/filecontext/plugins/ctags_view/__init__.py000066400000000000000000000004251363245777100263610ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os def name(): return 'ctags' def run_plugin(filename, parent): from . import CtagsView CtagsView.run(filename, parent) def description(): d = 'ctags description' return d priority = 500 seascope-0.9+8a669e0e/src/view/filecontext/plugins/generic_view/000077500000000000000000000000001363245777100245625ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/view/filecontext/plugins/generic_view/GenericView.py000066400000000000000000000045141363245777100273470ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PyQt5.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() res = res.decode() 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.9+8a669e0e/src/view/filecontext/plugins/generic_view/__init__.py000066400000000000000000000006031363245777100266720ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os def name(): return 'generic_cmd' def run_plugin(filename, parent, cmd=None): from . import GenericView GenericView.run(filename, parent, cmd=cmd) def description(): d = 'generic cmd description' return d def cmd_name(): from . import GenericView return GenericView.cmd_name() priority = 100 seascope-0.9+8a669e0e/src/web/000077500000000000000000000000001363245777100157125ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/web/BackendTool.py000077500000000000000000000062721363245777100204630ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2014 Anil Kumar # All rights reserved. # # License: BSD import os import backend import CtagsManager from collections import OrderedDict is_debug = os.getenv('SEASCOPE_WEB_DEBUG') g_proj_d = OrderedDict() def p_open(proj_path): bl = backend.plugin_guess(proj_path) if len(bl) == 0: msg = "Project '%s': No backend is interested" % proj_path print(msg) return None proj_type = bl[0] if len(bl) > 1: msg = "Project '%s': Many backends interested" % proj_path for b in be: msg += '\n\t' + b.name() msg += '\n\nGoing ahead with: ' + proj_type print(msg) print("Project '%s': using '%s' backend" % (proj_path, proj_type)) bp = backend.BProject() rc = bp.proj_open(proj_path, proj_type) if rc: return bp else: return None def find_prj(rd): pdir = rd.get('project', None) if not pdir: return None bp = g_proj_d.get(pdir, False) return bp def p_query(bp, rquery): return bp.proj_query(rquery) def p_query_fl(bp): return bp.proj_query_fl() def validate_op(rd): for r in ['cmd_type', 'cmd_str', 'req']: if r not in rd: return False return True def _run_op(rd): if is_debug: print('rd', rd) if not validate_op: return { 'err_data' : 'invalid request: validate_op failed' } cmd_type = rd['cmd_type'] if cmd_type == 'project_list': res = list(g_proj_d.keys()) outd = { 'res' : res } return outd if cmd_type == 'query': bp = find_prj(rd) if not bp: return { 'err_data' : 'failed to find project for query %s' % rd } if rd['cmd_str'] == 'FLIST': outd = p_query_fl(bp) res = [] res.append(['file', 'path']) for r in outd['res']: res.append([os.path.basename(r), r]) outd['res'] = res return outd if rd['cmd_str'] == 'FDATA': fname = rd['req'] pdir = bp.proj_dir() if not fname.startswith(pdir): return { 'err_data' : 'file %s not in project %s' % (fname, pdir)} try: data = open(fname).read() outd = { 'res' : [ data ] } return outd except: return { 'err_data' : 'failed to read file %s' % fname } if rd['cmd_str'] == 'FCTAGS': fname = rd['req'] if not fname.startswith(bp.proj_dir()): return [] try: data = CtagsManager.ct_query(rd['req']) outd = { 'res' : [data] } return outd except: pass rquery = { 'cmd' : rd['cmd_str'], 'req' : rd['req'], 'opt' : rd.get('opt', '').split(','), 'hint_file' : rd.get('hint_file', ''), } outd = p_query(bp, rquery) if is_debug: print('rquery', rquery) return outd return { 'err_data' : 'invalid request: unknown cmd_type=%s' % cmd_type } def run_op(rd): if is_debug: print('-' * 80) outd = _run_op(rd) if is_debug: print('-' * 80) if ('err_data' in outd) and outd['err_data']: print('==> ERR_DATA:', outd['err_data']) res = outd.get('res', None) if not res and 'out_data' in outd: res = outd['out_data'].splitlines() #if not rd['cmd_str'] == 'FDATA': #for r in res: #print r if is_debug: print('-' * 80) return outd def load_projects(plist): backend.load_plugins() for p in plist: bp = p_open(p) if not bp: return False global g_proj_d pdir = bp.proj_dir() g_proj_d[pdir] = bp if not len(g_proj_d): print('No projects') return False return True seascope-0.9+8a669e0e/src/web/CtagsManager.py000066400000000000000000000127301363245777100206230ustar00rootroot00000000000000# 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 as e: if e.errno == errno.EINTR: continue raise def cmdForFile(f): #args = 'ctags -n -u --fields=+K -f - --extra=+q' #args = 'ctags -n -u --fields=+Ki -f -' args = 'ctags -n -u --fields=+K -f -' opt_I_file = os.getenv('SEASCOPE_CTAGS_OPT_I_FILE') if opt_I_file and os.path.isfile(opt_I_file): args += ' -I ' + opt_I_file 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( ['', 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) err_data = err_data.decode() 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): #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 -' opt_I_file = os.getenv('SEASCOPE_CTAGS_OPT_I_FILE') if opt_I_file and os.path.isfile(opt_I_file): args += ' -I ' + opt_I_file 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( ['', 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() out_data = out_data.decode() 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 list(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.9+8a669e0e/src/web/ProcessMgr.py000077500000000000000000000012421363245777100203520ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2014 Anil Kumar # All rights reserved. # # License: BSD import sys import os import subprocess import threading class PluginProcess: def __init__(self, pargs): self.pargs = pargs self.proc = None self.res = { 'out_data' : None, 'err_data' : None, } def run(self): try: self.proc = subprocess.Popen(self.pargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out_data, err_data) = self.proc.communicate() self.res['out_data'] = out_data.decode() self.res['err_data'] = err_data.decode() except Exception as e: print('PluginProcess.run():', e) self.res['err_data'] = str(e) return self.res seascope-0.9+8a669e0e/src/web/SeascopeServer.py000066400000000000000000000052241363245777100212200ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2014 Anil Kumar # All rights reserved. # # License: BSD import sys import os import subprocess import threading import time import json import socket import signal import BackendTool from socketserver import ThreadingMixIn from http.server import HTTPServer from http.server import SimpleHTTPRequestHandler server_conf_js = None def setup_srvr_conf_js(host, port): global server_conf_js server_conf_js = '''var sinfo = { host: "%s", port: %s, }''' % (host, port) class ThreadingServer(ThreadingMixIn, HTTPServer): allow_reuse_address = True daemon_threads = True is_debug = os.getenv('SEASCOPE_WEB_DEBUG') class RequestHandler(SimpleHTTPRequestHandler): def parse_path(self): import urllib.parse p = urllib.parse.urlparse(self.path) if is_debug: print('path', p.path) if p.path.startswith('/'): path = p.path if path == '/': path = '/h.html' if path == '/js/server_conf.js': self.reply_to_GET(server_conf_js, 'text/javascript'); return None wp = 'www' + path if os.path.exists(wp): data = open(wp).read() cont_type = 'text/html' if p.path.endswith('.js'): cont_type = 'text/javascript' self.reply_to_GET(data, cont_type); return None if p.path != '/q': if is_debug: print('not /q instead', p.path) return if is_debug: print('p.query', p.query) qd = urllib.parse.parse_qs(p.query) for k in list(qd.keys()): v = qd[k] if len(v) == 0: print('len(v) == 0', k, v) continue qd[k] = v[-1] if is_debug: print('qd', qd) return qd def reply_to_GET(self, qres, cont_type): rh = self rh.send_response(200) #rh.send_header('Content-type', 'text/plain') rh.send_header('Content-type', cont_type) rh.send_header('Content-length', len(qres)) rh.end_headers() rh.wfile.write(qres) def do_GET(self): qd = self.parse_path() if not qd: return outd = BackendTool.run_op(qd) try: data = json.dumps(outd, ensure_ascii=False) if 'callback' in qd: data = '%s(%s);' % (qd['callback'], data) self.reply_to_GET(data, 'application/json') except Exception as e: print('qd', qd) print('outd', outd) print(e) data = e return def start_server(host, port): setup_srvr_conf_js(host, port) print('starting server at http://%s:%s' % (host, port)) try: ts = ThreadingServer((host, port), RequestHandler) def signal_handler(signal, frame): ts.socket.close() print('got signal %s, exiting' % signal) os._exit(0) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) ts.serve_forever() except Exception as e: print(e) sys.exit(-1) print('exiting') seascope-0.9+8a669e0e/src/web/SeascopeWeb.py000077500000000000000000000017311363245777100204710ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2014 Anil Kumar # All rights reserved. # # License: BSD import sys sys.dont_write_bytecode = True import os import socket import BackendTool import SeascopeServer def start(plist, host, port): if not BackendTool.load_projects(plist): sys.exit(-1) SeascopeServer.start_server(host, port) if __name__ == '__main__': import optparse usage = "usage: %prog [options] [project_path ...]" op = optparse.OptionParser(usage=usage) op.add_option("-H", "--host", dest="host", default="127.0.0.1", help="Host") op.add_option("-P", "--port", dest="port", type='int', default=8650, help="Port") (options, args) = op.parse_args() if options.port > 65535: print('options.port > 65535') sys.exit(-1) plist = [] for p in args: if not os.path.isdir(p): print('%p is not a directory') sys.exit(-2) plist.append(os.path.abspath(p)) #options.host = socket.gethostname() start(plist, options.host, options.port) seascope-0.9+8a669e0e/src/web/backend/000077500000000000000000000000001363245777100173015ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/web/backend/__init__.py000066400000000000000000000050771363245777100214230ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re 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') def plugin_list(): return backend_plugins def plugin_guess(proj_path): bi = [] for p in backend_plugins: if p.is_your_prj(proj_path): bi.append(p.name()) return bi class BProject: def __init__(self): self.prj = None def proj_new_open_app_cb(self): self.prj.prj_feature_setup() def proj_close_app_cb(self): pass def _proj_new_open(self): self.proj_new_open_app_cb() def proj_new(self, bname, proj_args): b = backend_dict[bname] assert not self.prj prj = b.project_class().prj_new(proj_args) if prj: _proj_new_open() return self.prj != None def proj_open(self, proj_path, proj_type): b = backend_dict[proj_type] self.prj = b.project_class().prj_open(proj_path) if self.prj: self._proj_new_open() return self.prj != None def proj_close(self): self.prj.prj_close() self.prj = None from .plugins import CtagsCache CtagsCache.flush() self.proj_close_app_cb() def proj_is_open(self): return self.prj != None def proj_name(self): return self.prj.prj_name() if self.prj else None def proj_dir(self): return self.prj.prj_dir() if self.prj else None def proj_src_files(self): return self.prj.prj_src_files() def proj_conf(self): return self.prj.prj_conf() def proj_settings_get(self): return self.prj.prj_settings_get() def proj_settings_update(proj_args): return self.prj.prj_settings_update(proj_args) def proj_is_ready(self): return self.prj.prj_is_ready() def proj_query(self, rquery): return self.prj.prj_query(rquery) def proj_rebuild(self): return self.prj.prj_rebuild() def proj_query_fl(self): return self.prj.prj_query_fl() def proj_type(self): return self.prj.prj_type() def proj_feature(self): return self.prj.prj_feature() seascope-0.9+8a669e0e/src/web/backend/plugins/000077500000000000000000000000001363245777100207625ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/web/backend/plugins/CtagsCache.py000066400000000000000000000165261363245777100233330ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, re, subprocess from datetime import datetime #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() #out_data = out_data.decode() #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: def __init__(self, sig): self.sig = sig self.ct_dict = {} def _finished_cb(self): #print 'CtagsThread.finished', len(self.ct_dict) ct_cache_update(self.ct_dict) self.ct_dict.clear() self.ct_dict = None self.res = self.parse_result(self.res, self.sig) 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).encode()) out_data = out_data.decode() 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 -' opt_I_file = os.getenv('SEASCOPE_CTAGS_OPT_I_FILE') if opt_I_file and os.path.isfile(opt_I_file): cmd += ' -I ' + opt_I_file args = cmd.split() proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate('\n'.join(self.file_list).encode()) out_data = out_data.decode() 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() g_ct = ct_cache flist = set() for line in self.res: if line[0] in self.cond_list: if line[1] not in g_ct: flist.add(line[1]) else: self.ct_dict[line[1]] = g_ct[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.run() return self.res 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 self._finished_cb() 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 def parse_result(self, res, sig): res = self._filter_res(res, sig) return res ct_cache = {} def ct_cache_update(d): # this is atomic ct_cache.update(d) def flush(): #print 'flushing ctags cache...' global ct_cache ct_cache = {} import threading import random import gc ct_flush_thread = None def flush_ct_cache(): global ct_cache global ct_flush_thread n = int(0.8 * len(ct_cache)) #print len(ct_cache) #print "Drop 25 percent: %s -> %s" % (len(ct_cache), n); new_ct_cache = {} for k in random.sample(ct_cache, n): new_ct_cache[k] = ct_cache[k] ct_cache = new_ct_cache gc.collect() ct_flush_thread = threading.Timer(10 * 60, flush_ct_cache) ct_flush_thread.start() flush_ct_cache() seascope-0.9+8a669e0e/src/web/backend/plugins/PluginBase.py000066400000000000000000000240561363245777100233740ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, re import copy import subprocess def NOT_IMPLEMENTED(n, f): msg = '%s: %s: Not implemeted' % (n, f) print(msg) assert false from . import CtagsCache is_seascope_debug = os.getenv('SEASCOPE_DEBUG') cmd_table_master = [ [ 'REF', ['&References', 'Ctrl+0'], ['References to' ] ], [ 'DEF', ['&Definitions', 'Ctrl+1'], ['Definition of' ] ], [ '<--', ['&Called Functions', 'Ctrl+2'], ['Functions called by' ] ], [ '-->', ['C&alling Functions', 'Ctrl+3'], ['Functions calling' ] ], [ 'TXT', ['Find &Text', 'Ctrl+4'], ['Find text' ] ], [ 'GREP', ['Find &Egrep', 'Ctrl+5'], ['Find egrep pattern' ] ], [ 'FIL', ['Find &File', 'Ctrl+7'], ['Find files' ] ], [ 'INC', ['&Include/Import', 'Ctrl+8'], ['Find include/import' ] ], [ '---', [None, ], None ], [ 'QDEF', ['&Quick Definition', 'Ctrl+]'], None ], [ 'CTREE', ['Call Tr&ee', 'Ctrl+\\'], ['Call tree' ] ], [ '---', [None, ], None ], [ 'CLGRAPH', ['Class &Graph', 'Ctrl+:'], ['Class graph' ] ], [ 'CLGRAPHD', ['Class Graph Dir', 'Ctrl+;'], ['Class graph dir' ] ], [ 'FFGRAPH', ['File Func Graph', 'Ctrl+^'], ['File Func graph dir' ] ], [ '---', [None, ], None ], [ 'UPD', ['Re&build Database', None ], None ], ] class PluginFeatureBase: def __init__(self): self.clgraph_query_args = [ ['CLGRAPH', 'D', 'Derived classes' ], ['CLGRAPH', 'B', 'Base classes' ], ] self.clgraph_query_args = [ ['CLGRAPH', 'D', 'Derived classes' ], ['CLGRAPH', 'B', 'Base classes' ], ] self.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'] ] def setup(self): feat_cmds = [ d[0] for d in self.feat_desc ] ct = copy.deepcopy(cmd_table_master) self.cmd_table = [ t for t in ct if t[0] in feat_cmds or t[0] == '---' ] self.menu_cmd_list = [ [c[0]] + c[1] for c in self.cmd_table ] self.cmd_str2id = {} self.cmd_str2qstr = {} self.cmd_qstr2str = {} for c in self.feat_desc: self.cmd_str2id[c[0]] = c[1] for c in self.cmd_table: if c[2] != None: self.cmd_str2qstr[c[0]] = c[2][0] self.cmd_qstr2str[c[2][0]] = c[0] # python 2.7 #self.cmd_str2id = { c[0]:c[1] for c in self.feat_desc } #self.cmd_str2qstr = { c[0]:c[2][0] for c in self.cmd_table if c[1] } #self.cmd_qstr2str = { c[2][0]:c[0] for c in self.cmd_table if c[1] } self.cmd_qstrlist = [ c[2][0] for c in self.cmd_table if c[2] ] class ProjectBase: prj = None qry = None def __init__(self): self.feat = None def prj_close(self): if (self.conf != None): self.conf.proj_close() self.conf = None def prj_dir(self): return self.conf.c_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_show_settings(self, proj_args): NOT_IMPLEMENTED(__name__, __func__) def prj_settings(self, proj_args): NOT_IMPLEMENTED(__name__, __func__) def prj_feature_setup(self): self.feat.setup() def prj_query(self, rquery): return self.qry.query(rquery) def prj_rebuild(self): return self.qry.rebuild() def prj_query_fl(self): return self.qry.query_fl() def prj_type(self): return self.conf.prj_type def prj_feature(self): return self.feat def prj_settings_get(self): proj_args = self.prj_conf() return proj_args def prj_settings_update(self, proj_args): NOT_IMPLEMENTED(__name__, __func__) return class ConfigBase: def __init__(self, ptype): self.prj_type = ptype self.c_dir = '' self.c_opt = '' self.c_flist = [] def get_proj_name(self): return os.path.split(self.c_dir)[1] def get_proj_src_files(self): fl = self.c_flist return fl def get_proj_conf(self): return (self.c_dir, self.c_opt, self.c_flist) def read_config(self): pass def write_config(self): pass def proj_start(self): pass def proj_open(self, proj_path): self.c_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.c_dir, self.c_opt, self.c_flist) = proj_args self.write_config() self.proj_start() def proj_close(self): pass def is_ready(self): return True @staticmethod def prepare_menu(menubar): pass class QueryBase: @staticmethod def prepare_menu(menubar): pass def __init__(self): pass def query(self, rquery): cmd_str = rquery['cmd'] req = rquery['req'] opt = rquery['opt'] if opt == None: opt = [] pargs = [] if cmd_str == 'GREP': pargs = ['grep', '-E', '-R', '-n', '-I'] pargs += [ '--', req ] pargs += [self.conf.c_dir] else: assert(false) return None qsig = PluginProcess(self.conf.c_dir, [cmd_str, req]).run_query_process(pargs, req, rquery) return qsig def rebuild(): NOT_IMPLEMENTED(__name__, __func__) def conf_is_open(self): return self.conf != None def conf_is_ready(self): return self.conf.is_ready() class QueryUiBase: def __init__(self): pass class QuerySignal: def __init__(self): pass 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) class PluginProcessBase: proc_list = [] def __init__(self, wdir): self.wdir = wdir self.proc = None self.outd = {} PluginProcess.proc_list.append(self) self.is_rebuild = False self.is_query_fl = False self.sig = QuerySignal() def _cleanup(self): PluginProcess.proc_list.remove(self) e = self.outd['err_data'] if e: s = '' + self.p_cmd + '

' + '

'.join(e.splitlines()) print('s') r = self.outd['err_data'] if r: s = '' + self.p_cmd + '

Summary

' + r print('s') def run_process(self, pargs): if is_seascope_debug: print(self.p_cmd) try: self.proc = subprocess.Popen(pargs, cwd=self.wdir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (out_data, err_data) = self.proc.communicate() print('ANIL2 %s' % out_data.decode()) print('ANIL %s' % out_data) self.outd['out_data'] = out_data.decode() self.outd['err_data'] = err_data.decode() #rc = self.proc.returncode #if rc: #print 'PluginProcess.run(): returncode', rc #self.outd['out_data'] = None #self.outd['err_data'] = str(pargs), 'exited with returncode %s' % rc except Exception as e: print('PluginProcess.run():', e) self.outd['out_data'] = None self.outd['err_data'] = str(e) self._finished_cb() def run_query_process(self, pargs, sym, rquery=None): self.sig.sym = sym self.sig.rquery = rquery self.p_cmd = ' '.join(pargs) self.run_process(pargs) return self.outd def _finished_cb(self): if 'out_data' in self.outd: #print 'output', res #print 'cmd:', self.p_cmd res = self.outd['out_data'] self.outd['out_data'] if self.is_rebuild: pass elif self.is_query_fl: res = self.parse_query_fl(res) else: # XXX result_dbg try: res = self.parse_result(res, self.sig) res = self.sig.relevancy_sort(res); except Exception as e: print(e) res = [['', '', '', 'error while parsing output of: ' + self.p_cmd]] self.outd['res'] = res self._cleanup() def run_rebuild_process(self, pargs): self.is_rebuild = True self.p_cmd = ' '.join(pargs) self.run_process(pargs) CtagsCache.flush() return self.outd def run_query_fl(self, pargs): self.is_query_fl = True self.p_cmd = ' '.join(pargs) self.run_process(pargs) return self.outd def parse_query_fl(self, text): fl = [] for f in re.split('\r?\n', text.strip()): if f == '': continue fl.append(os.path.join(self.wdir, f)) return fl class PluginProcess(PluginProcessBase): def __init__(self, wdir, rq): PluginProcessBase.__init__(self, wdir) 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) res = [] if self.cmd_str == 'GREP': for line in text: if line == '': continue line = [''] + line.split(':', 2) res.append(line) else: assert(false) res.append(['', '', '', 'PluginProcess.parse_result: FAILED']) return res res = CtagsCache.CtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return res 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') res = PluginProcess('.').run_query_process(['ls'], 'ls') #res = PluginProcess('/home/anil/prj/ss/lin').run_query_process(['cscope', '-q', '-k', '-L', '-d', '-0', 'vdso'], 'ls') print('res', res) seascope-0.9+8a669e0e/src/web/backend/plugins/__init__.py000066400000000000000000000001111363245777100230640ustar00rootroot00000000000000# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD seascope-0.9+8a669e0e/src/web/backend/plugins/cscope/000077500000000000000000000000001363245777100222365ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/web/backend/plugins/cscope/CscopeProject.py000066400000000000000000000110011363245777100253440ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, string, re from ..PluginBase import PluginFeatureBase, ProjectBase, ConfigBase, QueryBase from ..PluginBase import PluginProcess class CscopeFeature(PluginFeatureBase): def __init__(self): PluginFeatureBase.__init__(self) self.feat_desc = [ ['REF', '0'], ['DEF', '1'], ['<--', '2'], ['-->', '3'], ['TXT', '4'], ['GREP','5'], ['FIL', '7'], ['INC', '8'], ['QDEF', '11'], ['CTREE','12'], ['CLGRAPH', '13'], ['CLGRAPHD', '14'], ['FFGRAPH', '14'], ['UPD', '25'], ] self.ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], ['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] class ConfigCscope(ConfigBase): def __init__(self): ConfigBase.__init__(self, 'cscope') self.c_opt = [] def read_cs_files_common(self, filename): fl = [] config_file = os.path.join(self.c_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.c_flist = 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.c_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.c_flist) def get_config_file(self): config_file = 'seascope.opt' return os.path.join(self.c_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 == 'c_opt'): self.c_opt = line[1].split() cf.close() def write_seascope_opt(self): config_file = self.get_config_file() cf = open(config_file, 'w') cf.write('c_opt' + '=' + ' '.join(self.c_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 is_ready(self): return len(self.c_flist) > 0 class ProjectCscope(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectCscope() prj.feat = CscopeFeature() prj.conf = conf prj.qry = QueryCscope(prj.conf, prj.feat) return (prj) @staticmethod def prj_new(proj_args): 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_settings_update(self, proj_args): assert proj_args self.prj_update_conf(proj_args) return True class CsProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir, rq) self.name = 'cscope process' 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, feat): QueryBase.__init__(self) self.conf = conf self.feat = feat 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 = self.feat.cmd_str2id[cmd_str] if opt == None: opt = [] opt_args = [] if 'substring' in opt: req = '.*' + req + '.*' if 'ignorecase' in opt: opt_args += ['-C']; pargs = [ 'cscope' ] + self.conf.c_opt + opt_args + [ '-L', '-d', '-' + str(cmd_id), req ] qsig = CsProcess(self.conf.c_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.c_opt + [ '-L' ] qsig = CsProcess(self.conf.c_dir, None).run_rebuild_process(pargs) return qsig def query_fl(self): fl = self.conf.get_proj_src_files() return fl def cs_is_open(self): return self.conf != None def cs_is_ready(self): return self.conf.is_ready() seascope-0.9+8a669e0e/src/web/backend/plugins/cscope/__init__.py000066400000000000000000000006541363245777100243540ustar00rootroot00000000000000# 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.9+8a669e0e/src/web/backend/plugins/gtags/000077500000000000000000000000001363245777100220675ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/web/backend/plugins/gtags/GtagsProject.py000066400000000000000000000065201363245777100250400ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, string, re from ..PluginBase import PluginFeatureBase, ProjectBase, ConfigBase, QueryBase from ..PluginBase import PluginProcess from ..CtagsCache import CtagsThread class GtagsFeature(PluginFeatureBase): def __init__(self): PluginFeatureBase.__init__(self) self.feat_desc = [ ['REF', '-r'], ['DEF', ''], #['<--', '2'], ['-->', '-r'], #[ ['TXT', '4'], ['GREP','-g'], ['FIL', '-P'], ['INC', '-g'], ['QDEF', ''], ['CTREE','12'], ['CLGRAPH', '13'], ['CLGRAPHD', '14'], ['FFGRAPH', '14'], ['UPD', '25'], ] self.ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], #['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] class ConfigGtags(ConfigBase): def __init__(self): ConfigBase.__init__(self, 'gtags') class ProjectGtags(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectGtags() prj.feat = GtagsFeature() prj.conf = conf prj.qry = QueryGtags(prj.conf, prj.feat) return (prj) @staticmethod def prj_new(proj_args): d = proj_args[0] prj = ProjectGtags.prj_open(d) return None @staticmethod def prj_open(proj_path): conf = ConfigGtags() conf.proj_open(proj_path) prj = ProjectGtags._prj_new_or_open(conf) return (prj) class GtProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir, rq) self.name = 'gtags process' 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) res = CtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return res class QueryGtags(QueryBase): def __init__(self, conf, feat): QueryBase.__init__(self) self.conf = conf self.feat = feat 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 = [] opt_args = [] if 'substring' in opt: req = '.*' + req + '.*' if 'ignorecase' in opt: opt_args += ['-i'] cmd_opt = self.feat.cmd_str2id[cmd_str] pargs = [ 'global', '-a', '--result=cscope', '-x' ] + opt_args if cmd_opt != '': pargs += [ cmd_opt ] pargs += [ '--', req ] qsig = GtProcess(self.conf.c_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.c_dir, 'GTAGS'))): pargs = [ 'global', '-u' ] else: pargs = [ 'gtags', '-i' ] qsig = GtProcess(self.conf.c_dir, None).run_rebuild_process(pargs) return qsig def query_fl(self): if not os.path.exists(os.path.join(self.conf.c_dir, 'GTAGS')): return [] pargs = [ 'global', '-P', '-a' ] qsig = GtProcess(self.conf.c_dir, None).run_query_fl(pargs) return qsig def gt_is_open(self): return self.conf != None def gt_is_ready(self): return self.conf.is_ready() seascope-0.9+8a669e0e/src/web/backend/plugins/gtags/__init__.py000066400000000000000000000007221363245777100242010ustar00rootroot00000000000000# 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.9+8a669e0e/src/web/backend/plugins/idutils/000077500000000000000000000000001363245777100224375ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/web/backend/plugins/idutils/IdutilsProject.py000066400000000000000000000104211363245777100257530ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys, os, string, re from ..PluginBase import PluginFeatureBase, ProjectBase, ConfigBase, QueryBase from ..PluginBase import PluginProcess from ..CtagsCache import CtagsThread class IdutilsFeature(PluginFeatureBase): def __init__(self): PluginFeatureBase.__init__(self) self.feat_desc = [ ['REF', ''], ['DEF', ''], #['<--', '2'], ['-->', '3'], #['TXT', '4'], ['GREP', ''], ['FIL', ''], ['INC', '8'], ['QDEF', ''], ['CTREE', '12'], ['CLGRAPH', '13'], ['CLGRAPHD','14'], ['FFGRAPH', '14'], ['UPD', '25'], ] self.ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], #['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] def query_dlg_cb(self, req, cmd_str, in_opt): opt = [] if cmd_str != 'TXT' and req != '' and in_opt['substring']: opt.append('substring') if cmd_str == 'FIL': req = '*' + req + '*' else: req = '.*' + req + '.*' if in_opt['ignorecase']: opt.append('ignorecase') res = (cmd_str, req, opt) return res class ConfigIdutils(ConfigBase): def __init__(self): ConfigBase.__init__(self, 'idutils') class ProjectIdutils(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectIdutils() prj.feat = IdutilsFeature() prj.conf = conf prj.qry = QueryIdutils(prj.conf, prj.feat) return (prj) @staticmethod def prj_new(proj_args): d = proj_args[0] prj = ProjectIdutils.prj_open(d) return prj @staticmethod def prj_open(proj_path): conf = ConfigIdutils() conf.proj_open(proj_path) prj = ProjectIdutils._prj_new_or_open(conf) return (prj) class IdProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir, rq) self.name = 'idutils process' def parse_result(self, text, sig): if self.cmd_str in ['GREP']: return PluginProcess.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 = [] 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 res = CtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return res idutils_lid_cmd = os.getenv('SEASCOPE_IDUTILS_LID_CMD', 'lid') class QueryIdutils(QueryBase): def __init__(self, conf, feat): QueryBase.__init__(self) self.conf = conf self.feat = feat 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'] if cmd_str in ['GREP']: return QueryBase.query(self, rquery) req = rquery['req'] opt = rquery['opt'] if opt == None: opt = [] pargs = [idutils_lid_cmd, '-R', 'grep'] if cmd_str == 'FIL': pargs = ['fnid', '-S', 'newline'] #elif cmd_str == 'TXT': #pargs += ['-l'] elif cmd_str in ['-->', '<--']: pargs += ['-l'] if 'substring' in opt: if cmd_str == 'FIL': req = '*' + req + '*' else: req = '.*' + req + '.*' #pargs += ' -s' if 'ignorecase' in opt: if cmd_str == 'FIL': pass else: pargs += ['-i'] pargs += [ '--', req ] qsig = IdProcess(self.conf.c_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 = os.getenv('SEASCOPE_IDUTILS_MKID_CMD', '').strip().split() if not len(pargs): pargs = [ 'mkid', '-s' ] qsig = IdProcess(self.conf.c_dir, None).run_rebuild_process(pargs) return qsig def query_fl(self): if not os.path.exists(os.path.join(self.conf.c_dir, 'ID')): return [] pargs = [ 'fnid', '-S', 'newline', '-f', 'ID' ] qsig = IdProcess(self.conf.c_dir, None).run_query_fl(pargs) return qsig def id_is_open(self): return self.conf != None def id_is_ready(self): return self.conf.is_ready() seascope-0.9+8a669e0e/src/web/backend/plugins/idutils/__init__.py000066400000000000000000000017371363245777100245600ustar00rootroot00000000000000# 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.9+8a669e0e/src/web/www/000077500000000000000000000000001363245777100165365ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/web/www/h.html000066400000000000000000000061511363245777100176560ustar00rootroot00000000000000

seascope-0.9+8a669e0e/src/web/www/images/000077500000000000000000000000001363245777100200035ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/web/www/images/seascope.svg000066400000000000000000000075341363245777100223370ustar00rootroot00000000000000 Seascope image/svg+xml Seascope Anil Kumar Seascope logo http://seascope.googlecode.com S seascope-0.9+8a669e0e/src/web/www/js/000077500000000000000000000000001363245777100171525ustar00rootroot00000000000000seascope-0.9+8a669e0e/src/web/www/js/about_dlg.js000066400000000000000000000027451363245777100214600ustar00rootroot00000000000000function about_dlg_show() { var sym = ed_get_cur_word(); var Y = document['dlg_about_y']; var qpanel = document['dlg_about_p']; qpanel.show(); } YUI().use("panel", function (Y) { var body = '' + '' + '' + '' + '' + '
' + '' + '' + ' Seascope 0.9+ ' + '

A graphical user interface for idutils, cscope and gtags.

' + '

Copyright � 2010-2020 Anil Kumar

' + '

https://github.com/anilFree/seascope

' + '
'; var qpanel = new Y.Panel({ bodyContent: body, zIndex : 6, centered : true, modal : true, render : '#aboutPanel', buttons: [ { value : 'Ok', section: Y.WidgetStdMod.FOOTER, isDefault: true, action : function (e) { qpanel.hide(); } }, ] }); qpanel.hide(); document['dlg_about_y'] = Y; document['dlg_about_p'] = qpanel; }); seascope-0.9+8a669e0e/src/web/www/js/ed_tabs.js000066400000000000000000000364241363245777100211220ustar00rootroot00000000000000function ed_ct_resize(t, is_sel) { var cbox = t.get('panelNode'); var ed_tv = document['ed_tv']; var w = ed_tv.get('width'); w = Math.floor(w * 0.25); var lh = cbox.ancestor().ancestor().one('.yui3-tabview-list').get('clientHeight'); var h = ed_tv.get('height') - lh; if (is_sel) { if (cbox['g_table_h'] == h && cbox['g_table_w'] == w) { return; } } cbox['g_table_h'] = h cbox['g_table_w'] = w var table = cbox['g_table']; var dv = cbox['g_dv']; table.draw(dv, { width: w, height: h, page : 'enable', pageSize : 200, }); } function ed_ace_resize(t, is_sel) { var cbox = t.get('panelNode'); var ed_tv = document['ed_tv']; // var w = ed_tv.get('width') - 15; // var lh = cbox.ancestor().ancestor().one('.yui3-tabview-list').get('clientHeight'); // var h = ed_tv.get('height') - lh - 20; var editor = cbox['a_ed']; editor.resize(); } function ed_tv_resize(e) { var ed_tv = document['ed_tv']; if (!ed_tv.size()) { return; } var t = ed_tv.get('selection'); if (!t) { return; } ed_ct_resize(t); ed_ace_resize(t); } function ed_tv_resize_sel(e) { var ed_tv = document['ed_tv']; if (!ed_tv.size()) { return; } var t = ed_tv.get('selection'); if (!t) { return; } ed_ct_resize(t, true); ed_ace_resize(t, true); } function ed_get_cur_word() { var ed_tv = document['ed_tv']; if (!ed_tv.size()) { return ''; } //var t = ed_tv.get('activeDescendant'); var t = ed_tv.get('selection'); var cbox = t.get('panelNode'); var editor = cbox['a_ed']; var word = editor.getCopyText(); //word = word.replace(/^\s+|\s+$/g, ''); if (!word) { var pos = editor.getCursorPosition(); word = editor.getSession().getLine(pos.row); function is_word_char(c) { if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '_')) { return true; } return false; } var linx = pos.column; while(linx > 0 && is_word_char(word.charAt(linx - 1))) { linx--; } var rinx = pos.column; while(rinx < word.length && is_word_char(word.charAt(rinx))) { rinx++; } word = word.slice(linx, rinx); } return (word); } function ed_get_cur_file() { var ed_tv = document['ed_tv']; if (!ed_tv.size()) { return ''; } //var t = ed_tv.get('activeDescendant'); var t = ed_tv.get('selection'); if (!t) { return null; } return t['ed_file']; } function createCtTable(t) { var cbox = t.get('panelNode'); var ctNode = cbox.one('#ctTbl'); //confirm(ctNode); if (ctNode) { ctNode = ctNode.getDOMNode(); } if (!ctNode) { return; } var dt = new google.visualization.DataTable(); dt.addColumn('string', 'name'); dt.addColumn('number', 'line'); dt.addColumn('string', 'type'); dt.addRows(1); dt.setCell(0, 0, 'fetching ctags...'); var dv = new google.visualization.DataView(dt); var table = new google.visualization.Table(ctNode); cbox['g_dt'] = dt; cbox['g_dv'] = dv; cbox['g_table'] = table; var ed_tv = document['ed_tv']; ed_ct_resize(t); google.visualization.events.addListener(table, 'select', function() { var sel = table.getSelection() if (sel.length == 0) { return } var row = sel[0].row; var line = cbox['g_dv'].getValue(row, 1); var editor = cbox['a_ed']; editor.gotoLine(line); editor.focus(); }); } function populateCtTable(t, res) { var cbox = t.get('panelNode'); var table = cbox['g_table']; var dt = cbox['g_dt']; dt.removeRow(0); for (var i = 0; i < res.length; i++) { var r = res[i]; dt.addRow([r[0], parseInt(r[1]), r[2]]); } // var ed_tv = document['ed_tv']; ed_ct_resize(t); } function ed_ct_line_change(t, line) { var cbox = t.get('panelNode'); var table = cbox['g_table']; var dv = cbox['g_dv']; function line_val(dv, inx) { return dv.getValue(inx, 1); } // confirm('ed_ct_line_change ' + line); var num_rows = dv.getNumberOfRows(); if (num_rows == 0) { return; } var inx; var sel = table.getSelection(); if (sel.length) { inx = sel[0].row; } else { inx = 0; } if (line_val(dv, inx) == line) { return; } if (line_val(dv, inx) < line) { while (inx + 1 < num_rows) { if (line_val(dv, inx + 1) > line) { break; } inx++; } } else { while (inx - 1 >= 0) { inx--; if (line_val(dv, inx) <= line) { break; } } } table.setSelection([{row:inx, col:null}]); // confirm('inx = ' + inx); } function focusAceEditor(cbox, res, line) { var editor = cbox['a_ed']; if (editor) { editor.focus(); } } function setAceEditorText(t, res, line) { var cbox = t.get('panelNode'); var editor = cbox['a_ed']; var file = t['ed_file']; var fp = file.split('.') if (fp.length > 1) { var sfx = fp[fp.length - 1]; if (['c', 'cpp', 'c++', 'h'].indexOf(sfx) >= 0) { editor.getSession().setMode("ace/mode/c_cpp"); } else if (['java'].indexOf(sfx) >= 0) { editor.getSession().setMode("ace/mode/java"); } else if (['py'].indexOf(sfx) >= 0) { editor.getSession().setMode("ace/mode/python"); } else if (['tin', 'tac', 'itin'].indexOf(sfx) >= 0) { editor.getSession().setMode("ace/mode/c_cpp"); } } else { editor.getSession().setMode("ace/mode/c_cpp"); } editor.getSession().setTabSize(8); editor.setValue(res); editor.getSession().selection.on('changeCursor', function(e, e2, e3) { var old_line = cbox['a_ed_last_line']; var new_line = editor.getCursorPosition().row + 1; if (new_line != old_line) { cbox['a_ed_last_line'] = new_line; ed_ct_line_change(t, new_line); //confirm('onCursorChage: ' + old_line + ' ' + new_line); } }); editor.gotoLine(line); editor.scrollToLine(line, true); editor.focus(); ed_ace_resize(t); } function createAceEditor(t) { var cbox = t.get('panelNode'); var edNode = cbox.one('#aceEditor'); //confirm(edNode); if (edNode) { edNode = edNode.getDOMNode(); } if (!edNode) { return; } var editor = ace.edit(edNode); //var editor = ace.edit(cbox.getDOMNode()); editor.getSession().setUseWorker(false); editor.setTheme("ace/theme/eclipse"); editor.setReadOnly(true); //editor.setValue("Loading..."); //editor.resize(); editor.gotoLine("1"); editor.focus(); cbox['a_ed'] = editor; cbox['a_ed_last_line'] = 0; } function show_ctags_new(t, file) { if (!t) { return; } var Y = document['edy']; var src; src = new Y.DataSource.Get({ source : document['server_info'].url, }); src.plug(Y.Plugin.DataSourceJSONSchema, { schema : { resultListLocator : 'res', } }); var request = '?' + to_query_string({ project : document['project'], cmd_type : 'query', cmd_str : 'FCTAGS', req : file, }); src.sendRequest({ request : request, callback : { success: function (e) { var res = e.response.results; populateCtTable(t, res[0]); }, failure: function (e) { var cbox = t.get('panelNode'); cbox['g_dt'].setCell(0, 0, e.error.message); cbox['g_table'].draw(cbox['g_dv']); alert(e.error.message); }, }, }); } function show_ace_editor_new(t, file, line) { var Y = document['edy']; var src; src = new Y.DataSource.Get({ source : document['server_info'].url, }); src.plug(Y.Plugin.DataSourceJSONSchema, { schema : { resultListLocator : 'res', } }); var request = '?' + to_query_string({ project : document['project'], cmd_type : 'query', cmd_str : 'FDATA', req : file, }); src.sendRequest({ request : request, callback : { success: function (e) { var res = e.response.results; setAceEditorText(t, res[0], line); }, failure: function (e) { setAceEditorText(t, e.error.message, 1); alert(e.error.message); }, }, }); } function ed_show_file_line_new(file, line) { var ed_tv = document['ed_tv']; var fp = file.split('/'); var fname = fp[fp.length - 1]; var content2 = '' + '' + '' + '' + '' + '
' + '
' + '
' + '
' + '
'; var content = '' + '' + '' + '' + '' + '
' + '
' + '
' + '
' + '
'; var input = { label: fname, content : content, } ed_tv.add(input); found = ed_tv.size() - 1; t = ed_tv.item(found); t['ed_file'] = file; t['ed_line'] = line; ed_tv.selectChild(found); show_ace_editor_new(t, file, line) show_ctags_new(t, file); } function ed_show_file_line(file, line) { //confirm('ed_show_file_line ' + file + ':' + line); var edf = document['edf']; //edf.sayHi(); var ed_tv = document['ed_tv']; //confirm(ed_tv.size()); var found = -1; for (i = 0; i < ed_tv.size(); i++) { t = ed_tv.item(i); if (t['ed_file'] == file) { found = i; break; } } if (found == -1) { ed_show_file_line_new(file, line); } else { ed_tv.selectChild(found); var cbox = t.get('panelNode'); var editor = cbox['a_ed']; editor.gotoLine(line); editor.focus(); } } YUI().use('datasource-get', 'datasource-jsonschema', 'node-event-delegate', 'event-key', 'tabview', 'escape', 'plugin', 'node', function(Y) { document['edy'] = Y; var EdAddable = function(config) { EdAddable.superclass.constructor.apply(this, arguments); }; EdAddable.NAME = 'addableTabs'; EdAddable.NS = 'addable'; Y.extend(EdAddable, Y.Plugin.Base, { // ADD_TEMPLATE: '
  • ' + // '+
  • ', initializer: function(config) { var tabview = this.get('host'); tabview.after('render', this.afterRender, this); tabview.get('contentBox').delegate('click', this.onAddClick, '.yui3-tab-add', this); tabview.after('tab:render', this.afterTabRender, this); //tabview.after('tab:widget:contentUpdate', this.afterTabRender, this); tabview.after('selectionChange', function() { var t = tabview.get('activeDescendant'); if (t) { focusAceEditor(t.get('panelNode')); } }); tabview.get('listNode').setStyle('border-width', '0 0 0px'); tabview.get('panelNode').setStyle('padding', '0em'); }, afterRender: function(e) { var tabview = this.get('host'); //tabview.get('contentBox').one('> ul').append(this.ADD_TEMPLATE); }, onAddClick: function(e) { }, afterTabRender: function(e) { //e.stopPropagation(); var t = e.target; tv = this.get('host'); createAceEditor(t); createCtTable(t); } }); var EdRemoveable = function(config) { EdRemoveable.superclass.constructor.apply(this, arguments); }; EdRemoveable.NAME = 'removeableTabs'; EdRemoveable.NS = 'removeable'; Y.extend(EdRemoveable, Y.Plugin.Base, { REMOVE_TEMPLATE: 'x', initializer: function(config) { var tabview = this.get('host'), cb = tabview.get('contentBox'); cb.addClass('yui3-tabview-removeable'); cb.delegate('click', this.onRemoveClick, '.yui3-tab-remove', this); // Tab events bubble to TabView tabview.after('tab:render', this.afterTabRender, this); }, afterTabRender: function(e) { // boundingBox is the Tab's LI e.target.get('boundingBox').append(this.REMOVE_TEMPLATE); }, onRemoveClick: function(e) { e.stopPropagation(); var tab = Y.Widget.getByNode(e.target); tab.remove(); } }); var ed_tv= new Y.TabView({ children: [], plugins: [EdAddable, EdRemoveable] }); ed_tab_list_pop_dlg_setup(function(cargs) { if (cargs.choice == 'close_all') { ed_tv.removeAll(); } }); ed_pop_dlg_setup(function(cargs) { qry_dlg_show(start_query, cargs.choice); }); ed_tv.after('heightChange', ed_tv_resize); ed_tv.after('widthChange', ed_tv_resize); ed_tv.after("selectionChange", function(e) { Y.later(0, null, ed_tv_resize_sel, e); }); document['ed_tv'] = ed_tv; // ed_tv.set('height', 400); // ed_tv.set('width', 400); ed_tv.render('#edTabs'); function queryAction(e) { e.stopPropagation(); confirm('queryAction'); qry_dlg_show(); } var key1 = 'm+ctrl'; //confirm(key); Y.one('#edTabs').on('key', queryAction, key1); var key2 = ']+ctrl'; function qdefAction(e) { confirm('qdefAction'); var word = ed_get_cur_word(); if (word) { if (word.length < 3) { qry_dlg_show(); } else { start_query(word, 'DEF'); } } } Y.one('#edTabs').on('key', qdefAction, key2); }); seascope-0.9+8a669e0e/src/web/www/js/first.js000066400000000000000000000040501363245777100206360ustar00rootroot00000000000000 var url = 'http://' + sinfo.host; if (sinfo.port != 80) { url = url + ':' + sinfo.port } url = url + '/q'; sinfo.url = url; // confirm(url); document['server_info'] = sinfo; function filter_table(dt, fargs) { var col = fargs.col; var is_regex = (fargs.opt.indexOf('regex') != -1); var is_negate = (fargs.opt.indexOf('negate') != -1); var is_ignorecase = (fargs.opt.indexOf('ignorecase') != -1); var pat = fargs.symbol; if (is_regex) { pat = new RegExp(pat, is_ignorecase ? 'i' : ''); } var row_list = []; var num_rows = dt.getNumberOfRows(); for (var row = 0; row < num_rows; row++) { var val = dt.getValue(row, col); var found; if (is_regex) { found = pat.test(val); } else { if (is_ignorecase) { found = (val.toUpperCase().search(pat.toUpperCase()) != -1); } else { found = (val.search(pat) != -1); } } if (is_negate) { found = !found; } if (!found) { row_list.push(row); } } return row_list; } function to_query_string(obj) { var parts = []; for (var i in obj) { if (obj.hasOwnProperty(i)) { parts.push(encodeURIComponent(i) + "=" + encodeURIComponent(obj[i])); } } return parts.join("&"); } function send_my_request(Y, resultListLocator, success_func, failure_func ) { var src = new Y.DataSource.Get({ source : document['server_info'].url, }); src.plug(Y.Plugin.DataSourceJSONSchema, { schema : { resultListLocator : resultListLocator, } }); src.sendRequest({ request : request, callback : { success: success_func, failure: failure_func, }, }); } seascope-0.9+8a669e0e/src/web/www/js/flist_filt_dlg.js000066400000000000000000000057331363245777100225050ustar00rootroot00000000000000function flist_filt_dlg_show(cb_func, col_name) { var qpanel = document['dlg_flist_filt_p']; qpanel['cb_func'] = cb_func; var bnode = qpanel.bodyNode; var qtype_node = bnode.one('#qtype'); qtype_node.set('value', col_name); var sym_node = bnode.one('#symbol') sym_node.set('value', ''); var arr = ['regex', 'negate', 'ignorecase']; for (var inx = 0; inx < arr.length; inx++) { var node = bnode.one('#' + arr[inx]) node.set('checked', false); } sym_node.select(); qpanel.show(); sym_node.focus(); } YUI().use("panel", function (Y) { var qtype = ''; var body = '' + '' + '' + '' + '' + '' + '
    Filter in ' + qtype + '
    Filter for
    Regex
    Negate search
    Case Insensitive
    '; function okAction(e) { e.preventDefault(); qpanel.hide(); var bnode = qpanel.bodyNode; var qtype = bnode.one('#qtype').get('value'); if (!qtype) { return; } var symbol = bnode.one('#symbol').get('value'); if (!symbol) { return; } var opt = []; var arr = ['regex', 'negate', 'ignorecase']; for (var inx = 0; inx < arr.length; inx++) { if (bnode.one('#' + arr[inx]).get('checked')) { opt.push(arr[inx]); } } var col_name = bnode.one('#qtype').get('value'); var cb_func = qpanel['cb_func']; var q_args = { qtype : qtype, symbol : symbol, opt : opt, col_name : col_name, }; if (!cb_func) { return; } cb_func(q_args); } var qpanel = new Y.Panel({ bodyContent: body, // width : 250, zIndex : 6, centered : true, modal : true, render : '#flistFiltPanel', buttons: [ { value : 'Cancel', section: Y.WidgetStdMod.FOOTER, action : function (e) { e.preventDefault(); qpanel.hide(); } }, { value : 'Ok', section: Y.WidgetStdMod.FOOTER, action : okAction, } ] }); qpanel.bodyNode.on('key', okAction, 'enter'); qpanel.hide(); document['dlg_flist_filt_y'] = Y; document['dlg_flist_filt_p'] = qpanel; }); seascope-0.9+8a669e0e/src/web/www/js/fv_tabs.js000066400000000000000000000202311363245777100211320ustar00rootroot00000000000000function fv_t_resize(t, is_sel) { var cbox = t.get('panelNode'); var fv_tv = document['fv_tv']; var w = fv_tv.get('width') - 2; var lh = cbox.ancestor().ancestor().one('.yui3-tabview-list').get('clientHeight'); var h = fv_tv.get('height') - lh; if (is_sel) { if (cbox['g_table_h'] == h && cbox['g_table_w'] == w) { return; } } cbox['g_table_h'] = h cbox['g_table_w'] = w var table = cbox['g_table']; var dv = cbox['g_dv']; if (!table) { return; } table.draw(dv, { height: h, width: w, page : 'enable', pageSize : 200, }); } function fv_tv_cur_tab() { var fv_tv = document['fv_tv']; if (!fv_tv.size()) { return null; } return fv_tv.get('selection'); } function fv_tv_resize(e) { var t = fv_tv_cur_tab(); if (!t) { return; } fv_t_resize(t); } function fv_tv_resize_sel(e) { var t = fv_tv_cur_tab(); if (!t) { return; } fv_t_resize(t, true); } function flist_query() { var fv_tv = document['fv_tv']; var targs = { label : 'files', content : '
    ', }; fv_tv.add(targs); var inx = fv_tv.size() - 1; fv_tv.selectChild(inx); } function flist_filter_cb(fargs) { var t = fv_tv_cur_tab(); var cbox = t.get('panelNode'); var dt = cbox['g_dt']; var dv = cbox['g_dv']; var col_arr = ['file', 'path']; fargs.col = col_arr.indexOf(fargs.col_name); var row_list = filter_table(dt, fargs); if (row_list.length) { dv.hideRows(row_list); fv_tv_resize(null); } } function flist_show_all_cb() { var t = fv_tv_cur_tab(); var cbox = t.get('panelNode'); var dt = cbox['g_dt']; var dv = cbox['g_dv']; var num_rows = dt.getNumberOfRows(); if (num_rows) { dv.setRows(0, num_rows -1); } fv_tv_resize(null); } function flist_remove_item_cb(row) { if (row == -1) { return; } var t = fv_tv_cur_tab(); var cbox = t.get('panelNode'); var dt = cbox['g_dt']; var dv = cbox['g_dv']; dv.hideRows([row]); fv_tv_resize(null); } function flist_ctx_menu_cb(cargs) { //confirm('flist_ctx_menu_cb: ' + choice); if (cargs.choice == 'filter') { var col_arr = ['file', 'path']; var col_name = col_arr[cargs.col]; flist_filt_dlg_show(flist_filter_cb, col_name); } else if(cargs.choice == 'show_all') { flist_show_all_cb(); } else if (cargs.choice == 'remove_item') { flist_remove_item_cb(cargs.row); } } function createFvTable(t) { var cbox = t.get('panelNode'); var dt = new google.visualization.DataTable(); dt.addColumn('string', 'file'); dt.addColumn('string', 'path'); dt.addRows(1); dt.setCell(0, 0, 'fetching file list...'); var dv = new google.visualization.DataView(dt); var table = new google.visualization.Table(cbox.getDOMNode()); cbox['g_dt'] = dt; cbox['g_dv'] = dv; cbox['g_table'] = table; fv_t_resize(t); } function populateFvTable(t, res) { var cbox = t.get('panelNode'); var dt = google.visualization.arrayToDataTable(res); var dv = new google.visualization.DataView(dt); cbox['g_dt'] = dt; cbox['g_dv'] = dv; fv_t_resize(t); var table = cbox['g_table']; google.visualization.events.addListener(table, 'select', function() { var sel = table.getSelection(); if (sel.length == 0) { return } var row = sel[0].row; var dv = cbox['g_dv']; var file = dv.getValue(row, 1); var line = 1 ed_show_file_line(file, line); }); } YUI().use('datasource-get', 'datasource-jsonschema', 'tabview', 'escape', 'plugin', 'node', function(Y) { var ResAddable = function(config) { ResAddable.superclass.constructor.apply(this, arguments); }; ResAddable.NAME = 'addableTabs'; ResAddable.NS = 'addable'; Y.extend(ResAddable, Y.Plugin.Base, { // ADD_TEMPLATE: '
  • ' + // '+
  • ', initializer: function(config) { var tabview = this.get('host'); tabview.after('render', this.afterRender, this); tabview.get('contentBox').delegate('click', this.onAddClick, '.yui3-tab-add', this); tabview.after('tab:render', this.afterTabRender, this); //tabview.after('tab:widget:contentUpdate', this.afterTabRender, this); tabview.get('listNode').setStyle('border-width', '0 0 0px'); tabview.get('panelNode').setStyle('padding', '0em'); }, afterRender: function(e) { var tabview = this.get('host'); //tabview.get('contentBox').one('> ul').append(this.ADD_TEMPLATE); }, onAddClick: function(e) { e.stopPropagation(); var tabview = this.get('host'), input = this.getTabInput(); tabview.add(input); tabview.selectChild(tabview.size() - 1); }, afterTabRender: function(e) { var t = e.target; var cbox = t.get('panelNode'); var fvTblNode = cbox.one('#fvTbl'); // confirm(fvTblNode); // if (fvTblNode) { // fvTblNode = fvTblNode.getDOMNode(); // } if (fvTblNode) { createFvTable(t); var src = new Y.DataSource.Get({ source : document['server_info'].url, }); src.plug(Y.Plugin.DataSourceJSONSchema, { schema : { resultListLocator : 'res', } }); var request = '?' + to_query_string({ project : document['project'], cmd_type : 'query', cmd_str : 'FLIST', }); src.sendRequest({ request : request, callback : { success: function (e) { var res = e.response.results; populateFvTable(t, res); }, failure: function (e) { cbox['g_dt'].setCell(0, 0, e.error.message); cbox['g_table'].draw(cbox['g_dv']); alert(e.error.message); }, }, }); } } }); var Removeable = function(config) { Removeable.superclass.constructor.apply(this, arguments); }; Removeable.NAME = 'removeableTabs'; Removeable.NS = 'removeable'; Y.extend(Removeable, Y.Plugin.Base, { REMOVE_TEMPLATE: 'x', initializer: function(config) { var tabview = this.get('host'), cb = tabview.get('contentBox'); cb.addClass('yui3-tabview-removeable'); cb.delegate('click', this.onRemoveClick, '.yui3-tab-remove', this); // Tab events bubble to TabView tabview.after('tab:render', this.afterTabRender, this); }, afterTabRender: function(e) { // boundingBox is the Tab's LI e.target.get('boundingBox').append(this.REMOVE_TEMPLATE); }, onRemoveClick: function(e) { e.stopPropagation(); var tab = Y.Widget.getByNode(e.target); tab.remove(); } }); var fv_tv = new Y.TabView({ children: [], plugins: [ResAddable, Removeable] }); flist_tbl_pop_dlg_setup(flist_ctx_menu_cb); fv_tv.after('heightChange', fv_tv_resize); fv_tv.after('widthChange', fv_tv_resize); fv_tv.after("selectionChange", function(e) { Y.later(0, null, fv_tv_resize_sel, e); }); fv_tv.after('removeChild', function(e) { flist_query(); }); document['fv_tv'] = fv_tv; fv_tv.render('#fvTabs'); }); seascope-0.9+8a669e0e/src/web/www/js/lay_main.js000066400000000000000000000063121363245777100213030ustar00rootroot00000000000000YUI().use('node', 'yui2-utilities', 'yui2-layout', 'yui2-resize', 'yui2-menu', function(Y) { Y.one('body').addClass('yui-skin-sam'); //This will make your YUI 2 code run unmodified var YAHOO = Y.YUI2; var Event = YAHOO.util.Event; Event.onDOMReady(function() { var layout = new YAHOO.widget.Layout({ units: [ { position: 'top', body: 'top1', height: 34, resize: false, scroll: true, gutter: '0px' }, { position: 'center', body: 'edTabs', scroll: true, gutter: '5px' }, { position: 'right', body: 'fvTabs', width: 300, resize: true, scroll: true, gutter: '5px' }, { position: 'bottom', body: 'resTabs', height: 300, resize: true, scroll: true, gutter: '5px' }, ] }); layout.on('render', function() { }); layout.render(); document['lay_main'] = layout; function cu_size_change(e) { var x = 25; var node = layout.getUnitByPosition('center'); var h = node.get('height'); var w = node.get('width'); var ed_tv = document['ed_tv']; ed_tv.set('height', h - x); ed_tv.set('width', w - x - 2); } function bu_size_change(e) { var x = 25; var h2 = layout.getUnitByPosition('bottom').get('height'); //var w2 = layout.getUnitByPosition('bottom').get('width'); //var w2 = document.documentElement.clientWidth; var w2 = YAHOO.util.Dom.getViewportWidth(); var res_tv = document['res_tv']; res_tv.set('height', h2 - x); res_tv.set('width', w2 - x - 2); } function ru_size_change(e) { var x = 25; var h2 = layout.getUnitByPosition('right').get('height'); var w2 = layout.getUnitByPosition('right').get('width'); //var w2 = document.documentElement.clientWidth; var fv_tv = document['fv_tv']; fv_tv.set('height', h2 - x); fv_tv.set('width', w2 - x - 2); } var bu = layout.getUnitByPosition('bottom'); var ru = layout.getUnitByPosition('right'); bu.on('heightChange', function(e) { cu_size_change(e); ru_size_change(e); bu_size_change(e); }); ru.on('widthChange', function(e) { cu_size_change(e); ru_size_change(e); }); var e = null; cu_size_change(e); ru_size_change(e); bu_size_change(e); plist_dlg_show(function(pargs) { document['project'] = pargs.project; Y.one('#project_name').setHTML(pargs.project); flist_query(); // var qargs = { // qtype : 'REF', // symbol : 'query', // opt : [], // }; // start_query(qargs); }); }); function g_do_resize(e) { confirm('g_do_resize'); var e = null; cu_size_change(e); ru_size_change(e); bu_size_change(e); } Y.after('windowresize', g_do_resize); }); seascope-0.9+8a669e0e/src/web/www/js/pop_dlg.js000066400000000000000000000152401363245777100211360ustar00rootroot00000000000000function res_tbl_pop_dlg_setup(cb_func) { YUI().use("panel", "gallery-contextmenu-view", function (Y) { var pmenu = new Y.ContextMenuView({ // Set what Node should accept the right clicks, and the target on that node ... trigger: { node: Y.one('#resTabs'), target: 'td' }, // Define the pop-up menu contents menuItems: [ { label: 'Filter', value: 'filter' }, { label: 'Show All', value: 'show_all' }, //{ label: '
    ', value: null }, //{ label: 'Remove Item', value: 'remove_item' }, ], }); pmenu['cb_func'] = cb_func; function menu_choice(e) { // e.stopPropagation(); // e.preventDefault(); var td = this.get('contextTarget'); var row = td.ancestor().get('sectionRowIndex') - 1; var col = td.get('cellIndex'); var choice = e.newVal.menuItem.value; var cb_func = pmenu['cb_func']; if (!cb_func) { return; } var cargs = { choice : choice, row : row, col : col, }; cb_func(cargs); } pmenu.after('selectedMenuChange', menu_choice); }); } function flist_tbl_pop_dlg_setup(cb_func) { YUI().use("panel", "gallery-contextmenu-view", function (Y) { var pmenu = new Y.ContextMenuView({ // Set what Node should accept the right clicks, and the target on that node ... trigger: { node: Y.one('#fvTabs'), target: 'td' }, // Define the pop-up menu contents menuItems: [ { label: 'Filter', value: 'filter' }, { label: 'Show All', value: 'show_all' }, //{ label: '
    ', value: null }, //{ label: 'Remove Item', value: 'remove_item' }, ], }); pmenu['cb_func'] = cb_func; function menu_choice(e) { var td = this.get('contextTarget'); var row = td.ancestor().get('sectionRowIndex') - 1; var col = td.get('cellIndex'); var choice = e.newVal.menuItem.value; var cb_func = pmenu['cb_func']; if (!cb_func) { return; } var cargs = { choice : choice, row : row, col : col, }; cb_func(cargs); } pmenu.after('selectedMenuChange', menu_choice); }); } function ed_pop_dlg_setup(cb_func) { var qry_arr = [ ['REF', 'References to'], ['DEF', 'Definition of'], //['<--', 'Called Functions'], ['-->', 'Calling Functions'], //['TXT', 'Find Text'], ['GREP', 'Find Egrep'], ['FIL', 'Find File'], ['INC', 'Include/Import'], ['CTREE', 'Call Tree'], ['CLGRAPH', 'Class Graph'], ['CLGRAPHD', 'Class Graph Dir'], ['FFGRAPH', 'File Func Graph'], ]; var menu_items = []; var is_disabled = false; for (var i = 0; i < qry_arr.length; i++) { v = qry_arr[i]; if (v[0] == 'CTREE') { is_disabled = true; } if (is_disabled) { // menu_items.push({ // class : "disabled", // label : v[1], // value : null, // }) } else { menu_items.push({ label : v[1], value : v[0], }) } } YUI().use("panel", "gallery-contextmenu-view", function (Y) { var pmenu = new Y.ContextMenuView({ // Set what Node should accept the right clicks, and the target on that node ... trigger: { node: Y.one('#edTabs'), target: '#aceEditor' }, // Define the pop-up menu contents menuItems: menu_items, }); pmenu['cb_func'] = cb_func; function menu_choice(e) { var choice = e.newVal.menuItem.value; var cb_func = pmenu['cb_func']; if (!cb_func) { return; } var cargs = { choice : choice, }; cb_func(cargs); } pmenu.after('selectedMenuChange', menu_choice); }); } function res_tab_list_pop_dlg_setup(cb_func) { YUI().use("panel", "gallery-contextmenu-view", function (Y) { var pmenu = new Y.ContextMenuView({ // Set what Node should accept the right clicks, and the target on that node ... trigger: { node: Y.one('#resTabs'), target: '.yui3-tabview-list ' }, // Define the pop-up menu contents menuItems: [ { label: 'Close All', value: 'close_all', confirm: true }, ], }); pmenu['cb_func'] = cb_func; function menu_choice(e) { var choice = e.newVal.menuItem.value; if (e.newVal.menuItem.confirm && !confirm('Close all tabs?')) { return; } var cb_func = pmenu['cb_func']; if (!cb_func) { return; } var cargs = { choice : choice, }; cb_func(cargs); } pmenu.after('selectedMenuChange', menu_choice); }); } function ed_tab_list_pop_dlg_setup(cb_func) { YUI().use("panel", "gallery-contextmenu-view", function (Y) { var pmenu = new Y.ContextMenuView({ // Set what Node should accept the right clicks, and the target on that node ... trigger: { node: Y.one('#edTabs'), target: '.yui3-tabview-list ' }, // Define the pop-up menu contents menuItems: [ { label: 'Close All', value: 'close_all', confirm: true }, ], }); pmenu['cb_func'] = cb_func; function menu_choice(e) { var choice = e.newVal.menuItem.value; if (e.newVal.menuItem.confirm && !confirm('Close all tabs?')) { return; } var cb_func = pmenu['cb_func']; if (!cb_func) { return; } var cargs = { choice : choice, }; cb_func(cargs); } pmenu.after('selectedMenuChange', menu_choice); }); } seascope-0.9+8a669e0e/src/web/www/js/prj_list.js000066400000000000000000000073161363245777100213450ustar00rootroot00000000000000function plist_dlg_show(cb_func) { var sym = ed_get_cur_word(); var qpanel = document['dlg_plist_p']; qpanel['cb_func'] = cb_func; qpanel.show(); qpanel['fetch_func'](); } YUI().use('datasource-get', 'datasource-jsonschema', "panel", function (Y) { var body = '' + //'Choose a project' + '
    ' + '
    '; function prj_choice(prj) { var cb_func = qpanel['cb_func']; var p_args = { project : prj, }; if (!cb_func) { return; } cb_func(p_args); } var qpanel = new Y.Panel({ bodyContent: body, width : 250, zIndex : 6, centered : true, modal : true, render : '#plistPanel', buttons: [ { value : 'Refresh', section: Y.WidgetStdMod.FOOTER, action : function (e) { fetch_prj_list(); } }, ] }); function createPlistTable(cbox) { var dt = new google.visualization.DataTable(); dt.addColumn('string', 'Choose a project'); dt.addRows(1); dt.setCell(0, 0, 'fetching project list...'); var dv = new google.visualization.DataView(dt); var table = new google.visualization.Table(cbox.one('#prjListTbl').getDOMNode()); cbox['g_dt'] = dt; cbox['g_dv'] = dv; cbox['g_table'] = table; table.draw(dv); } function populatePlistTable(cbox, res) { var table = cbox['g_table']; var dt = new google.visualization.DataTable(); dt.addColumn('string', 'Choose a project'); for(var i = 0; i < res.length; i++) { dt.addRow([res[i]]); } var dv = new google.visualization.DataView(dt); table.draw(dv); cbox['g_dt'] = dt; cbox['g_dv'] = dv; if (res.length == 1) { qpanel.hide(); //confirm(res[0]); prj_choice(res[0]); return; } google.visualization.events.addListener(table, 'select', function() { var sel = table.getSelection(); if (sel.length == 0) { return } var row = sel[0].row; var dv = cbox['g_dv']; var prj = dv.getValue(row, 0); qpanel.hide(); prj_choice(prj); }); } function fetch_prj_list() { var cbox = qpanel.bodyNode; var url = document['server_info'].url; var src = new Y.DataSource.Get({ source : url, }); src.plug(Y.Plugin.DataSourceJSONSchema, { schema : { resultListLocator : 'res', } }); var rd = { cmd_type : 'project_list', } var request = '?' + to_query_string(rd); src.sendRequest({ request : request, callback : { success: function (e) { var res = e.response.results; populatePlistTable(cbox, res); }, failure: function (e) { alert(e.error.message); }, }, }); } qpanel.after('render', function(e) { var cbox = qpanel.bodyNode; var node = cbox.one('#prjListTbl'); createPlistTable(cbox); }); qpanel['fetch_func'] = fetch_prj_list; qpanel.hide(); document['dlg_plist_y'] = Y; document['dlg_plist_p'] = qpanel; }); seascope-0.9+8a669e0e/src/web/www/js/qry_dlg.js000066400000000000000000000071231363245777100211540ustar00rootroot00000000000000function qry_dlg_show(cb_func, qtype) { var sym = ed_get_cur_word(); var qpanel = document['dlg_qry_p']; qpanel['cb_func'] = cb_func; var bnode = qpanel.bodyNode; if (!qtype) { qtype = 'REF'; } var qtype_node = bnode.one('#qtype') qtype_node.set('value', qtype); var sym_node = bnode.one('#symbol') sym_node.set('value', sym); var substring_node = bnode.one('#substring') substring_node.set('checked', false); var ignorecase_node = bnode.one('#ignorecase') ignorecase_node.set('checked', false); sym_node.select(); qpanel.show(); sym_node.focus(); } YUI().use("panel", function (Y) { var qry_arr = [ ['REF', 'References to'], ['DEF', 'Definition of'], //['<--', 'Called Functions'], ['-->', 'Calling Functions'], //['TXT', 'Find Text'], ['GREP', 'Find Egrep'], ['FIL', 'Find File'], ['INC', 'Include/Import'], ['CTREE', 'Call Tree'], ['CLGRAPH', 'Class Graph'], ['CLGRAPHD', 'Class Graph Dir'], ['FFGRAPH', 'File Func Graph'], ]; var qtype = ''; var body = '' + '' + '' + '' + '' + '
    Type ' + qtype + '
    Symbol
    Substring
    Case Insensitive
    '; function okAction(e) { e.preventDefault(); qpanel.hide(); var bnode = qpanel.bodyNode; var qtype = bnode.one('#qtype').get('value'); if (!qtype) { return; } var symbol = bnode.one('#symbol').get('value'); if (!symbol) { return; } var opt = []; if (bnode.one('#substring').get('checked')) { opt.push('substring'); } if (bnode.one('#ignorecase').get('checked')) { opt.push('ignorecase'); } var cb_func = qpanel['cb_func']; var q_args = { qtype : qtype, symbol : symbol, opt : opt, }; if (!cb_func) { return; } cb_func(q_args); } var qpanel = new Y.Panel({ bodyContent: body, // width : 250, zIndex : 6, centered : true, modal : true, render : '#qryPanel', buttons: [ { value : 'Cancel', section: Y.WidgetStdMod.FOOTER, action : function (e) { e.preventDefault(); qpanel.hide(); } }, { value : 'Ok', section: Y.WidgetStdMod.FOOTER, //isDefault: true, action : okAction, } ] }); qpanel.bodyNode.on('key', okAction, 'enter'); qpanel.hide(); document['dlg_qry_y'] = Y; document['dlg_qry_p'] = qpanel; }); seascope-0.9+8a669e0e/src/web/www/js/res_filt_dlg.js000066400000000000000000000061071363245777100221510ustar00rootroot00000000000000function res_filt_dlg_show(cb_func, col_name) { var qpanel = document['dlg_res_filt_p']; qpanel['cb_func'] = cb_func; var bnode = qpanel.bodyNode; var qtype_node = bnode.one('#qtype'); qtype_node.set('value', col_name); var sym_node = bnode.one('#symbol') sym_node.set('value', ''); var arr = ['regex', 'negate', 'ignorecase']; for (var inx = 0; inx < arr.length; inx++) { var node = bnode.one('#' + arr[inx]) node.set('checked', false); } sym_node.select(); qpanel.show(); sym_node.focus(); } YUI().use("panel", function (Y) { var qtype = ''; var body = '' + '' + '' + '' + '' + '' + '
    Filter in ' + qtype + '
    Filter for
    Regex
    Negate search
    Case Insensitive
    '; function okAction(e) { e.preventDefault(); qpanel.hide(); var bnode = qpanel.bodyNode; var qtype = bnode.one('#qtype').get('value'); if (!qtype) { return; } var symbol = bnode.one('#symbol').get('value'); if (!symbol) { return; } var opt = []; var arr = ['regex', 'negate', 'ignorecase']; for (var inx = 0; inx < arr.length; inx++) { if (bnode.one('#' + arr[inx]).get('checked')) { opt.push(arr[inx]); } } var col_name = bnode.one('#qtype').get('value'); var cb_func = qpanel['cb_func']; var q_args = { qtype : qtype, symbol : symbol, opt : opt, col_name : col_name, }; if (!cb_func) { return; } cb_func(q_args); } var qpanel = new Y.Panel({ bodyContent: body, // width : 250, zIndex : 6, centered : true, modal : true, render : '#resFiltPanel', buttons: [ { value : 'Cancel', section: Y.WidgetStdMod.FOOTER, action : function (e) { e.preventDefault(); qpanel.hide(); } }, { value : 'Ok', section: Y.WidgetStdMod.FOOTER, action : okAction, } ] }); qpanel.bodyNode.on('key', okAction, 'enter'); qpanel.hide(); document['dlg_res_filt_y'] = Y; document['dlg_res_filt_p'] = qpanel; }); seascope-0.9+8a669e0e/src/web/www/js/res_tabs.js000066400000000000000000000240671363245777100213230ustar00rootroot00000000000000function res_t_resize(t, is_sel) { var res_tv = document['res_tv']; var cbox = t.get('panelNode'); var table = cbox['g_table']; var lh = cbox.ancestor().ancestor().one('.yui3-tabview-list').get('clientHeight'); var w = res_tv.get('width') - 2; var h = res_tv.get('height') - lh; if (is_sel) { if (cbox['g_table_h'] == h && cbox['g_table_w'] == w) { return; } } cbox['g_table_h'] = h cbox['g_table_w'] = w var dv = cbox['g_dv']; table.draw(dv, { height: h, width: w, page : 'enable', pageSize : 200, }); } function res_tv_cur_tab() { var res_tv = document['res_tv']; if (!res_tv.size()) { return; } return res_tv.get('selection'); } function res_tv_resize(e) { var t = res_tv_cur_tab(); if (!t) { return; } res_t_resize(t); } function res_tv_resize_sel(e) { var t = res_tv_cur_tab(); if (!t) { return; } res_t_resize(t, true); } function start_query(qargs) { var res_tv = document['res_tv']; var label = qargs.symbol; if (qargs.opt.indexOf('substring') >= 0) { if (qargs.qtype == 'FIL') { label = '*' + label + '*' } else { label = '.*' + label + '.*' } } label = qargs.qtype + ' ' + label; var targs = { label : label, content : // '' + // '' + '' + // '' + // '' + '
    ', // '' + // '
    ', }; res_tv['qargs'] = qargs; res_tv.add(targs); var inx = res_tv.size() - 1; res_tv.selectChild(inx); // var t = res_tv.item(inx); // t['qargs'] = qargs; } function res_filter_cb(fargs) { var t = res_tv_cur_tab(); var cbox = t.get('panelNode'); var dt = cbox['g_dt']; var dv = cbox['g_dv']; var col_arr = ['tag', 'file', 'line', 'text']; fargs.col = col_arr.indexOf(fargs.col_name); var row_list = filter_table(dt, fargs); if (row_list.length) { dv.hideRows(row_list); res_tv_resize(null); } } function res_show_all_cb() { var t = res_tv_cur_tab(); var cbox = t.get('panelNode'); var dt = cbox['g_dt']; var dv = cbox['g_dv']; var num_rows = dt.getNumberOfRows(); if (num_rows) { dv.setRows(0, num_rows -1); } res_tv_resize(null); } function res_remove_item_cb(row) { if (row == -1) { return; } var t = res_tv_cur_tab(); var cbox = t.get('panelNode'); var dt = cbox['g_dt']; var dv = cbox['g_dv']; dv.hideRow([row]); res_tv_resize(null); } function res_ctx_menu_cb(cargs) { //confirm('res_ctx_menu_cb: ' + choice); if (cargs.choice == 'filter') { var col_arr = ['tag', 'file', 'line', 'text']; var col_name = col_arr[cargs.col]; res_filt_dlg_show(res_filter_cb, col_name); } else if(cargs.choice == 'show_all') { res_show_all_cb(); } else if (cargs.choice == 'remove_item') { res_remove_item_cb(cargs.row); } } function createResTable(t) { var cbox = t.get('panelNode'); var dt = new google.visualization.DataTable(); dt.addColumn('string', 'tag'); dt.addColumn('string', 'file'); dt.addColumn('string', 'line'); dt.addColumn('string', 'text'); dt.addRows(1); dt.setCell(0, 0, 'running query...'); var dv = new google.visualization.DataView(dt); var table = new google.visualization.Table(cbox.one('#resTbl').getDOMNode()); cbox['g_dt'] = dt; cbox['g_dv'] = dv; cbox['g_table'] = table; res_t_resize(t); } function populateResTable(t, res) { var cbox = t.get('panelNode'); var dt = cbox['g_dt']; dt.removeRow(0); //confirm(res.length); dt.addRows(res); cbox['g_table_h'] = 0; res_t_resize(t); if (res.length == 1) { var dv = cbox['g_dv']; var row = 0; var file = dv.getValue(row, 1); var line = dv.getValue(row, 2); ed_show_file_line(file, line); } var table = cbox['g_table']; google.visualization.events.addListener(table, 'select', function(e) { var sel = table.getSelection() if (sel.length == 0) { return } var row = sel[0].row; var dv = cbox['g_dv']; var file = dv.getValue(row, 1); var line = dv.getValue(row, 2); ed_show_file_line(file, line); }); } YUI().use('datasource-get', 'datasource-jsonschema', 'node-event-delegate', 'event-key', 'tabview', 'escape', 'plugin', 'node', function(Y) { var ResAddable = function(config) { ResAddable.superclass.constructor.apply(this, arguments); }; ResAddable.NAME = 'addableTabs'; ResAddable.NS = 'addable'; Y.extend(ResAddable, Y.Plugin.Base, { ADD_TEMPLATE: '
  • ' + '+
  • ', initializer: function(config) { var tabview = this.get('host'); tabview.after('render', this.afterRender, this); tabview.get('contentBox').delegate('click', this.onAddClick, '.yui3-tab-add', this); tabview.after('tab:render', this.afterTabRender, this); //tabview.after('tab:widget:contentUpdate', this.afterTabRender, this); tabview.get('listNode').setStyle('border-width', '0 0 0px'); tabview.get('panelNode').setStyle('padding', '0em'); }, afterRender: function(e) { var tv = this.get('host'); tv.get('contentBox').one('> ul').append(this.ADD_TEMPLATE); }, onAddClick: function(e) { e.stopPropagation(); qry_dlg_show(start_query); }, afterTabRender: function(e) { var t = e.target; var cbox = t.get('panelNode'); var resTblNode = cbox.one('#resTbl'); // confirm(resTblNode); // if (resTblNode) { // resTblNode = resTblNode.getDOMNode(); // } if (resTblNode) { createResTable(t); var url = document['server_info'].url; var src = new Y.DataSource.Get({ source : url, }); src.plug(Y.Plugin.DataSourceJSONSchema, { schema : { //resultListLocator : 'res', resultFields : ['res', 'err_data'], } }); var tv = this.get('host'); var qargs = tv['qargs']; tv['qargs'] = null; var rd = { project : document['project'], cmd_type : 'query', cmd_str : qargs.qtype, req : qargs.symbol, opt : qargs.opt.join(','), } var hint_file = ed_get_cur_file(); if (hint_file) { rd.hint_file = hint_file; } var request = '?' + to_query_string(rd); src.sendRequest({ request : request, callback : { success: function (e) { var err_data = e.data.err_data; if (err_data) { var node = cbox.one('#errLbl'); node.setHTML(err_data); node.show(); node.after('click', function(e) { node.hide(); }); } var res = e.data.res; populateResTable(t, res); }, failure: function (e) { cbox['g_dt'].setCell(0, 0, e.error.message); cbox['g_table'].draw(cbox['g_dv']); }, }, }); } } }); var Removeable = function(config) { Removeable.superclass.constructor.apply(this, arguments); }; Removeable.NAME = 'removeableTabs'; Removeable.NS = 'removeable'; Y.extend(Removeable, Y.Plugin.Base, { REMOVE_TEMPLATE: 'x', initializer: function(config) { var tabview = this.get('host'), cb = tabview.get('contentBox'); cb.addClass('yui3-tabview-removeable'); cb.delegate('click', this.onRemoveClick, '.yui3-tab-remove', this); // Tab events bubble to TabView tabview.after('tab:render', this.afterTabRender, this); }, afterTabRender: function(e) { // boundingBox is the Tab's LI e.target.get('boundingBox').append(this.REMOVE_TEMPLATE); }, onRemoveClick: function(e) { e.stopPropagation(); var tab = Y.Widget.getByNode(e.target); tab.remove(); } }); var res_tv = new Y.TabView({ children: [], plugins: [ResAddable, Removeable] }); res_tab_list_pop_dlg_setup(function(cargs) { if (cargs.choice == 'close_all') { res_tv.removeAll(); } }); res_tbl_pop_dlg_setup(res_ctx_menu_cb); res_tv.after('heightChange', res_tv_resize); res_tv.after('widthChange', res_tv_resize); res_tv.after("selectionChange", function(e) { Y.later(0, null, res_tv_resize_sel, e); }); document['res_tv'] = res_tv; res_tv.render('#resTabs'); });