seascope-0.7/0000775002376300237630000000000012062273206011634 5ustar anilanilseascope-0.7/setup.py0000775002376300237630000000323412062273150013351 0ustar anilanil#!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from distutils.core import setup setup(name='Seascope', version='0.7', description='A multi-platform multi-language source code browsing tool' long_description='A pyQt GUI front-end for idutils, cscope and gtags. Written in python using pyQt, QScintilla libraries.', url='http://seascope.googlecode.com', packages=['Seascope', 'Seascope.backend', 'Seascope.backend.plugins', 'Seascope.backend.plugins.idutils' 'Seascope.backend.plugins.cscope', 'Seascope.backend.plugins.gtags', 'Seascope.view', 'Seascope.view.filecontext', 'Seascope.view.filecontext.plugins', 'Seascope.view.filecontext.plugins.ctags_view', 'Seascope.view.filecontext.plugins.generic_view', ], package_dir={'Seascope': 'src'}, package_data={'Seascope': ['icons/*.svg','ui/*.ui','tools/*.py']}, license="BSD License", classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: X11 Applications :: Qt', 'Environment :: Win32 (MS Windows)', 'Intended Audience :: End Users/Desktop', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: MacOS :: MacOS X', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Programming Language :: Python', 'Topic :: Software Development', ], options= {'bdist_rpm':{'requires': 'PyQt4,qscintilla-python,idutils,cscope,global,ctags,graphviz', 'group': 'Development Tools', 'vendor': 'The Seascope Team'}} ) seascope-0.7/LICENSE0000664002376300237630000000255412062273150012645 0ustar anilanilCopyright (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.7/README0000664002376300237630000000035312062273150012513 0ustar anilanilSeascope 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.7/MANIFEST.in0000664002376300237630000000002012062273150013360 0ustar anilanilinclude LICENSE seascope-0.7/src/0000775002376300237630000000000012062273150012421 5ustar anilanilseascope-0.7/src/ui/0000775002376300237630000000000012062273150013036 5ustar anilanilseascope-0.7/src/ui/filter.ui0000664002376300237630000000772612062273150014676 0ustar anilanil 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.7/src/ui/proj_new.ui0000664002376300237630000000444712062273150015231 0ustar anilanil 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.7/src/ui/find.ui0000664002376300237630000000613712062273150014324 0ustar anilanil 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.7/src/ui/preferences.ui0000664002376300237630000001373412062273150015706 0ustar anilanil 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.7/src/ui/goto_line.ui0000664002376300237630000000520412062273150015355 0ustar anilanil 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.7/src/ui/project_settings.ui0000664002376300237630000001063612062273150016771 0ustar anilanil 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.7/src/ui/proj_open.ui0000664002376300237630000000500712062273150015372 0ustar anilanil 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.7/src/ui/about.ui0000664002376300237630000003203712062273150014514 0ustar anilanil 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.7</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-2012 Anil Kumar</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://seascope.googlecode.com"><span style=" text-decoration: underline; color:#0000ff;">http://seascope.googlecode.com</span></a></p></body></html> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Qt::Horizontal 40 20 Qt::Vertical 20 40 Author QTextEdit::AutoNone true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Anil Kumar</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> anil.omkar@gmail.com</p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Developer</p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></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;"></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="-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;">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></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;"></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;"></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;"></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.7/src/ui/debug.ui0000664002376300237630000000375112062273150014471 0ustar anilanil dbg_main_window 0 0 514 394 Debug info... QTabWidget::Rounded 0 Info true 0 0 472 323 Version Not implemented yet seascope-0.7/src/view/0000775002376300237630000000000012062273150013373 5ustar anilanilseascope-0.7/src/view/EdView.py0000664002376300237630000003105112062273150015130 0ustar anilanil#!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import re from PyQt4 import QtGui from PyQt4.QtGui import * from PyQt4.QtCore import * try: from PyQt4.Qsci import QsciScintilla, QsciScintillaBase, QsciLexerCPP, QsciLexerPython except ImportError: print "Error: required qscintilla-python package not found" raise ImportError import DialogManager from FileContextView import * class EditorView(QsciScintilla): ev_popup = None def __init__(self, parent=None): QsciScintilla.__init__(self, parent) #self.setGeometry(300, 300, 400, 300) ## Editing line color self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QtGui.QColor("#EEF6FF")) #self.setCaretWidth(2) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.font = None self.lexer = None self.codemark_marker = self.markerDefine(self.Circle) def get_filename(self): return self.filename def ed_settings_1(self): ## Margins colors # line numbers margin self.setMarginsBackgroundColor(QtGui.QColor("#333333")) self.setMarginsForegroundColor(QtGui.QColor("#CCCCCC")) # folding margin colors (foreground,background) self.setFoldMarginColors(QtGui.QColor("#888888"),QtGui.QColor("#eeeeee")) ## Edge Mode shows a red vetical bar at 80 chars self.setEdgeMode(QsciScintilla.EdgeLine) self.setEdgeColumn(80) self.setEdgeColor(QtGui.QColor("#FF0000")) ## Editing line color self.setCaretLineVisible(True) self.setCaretLineBackgroundColor(QtGui.QColor("#CDA869")) def show_line_number_cb(self, val): if (val): width = self.fm.width( "00000" ) + 5 else: width = 0 self.setMarginWidth(0, width) self.setMarginLineNumbers(0, val) def show_folds_cb(self, val): if val: #self.setMarginsForegroundColor( QtGui.QColor("#404040") ) #self.setMarginsBackgroundColor( QtGui.QColor("#888888") ) ## Folding visual : we will use circled tree fold self.setFolding(QsciScintilla.CircledTreeFoldStyle) else: self.setFolding(QsciScintilla.NoFoldStyle) self.clearFolds() def toggle_folds_cb(self): self.foldAll() def codemark_add(self, line): self.markerAdd(line, self.codemark_marker) def codemark_del(self, line): self.markerDelete(line, self.codemark_marker) def goto_marker(self, is_next): (eline, inx) = self.getCursorPosition() if is_next: val = self.markerFindNext(eline + 1, -1) else: val = self.markerFindPrevious(eline - 1, -1) if val >= 0: self.setCursorPosition(val, 0) def 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 open_file(self, filename): self.filename = filename ## Choose a lexer if not self.lexer: if (re.search('\.(py|pyx|pxd|pxi|scons)$', filename) != None): self.lexer = QsciLexerPython() else: self.lexer = QsciLexerCPP() ## Braces matching self.setBraceMatching(QsciScintilla.SloppyBraceMatch) ## Render on screen self.show() ## Show this file in the editor self.setText(open(filename).read()) ## Mark read-only self.setReadOnly(True) self.show() self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) #self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setFocus() def goto_line(self, line): line = line - 1 self.setCursorPosition(line, 0) self.ensureLineVisible(line) self.setFocus() def contextMenuEvent(self, ev): f = EditorView.ev_popup.font() EditorView.ev_popup.setFont(QFont("San Serif", 8)) EditorView.ev_popup.exec_(QCursor.pos()) EditorView.ev_popup.setFont(f) class EditorPage(QSplitter): def __init__(self, parent=None): QSplitter.__init__(self) self.fcv = FileContextView(self) self.ev = self.new_editor_view() self.addWidget(self.fcv) self.addWidget(self.ev) self.setSizes([1, 300]) self.ev.cursorPositionChanged.connect(self.fcv.sig_ed_cursor_changed) self.fcv.sig_goto_line.connect(self.ev.goto_line) def new_editor_view(self): return EditorView(self) def open_file(self, filename): self.ev.open_file(filename); self.fcv.run(filename); def get_filename(self): return self.ev.get_filename() class EditorBook(QTabWidget): sig_file_closed = pyqtSignal(str) sig_history_update = pyqtSignal(str, int) sig_tab_changed = pyqtSignal(str) sig_open_dir_view = pyqtSignal(str) def __init__(self, *args): apply(QTabWidget.__init__,(self, ) + args) self.setMovable(True) self.setTabsClosable(True) self.tabCloseRequested.connect(self.removeTab) self.currentChanged.connect(self.tab_change_cb) self.is_show_line = False self.is_show_folds = False self.f_text = None self.ev_font = "Monospace,10,-1,5,50,0,0,0,0,0" def new_editor_page(self): return EditorPage() def addFile(self, fileName): ed = self.new_editor_page() ed.open_file(fileName) ed.ev.set_font(self.ev_font) ed.ev.show_line_number_cb(self.is_show_line) ed.ev.show_folds_cb(self.is_show_folds) self.addTab(ed, os.path.basename(fileName)) return ed def search_already_opened_files(self, filename): for i in range(self.count()): page = self.widget(i) if (page.get_filename() == filename): return page return None def removeTab(self, inx): ed = self.widget(inx) f = ed.ev.get_filename() QTabWidget.removeTab(self, inx) self.sig_file_closed.emit(f) def clear(self): while self.count() != 0: self.removeTab(0) def remove_tab_list(self, inx_list): for inx in sorted(inx_list, reverse=True): self.removeTab(inx) def tab_list(self, inx, type): inx_list = [] if type == 'all' or type == 'files': return range(self.count()) if type == 'left': return range(inx) if type == 'right': return range(inx + 1, self.count()) if type == 'other': return self.tab_list(inx, 'left') + self.tab_list(inx, 'right') assert 0 def close_list_common(self, type): inx_list = self.tab_list(self.currentIndex(), type) if len(inx_list) == 0: return if not DialogManager.show_yes_no('Close all %s ?' % type): return self.remove_tab_list(inx_list) def close_all_left_cb(self): self.close_list_common('left') def close_all_right_cb(self): self.close_list_common('right') def close_all_other_cb(self): self.close_list_common('other') def close_all_cb(self): self.close_list_common('files') def get_current_word(self): ed = self.currentWidget() if not ed: return if ed.ev.hasSelectedText(): return ed.ev.selectedText() (line, index) = ed.ev.getCursorPosition() text = ed.ev.text(line) # Go left linx = index while linx > 0 and ed.ev.isWordCharacter(text[linx - 1]): linx = linx - 1 # Go right rinx = index while rinx < len(text) and ed.ev.isWordCharacter(text[rinx]): rinx = rinx + 1 text = text[linx:rinx] if text == '': return None return text def get_current_file_line(self): ed = self.currentWidget() if not ed: return (None, None) (line, inx) = ed.ev.getCursorPosition() return (ed.ev.filename, line + 1) def get_file_line_list(self): fl_list = [] tlist = range(self.count()) inx = self.currentIndex() if inx >= 0: tlist.append(inx) for inx in tlist: ed = self.widget(inx) (line, inx) = ed.ev.getCursorPosition() fl_list.append('%s:%d' % (ed.ev.filename, line + 1)) return fl_list def matching_brace_cb(self): ed = self.currentWidget() if ed: ed.ev.moveToMatchingBrace() #ed.ev.setFocus() def goto_line_cb(self): ed = self.currentWidget() if not ed: return (None, None) (line, inx) = ed.ev.getCursorPosition() #return (line + 1, ed.ev.lines()) line = DialogManager.show_goto_line_dialog(line + 1, ed.ev.lines()) if (line == None): return ed.ev.goto_line(line) def focus_editor(self): page = self.currentWidget() if page: page.ev.setFocus() def close_current_page(self): self.removeTab(self.currentIndex()) self.focus_editor() def focus_search_ctags(self): ed = self.currentWidget() if ed: ed.fcv.focus_search_ctags() def copy_edit_cb(self): ed = self.currentWidget() if ed: ed.ev.copy() def tab_change_cb(self, inx): if (inx == -1): fname = '' else: page = self.currentWidget() page.ev.setFocus() fname = page.get_filename() self.sig_tab_changed.emit(fname) def open_dir_cb(self): page = self.currentWidget() if page: fname = page.get_filename() self.sig_open_dir_view.emit(fname) def mousePressEvent(self, m_ev): QTabWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): # setup popup menu self.pmenu = QMenu() self.pmenu.addAction("Open dir", self.open_dir_cb) self.pmenu.addSeparator() self.pmenu.addAction("Close All &Left", self.close_all_left_cb) self.pmenu.addAction("Close All &Right", self.close_all_right_cb) self.pmenu.addAction("Close &Others", self.close_all_other_cb) self.pmenu.addSeparator() self.pmenu.addAction("Close &All", self.close_all_cb) self.pmenu.exec_(QCursor.pos()) def show_file_line(self, filename, line, hist=True): if line: (f, l) = self.get_current_file_line() if (f): if hist: self.sig_history_update.emit(f, l) filename = str(filename) if (not os.path.exists(filename)): return page = self.search_already_opened_files(filename) if page == None: page = self.addFile(filename) self.setCurrentWidget(page) if line: page.ev.goto_line(line) if hist: self.sig_history_update.emit(filename, line) page.ev.setFocus() def show_file(self, filename): self.show_file_line(filename, 0) def show_line(self, line): ed = self.currentWidget() if not ed: return ed.ev.goto_line(line) def find_cb(self): ed = self.currentWidget() if not ed: return res = DialogManager.show_find_dialog(self.get_current_word()) if (res == None): return (text, opt) = res if (text == None): return self.f_text = text self.f_opt = opt self.find_text(opt['cursor'], opt['fw']) def find_text(self, from_cursor, is_fw): if (self.f_text == None): return ed = self.currentWidget() if not ed: return text = self.f_text opt = self.f_opt if (from_cursor): if (is_fw): (line, inx) = (-1, -1) else: (line, inx) = ed.ev.getCursorPosition() if (ed.ev.hasSelectedText()): inx = inx - 1 if ed.ev.findFirst(text, opt['re'], opt['cs'], opt['wo'], False, is_fw, line, inx): return True if not DialogManager.show_yes_no('End of document reached. Continue from beginning?'): return False if (is_fw): (line, inx) = (0, 0) else: (line, inx) = (ed.ev.lines(), 0) if ed.ev.findFirst(text, opt['re'], opt['cs'], opt['wo'], False, is_fw, line, inx): return DialogManager.show_msg_dialog("Could not find " + "'" + text + "'") def find_next_cb(self): self.find_text(True, True) def find_prev_cb(self): self.find_text(True, False) def change_ev_font(self, font): if font == self.ev_font: return self.ev_font=font for inx in range(self.count()): ed = self.widget(inx) ed.ev.set_font(self.ev_font) def show_line_number_cb(self): val = self.m_show_line_num.isChecked() self.is_show_line = val for inx in range(self.count()): ed = self.widget(inx) ed.ev.show_line_number_cb(val) def show_line_number_pref(self, val): if val == self.m_show_line_num.isChecked(): return self.m_show_line_num.setChecked(val) self.show_line_number_cb() def show_folds_cb(self): val = self.m_show_folds.isChecked() self.is_show_folds = val for inx in range(self.count()): ed = self.widget(inx) ed.ev.show_folds_cb(val) def toggle_folds_cb(self): ed = self.currentWidget() if not ed: return if self.is_show_folds: ed.ev.toggle_folds_cb() def open_in_external_editor(self, cmd): if not cmd: DialogManager.show_msg_dialog('Please configure external editor') return (f, l) = self.get_current_file_line() if not f: return cmd = cmd.replace('%F', f).replace('%L', str(l)) if not QProcess.startDetached(cmd): DialogManager.show_msg_dialog('Failed to start: ' + cmd) def codemark_add(self, filename, line): ed = self.search_already_opened_files(filename) if ed: ed.ev.codemark_add(line) def codemark_del(self, filename, line): ed = self.search_already_opened_files(filename) if ed: ed.ev.codemark_del(line) def bookmark_prev_cb(self): ed = self.currentWidget() if ed: ed.ev.goto_marker(False) def bookmark_next_cb(self): ed = self.currentWidget() if ed: ed.ev.goto_marker(True) seascope-0.7/src/view/ResView.py0000664002376300237630000001725012062273150015336 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import re from PyQt4.QtGui import * from PyQt4.QtCore import * import DialogManager class ResultPageItem(QTreeWidgetItem): def __init__(self, li): QTreeWidgetItem.__init__(self, li) def column_val(self, col): try: val = str(self.data(col, Qt.DisplayRole).toString()) except: return None return val class ResultPage(QTreeWidget): sig_show_file_line = pyqtSignal(str, int) is_history_call = False def __init__(self, parent): QTreeWidget.__init__(self) self.is_history = False self.pbar = None self.parent = parent self.setColumnCount(4) self.cmd_items = ['Tag', 'File', 'Line', 'Text'] self.setHeaderLabels(self.cmd_items) self.setColumnWidth(0, 200) self.setColumnWidth(1, 300) self.setColumnWidth(2, 40) # setup popup menu self.pmenu = QMenu() self.pmenu.addAction("&Filter", self.filter_cb) self.pmenu.addAction("&Show All", self.show_all_cb) self.pmenu.addSeparator() self.pmenu.addAction("&Remove Item", self.remove_item_cb) #self.setMinimumHeight(200) #self.setMinimumWidth(600) ## set column width to fit contents ##self.resizeColumnsToContents() ##self.resizeRowsToContents() ## set row height #nrows = len(result) #for row in xrange(nrows): #self.setRowHeight(row, 14) #self.setTextElideMode(Qt.ElideLeft) self.setIndentation(-2) self.setAllColumnsShowFocus(True) self.activated.connect(self.activated_cb) def activated_cb(self, minx): (filename, line) = self.get_file_line(minx) if (not filename): return if (self.is_history): ResultPage.is_history_call = True self.sig_show_file_line.emit(filename, line) ResultPage.is_history_call = False def filter_cb(self): filtered = False cmd_sel = self.cmd_items[self.last_minx.column()] res = DialogManager.show_filter_dialog(self.cmd_items,cmd_sel) if res == None: return (filter_text, is_regex, is_negate, is_ignorecase, cmd_sel) = res cmd_idx = self.cmd_items.index(cmd_sel) if cmd_idx == -1: return for inx in range(self.topLevelItemCount()): item = self.topLevelItem(inx) text = item.column_val(cmd_idx) if (text == None): continue matched = False if (is_regex): if (is_ignorecase): if (re.search(filter_text, text, re.I) != None): matched = True else: if (re.search(filter_text, text) != None): matched = True else: if (is_ignorecase): if (text.upper().find(filter_text.upper()) != -1): matched = True else: if (text.find(filter_text) != -1): matched = True if (is_negate): matched = not matched if not matched: self.setItemHidden(item, True) filtered = True if filtered: self.mark_tab_filtered(True) def mark_tab_filtered(self, mark): tabIndex = self.parent.indexOf(self) label = self.parent.tabText(tabIndex) if mark and label[0] != "*": self.parent.setTabText(tabIndex, "*" + label) elif not mark and label[0] == "*": self.parent.setTabText(tabIndex, label.remove(0,1)) def show_all_cb(self): for inx in range(self.topLevelItemCount()): item = self.topLevelItem(inx) self.setItemHidden(item, False) self.mark_tab_filtered(False) def remove_item_cb(self): self.setItemHidden(self.itemFromIndex(self.last_minx), True) self.mark_tab_filtered(True) def get_file_line(self, minx): model = minx.model() row = minx.row() if (not model): return (None, None) filename = str(model.data(model.index(row, 1)).toString()) try: line = model.data(model.index(row, 2)).toString() line = int(line) except: line = 0 return (filename, line) def add_result_continue(self): self.add_result(self.name, self.res) def add_result(self, name, res): res_list = [] ret_val = True root = self.invisibleRootItem() count = 0 for line in res: item = ResultPageItem(line) #self.addTopLevelItem(item) if (self.is_history): root.insertChild(0, item) else: root.addChild(item) count = count + 1 if (count == 1000): self.name = name self.res = res[count:] QTimer.singleShot(100, self.add_result_continue) return self.remove_progress_bar() if (self.topLevelItemCount() < 5000): self.resizeColumnToContents(0) self.resizeColumnToContents(1) self.resizeColumnToContents(2) self.resizeColumnToContents(3) if (self.topLevelItemCount() == 1): item = self.topLevelItem(0) item.setSelected(True) minx = self.indexFromItem(item) self.activated_cb(minx) return ret_val def mousePressEvent(self, m_ev): QTreeWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): self.last_minx = self.indexAt(m_ev.pos()) self.pmenu.exec_(QCursor.pos()) def show_progress_bar(self): self.pbar = QProgressBar(self) self.pbar.setMinimum(0) self.pbar.setMaximum(0) self.pbar.show() def remove_progress_bar(self): if (self.pbar): self.pbar.setParent(None) self.pbar = None class ResultManager(QTabWidget): book = None sig_show_file_line = pyqtSignal(str, int) def __init__(self, *args): apply(QTabWidget.__init__,(self, ) + args) self.setMovable(True) self.setTabsClosable(True) self.tabCloseRequested.connect(self.close_cb) self.h_page = None self.setFont(QFont("San Serif", 8)) ResultManager.book = self def go_next_res_common(self, page, inc): if page == None: return if (inc == 1): minx = page.moveCursor(QAbstractItemView.MoveDown, Qt.NoModifier) else: minx = page.moveCursor(QAbstractItemView.MoveUp, Qt.NoModifier) page.setCurrentItem(page.itemFromIndex(minx)) page.activated.emit(minx) def go_next_res(self, inc): self.go_next_res_common(self.currentWidget(), inc) def go_next_history(self, inc): self.go_next_res_common(self.h_page, -inc) def show_history(self): if (self.h_page): self.setCurrentWidget(self.h_page) def new_cb(self): print "new_cb" def refresh_cb(self): print "refresh_cb" def close_cb(self, inx): if (self.widget(inx) == self.h_page): self.h_page = None self.removeTab(inx) def close_all_cb(self): if DialogManager.show_yes_no("Close all query results ?"): self.clear() self.h_page = None def mousePressEvent(self, m_ev): QTabWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): # setup popup menu self.pmenu = QMenu() #self.pmenu.addAction("&New", self.new_cb) #self.pmenu.addAction("&Refresh", self.refresh_cb) #self.pmenu.addSeparator() self.pmenu.addAction("Close &All", self.close_all_cb) self.pmenu.exec_(QCursor.pos()) def history_create(self): self.h_page = ResultManager.create_result_page(self, None) assert self.h_page.is_history self.h_page.hideColumn(0) self.h_page.hideColumn(3) def history_update(self, filename, line): if (ResultPage.is_history_call): return if (self.h_page == None): self.history_create() for idx in range(self.h_page.indexOfTopLevelItem(self.h_page.currentItem())): self.h_page.invisibleRootItem().removeChild(self.h_page.topLevelItem(0)) if self.h_page.topLevelItemCount(): item = self.h_page.topLevelItem(0) minx = self.h_page.indexFromItem(item) (f, l) = self.h_page.get_file_line(minx) if (filename and f == filename and l == line): return self.h_page.add_result('History', [['', filename, str(line), '']]) if self.h_page.topLevelItemCount(): self.h_page.setCurrentItem(self.h_page.topLevelItem(0)) def create_result_page(self, name): page = ResultPage(self) if not name: name = 'History' page.is_history = True self.addTab(page, name) if not page.is_history: self.setCurrentWidget(page) page.sig_show_file_line.connect(self.sig_show_file_line) page.show_progress_bar() return page def create_result_page_single(self): return ResultPage(self) seascope-0.7/src/view/filecontext/0000775002376300237630000000000012062273150015717 5ustar anilanilseascope-0.7/src/view/filecontext/plugins/0000775002376300237630000000000012062273150017400 5ustar anilanilseascope-0.7/src/view/filecontext/plugins/ctags_view/0000775002376300237630000000000012062273150021533 5ustar anilanilseascope-0.7/src/view/filecontext/plugins/ctags_view/__init__.py0000664002376300237630000000041612062273150023645 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os def name(): return 'ctags' def run_plugin(filename, parent): import CtagsView CtagsView.run(filename, parent) def description(): d = 'ctags description' return d priority = 500 seascope-0.7/src/view/filecontext/plugins/ctags_view/CtagsManager.py0000664002376300237630000001026412062273150024444 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import subprocess import re def _eintr_retry_call(func, *args): while True: try: return func(*args) except OSError, e: if e.errno == errno.EINTR: continue raise def ct_query(filename): cmd = 'ctags -n -u --fields=+K -f -' args = cmd.split() args.append(filename) try: proc = subprocess.Popen(args, stdout=subprocess.PIPE) (out_data, err_data) = _eintr_retry_call(proc.communicate) out_data = out_data.split('\n') except Exception as e: out_data = [ 'Failed to run ctags cmd\tignore\t0;\t ', 'cmd: %s\tignore\t0;\t ' % ' '.join(args), 'error: %s\tignore\t0;\t ' % str(e), 'ctags not installed ?\tignore\t0;\t ', ] res = [] for line in out_data: if (line == ''): break line = line.split('\t') num = line[2].split(';', 1)[0] line = [line[0], num, line[3]] res.append(line) return res is_OrderedDict_available = False try: # OrderedDict available only in python >= 2.7 from collections import OrderedDict is_OrderedDict_available = True except: pass def emptyOrderedDict(): if is_OrderedDict_available: return OrderedDict({}) return {} class CtagsTreeBuilder: def __init__(self): self.symTree = emptyOrderedDict() def runCtags(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 -' args = args.split() args.append(f) # In python >= 2.7 can use subprocess.check_output # output = subprocess.check_output(args) # return output proc = subprocess.Popen(args, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate() return out_data def parseCtagsOutput(self, data): data = re.split('\r?\n', data) res = [] for line in data: if line == '': continue line = line.split('\t', 4) res.append(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 sd = dict([ x.split(':', 1) for x in line[4].split('\t')]) 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): output = self.runCtags(filename) output = self.parseCtagsOutput(output) output = self.buildTree(output) return output def ct_tree_query(filename): ct = CtagsTreeBuilder() output = ct.doQuery(filename) return output if __name__ == '__main__': import optparse import sys depth = 0 def recursePrint(t): global depth for k, v in t.items(): if k == '*': for line in v: print '%s%s' % (' ' * depth, line) continue if k == '+': continue if '+' in v: k = v['+'] print '%s%s' % (' ' * depth, k) depth = depth + 4 recursePrint(v) depth = depth - 4 op = optparse.OptionParser() (options, args) = op.parse_args() if len(args) != 1: print 'Please specify a file' sys.exit(-1) (output, isTree) = ct_tree_query(args[0]) if isTree: recursePrint(output) else: for line in output: print line seascope-0.7/src/view/filecontext/plugins/ctags_view/CtagsView.py0000664002376300237630000001377612062273150024017 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * import CtagsManager # Search Result class SR: NONE = 0 LSKIP = 1 LUPD = 2 MATCH = 3 RUPD = 4 RSKIP = 5 def __init__(self, k): self.line = k self.left = 0 self.right = 1000000 self.item = None self.done = False class CtagsListItem(QTreeWidgetItem): def __init__(self, li): QTreeWidgetItem.__init__(self, li) if li[2] in [ 'class', 'interface', 'struct', 'type', 'enum', '' ]: self.set_bold() def set_bold(self): f = self.font(0) f.setBold(True) self.setFont(0, f) def column_val(self, col): return str(self.data(col, Qt.DisplayRole).toString()) def line_val(self): return (int(self.column_val(1))) class CtagsList(QTreeWidget): def __init__(self, parent=None, isTree=False): QTreeWidget.__init__(self) self.setColumnCount(3) self.setHeaderLabels(['Name', 'Line', 'Type']) #self.setMinimumHeight(200) self.setMinimumWidth(50) self.setFont(QFont("San Serif", 8)) if isTree: self.setIndentation(12) self.setExpandsOnDoubleClick(False) #self.setAnimated(True) else: self.setIndentation(-2) self.setAllColumnsShowFocus(True) def add_ct_result(self, res): for line in res: item = CtagsListItem(line) self.addTopLevelItem(item) #self.sortItems(1, Qt.AscendingOrder) #self.resizeColumnsToContents(1) self.resizeColumnToContents(0) self.resizeColumnToContents(1) self.resizeColumnToContents(2) def recurseTreeAdd(self, t, p): for k, v in t.items(): if k == '+': continue if k == '*': for line in v: item = CtagsListItem(line) p.addChild(item) continue if '+' in v: item = CtagsListItem(v['+']) else: item = CtagsListItem([k, '', '', '']) p.addChild(item) self.recurseTreeAdd(v, item) self.setItemExpanded(p, True) def add_ctree_result(self, res): p = self.invisibleRootItem() self.recurseTreeAdd(res, p) #self.sortItems(1, Qt.AscendingOrder) #self.resizeColumnsToContents(1) self.resizeColumnToContents(0) self.resizeColumnToContents(1) self.resizeColumnToContents(2) def ed_cursor_changed(self, line, pos): line = line + 1 item = self.currentItem() if not item: item = self.topLevelItem(0) if not item: return if (item.line_val() == line): pass elif (item.line_val() < line): while True: next_item = self.itemBelow(item) if not next_item: break if (next_item.line_val() > line): break item = next_item else: while True: prev_item = self.itemAbove(item) if not prev_item: break item = prev_item if (item.line_val() <= line): break self.setCurrentItem(item) def search_item_check(self, item, sr): try: val = item.line_val() except: return SR.NONE if val < sr.left: return SR.LSKIP if val < sr.line: sr.left = val sr.item = item return SR.LUPD if val == sr.line: sr.left = val sr.item = item sr.done = True return SR.MATCH if val < sr.right: sr.right = val if not sr.item: sr.item = item return SR.RUPD return SR.RSKIP def search_recursive(self, p, sr): inx = 0; r = SR.NONE while inx < p.childCount(): item = p.child(inx) if not item.childCount(): break inx += 1 if r < SR.MATCH: r = self.search_item_check(item, sr) if r == SR.MATCH: return self.search_recursive(item, sr) if sr.done: return if not inx < p.childCount(): return last_item = p.child(p.childCount() - 1) r = self.search_item_check(last_item, sr) if r <= sr.MATCH: return r = SR.NONE while inx < p.childCount(): item = p.child(inx) inx += 1 r = self.search_item_check(item, sr) if r >= SR.MATCH: return def search_tree(self, line, pos): line = line + 1 sr = SR(line) p = self.invisibleRootItem() self.search_recursive(p, sr) self.setCurrentItem(sr.item) class CtagsListPage(QWidget): sig_goto_line = pyqtSignal(int) def __init__(self, parent=None): QWidget.__init__(self) self.le = QLineEdit() self.ct = CtagsList(self) vlay = QVBoxLayout() vlay.addWidget(self.le) vlay.addWidget(self.ct) self.setLayout(vlay) self.le.textChanged.connect(self.le_textChanged) self.le.returnPressed.connect(self.le_returnPressed) self.ct.itemActivated.connect(self.ct_itemActivated) def le_textChanged(self, text): #if (len(str(text)) == 1): #self.ct.keyboardSearch('') self.ct.keyboardSearch('') self.ct.keyboardSearch(text) def le_returnPressed(self): items = self.ct.selectedItems() if len(items) == 0: return self.ct.itemActivated.emit(items[0], 0) def ct_itemActivated(self, item): try: line = int(str(item.data(1, Qt.DisplayRole).toString())) except: return self.sig_goto_line.emit(line) self.le.clear() def keyPressEvent(self, ev): if ev.key() in [Qt.Key_Up, Qt.Key_Down, Qt.Key_PageUp or Qt.Key_PageDown]: self.ct.keyPressEvent(ev) return @staticmethod def do_ct_query(filename, parent): page = CtagsListPage(parent) res = CtagsManager.ct_query(filename) page.ct.add_ct_result(res) parent.add_page(page, 'C') parent.sig_ed_cursor_changed.connect(page.ct.ed_cursor_changed) class CtagsTreePage(QWidget): sig_goto_line = pyqtSignal(int) def __init__(self, parent=None): QWidget.__init__(self) self.ct = CtagsList(self, isTree=True) vlay = QVBoxLayout() vlay.addWidget(self.ct) self.setLayout(vlay) self.ct.itemActivated.connect(self.ct_itemActivated) def ct_itemActivated(self, item): try: line = int(str(item.data(1, Qt.DisplayRole).toString())) except: return self.sig_goto_line.emit(line) @staticmethod def do_ct_query(filename, parent): (res, isTree) = CtagsManager.ct_tree_query(filename) if not isTree: return page = CtagsTreePage(parent) page.ct.add_ctree_result(res) parent.add_page(page, 'T') parent.sig_ed_cursor_changed.connect(page.ct.search_tree) def run(filename, parent): CtagsListPage.do_ct_query(filename, parent) CtagsTreePage.do_ct_query(filename, parent) seascope-0.7/src/view/filecontext/plugins/__init__.py0000664002376300237630000000011212062273150021503 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD seascope-0.7/src/view/filecontext/plugins/generic_view/0000775002376300237630000000000012062273150022046 5ustar anilanilseascope-0.7/src/view/filecontext/plugins/generic_view/GenericView.py0000664002376300237630000000442312062273150024632 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * class GenericResItem(QTreeWidgetItem): def __init__(self, li): QTreeWidgetItem.__init__(self, li) def column_val(self, col): return str(self.data(col, Qt.DisplayRole).toString()) def line_val(self): return (int(self.column_val(1))) class GenericRes(QTreeWidget): def __init__(self, parent=None): QTreeWidget.__init__(self) self.setColumnCount(1) self.setHeaderLabels(['Result']) #self.setMinimumHeight(200) self.setMinimumWidth(50) self.setFont(QFont("San Serif", 8)) self.setIndentation(-2) self.setAllColumnsShowFocus(True) def add_result(self, res): for line in res: item = GenericResItem([line]) self.addTopLevelItem(item) class GenericFileCmdPage(QWidget): sig_goto_line = pyqtSignal(int) def __init__(self, parent=None): QWidget.__init__(self) self.ct = GenericRes(self) vlay = QVBoxLayout() #self.lbl = QLabel() #vlay.addWidget(self.lbl) vlay.addWidget(self.ct) self.setLayout(vlay) self.ct.itemActivated.connect(self.ct_itemActivated) def ct_itemActivated(self, item): try: line = int(str(item.data(1, Qt.DisplayRole).toString())) except: return self.sig_goto_line.emit(line) @staticmethod def run_plugin(cmd, filename, parent): if '%f' in cmd: args = cmd.replace('%f', filename) args = args.strip().split() else: args = cmd.strip().split() args.append(filename) import subprocess try: proc = subprocess.Popen(args, stdout=subprocess.PIPE) (res, err_data) = proc.communicate() except Exception as e: res = '%s\n%s' % (' '.join(args), str(e)) import re res = [ x.strip() for x in re.split('\r?\n', res.strip()) ] page = GenericFileCmdPage(parent) page.cmd = cmd #page.lbl.setText(' '.join(args)) page.ct.add_result(res) parent.add_page(page, cmd) def cmd_name(): cmd_list = [ #'stat', #'ls %f', #'ls %f %f' ] import os cmd = os.getenv('SEASCOPE_FC_CUSTOM_CMD') if cmd: cmd_list += [ x.strip() for x in cmd.split(';') ] return list(set(cmd_list)) def run(filename, parent, cmd=None): if cmd: cmd_list = [ cmd ] else: cmd_list = cmd_name() for cmd in cmd_list: GenericFileCmdPage.run_plugin(cmd, filename, parent) seascope-0.7/src/view/filecontext/plugins/generic_view/__init__.py0000664002376300237630000000056512062273150024165 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os def name(): return 'generic_cmd' def run_plugin(filename, parent, cmd=None): import GenericView GenericView.run(filename, parent, cmd=cmd) def description(): d = 'generic cmd description' return d def cmd_name(): import GenericView return GenericView.cmd_name() priority = 100 seascope-0.7/src/view/filecontext/__init__.py0000664002376300237630000000212712062273150020032 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import re, os from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * #import DialogManager #from plugins import PluginHelper fc_plugins = [] fc_dict = {} def _load_plugins(module, directory): pluginImports = __import__(module, globals(), locals()) print 'Scanning for view plugins...' plist = [] pdict = {} for i in sorted(os.listdir(directory)): path = os.path.join( directory, i, '__init__.py' ) if os.path.isfile( path ): p = __import__( '%s.%s' % (module, i), globals(), locals(), ['*'] ) plist.append(p) pdict[p.name()] = p if not hasattr(p, 'priority'): p.priority = 0 plist = sorted(plist, key=lambda p: p.priority, reverse=True) for p in plist: print '\t', p.name() return (plist, pdict) def load_plugins(): global fc_plugins, fc_dict (fc_plugins, fc_dict) = _load_plugins('view.filecontext.plugins', 'view/filecontext/plugins') def run_plugins(filename, parent): for p in fc_plugins: if not hasattr(p, 'cmd_name'): p.run_plugin(filename, parent) seascope-0.7/src/view/CodemarkView.py0000664002376300237630000000500512062273150016325 0ustar anilanil#!/usr/bin/env python # Copyright (c) 2012 Anthony Liu # All rights reserved. # # License: BSD import sys from array import * class CodemarkManager(): def __init__(self, parent=None): self.haystack = [] def check(self, filename, line): if self.haystack.count((filename, line)): return 1 return 0 def append(self, filename, line): if self.check(filename, line) == 0: self.haystack.append((filename, line)) return self.haystack.index((filename, line)) def delete(self, filename, line): if self.haystack.count((filename, line)) == 0: return -1 else: self.haystack.remove((filename, line)) return 0 def delete_index(self, index): if self.count() <= index: return -1 elif index < 0: return -1 else: self.haystack.pop(index) return 0 def count(self): return len(self.haystack) def get(self, index): if self.count() <= index: return (None, None) elif index < 0: return (None, None) else: (filename, line) = self.haystack.pop(index) self.haystack.insert(index, (filename, line)) return (filename, line) def clear(self): del self.haystack[:] def codemarks(self): return self.haystack def dump(self): for i in range(len(self.haystack)): print >> sys.stderr, "cm index ", i, " ", self.haystack[i] ############################################################################# # # Basic unit test # ############################################################################# if __name__ == '__main__': cm = CodemarkManager() # # case 1, basic add, delete # print >> sys.stderr, "Initial empty" print >> sys.stderr, "cm has ", cm.count(), "items (0)" cm.append("file1", 100) cm.append("file2", 200) cm.append("file3", 300) print >> sys.stderr, "cm has " , cm.count(), "items (3) " cm.delete("file1", 100) print >> sys.stderr, "cm has " , cm.count(), "items (2)" cm.delete("file2", 100) # not existed print >> sys.stderr, "cm has " , cm.count(), "items (2)" cm.delete_index(1) print >> sys.stderr, "cm has " , cm.count(), "items (1)" # # case 2, dump # for i in range(cm.count()): (f, l) = cm.get(i) print >> sys.stderr, f, " (#", l, ")" # # case 3, duplicate # index = cm.append("file4", 400) print >> sys.stderr, "index for file4 #400 is " , index index = cm.append("file4", 400) print >> sys.stderr, "index for file4 #400 is " , index, " (again)" print >> sys.stderr, "cm has " , cm.count(), "items (2) " # # case 4, dump for eye examine # print >> sys.stderr, "cm dump for final check" cm.dump() seascope-0.7/src/view/FileView.py0000664002376300237630000001600312062273150015457 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os from PyQt4.QtGui import * from PyQt4.QtCore import * dir_prefix = None class DirTab(QWidget): sig_show_file = pyqtSignal(str) def __init__(self, parent=None): QWidget.__init__(self) self.is_ft = False # Tree view self.tmodel = QFileSystemModel() self.tmodel.setRootPath(QDir.rootPath()) self.tview = QTreeView() self.tview.setHeaderHidden(True) self.ted = QLineEdit() self.completer = QCompleter() self.completer.setCompletionMode(QCompleter.PopupCompletion) self.ted.setToolTip("Current folder") self.ted.setCompleter(self.completer) self.tdbtn = QPushButton() self.tdbtn.setIcon(QApplication.style().standardIcon(QStyle.SP_DirIcon)) self.tdbtn.setToolTip("Open folder for browsing") self.trbtn = QPushButton() self.trbtn.setIcon(QApplication.style().standardIcon(QStyle.SP_BrowserReload)) self.trbtn.setToolTip("Reset to common top-level folder of file in list") self.completer.setModel(self.tmodel) self.tview.setModel(self.tmodel) thlay = QHBoxLayout() thlay.addWidget(self.ted) thlay.addWidget(self.tdbtn) thlay.addWidget(self.trbtn) tvlay = QVBoxLayout() tvlay.addLayout(thlay) tvlay.addWidget(self.tview) self.setLayout(tvlay) self.tview.activated.connect(self.tview_itemActivated) self.tdbtn.clicked.connect(self.change_btn_cb) self.ted.editingFinished.connect(self.ted_editingFinished) self.trbtn.clicked.connect(self.reset_btn_cb) self.hide_view_columns(self.tview) def hide_view_columns(self, view): header = view.header() for col in range(header.count()): if col > 0: view.setColumnHidden(col, True) def tview_itemActivated(self): list = self.tview.selectionModel().selectedIndexes() for item in list: if self.tmodel.fileInfo(item).isFile(): self.sig_show_file.emit(self.tmodel.fileInfo(item).absoluteFilePath()) def set_tab_name(self, dirstr): # Set tab name inx = self.parent.indexOf(self) try: if dirstr != dir_prefix: name = os.path.split(dirstr)[1] else: name = '' self.parent.setTabText(inx, name) except: pass def dir_reset(self, dirstr): self.set_tab_name(dirstr) self.tview.setRootIndex(self.tmodel.index(dirstr)) self.ted.setText(dirstr) def ted_editingFinished(self): path = str(self.ted.text()) if not os.path.isdir(path): path = os.path.dirname(path) if os.path.isdir(path): self.dir_reset(path) else: self.dir_reset(dir_prefix) def change_btn_cb(self): fdlg = QFileDialog(None, "Choose directory to browse") fdlg.setFileMode(QFileDialog.Directory) fdlg.setOptions(QFileDialog.ShowDirsOnly) # and QFileDialog.HideNameFilterDetails) fdlg.setDirectory(self.ted.text()) if (fdlg.exec_()): browse_dir = fdlg.selectedFiles()[0] self.dir_reset(str(browse_dir)) def reset_btn_cb(self): self.dir_reset(dir_prefix) def resizeEvent(self, event): self.tdbtn.setMaximumHeight(self.ted.height()) self.trbtn.setMaximumHeight(self.ted.height()) class FileTab(QWidget): sig_show_file = pyqtSignal(str) def __init__(self, parent=None): QWidget.__init__(self) self.is_ft = True # List view self.le = QLineEdit() self.lview = QTreeWidget(self) self.lview.setColumnCount(2) self.lview.setHeaderLabels(['File', 'Path']) self.lview.setFont(QFont("San Serif", 8)) self.lview.setIndentation(-2) self.lview.setAllColumnsShowFocus(True) lvlay = QVBoxLayout() lvlay.addWidget(self.le) lvlay.addWidget(self.lview) self.setLayout(lvlay) self.le.textChanged.connect(self.le_textChanged) self.le.returnPressed.connect(self.le_returnPressed) self.lview.itemActivated.connect(self.lview_itemActivated) global dir_prefix dir_prefix = QDir.rootPath() def le_textChanged(self, text): if (text == ''): return self.lview.keyboardSearch('') self.lview.keyboardSearch(text) def le_returnPressed(self): self.le.clear() items = self.lview.selectedItems() if len(items) == 0: return self.lview.itemActivated.emit(items[0], 0) def lview_itemActivated(self, item): filename = str(item.data(1, Qt.DisplayRole).toString()) if self.is_rel_path: filename = filename.replace("...", dir_prefix, 1) self.sig_show_file.emit(filename) def keyPressEvent(self, ev): if ev.key() in [Qt.Key_Up, Qt.Key_Down, Qt.Key_PageUp or Qt.Key_PageDown]: self.lview.keyPressEvent(ev) return def search_file_cb(self): self.le.setFocus() self.le.selectAll() def clear(self): global dir_prefix dir_prefix = QDir.rootPath() self.is_rel_path = False self.le.clear() self.lview.clear() def add_files(self, flist): global dir_prefix self.clear() dir_prefix = os.path.dirname(os.path.commonprefix(flist)) if len(dir_prefix) > 16: self.is_rel_path = True for f in flist: if self.is_rel_path: f = f.replace(dir_prefix, "...", 1) item = QTreeWidgetItem([os.path.basename(f), f]) self.lview.addTopLevelItem(item) #if (self.lview.topLevelItemCount() > 0): #self.lview.resizeColumnToContents(0) #self.lview.resizeColumnToContents(1) self.lview.sortByColumn(0, Qt.AscendingOrder) class FileTree(QTabWidget): sig_show_file = pyqtSignal(str) def __init__(self, parent=None): QTabWidget.__init__(self) self.setMovable(True) t = FileTab() icon = QApplication.style().standardIcon(QStyle.SP_FileDialogDetailedView) self.addTab(t, icon, '') self.ft = t self.dlist = [] self.new_dir_tab_cb() self.clear() # setup popup menu self.pmenu = QMenu() self.pmenu.addAction("&New Dir View", self.new_dir_tab_cb) self.pmenu.addAction("&Close Active Dir View", self.close_active_dir_tab_cb) self.pmenu.addAction("&Close All Dir View", self.close_all_dir_tab_cb) def new_dir_tab_cb(self, d=None): t = DirTab() t.parent = self self.dlist.append(t) icon = QApplication.style().standardIcon(QStyle.SP_DirClosedIcon) self.addTab(t, icon, '') if d: t.dir_reset(d) else: t.reset_btn_cb() def close_all_dir_tab_cb(self): for t in self.dlist: inx = self.indexOf(t) self.removeTab(inx) self.dlist = [] # Always have atleast one dir view self.new_dir_tab_cb() def open_dir_view(self, filename): d = os.path.dirname(str(filename)) self.new_dir_tab_cb(d) def close_active_dir_tab_cb(self): inx = self.currentIndex() if inx < 0: return t = self.widget(inx) if t.is_ft: return if self.count() <= 2: self.close_all_dir_tab_cb() return self.dlist.remove(t) self.removeTab(inx) def addTab(self, t, icon, x): t.sig_show_file.connect(self.sig_show_file) QTabWidget.addTab(self, t, icon, x) if self.count() > 2: inx = self.indexOf(t) else: inx = 0 self.setCurrentIndex(inx) def mousePressEvent(self, m_ev): QTabWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): self.pmenu.exec_(QCursor.pos()) def search_file_cb(self): self.ft.search_file_cb() self.setCurrentWidget(self.ft) def clear(self): self.ft.clear() self.close_all_dir_tab_cb() def add_files(self, flist): self.ft.add_files(flist) for t in self.dlist: t.reset_btn_cb() seascope-0.7/src/view/__init__.py0000664002376300237630000000033012062273150015500 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD __all__ = ["CallView", "ClassGraphView", "EdView", "FileView", "ResView"] def load_plugins(): import filecontext filecontext.load_plugins()seascope-0.7/src/view/ClassGraphView.py0000664002376300237630000001360212062273150016631 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * from PyQt4.QtSvg import * import os import sys if __name__ == '__main__': import sys import os app_dir = os.path.dirname(os.path.realpath(__file__)) os.chdir(app_dir) sys.path.insert(0, os.path.abspath('..')) os.chdir(os.path.abspath('..')) from backend.plugins.PluginBase import PluginProcess class CallGraphProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir) self.name = 'call graph process' if rq == None: rq = ['', ''] self.cmd_str = rq[0] self.req = rq[1] def parse_result(self, text, sig): return [text] class ClassGraphWidget(QWidget): def __init__(self, parent, cmd_func, cmd_id, cmd_opt): QWidget.__init__(self, parent) self.is_busy = False self.is_done = False self.cmd_func = cmd_func self.cmd_id = cmd_id self.cmd_opt = cmd_opt self.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, proj_dir, inx): if self.is_done: return self.lbl.setText(['derived', 'base'][inx] + '(' + req + ')') tool_path = os.path.join('tools', 'ClassGraph.py') pargs = [sys.executable, tool_path] if inx == 1: pargs += ['-b'] pargs += ['-p', proj_dir, req] sig_res = CallGraphProcess('.', 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): self.is_busy = False self.is_done = True self.remove_progress_bar() self.svgw = QSvgWidget() self.scrolla.setWidget(self.svgw) self.svgw.load(QByteArray(res[0])) #print self.svgw.renderer().defaultSize() sz = self.svgw.sizeHint() scale = 1 if sz.width() > 1024: scale = 0.8 self.svgw.setMinimumSize(sz.width() * scale, sz.height() * scale) #self.svgw.setMaximumSize(self.svgw.sizeHint()) #print self.scrolla.sizeHint() def show_progress_bar(self): self.pbar = QProgressBar(self.scrolla) self.pbar.setMinimum(0) self.pbar.setMaximum(0) self.pbar.show() def remove_progress_bar(self): if self.pbar: self.pbar.hide() self.pbar.setParent(None) self.pbar = None class ClassGraphWindow(QMainWindow): parent = None def __init__(self, req, proj_dir, cmd_func, cmd_args, cmd_opt): QMainWindow.__init__(self, ClassGraphWindow.parent) self.req = req self.proj_dir = proj_dir 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 = 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.proj_dir, inx) def create_page(req, proj_dir, cmd_func, cmd_args, cmd_opt): w = ClassGraphWindow(req, proj_dir, cmd_func, cmd_args, cmd_opt) w.resize(900, 600) w.show() return w if __name__ == '__main__': import optparse usage = "usage: %prog [options] symbol" op = optparse.OptionParser(usage=usage) op.add_option("-p", "--project", dest="id_path", help="Idutils project dir", metavar="PROJECT") (options, args) = op.parse_args() # id utils project dir if not options.id_path: print >> sys.stderr, 'idutils project path required' sys.exit(-1) id_path = os.path.normpath(options.id_path) if not os.path.exists(os.path.join(id_path, 'ID')): print >> sys.stderr, 'idutils project path does not exist' sys.exit(-2) # symbol if len(args) != 1: print >> sys.stderr, 'Please specify a symbol' sys.exit(-3) sym = args[0] #print options.id_path, args app = QApplication(sys.argv) cmd_args = [ ['CLGRAPH', 'D', 'Derived classes'], ['CLGRAPH', 'B', 'Base classes'] ] w = create_page(sym, id_path, None, cmd_args, None) sys.exit(app.exec_()) seascope-0.7/src/view/CallView.py0000664002376300237630000001237112062273150015457 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * class CallTreeWidgetItem(QTreeWidgetItem): def __init__(self, li): QTreeWidgetItem.__init__(self, li) func = li[0] if (func == ""): self.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicatorWhenChildless) else: self.setChildIndicatorPolicy(QTreeWidgetItem.ShowIndicator) self.is_done = False def set_no_children(self): self.setChildIndicatorPolicy(QTreeWidgetItem.DontShowIndicatorWhenChildless) def column_val(self, col): return str(self.data(col, Qt.DisplayRole).toString()) def add_result(self, res): self.is_done = True res_list = [] ret_val = True for line in res: if (line[0] == ""): continue if (line[0] == self.column_val(0)): if (line [1] == self.column_val(1) and line[2] == self.column_val(2)): continue self.addChild(CallTreeWidgetItem(line)) if (self.childCount() == 0): self.set_no_children() # resize column self.treeWidget().resizeColumnToContents(0) self.treeWidget().resizeColumnToContents(1) self.treeWidget().resizeColumnToContents(2) self.treeWidget().resizeColumnToContents(3) # hdr #self.treeWidget().header().setDefaultAlignment(Qt.AlignRight) return ret_val class CallTreeWidget(QTreeWidget): sig_show_file_line = pyqtSignal(str, int) def __init__(self, parent, cmd_func, cmd_id, cmd_opt, hint_file): QTreeWidget.__init__(self, parent) self.is_busy = False self.cmd_func = cmd_func self.cmd_id = cmd_id self.cmd_opt = cmd_opt self.hint_file = hint_file self.itemExpanded.connect(self.ctree_itemExpanded) self.itemActivated.connect(self.ctree_itemActivated) self.setExpandsOnDoubleClick(False) self.setColumnCount(4) self.setHeaderLabels(['Tag', 'File', 'Line', 'Text']) self.setSelectionMode(QAbstractItemView.SingleSelection) #self.resize(QSize(800, 500)) self.setMinimumWidth(800) self.setMinimumHeight(500) ##sel behaviour #self.setSelectionBehavior(QAbstractItemView.SelectRows) ## set the font self.setFont(QFont("San Serif", 8)) #self.setTextElideMode(Qt.ElideLeft) self.setAllColumnsShowFocus(True) def add_root(self, name): parent = CallTreeWidgetItem([name, '', '', '']) self.addTopLevelItem(parent) parent.setExpanded(True) def mousePressEvent(self, m_ev): QTreeWidget.mousePressEvent(self, m_ev) if (m_ev.button() == Qt.RightButton): self.last_minx = self.indexAt(m_ev.pos()) def ctree_itemActivated(self, item, col): filename = item.column_val(1) try: line = int(item.column_val(2)) except: return self.sig_show_file_line.emit(filename, line) def ctree_itemExpanded(self, item): if (item.is_done): return tag = str(item.data(0, Qt.DisplayRole).toString()) if str(item.data(1, Qt.DisplayRole).toString()) == '': opt = self.cmd_opt else: opt = None if (self.is_busy): return self.is_busy = True self.pbar = QProgressBar(self) self.pbar.setMinimum(0) self.pbar.setMaximum(0) self.pbar.show() ## add result rquery = {} rquery['cmd'] = self.cmd_id rquery['req'] = tag rquery['opt'] = opt hfile = str(item.data(1, Qt.DisplayRole).toString()) if hfile == '': hfile = self.hint_file rquery['hint_file'] = hfile sig_res = self.cmd_func(rquery) self.query_item = item sig_res[0].connect(self.ctree_add_result) def ctree_add_result(self, req, res): self.query_item.add_result(res) self.is_busy = False if self.pbar: self.pbar.setParent(None) self.pbar = None class CallTreeWindow(QMainWindow): sig_show_file_line = pyqtSignal(str, int) parent = None def __init__(self, req, cmd_func, cmd_args, cmd_opt, hint_file): QMainWindow.__init__(self, CallTreeWindow.parent) self.req = req self.setWindowTitle(req) self.setFont(QFont("San Serif", 8)) w = QWidget() self.setCentralWidget(w) self.vlay = QVBoxLayout() w.setLayout(self.vlay) self.sw = QStackedWidget() self.hlay = QHBoxLayout() self.vlay.addLayout(self.hlay) self.vlay.addWidget(self.sw) self.bgrp = QButtonGroup() self.bgrp.buttonClicked.connect(self.set_current) self.bgrp.setExclusive(True) self.btn = [] self.ctree = [] for inx in range(len(cmd_args)): # cmd format: [ cmd_id, cmd_str, cmd_tip ] cmd = cmd_args[inx] btn = QToolButton() btn.setText(cmd[1]) btn.setToolTip(cmd[2]) #btn.setFlat(True) btn.setCheckable(True) self.bgrp.addButton(btn, inx) self.hlay.addWidget(btn) ct = CallTreeWidget(self, cmd_func, cmd[0], cmd_opt, hint_file) ct.sig_show_file_line.connect(self.sig_show_file_line) self.sw.addWidget(ct) self.btn.append(btn) self.ctree.append(ct) self.hlay.addStretch(0) self.set_current(self.btn[0]) def set_current(self, btn): inx = self.bgrp.id(btn) self.btn[inx].setChecked(True) self.sw.setCurrentIndex(inx) ct = self.ctree[inx] if ct.topLevelItemCount() == 0: ct.add_root(self.req) ct.setFocus() def ctree_show_file_line(filename, line): parent = CallTreeWindow.parent parent.raise_() parent.activateWindow() parent.show_file_line(filename, line) def create_page(req, cmd_func, cmd_args, cmd_opt, hint_file): w = CallTreeWindow(req, cmd_func, cmd_args, cmd_opt, hint_file) w.sig_show_file_line.connect(ctree_show_file_line) w.show() seascope-0.7/src/view/EdViewRW.py0000664002376300237630000000754012062273150015407 0ustar anilanil#!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import re from PyQt4 import QtGui from PyQt4.QtGui import * from PyQt4.QtCore import * from EdView import * # inherit from EditView, add editing support. class EditorViewRW(EditorView): sig_file_modified = pyqtSignal(bool) def __init__(self, parent=None): EditorView.__init__(self, parent) # use default settings. EditorView.ed_settings_1(self) def open_file(self, filename): self.filename = filename ## Choose a lexer if not self.lexer: if (re.search('\.(py|pyx|pxd|pxi|scons)$', filename) != None): self.lexer = QsciLexerPython() else: self.lexer = QsciLexerCPP() ## Braces matching self.setBraceMatching(QsciScintilla.SloppyBraceMatch) ## Render on screen self.show() ## 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.show() self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setFocus() def modifiedChanged(self): self.sig_file_modified.emit(self.isModified()) # FIXME: too simple for big files or remote files. def save_file(self, filename): if(self.isModified()): fobj = open(filename, 'w') if (not fobj.closed): fobj.write(str(self.text().toUtf8())) fobj.flush() fobj.close() self.setModified(False) class EditorPageRW(EditorPage): def new_editor_view(self): return EditorViewRW(self) class EditorBookRW(EditorBook): def new_editor_page(self): return EditorPageRW() def save_file_at_inx(self, inx): if inx < 0: return page = self.widget(inx) filename = page.get_filename() if filename: page.ev.save_file(filename) page.fcv.rerun(filename) def save_current_page(self): inx = self.currentIndex() self.save_file_at_inx(inx) def save_tab_list(self, inx_list): for inx in inx_list: self.save_file_at_inx(inx) def save_all_file(self): inx_list = range(self.count()) self.save_tab_list(inx_list) def page_modified_cb(self, isModifiled): inx = self.currentIndex() filename = self.tabText(inx) # Sign modified. if isModifiled: filename = "*" + filename self.setTabText(inx, filename) else: filename = str(filename) filename = filename.strip('*') self.setTabText(inx, filename) 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.7/src/view/DebugView.py0000664002376300237630000000312512062273150015627 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys import os import string from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * class DebugInfoEntry(QFrame): def __init__(self, parent=None): QFrame.__init__(self) self.vlay = QVBoxLayout() self.setLayout(self.vlay) #def add_result_continue(self): #self.add_result(self.name, self.res) def add_result(self, cmd, out, err): #self.setFrameStyle(QFrame.StyledPanel | QFrame.Plain) self.cmd_lbl = QLabel() self.cmd_lbl.setText(cmd) self.vlay.addWidget(self.cmd_lbl) #if err != None and err != '': #self.err_lbl = QLabel() #self.err_lbl.setText('Error: ' + err) #self.vlay.addWidget(self.err_lbl) #self.res_lbl = QLabel() #self.res_lbl.setText(out) #self.vlay.addWidget(self.res_lbl) #self.res_lbl.hide() class DebugWindow(QMainWindow): dlg = None def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.ui = uic.loadUi('ui/debug.ui', self) self.vlay = self.ui.dbg_widget.layout() def append_widget(self, w): self.vlay.addWidget(w) def run_dialog(self): self.ui.show() vbar = self.ui.dbg_scroll_area.verticalScrollBar() vbar.setValue(vbar.maximum()) self.ui.show() def closeEvent(self, e): DebugWindow.dlg = None def show_dbg_dialog(parent): if (DebugWindow.dlg == None): DebugWindow.dlg = DebugWindow(parent) DebugWindow.dlg.run_dialog() def connect_to_sig(sig_res): if (DebugWindow.dlg == None): return entry = DebugInfoEntry() DebugWindow.dlg.append_widget(entry) sig_res.connect(entry.add_result) seascope-0.7/src/view/FileContextView.py0000664002376300237630000000412012062273150017021 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtGui import * from PyQt4.QtCore import * import filecontext class FileContextView(QTabWidget): sig_goto_line = pyqtSignal(int) sig_ed_cursor_changed = pyqtSignal(int, int) def __init__(self, parent=None): QTabWidget.__init__(self) self.setTabPosition(QTabWidget.South) def add_page(self, page, title): page.sig_goto_line.connect(self.sig_goto_line) self.addTab(page, title) self.setCurrentWidget(page) def run(self, filename): self.filename = filename filecontext.run_plugins(filename, self) def rerun(self, filename): inx = self.currentIndex() self.clear() self.run(filename) self.setCurrentIndex(inx) def focus_search_ctags(self): for inx in range(self.count()): page = self.widget(inx) if hasattr(page, 'le') and hasattr(page.le, 'setFocus'): self.setCurrentWidget(page) page.le.setFocus() break def get_already_opened_cmd_list(self): a_cmd_list = [] for inx in range(self.count()): page = self.widget(inx) if hasattr(page, 'cmd'): a_cmd_list.append(page.cmd) return a_cmd_list def get_plugin_cmd_list(self): a_cmd_list = self.get_already_opened_cmd_list() cmd_list = [] for p in filecontext.fc_plugins: if not hasattr(p, 'cmd_name'): continue cmd_name = p.cmd_name() if not cmd_name: continue if not isinstance(cmd_name, list): if cmd_name == '': continue cmd_name = [ cmd_name ] for cmd in cmd_name: if cmd in a_cmd_list: continue cmd_list.append((cmd, p)) return cmd_list def menu_act_triggered_cb(self, act): act.plugin.run_plugin(self.filename, self, cmd=act.cmd_name) def mousePressEvent(self, m_ev): cmd_list = self.get_plugin_cmd_list() if len(cmd_list) == 0: return if (m_ev.button() == Qt.RightButton): # setup popup menu pmenu = QMenu() pmenu.triggered.connect(self.menu_act_triggered_cb) for (cmd_name, p) in cmd_list: act = pmenu.addAction(cmd_name) act.plugin = p act.cmd_name = cmd_name pmenu.exec_(QCursor.pos()) pmenu = None seascope-0.7/src/icons/0000775002376300237630000000000012062273150013534 5ustar anilanilseascope-0.7/src/icons/seascope.svg0000664002376300237630000000750512062273150016066 0ustar anilanil Seascope image/svg+xml Seascope Anil Kumar Seascope logo http://seascope.googlecode.com S seascope-0.7/src/icons/go-jump.png0000664002376300237630000000112312062273150015615 0ustar anilanilPNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8ARQtzTSavCaꈋ6pnʕM wB [IndIxBՋ~|s5q2pag8N7g 84Ml|>@D5[^x0~x<~D;lJo_JnkE@D|"rh=`!Li"8 XJefR73!l`ڢײeYρu@/W^wڌD" V.\p8mJeZ&ZXFv f3<c# p%A~&~0{Bo۶?-a`qc `Y4, &ޮjw29)Jg4}0MsbFٷE",ν^$J=mWK]Â/bX,IENDB`seascope-0.7/src/icons/cut.png0000664002376300237630000000134412062273150015037 0ustar anilanilPNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<aIDAT8uKq?ut7 d0 AIJ"nC ܡЛa bl4X.d.{<}Q"S.2p gS `-spxI8HæifR[drHDd292M3#"V/ ) vDWDӽn{ "#ׁrRFG#T*~Tiaa#P(X, X5 cݶ큵acccODdsNifw].ײRt>rwnCSåˑH$;33ӷZ~F(1 "B0jYֽ@: =VDlܿH7Ri4_f2"hh>3?vvv@E%Q0VM`yqq#iJ"wSJ&&&6+`X,憇c.JMI=SDNwwwNNN o"x.Ji 矩dYVl>Zil>驴_,+.r#`W` y }IENDB`seascope-0.7/src/icons/codeview.png0000664002376300237630000000107212062273150016047 0ustar anilanilPNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT81QDd`3 bambA alBV [fw;I0섉ɵy!)ywD>7}6`k7:'mtza,'21fs5Қc`5ȉ F'ܦ;}/T#I.=bTs$Q:Xplz׫ N`*Js<;Y*>tK0zAVA#㼦wbFnρ0-xSs6_x`bQFF_Km_suL +2ujf0ߖ 5N6F7jBIENDB`seascope-0.7/src/icons/save.png0000664002376300237630000000106012062273150015175 0ustar anilanilPNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT81Q;J&ň,bI5Qll[`XBHcRdAa ۈn62$ 8<>WcN*mA ?8]I$u<{#颼3r||qbLRh> :FE$YYޖcߐ=Iے='(7(}^Hz[*$u|W ~i:[,/SCq|)|pi9W+Rm :);bͫh4z2LIz7p8\pw6zev}1Nts\B%I&I#)d[f-IENDB`seascope-0.7/src/icons/copy.png0000664002376300237630000000102512062273150015212 0ustar anilanilPNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8nQYmkK)Ie+-@KAEAbet.x^7 h"HHŊ#fFΙsL#`\k`<|.@)0$'IYRUK`6ɖTZ,mݹ\.kIvZv}|t%%;dg_/ ?lc鷡{xW@4Y# _ B_r⎂$jڄp8|CpH퓲,0Ȳ9X5*(<˲ Ye7EQ9+T`4}fն7`[:+\ <Zqmz xdr1N;ͭVn<eϔWv.do;3IENDB`seascope-0.7/src/icons/redo.png0000664002376300237630000000105612062273150015175 0ustar anilanilPNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8œ?kZq{.RE[S(q* vV E_@D`ݵR@El`[)m&rOkɐ%X)r|ܫV{HU x#"EGJ00F)p "BDp-z!""b8VrWE̛恮#x<~j^H)].7kZ+EO2t:=f[N~fd*4BDW 74d 0i`P5-۶ 0b85MwPxڕ$`S};N}e% U*c) nw7ɼ&5Q6m.p975>:ڀ?; 9IENDB`seascope-0.7/src/icons/undo.png0000664002376300237630000000105312062273150015206 0ustar anilanilPNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8Փ1hZaO!fPtuynqꖥ \:9tt;ۡH]; h)fhF*AHjv꒥ß;?wǝn}B bl -l㯀o@`"ds#Mb}вzF="Mz;L&q.p cSuF;"ؕJew0ԁMQ aĻ|jL&fXklr\N/Ɓ>-Zvi}RG2r]xNwv]`#Aa;}qNZlmd<BVJv*z?r9,JfC˲# 46p΀@9pMEݳl2IENDB`seascope-0.7/src/icons/find-replace.png0000664002376300237630000000136212062273150016575 0ustar anilanilPNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<oIDAT8uKQ?g;oEl kk).$ A.+ JƁ`P0FWԆ`VRR(`nzLx9|k$Q-f<$ IVR霵1fZ4LT+WVM4 ^欵/50SeȺ---ۆg%tjzz|$IoK e~433sZRMEC|||u]ZpJҦx #P-//Ǻ!kyB-H|(_t:}<;/5cwGFF$m(ƺT*ucƘqpF/I WLy}CCCɝZ[[/:GP{{c+ı켕f_HI-is1I{2L)2p?LTX IڷIJd23\nJka#<ό,Ip <zb@+x9t9IENDB`seascope-0.7/src/icons/paste.png0000664002376300237630000000100712062273150015354 0ustar anilanilPNG  IHDRasBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDAT8AK@-饴=B)xx }h@؃!–e ]6j'5#%oIHHjGQ:0 ף(Z$7jv_BNFƞv`$xwg! 1T4\TIikJ )4.5) and qscintilla-python\nError: program aborted.' sys.exit(-1) try: from PyQt4.QtGui import * from PyQt4.QtCore import * from view import EdView, EdViewRW, ResView, FileView, CallView, ClassGraphView, DebugView, CodemarkView import backend from backend.plugins import PluginHelper import DialogManager import view except ImportError: print "Error: failed to import supporting packages.\nError: program aborted." sys.exit(-1) class SeascopeApp(QMainWindow): def file_preferences_cb(self): ev_font = QFont() ev_font.fromString(self.edit_book.ev_font) res = DialogManager.show_preferences_dialog(self.app_style, self.edit_ext_cmd, ev_font, self.exit_dont_ask, self.inner_editing, self.eb_is_show_line) (self.app_style, self.app_font, self.edit_ext_cmd, ev_font, self.exit_dont_ask, self.inner_editing, 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.edit_book.show_line_number_pref(self.eb_is_show_line) self.app_write_config() def file_close_cb(self): self.edit_book.close_current_page() def closeEvent(self, ev): if not self.exit_dont_ask and backend.proj_is_open(): ret = DialogManager.show_yes_no_dontask('Close project and quit?') if ret == 1: ev.ignore() return if ret == 2: self.exit_dont_ask = True # extra proc for editing enabled if self.inner_editing: self.edit_book.close_all_cb() self.app_write_config() ev.accept() def file_restart_cb(self): if not DialogManager.show_yes_no('Restart ?'): return hint = self.edit_book.get_file_line_list() self.proj_close_cb() QApplication.quit() os.environ['SEASCOPE_RESTART_HINT'] = '%s' % str(hint) QProcess.startDetached(sys.executable, QApplication.arguments()); def file_restarted_cb(self): try: hint = os.environ['SEASCOPE_RESTART_HINT'] #del os.environ['SEASCOPE_RESTART_HINT'] fll = eval(hint) for fl in fll: try: (f, l) = fl.rsplit(':', 1) l = int(l) self.edit_book.show_file_line(f, l, hist=False) except Exception as e: print e pass except: pass def codemark_add(self, f, l): self.cm_mgr.append(f, l) self.edit_book.codemark_add(f, l - 1) actionText = QString(f + " : " + str(l)) act = QAction(actionText, self) self.cm_actionGroup.addAction(act) self.m_cm.addAction(act) def codemark_delete(self, f, l): self.cm_mgr.delete(f, l) self.edit_book.codemark_del(f, l - 1) actionText = QString(f + " : " + str(l)) actions = self.cm_actionGroup.actions() for act in actions: if actionText == act.text(): self.cm_actionGroup.removeAction(act) def codemark_toggle_cb(self): (f, l) = self.edit_book.get_current_file_line() if self.cm_mgr.check(f, l) == 0: self.codemark_add(f, l) else: self.codemark_delete(f, l) def codemark_del_file_cb(self, filename): if filename == '': return for f, l in reversed(self.cm_mgr.codemarks()): if f == filename: self.codemark_delete(f, l) def codemark_del_all_cb(self): if not self.cm_mgr.count(): return if not DialogManager.show_yes_no('Delete all codemarks ?'): return for f, l in reversed(self.cm_mgr.codemarks()): self.codemark_delete(f, l) def codemark_go(self, action): for f, l in self.cm_mgr.codemarks(): if action.text() == QString(f + " : " + str(l)): self.edit_book.show_file_line(f, l) def go_prev_res_cb(self): self.res_book.go_next_res(-1) def go_next_res_cb(self): self.res_book.go_next_res(+1) def go_prev_pos_cb(self): self.res_book.go_next_history(-1) def go_next_pos_cb(self): self.res_book.go_next_history(+1) def go_pos_history_cb(self): self.res_book.show_history() def go_search_file_list_cb(self): self.file_view.search_file_cb() def go_search_ctags_cb(self): self.edit_book.focus_search_ctags() def help_about_cb(self): DialogManager.show_about_dialog() def external_editor_cb(self): self.edit_book.open_in_external_editor(self.edit_ext_cmd) def show_dbg_dialog(self): DebugView.show_dbg_dialog(self) def create_mbar(self): menubar = self.menuBar() m_file = menubar.addMenu('&File') m_file.addAction('&Preferences', self.file_preferences_cb) m_file.addAction('&Debug', self.show_dbg_dialog, 'Ctrl+D') m_file.addSeparator() if self.inner_editing: m_file.addAction('&Save', self.edit_book.save_current_page, 'Ctrl+S') m_file.addAction('&Close', self.file_close_cb, QKeySequence.Close) m_file.addSeparator() m_file.addAction('&Restart', self.file_restart_cb, QKeySequence.Quit) m_file.addAction('&Quit', self.close, QKeySequence.Quit) m_edit = menubar.addMenu('&Edit') if self.inner_editing: m_edit.addAction('Undo', self.edit_book.undo_edit_cb, 'Ctrl+Z') m_edit.addAction('Rebo', self.edit_book.redo_edit_cb, 'Ctrl+Y') m_edit.addSeparator() m_edit.addAction('Copy', self.edit_book.copy_edit_cb, 'Ctrl+C') if self.inner_editing: m_edit.addAction('Paste', self.edit_book.paste_edit_cb, 'Ctrl+V') m_edit.addAction('Cut', self.edit_book.cut_edit_cb, 'Ctrl+X') m_edit.addSeparator() m_edit.addAction('&Find...', self.edit_book.find_cb, 'Ctrl+F') m_edit.addAction('Find &Next', self.edit_book.find_next_cb, 'F3') m_edit.addAction('Find &Previous', self.edit_book.find_prev_cb, 'Shift+F3') m_edit.addSeparator() self.edit_book.m_show_line_num = m_edit.addAction('Show line number', self.edit_book.show_line_number_cb, 'F11') self.edit_book.m_show_line_num.setCheckable(True) self.edit_book.m_show_line_num.setChecked(True) self.show_toolbar = m_edit.addAction('Show toolbar', self.show_toolbar_cb, 'F4') self.show_toolbar.setCheckable(True) m_edit.addSeparator() self.edit_book.m_show_folds = m_edit.addAction('Show folds', self.edit_book.show_folds_cb) self.edit_book.m_show_folds.setCheckable(True) self.toggle_folds = m_edit.addAction('Toggle folds', self.edit_book.toggle_folds_cb) m_edit.addSeparator() m_edit.addAction('Matching brace', self.edit_book.matching_brace_cb, 'Ctrl+6') m_edit.addAction('Goto line', self.edit_book.goto_line_cb, 'Ctrl+G') m_edit.addAction('External editor', self.external_editor_cb, 'Ctrl+E'); m_prj = menubar.addMenu('&Project') m_prj.addAction('&New Project', self.proj_new_cb) m_prj.addAction('&Open Project', self.proj_open_cb) m_prj.addSeparator() act = m_prj.addAction('&Settings', self.proj_settings_cb) act.setDisabled(True) backend.prj_actions.append(act) act = m_prj.addAction('&Close Project', self.proj_close_cb) act.setDisabled(True) backend.prj_actions.append(act) self.backend_menu = menubar.addMenu('') self.m_cm = menubar.addMenu('&Codemark') self.m_cm.addAction('Toggle codemark', self.codemark_toggle_cb, 'Ctrl+B') self.m_cm.addAction('Delete all codemarks', self.codemark_del_all_cb, '') self.m_cm.addSeparator() self.m_cm.addAction('Previous bookmark', self.edit_book.bookmark_prev_cb, 'Alt+PgUp') self.m_cm.addAction('Next bookmark', self.edit_book.bookmark_next_cb, 'Alt+PgDown') self.m_cm.addSeparator() self.cm_actionGroup = QActionGroup(self, triggered=self.codemark_go) m_go = menubar.addMenu('&Go') m_go.addAction('Previous Result', self.go_prev_res_cb, 'Alt+Up') m_go.addAction('Next Result', self.go_next_res_cb, 'Alt+Down') m_go.addSeparator() m_go.addAction('Previous Position', self.go_prev_pos_cb, 'Alt+Left') m_go.addAction('Next Position', self.go_next_pos_cb, 'Alt+Right') m_go.addAction('Position History', self.go_pos_history_cb, 'Ctrl+H') m_go.addSeparator() m_go.addAction('Search file list', self.go_search_file_list_cb, 'Ctrl+Shift+O') m_go.addAction('Search ctags', self.go_search_ctags_cb, 'Ctrl+Shift+T') m_help = menubar.addMenu('&Help') m_help.addAction('About Seascope', self.help_about_cb) m_help.addAction('About Qt', QApplication.aboutQt) def create_toolbar(self): self.toolbar = self.addToolBar('Toolbar') self.toolbar.setIconSize(QSize(16,16)) self.toolbar.setToolButtonStyle(Qt.ToolButtonIconOnly) si = QApplication.style().standardIcon #(QStyle.SP_DirClosedIcon) # exit self.toolbar.addAction(si(QStyle.SP_TitleBarCloseButton), 'Quit', self.close) # edit related # if need editing support if self.inner_editing: self.toolbar.addSeparator() self.toolbar.addAction(si(QStyle.SP_DialogSaveButton), 'Save', self.edit_book.save_current_page) self.toolbar.addSeparator() self.toolbar.addAction(QIcon('icons/undo.png'), 'Undo', self.edit_book.undo_edit_cb) self.toolbar.addAction(QIcon('icons/redo.png'), 'Redo', self.edit_book.redo_edit_cb) self.toolbar.addSeparator() self.toolbar.addAction(QIcon('icons/cut.png'), 'Cut', self.edit_book.cut_edit_cb) self.toolbar.addAction(QIcon('icons/copy.png'), 'Copy', self.edit_book.copy_edit_cb) self.toolbar.addAction(QIcon('icons/paste.png'), 'Paste', self.edit_book.paste_edit_cb) self.toolbar.addSeparator() self.toolbar.addAction(QIcon('icons/find-replace.png'), 'Find & Replace', self.edit_book.find_cb) # find self.toolbar.addSeparator() self.toolbar.addAction(si(QStyle.SP_FileDialogContentsView), 'Find', self.edit_book.find_cb) self.toolbar.addAction(si(QStyle.SP_ArrowDown), 'Find Next', self.edit_book.find_next_cb) self.toolbar.addAction(si(QStyle.SP_ArrowUp), 'Find Previous', self.edit_book.find_prev_cb) self.toolbar.addSeparator() # goto self.toolbar.addAction(QIcon('icons/go-jump.png'), 'Go to line', self.edit_book.goto_line_cb) self.toolbar.addSeparator() # code view self.toolbar.addAction(si(QStyle.SP_FileDialogListView), 'Search ctags', self.go_search_ctags_cb) self.toolbar.addAction(si(QStyle.SP_FileDialogDetailedView), 'Search file list', self.go_search_file_list_cb) self.toolbar.addSeparator() self.toolbar.addAction(si(QStyle.SP_MediaSeekBackward), 'Previous Result', self.go_prev_res_cb) self.toolbar.addAction(si(QStyle.SP_MediaSeekForward), 'Next Result', self.go_next_res_cb) self.toolbar.addSeparator() self.toolbar.addAction(si(QStyle.SP_MediaSkipBackward), 'Previous Position', self.go_prev_pos_cb) self.toolbar.addAction(si(QStyle.SP_MediaSkipForward), 'Next Position', self.go_next_pos_cb) self.toolbar.addSeparator() self.toolbar.addAction(QIcon('icons/codeview.png'), 'Code Quick View', self.is_code_quick_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.edit_ext_cmd = 'x-terminal-emulator -e vim %F +%L' self.eb_is_show_line = False path = self.app_get_config_file() if (not os.path.exists(path)): return cf = open(path, 'r') for line in cf: line = line.split('=', 1) key = line[0].strip() if (key == 'recent_projects'): for path in line[1].split(','): path=path.strip() if (os.path.isdir(path)): self.recent_projects.append(path) if (key == 'app_style'): self.app_style = line[1].split('\n')[0] if (key == 'app_font'): self.app_font = line[1].split('\n')[0] if (key == 'edit_font'): self.ev_font = line[1].split('\n')[0] if (key == 'edit_show_line_num'): if ('true' == line[1].split('\n')[0]): self.eb_is_show_line = True if (key == 'show_toolbar'): if ('true' == line[1].split('\n')[0]): self.is_show_toolbar = True else: self.is_show_toolbar = False if (key == 'edit_ext_cmd'): self.edit_ext_cmd = line[1] if (key == 'exit_dont_ask'): if ('true' == line[1].split('\n')[0]): self.exit_dont_ask = True if (key == 'inner_editing'): if ('true' == line[1].split('\n')[0]): self.inner_editing_conf = True else: self.inner_editing_conf = False if os.getenv("SEASCOPE_EDIT"): self.inner_editing = True else: self.inner_editing = self.inner_editing_conf cf.close() def app_write_config(self): cf = open(self.app_get_config_file(), 'w') cf.write('recent_projects' + '=' + string.join(self.recent_projects, ',')+ '\n') if (self.app_style): cf.write('app_style' + '=' + self.app_style + '\n') if (self.app_font): cf.write('app_font' + '=' + self.app_font + '\n') if (self.ev_font): cf.write('edit_font' + '=' + self.ev_font + '\n') if (self.inner_editing_conf): cf.write('inner_editing' + '=' + 'true' + '\n') else: cf.write('inner_editing' + '=' + 'false' + '\n') if (self.eb_is_show_line): cf.write('edit_show_line_num' + '=' + 'true' + '\n') if (self.is_show_toolbar): cf.write('show_toolbar' + '=' + 'true' + '\n') if (self.exit_dont_ask): cf.write('exit_dont_ask' + '=' + 'true' + '\n') if (self.edit_ext_cmd): cf.write('edit_ext_cmd' + '=' + self.edit_ext_cmd + '\n') cf.close() def update_recent_projects(self, path): if (path == None or path == ""): return new_list = [path] for ele in self.recent_projects: if ele != path: new_list.append(ele) self.recent_projects = new_list self.app_write_config() # project menu functions def proj_new_or_open(self): self.editor_tab_changed_cb(None) self.update_recent_projects(backend.proj_dir()) def proj_new_cb(self): if (backend.proj_is_open()): if (not DialogManager.show_proj_close()): return self.proj_close_cb() if backend.proj_new(): self.proj_new_or_open() def proj_open(self, proj_path): rc = backend.proj_open(proj_path) if not rc: print 'proj_open', proj_path, 'failed' return self.proj_new_or_open() def proj_open_cb(self): proj_path = DialogManager.show_project_open_dialog(self.recent_projects) if (proj_path != None): if backend.proj_is_open(): self.proj_close_cb() self.proj_open(proj_path) def proj_close_cb(self): self.update_recent_projects(backend.proj_dir()) self.setWindowTitle("Seascope") backend.proj_close() if self.inner_editing: self.edit_book.close_all_cb() else: self.edit_book.clear() self.res_book.clear() self.file_view.clear() self.cm_mgr.clear() def proj_settings_cb(self): backend.proj_settings_trigger() def editor_tab_changed_cb(self, fname): #title = backend.proj_name() prj_dir = backend.proj_dir() if prj_dir: parent = prj_dir home_dir = os.path.expanduser('~') for i in range(2): parent = os.path.dirname(parent) if parent == home_dir: break title = os.path.relpath(prj_dir, parent) if not prj_dir: title = 'Seascope' if fname and fname != '': fname = str(fname) #if fname.startswith(prj_dir): #fname = os.path.relpath(fname, prj_dir) title = title + ' - ' + fname else: fname = 'Seascope' title = title + ' - ' + fname self.setWindowTitle(title) def show_file_line(self, filename, line): self.edit_book.show_file_line(filename, line) def show_toolbar_cb(self): self.is_show_toolbar = self.show_toolbar.isChecked() if (self.is_show_toolbar): self.create_toolbar() else: self.removeToolBar(self.toolbar) def is_code_quick_view(self): QMessageBox.information(None, "Seascope", 'Not implemented yet!', QMessageBox.Ok) 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) 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.vsp.setSizes([1, 1]) 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.show_toolbar.setChecked(self.is_show_toolbar) def create_widgets(self): if self.inner_editing: self.edit_book = EdViewRW.EditorBookRW() else: self.edit_book = EdView.EditorBook() self.res_book = ResView.ResultManager() self.file_view = FileView.FileTree() self.cm_mgr = CodemarkView.CodemarkManager() self.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 PluginHelper.backend_menu = self.backend_menu PluginHelper.edit_book = self.edit_book PluginHelper.res_book = self.res_book PluginHelper.call_view = CallView PluginHelper.class_graph_view = ClassGraphView PluginHelper.file_view = self.file_view PluginHelper.dbg_view = DebugView def setup_style_and_font(self): if self.app_style: QApplication.setStyle(self.app_style) if self.app_font: font = QFont() font.fromString(self.app_font) QApplication.setFont(font) def __init__(self, parent=None): QMainWindow.__init__(self) self.app_read_config() self.create_widgets() self.setup_widget_hints() self.connect_signals() self.setup_widget_tree() self.setup_style_and_font() if len(self.recent_projects): self.proj_open(self.recent_projects[0]) #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_dir = os.path.dirname(os.path.realpath(__file__)) os.chdir(app_dir) backend.load_plugins() view.load_plugins() app = QApplication(sys.argv) ma = SeascopeApp() ma.show() ret = app.exec_() sys.exit(ret) seascope-0.7/src/backend/0000775002376300237630000000000012062273150014010 5ustar anilanilseascope-0.7/src/backend/plugins/0000775002376300237630000000000012062273150015471 5ustar anilanilseascope-0.7/src/backend/plugins/cscope/0000775002376300237630000000000012062273150016745 5ustar anilanilseascope-0.7/src/backend/plugins/cscope/ui/0000775002376300237630000000000012062273150017362 5ustar anilanilseascope-0.7/src/backend/plugins/cscope/ui/cs_query.ui0000664002376300237630000000702012062273150021552 0ustar anilanil QueryDialog Qt::ApplicationModal 0 0 357 171 Cscope Query 40 16777215 Type false Symbol true 10 50 16777215 Substring Case Insensitive Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qd_sym_inp qd_substr_chkbox qd_icase_chkbox buttonBox qd_cmd_inp buttonBox accepted() QueryDialog accept() 248 254 157 274 buttonBox rejected() QueryDialog reject() 316 260 286 274 seascope-0.7/src/backend/plugins/cscope/ui/cs_project_settings.ui0000664002376300237630000001640312062273150024000 0ustar anilanil 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.7/src/backend/plugins/cscope/__init__.py0000664002376300237630000000065312062273150021062 0ustar anilanil# 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.7/src/backend/plugins/cscope/CscopeProjectUi.py0000664002376300237630000001703212062273150022363 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase from ..PluginBase import QueryUiBase from .. import PluginBase, PluginHelper cmd_table = [ [ ['REF', '0'], ['&References', 'Ctrl+0'], ['References to' ] ], [ ['DEF', '1'], ['&Definitions', 'Ctrl+1'], ['Definition of' ] ], [ ['<--', '2'], ['&Called Functions', 'Ctrl+2'], ['Functions called by' ] ], [ ['-->', '3'], ['C&alling Functions', 'Ctrl+3'], ['Functions calling' ] ], [ ['TXT', '4'], ['Find &Text', 'Ctrl+4'], ['Find text' ] ], [ ['GRP', '5'], ['Find &Egrep', 'Ctrl+5'], ['Find egrep pattern' ] ], [ ['FIL', '7'], ['Find &File', 'Ctrl+7'], ['Find files' ] ], [ ['INC', '8'], ['&Including Files', 'Ctrl+8'], ['Find #including' ] ], [ ['---', None], [None ] ], [ ['QDEF', '11'], ['&Quick Definition', 'Ctrl+]'], [None ] ], [ ['CTREE','12'], ['Call Tr&ee', 'Ctrl+\\'], ['Call tree' ] ], [ ['---', None], [None ], ], [ ['UPD', '25'], ['Re&build Database', None ], [None ] ], ] menu_cmd_list = [ [c[0][0]] + c[1] for c in cmd_table ] cmd_str2id = {} cmd_str2qstr = {} cmd_qstr2str = {} for c in cmd_table: if c[0][1] != None: cmd_str2id[c[0][0]] = c[0][1] cmd_str2qstr[c[0][0]] = c[2][0] cmd_qstr2str[c[2][0]] = c[0][0] # python 2.7 #cmd_str2id = { c[0][0]:c[0][1] for c in cmd_table if c[0][1] != None } #cmd_str2qstr = { c[0][0]:c[2][0] for c in cmd_table if c[0][1] != None } #cmd_qstr2str = { c[2][0]:c[0][0] for c in cmd_table if c[0][1] != None } cmd_qstrlist = [ c[2][0] for c in cmd_table if c[0][1] != None and c[2][0] != None ] ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], ['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] class QueryDialog(QDialog): dlg = None def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('backend/plugins/cscope/ui/cs_query.ui', self) self.qd_sym_inp.setAutoCompletion(False) self.qd_sym_inp.setInsertPolicy(QComboBox.InsertAtTop) self.qd_cmd_inp.addItems(cmd_qstrlist) def run_dialog(self, cmd_str, req): s = cmd_str2qstr[cmd_str] inx = self.qd_cmd_inp.findText(s) self.qd_cmd_inp.setCurrentIndex(inx) if (req == None): req = '' self.qd_sym_inp.setFocus() self.qd_sym_inp.setEditText(req) self.qd_sym_inp.lineEdit().selectAll() self.qd_substr_chkbox.setChecked(False) self.qd_icase_chkbox.setChecked(False) self.show() if (self.exec_() == QDialog.Accepted): req = str(self.qd_sym_inp.currentText()) s = str(self.qd_cmd_inp.currentText()) cmd_str = cmd_qstr2str[s] #self.qd_sym_inp.addItem(req) if (req != '' and self.qd_substr_chkbox.isChecked()): req = '.*' + req + '.*' opt = None if (self.qd_icase_chkbox.isChecked()): opt = '-C' res = (cmd_str, req, opt) return res return None @staticmethod def show_dlg(cmd_str, req): if (QueryDialog.dlg == None): QueryDialog.dlg = QueryDialog() return QueryDialog.dlg.run_dialog(cmd_str, req) def show_msg_dialog(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) def dir_scan_csope_files(rootdir): file_list = [] if (not os.path.isdir(rootdir)): print "Not a directory:", rootdir return file_list for root, subFolders, files in os.walk(rootdir): for f in files: f = os.path.join(root, f) if (re.search('\.(h|c|H|C|hh|cc|hpp|cpp|hxx|cxx||l|y|s|S|pl|pm|java)$', f) != None): file_list.append(f) return file_list class QueryUiCscope(QueryUiBase): def __init__(self, qry): self.menu_cmd_list = menu_cmd_list QueryUiBase.__init__(self) self.query = qry self.ctree_args = ctree_query_args def query_cb(self, cmd_str): if (not self.query.cs_is_open()): return if (not self.query.cs_is_ready()): show_msg_dialog('\nProject has no source files') return req = PluginHelper.editor_current_word() if (req != None): req = str(req).strip() opt = None if (cmd_str != 'QDEF'): val = QueryDialog.show_dlg(cmd_str, req) if (val == None): return (cmd_str, req, opt) = val if (req == None or req == ''): return if cmd_str == 'QDEF': self.query_qdef(req, opt) elif cmd_str == 'CTREE': self.query_ctree(req, opt) else: self.do_query(cmd_str, req, opt) def prepare_menu(self): QueryUiBase.prepare_menu(self) menu = PluginHelper.backend_menu menu.setTitle('&Cscope') @staticmethod def prj_show_settings_ui(proj_args): dlg = ProjectSettingsCscopeDialog() return dlg.run_dialog(proj_args) class ProjectSettingsCscopeDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('backend/plugins/cscope/ui/cs_project_settings.ui', self) self.pd_path_tbtn.setIcon(QFileIconProvider().icon(QFileIconProvider.Folder)) self.pd_src_list.setSelectionMode(QAbstractItemView.ExtendedSelection) QObject.connect(self.pd_path_tbtn, SIGNAL("clicked()"), self.path_open_cb) QObject.connect(self.pd_add_btn, SIGNAL("clicked()"), self.src_add_cb) QObject.connect(self.pd_rem_btn, SIGNAL("clicked()"), self.src_rem_cb) QObject.connect(self, SIGNAL("accepted()"), self.ok_btn_cb) def path_open_cb(self): fdlg = QFileDialog(None, "Choose directory") fdlg.setFileMode(QFileDialog.Directory); fdlg.setDirectory(self.pd_path_inp.text()) if (fdlg.exec_()): path_dir = fdlg.selectedFiles()[0]; self.pd_path_inp.setText(str(path_dir)) def src_add_cb(self): fdlg = QFileDialog(None, "Choose directory") fdlg.setFileMode(QFileDialog.Directory); fdlg.setDirectory(self.pd_path_inp.text()) if (fdlg.exec_()): d = fdlg.selectedFiles()[0]; d = str(d) d = d.strip() if (d == None): return d = os.path.normpath(d) if (d == '' or not os.path.isabs(d)): return self.src_add_files(d) def src_rem_cb(self): li = self.pd_src_list for item in li.selectedItems(): row = li.row(item) li.takeItem(row) def src_add_files(self, src_dir): file_list = dir_scan_csope_files(src_dir) self.pd_src_list.addItems(file_list) def ok_btn_cb(self): proj_dir = os.path.join(str(self.pd_path_inp.text()), str(self.pd_name_inp.text())) proj_dir = os.path.normpath(proj_dir) if (self.is_new_proj): if (proj_dir == '' or not os.path.isabs(proj_dir)): return if (os.path.exists(proj_dir)): show_msg_dialog("\nProject already exists") return os.mkdir(proj_dir) # File list cs_list = [] for inx in range(self.pd_src_list.count()): val = str(self.pd_src_list.item(inx).text()) cs_list.append(val) cs_list = list(set(cs_list)) # Cscope opt cs_opt = [] if self.pd_invert_chkbox.isChecked(): cs_opt.append('-q') if self.pd_kernel_chkbox.isChecked(): cs_opt.append('-k') self.res = [proj_dir, cs_opt, cs_list] def set_proj_args(self, proj_args): (proj_dir, cs_opt, cs_list) = proj_args (proj_base, proj_name) = os.path.split(proj_dir) self.pd_path_inp.setText(proj_base) self.pd_name_inp.setText(proj_name) # File list fl = cs_list self.pd_src_list.addItems(fl) # Cscope opt for opt in cs_opt: if (opt == '-q'): self.pd_invert_chkbox.setChecked(True) if (opt == '-k'): self.pd_kernel_chkbox.setChecked(True) def run_dialog(self, proj_args): self.pd_src_list.clear() if (proj_args == None): self.is_new_proj = True self.pd_invert_chkbox.setChecked(True) else: self.is_new_proj = False self.set_proj_args(proj_args) self.res = None self.pd_path_frame.setEnabled(self.is_new_proj) while True: ret = self.exec_() if (ret == QDialog.Accepted or ret == QDialog.Rejected): break return self.res seascope-0.7/src/backend/plugins/cscope/CscopeProject.py0000664002376300237630000001267612062273150022076 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, string, re from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase import CscopeProjectUi from CscopeProjectUi import QueryUiCscope from .. import PluginHelper class ConfigCscope(ConfigBase): def __init__(self): ConfigBase.__init__(self) self.cs_dir = '' self.cs_opt = [] self.cs_list = [] def get_proj_name(self): return os.path.split(self.cs_dir)[1] def get_proj_src_files(self): fl = self.cs_list return fl def read_cs_files_common(self, filename): fl = [] config_file = os.path.join(self.cs_dir, filename) if (os.path.exists(config_file)): cf = open(config_file, 'r') for f in cf: f = f[:-1] fl.append(f) cf.close() return fl def read_cs_files(self): self.cs_list = self.read_cs_files_common('cscope.files') def write_cs_files_common(self, filename, fl): if (len(fl) <= 0): return config_file = os.path.join(self.cs_dir, filename) cf = open(config_file, 'w') for f in fl: cf.write(f + '\n') cf.close() def write_cs_files(self): self.write_cs_files_common("cscope.files", self.cs_list) def get_config_file(self): config_file = 'seascope.opt' return os.path.join(self.cs_dir, config_file) def read_seascope_opt(self): config_file = self.get_config_file() if (not os.path.exists(config_file)): return cf = open(config_file, 'r') for line in cf: line = line.split('=', 1) key = line[0].strip() if (key == 'cs_opt'): self.cs_opt = line[1].split() cf.close() def write_seascope_opt(self): config_file = self.get_config_file() cf = open(config_file, 'w') cf.write('cs_opt' + '=' + string.join(self.cs_opt)+ '\n') cf.close() def read_config(self): self.read_seascope_opt() self.read_cs_files() def write_config(self): self.write_seascope_opt() self.write_cs_files() def proj_start(self): cs_args = string.join(self.cs_opt) def proj_open(self, proj_path): self.cs_dir = proj_path self.read_config() self.proj_start() def proj_update(self, proj_args): self.proj_new(proj_args) def proj_new(self, proj_args): self.proj_args = proj_args (self.cs_dir, self.cs_opt, self.cs_list) = proj_args self.write_config() self.proj_start() def proj_close(self): pass def get_proj_conf(self): self.read_cs_files() return (self.cs_dir, self.cs_opt, self.cs_list) def is_ready(self): return len(self.cs_list) > 0 class ProjectCscope(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectCscope() prj.conf = conf prj.qry = QueryCscope(prj.conf) prj.qryui = QueryUiCscope(prj.qry) PluginHelper.file_view_update(prj.conf.get_proj_src_files()) return (prj) @staticmethod def prj_new(): proj_args = QueryUiCscope.prj_show_settings_ui(None) if (proj_args == None): return None conf = ConfigCscope() conf.proj_new(proj_args) prj = ProjectCscope._prj_new_or_open(conf) return (prj) @staticmethod def prj_open(proj_path): conf = ConfigCscope() conf.proj_open(proj_path) prj = ProjectCscope._prj_new_or_open(conf) return (prj) def prj_close(self): if (self.conf != None): self.conf.proj_close() self.conf = None def prj_dir(self): return self.conf.cs_dir def prj_name(self): return self.conf.get_proj_name() def prj_src_files(self): return self.conf.get_proj_src_files() def prj_is_open(self): return self.conf != None def prj_is_ready(self): return self.conf.is_ready() def prj_conf(self): return self.conf.get_proj_conf() def prj_update_conf(self, proj_args): self.conf.proj_update(proj_args) def prj_settings_trigger(self): proj_args = self.prj_conf() proj_args = QueryUiCscope.prj_show_settings_ui(proj_args) if (proj_args == None): return False self.prj_update_conf(proj_args) PluginHelper.file_view_update(self.conf.get_proj_src_files()) return True from ..PluginBase import PluginProcess class CsProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir) self.name = 'cscope process' if rq == None: rq = ['', ''] self.cmd_str = rq[0] self.req = rq[1] def parse_result(self, text, sig): text = re.split('\r?\n', text) if self.cmd_str == 'FIL': res = [ ['', line[0], '', ''] for line in text if line != '' ] return res res = [] for line in text: if line == '': continue line = line.split(' ', 3) line = [line[1], line[0], line[2], line[3]] res.append(line) return res class QueryCscope(QueryBase): def __init__(self, conf): QueryBase.__init__(self) self.conf = conf def query(self, rquery): if (not self.conf or not self.conf.is_ready()): print "pm_query not is_ready" return None cmd_str = rquery['cmd'] req = rquery['req'] opt = rquery['opt'] cmd_id = CscopeProjectUi.cmd_str2id[cmd_str] if opt == None or opt == '': opt = [] else: opt = opt.split() pargs = [ 'cscope' ] + self.conf.cs_opt + opt + [ '-L', '-d', '-' + str(cmd_id), req ] qsig = CsProcess(self.conf.cs_dir, [cmd_str, req]).run_query_process(pargs, req, rquery) return qsig def rebuild(self): if (not self.conf.is_ready()): print "pm_query not is_ready" return None pargs = [ 'cscope' ] + self.conf.cs_opt + [ '-L' ] qsig = CsProcess(self.conf.cs_dir, None).run_rebuild_process(pargs) return qsig def cs_is_open(self): return self.conf != None def cs_is_ready(self): return self.conf.is_ready() seascope-0.7/src/backend/plugins/CtagsCache.py0000664002376300237630000001243612062273150020036 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtCore import * from datetime import datetime import re #class CtagsInfo: #def __init__(self): #pass #@staticmethod #def lang_suffixes(): #cmd = 'ctags --list-maps' #args = cmd.split() #import subprocess #proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) #(out_data, err_data) = proc.communicate() #res = re.split('\r?\n', out_data) # res = out_data #res = [ line.split(None, 1) for line in res if line != '' ] #d = {} #for line in res: #import fnmatch #fn_pats = line[1] .split() #print line[0], fn_pats #re_pats = '|'.join(fnmatch.translate(p) for p in fn_pats) #print line[0], re_pats #d[line[0]] = re_pats #print d #print 'ctag.lang' #CtagsInfo.lang_suffixes() class CtagsThread(QThread): thread_list = [] def __init__(self, sig): QThread.__init__(self) self.sig = sig self.ct_dict = {} self.finished.connect(self._finished_cb) CtagsThread.thread_list.append(self) def _finished_cb(self): #print 'CtagsThread.finished', len(self.ct_dict) CtagsThread.thread_list.remove(self) for k in self.ct_dict: ct_cache[k] = self.ct_dict[k] self.res = self.parse_result(self.res, self.sig) if self.res != None: self.sig.emit_result(self.res) def ctags_bsearch(self, ct, n): x = -1 y = len(ct) - 1 #print f, n while x < y: m = (x + y + 1) / 2 #print '(', x, y, m, ')' if ct[m][1] > n: #print 'y: m -1', ct[m][1] m = m - 1 y = m continue if ct[m][1] < n: #print 'x: m', ct[m][1] x = m continue break if y == -1: return y #assert x == m or y == m or ct[m][1] == n return m def _ctags_fix(self, line): f = line[1] n = int(line[2]) ct = self.ct_dict[f] m = self.ctags_bsearch(ct, n) if m == -1: return True if ct[m][1] != n: if ct[m][2] in ['variable']: #line[0] = '***** SMART *****' #print line return True if f.endswith('.py'): while m > 0 and (ct[m][2] in ['namespace']): m = m - 1 if m == - 1: return True if ct[m][1] == n: if self.cmd_str == 'DEF': x = m y = m while x > 1 and ct[x - 1][1] == n: x = x - 1 while y < len(ct) - 1 and ct[y + 1][1] == n: y = y + 1 if x < y: for m in range(x, y + 1): if re.match(self.sig.sym, ct[m][0]): break else: if self.cmd_str == 'DEF': return False line[0] = ct[m][0] return True def _run_ctags(self): cmd = 'ctags -n -u --fields=+K -L - -f -' args = cmd.split() import subprocess proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate('\n'.join(self.file_list)) out_data = re.split('\r?\n', out_data) 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: if not re.match(req, 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+') 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); for line in res: if line[0] == req: if not re.search('(\.|->)%s\\b' % req, line[3]): continue elif call_re.search(line[3]): if extern_re.search(line[3]): continue else: grp = func_ptr_re.search(line[3]) if grp: line[0] = grp.group(1) else: if not func_as_arg_re.search(line[3]): continue if line[0] == '': continue if comment_re.search(line[3]): continue out_res.append(line) return out_res if self.cmd_str == '<--': return res if self.cmd_str == 'INC': inc_re = re.compile('^\s*(#\s*include|(from\s+[^\s]+\s+)?import)\s+.*%s.*' % req) for line in res: if not inc_re.search(line[3]): continue out_res.append(line) return out_res return res ct_cache = {} def flush(): #print 'flushing ctags cache...' global ct_cache ct_cache = {} seascope-0.7/src/backend/plugins/PluginHelper.py0000664002376300237630000000331612062273150020444 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtCore import * from PyQt4.QtGui import * backend_menu = None edit_book = None res_book = None call_view = None class_graph_view = None file_view = None dbg_view = None def editor_current_file(): (f, l) = edit_book.get_current_file_line() return f def editor_current_word(): return edit_book.get_current_word() def result_page_new(name, sig_res): if sig_res == None: return page = res_book.create_result_page(name) ## add result sig_res[0].connect(page.add_result) #page.add_result(req, res) dbg_view.connect_to_sig(sig_res[1]) def _quick_def_result(req, res): count = len(res) if count > 1: page = res_book.create_result_page_single() page.add_result(req, res) dlg = QDialog() dlg.setWindowTitle('Quick Definition: ' + req) vlay = QVBoxLayout(dlg) vlay.addWidget(page) page.sig_show_file_line.connect(edit_book.show_file_line) page.activated.connect(dlg.accept) page.setMinimumWidth(800) page.setMinimumHeight(100) dlg.exec_() return if (count == 1): filename = res[0][1] try: line = int(res[0][2]) except: return edit_book.show_file_line(filename, line) def quick_def_page_new(sig_res): if sig_res == None: return sig_res[0].connect(_quick_def_result) dbg_view.connect_to_sig(sig_res[1]) def call_view_page_new(req, query_func, ctree_query_args, opt): hint_file = editor_current_file() call_view.create_page(req, query_func, ctree_query_args, opt, hint_file) def class_graph_view_page_new(req, proj_dir, query_func, clgraph_query_args, opt): class_graph_view.create_page(req, proj_dir, query_func, clgraph_query_args, opt) def file_view_update(flist): file_view.add_files(flist) seascope-0.7/src/backend/plugins/gtags/0000775002376300237630000000000012062273150016576 5ustar anilanilseascope-0.7/src/backend/plugins/gtags/ui/0000775002376300237630000000000012062273150017213 5ustar anilanilseascope-0.7/src/backend/plugins/gtags/ui/gt_query.ui0000664002376300237630000000701712062273150021416 0ustar anilanil QueryDialog Qt::ApplicationModal 0 0 357 171 gtags query 40 16777215 Type false Symbol true 10 50 16777215 Substring Case Insensitive Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qd_sym_inp qd_substr_chkbox qd_icase_chkbox buttonBox qd_cmd_inp buttonBox accepted() QueryDialog accept() 248 254 157 274 buttonBox rejected() QueryDialog reject() 316 260 286 274 seascope-0.7/src/backend/plugins/gtags/__init__.py0000664002376300237630000000072112062273150020707 0ustar anilanil# 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.7/src/backend/plugins/gtags/GtagsProject.py0000664002376300237630000001234612062273150021552 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os, string, re from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase import GtagsProjectUi from GtagsProjectUi import QueryUiGtags from .. import PluginHelper class ConfigGtags(ConfigBase): def __init__(self): ConfigBase.__init__(self) self.gt_dir = '' self.gt_opt = '' self.gt_list = [] def get_proj_name(self): return os.path.split(self.gt_dir)[1] def get_proj_src_files(self): fl = self.gt_list return fl def proj_start(self): gt_args = string.join(self.gt_opt) def proj_open(self, proj_path): self.gt_dir = proj_path self.proj_start() def proj_update(self, proj_args): self.proj_new(proj_args) def proj_new(self, proj_args): self.proj_args = proj_args (self.gt_dir, self.gt_opt, self.gt_list) = proj_args self.proj_start() def proj_close(self): pass def get_proj_conf(self): return (self.gt_dir, self.gt_opt, self.gt_list) def is_ready(self): return True class ProjectGtags(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectGtags() prj.conf = conf prj.qry = QueryGtags(prj.conf) prj.qryui = QueryUiGtags(prj.qry) return (prj) @staticmethod def prj_new(): from PyQt4.QtGui import QFileDialog fdlg = QFileDialog(None, "Choose source code directory") fdlg.setFileMode(QFileDialog.Directory); #fdlg.setDirectory(self.pd_path_inp.text()) if fdlg.exec_(): d = fdlg.selectedFiles()[0]; d = str(d) if not d: return None d = os.path.normpath(d) if d == '' or not os.path.isabs(d): return None prj = ProjectGtags.prj_open(d) prj.qryui.do_rebuild() return prj return None @staticmethod def prj_open(proj_path): conf = ConfigGtags() conf.proj_open(proj_path) prj = ProjectGtags._prj_new_or_open(conf) return (prj) def prj_close(self): if (self.conf != None): self.conf.proj_close() self.conf = None def prj_dir(self): return self.conf.gt_dir def prj_name(self): return self.conf.get_proj_name() def prj_src_files(self): return self.conf.get_proj_src_files() def prj_is_open(self): return self.conf != None def prj_is_ready(self): return self.conf.is_ready() def prj_conf(self): return self.conf.get_proj_conf() def prj_update_conf(self, proj_args): self.conf.proj_update(proj_args) def prj_settings_trigger(self): proj_args = self.prj_conf() proj_args = QueryUiGtags.prj_show_settings_ui(proj_args) #if (proj_args == None): #return False #self.prj_update_conf(proj_args) #return True return False from ..PluginBase import PluginProcess from .. import PluginHelper from ..CtagsCache import CtagsThread class GtCtagsThread(CtagsThread): def __init__(self, sig): CtagsThread.__init__(self, sig) def ctags_bsearch(self, ct, n): m = CtagsThread.ctags_bsearch(self, ct, n) return m def parse_result(self, res, sig): res = self._filter_res(res, sig) return res class GtProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir) self.name = 'gtags process' if rq == None: rq = ['', ''] self.cmd_str = rq[0] self.req = rq[1] def parse_result(self, text, sig): text = re.split('\r?\n', text) if self.cmd_str == 'FIL': res = [ ['', line.split(' ')[0], '', '' ] for line in text if line != '' ] return res res = [] for line in text: if line == '': continue line = line.split(' ', 3) line = ['', line[0], line[2], line[3]] res.append(line) GtCtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return None class QueryGtags(QueryBase): def __init__(self, conf): QueryBase.__init__(self) self.conf = conf self.gt_file_list_update() def query(self, rquery): if (not self.conf): #or not self.conf.is_ready()): print "pm_query not is_ready" return None cmd_str = rquery['cmd'] req = rquery['req'] opt = rquery['opt'] if opt == None or opt == '': opt = [] else: opt = opt.split() cmd_opt = GtagsProjectUi.cmd_str2id[cmd_str] pargs = [ 'global', '-a', '--result=cscope', '-x' ] + opt if cmd_opt != '': pargs += [ cmd_opt ] pargs += [ '--', req ] qsig = GtProcess(self.conf.gt_dir, [cmd_str, req]).run_query_process(pargs, req, rquery) return qsig def rebuild(self): if (not self.conf.is_ready()): print "pm_query not is_ready" return None if (os.path.exists(os.path.join(self.conf.gt_dir, 'GTAGS'))): pargs = [ 'global', '-u' ] else: pargs = [ 'gtags', '-i' ] qsig = GtProcess(self.conf.gt_dir, None).run_rebuild_process(pargs) qsig.connect(self.gt_file_list_update) return qsig def gt_file_list_update(self): wdir = self.conf.gt_dir if not os.path.exists(os.path.join(wdir, 'GTAGS')): return fl = [] try: import subprocess pargs = [ 'global', '-P', '-a' ] proc = subprocess.Popen(pargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=wdir) (out_data, err_data) = proc.communicate() fl = re.split('\r?\n', out_data.strip()) PluginHelper.file_view_update(fl) except: import sys e = sys.exc_info()[1] print ' '.join(pargs) print e def gt_is_open(self): return self.conf != None def gt_is_ready(self): return self.conf.is_ready() seascope-0.7/src/backend/plugins/gtags/GtagsProjectUi.py0000664002376300237630000001072512062273150022047 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase from ..PluginBase import QueryUiBase from .. import PluginBase, PluginHelper cmd_table = [ [ ['REF', '-r'], ['&References', 'Ctrl+0'], ['References to' ] ], [ ['DEF', ''], ['&Definitions', 'Ctrl+1'], ['Definition of' ] ], #[ ['<--', '2'], ['&Called Functions', 'Ctrl+2'], ['Functions called by' ] ], [ ['-->', '-r'], ['C&alling Functions', 'Ctrl+3'], ['Functions calling' ] ], #[ ['TXT', '4'], ['Find &Text', 'Ctrl+4'], ['Find text' ] ], [ ['GRP', '-g'], ['Find &Egrep', 'Ctrl+5'], ['Find egrep pattern' ] ], [ ['FIL', '-P'], ['Find &File', 'Ctrl+7'], ['Find files' ] ], [ ['INC', '-g'], ['&Include/Import', 'Ctrl+8'], ['Find include/import' ] ], [ ['---', None], [None ] ], [ ['QDEF', ''], ['&Quick Definition', 'Ctrl+]'], [None ] ], [ ['CTREE','12'], ['Call Tr&ee', 'Ctrl+\\'], ['Call tree' ] ], [ ['---', None], [None ], ], [ ['UPD', '25'], ['Re&build Database', None ], [None ] ], ] menu_cmd_list = [ [c[0][0]] + c[1] for c in cmd_table ] cmd_str2id = {} cmd_str2qstr = {} cmd_qstr2str = {} for c in cmd_table: if c[0][1] != None: cmd_str2id[c[0][0]] = c[0][1] cmd_str2qstr[c[0][0]] = c[2][0] cmd_qstr2str[c[2][0]] = c[0][0] # python 2.7 #cmd_str2id = { c[0][0]:c[0][1] for c in cmd_table if c[0][1] != None } #cmd_str2qstr = { c[0][0]:c[2][0] for c in cmd_table if c[0][1] != None } #cmd_qstr2str = { c[2][0]:c[0][0] for c in cmd_table if c[0][1] != None } cmd_qstrlist = [ c[2][0] for c in cmd_table if c[0][1] != None and c[2][0] != None ] ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], #['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] class QueryDialog(QDialog): dlg = None def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('backend/plugins/gtags/ui/gt_query.ui', self) self.qd_sym_inp.setAutoCompletion(False) self.qd_sym_inp.setInsertPolicy(QComboBox.InsertAtTop) self.qd_cmd_inp.addItems(cmd_qstrlist) def run_dialog(self, cmd_str, req): s = cmd_str2qstr[cmd_str] inx = self.qd_cmd_inp.findText(s) self.qd_cmd_inp.setCurrentIndex(inx) if (req == None): req = '' self.qd_sym_inp.setFocus() self.qd_sym_inp.setEditText(req) self.qd_sym_inp.lineEdit().selectAll() self.qd_substr_chkbox.setChecked(False) self.qd_icase_chkbox.setChecked(False) self.show() if (self.exec_() == QDialog.Accepted): req = str(self.qd_sym_inp.currentText()) s = str(self.qd_cmd_inp.currentText()) cmd_str = cmd_qstr2str[s] #self.qd_sym_inp.addItem(req) if (req != '' and self.qd_substr_chkbox.isChecked()): req = '.*' + req + '.*' opt = None if (self.qd_icase_chkbox.isChecked()): opt = '-i' res = (cmd_str, req, opt) return res return None @staticmethod def show_dlg(cmd_str, req): if (QueryDialog.dlg == None): QueryDialog.dlg = QueryDialog() return QueryDialog.dlg.run_dialog(cmd_str, req) def show_msg_dialog(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) class QueryUiGtags(QueryUiBase): def __init__(self, qry): self.menu_cmd_list = menu_cmd_list QueryUiBase.__init__(self) self.query = qry self.ctree_args = ctree_query_args def query_cb(self, cmd_str): if (not self.query.gt_is_open()): return if (not self.query.gt_is_ready()): show_msg_dialog('\nProject has no source files') return req = PluginHelper.editor_current_word() if (req != None): req = str(req).strip() opt = None if (cmd_str != 'QDEF'): val = QueryDialog.show_dlg(cmd_str, req) if (val == None): return (cmd_str, req, opt) = val if (req == None or req == ''): return if cmd_str == 'QDEF': self.query_qdef(req, opt) elif cmd_str == 'CTREE': self.query_ctree(req, opt) else: self.do_query(cmd_str, req, opt) def prepare_menu(self): QueryUiBase.prepare_menu(self) menu = PluginHelper.backend_menu menu.setTitle('G&tags') @staticmethod def prj_show_settings_ui(proj_args): dlg = ProjectSettingsGtagsDialog() return dlg.run_dialog(proj_args) class ProjectSettingsGtagsDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('ui/project_settings.ui', self) def run_dialog(self, proj_args): self.pi_path_lbl.setText(proj_args[0]) self.pi_type_lbl.setText('GNU global/gtags') self.exec_() return proj_args seascope-0.7/src/backend/plugins/__init__.py0000664002376300237630000000011212062273150017574 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD seascope-0.7/src/backend/plugins/PluginBase.py0000664002376300237630000002002612062273150020074 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD from PyQt4.QtCore import * from PyQt4.QtGui import * import os, re def msg_box(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) class ProjectBase(QObject): prj = None qry = None def __init__(self): QObject.__init__(self) def prj_close(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_get_dir(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_get_name(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_get_src_files(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_is_open(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_is_ready(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_get_conf(self): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_update_conf(self, proj_args): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_show_settings(self, proj_args): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def prj_settings(self, proj_args): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) class ConfigBase(QObject): @staticmethod def prepare_menu(menubar): pass class QueryBase(QObject): @staticmethod def prepare_menu(menubar): pass def query(self, rquery): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) def rebuild(): msg_box('%s: %s: Not implemeted' % (__name__, __func__)) import PluginHelper class QueryUiBase(QObject): def __init__(self): QObject.__init__(self) self.prepare_menu() def menu_cb(self, act): if act.cmd_str != None: self.query_cb(act.cmd_str) def prepare_menu(self): menu = PluginHelper.backend_menu menu.triggered.connect(self.menu_cb) for c in self.menu_cmd_list: if c[0] == '---': menu.addSeparator() continue if c[2] == None: if c[0] == 'UPD': func = self.rebuild_cb act = menu.addAction(c[1], func) act.cmd_str = None else: act = menu.addAction(c[1]) act.setShortcut(c[2]) act.cmd_str = c[0] def query_ctree(self, req, opt): PluginHelper.call_view_page_new(req, self.query.query, self.ctree_args, opt) def query_class_graph(self, req, opt): PluginHelper.class_graph_view_page_new(req, self.query.conf.id_dir, self.query.query, self.clgraph_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'] = PluginHelper.editor_current_file() return rquery def query_qdef(self, req, opt): rquery = {} rquery = self._prepare_rquery('DEF', req, opt) sig_res = self.query.query(rquery) PluginHelper.quick_def_page_new(sig_res) def do_query(self, cmd_str, req, opt): ## create page name = cmd_str + ' ' + req rquery = self._prepare_rquery(cmd_str, req, opt) sig_res = self.query.query(rquery) PluginHelper.result_page_new(name, sig_res) def do_rebuild(self): sig_rebuild = self.query.rebuild() if not sig_rebuild: return dlg = QProgressDialog() dlg.setWindowTitle('Seascope rebuild') dlg.setLabelText('Rebuilding database...') dlg.setCancelButton(None) dlg.setMinimum(0) dlg.setMaximum(0) sig_rebuild.connect(dlg.accept) while dlg.exec_() != QDialog.Accepted: pass def rebuild_cb(self): self.do_rebuild() from PyQt4.QtGui import QMessageBox class QuerySignal(QObject): sig_result = pyqtSignal(str, list) sig_result_dbg = pyqtSignal(str, str, str) sig_rebuild = pyqtSignal() def __init__(self): QObject.__init__(self) def _relevancy_sort(self, hfile, res): pt = [] pd = {} p = hfile (pre, ext) = os.path.splitext(hfile) c = None while p != c: e = [p, [], []] pt += [e] pd[p] = e c = p p = os.path.dirname(p) for line in res: f = line[1] d = os.path.dirname(f) p = f while p not in pd: p = os.path.dirname(p) e = pd[p] if p in [f, d]: e[1].append(line) else: e[2].append(line) for e in pt: e[1] = sorted(e[1], key=lambda li: li[1]) e[2] = sorted(e[2], key=lambda li: li[1]) pre = pre + '.*' e0 = [] e1 = [] for e in pt[1][1]: if re.match(pre, e[1]): e0 += [e] else: e1 += [e] pt[0][1] += e0 pt[1][1] = e1 res1 = [] res2 = [] for e in pt: res1 += e[1] res2 += e[2] res = res1 + res2 return res def relevancy_sort(self, res): if os.getenv('RELEVANCY_SORT', 1) == 0: return res hint_file = None try: hint_file = self.rquery['hint_file'] except: pass if not hint_file: return res if not os.path.isabs(hint_file): print 'BUG: relevancy_sort: not abs path:', hint_file return res if len(res) > 10000: return res return self._relevancy_sort(hint_file, res) def emit_result(self, res): res = self.relevancy_sort(res) self.sig_result.emit(self.sym, res) class PluginProcess(QObject): proc_list = [] def __init__(self, wdir): QObject.__init__(self) PluginProcess.proc_list.append(self) self.is_rebuild = False self.sig = QuerySignal() self.proc = QProcess() self.proc.finished.connect(self._finished_cb) self.proc.error.connect(self._error_cb) self.proc.setWorkingDirectory(wdir) self.wdir = wdir def _cleanup(self): PluginProcess.proc_list.remove(self) if self.err_str != '': s = '' + self.p_cmd + '

' + '

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

Summary

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

' + err_dict[err] self._cleanup() def _finished_cb(self, ret): res = str(self.proc.readAllStandardOutput()) self.err_str = str(self.proc.readAllStandardError()) #print 'output', res #print 'cmd:', self.p_cmd if self.is_rebuild: self.res = res self.sig.sig_rebuild.emit() else: self.res = '' self.sig.sig_result_dbg.emit(self.p_cmd, res, self.err_str) try: res = self.parse_result(res, self.sig) except: res = [['', '', '', 'error while parsing output of: ' + self.p_cmd]] if res != None: self.sig.emit_result(res) self._cleanup() def run_query_process(self, pargs, sym, rquery=None): self.sig.sym = sym self.sig.rquery = rquery self.p_cmd = ' '.join(pargs) if os.getenv('SEASCOPE_DEBUG'): print self.p_cmd self.proc.start(pargs[0], pargs[1:]) if self.proc.waitForStarted() == False: return None self.proc.closeWriteChannel() return [self.sig.sig_result, self.sig.sig_result_dbg] def run_rebuild_process(self, pargs): self.is_rebuild = True self.p_cmd = ' '.join(pargs) self.proc.start(pargs[0], pargs[1:]) if self.proc.waitForStarted() == False: return None #print 'cmd:', pargs import CtagsCache self.sig.sig_rebuild.connect(CtagsCache.flush) return self.sig.sig_rebuild def parse_result(self, text, sig): print 'parse_result not implemented' if text == '': text = ['Empty output'] else: text = text.strip().split('\n') return text if __name__ == '__main__': import sys def slot_result(sym, res): print 'slot_result: ', [str(sym), res] sys.exit(0) def slot_result_dbg(cmd, res, err_str): print 'slot_result_dbg:', [str(cmd), str(res).strip().split('\n'), str(err_str)] def slot_rebuild(): print 'slot_rebuild' app = QCoreApplication(sys.argv) qsig = PluginProcess('.').run_query_process(['ls'], 'ls') #qsig = PluginProcess('/home/anil/prj/ss/lin').run_query_process(['cscope', '-q', '-k', '-L', '-d', '-0', 'vdso'], 'ls') if qsig == None: sys.exit(-1) qsig[0].connect(slot_result) qsig[1].connect(slot_result_dbg) app.exec_() seascope-0.7/src/backend/plugins/idutils/0000775002376300237630000000000012062273150017146 5ustar anilanilseascope-0.7/src/backend/plugins/idutils/ui/0000775002376300237630000000000012062273150017563 5ustar anilanilseascope-0.7/src/backend/plugins/idutils/ui/id_query.ui0000664002376300237630000000702112062273150021743 0ustar anilanil QueryDialog Qt::ApplicationModal 0 0 357 171 Idutils Query 40 16777215 Type false Symbol true 10 50 16777215 Substring Case Insensitive Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok qd_sym_inp qd_substr_chkbox qd_icase_chkbox buttonBox qd_cmd_inp buttonBox accepted() QueryDialog accept() 248 254 157 274 buttonBox rejected() QueryDialog reject() 316 260 286 274 seascope-0.7/src/backend/plugins/idutils/__init__.py0000664002376300237630000000173712062273150021267 0ustar anilanil# 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.7/src/backend/plugins/idutils/IdutilsProject.py0000664002376300237630000001272112062273150022467 0ustar anilanil#!/usr/bin/python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys, os, string, re from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase from IdutilsProjectUi import QueryUiIdutils class ConfigIdutils(ConfigBase): def __init__(self): ConfigBase.__init__(self) self.id_dir = '' self.id_opt = '' self.id_list = [] def get_proj_name(self): return os.path.split(self.id_dir)[1] def get_proj_src_files(self): return [] def proj_start(self): id_args = string.join(self.id_opt) def proj_open(self, proj_path): self.id_dir = proj_path self.proj_start() def proj_update(self, proj_args): self.proj_new(proj_args) def proj_new(self, proj_args): self.proj_args = proj_args (self.id_dir, self.id_opt, self.id_list) = proj_args self.proj_start() def proj_close(self): pass def get_proj_conf(self): return (self.id_dir, self.id_opt, self.id_list) def is_ready(self): return True class ProjectIdutils(ProjectBase): def __init__(self): ProjectBase.__init__(self) @staticmethod def _prj_new_or_open(conf): prj = ProjectIdutils() prj.conf = conf prj.qry = QueryIdutils(prj.conf) prj.qryui = QueryUiIdutils(prj.qry) return (prj) @staticmethod def prj_new(): from PyQt4.QtGui import QFileDialog fdlg = QFileDialog(None, "Choose source code directory") fdlg.setFileMode(QFileDialog.Directory); #fdlg.setDirectory(self.pd_path_inp.text()) if fdlg.exec_(): d = fdlg.selectedFiles()[0]; d = str(d) if not d: return None d = os.path.normpath(d) if d == '' or not os.path.isabs(d): return None prj = ProjectIdutils.prj_open(d) prj.qryui.do_rebuild() return prj return None @staticmethod def prj_open(proj_path): conf = ConfigIdutils() conf.proj_open(proj_path) prj = ProjectIdutils._prj_new_or_open(conf) return (prj) def prj_close(self): if (self.conf != None): self.conf.proj_close() self.conf = None def prj_dir(self): return self.conf.id_dir def prj_name(self): return self.conf.get_proj_name() def prj_src_files(self): return self.conf.get_proj_src_files() def prj_is_open(self): return self.conf != None def prj_is_ready(self): return self.conf.is_ready() def prj_conf(self): return self.conf.get_proj_conf() def prj_update_conf(self, proj_args): self.conf.proj_update(proj_args) def prj_settings_trigger(self): proj_args = self.prj_conf() proj_args = QueryUiIdutils.prj_show_settings_ui(proj_args) #if (proj_args == None): #return False #self.prj_update_conf(proj_args) #return True return False from ..PluginBase import PluginProcess from .. import PluginHelper from ..CtagsCache import CtagsThread class IdCtagsThread(CtagsThread): def __init__(self, sig): CtagsThread.__init__(self, sig) def ctags_bsearch(self, ct, n): m = CtagsThread.ctags_bsearch(self, ct, n) return m def parse_result(self, res, sig): res = self._filter_res(res, sig) return res class IdProcess(PluginProcess): def __init__(self, wdir, rq): PluginProcess.__init__(self, wdir) self.name = 'idutils process' if rq == None: rq = ['', ''] self.cmd_str = rq[0] self.req = rq[1] def parse_result(self, text, sig): #from datetime import datetime #t1 = datetime.now() text = re.split('\r?\n', text) #t2 = datetime.now() #print 'parse-split', t2 - t1 if self.cmd_str == 'FIL': res = [ ['', os.path.join(self.wdir, line), '', '' ] for line in text if line != '' ] return res res = [] for line in text: if line == '': continue line = line.split(':', 2) line = ['', os.path.join(self.wdir, line[0]), line[1], line[2]] res.append(line) #t3 = datetime.now() #print 'parse-loop', t3 - t2 IdCtagsThread(sig).apply_fix(self.cmd_str, res, ['']) return None class QueryIdutils(QueryBase): def __init__(self, conf): QueryBase.__init__(self) self.conf = conf self.id_file_list_update() def query(self, rquery): if (not self.conf): #or not self.conf.is_ready()): print "pm_query not is_ready" return None cmd_str = rquery['cmd'] req = rquery['req'] opt = rquery['opt'] if opt == None: opt = [] pargs = ['lid', '-R', 'grep'] if cmd_str == 'FIL': pargs = ['fnid', '-S', 'newline'] elif cmd_str == 'TXT': pargs += ['-l'] elif 'substring' in opt: #req = '.*' + req + '.*' #pargs += ' -s' pass elif cmd_str in ['-->', '<--']: pargs += ['-l'] pargs += [ '--', req ] qsig = IdProcess(self.conf.id_dir, [cmd_str, req]).run_query_process(pargs, req, rquery) return qsig def rebuild(self): if (not self.conf.is_ready()): print "pm_query not is_ready" return None pargs = [ 'mkid', '-s' ] qsig = IdProcess(self.conf.id_dir, None).run_rebuild_process(pargs) qsig.connect(self.id_file_list_update) return qsig def id_file_list_update(self): wdir = self.conf.id_dir if not os.path.exists(os.path.join(wdir, 'ID')): return fl = [] try: import subprocess pargs = [ 'fnid', '-S', 'newline', '-f', 'ID' ] proc = subprocess.Popen(pargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, cwd=wdir) (out_data, err_data) = proc.communicate() fl = [] for f in re.split('\r?\n', out_data.strip()): if f == '': continue fl.append(os.path.join(wdir, f)) PluginHelper.file_view_update(fl) except: import sys e = sys.exc_info()[1] print ' '.join(pargs) print e def id_is_open(self): return self.conf != None def id_is_ready(self): return self.conf.is_ready() seascope-0.7/src/backend/plugins/idutils/IdutilsProjectUi.py0000664002376300237630000001162012062273150022762 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * from ..PluginBase import ProjectBase, ConfigBase, QueryBase from ..PluginBase import QueryUiBase from .. import PluginBase, PluginHelper cmd_table = [ [ ['REF', ''], ['&References', 'Ctrl+0'], ['References to' ] ], [ ['DEF', ''], ['&Definitions', 'Ctrl+1'], ['Definition of' ] ], #[ ['<--', '2'], ['&Called Functions', 'Ctrl+2'], ['Functions called by' ] ], [ ['-->', '3'], ['C&alling Functions', 'Ctrl+3'], ['Functions calling' ] ], #[ ['TXT', '4'], ['Find &Text', 'Ctrl+4'], ['Find text' ] ], #[ ['GRP', ''], ['Find &Egrep', 'Ctrl+5'], ['Find egrep pattern' ] ], [ ['FIL', ''], ['Find &File', 'Ctrl+7'], ['Find files' ] ], [ ['INC', '8'], ['&Include/Import', 'Ctrl+8'], ['Find include/import' ] ], [ ['---', None], [None ] ], [ ['QDEF', ''], ['&Quick Definition', 'Ctrl+]'], [None ] ], [ ['CTREE','12'], ['Call Tr&ee', 'Ctrl+\\'], ['Call tree' ] ], [ ['---', None], [None ], ], [ ['CLGRAPH', '13'], ['Class &Graph', 'Ctrl+:'], ['Class graph' ] ], [ ['---', None], [None ], ], [ ['UPD', '25'], ['Re&build Database', None ], [None ] ], ] menu_cmd_list = [ [c[0][0]] + c[1] for c in cmd_table ] cmd_str2id = {} cmd_str2qstr = {} cmd_qstr2str = {} for c in cmd_table: if c[0][1] != None: cmd_str2id[c[0][0]] = c[0][1] cmd_str2qstr[c[0][0]] = c[2][0] cmd_qstr2str[c[2][0]] = c[0][0] # python 2.7 #cmd_str2id = { c[0][0]:c[0][1] for c in cmd_table if c[0][1] != None } #cmd_str2qstr = { c[0][0]:c[2][0] for c in cmd_table if c[0][1] != None } #cmd_qstr2str = { c[2][0]:c[0][0] for c in cmd_table if c[0][1] != None } cmd_qstrlist = [ c[2][0] for c in cmd_table if c[0][1] != None and c[2][0] != None ] ctree_query_args = [ ['-->', '--> F', 'Calling tree' ], #['<--', 'F -->', 'Called tree' ], ['REF', '==> F', 'Advanced calling tree' ], ] clgraph_query_args = [ ['CLGRAPH', 'D', 'Derived classes' ], ['CLGRAPH', 'B', 'Base classes' ], ] class QueryDialog(QDialog): dlg = None def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('backend/plugins/idutils/ui/id_query.ui', self) self.qd_sym_inp.setAutoCompletion(False) self.qd_sym_inp.setInsertPolicy(QComboBox.InsertAtTop) self.qd_cmd_inp.addItems(cmd_qstrlist) def run_dialog(self, cmd_str, req): s = cmd_str2qstr[cmd_str] inx = self.qd_cmd_inp.findText(s) self.qd_cmd_inp.setCurrentIndex(inx) if (req == None): req = '' self.qd_sym_inp.setFocus() self.qd_sym_inp.setEditText(req) self.qd_sym_inp.lineEdit().selectAll() self.qd_substr_chkbox.setChecked(False) self.qd_icase_chkbox.setChecked(False) self.show() if (self.exec_() == QDialog.Accepted): req = str(self.qd_sym_inp.currentText()) s = str(self.qd_cmd_inp.currentText()) cmd_str = cmd_qstr2str[s] #self.qd_sym_inp.addItem(req) opt = [] if cmd_str != 'TXT' and req != '' and self.qd_substr_chkbox.isChecked(): opt.append('substring') if cmd_str == 'FIL': req = '*' + req + '*' else: req = '.*' + req + '.*' if (self.qd_icase_chkbox.isChecked()): opt.append('ignorecase') res = (cmd_str, req, opt) return res return None @staticmethod def show_dlg(cmd_str, req): if (QueryDialog.dlg == None): QueryDialog.dlg = QueryDialog() return QueryDialog.dlg.run_dialog(cmd_str, req) def show_msg_dialog(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) class QueryUiIdutils(QueryUiBase): def __init__(self, qry): self.menu_cmd_list = menu_cmd_list QueryUiBase.__init__(self) self.query = qry self.ctree_args = ctree_query_args self.clgraph_args = clgraph_query_args def query_cb(self, cmd_str): if (not self.query.id_is_open()): return if (not self.query.id_is_ready()): show_msg_dialog('\nProject has no source files') return req = PluginHelper.editor_current_word() if (req != None): req = str(req).strip() opt = None if cmd_str not in [ 'QDEF' ]: val = QueryDialog.show_dlg(cmd_str, req) if (val == None): return (cmd_str, req, opt) = val if (req == None or req == ''): return if cmd_str == 'QDEF': self.query_qdef(req, opt) elif cmd_str == 'CTREE': self.query_ctree(req, opt) elif cmd_str == 'CLGRAPH': self.query_class_graph(req, opt) else: self.do_query(cmd_str, req, opt) def prepare_menu(self): QueryUiBase.prepare_menu(self) menu = PluginHelper.backend_menu menu.setTitle('&Idutils') @staticmethod def prj_show_settings_ui(proj_args): dlg = ProjectSettingsIdutilsDialog() return dlg.run_dialog(proj_args) class ProjectSettingsIdutilsDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('ui/project_settings.ui', self) def run_dialog(self, proj_args): self.pi_path_lbl.setText(proj_args[0]) self.pi_type_lbl.setText('idutils') self.exec_() return proj_args seascope-0.7/src/backend/__init__.py0000664002376300237630000000647412062273150016134 0ustar anilanil# Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import os import sys import re from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * import DialogManager from plugins import PluginHelper backend_plugins = [] backend_dict = {} def _load_plugins(module, directory): pluginImports = __import__(module, globals(), locals()) print 'Scanning for backend plugins...' plist = [] pdict = {} for i in sorted(os.listdir(directory)): path = os.path.join( directory, i, '__init__.py' ) if os.path.isfile( path ): p = __import__( '%s.%s' % (module, i), globals(), locals(), ['*'] ) plist.append(p) pdict[p.name()] = p if not hasattr(p, 'priority'): p.priority = 0 plist = sorted(plist, key=lambda p: p.priority, reverse=True) for p in plist: print '\t', p.name() return (plist, pdict) def load_plugins(): global backend_plugins, backend_dict (backend_plugins, backend_dict) = _load_plugins('backend.plugins', 'backend/plugins') from plugins.PluginBase import ProjectBase, ConfigBase, QueryBase, QueryUiBase prj_actions = [] prj = None def _proj_new_open(): for act in prj_actions: act.setEnabled(True) class ProjectNewDialog(QDialog): def __init__(self): QDialog.__init__(self) self.ui = uic.loadUi('ui/proj_new.ui', self) self.backend_lw.currentRowChanged.connect(self.currentRowChanged_cb) def currentRowChanged_cb(self, row): if row == -1: return bname = str(self.backend_lw.currentItem().text()) b = backend_dict[bname] try: self.descr_te.setText(b.description()) except: self.descr_te.setText('') def run_dialog(self): bi = [ b.name() for b in backend_plugins] self.backend_lw.addItems(bi) self.backend_lw.setCurrentRow(0) if self.exec_() == QDialog.Accepted: bname = str(self.backend_lw.currentItem().text()) return (backend_dict[bname]) return None def msg_box(msg): QMessageBox.warning(None, "Seascope", msg, QMessageBox.Ok) def proj_new(): if len(backend_plugins) == 0: msg_box('No backends are available/usable') dlg = ProjectNewDialog() b = dlg.run_dialog() if b == None: return global prj assert not prj prj = b.project_class().prj_new() if prj: _proj_new_open() return prj != None def proj_open(proj_path): be = [] for p in backend_plugins: if p.is_your_prj(proj_path): be.append(p) if len(be) == 0: msg = "Project '%s': No backend is interested" % proj_path msg_box(msg) return if len(be) > 1: msg = "Project '%s': Many backends interested" % proj_path for b in be: msg += '\n\t' + b.name() msg += '\n\nGoing ahead with: ' + be[0].name() msg_box(msg) b = be[0] print "Project '%s': using '%s' backend" % (proj_path, b.name()) global prj prj = b.project_class().prj_open(proj_path) if prj: _proj_new_open() return prj != None def proj_close(): global prj prj.prj_close() prj = None PluginHelper.backend_menu.clear() PluginHelper.backend_menu.setTitle('') for act in prj_actions: act.setEnabled(False) from plugins import CtagsCache CtagsCache.flush() def proj_is_open(): return prj != None def proj_name(): return prj.prj_name() if prj else None def proj_dir(): return prj.prj_dir() if prj else None def proj_src_files(): return prj.prj_src_files() def proj_conf(): return prj.prj_conf() def proj_settings_trigger(): return prj.prj_settings_trigger()seascope-0.7/src/DialogManager.py0000664002376300237630000001646112062273150015475 0ustar anilanil#!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys import os import string from PyQt4 import QtGui, QtCore, uic from PyQt4.QtGui import * from PyQt4.QtCore import * def show_msg_dialog(msg): QMessageBox.information(None, "Seascope", msg, QMessageBox.Ok) def show_yes_no(msg): ret = QMessageBox.question(None, "Seascope", msg, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) return ret == QMessageBox.Yes def show_yes_no_dontask(msg): return QMessageBox.question(None, "Seascope", msg, "Yes", "No", "Yes, Don't ask again") def show_proj_close(): return show_yes_no("\nClose current project?") class ProjectOpenDialog(QObject): def __init__(self): QObject.__init__(self) self.dlg = uic.loadUi('ui/proj_open.ui') self.dlg.pod_open_btn.setIcon(QFileIconProvider().icon(QFileIconProvider.Folder)) QObject.connect(self.dlg.pod_open_btn, SIGNAL("clicked()"), self.open_btn_cb) QObject.connect(self.dlg, SIGNAL("accepted()"), self.ok_btn_cb) QObject.connect(self.dlg.pod_proj_list, SIGNAL("itemSelectionChanged()"), self.proj_list_change_cb) def proj_list_change_cb(self): item = self.dlg.pod_proj_list.selectedItems()[0] proj_dir = str(item.text()) self.dlg.pod_proj_name.setText(str(proj_dir)) self.path = proj_dir def open_btn_cb(self): fdlg = QFileDialog(None, "Choose project directory") fdlg.setFileMode(QFileDialog.Directory); fdlg.setDirectory(self.dlg.pod_proj_name.text()) if (fdlg.exec_()): proj_dir = fdlg.selectedFiles()[0]; self.dlg.pod_proj_name.setText(str(proj_dir)) def ok_btn_cb(self): p = str(self.dlg.pod_proj_name.text()).strip() if (p == ''): self.dlg.setResult(2) return p = os.path.normpath(p) if (not os.path.isabs(p)): show_msg_dialog("\nProject path is not absolute") self.dlg.setResult(2) return if (not os.path.isdir(p)): show_msg_dialog("\nProject path is not a directory") self.dlg.setResult(2) return self.path = p def run_dialog(self, path_list): self.path = None self.dlg.pod_proj_name.setText('') self.dlg.pod_proj_list.addItems(path_list) while True: ret = self.dlg.exec_() if (ret == QDialog.Accepted or ret == QDialog.Rejected): break return self.path def show_project_open_dialog(path_list): d = ProjectOpenDialog() return d.run_dialog(path_list) class FilePreferencesDialog(QObject): def __init__(self, app_style, edit_ext_cmd, ev_font, dontask, innered, ln_nr): QObject.__init__(self) self.dlg = uic.loadUi('ui/preferences.ui') self.dlg.prd_style_lw.addItems(QStyleFactory.keys()) self.dlg.prd_style_lw.itemSelectionChanged.connect(self.style_changed_cb) self.dlg.prd_font_app_btn.clicked.connect(self.font_app_btn_cb) self.dlg.prd_font_ev_btn.clicked.connect(self.font_ev_btn_cb) self.set_btn_text_and_font(self.dlg.prd_font_app_btn, QApplication.font()) self.set_btn_text_and_font(self.dlg.prd_font_ev_btn, ev_font) self.app_style = app_style self.ev_font = ev_font self.edit_ext_cmd = edit_ext_cmd self.exit_dontask = dontask self.inner_editing = innered self.show_ln_nr = ln_nr if self.exit_dontask: self.dlg.prd_opt_ask_chkb.setCheckState(Qt.Unchecked) else: self.dlg.prd_opt_ask_chkb.setCheckState(Qt.Checked) if self.inner_editing: self.dlg.prd_opt_inner_ed.setCheckState(Qt.Checked) else: self.dlg.prd_opt_inner_ed.setCheckState(Qt.Unchecked) if self.show_ln_nr: self.dlg.prd_opt_show_ln_nr.setCheckState(Qt.Checked) else: self.dlg.prd_opt_show_ln_nr.setCheckState(Qt.Unchecked) if (self.edit_ext_cmd): self.dlg.prd_edit_ext_inp.setText(self.edit_ext_cmd) def set_btn_text_and_font(self, btn, font): ftext = font.family() + ' ' + str(font.pointSize()) btn.setFont(font) btn.setText(ftext) def style_changed_cb(self): item = self.dlg.prd_style_lw.currentItem() self.app_style = item.text() QApplication.setStyle(self.app_style) def font_app_btn_cb(self): (font, ok) = QFontDialog().getFont(QApplication.font()) if (ok): self.set_btn_text_and_font(self.dlg.prd_font_app_btn, font) def font_ev_btn_cb(self): (font, ok) = QFontDialog().getFont(self.ev_font) if (ok): self.set_btn_text_and_font(self.dlg.prd_font_ev_btn, font) def run_dialog(self): ret = self.dlg.exec_() if (ret == QDialog.Accepted): QApplication.setFont(self.dlg.prd_font_app_btn.font()) self.ev_font = self.dlg.prd_font_ev_btn.font() self.edit_ext_cmd = self.dlg.prd_edit_ext_inp.text() self.exit_dontask = self.dlg.prd_opt_ask_chkb.checkState() == Qt.Unchecked self.inner_editing = self.dlg.prd_opt_inner_ed.checkState() == Qt.Checked self.show_ln_nr = self.dlg.prd_opt_show_ln_nr.checkState() == Qt.Checked return (self.app_style, self.dlg.prd_font_app_btn.font().toString(), self.edit_ext_cmd, self.ev_font, self.exit_dontask, self.inner_editing, self.show_ln_nr) def show_preferences_dialog(app_style, edit_ext_cmd, ev_font, dontask, innered, ln_nr): d = FilePreferencesDialog(app_style, edit_ext_cmd, ev_font, dontask, innered, ln_nr) return d.run_dialog() def show_about_dialog(): d = uic.loadUi('ui/about.ui') p = QApplication.windowIcon().pixmap(128) d.ad_logo_lbl.setPixmap(p) d.exec_() def show_goto_line_dialog(line, max_line): d = uic.loadUi('ui/goto_line.ui') d.gl_spinbox.setMaximum(max_line) d.gl_hslider.setMaximum(max_line) d.gl_spinbox.setValue(line) d.gl_spinbox.lineEdit().selectAll() if (d.exec_() == QDialog.Accepted): return d.gl_spinbox.value() return None class FindDialog: dlg = None def __init__(self): self.dlg = uic.loadUi('ui/find.ui') self.dlg.ft_text_inp.setAutoCompletion(False) self.dlg.ft_text_inp.setInsertPolicy(QComboBox.InsertAtTop) def run_dlg(self, text): if (text == None): text = '' d = self.dlg d.ft_text_inp.lineEdit().setText(text) d.ft_text_inp.lineEdit().selectAll() d.ft_text_inp.lineEdit().setFocus() d.ft_from_cursor.setChecked(True) while True: ret = d.exec_() if (ret != QDialog.Accepted): return None text = d.ft_text_inp.currentText() text = str(text).strip() if (text != ''): break opt = { 'cs' : d.ft_cs.isChecked(), 're' : d.ft_re.isChecked(), 'wo' : d.ft_wo.isChecked(), 'fw' : not d.ft_bw.isChecked(), 'cursor' : d.ft_from_cursor.isChecked(), } return (text, opt) def show_find_dialog(text): if (FindDialog.dlg == None): FindDialog.dlg = FindDialog() return FindDialog.dlg.run_dlg(text) class FilterDialog: def __init__(self, cmd_items, cmd_sel): self.dlg = uic.loadUi('ui/filter.ui') self.dlg.fd_cmd_inp.addItems(cmd_items) self.dlg.fd_cmd_inp.setCurrentIndex(cmd_items.index(cmd_sel)) self.dlg.fd_regex_err_lbl.setVisible(False) def run_dialog(self): while True: ret = self.dlg.exec_() if ret != QDialog.Accepted: return None is_regex = self.dlg.fd_regex_chkbox.isChecked() text = str(self.dlg.fd_filter_inp.text()) if is_regex == True: try: import re re.compile(text) except: e = str(sys.exc_info()[1]) lbl = self.dlg.fd_regex_err_lbl lbl.setVisible(True) lbl.setText("regex: " + e + '') continue res = [ text, is_regex, self.dlg.fd_negate_chkbox.isChecked(), self.dlg.fd_icase_chkbox.isChecked(), str(self.dlg.fd_cmd_inp.currentText()) ] return res def show_filter_dialog(cmd_items, cmd_sel): dlg = FilterDialog(cmd_items,cmd_sel) return dlg.run_dialog() seascope-0.7/src/tools/0000775002376300237630000000000012062273150013561 5ustar anilanilseascope-0.7/src/tools/ClassGraph.py0000664002376300237630000001151512062273150016165 0ustar anilanil#!/usr/bin/env python # Copyright (c) 2010 Anil Kumar # All rights reserved. # # License: BSD import sys import subprocess import os import re class ClassGraphGenerator: def __init__(self, d, wlimit=5000, is_base=False): self.wdir = d; self.width_limit = wlimit; self.graphRules = [] self.visitedRules = {} self.visitedSym = {} if is_base: self.visitedSym = {'object' : 1} self.is_base = is_base def addGraphRule(self, sym, d): if (sym, d) in self.visitedRules: return self.visitedRules[(sym, d)] = 1 self.graphRules.append([sym, d]) def refFiles(self, sym): args = ['lid', '-R', 'grep', sym] try: # In python >= 2.7 can use subprocess.check_output # output = subprocess.check_output(args, cwd=self.wdir) proc = subprocess.Popen(args, cwd=self.wdir, stdout=subprocess.PIPE) (output, err_data) = proc.communicate() output = re.split('\r?\n', output) except Exception as e: print >> sys.stderr, e, '\n' print >> sys.stderr, 'Run this script from a directory where lid can find ID file\n' sys.exit(-1) res = set() for line in output: if line == '': continue f = line.split(':', 1)[0] f = os.path.normpath(os.path.join(self.wdir, f)) res.add(f) return res def runCtags(self, fl): cmd = 'ctags -n -u --fields=+i -L - -f -' args = cmd.split() proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (out_data, err_data) = proc.communicate('\n'.join(fl)) out_data = re.split('\r?\n', out_data) return out_data def classHierarchy(self, sym): fl = self.refFiles(sym) data = self.runCtags(fl) 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'] if sd == '': continue sd = sd.split(',') dd = [ re.split('::|\.', x.strip())[-1] for x in sd ] if self.is_base: if sym == line[0]: res += dd else: if sym in dd: res.append(line[0]) return res def classHierarchyRecursive(self, symList): for sym in symList: if sym in self.visitedSym: return self.visitedSym[sym] = 1 dclasses = self.classHierarchy(sym) if len(dclasses): if len(dclasses) > self.width_limit: if is_base: s = 'base' else: s= 'derived' print >> sys.stderr, 'num %s classes(%s) = %d, truncating to %d.\n' % (s, sym, len(dclasses), self.width_limit) dclasses = dclasses[0:self.width_limit] self.addGraphRule(sym, '...(%s)' % sym) for d in dclasses: self.addGraphRule(sym, d) self.classHierarchyRecursive(dclasses) def prepareDotInput(self, sym): if len(self.graphRules) == 0: if is_base: s = 'base' else: s= 'derived' print >> sys.stderr, 'No %s classes for %s\n' % (s, sym) sys.exit(0) dotInput = 'digraph "%s" {\n' % sym dotInput += '\t"%s" [style=bold];\n' % sym for r in self.graphRules: if not self.is_base: dotInput += '\t"%s" -> "%s";\n' % (r[0], r[1]) else: dotInput += '\t"%s" -> "%s";\n' % (r[1], r[0]) dotInput += '}\n' return dotInput def saveDotFile(self, sym, dotInput): f = open(sym + '.dot', 'w') f.write(dotInput) f.close() def saveSvgFile(sym, svg_data): dot_svg = sym + '.svg' f = open(dot_svg, 'w') f.write(svg_data) f.close() print >> sys.stderr, 'saved', dot_svg, '\n' def generateGraph(self, sym): self.classHierarchyRecursive([sym]) dotInput = self.prepareDotInput(sym) #self.saveDotFile(sym, dotInput) args = ['dot', '-Tsvg'] try: p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) (svg_data, err_data) = p.communicate(dotInput) if err_data and err_data != '': print >> sys.stderr, err_data, '\n' #self.saveSvgFile(sym, svg_data) return svg_data except Exception as e: print >> sys.stderr, 'Failed to run:', ' '.join(args), '\n' print >> sys.stderr, e, '\n' if __name__ == '__main__': import optparse usage = "usage: %prog [options] symbol" op = optparse.OptionParser(usage=usage) op.add_option("-p", "--project", dest="id_path", help="Idutils project dir", metavar="PROJECT") op.add_option("-b", action="store_true", dest="is_base", help="Show base classes") (options, args) = op.parse_args() # id utils project dir if not options.id_path: print >> sys.stderr, 'idutils project path required' sys.exit(-1) id_path = os.path.normpath(options.id_path) if not os.path.exists(os.path.join(id_path, 'ID')): print >> sys.stderr, 'idutils project path does not exist' sys.exit(-2) is_base = False if options.is_base: is_base = True # symbol if len(args) != 1: print >> sys.stderr, 'Please specify a symbol' sys.exit(-3) sym = args[0] #print options.id_path, args cgg = ClassGraphGenerator(id_path, is_base=is_base) svg_data = cgg.generateGraph(sym) print svg_data