Commit 900c3cff authored by Ritesh Sarraf's avatar Ritesh Sarraf

Imported Upstream version 0.6

parents
BSD License
include LICENSE
Seascope is a GUI frontend for cscope, idutils.
* Running the application
cd src
python Seascope.py
* Generating source distribution package
python setup.py sdist
* Generating RPM distribution package
python setup.py bdist_rpm
#!/usr/bin/env python
from distutils.core import setup
setup(name='Seascope',
version='0.5',
description='A PyQt GUI front-end for cscope',
long_description='A pyQt GUI front-end for cscope. Written in python using pyQt, QScintilla libraries.',
url='http://seascope.googlecode.com',
packages=['Seascope',
'Seascope.backend',
'Seascope.backend.plugins',
'Seascope.backend.plugins.cscope',
'Seascope.backend.plugins.gtags',
'Seascope.view'
],
package_dir={'Seascope': 'src'},
package_data={'Seascope': ['icons/*.svg','ui/*.ui']},
license="BSD License",
classifiers=[
'Development Status :: 4 - Beta',
'Environment :: X11 Applications :: Qt',
'Environment :: Win32 (MS Windows)',
'Intended Audience :: End Users/Desktop',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Programming Language :: Python',
'Topic :: Software Development',
],
options= {'bdist_rpm':{'requires': 'PyQt4,qscintilla-python,cscope,ctags',
'group': 'Development Tools',
'vendor': 'The Seascope Team'}}
)
#!/usr/bin/env python
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):
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
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.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
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)
def show_preferences_dialog(app_style, edit_ext_cmd, ev_font, dontask, innered):
d = FilePreferencesDialog(app_style, edit_ext_cmd, ev_font, dontask, innered)
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("<font color='red'>regex: " + e + '</font>')
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()
This diff is collapsed.
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()
\ No newline at end of file
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.sig_result.emit(self.sig.sym, 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
if ct[m][1] != n:
if ct[m][2] in ['variable']:
#line[0] = '***** SMART *****'
#print line
return
if f.endswith('.py'):
while m > 0 and (ct[m][2] in ['namespace']):
m = m - 1
if m == - 1:
return
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
line[0] = ct[m][0]
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
for line in self.res:
if line[0] not in self.cond_list:
continue
self._ctags_fix(line)
#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] == '<unknown>':
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 = {}
from PyQt4.QtCore import *
from PyQt4.QtGui import *
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__))