Initial import of kscope 1.6.2

remotes/origin/feat/cmakeConv
Slávek Banko 11 years ago
commit 3af5832abe

@ -0,0 +1 @@
Elad Lahav <elad_lahav@users.sf.net>

@ -0,0 +1,20 @@
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.
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.

@ -0,0 +1,408 @@
1.6.2 (?)
* New: Support for hidden project folders under the source root
* Bug fix: Make the configuration script sh-friendly
* Bug fix: Handle unicode characters on gcc's output
* Bug fix: KScope crashes when clicking on empty area in the tree view
* Bug fix: Do not show the "Function" column in the error list
* Bug fix: Do not close KScope when choosing "Cancel" in the "Save Files?"
message box
1.6.1 (9-Jan-2008)
* New: Support for case-insensitive queries
* New: Per-project Ctags command line (for advanced users only)
* Bug fix: Stop queries when their result windows are destroyed
* Bug fix: Query results sorted by line numbers are sorted numerically
* Translation: Chinese
1.6.0 (10-Jul-2007)
* Improved: Updated the documentation
* Improved: Implemented multiple-call nodes in the call-graph
* Improved: Workspace toolbar buttons re-arranged
* Improved: Hitting Enter in the "Open Project" dialogue's list of
recent projects opens the selected project
* Bug fix: Handle file extensions correctly in the file list
* Bug fix: Avoid hanging status bar messages when a project is closed
* Bug fix: Prevent infinite loops in the file finder in the presence of
recursive symbolic links
* Bug fix: Child windows should not disappear when dialogues are invoked
* Bug fix: Added padding to the call graph, to avoid chopped-off drawing
of nodes close to the borders
* Bug fix: Honour the preferred font when drawing the graph
* Bug fix: Delete temporary dot files used for drawing graphs
* Bug fix: Save call-tree files when a project is closed
* Bug fix: Clean-up a project's directory name after it is created
1.5.2 (7-May-2007)
* New: Useable global bookmarks system
* Improved: Better infrastructure for handling projects
* Improved: The soure root is set in the project properties dialogue
* Improved: When saving a new file, the user is asked whether to include
it in the project
* Improved: New toolbar layout
* Improved: Temporary projects appear in the list of recently open
projects
* Improved: Load a temporary project's cscope.files file, if it exists
* Bug fix: Enable file/project menu items only when a file/project is
open
* Bug fix: Handle column numbers in make output
* Bug fix: Do not allow multiple instances of the same command in the
make history
* Bug fix: Dropped project semaphores (too much hassle for a minor
feature)
* Compilation fix: Support for automake 1.10
1.5.1 (15-Feb-2007)
* Improved: Support for recursive builds (make changing directories)
* Improved: Show build errors/warnings on a separate list
* Bug fix: The main window was not activated when requesting a source
position in a child window (call tree or the make window)
* Bug fix: Maintain Call-tree child item order (by line)
* Bug fix: Build output occasionally mixed standard output with standard
error
1.5.0 (6-Feb-2007)
* New: Make front-end (Rudimentary)
* New: Global bookmarks list
* New: Support for Cscope's -c and -D command-line options (-D requires
a patch to Cscope)
* Improved: Detect Cscope's executable and capabilities on each load
* Improved: Graph windows are no longer top-level (can be minimised or
hidden behind the main window)
* Improved: Do not automatically open a project if it was already loaded
by another instance of KScope
* Improved: Show #include directives in the tag list
* Bug fix: Better calculation of the area defined by a graph arrow
* Bug fix: Files could not be found in the file list when using a common
root ($)
1.4.3 (15-Jan-2007)
* New: Option for negating filters on query result lists
* New: Command for setting the keyboard focus to the tag list
* Improved: Restrict tag/file list navigation to current search pattern
* Improved: Show goto labels in the tag list
* Bug fix: Crash due to in-edges not being removed along with a function
* Bug fix: Connected components disappeared after filtering calling/
called functions
* Bug fix: Use only sh-style ouput redirection in kscope_config
1.4.2 (16-Oct-2006)
* New: Tool-tips for the project's file list
* New: "Find Definition" entry in the query-results popup menu
* Improved: Added '*.S' (kernel assembly files) to the list of standard
file types
* Improved: Some code clean-ups in the query-results popup menu
* Bug fix: All query results following a global definition were omitted
1.4.1 (23-Aug-2006)
* Improved: Speed-up result list filtering
* Improved: Keyboard shortcuts for the first entries in the Window menu
* Improved: Show assmebly labels in the tag list
* Bug fix: KScope crashes when a node is removed from the graph
* Bug fix: KScope crashes when Next/Previous Result is invoked on an
empty query results list
* Bug fix: Prevent whitespace in project names
* Bug fix: Add entries to the results query list in the right order
* Bug fix: Fixed several memory leaks
1.4.0 (9-Aug-2006)
* New: Option for sorting the file list when a project is loaded (on by
default)
* Improved: The documentation is now up to date
* Improved: Nicer layout for the "New Project" dialogue
* Improved: Corrections to the desktop file (thanks to Tom Albers)
* Improved: Close a project automatically before a new one is created
* Bug fix: Do not show the progress dialogue if building fails to start
* Compilation fix: Include stdlib.h in graphwidget.cpp
* Compilation fix: Support for autoconf 2.6x
* Compilation fix: Removed unnecessary options from the YACC source file
* Compilation fix: Abort configuration if lex/flex and yacc/bison are not
found
1.3.4 (14-Apr-2006)
* New: Use graphviz from the command-line (dot). Should finally solve _all_
licensing issues
* New: Informative welcome message
* Improved: Allow multiple files on "File->Open..."
* Improved: Better tool-tips for the tag list
* Bug fix: KScope crashes after startup when attempting to set the cursor
to a non-existing line
1.3.3 (5-Jan-2006)
* License changed to BSD due to incompatibility between the GPL and the CPL
(graphviz)
* New: Multiple-view call graph/tree dialogue
* Improved: Function name is displayed first (consistent behaviour for query
views and call tree widgets)
* Improved: Updated to the latest KDE 'configure' template
1.3.2 (16-Nov-2005)
* New: Support for graphviz 2.6
* Improved: The 'configure' script detects he graphviz version and build flags
* Improved: Better automatic configuration script for Cscope and Ctags
* Improved: Added 'exctags' to the search for exuberant-ctags (FreeBSD)
* Bug fix: Cursor set to the end of the line when jumping to a location in the
code
* Bug fix: Draw the call graph using the current DPI settings
* Bug fix: Automatic configuration script no longer depends on "source" (which
is not available for all shells)
* Bug fix: Editor GUI not merged upon opening a project if the selected file is
the last one loaded
1.3.1 (14-Oct-2005)
* New: "Save All" menu command (was not included in previous release, despite
a claim to the contrary)
* New: List and filter called/calling functions in the call graph
* New: Delete graph nodes
* New: Limit graph node in/out degree (requires latest Cscope CVS snapshot)
* Improved: Redesigned node menu in the graph widget
* Improved: All query result views share the same widget
* Improved: Session management remembers file locations and last open file
(thanks to Alexander Kern)
* Bug Fix: Delete graph files when they are no longer required (i.e., after
a graph dialogue is manually closed)
* Bug fix: Do not show a border around the graph (nasty fix, but it works)
* Bug fix: Nodes are now always drawn on top of edges
* Compilation fix: Use QPtrList instead of the deprecated QList
* Compilation fix: Should now compile with gcc 4.x
1.3.0 (29-Jun-2005)
* New: A new call graph based on the graphviz library
* New: Use a special dialogue for executing and displaying quick
definition queries
* New: Use the project's root in the file list (root directory replaced
by a $ symbol)
* Improved: Faster compilation through the inclusion of moc files
* Improved: Better organised menu and toolbars
* Improved: Quick definition does not write into the query widget
1.2.0 (25-May-2005)
* New: Keyboard shortcut for setting the focus to the file list
* Improved: Documentation is now up to date
* Improved: Use standard configuration actions
* Improved: Faster loading times for projects
* Bug fix: Incorrect sorting of the symbol history combo-box
* Bug fix: Query window hidden unnecessarily on some occasions
* Bug fix: A hidden query window is shown by the "Position History" menu
command
* Bug fix: Modifying non-project files triggered a database rebuild
1.1.1 (17-Mar-2005)
* New: A new tab widget that displays a popup-menu with all open tabs
* New: Automatic configuration of Cscope/Ctags paths and parameters
* New: Filter query results
* New: Tag list can be hidden
* Improved: Display unique entries in the completion list
* Improved: Two options for the editor's popup menu: Cscope actions embedded
in the editor's own menu, or the old-style KScope-only menu
* Improved: The process of closing all editor windows (explicitly, when closing a
project or when exiting KScope) is much faster
* Bug fix: Do not show a hidden query window when browsing through position
history
* Bug fix: Refreshing a locked query opened a new page
* Bug fix: Possibly wrong tag-highlighting if cursor was moved while Ctags is
working
* Compilation Fix: Compiles under KDE 3.2 again
1.1.0 (1-Feb-2005)
* New: Cross-reference database is rebuilt automatically
* New: Symbol completion (manual and automatic)
* New: Allow multiple queries to be issued simultaneously
* New: Query dialogue with symbol hinting, history, substring search option
and and the ability to change the query type
* New: System profiles (fast/slow) determine default settings for
time-consuming operations
* New: Multiple position history paths
* New: Postion history can be saved and restored
* New: Drag&Drop support
* New: Optional warnings when file is modified outside KScope (Supports Kate
part only)
* New: Call Tree support for both Called and Calling tree modes
* New: Call Tree save/restore support within the project
* New: Unobtrusive progress information for all Cscope queries
* New: Query results popup-menu for copying and removing items
* New: Menu option for showing/hiding the toolbar
* New: Configurable keyboard shortcuts
* Improved: More command line options
* Improved: External editor can be invoked in read-write mode
* Improved: Faster project load times (file list is not sorted by default)
* Bug fix: Symbol list last entry was not found
* Bug fix: Crashed when jumping to a new position and no pages are open
* Bug fix: Synchronise splitter sizes whenever a page gains focus
* Bug fix: Query dialogue suggested text did not check current character
* Bug fix: the progress information did not work with inverted index or
regular expressions
1.0 (7-Dec-2004)
* Bug fix: Selecting entries in the position history dialogue messes up the
history (thanks to Fekete Gabor)
* Bug fix: Double clicking a directory name in the file system tree view opens
an editor page (thanks to Fekete Gabor)
* Bug fix: "No source file found" message not detected since error output may
be broken (fix allows Cscope restart mechanism to be re-enabled)
* Bug fix: Return file-system root as the root directory of a temporary project
* Bug fix: Handle file names without an extension in the file list (thanks to
Anton G. Alvedro)
* Bug fix: Show the main window before loading the last project (fixes
problems with the width of the tag list)
* Bug fix: Use CTRL-5 for the EGrep pattern shortcut (CTRL-6 is already used
by Kate)
* Bug fix: Do not restart Cscope when a file of the wrong format is opened as
a cscope.out file
* Bug fix: Open editor pages were not found when using relative paths in
cscope.files (thanks to Chris Mason)
* Bug fix: Cannot rebuild database when working with temporary projects,
re-run Cscope instead (thanks to Chris Mason)
* Bug fix: Do not populate file tree recursively (may significantly
increase the project loading time) (thanks to Albert Yosher)
* Bug fix: Maximise main window before displaying the welcome message (on
first time usage)
* Bug fix: Empty position history was added if jumping when no files were
open (thanks to Fekete Gabor)
* Bug fix: Editor was not set to read-write mode if the edited file changed
its permission (thanks to Albert Yosher)
* Bug fix: Clean paths from '.' and '..' before opening a file (thanks to
Albert Yosher)
* Bug fix: KScope Crashes after applying new configuration if an empty query page
exists
* Bug fix: Use Ctrl-\ for a call tree (Ctrl-- is already used by Kate)
* Improved project loading process
* Made documentation compliant with KDE's conventions
0.9 (14-Oct-2004)
* Option for using an external editor
* File-system tree-view
* Use application icons for tabs (for consistent look across themes)
* Option for shorter query captions (thanks to Fekete Gabor)
* Store current location before jumping (fixes position history behaviour)
* Show current file path in KScope's title bar
* Handle read-only files correctly
* Show a special tab icon for a read-only file
* Vim-style quick definition
* Bug fix: ignore Cscope's "Possible references retrieved" messages
(thanks to Fekete Gabor)
* Bug fix: report Cscope is working when rebuilding the cross-reference
database
0.8 (2-Aug-2004)
* Select word from cursor position when initiating a query
* Show cursor position in status bar
* Highlight relevant tag based on cursor position
* Allow running KScope in read-only mode
* "Fonts" preference page
* "Options" preference page
* A "refresh query" command for the query pages
* Query file format changed to include query type and text (old files will
not be loaded)
* Bug fix: restore file icon to unchanged when all undo levels have been
applied (thanks to Fekete Gabor)
* Bug fix: better handling of the tag list width
* Bug fix: accept any file name containing "ctags" as the Ctags executable
(since Gentoo is using exuberant-ctags)
* Bug fix: files could not be reopened after "Close All Windows" (thanks to
Fekete Gabor)
* Bug fix: query window may be incorrectly hidden if query returns a
single record
0.7 (15-Jun-2004)
* Restore project session (open files and locked queries)
* Lock/unlock queries
* Prompt to save files before any file is closed
* Use KTabWidget for both the Editors window and the Query window
* Mark modified files
* Show/hide the file list and the query window (thanks to Fekete Gabor)
* Save/restore main window layout
* Better Ctags support (using native Ctags files)
* Open Cscope.out files in temporary projects, also available from the
command line (thanks to Fekete Gabor)
* Removed sort buttons (requires further consideration)
* Tag list sorting order is saved
* Query page buttons to the right of the query widget
* Bug fix: project was not closed if program was terminated from the main
window's title-bar
* Bug fix: allow ctags-exuberant as the programme name for Ctags
0.6 (21-Apr-2004)
* Adjusted to KDE 3.2 (previous versions are no longer supported)
* Implemented standard "New File" and "Open File" commands
* Line numbers are aligned to the right
* Display the type of each file in the file list
* Use unsigned int for the entry size in Frontend (fixes compiler warnings)
* Implemented Cscope's search for file query
* Files are opened automatically if only one record was returned by a query
* Close buttons for the editor tabs
* Display Cscope error messages in a modeless dialogue
* Basic navigation through position history
* Open last project on restart
* Option to build inverted index for projects (thanks to Fekete Gabor)
* Project properties dialogue
* Bug fix: calling for an including files query prompts for an EGrep pattern
(thanks to Fekete Gabor)
* Bug fix: program crashes on including files query
* Bug fix: set keyboard focus to editor when moving between tabs
0.5 (3-Jan-2004)
* Moved project to KDevelop 3.0 format
* A new "Window" menu displaying a list of open files
* The full path name appears as a tool-tip on each editor tab
* Close buttons for query results windows
* Fixed Tab order in dialogues
0.4 (9-Oct-2003)
* New integrated manual
* Project files dialogue (add/remove source files)
* Prompt for files when a project is empty
* Bug fix: Error in rebuild command to cscope (string too long)
* Bug fix: Directory names in the paths configuration were mistaken as legal
executable files
* Bug fix: The directory scanner did not clean its list between consecutive
searches (thanks to Craig Graham for this fix)
* Bug fix: Initial file count in the dir scanning progress dialogue showed
'123456' instead of '0'
* Prompt the user to close the active project before creating a new one
* Prevent the user from cancelling an already-finished query (i.e., while
results are written to the query window)
0.3 (3-Aug-2003)
* Context menu for running queries from an editor window
* A dummy progress dialogue is displayed when progress information is
unavailable (simply to indicate that KScope is working)
* Bug fix: Mix-up between the "Calling functions" and "Called functions" in
the query page titles
* Bug fix: Only ".c" and ".h" files could be added to a project
* New query type: find #including files
* Inform the user when a query ends with no results
* Menu command to close the active project
* All query pages are removed when a project is closed
0.2 (21-Jul-2003)
* Call tree window
* High-colour icons
* Sort buttons for the tag list
* Partial fix for the cursor positioning bug in Kate
0.1 (3-Jul-2003)
* First public release
* Front-end to most CScope features
* Basic editing environment (multiple windows)
* Tag list for each open editor
* Multiple query windows
* Basic project management

@ -0,0 +1,259 @@
# Doxyfile 1.4.1-KDevelop
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = KScope
PROJECT_NUMBER = 1.3.3
OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = YES
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = src
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.idl \
*.odl \
*.cs \
*.php \
*.php3 \
*.inc \
*.C \
*.H \
*.tlh \
*.diff \
*.patch \
*.moc \
*.xpm \
*.dox
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = YES
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

@ -0,0 +1,167 @@
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes a while. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Type `make install' to install the programs and any data files and
documentation.
4. You can remove the program binaries and object files from the
source code directory by typing `make clean'.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made.
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.

@ -0,0 +1,22 @@
SUBDIRS = $(TOPSUBDIRS)
$(top_srcdir)/configure.in: configure.in.in $(top_srcdir)/subdirs
cd $(top_srcdir) && $(MAKE) -f admin/Makefile.common configure.in ;
$(top_srcdir)/subdirs:
cd $(top_srcdir) && $(MAKE) -f admin/Makefile.common subdirs
$(top_srcdir)/acinclude.m4: $(top_srcdir)/admin/acinclude.m4.in $(top_srcdir)/admin/libtool.m4.in
@cd $(top_srcdir) && cat admin/acinclude.m4.in admin/libtool.m4.in > acinclude.m4
MAINTAINERCLEANFILES = subdirs configure.in acinclude.m4 configure.files
package-messages:
$(MAKE) -f admin/Makefile.common package-messages
$(MAKE) -C po merge
EXTRA_DIST = admin COPYING configure.in.in
dist-hook:
cd $(top_distdir) && perl admin/am_edit -padmin
cd $(top_distdir) && $(MAKE) -f admin/Makefile.common subdirs

@ -0,0 +1 @@

17
TODO

@ -0,0 +1,17 @@
KScope TODO List
================
No. Problem Type Target Version
~~~ ~~~~~~~ ~~~~ ~~~~~~~~~~~~~~
01. Project bookmark infrastructure/GUI Feat ?
02. "Find Next" in search lists Feat ?
03. New call tree widget Feat ?
04. Plugin architecture Feat ?
05. New GUI Feat ?
* IDEAl-style main window (?)
* True MDI (?)

File diff suppressed because it is too large Load Diff

902
aclocal.m4 vendored

@ -0,0 +1,902 @@
# generated automatically by aclocal 1.10.1 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(AC_AUTOCONF_VERSION, [2.62],,
[m4_warning([this file was generated for autoconf 2.62.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.])])
# Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.10'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.10.1], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# _AM_AUTOCONF_VERSION(VERSION)
# -----------------------------
# aclocal traces this macro to find the Autoconf version.
# This is a private macro too. Using m4_define simplifies
# the logic in aclocal, which can simply ignore this definition.
m4_define([_AM_AUTOCONF_VERSION], [])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.10.1])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
#
# Of course, Automake must honor this variable whenever it calls a
# tool from the auxiliary directory. The problem is that $srcdir (and
# therefore $ac_aux_dir as well) can be either absolute or relative,
# depending on how configure is run. This is pretty annoying, since
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
# source directory, any form will work fine, but in subdirectories a
# relative path needs to be adjusted first.
#
# $ac_aux_dir/missing
# fails when called from a subdirectory if $ac_aux_dir is relative
# $top_srcdir/$ac_aux_dir/missing
# fails if $ac_aux_dir is absolute,
# fails when called from a subdirectory in a VPATH build with
# a relative $ac_aux_dir
#
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
# are both prefixed by $srcdir. In an in-source build this is usually
# harmless because $srcdir is `.', but things will broke when you
# start a VPATH build or use an absolute $srcdir.
#
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
# and then we would define $MISSING as
# MISSING="\${SHELL} $am_aux_dir/missing"
# This will work as long as MISSING is not called from configure, because
# unfortunately $(top_srcdir) has no meaning in configure.
# However there are other variables, like CC, which are often used in
# configure, and could therefore not use this "fixed" $ac_aux_dir.
#
# Another solution, used here, is to always expand $ac_aux_dir to an
# absolute PATH. The drawback is that using absolute paths prevent a
# configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND],
[dnl Rely on autoconf to set up CDPATH properly.
AC_PREREQ([2.50])dnl
# expand $ac_aux_dir to an absolute path
am_aux_dir=`cd $ac_aux_dir && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 8
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
[AC_PREREQ(2.52)dnl
ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi
AC_CONFIG_COMMANDS_PRE(
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
AC_MSG_ERROR([[conditional "$1" was never defined.
Usually this means the macro was only invoked conditionally.]])
fi])])
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 9
# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
# written in clear, in which case automake, when reading aclocal.m4,
# will think it sees a *use*, and therefore will trigger all it's
# C support machinery. Also note that it means that autoscan, seeing
# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
# _AM_DEPENDENCIES(NAME)
# ----------------------
# See how the compiler implements dependency checking.
# NAME is "CC", "CXX", "GCJ", or "OBJC".
# We try a few techniques and use that to set a single cache variable.
#
# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
# dependency, and given that the user is not expected to run this macro,
# just rely on AC_PROG_CC.
AC_DEFUN([_AM_DEPENDENCIES],
[AC_REQUIRE([AM_SET_DEPDIR])dnl
AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
AC_REQUIRE([AM_MAKE_INCLUDE])dnl
AC_REQUIRE([AM_DEP_TRACK])dnl
ifelse([$1], CC, [depcc="$CC" am_compiler_list=],
[$1], CXX, [depcc="$CXX" am_compiler_list=],
[$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
[$1], UPC, [depcc="$UPC" am_compiler_list=],
[$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
[depcc="$$1" am_compiler_list=])
AC_CACHE_CHECK([dependency style of $depcc],
[am_cv_$1_dependencies_compiler_type],
[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
# We make a subdir and do the tests there. Otherwise we can end up
# making bogus files that we don't know about and never remove. For
# instance it was reported that on HP-UX the gcc test will end up
# making a dummy file named `D' -- because `-MD' means `put the output
# in D'.
mkdir conftest.dir
# Copy depcomp to subdir because otherwise we won't find it if we're
# using a relative directory.
cp "$am_depcomp" conftest.dir
cd conftest.dir
# We will build objects and dependencies in a subdirectory because
# it helps to detect inapplicable dependency modes. For instance
# both Tru64's cc and ICC support -MD to output dependencies as a
# side effect of compilation, but ICC will put the dependencies in
# the current directory while Tru64 will put them in the object
# directory.
mkdir sub
am_cv_$1_dependencies_compiler_type=none
if test "$am_compiler_list" = ""; then
am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
fi
for depmode in $am_compiler_list; do
# Setup a source with many dependencies, because some compilers
# like to wrap large dependency lists on column 80 (with \), and
# we should not choose a depcomp mode which is confused by this.
#
# We need to recreate these files for each test, as the compiler may
# overwrite some of them when testing with obscure command lines.
# This happens at least with the AIX C compiler.
: > sub/conftest.c
for i in 1 2 3 4 5 6; do
echo '#include "conftst'$i'.h"' >> sub/conftest.c
# Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
# Solaris 8's {/usr,}/bin/sh.
touch sub/conftst$i.h
done
echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
case $depmode in
nosideeffect)
# after this tag, mechanisms are not by side-effect, so they'll
# only be used when explicitly requested
if test "x$enable_dependency_tracking" = xyes; then
continue
else
break
fi
;;
none) break ;;
esac
# We check with `-c' and `-o' for the sake of the "dashmstdout"
# mode. It turns out that the SunPro C++ compiler does not properly
# handle `-M -o', and we need to detect this.
if depmode=$depmode \
source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \
depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
$SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \
>/dev/null 2>conftest.err &&
grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 &&
${MAKE-make} -s -f confmf > /dev/null 2>&1; then
# icc doesn't choke on unknown options, it will just issue warnings
# or remarks (even with -Werror). So we grep stderr for any message
# that says an option was ignored or not supported.
# When given -MP, icc 7.0 and 7.1 complain thusly:
# icc: Command line warning: ignoring option '-M'; no argument required
# The diagnosis changed in icc 8.0:
# icc: Command line remark: option '-MP' not supported
if (grep 'ignoring option' conftest.err ||
grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
am_cv_$1_dependencies_compiler_type=$depmode
break
fi
fi
done
cd ..
rm -rf conftest.dir
else
am_cv_$1_dependencies_compiler_type=none
fi
])
AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
AM_CONDITIONAL([am__fastdep$1], [
test "x$enable_dependency_tracking" != xno \
&& test "$am_cv_$1_dependencies_compiler_type" = gcc3])
])
# AM_SET_DEPDIR
# -------------
# Choose a directory name for dependency files.
# This macro is AC_REQUIREd in _AM_DEPENDENCIES
AC_DEFUN([AM_SET_DEPDIR],
[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
])
# AM_DEP_TRACK
# ------------
AC_DEFUN([AM_DEP_TRACK],
[AC_ARG_ENABLE(dependency-tracking,
[ --disable-dependency-tracking speeds up one-time build
--enable-dependency-tracking do not reject slow dependency extractors])
if test "x$enable_dependency_tracking" != xno; then
am_depcomp="$ac_aux_dir/depcomp"
AMDEPBACKSLASH='\'
fi
AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
AC_SUBST([AMDEPBACKSLASH])dnl
_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
])
# Generate code to set up dependency tracking. -*- Autoconf -*-
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#serial 3
# _AM_OUTPUT_DEPENDENCY_COMMANDS
# ------------------------------
AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
[for mf in $CONFIG_FILES; do
# Strip MF so we end up with the name of the file.
mf=`echo "$mf" | sed -e 's/:.*$//'`
# Check whether this is an Automake generated Makefile or not.
# We used to match only the files named `Makefile.in', but
# some people rename them; so instead we look at the file content.
# Grep'ing the first line is not enough: some people post-process
# each Makefile.in and add a new line on top of each file to say so.
# Grep'ing the whole file is not good either: AIX grep has a line
# limit of 2048, but all sed's we know have understand at least 4000.
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
dirpart=`AS_DIRNAME("$mf")`
else
continue
fi
# Extract the definition of DEPDIR, am__include, and am__quote
# from the Makefile without running `make'.
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
test -z "$DEPDIR" && continue
am__include=`sed -n 's/^am__include = //p' < "$mf"`
test -z "am__include" && continue
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
# When using ansi2knr, U may be empty or an underscore; expand it
U=`sed -n 's/^U = //p' < "$mf"`
# Find all dependency output files, they are included files with
# $(DEPDIR) in their names. We invoke sed twice because it is the
# simplest approach to changing $(DEPDIR) to its actual value in the
# expansion.
for file in `sed -n "
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
# Make sure the directory exists.
test -f "$dirpart/$file" && continue
fdir=`AS_DIRNAME(["$file"])`
AS_MKDIR_P([$dirpart/$fdir])
# echo "creating $dirpart/$file"
echo '# dummy' > "$dirpart/$file"
done
done
])# _AM_OUTPUT_DEPENDENCY_COMMANDS
# AM_OUTPUT_DEPENDENCY_COMMANDS
# -----------------------------
# This macro should only be invoked once -- use via AC_REQUIRE.
#
# This code is only required when automatic dependency tracking
# is enabled. FIXME. This creates each `.P' file that we will
# need in order to bootstrap the dependency handling code.
AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
[AC_CONFIG_COMMANDS([depfiles],
[test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
[AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
])
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 8
# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS.
AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 13
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
# AM_INIT_AUTOMAKE([OPTIONS])
# -----------------------------------------------
# The call with PACKAGE and VERSION arguments is the old style
# call (pre autoconf-2.50), which is being phased out. PACKAGE
# and VERSION should now be passed to AC_INIT and removed from
# the call to AM_INIT_AUTOMAKE.
# We support both call styles for the transition. After
# the next Automake release, Autoconf can make the AC_INIT
# arguments mandatory, and then we can depend on a new Autoconf
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.60])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
AC_REQUIRE([AC_PROG_INSTALL])dnl
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
fi
# test whether we have cygpath
if test -z "$CYGPATH_W"; then
if (cygpath --version) >/dev/null 2>/dev/null; then
CYGPATH_W='cygpath -w'
else
CYGPATH_W=echo
fi
fi
AC_SUBST([CYGPATH_W])
# Define the identity of the package.
dnl Distinguish between old-style and new-style calls.
m4_ifval([$2],
[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
_AM_IF_OPTION([no-define],,
[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
# Some tools Automake needs.
AC_REQUIRE([AM_SANITY_CHECK])dnl
AC_REQUIRE([AC_ARG_PROGRAM])dnl
AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
AM_MISSING_PROG(AUTOCONF, autoconf)
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
AM_MISSING_PROG(AUTOHEADER, autoheader)
AM_MISSING_PROG(MAKEINFO, makeinfo)
AM_PROG_INSTALL_SH
AM_PROG_INSTALL_STRIP
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
[_AM_PROG_TAR([v7])])])
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
[_AM_DEPENDENCIES(CC)],
[define([AC_PROG_CC],
defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
[_AM_DEPENDENCIES(CXX)],
[define([AC_PROG_CXX],
defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[_AM_DEPENDENCIES(OBJC)],
[define([AC_PROG_OBJC],
defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
])
])
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp files are numbered to have different names.
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
# loop where config.status creates the headers, so we can generate
# our stamp files there.
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
[# Compute $1's index in $config_headers.
_am_arg=$1
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"}
AC_SUBST(install_sh)])
# Copyright (C) 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 2
# Check whether the underlying file-system supports filenames
# with a leading dot. For instance MS-DOS doesn't.
AC_DEFUN([AM_SET_LEADING_DOT],
[rm -rf .tst 2>/dev/null
mkdir .tst 2>/dev/null
if test -d .tst; then
am__leading_dot=.
else
am__leading_dot=_
fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 5
# AM_PROG_LEX
# -----------
# Autoconf leaves LEX=: if lex or flex can't be found. Change that to a
# "missing" invocation, for better error output.
AC_DEFUN([AM_PROG_LEX],
[AC_PREREQ(2.50)dnl
AC_REQUIRE([AM_MISSING_HAS_RUN])dnl
AC_REQUIRE([AC_PROG_LEX])dnl
if test "$LEX" = :; then
LEX=${am_missing_run}flex
fi])
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 3
# AM_MAKE_INCLUDE()
# -----------------
# Check to see how make treats includes.
AC_DEFUN([AM_MAKE_INCLUDE],
[am_make=${MAKE-make}
cat > confinc << 'END'
am__doit:
@echo done
.PHONY: am__doit
END
# If we don't find an include directive, just comment out the code.
AC_MSG_CHECKING([for style of include used by $am_make])
am__include="#"
am__quote=
_am_result=none
# First try GNU make style include.
echo "include confinc" > confmf
# We grep out `Entering directory' and `Leaving directory'
# messages which can occur if `w' ends up in MAKEFLAGS.
# In particular we don't look at `^make:' because GNU make might
# be invoked under some other name (usually "gmake"), in which
# case it prints its new name instead of `make'.
if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then
am__include=include
am__quote=
_am_result=GNU
fi
# Now try BSD make style include.
if test "$am__include" = "#"; then
echo '.include "confinc"' > confmf
if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then
am__include=.include
am__quote="\""
_am_result=BSD
fi
fi
AC_SUBST([am__include])
AC_SUBST([am__quote])
AC_MSG_RESULT([$_am_result])
rm -f confinc confmf
])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 5
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
[AC_REQUIRE([AM_MISSING_HAS_RUN])
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
# AM_MISSING_HAS_RUN
# ------------------
# Define MISSING if not defined so far and test if it supports --run.
# If it does, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
# Use eval to expand $SHELL
if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
else
am_missing_run=
AC_MSG_WARN([`missing' script is too old or missing])
fi
])
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_MKDIR_P
# ---------------
# Check for `mkdir -p'.
AC_DEFUN([AM_PROG_MKDIR_P],
[AC_PREREQ([2.60])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
dnl while keeping a definition of mkdir_p for backward compatibility.
dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
dnl Makefile.ins that do not define MKDIR_P, so we do our own
dnl adjustment using top_builddir (which is defined more often than
dnl MKDIR_P).
AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
case $mkdir_p in
[[\\/$]]* | ?:[[\\/]]*) ;;
*/*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
esac
])
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 3
# _AM_MANGLE_OPTION(NAME)
# -----------------------
AC_DEFUN([_AM_MANGLE_OPTION],
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
# _AM_SET_OPTION(NAME)
# ------------------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
# _AM_SET_OPTIONS(OPTIONS)
# ----------------------------------
# OPTIONS is a space-separated list of Automake options.
AC_DEFUN([_AM_SET_OPTIONS],
[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
# -------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 4
# AM_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftest.file
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
if test "$[*]" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftest.file`
fi
rm -f conftest.file
if test "$[*]" != "X $srcdir/configure conftest.file" \
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "$[2]" = conftest.file
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
AC_MSG_RESULT(yes)])
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_STRIP
# ---------------------
# One issue with vendor `install' (even GNU) is that you can't
# specify the program used to strip binaries. This is especially
# annoying in cross-compiling environments, where the build's strip
# is unlikely to handle the host's binaries.
# Fortunately install-sh will honor a STRIPPROG variable, so we
# always use install-sh in `make install-strip', and initialize
# STRIPPROG with the value of the STRIP variable (set by the user).
AC_DEFUN([AM_PROG_INSTALL_STRIP],
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
# Installed binaries are usually stripped using `strip' when the user
# run `make install-strip'. However `strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
# will honor the `STRIP' environment variable to overrule this program.
dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
if test "$cross_compiling" != no; then
AC_CHECK_TOOL([STRIP], [strip], :)
fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
# This macro is traced by Automake.
AC_DEFUN([_AM_SUBST_NOTMAKE])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 2
# _AM_PROG_TAR(FORMAT)
# --------------------
# Check how to create a tarball in format FORMAT.
# FORMAT should be one of `v7', `ustar', or `pax'.
#
# Substitute a variable $(am__tar) that is a command
# writing to stdout a FORMAT-tarball containing the directory
# $tardir.
# tardir=directory && $(am__tar) > result.tar
#
# Substitute a variable $(am__untar) that extract such
# a tarball read from stdin.
# $(am__untar) < result.tar
AC_DEFUN([_AM_PROG_TAR],
[# Always define AMTAR for backward compatibility.
AM_MISSING_PROG([AMTAR], [tar])
m4_if([$1], [v7],
[am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
[m4_case([$1], [ustar],, [pax],,
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
# Loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
# Do not fold the above two line into one, because Tru64 sh and
# Solaris sh will not grok spaces in the rhs of `-'.
for _am_tool in $_am_tools
do
case $_am_tool in
gnutar)
for _am_tar in tar gnutar gtar;
do
AM_RUN_LOG([$_am_tar --version]) && break
done
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
am__untar="$_am_tar -xf -"
;;
plaintar)
# Must skip GNU tar: if it does not support --format= it doesn't create
# ustar tarball either.
(tar --version) >/dev/null 2>&1 && continue
am__tar='tar chf - "$$tardir"'
am__tar_='tar chf - "$tardir"'
am__untar='tar xf -'
;;
pax)
am__tar='pax -L -x $1 -w "$$tardir"'
am__tar_='pax -L -x $1 -w "$tardir"'
am__untar='pax -r'
;;
cpio)
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
am__untar='cpio -i -H $1 -d'
;;
none)
am__tar=false
am__tar_=false
am__untar=false
;;
esac
# If the value was cached, stop now. We just wanted to have am__tar
# and am__untar set.
test -n "${am_cv_prog_tar_$1}" && break
# tar/untar a dummy directory, and stop if the command works
rm -rf conftest.dir
mkdir conftest.dir
echo GrepMe > conftest.dir/file
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
rm -rf conftest.dir
if test -s conftest.tar; then
AM_RUN_LOG([$am__untar <conftest.tar])
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
fi
done
rm -rf conftest.dir
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([acinclude.m4])

@ -0,0 +1,252 @@
/* config.h.in. Generated from configure.in by autoheader. */
/* Define to 1 if you have the <Carbon/Carbon.h> header file. */
#undef HAVE_CARBON_CARBON_H
/* Define if you have the CoreAudio API */
#undef HAVE_COREAUDIO
/* Define to 1 if you have the <crt_externs.h> header file. */
#undef HAVE_CRT_EXTERNS_H
/* Defines if your system has the crypt function */
#undef HAVE_CRYPT
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define if you have libjpeg */
#undef HAVE_LIBJPEG
/* Define if you have libpng */
#undef HAVE_LIBPNG
/* Define if you have a working libpthread (will enable threaded code) */
#undef HAVE_LIBPTHREAD
/* Define if you have libz */
#undef HAVE_LIBZ
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define if your system needs _NSGetEnviron to set up the environment */
#undef HAVE_NSGETENVIRON
/* Define if you have res_init */
#undef HAVE_RES_INIT
/* Define if you have the res_init prototype */
#undef HAVE_RES_INIT_PROTO
/* Define if you have a STL implementation by SGI */
#undef HAVE_SGI_STL
/* Define to 1 if you have the `snprintf' function. */
#undef HAVE_SNPRINTF
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if you have strlcat */
#undef HAVE_STRLCAT
/* Define if you have the strlcat prototype */
#undef HAVE_STRLCAT_PROTO
/* Define if you have strlcpy */
#undef HAVE_STRLCPY
/* Define if you have the strlcpy prototype */
#undef HAVE_STRLCPY_PROTO
/* Define to 1 if you have the <sys/bitypes.h> header file. */
#undef HAVE_SYS_BITYPES_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
/* Suffix for lib directories */
#undef KDELIBSUFF
/* Define a safe value for MAXPATHLEN */
#undef KDEMAXPATHLEN
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of `char *', as computed by sizeof. */
#undef SIZEOF_CHAR_P
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of `long', as computed by sizeof. */
#undef SIZEOF_LONG
/* The size of `short', as computed by sizeof. */
#undef SIZEOF_SHORT
/* The size of `size_t', as computed by sizeof. */
#undef SIZEOF_SIZE_T
/* The size of `unsigned long', as computed by sizeof. */
#undef SIZEOF_UNSIGNED_LONG
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
/* Defined if compiling without arts */
#undef WITHOUT_ARTS
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel and VAX). */
#if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
#elif ! defined __LITTLE_ENDIAN__
# undef WORDS_BIGENDIAN
#endif
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
`char[]'. */
#undef YYTEXT_POINTER
/*
* jpeg.h needs HAVE_BOOLEAN, when the system uses boolean in system
* headers and I'm too lazy to write a configure test as long as only
* unixware is related
*/
#ifdef _UNIXWARE
#define HAVE_BOOLEAN
#endif
/*
* AIX defines FD_SET in terms of bzero, but fails to include <strings.h>
* that defines bzero.
*/
#if defined(_AIX)
#include <strings.h>
#endif
#if defined(HAVE_NSGETENVIRON) && defined(HAVE_CRT_EXTERNS_H)
# include <sys/time.h>
# include <crt_externs.h>
# define environ (*_NSGetEnviron())
#endif
#if !defined(HAVE_RES_INIT_PROTO)
#ifdef __cplusplus
extern "C" {
#endif
int res_init(void);
#ifdef __cplusplus
}
#endif
#endif
#if !defined(HAVE_STRLCAT_PROTO)
#ifdef __cplusplus
extern "C" {
#endif
unsigned long strlcat(char*, const char*, unsigned long);
#ifdef __cplusplus
}
#endif
#endif
#if !defined(HAVE_STRLCPY_PROTO)
#ifdef __cplusplus
extern "C" {
#endif
unsigned long strlcpy(char*, const char*, unsigned long);
#ifdef __cplusplus
}
#endif
#endif
/*
* On HP-UX, the declaration of vsnprintf() is needed every time !
*/
#if !defined(HAVE_VSNPRINTF) || defined(hpux)
#if __STDC__
#include <stdarg.h>
#include <stdlib.h>
#else
#include <varargs.h>
#endif
#ifdef __cplusplus
extern "C"
#endif
int vsnprintf(char *str, size_t n, char const *fmt, va_list ap);
#ifdef __cplusplus
extern "C"
#endif
int snprintf(char *str, size_t n, char const *fmt, ...);
#endif
#if defined(__SVR4) && !defined(__svr4__)
#define __svr4__ 1
#endif
/* type to use in place of socklen_t if not defined */
#undef kde_socklen_t
/* type to use in place of socklen_t if not defined (deprecated, use
kde_socklen_t) */
#undef ksize_t

@ -0,0 +1,2 @@
./admin/configure.in.min
configure.in.in

@ -0,0 +1,93 @@
dnl This file is part of the KDE libraries/packages
dnl Copyright (C) 2001 Stephan Kulow (coolo@kde.org)
dnl This file is free software; you can redistribute it and/or
dnl modify it under the terms of the GNU Library General Public
dnl License as published by the Free Software Foundation; either
dnl version 2 of the License, or (at your option) any later version.
dnl This library is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dnl Library General Public License for more details.
dnl You should have received a copy of the GNU Library General Public License
dnl along with this library; see the file COPYING.LIB. If not, write to
dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
dnl Boston, MA 02111-1307, USA.
# Original Author was Kalle@kde.org
# I lifted it in some mater. (Stephan Kulow)
# I used much code from Janos Farkas
dnl Process this file with autoconf to produce a configure script.
AC_INIT(acinclude.m4) dnl a source file from your sub dir
dnl This is so we can use kde-common
AC_CONFIG_AUX_DIR(admin)
dnl This ksh/zsh feature conflicts with `cd blah ; pwd`
unset CDPATH
dnl Checking host/target/build systems, for make, install etc.
AC_CANONICAL_SYSTEM
dnl Perform program name transformation
AC_ARG_PROGRAM
dnl Automake doc recommends to do this only here. (Janos)
AM_INIT_AUTOMAKE(kscope, 1.6.2) dnl searches for some needed programs
KDE_SET_PREFIX
dnl generate the config header
AM_CONFIG_HEADER(config.h) dnl at the distribution this done
dnl Checks for programs.
AC_CHECK_COMPILERS
AC_ENABLE_SHARED(yes)
AC_ENABLE_STATIC(no)
KDE_PROG_LIBTOOL
dnl for NLS support. Call them in this order!
dnl WITH_NLS is for the po files
AM_KDE_WITH_NLS
KDE_USE_QT(3.3)
AC_PATH_KDE
#MIN_CONFIG(3.3)
dnl PACKAGE set before
AC_C_BIGENDIAN
AC_CHECK_KDEMAXPATHLEN
AM_PROG_LEX
AC_CHECK_PROG(HAVE_LEX, $LEX, yes, no)
if [[ "$HAVE_LEX" = "no" ]]; then
AC_MSG_ERROR(Lex/Flex is required in order to build KScope)
fi
AC_PROG_YACC
AC_CHECK_PROG(HAVE_YACC, $YACC, yes, no)
if [[ "$HAVE_YACC" = "no" ]]; then
AC_MSG_ERROR(Yacc/Bison is required in order to build KScope)
fi
KDE_CREATE_SUBDIRSLIST
AC_CONFIG_FILES([ Makefile ])
AC_CONFIG_FILES([ doc/Makefile ])
AC_CONFIG_FILES([ doc/en/Makefile ])
AC_CONFIG_FILES([ po/Makefile ])
AC_CONFIG_FILES([ src/Makefile ])
AC_OUTPUT
if test "$all_tests" = "bad"; then
if test ! "$cache_file" = "/dev/null"; then
echo ""
echo "Please remove the file $cache_file after changing your setup"
echo "so that configure will find the changes next time."
echo ""
fi
else
echo ""
echo "Good - your configure finished. Start make now"
echo ""
fi

@ -0,0 +1,17 @@
#MIN_CONFIG(3.3)
AM_INIT_AUTOMAKE(kscope, 1.6.2)
AC_C_BIGENDIAN
AC_CHECK_KDEMAXPATHLEN
AM_PROG_LEX
AC_CHECK_PROG(HAVE_LEX, $LEX, yes, no)
if [[ "$HAVE_LEX" = "no" ]]; then
AC_MSG_ERROR(Lex/Flex is required in order to build KScope)
fi
AC_PROG_YACC
AC_CHECK_PROG(HAVE_YACC, $YACC, yes, no)
if [[ "$HAVE_YACC" = "no" ]]; then
AC_MSG_ERROR(Yacc/Bison is required in order to build KScope)
fi

@ -0,0 +1,6 @@
# the SUBDIRS is filled automatically by am_edit. If files are
# in this directory they are installed into the english dir
KDE_LANG = en
KDE_DOCS = kscope
SUBDIRS = $(AUTODIRS)

@ -0,0 +1,5 @@
KDE_DOCS = kscope
KDE_LANG = en
kde_docs_KDEDOCS = call_tree.png main_window.png pref.png project_files.png \
project_new.png project_open.png query_dlg.png autocomp_dlg.png query_filter.png \
call_graph.png

@ -0,0 +1,31 @@
<sect1 id="about">
<title>About &kapp;</title>
<para>
&kapp; is a KDE-based source-editing environment for C and C-style languages. Primarily, it is a front-end to the veteran <ulink url="http://cscope.sourceforge.net">Cscope</ulink>, a source-code browser originally developed at Bell Labs. <application>Cscope</application> works by parsing a set of source files, creating a cross-reference database, and allowing the user to query this database. &kapp; extends the feature-set of <application>Cscope</application> with a contemporary user interface, editor integration, project management capabilities, multiple query result windows, call trees and graphs, and more.
</para>
<para>
&kapp; implements (almost) all of <application>Cscope</application>'s query types. Among these are:
<itemizedlist>
<listitem><para>Browse for all references to a symbol;</para></listitem>
<listitem><para>Get the global definition of a symbol;</para></listitem>
<listitem><para>Find all functions calling to or called by a function;</para></listitem>
<listitem><para>Find a text string or an EGrep pattern;</para></listitem>
<listitem><para>and more.</para></listitem>
</itemizedlist>
</para>
<para>
The main purpose of &kapp; is to provide developers with a rich environment for code editing and analysis. It is specifically geared towards large projects, with thousands of source files and millions of lines of code. Many traditional C/C++ IDEs do not scale well to handle projects of this magnitude, either because they do not provide adequate tools for understanding the code base, or because they are unable to efficiently digest that much information. By using <application>Cscope</application> as its underlying engine, &kapp; can easily handle projects such as the <ulink url="http://www.kernel.org">Linux kernel</ulink>, <ulink url="http://www.winehq.org">WINE</ulink>, <ulink url="http://www.postgresql.org">PostgreSQL</ulink>, etc.
</para>
<note><para>
It has been reported by some users that &kapp; can be successfully used for C++ development. Nonetheless, &kapp; is mainly a tool for developing in pure C (either ANSI or K&amp;R style). Most C++ features will not be recognised by the cross-reference generator.
</para></note>
<para>
&kapp; is a part of an ongoing effort to expand the range of open source applications. It could not have been created without the previous work of many devoted developers. &kapp; is therefore freely distributed, along with its source code, for the benefit of the open source community. I hope it can be of use to others, and I would appreciate any help in the form of bug reports or improvement suggestions.
</para>
</sect1>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@ -0,0 +1,28 @@
<sect1 id="bookmarks">
<title>Bookmarks</title>
<para>
Bookmarks provide an easy way to navigate through a defined set of positions in the source code. Most editors support the concept of bookmarks as tags attached to lines in a source file. &kapp; can enhance the usablity of per-file markers by enabling users to access the bookmarks currently defined in all open files. &kapp; also saves and restores these bookmarks as part of its session-management services.
</para>
<para>
The <guilabel>Bookmarks</guilabel> dialogue is invoked by the <menuchoice><guimenu>Go</guimenu><guimenuitem>Global Bookmarks</guimenuitem></menuchoice> menu command. Once open, it displays the set bookmarks among all currently-open files. This includes the file path, the source line and the line's text (similar to other source views available in &kapp;).
</para>
<screenshot>
<screeninfo>The Bookmarks dialogue</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="bookmarks.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Bookmarks dialogue</phrase>
</textobject>
</mediaobject>
</screenshot>
<para>
Navigating to a defined bookmark can be done by either double-clicking an entry in the dialogue, or by choosing the <menuchoice><guimenuitem>View Source</guimenuitem></menuchoice> item from the context menu (available by right-clicking over a bookmark entry). Other choices presented by the context menu include <menuchoice><guimenuitem>Copy [FIELD]</guimenuitem></menuchoice> for copying the contents of the current field to the clipboard, <menuchoice><guimenuitem>Filter...</guimenuitem></menuchoice> for selecting entries based on some criteria, <menuchoice><guimenuitem>Show All</guimenuitem></menuchoice> for removing all filters and <menuchoice><guimenuitem>Remove Item</guimenuitem></menuchoice> for deleting the bookmark.
</para>
</sect1>

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

@ -0,0 +1,206 @@
<sect1 id="config-dlg">
<title>The Configuration Dialogue</title>
<para>
The configuration dialogue is the main tool for setting parameters required by &kapp;, or adjusting the user's preferences. The dialogue is displayed the first time &kapp; is run, and can be invoked later by using the <menuchoice><guimenu>Settings</guimenu><guimenuitem>Configure KScope...</guimenuitem></menuchoice> menu command.
</para>
<para>
The dialogue is composed of several pages, each of which handles a different set of parameters.
</para>
<sect2 id="config-progs">
<title>The Programmes Page</title>
<para>
&kapp; serves as a front-end to several console-based programmes: <application>Cscope</application>, <application>Ctags</application> and <application>Dot</application> (which is part of the <application>Graphviz</application> suite). Since &kapp; invokes these programmes directly, without using a shell, it cannot determine their paths. Therefore, it is required to inform &kapp; of the paths where the relevant executable files reside. Note that &kapp; needs the full path to each programme, along with the name of the executable.
</para>
<para>
Another parameter required by &kapp; is whether <application>Cscope</application> supports the <option>-v</option> command line option. This is a relatively new feature, added to <application>Cscope</application> in version 15.5. It allows &kapp; to display accurate progress information during time-consuming operations, such as building the cross-reference database, or running a long query. It is highly recommended that you upgrade <application>Cscope</application> to a version that supports the <option>-v</option> option, as the user experience of &kapp; is much improved with it. However, if you choose to use an older version of <application>Cscope</application>, make sure the check-box for using the <option>-v</option> option is cleared.
</para>
<para>
You can determine whether your version of <application>Cscope</application> supports this option by running <userinput><option>cscope</option> <option>-h</option></userinput>.
</para>
<para>
The easiest way to configure programme paths is by using the automated script provided with &kapp;. This script can be activated by clicking the <guibutton>Guess...</guibutton> button. Once invoked, the script looks for the required programmes (using the shell's <filename>which</filename> utility). The script also makes sure that the found executables adhere to the standards required by &kapp; (e.g., that <application>Ctags</application> is the one provided by <application>Exuberant-Ctags</application> and that <application>Dot</application> supports the <option>-Tplain</option> command-line option). &kapp; uses the results of the script to adjust the values in the dialogue's controls.
</para>
<note>
<para>The script will not override paths already set by the user. Instead, it will only verify the validity of these paths. For the script to determine paths automatically, the relevant text fields in the dialogue need to be cleared.</para>
</note>
<para>
<screenshot>
<screeninfo>The Programmes page</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="pref_progs.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Programmes page</phrase>
</textobject>
</mediaobject>
</screenshot>
<variablelist>
<varlistentry>
<term><guilabel>Cscope Path</guilabel></term>
<listitem><para>The full path of the Cscope executable. The name of this executable must be <filename>cscope</filename>.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Use verbose mode (-v)</guilabel></term>
<listitem><para>Instructs Cscope to produce verbose progress output, by appending <option>-v</option> to the command line.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Ctags Path</guilabel></term>
<listitem><para>The full path of the Ctags executable. The name of this executable must contain the string <filename>ctags</filename>.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Dot Path</guilabel></term>
<listitem><para>The full path of the Dot executable. The name of this executable must be <filename>dot</filename>.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Guess</guibutton></term>
<listitem><para><action>Runs a script which attempts to determine the previous values automatically.</action> This script should work in most cases, by may fail to correctly obtain some or all of the values.</para></listitem>
</varlistentry>
</variablelist>
If the file names on your system do not conform to the limitations described above, please create symbolic links to the executables.
</para>
</sect2>
<sect2 id="config-clrs">
<title>The Colours Page</title>
<para>
<screenshot>
<screeninfo>The Colours page</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="pref_clrs.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Colours page</phrase>
</textobject>
</mediaobject>
</screenshot>
The Colours page allows you to configure &kapp; to look the way you want it to, by changing the foreground and background colours of some of &kapp;'s GUI elements. The elements that can be modified are:
<itemizedlist>
<listitem><para>The project's file list (to the right of the editing area)</para></listitem>
<listitem><para>The editor's symbol (or tag) list (to the left of each editor window)</para></listitem>
<listitem><para>The query results window</para></listitem>
<listitem><para>The call graph's background and nodes</para></listitem>
</itemizedlist>
</para>
<para>
To change the colour of a GUI element, double-click over the element's entry in the list (or select this element and click <keycap>Enter</keycap>).
</para>
<note>
<para>The editor's own colours are determined by the settings of the embedded editor, and are not controlled by &kapp;.</para>
</note>
</sect2>
<sect2 id="config-fonts">
<title>The Fonts Page</title>
<para>
<screenshot>
<screeninfo>The Fonts page</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="pref_fonts.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Fonts page</phrase>
</textobject>
</mediaobject>
</screenshot>
The Fonts page allows you to determine the fonts used by any of &kapp;'s windows (see <link linkend="config-clrs">The Colours Page</link> section for a description of these windows.)
</para>
<para>
To change the colour of a GUI element, double-click over the element's entry in the list (or select this element and click <keycap>Enter</keycap>).
</para>
<note>
<para>As with the colour scheme, the fonts used by the embedded editor are not determined by &kapp;.</para>
</note>
</sect2>
<sect2 id="config-opts">
<title>The Options Page</title>
<para>
This page allows the user to configure certain parameters that affect the behaviour of &kapp;.
</para>
<para>
<screenshot>
<screeninfo>The Options page</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="pref_opts.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Options page</phrase>
</textobject>
</mediaobject>
</screenshot>
<variablelist>
<varlistentry>
<term><guilabel>External Editor</guilabel></term>
<listitem><para>Specifies a command line for invoking an external editor application. &kapp; will replace the escape sequence %F with the file path, and the sequence %L with the current line number.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Read-Only Mode</guilabel></term>
<listitem><para>If set, the embedded editor will be work in read-only mode, i.e., &kapp; will not allow any changes to the displayed source files (but you can still use the external editor).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Open Last Project on Start-Up</guilabel></term>
<listitem><para>Determines whether &kapp; should automatically attempt to load the last active project when started.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Automatic Tag Highlighting</guilabel></term>
<listitem><para>If set, &kapp; will highlight tags in the tag list based on the current position of the text cursor.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Brief Tab Captions for Query Pages</guilabel></term>
<listitem><para>This option allows some space to be saved by using shortcuts for the page titles in the query window.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Warn When a File is Modified Outside &kapp;</guilabel></term>
<listitem><para>If set, &kapp; will issue a warning whenever a file is changed on the hard drive, while it is open for editing in &kapp;. This option will only work in conjunction with the Kate text editor).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Automatically Sort Files in the File List</guilabel></term>
<listitem><para>By default, &kapp; will sort the files in the project's file list whenever a project is loaded. However, such behaviour may not be suitable for large projects on older machines, causing &kapp; to hang for long periods when loading such projects. Uncheck this option to avoid automatic sorting.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>System Profile</guilabel></term>
<listitem><para>Allows the choice between a fast and a slow system configuration. The fast profile will take certain actions automatically which are not appropriate for a slower system (for example, automatic database rebuilds and auto-completion are enabled by default for fast systems and disabled for slow systems). Note that the terms "fast" and "slow" do not necessarily refer to the particular machine which runs &kapp;, but rather to the complete environment (e.g., a fast machine may still be using a relatively slow file server).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Editor Popup Menu</guilabel></term>
<listitem><para>Provides two choices for the embedded editor's context menu:
<itemizedlist>
<listitem><para>Embedded: A menu with Cscope actions is included as a sub-menu of the editor's own context menu.</para></listitem>
<listitem><para>&kapp; Only: Only Cscope actions are available through the context menu.</para></listitem>
</itemizedlist>
The second choice provides quicker access to Cscope commands, but the editor's menu is discarded.
</para></listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
</sect1>

@ -0,0 +1,138 @@
<sect1 id="editing">
<title>Editing Source Files</title>
<sect2 id="editor">
<title>The Editor</title>
<para>
&kapp; does not provide its own editor. Instead, it utilises KDE's KTextEditor infrastructure to embed the system's default editor. This means that any editor that supports the KTextEditor interface (e.g., &kate;, <application>KVim</application>) can be used with &kapp;. The editor is defined in KDE's control centre.
</para>
<para>
In any matter related to operating or configuring the editor, please refer to the manual of the editor itself.
</para>
</sect2>
<sect2 id="open-file">
<title>Opening Files for Editing</title>
<para>
Files are usually opened for editing as part of a project. However, &kapp; enables the user to edit an occasional file that is not related to the project, through the <menuchoice><guimenu>File</guimenu><guimenuitem>Open...</guimenuitem></menuchoice> menu command. Note, however, that query results on files outside a project are meaningless.
</para>
<para>
Once a project has been opened, the list of all project files appears in the file list, to the right of the editing area. Each file entry in the list shows the file's type, its name, and its full path. Files are opened by either double-clicking their entry in the list, or by selecting the entry, and hitting the <keycap>Enter</keycap> key. The edit-box above the list can be used to quickly search for a file. Typing in this box selects the first list entry whose file name begins with the entered text.
</para>
<para>
Files can also be opened through the file tree, which shares its location with the project's file list (using a tabbed-window.) The file tree displays all files in the system, starting with a specific root directory. A root directory for the file tree is set on a per-project basis by using the <guibutton>Set Root...</guibutton> button. The file tree also sports a <guibutton>Find File...</guibutton> button for launching the file search <application>Cscope</application> query.
</para>
<note>
<para>
To decrease the loading time of projects, files and directories are only added to the tree when their parent directory is expanded. Therefore directories will not be marked as expandable by default, even if they are not empty.
</para>
</note>
<para>
For each file opened, &kapp; creates a separate editor window, inside the editing area. Each editor is associated with a tab, displaying the name of the edited file. Thus &kapp; provides a convenient multi-editor environment. You can switch between open files by selecting their respective tabs, or by using the <guimenu>Window</guimenu> menu.
</para>
<para>
To work on a new file, the user first needs to create it using the <menuchoice><guimenu>File</guimenu><guimenuitem>New...</guimenuitem></menuchoice> menu command. This opens an empty editor, that is not associated with a file name or path. Upon saving the work in this new editor, &kapp; will prompt the user for a file name and directory. Note that this does not add the file to the project. The user still needs to invoke the <guilabel>Project Files</guilabel> dialogue and add the new file to an open project.
</para>
</sect2>
<sect2 id="file-tags">
<title>File Tags</title>
<para>
In addition to being a front-end to <application>Cscope</application>, &kapp; also uses <application>Ctags</application> to display a list of symbols defined in the current file. Each editor window is added a list of these symbols to its left. This list displays the name of a symbol, its type (as a graphic shape), and the line where it is defined. Double-clicking a symbol, or selecting it and hitting the <keycap>Enter</keycap> key, sets the cursor to the beginning of this symbol's definition line. The list of symbols is refreshed whenever a file is saved.
</para>
<para>
The edit-box above the list of symbols can be used for quick symbol look-ups. Entering text in this box selects the first symbol whose name begins with this text.
</para>
<para>
By default, tags are sorted by to their name in ascending order. Click on a column header to sort the tags according to that column. A triangle to the side of a column name indicates this is the sorting column, and shows the sorting order (ascending or descending.) Once a sorting order is chosen, it becomes the default, and is used for all newly created lists (though not for currently open, unmodified, editor windows.)
</para>
</sect2>
<sect2 id="files-other">
<title>Other File Options</title>
<para>
&kapp;'s <guimenu>File</guimenu> menu includes further options, such as saving, printing and closing files. In addition, specific editors can offer extended features under the <guimenu>Tools</guimenu> menu (e.g., syntax highlighting, indentation, etc.)
</para>
</sect2>
<sect2 id="symbol-completion">
<title>Symbol Completion</title>
<para>
Symbol completion is a convenient feature that enables the user to enter previously declared symbols with fewer key strokes. Since the cross-reference database keeps record of all globally declared symbols, it can be queried for a complete symbol name based on a given prefix.
There are two types of symbol completion: manual and automatic. Manual symbol completion is always available, and can be invoked by the <menuchoice><guimenu>Edit</guimenu><guimenuitem>Complete Symbol</guimenuitem></menuchoice> menu command (or, more conveniently, by pressing <keycombo><keycap>Ctrl</keycap><keycap>Space</keycap></keycombo>). Once a completion request has been issued, &kapp; uses the characters immediately preceding the current cursor position as a prefix, and queries the database for possible completions. These completions are displayed in a list box, which can be browsed using the arrow keys. Pressing <keycap>Enter</keycap> replaces the prefix with the selected symbol. The <keycap>Esc</keycap> key hides the list without completing the symbol.
</para>
<sect3 id="auto-symbol-completion">
<title>Automatic Symbol Completion</title>
<para>
In addition to manual symbol completion, &kapp; can also provide automatic completion based on changes made by the user to the edited source code. Specifically, &kapp; tracks changes to the edited file, and if certain criteria are met, initiates a symbol completion query to the cross-reference database. Once a completion list is displayed, symbol completion behaves in the same way as in the manual case.
</para>
<para>
Automatic symbol completion is configured on a per-project basis. This feature is enabled or disabled via the <guilabel>Use Symbol Auto-Completion</guilabel> check-box in the <guilabel>New Project</guilabel> dialogue (this option can also be changed after a project has been created by invoking the <guilabel>Project Properties</guilabel> dialogue).
</para>
<note>
<para>
For performance reasons, it is highly recommended that automatic symbol completion will be used in conjunction with the inverted-index option.
</para>
</note>
<para>
As mentioned above, &kapp; uses several parameters to decide whether automatic symbol completion should be initiated. These parameters can be configured by clicking on the <guibutton>Options...</guibutton> button in the <guilabel>New Project</guilabel> dialogue (or, later, in the <guilabel>Project Properties</guilabel> dialogue). Clicking this button invokes the <guilabel>Auto-Completion Properties</guilabel> dialogue.
<screenshot>
<screeninfo>The auto-completion properties dialogue</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="autocomp_dlg.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The auto-completion properties dialogue</phrase>
</textobject>
</mediaobject>
</screenshot>
<variablelist>
<varlistentry>
<term><guilabel>Minimum Characters</guilabel></term>
<listitem><para>The minimal length of a symbol for which completion is provided.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Delay (ms)</guibutton></term>
<listitem><para>Specifies a time interval that should elapse after the last change to the edited text and before the symbol completion query is executed.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Maximum Entries</guilabel></term>
<listitem><para>The symbol completion list will display at most this number of possible completions. If the number of matched symbols in the database is greater, a message will be displayed (and no symbols will be available).</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>
The main purpose of these parameters is to reduce the load on the system caused by frequent queries to the database. The default values have been tested in various scenarios, and are usually adequate.
</para>
</sect3>
</sect2>
</sect1>

@ -0,0 +1,174 @@
<?xml version="1.0" ?>
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.1.2-Based Variant V1.0//EN" "dtd/kdex.dtd" [
<!ENTITY kscope '<application>KScope</application>'>
<!ENTITY kapp "&kscope;"><!-- replace kscope here -->
<!ENTITY about SYSTEM "about.docbook">
<!ENTITY quick-start SYSTEM "quick_start.docbook">
<!ENTITY main-window SYSTEM "main_window.docbook">
<!ENTITY projects SYSTEM "projects.docbook">
<!ENTITY editing SYSTEM "editing.docbook">
<!ENTITY query-system SYSTEM "query_system.docbook">
<!ENTITY position-history SYSTEM "pos_history.docbook">
<!ENTITY bookmarks SYSTEM "bookmarks.docbook">
<!ENTITY config-dlg SYSTEM "config_dlg.docbook">
<!ENTITY main-menu SYSTEM "main_menu.docbook">
<!ENTITY % addindex "IGNORE">
<!ENTITY % English "INCLUDE"><!-- change language only here -->
<!-- Do not define any other entities; instead, use the entities
from kde-genent.entities and $LANG/user.entities. -->
]>
<!-- The language must NOT be changed here. -->
<book lang="&language;">
<!-- This header contains all of the meta-information for the document such
as Authors, publish date, the abstract, and Keywords -->
<bookinfo>
<title>The &kapp; Handbook</title>
<authorgroup>
<author>
<firstname>Elad</firstname>
<othername></othername>
<surname>Lahav</surname>
<affiliation>
<address><email>elad_lahav@users.sourceforge.net</email></address>
</affiliation>
</author>
</authorgroup>
<!-- TRANS:ROLES_OF_TRANSLATORS -->
<copyright>
<year>2003-2007</year>
<holder>Elad Lahav</holder>
</copyright>
<!-- Translators: put here the copyright notice of the translation -->
<!-- Put here the FDL notice. Read the explanation in fdl-notice.docbook
and in the FDL itself on how to use it. -->
<legalnotice>&FDLNotice;</legalnotice>
<!-- Date and version information of the documentation
Don't forget to include this last date and this last revision number, we
need them for translation coordination !
Please respect the format of the date (DD/MM/YYYY) and of the version
(V.MM.LL), it could be used by automation scripts.
Do NOT change these in the translation. -->
<date>08/07/2007</date>
<releaseinfo>1.6.0</releaseinfo>
<!-- Abstract about this handbook -->
<abstract>
<para>
&kapp; is a source-editing environment for KDE, based on <application>Cscope</application>.
</para>
</abstract>
<!-- This is a set of Keywords for indexing by search engines.
Please at least include KDE, the KDE package it is in, the name
of your application, and a few relevant keywords. -->
<keywordset>
<keyword>KDE</keyword>
<keyword>KScope</keyword>
<keyword>Cscope</keyword>
<keyword>source</keyword>
<keyword>editor</keyword>
<keyword>browser</keyword>
</keywordset>
</bookinfo>
<!-- The contents of the documentation begin here. Label
each chapter so with the id attribute. This is necessary for two reasons: it
allows you to easily reference the chapter from other chapters of your
document, and if there is no ID, the name of the generated HTML files will vary
from time to time making it hard to manage for maintainers and for the CVS
system. Any chapter labelled (OPTIONAL) may be left out at the author's
discretion. Other chapters should not be left out in order to maintain a
consistent documentation style across all KDE apps. -->
<chapter id="introduction">
<title>Introduction</title>
&about;
&quick-start;
</chapter>
<chapter id="using-kscope">
<title>Using &kapp;</title>
&main-window;
&projects;
&editing;
&query-system;
&position-history;
&bookmarks;
</chapter>
<chapter id="configuration">
<title>Configuring &kapp;</title>
&config-dlg;
</chapter>
<chapter id="commands">
<title>Command Reference</title>
&main-menu;
</chapter>
<chapter id="credits">
<!-- Include credits for the programmers, documentation writers, and
contributors here. The license for your software should then be included below
the credits with a reference to the appropriate license file included in the KDE
distribution. -->
<title>Credits and License</title>
<para>
&kapp;
</para>
<para>
Programme copyright 2003-2007 Elad Lahav <email>elad_lahav@users.sourceforge.net</email>
</para>
<para>
I would like to thank:
<itemizedlist>
<listitem><para>The <ulink url="http://www.kde.org">KDE</ulink> team</para></listitem>
<listitem><para>The <ulink url="http://www.kdevelop.org">KDevelop</ulink> team</para></listitem>
<listitem><para>Hans-Bernhard Broker, who maintains <ulink url="http://cscope.sourceforge.net">Cscope</ulink></para></listitem>
</itemizedlist>
</para>
<para>
Documentation copyright 2007-2006 Elad Lahav <email>elad_lahav@users.sourceforge.net</email>
</para>
<!-- TRANS:CREDIT_FOR_TRANSLATORS -->
&underFDL; <!-- FDL: do not remove. Commercial development should -->
<!-- replace this with their copyright and either remove it or re-set this.-->
<!-- Determine which license your application is licensed under,
and delete all the remaining licenses below:
(NOTE: All documentation are licensed under the FDL,
regardless of what license the application uses) -->
&underBSDLicense; <!-- BSD License -->
</chapter>
</book>

@ -0,0 +1,465 @@
<sect1 id="mainmenu">
<title>&kapp;'s Main Menu</title>
<para>
This section describes the menu entries declared by &kapp; only. Additional entries may be added to the main menu by the embedded editor (e.g., <guimenu>Edit</guimenu>, <guimenu>View</guimenu> or <guimenu>Tools</guimenu>.) Please refer to the editor's manual for a description of the commands under these sub-menus.
</para>
<sect2>
<title>The File Menu</title>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>N</keycap></keycombo>
</shortcut>
<guimenu>File</guimenu>
<guimenuitem>New</guimenuitem>
</menuchoice></term>
<listitem><para><action>Opens an empty editor window.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>O</keycap></keycombo>
</shortcut>
<guimenu>File</guimenu>
<guimenuitem>Open...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Opens a file for editing.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>W</keycap></keycombo>
</shortcut>
<guimenu>File</guimenu>
<guimenuitem>Close</guimenuitem>
</menuchoice></term>
<listitem><para><action>Closes the active editor window</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>Q</keycap></keycombo>
</shortcut>
<guimenu>File</guimenu>
<guimenuitem>Quit</guimenuitem>
</menuchoice></term>
<listitem><para><action>Quits</action> &kapp;</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>
Other file operations such as <guimenuitem>Save</guimenuitem> and <guimenuitem>Print</guimenuitem> are not integral &kapp; actions, but are rather defined by the type of editor used.
</para>
</sect2>
<sect2>
<title>The Edit Menu</title>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>E</keycap></keycombo>
</shortcut>
<guimenu>Edit</guimenu>
<guimenuitem>Edit in External Editor</guimenuitem>
</menuchoice></term>
<listitem><para><action>Launches an editor application for the current file and line number</action> </para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>Shift</keycap><keycap>T</keycap></keycombo>
</shortcut>
<guimenu>Edit</guimenu>
<guimenuitem>Go To Tag</guimenuitem>
</menuchoice></term>
<listitem><para><action>Moves the cursor to the tag list</action>, used for browsing through the file's tags</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>Space</keycap></keycombo>
</shortcut>
<guimenu>Edit</guimenu>
<guimenuitem>Complete Symbol</guimenuitem>
</menuchoice></term>
<listitem><para><action>Generates a list of possible symbol completions for the text to the left of the cursor.</action> Note that this option is available even if automatic completion is disabled.</para></listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
<sect2>
<title>The View Menu</title>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>/</keycap></keycombo>
</shortcut>
<guimenu>View</guimenu>
<guimenuitem>Toggle File List</guimenuitem>
</menuchoice></term>
<listitem><para><action>Shows or hides the project's file list window.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>.</keycap></keycombo>
</shortcut>
<guimenu>View</guimenu>
<guimenuitem>Toggle Query Window</guimenuitem>
</menuchoice></term>
<listitem><para><action>Shows or hides the query window.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>.</keycap></keycombo>
</shortcut>
<guimenu>View</guimenu>
<guimenuitem>Toggle Tag List</guimenuitem>
</menuchoice></term>
<listitem><para><action>Shows or hides the tag lists attached to the editor windows.</action></para></listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
<sect2>
<title>The Project Menu</title>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<guimenu>Project</guimenu>
<guimenuitem>New...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays the New Project dialogue box.</action>Use this dialogue to create a new project.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Project</guimenu>
<guimenuitem>Open...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays the Open Project dialogue box</action>, which lets you search for an existing project to open.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Project</guimenu>
<guimenuitem>Open Cscope.out...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Prompts for an existing Cscope.out</action>, which can be opened as a temporary project.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Project</guimenu>
<guimenuitem>Add/Remove Files...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays the Project Files dialogue box</action>, which allows you to add source files to the current project, or remove files from it.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Project</guimenu>
<guimenuitem>Properties...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays the Project Properties dialogue box.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>M</keycap></keycombo>
</shortcut>
<guimenu>Project</guimenu>
<guimenuitem>Make Project...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays the Build dialogue.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>Shift</keycap><keycap>M</keycap></keycombo>
</shortcut>
<guimenu>Project</guimenu>
<guimenuitem>Remake Project</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays the Build dialogue and executes the last build command.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Project</guimenu>
<guimenuitem>Close</guimenuitem>
</menuchoice></term>
<listitem><para><action>Closes the active project</action>, along with all open editor windows.</para></listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
<sect2>
<title>The Cscope Menu</title>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<guimenu>Cscope</guimenu>
<guimenuitem>Rebuild Database</guimenuitem>
</menuchoice></term>
<listitem><para><action>Updates the cross-reference database for the current project</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>0</keycap></keycombo>
</shortcut>
<guimenu>Cscope</guimenu>
<guimenuitem>References...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Finds all references to a given symbol</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>1</keycap></keycombo>
</shortcut>
<guimenu>Cscope</guimenu>
<guimenuitem>Definition...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Finds the global definition of a symbol</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>2</keycap></keycombo>
</shortcut>
<guimenu>Cscope</guimenu>
<guimenuitem>Called Functions...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Finds all functions called by a given function</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>3</keycap></keycombo>
</shortcut>
<guimenu>Cscope</guimenu>
<guimenuitem>Calling Functions...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Finds all functions calling a given function</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>4</keycap></keycombo>
</shortcut>
<guimenu>Cscope</guimenu>
<guimenuitem>Find Text...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Finds all occurrences of a text string</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>5</keycap></keycombo>
</shortcut>
<guimenu>Cscope</guimenu>
<guimenuitem>Find EGrep Pattern...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Finds all text strings matching a regular expression</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>8</keycap></keycombo>
</shortcut>
<guimenu>Cscope</guimenu>
<guimenuitem>Find Including Files...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Finds all files #including a given file</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>]</keycap></keycombo>
</shortcut>
<guimenu>Cscope</guimenu>
<guimenuitem>Quick Definition</guimenuitem>
</menuchoice></term>
<listitem><para><action>Finds the global definition of the symbol currently under the cursor.</action> The symbol dialogue appears only if a symbol cannot be determined automatically.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>\</keycap></keycombo>
</shortcut>
<guimenu>Cscope</guimenu>
<guimenuitem>Call Graph...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays a call-graph and/or a call-tree for a given function</action></para></listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
<sect2>
<title>The Go Menu</title>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Alt</keycap><keycap>Up Arrow</keycap></keycombo>
</shortcut>
<guimenu>Go</guimenu>
<guimenuitem>Previous Result</guimenuitem>
</menuchoice></term>
<listitem><para><action>Selects the previous result in the current query window.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Alt</keycap><keycap>Down Arrow</keycap></keycombo>
</shortcut>
<guimenu>Go</guimenu>
<guimenuitem>Next Result</guimenuitem>
</menuchoice></term>
<listitem><para><action>Selects the next result in the current query window.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Alt</keycap><keycap>Left Arrow</keycap></keycombo>
</shortcut>
<guimenu>Go</guimenu>
<guimenuitem>Previous Position</guimenuitem>
</menuchoice></term>
<listitem><para><action>Jumps to the previous stored position in the active history list.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Alt</keycap><keycap>Right Arrow</keycap></keycombo>
</shortcut>
<guimenu>Go</guimenu>
<guimenuitem>Next Position</guimenuitem>
</menuchoice></term>
<listitem><para><action>Jumps to the next stored position in the active history list.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>H</keycap></keycombo>
</shortcut>
<guimenu>Go</guimenu>
<guimenuitem>Position History...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Selects the active position history page in the query window.</action> If the query window is hidden, it becomes visible. </para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Ctrl</keycap><keycap>Shift</keycap><keycap>G</keycap></keycombo>
</shortcut>
<guimenu>Go</guimenu>
<guimenuitem>Global Bookmarks...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays the Bookmarks dialogue.</action></para></listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
<sect2>
<title>The Window Menu</title>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<guimenu>Window</guimenu>
<guimenuitem>Close All</guimenuitem>
</menuchoice></term>
<listitem><para><action>Closes all open editor windows</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Alt</keycap><keycap>Shift</keycap><keycap>Left Arrow</keycap></keycombo>
</shortcut>
<guimenu>Window</guimenu>
<guimenuitem>Go Left</guimenuitem>
</menuchoice></term>
<listitem><para><action>Selects the editor window to the left of the current one.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<shortcut>
<keycombo><keycap>Alt</keycap><keycap>Shift</keycap><keycap>Right Arrow</keycap></keycombo>
</shortcut>
<guimenu>Window</guimenu>
<guimenuitem>Go Right</guimenuitem>
</menuchoice></term>
<listitem><para><action>Selects the editor window to the right of the current one.</action></para></listitem>
</varlistentry>
</variablelist>
</para>
<para>
This menu displays the full path of each file edited in an open window. Clicking a
file name will make its editor window active.
</para>
</sect2>
<sect2>
<title>The Settings Menu</title>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<guimenu>Settings</guimenu>
<guisubmenu>Toolbars</guisubmenu>
</menuchoice></term>
<listitem><para><action>Toggles the different toolbars.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Settings</guimenu>
<guimenuitem>Configure Shortcuts...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Allows the user to assign different shortcuts to &kapp; commands.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Settings</guimenu>
<guimenuitem>Configure KScope...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays the &kapp; configuration dialogue</action></para></listitem>
</varlistentry>
</variablelist>
</para>
<para>
A menu item to configure the embedded editor may also appear under this menu.
</para>
</sect2>
</sect1>

@ -0,0 +1,24 @@
<sect1 id="main-window">
<title>The Main Window</title>
<para>
&kapp;'s main window is divided into three. The central area is dedicated to source editing, and holds a set of editor windows, one for each source file being viewed or edited. This area is greyed-out if no files are open for editing. The window to the right is the file browser, comprised of a list of project files, and a tree-like view of the file system. The project file list will only display files after a project has been created and source files have been added to it. The bottom area contains the query windows, which hold the results of <application>Cscope</application> queries, and the history pages that display locations in the source code visited by the user.
</para>
<screenshot>
<screeninfo>The Main Window</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="main_window.png" format="PNG" />
</imageobject>
<textobject>
<phrase>&kapp;'s main window</phrase>
</textobject>
</mediaobject>
</screenshot>
<para>
The size of each of these sub-windows can be changed to meet the user's personal preferences. This is done by dragging the lines that separate one area from the other. The new sizes will be kept and used on the next sessions as well.
</para>
<para>
The file browser and the query window can be hidden in order to free up desktop space (especially on low resolution displays). Hiding and showing these windows is done through the <guimenu>View</guimenu> menu. A window can also be hidden by clicking on its close button, at the upper right corner. As with window sizes, the visibility status will be saved when &kapp; is closed.
</para>
</sect1>

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

@ -0,0 +1,101 @@
<sect1 id="position-history">
<title>Position History</title>
<sect2 id="pos-hist-intro">
<title>Introduction</title>
<para>
In its capacity as a source code browser, &kapp; allows the user to quickly browse through different lines in the code base. We refer to a combination of a source file and a line number as a "position" in the project. While browsing the code, it is often required to go back to a position visited in the past, e.g., to return to the caller after visiting the callee. To achieve this task, &kapp; provides a sophisticated position history mechanism, which not only allows the user to go back and forth between visited locations, but also to save and restore snapshots of "tours" through the code, as well as other manipulations of the position history. For the sake of both consistency and ease of use, recorded position history is viewed and handled in a way similar to the query results system.
</para>
<note>
<para>
In the context of this section, a "jump" is defined as the action taken by &kapp; after a query result record is selected for viewing (either by the user from a query page or a call-tree window, or automatically).
</para>
</note>
<para>
Position history records appear in pages incorporated into the Query Results window. These pages can be immediately distinguished from query results by their tab labels, which always read "History X" (where X is a unique number that identifies the page). Other than that the two types of pages look very much the same: a history page is composed of a list of records, each comprised of the following fields:
<itemizedlist>
<listitem><para>File</para></listitem>
<listitem><para>Line</para></listitem>
<listitem><para>Text</para></listitem>
</itemizedlist>
</para>
<para>
Note that the "Function" field is not provided for position history records.
</para>
<para>
A history page behaves like a stack: entries are always added at the top of the list, and represent the most recently visited positions. The user can then go backwards in time, by moving the lower records, or forward, by moving to upper records. If the current record in the list is not the top one, all records above it are removed before new records are added at the top (the future history is thus "forgotten").
</para>
<para>
At any given moment, at most one history page is considered as "active". This is the page to which history position records are added as the user browses through the code, and to which position navigation commands apply. See <link linkend="pos-hist-multi">Using Multiple Histories</link> for a detailed description of the active page concept.
</para>
<para>
A newly created project contains no position history pages. An initial page is created and set as active automatically when the first jump is made to a location in the code.
</para>
<para>
Each jump may add up to two entries to the active history list:
<orderedlist>
<listitem><para>The current position of the cursor (before the cursor jumps to the requested position), and</para></listitem>
<listitem><para>The new position of the cursor.</para></listitem>
</orderedlist>
Duplicates never occur in the list. If the location of the cursor is the same as the location that appears at the top of the history list, only the new position of the cursor will be added.
</para>
</sect2>
<sect2 id="pos-hist-nav">
<title>Navigation</title>
<para>
The key feature of the position history mechanism is the ability to navigate through the recorded locations in the source code. There are two ways to navigate through a history list: moving back and forth through the list, and jumping directly to a specific position.
</para>
<para>
To go back to the last position visited, select the <menuchoice><guimenu>Go</guimenu><guimenuitem>Previous Position</guimenuitem></menuchoice> menu item. This command selects the item immediately below the current one in the active history list (and moves the cursor to that position). Similarly, the menu command <menuchoice><guimenu>Go</guimenu><guimenuitem>Next Position</guimenuitem></menuchoice> selects the position record immediately above the current one in the active history page, and moves the editing cursor to the appropriate location.
</para>
<para>
In addition to these commands, any position recorded in a history list can be accessed directly, by selecting the relevant item in the list (either by double-clicking the item, or by highlighting it and pressing the <keycap>Enter</keycap> key. This action can be applied to any history list, and not just to the active one.
</para>
<note>
<para>
Selecting a history record from a non-active list will add the selected item to the top of the active list, similar to a jump from a query result page.
</para>
</note>
</sect2>
<sect2 id="pos-hist-multi">
<title>Using Multiple Histories</title>
<para>
The position history is a dynamic object, which changes as the user navigates through the code. In some cases, however, it is convenient to create a snapshot of a tour through the code, and keep it for later reference. &kapp; provides this feature through the availability of multiple history pages.
</para>
<para>
As mentioned earlier, a history page is created automatically for a project when the first jump through the code is made. This page is considered as the active history page, which means that locations are added to this page, and that all navigational commands apply to the list contained in it.
</para>
<para>
The user can decide to freeze the contents of the history recorded by the current page. This is done by locking the page, in a way similar to locking query results (see <link linkend="query-window">The Query Window</link>). Once the page is locked, its contents remain the same, even if jumps are made to other locations in the code. To record any successive jumps, &kapp; creates a new history page, which becomes the active one. A locked history page can also be activated by unlocking it. However, there can only be one unlocked history page at any given time (the active one), which means that unlocking one history page locks the previously unlocked one.
</para>
<para>
Navigational commands (<menuchoice><guimenu>Go</guimenu><guimenuitem>Next Position</guimenuitem></menuchoice> and <menuchoice><guimenu>Go</guimenu><guimenuitem>Previous Position</guimenuitem></menuchoice>) always apply to the active history page. This is usually the unlocked history page, but may also be a locked one. This happens after the active page is locked, and before a new page is created due to a jump in the code. Other locked pages can still be used by manually selecting location records from these pages. Such a selection will move the editing cursor to the appropriate location, and hence add an entry in the active history page.
</para>
<para>
As with query pages, locked history pages are saved when a project is closed, and restored when it is opened.
</para>
</sect2>
</sect1>

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

@ -0,0 +1,394 @@
<sect1 id="projects">
<title>Working with Projects</title>
<para>
Before any significant work can be done with &kapp;, the user needs to define a project. A &kapp; project is a set of source files, which <application>Cscope</application> uses to create its cross-reference database. Unlike many other project-based environments, &kapp; is not intrusive: it only uses three files to define the project (with additional two files if the inverted index option is used). These files reside on a user-specified folder that does not have to be related to the location of the source files. Thus, &kapp; does not require any source files to be moved, and does not affect the structure of the source tree.
</para>
<para>
The files used by a &kapp; project are:
<variablelist>
<varlistentry>
<term><filename>cscope.proj</filename></term>
<listitem><para>The project's configuration file</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>cscope.files</filename></term>
<listitem><para>A list of all source files included in the project</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>cscope.out</filename></term>
<listitem><para><application>Cscope</application>'s cross-reference database</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>cscope.in.out</filename></term>
<listitem><para>An inverted index file (optional)</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>cscope.po.out</filename></term>
<listitem><para>An inverted index file (optional)</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>
The only limitation imposed by &kapp; is that these files have to reside in the same directory, referred to as the project's directory. The project's directory has the same name as the project (which means that project names should conform to the file-system conventions), and can be placed by the user under any directory. Normally, a user will create a <filename>projects</filename> sub-directory under his or her home directory, and create all projects there. However, this is only a convention, and, as explained above, the user can choose any other method he or she prefers. Furthermore, the project's directory can later be moved to another parent directory, without any risk of data loss.
</para>
<sect2 id="project-create">
<title>Creating a New Project</title>
<para>
The first step in working with projects is to create a new one. This is done by choosing the <menuchoice><guimenu>Projects</guimenu><guimenuitem>New...</guimenuitem></menuchoice> command from the main menu. Issuing this command opens the <guilabel>New Project</guilabel> dialogue. The dialogue consists of three pages: <guilabel>Details</guilabel>, <guilabel>File Types</guilabel> and <guilabel>Options</guilabel>.
</para>
<para>
Note that this dialogue is intended for creating an empty project only, and has nothing to do with the actual source files of the project. This task is left to the <guilabel>Project Files</guilabel> dialogue.
</para>
<sect3>
<title>Details</title>
<screenshot>
<screeninfo>The Project Details page</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="project_details.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Project Details page</phrase>
</textobject>
</mediaobject>
</screenshot>
<variablelist>
<varlistentry>
<term><guilabel>Name</guilabel></term>
<listitem><para>The name of the project. Note that this name will be given to the project's directory, and should therefore comply with the file-system convention for directory names (e.g., no spaces).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Path</guilabel></term>
<listitem><para>The full path of the directory under which the new project will be created. &kapp; will create a new directory under this one, and name it after the project. Thus this path does not need to point directly to the project's directory, but rather to the project's parent directory. For example, if a user wants to create a project called "my_project" under his local <filename>projects</filename> directory, the project's name should be set to "my_project" and the path to <filename>/home/my_username/projects</filename>. This will set the project's directory to <filename>/home/my_username/projects/my_project</filename>.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Source Root (Optional)</guilabel></term>
<listitem><para>The top-level directory that contains the source files to be included in the project. This path only serves as a hint to &kapp;, as files may later be added from different directories as well By default, this value is set to the root directory.</para></listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3>
<title>File Types</title>
<screenshot>
<screeninfo>The File Types page</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="project_types.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The File Types page</phrase>
</textobject>
</mediaobject>
</screenshot>
<variablelist>
<varlistentry>
<term><guilabel>This Project</guilabel></term>
<listitem><para>A list of file name patterns that are used to define the type of source files to be included in the project. By default, C source files (<filename>.c</filename>) and C header files (<filename>.h</filename>) are included, but other types (including Lex's <filename>.l</filename> files and Yacc's <filename>.y</filename> files) can be added.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Available Types</guilabel></term>
<listitem><para>A list of standard file types that can be included in a project. To add a type, highlight its entry in the list, and click the <guibutton>Add</guibutton> button. Custom types can also be added, by typing in shell-style patterns in the edit-box at the top of the list.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Add</guibutton></term>
<listitem><para><action>Adds the currently selected file type to the project.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Remove</guibutton></term>
<listitem><para><action>Removes the currently selected file types from the project.</action> The file type is added to the list of available types.</para></listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3>
<title>Options</title>
<screenshot>
<screeninfo>The Project Options page</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="project_opts.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Project Options page</phrase>
</textobject>
</mediaobject>
</screenshot>
<variablelist>
<varlistentry>
<term><guilabel>Kernel project</guilabel></term>
<listitem><para>Mark this check-box if the project is designated to be a kernel-style project. For kernel projects, <application>Cscope</application> ignores the system's include files when building the cross-reference database (i.e., <symbol>printf</symbol> will not be found in <filename>/usr/include/stdio.h</filename>).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Build inverted index</guilabel></term>
<listitem><para><application>Cscope</application> can build an inverted index for the project to speed up queries (though at the expense of more time spent on building and refreshing the database).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Do not compress the database</guilabel></term>
<listitem><para>Builds cross-reference database without compression. This will create a larger, but human-readable database.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Slower, but more accurate, function definition detection</guilabel></term>
<listitem><para>Applies a huristic that can overcome <application>Cscope</application>'s inability to detect function declarations with function pointers as parameters. Requires a patch to <application>Cscope</application>.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Refresh database automatically</guilabel></term>
<listitem><para>&kapp; can rebuild the cross-reference database automatically, a process which is triggered when a source file is saved. If this option is selected, the user needs to specify the time (in seconds) that should elapse after each file save operation and before the database is rebuilt.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Use symbol auto-completion</guilabel></term>
<listitem><para>Enables automatic "as-you-type" symbol completion. Note that manual symbol completion is always available, regardless of whether this option is selected.</para>
<note><para>If you choose to enable this option, it is recommended that you also select the inverted index option.</para></note></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Options...</guibutton></term>
<listitem><para><action>Displays the symbol auto-completion configuration dialogue.</action> This button is only enabled if the symbol auto-completion is selected (see <link linkend="auto-symbol-completion">Automatic Symbol Completion</link> for a description of this dialogue).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Override default tab width (Kate only)</guilabel></term>
<listitem><para>Use a per-project tab-width (overriding the editor's settings). Helps when browsing code bases that use different styles than the user's preferred one.</para></listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3>
<title>Common Buttons</title>
<variablelist>
<varlistentry>
<term><guibutton>OK</guibutton></term>
<listitem><para><action>Accepts the values entered in the dialogue, and creates a new project.</action> If any mandatory values were omitted, or not entered correctly, the user is prompted.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Cancel</guibutton></term>
<listitem><para><action>Closes the dialogue without creating a new project.</action></para></listitem>
</varlistentry>
</variablelist>
</sect3>
</sect2>
<sect2 id="project-files">
<title>Adding and Removing Project Files</title>
<para>
The project's list of source files is maintained by the <guilabel>Project Files</guilabel> dialogue. This dialogue allows the user to add source files to a project, or remove files currently included in it. The dialogue is invoked automatically after a new project has been created, or manually by selecting the <menuchoice><guimenu>Project</guimenu><guimenuitem>Add/Remove Files...</guimenuitem></menuchoice> command from the main menu.
</para>
<screenshot>
<screeninfo>The Project Files dialogue</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="project_files.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Project Files dialogue</phrase>
</textobject>
</mediaobject>
</screenshot>
<variablelist>
<varlistentry>
<term><guilabel>File Path</guilabel></term>
<listitem><para>Displays a list of all source files included in the project. Note that when adding and removing files, the project itself is not modified until the <guibutton>OK</guibutton> button is clicked.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Filter</guibutton></term>
<listitem><para>Hides all files whose path names do not include the text entered in the edit-box to the left of the button. This can simplify the task of finding files in the project. The filter text can be any simplified regular expression (as given to file commands in a shell).</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Show All</guibutton></term>
<listitem><para>Reveals any files formerly hidden with the <guibutton>Filter</guibutton> button.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Add</guilabel></term>
<listitem><para>All buttons in this group add files to the current project.</para>
<variablelist>
<varlistentry>
<term><guibutton>Files...</guibutton></term>
<listitem><para><action>Adds user-selected files to the current project.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Directory...</guibutton></term>
<listitem><para><action>Adds all source files in a directory to the current project.</action> Source files are scanned according to the file-types associated with the project. Note that sub-directories are not scanned for files.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Tree...</guibutton></term>
<listitem><para><action>Adds all source files in a selected directory and its sub-directories to the current project.</action> Source files are scanned according to the file-types associated with the project.</para></listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Remove</guilabel></term>
<listitem><para>All buttons in this group remove files from the current project.</para>
<variablelist>
<varlistentry>
<term><guibutton>Selected</guibutton></term>
<listitem><para><action>Removes all selected files from the current project.</action> Files can be selected for removal by clicking their path name in the file list. The <keycap>Ctrl</keycap> key can be used to select multiple files, and the <keycap>Shift</keycap> key can be used to select ranges of files.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Directory...</guibutton></term>
<listitem><para><action>Removes all source files in a directory from the current project.</action> Note that sub-directories are not included.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Tree...</guibutton></term>
<listitem><para><action>Removes all source files in a directory and any of its sub-directories from the current project.</action></para></listitem>
</varlistentry>
</variablelist>
</listitem>
</varlistentry>
<varlistentry>
<term><guibutton>OK</guibutton></term>
<listitem><para><action>Accepts the new list of source files, and updates the project.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Cancel</guibutton></term>
<listitem><para><action>Closes the dialogue without modifying the list of project files.</action></para></listitem>
</varlistentry>
</variablelist>
<para>
Once the list of project files changes (either when files are first added to the project, or upon any subsequent modification), &kapp; informs <application>Cscope</application> to rebuild the cross-reference database.
</para>
</sect2>
<sect2 id="project-open">
<title>Opening an Existing Project</title>
<para>
Existing projects can be opened using the <menuchoice><guimenu>Project</guimenu><guimenuitem>Open...</guimenuitem></menuchoice> menu command. Choosing this command invokes the <guilabel>Open Project</guilabel> dialogue, which allows the user to select the project to open.
</para>
<screenshot>
<screeninfo>The Open Project dialogue</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="project_open.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Open Project dialogue</phrase>
</textobject>
</mediaobject>
</screenshot>
<variablelist>
<varlistentry>
<term><guilabel>Project Path</guilabel></term>
<listitem><para>The full path of the project directory. Use the browser button to locate a project by its configuration file (<filename>cscope.proj</filename>).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Recent Projects</guilabel></term>
<listitem><para>Displays a list of recently-opened projects. Clicking a list item copies its path to the Project Path edit-box, while double-clicking an item opens the project.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Remove</guibutton></term>
<listitem><para><action>Removes an entry from the list of recently-opened projects.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Open</guibutton></term>
<listitem><para><action>Opens the project whose directory is set in the Project Path edit-box.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Cancel</guibutton></term>
<listitem><para><action>Closes the dialogue without opening a project.</action></para></listitem>
</varlistentry>
</variablelist>
<para>
When a project is closed, it saves session information, such as source files being edited and the contents of locked queries. The session is restored when that project is opened again.
</para>
<para>
After the project has been opened, &kapp; will invoke <application>Cscope</application>, which, in turn, will check whether any files have been modified since the last time the project had been closed. If any files have changed, <application>Cscope</application> will rebuild the cross-reference database.
</para>
</sect2>
<sect2 id="project-prop">
<title>Changing Project Properties</title>
<para>
The properties of an open project can be changed by choosing the <menuchoice><guimenu>Project</guimenu><guimenuitem>Properties...</guimenuitem></menuchoice> menu command. This command invokes the <guilabel>Project Properties</guilabel> dialogue, which is similar to the <guilabel>New Project</guilabel> dialogue, except that the name and path of the project cannot be changed.
</para>
<para>
See the <link linkend="project-create">New Project dialogue</link> for a description of the available project options.
</para>
</sect2>
<sect2 id="projects-temp">
<title>Temporary Projects</title>
<para>
Temporary projects are created when a user opens a cscope.out file directly. This option is useful for working on projects created by some other <application>Cscope</application> front-end (<application>Cscope</application>'s ncurses interface, <application>Vi</application>, <application>>Emacs</application>, etc.), or simply using <application>Cscope</application>'s <option>-b</option> command-line parameter.
</para>
<para>
To open a database file, use the <menuchoice><guimenu>Project</guimenu><guimenuitem>Open Cscope.out...</guimenuitem></menuchoice> menu command. If the file is a valid <application>Cscope</application> cross-reference database, &kapp; will invoke <application>Cscope</application> using this file, and will be ready to accept queries on the database. Cscope.out files can also be opened through the command line, which means that you can simply drag a Cscope.out file, and drop it over &kapp;'s programme icon.
</para>
<para>
Note, however, that most project management options provided by &kapp; will not be available for temporary projects: the file list for the project will be empty, users will not be able to add or remove files, and the project properties dialogue will not be available. You will also need to rebuild the database manually when making any changes. &kapp;'s rebuild command assumes the database has been updated, and only re-runs <application>Cscope</application>.
</para>
</sect2>
<sect2 id="projects-build">
<title>Building Projects</title>
<para>
While &kapp; was not designed as an IDE with a complete write-build-debug cycle, it does provide a simple GUI for building projects. The command <menuchoice><guimenu>Project</guimenu><guimenuitem>Make Project</guimenuitem></menuchoice> displays a dialogue, which can be used to invoke any external tool on a given directory. By default, it runs <command>make</command> on the project's source root. The output of the command will be displayed in the dialogue's <guilabel>Output</guilabel> pane, with any errors or warnings marked-up, similar to links in a browser. Clicking on a link will jump to an editor page showing the source file and line responsible for the message. A list of all abnormal messages also appears in the dialogue's <guilabel>Errors and Warnings</guilabel> pane.
</para>
<screenshot>
<screeninfo>The Make Project dialogue</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="project_make.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Make Project dialogue</phrase>
</textobject>
</mediaobject>
</screenshot>
<variablelist>
<varlistentry>
<term><guilabel>Root Directory</guilabel></term>
<listitem><para>The directory in which to run the build command.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Command</guilabel></term>
<listitem><para>The command to execute.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Make</guibutton></term>
<listitem><para><action>Executes the build command.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Stop</guibutton></term>
<listitem><para><action>Halts an executing build process.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Close</guibutton></term>
<listitem><para><action>Closes the dialogue.</action></para></listitem>
</varlistentry>
</variablelist>
</sect2>
</sect1>

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@ -0,0 +1,434 @@
<sect1 id="queries">
<title>The Query System</title>
<para>
The most important task of &kapp; is to execute <application>Cscope</application> queries and display their results. Queries are always performed on the cross-reference database of the active project.
</para>
<para>
&kapp; currently supports the following query types:
<itemizedlist>
<listitem><para>Find all references to a symbol</para></listitem>
<listitem><para>Find a symbol's global definition</para></listitem>
<listitem><para>Find all functions called by a given function</para></listitem>
<listitem><para>Find all functions calling a given function</para></listitem>
<listitem><para>Find a text string</para></listitem>
<listitem><para>Find an EGrep pattern (regular expression)</para></listitem>
<listitem><para>Find a file's path by its name</para></listitem>
<listitem><para>Find all files including a given file</para></listitem>
<listitem><para>Display a call-tree for a given function</para></listitem>
</itemizedlist>
A symbol, as referred to in the above list, may be a function, a global variable, a structure, a union or a type definition.
</para>
<para>
The cross-reference database may become obsolete when source files are modified, resulting in inaccurate (or simply wrong) query results. &kapp; has two ways for refreshing the database, manual and automatic. Manual database rebuilds are available through the <menuchoice><guimenu>Cscope</guimenu><guimenuitem>Rebuild Database</guimenuitem></menuchoice> menu command. Selecting this command will instruct Cscope to immediately rebuild the cross-reference database.
</para>
<para>
Automatic database rebuilds are enabled per-project, an option controlled by the <guilabel>Project Properties</guilabel> dialogue. Since a database rebuild may be a time and resource-consuming operation, &kapp; does not invoke this procedure after every change to the source code. Instead, changes to the code initiate a timer (whose value is determined by the user in the <guilabel>Project Properties</guilabel> dialogue). Once this timer elapses, &kapp; instructs Cscope to rebuild the database. Code modifications that occur while the timer is running reset its value.
</para>
<para>
A project's database is also updated whenever that project is opened.
</para>
<sect2 id="query-run">
<title>Running a Query</title>
<para>
A query can be started in one of three ways:
<orderedlist>
<listitem><para>The main menu</para></listitem>
<listitem><para>Keyboard shortcuts</para></listitem>
<listitem><para>The editor's context-menu</para></listitem>
</orderedlist>
</para>
<para>
To start a query from the main menu, select the desired query type from the <guimenu>Cscope</guimenu> menu. This will display a dialogue box prompting you for the query's text. The text to enter depends upon the query's type.
<screenshot>
<screeninfo>The query dialogue</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="query_dlg.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The query dialogue</phrase>
</textobject>
</mediaobject>
</screenshot>
</para>
<variablelist>
<varlistentry>
<term><guilabel>Type</guilabel></term>
<listitem><para>The type of query to perform. This value defaults to the requested type, by can be changed by selecting a different entry in the list.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Symbol</guibutton></term>
<listitem><para>Enter the symbol to query in this box. The default value is the symbol currently under the editor's cursor (if any).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Search for a Sub-String</guilabel></term>
<listitem><para>Mark this check-box to treat the entered text as part of a symbol (will query all symbols containing the entered text as a sub-string).</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>OK</guibutton></term>
<listitem><para><action>Runs the query.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Hint</guibutton></term>
<listitem><para><action>Provides a list of possible matches to the entered symbol.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Cancel</guibutton></term>
<listitem><para><action>Closes the dialogue without running the query.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Suggested Symbols</guilabel></term>
<listitem><para>A list of known symbols matching the text in the symbol box.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Hint Options</guilabel></term>
<listitem><para>These buttons affect the way text in the symbol box is matched to fill the suggested symbols list.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Symbols Beginning With...</guilabel></term>
<listitem><para>Choose this option to match symbols starting with the given text.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Symbols Containing...</guilabel></term>
<listitem><para>Choose this option to match symbols containing the given text.</para></listitem>
</varlistentry>
</variablelist>
<para>
Any text selected in the editor when a query is requested will be automatically copied to the query dialogue. If no text is selected, KScope attempts to guess the requested symbol from the current location of the cursor.
</para>
<para>
Each menu item is associated with a keyboard shortcut. These shortcuts follow the convention of using the <keycap>Ctrl</keycap> key, together with the numeric query index used by <application>Cscope</application> (this should allow experienced <application>Cscope</application> users to get quickly acquainted with &kapp;). For example, use <keycombo><keycap>Ctrl</keycap><keycap>1</keycap></keycombo> to look-up a symbol's definition. The call-tree is an exception to this convention (as it is not a native <application>Cscope</application> query). See the <link linkend="commands">Command Reference</link> for a complete listing of all menu and shortcut options.
</para>
<note>
<para>
The EGrep query is invoked using <keycombo><keycap>Ctrl</keycap><keycap>5</keycap></keycombo>, as <keycombo><keycap>Ctrl</keycap><keycap>6</keycap></keycombo> is already used by &kate;.
</para>
</note>
<para>
The third way of starting a query is by right-clicking inside an editor window. This invokes the context-menu, that displays the same options as in the <guimenu>Cscope</guimenu> section of the main menu. Using a context-menu is easy when combined with a symbol selection in the editor: position the text cursor inside a symbol, and then right click to display the context-menu.
</para>
<para>
A query may take some time to complete, depending on its type and the size of the project. &kapp; displays a progress indicator during long queries. If <application>Cscope</application>'s <option>-v</option> command line option is used, this progress indication is accurate, and displays the percentage of files already searched in. In case this option was omitted (e.g., if working with a version of <application>Cscope</application> prior to 15.5), &kapp; will present a dummy progress bar, used simply to indicate that a query is running, and that &kapp; has not frozen. Please refer to the section <link linkend="configuration">Configuring &kapp;</link> for more information.
</para>
</sect2>
<sect2 id="query-window">
<title>The Query Results Window</title>
<para>
When a query has terminated, its output is displayed in the query window, at the bottom of &kapp;'s main window. This window can manage several result pages simultaneously, with each page holding the results of a different query. Each page is associated with a tab that displays a summary of the query that generated these results. This tab is used to bring the results page forward, and is also associated with several page operations through a close button and a context menu.
</para>
<para>
By default, query results are displayed in the currently active page, overriding any prior contents. To keep a results page unchanged, the page needs to be "locked". Locked query pages are never overridden. The contents of these pages are also saved when the project is closed, and are restored when the project is reopened. To lock a project, either click the <guibutton>Lock/Unlock Query</guibutton> toggle button to the right of the query window, or use the context menu (available by right-clicking the page's tab.) The same methods can also be used to unlock a query.
</para>
<para>
New query pages can also be created explicitly, by using either the <guibutton>New Query</guibutton> button to the right of the query window, or the context menu available by right-clicking the tab area of the query window.
</para>
<para>
Each entry in a query results page represents a symbol or text string that complies to the search criteria. The entry is composed of four sections:
<itemizedlist>
<listitem><para>The path of the file in which the symbol or string were found</para></listitem>
<listitem><para>The name of the function containing the symbol or text string</para></listitem>
<listitem><para>The line number in this file</para></listitem>
<listitem><para>The text of this line</para></listitem>
</itemizedlist>
</para>
<para>
By default, results are sorted according to the file name. This can be changed by clicking the column headers of the results list.
</para>
<para>
The entries in a query results page can be used as shortcuts to editing the line in which the symbol or text string were found (or lines in that vicinity.) This is done by either double-clicking a result entry, or by selecting this entry and hitting the <keycap>Enter</keycap> key. As a result, &kapp; will open an editor window displaying the file referred to in the selected entry, and set the cursor to the beginning of the appropriate line.
</para>
<para>
If a query results in a single entry, this entry is automatically selected for display.
</para>
<para>
The results of a query can be refreshed by clicking the <guibutton>Refresh Query</guibutton> button to the right of the query window, or by using the context menu. This command is useful to rerun queries after the database has changed (such as after a <guimenuitem>Rebuild Database</guimenuitem> command had been issued).
</para>
<para>
Query results pages can be closed by either clicking the icon on their tab, by clicking on the <guibutton>Close Query</guibutton> button to the right of the query window, by using the context menu (available by right-clicking the page's tab), or by selecting the <menuchoice><guimenu>Cscope</guimenu><guimenuitem>Close Query</guimenuitem></menuchoice> main-menu command.
</para>
<para>
If the query window is not visible when a query is executed, it is temporarily displayed, and then re-hidden when the user selects an entry for viewing.
</para>
</sect2>
<sect2 id="result-options">
<title>Query Results Options</title>
<para>
Right-clicking a query result in either a query window or a call-tree dialogue displays a context menu. This menu includes several actions that can be used to either extract information or fine tune these results.
</para>
<para>
<variablelist>
<varlistentry>
<term><menuchoice>
<guimenuitem>Copy File</guimenuitem>
</menuchoice></term>
<listitem><para><action>Copies the file path part of a result record to the clipboard</action> (the copy commands are available depending on the position of the mouse cursor).</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenuitem>Copy Function</guimenuitem>
</menuchoice></term>
<listitem><para><action>Copies the function name part of a result record to the clipboard.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenuitem>Copy Line</guimenuitem>
</menuchoice></term>
<listitem><para><action>Copies the line number part of a result record.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenuitem>Copy Text</guimenuitem>
</menuchoice></term>
<listitem><para><action>Copies the function name part of a result record to the clipboard.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenuitem>Filter...</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays the Filter Query Results dialogue.</action> See the section <link linkend="filter-results">Filtering Query Results</link> for a detailed description of this option.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenuitem>Show All</guimenuitem>
</menuchoice></term>
<listitem><para><action>Displays all query results.</action> This option reverts the effects of any filters previously applied.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenuitem>Remove Item</guimenuitem>
</menuchoice></term>
<listitem><para><action>Permanently removes a record from a query results window.</action> This action can only be undone by rerunning the query.</para></listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
<sect2 id="filter-results">
<title>Filtering Query Results</title>
<para>
It is often the case the a query results in an abundance of information. &kapp; allows the user to filter query results in order to show only those results that the user finds interesting, an action referred to as "Filtering". Filtering is done by matching patterns on any of the query record fields (file name, function, line number and line text).
</para>
<para>
The Filter Query Results dialogue is invoked from the query context menu (see <link linkend="result-options">Query Result Options</link>).
<screenshot>
<screeninfo>The Filter Query Results dialogue</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="query_filter.png" format="PNG" />
</imageobject>
<textobject>
<phrase>The Filter Query Results dialogue</phrase>
</textobject>
</mediaobject>
</screenshot>
</para>
<variablelist>
<varlistentry>
<term><guilabel>Search For</guilabel></term>
<listitem><para>Enter the pattern to match in the query result records. This pattern is interpreted based on the Search Type selection.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Search In</guilabel></term>
<listitem><para>The record field in which to look for the search pattern. By default, this is the field over which the context menu was invoked.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Search Type</guilabel></term>
<listitem><para>Defines the way in which the pattern should be interpreted.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Plain Text</guilabel></term>
<listitem><para>Choose this option to treat the pattern as a simple text string to search for.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>RegExp</guilabel></term>
<listitem><para>Choose this option to treat the pattern as a regular expression.</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Simplified RegExp</guilabel></term>
<listitem><para>Choose this option to treat the pattern as a simplified regular expression (a-la file expressions in a Unix shell).</para></listitem>
</varlistentry>
<varlistentry>
<term><guilabel>Case Sensitive</guilabel></term>
<listitem><para>Check for a case sensitive search, uncheck for a case insensitive one.</para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>OK</guibutton></term>
<listitem><para><action>Filters the query results based on the given information.</action></para></listitem>
</varlistentry>
<varlistentry>
<term><guibutton>Cancel</guibutton></term>
<listitem><para><action>Closes the dialogue without filtering the results.</action></para></listitem>
</varlistentry>
</variablelist>
</sect2>
<sect2 id="call-tree-graph">
<title>Displaying Call-Trees and Graphs</title>
<para>
Tracing a sequence of calls in the code base is a common task in code analysis. To facilitate this task, &kapp; offers two mechanisms for visualising the relationships between different functions in a project: the Call-Tree and the Call-Graph. Both of these mechanisms are provided through the <guilabel>Call Graph Dialogue</guilabel> which can be invoked on a function name in a similar way to a regular <application>Cscope</application> query.
</para>
<sect3 id="call-tree">
<title>Call Trees</title>
<para>
The Call-Tree has two modes, "Called Functions" and "Calling Functions". In the first case, the call chain starts with a root function, and goes on to display all the functions it references. The second mode shows all functions calling the root function. In both modes each function in the second level can be further expanded to show functions calling it (or functions it calls). This process can be further applied to functions in the third level, an so on.
</para>
<para>
Both modes use a standard tree widget to display the call chain. Expanding a function to the next level is performed by clicking the plus sign to the left of the function's name. Double-clicking a function (or selecting it and then hitting <keycap>Enter</keycap>) points the editor to the call's actual text. Right-clicking an entry provides a popup-menu with further options, similar to the query results menu (see <link linkend="result-options">Query Result Options</link>).
</para>
<para>
<screenshot>
<screeninfo>A Call-Tree</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="call_tree.png" format="PNG" />
</imageobject>
<textobject>
<phrase>A Call-Tree in "Called Functions" mode</phrase>
</textobject>
</mediaobject>
</screenshot>
</para>
</sect3>
<sect3 id="call-graph">
<title>Call Graphs</title>
<para>
A Call-Tree often misses the true nature of a call sequence, since many such sequences contain loops, that is, functions calling back functions that precede them in the sequence. (Recursive calls provide a natural example for such a state of affairs.) A Call-Graph provides a more accurate description of the relationships between functions by depicting calls using a directed graph. Each node in the graph represents a function and each edge a function call. An edge is directed from the caller to the callee.
</para>
<para>
<screenshot>
<screeninfo>A Call-Graph</screeninfo>
<mediaobject>
<imageobject>
<imagedata fileref="call_graph.png" format="PNG" />
</imageobject>
<textobject>
<phrase>A Call-Graph</phrase>
</textobject>
</mediaobject>
</screenshot>
</para>
<para>
When a Call-Graph is created, it only displays a single function. Right-clicking on this function opens a popup menu that allows the user to display or hide either the functions called by or calling to this one. This menu consists of the following entries:
<variablelist>
<varlistentry>
<term><menuchoice>
<guimenu>Called Functions</guimenu>
<guimenuitem>Show</guimenuitem>
</menuchoice></term>
<listitem><para>Shows all functions called by this one.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Called Functions</guimenu>
<guimenuitem>List/Filter...</guimenuitem>
</menuchoice></term>
<listitem><para>Displays a detailed list of called functions. This list can also be used to select which calling functions to show.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Called Functions</guimenu>
<guimenuitem>Hide</guimenuitem>
</menuchoice></term>
<listitem><para>Removes any functions called by this one. This will also remove any unconnected graph components resulting from the removal of the corresponding nodes.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Calling Functions</guimenu>
<guimenuitem>Show</guimenuitem>
</menuchoice></term>
<listitem><para>Shows all functions calling this one.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Calling Functions</guimenu>
<guimenuitem>List/Filter...</guimenuitem>
</menuchoice></term>
<listitem><para>Displays a detailed list of calling functions. This list can also be used to select which calling functions to show.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>Calling Functions</guimenu>
<guimenuitem>Hide</guimenuitem>
</menuchoice></term>
<listitem><para>Removes any functions calling this one. This will also remove any unconnected graph components resulting from the removal of the corresponding nodes.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>This Function</guimenu>
<guimenuitem>Find Definition</guimenuitem>
</menuchoice></term>
<listitem><para>Queries the database for the definition of the selected function.</para></listitem>
</varlistentry>
<varlistentry>
<term><menuchoice>
<guimenu>This Function</guimenu>
<guimenuitem>Remove</guimenuitem>
</menuchoice></term>
<listitem><para>Deletes the selected node from the graph.</para></listitem>
</varlistentry>
</variablelist>
</para>
<para>
Another popup menu is displayed when an arrow head is right-clicked:
<variablelist>
<varlistentry>
<term><menuchoice>
<guimenuitem>Open Call</guimenuitem>
</menuchoice></term>
<listitem><para>Opens an editor page at the location of the call represented by this edge.</para></listitem>
</varlistentry>
</variablelist>
</para>
</sect3>
</sect2>
</sect1>

@ -0,0 +1,41 @@
<sect1 id="quick-start">
<title>Quick Start</title>
<para>
This section provides information for the impatient user who would like to start using &kapp; right away. While using &kapp; should be straight-forward for anyone who has ever used similar tools in the past, and is familiar with KDE applications, there are, nonetheless, some points that require attention. Even if you do not have the time or patience to browse through this entire manual, please make sure to read at least this section.
</para>
<sect2>
<title>Configure Paths</title>
<para>
&kapp; needs to be informed of the absolute paths to several executables, including <application>Cscope</application>, <application>Ctags</application> and (optionally) <application>Dot</application>. These can be configured in the <guilabel>Programmes</guilabel> page of the main configuration dialogue. See <link linkend="config-dlg">The Configuration Dialogue</link> section for more information.
<warning><para>&kapp; will not work properly if these paths are not configured correctly!</para></warning>
</para>
</sect2>
<sect2>
<title>Create a Project</title>
<para>
While &kapp; can be used to edit individual files, most of its browsing, analysis and editing features will not be available outside of a project. A project is a set of source files for which &kapp; creates a cross-reference database, the key to most of &kapp;'s capabilities. See <link linkend="project-create">Creating a New Project</link> for detailed instructions.
</para>
</sect2>
<sect2>
<title>Populate the Project</title>
<para>
As mentioned above, a project is associated with a set of source files. These need to be added to the project, before any useful work can be done. Files can be added (or removed) using the <link linkend="project-files">Project Files</link> dialogue.
</para>
</sect2>
<sect2>
<title>Browse and Edit Files</title>
<para>
Once a project has been defined, &kapp; is ready for use. You can now open files for viewing and editing, and use the query system for browsing and analysing the project's code base. See the rest of this manual for more information.
</para>
</sect2>
</sect1>

@ -0,0 +1 @@
POFILES = AUTO

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,68 @@
# set the include path for X, qt and KDE
INCLUDES = $(all_includes)
# these are the headers for your project
noinst_HEADERS = bookmarksdlg.h calltreedlg.h calltreemanager.h \
configfrontend.h cscopefrontend.h cscopemsgdlg.h ctagsfrontend.h ctagslist.h \
dirscanner.h dotfrontend.h editormanager.h editorpage.h editortabs.h encoder.h \
filelist.h fileview.h frontend.h graphedge.h graphnode.h graphprefdlg.h \
graphwidget.h historypage.h historyview.h kscope.h kscopeactions.h kscopeconfig.h \
kscopepixmaps.h makedlg.h makefrontend.h newprojectdlg.h openprojectdlg.h prefcolor.h \
preferencesdlg.h preffont.h preffrontend.h prefopt.h progressdlg.h project.h \
projectbase.h projectfilesdlg.h projectmanager.h querypage.h querypagebase.h \
queryresultsmenu.h queryview.h queryviewdlg.h queryviewdriver.h querywidget.h \
scanprogressdlg.h searchlist.h searchresultsdlg.h symbolcompletion.h symboldlg.h \
tabwidget.h treewidget.h
# let automoc handle all of the meta source files (moc)
METASOURCES = AUTO
messages: rc.cpp
$(XGETTEXT) *.cpp -o $(podir)/kscope.pot
KDE_ICON = kscope
#########################################################################
# APPLICATION SECTION
#########################################################################
# this is the program that gets installed. it's name is used for all
# of the other Makefile.am variables
bin_PROGRAMS = kscope
# the application source, library search path, and link libraries
kscope_SOURCES = autocompletionlayout.ui bookmarksdlg.cpp bookmarkslayout.ui \
calltreedlg.cpp calltreelayout.ui calltreemanager.cpp configfrontend.cpp \
cscopefrontend.cpp cscopemsgdlg.cpp cscopemsglayout.ui ctagsfrontend.cpp ctagslist.cpp \
dirscanner.cpp dotfrontend.cpp dotparse.ypp dotscan.lpp editormanager.cpp \
editorpage.cpp editortabs.cpp encoder.cpp filelist.cpp fileview.cpp fileviewlayout.ui \
frontend.cpp graphedge.cpp graphnode.cpp graphprefdlg.cpp graphpreflayout.ui \
graphwidget.cpp historypage.cpp historyview.cpp kscope.cpp kscopeactions.cpp \
kscopeconfig.cpp kscopepixmaps.cpp main.cpp makedlg.cpp makefrontend.cpp makelayout.ui \
newprojectdlg.cpp newprojectlayout.ui openprojectdlg.cpp openprojectlayout.ui \
prefcolor.cpp prefcolorlayout.ui preferencesdlg.cpp preffont.cpp preffontlayout.ui \
preffrontend.cpp preffrontendlayout.ui prefopt.cpp prefoptlayout.ui progressdlg.cpp \
project.cpp projectbase.cpp projectfilesdlg.cpp projectfileslayout.ui \
projectmanager.cpp querypage.cpp querypagebase.cpp queryresultsmenu.cpp queryview.cpp \
queryviewdlg.cpp queryviewdriver.cpp queryviewlayout.ui querywidget.cpp \
querywidgetlayout.ui scanprogressdlg.cpp scanprogresslayout.ui searchlist.cpp \
searchresultsdlg.cpp searchresultslayout.ui symbolcompletion.cpp symboldlg.cpp \
symbollayout.ui tabwidget.cpp treewidget.cpp welcomedlg.ui
kscope_LDFLAGS = $(KDE_RPATH) $(all_libraries)
kscope_LDADD = -lkateinterfaces -lktexteditor $(LIB_KDEUI)
# this is where the desktop file will go
shelldesktopdir = $(kde_appsdir)/Development
shelldesktop_DATA = kscope.desktop
# this is where the shell's XML-GUI resource file goes
shellrcdir = $(kde_datadir)/kscope
shellrc_DATA = kscopeui.rc kscope_config
picsdir = $(kde_datadir)/kscope/pics
pics_DATA = file_ro.png file_rw.png file_save.png query_locked.png \
query_unlocked.png tab_list.png call_graph.png called_tree.png calling_tree.png \
bookmark.png
BUILT_SOURCES = dotparse.h
AM_YFLAGS = -d

@ -0,0 +1,217 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>AutoCompletionLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>AutoCompletionLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>287</width>
<height>183</height>
</rect>
</property>
<property name="caption">
<string>Auto-Completion Properties</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout20</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="text">
<string>Minimum Characters</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer15</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>71</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QSpinBox">
<property name="name">
<cstring>m_pMinCharsSpin</cstring>
</property>
</widget>
</hbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout21</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel2</cstring>
</property>
<property name="text">
<string>Delay (ms)</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer16</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>101</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QSpinBox">
<property name="name">
<cstring>m_pDelaySpin</cstring>
</property>
<property name="maxValue">
<number>10000</number>
</property>
<property name="lineStep">
<number>100</number>
</property>
</widget>
</hbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout22</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel3</cstring>
</property>
<property name="text">
<string>Maximum Entries</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer17</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>81</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QSpinBox">
<property name="name">
<cstring>m_pMaxEntriesSpin</cstring>
</property>
<property name="maxValue">
<number>1000</number>
</property>
<property name="minValue">
<number>1</number>
</property>
</widget>
</hbox>
</widget>
<spacer>
<property name="name">
<cstring>spacer19</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>20</width>
<height>31</height>
</size>
</property>
</spacer>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout23</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer18</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>111</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pOKButton</cstring>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCancelButton</cstring>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<layoutdefaults spacing="6" margin="11"/>
</UI>

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 B

@ -0,0 +1,60 @@
/***************************************************************************
*
* Copyright (C) 2007 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include "bookmarksdlg.h"
#include "queryview.h"
BookmarksDlg::BookmarksDlg(QWidget* pParent, const char* szName) :
BookmarksLayout (pParent, szName, true)
{
// Do not show the "Function" column
m_pView->setColumnWidth(0, 0);
// Handle requests for source locations
connect(m_pView, SIGNAL(lineRequested(const QString&, uint)), this,
SLOT(slotLineRequested(const QString&, uint)));
}
BookmarksDlg::~BookmarksDlg()
{
}
void BookmarksDlg::getBookmark(QString& sPath, uint& nLine)
{
sPath = m_sPath;
nLine = m_nLine;
}
void BookmarksDlg::slotLineRequested(const QString& sPath, uint nLine)
{
m_sPath = sPath;
m_nLine = nLine;
accept();
}
#include "bookmarksdlg.moc"

@ -0,0 +1,53 @@
/***************************************************************************
*
* Copyright (C) 2007 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef BOOKMARKSDLG_H
#define BOOKMARKSDLG_H
#include "bookmarkslayout.h"
class BookmarksDlg : public BookmarksLayout
{
Q_OBJECT
public:
BookmarksDlg(QWidget* pParent = 0, const char* szName = 0);
~BookmarksDlg();
QueryView* getView() { return m_pView; }
void getBookmark(QString&, uint&);
private:
QString m_sPath;
uint m_nLine;
private slots:
void slotLineRequested(const QString&, uint);
};
#endif

@ -0,0 +1,116 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>BookmarksLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>BookmarksLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>480</height>
</rect>
</property>
<property name="caption">
<string>Global Bookmarks</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QueryView">
<property name="name">
<cstring>m_pView</cstring>
</property>
</widget>
<widget class="Line">
<property name="name">
<cstring>line1</cstring>
</property>
<property name="frameShape">
<enum>HLine</enum>
</property>
<property name="frameShadow">
<enum>Sunken</enum>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout1</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer1</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>291</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCloseButton</cstring>
</property>
<property name="text">
<string>Close</string>
</property>
<property name="accel">
<string></string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<customwidgets>
<customwidget>
<class>QueryView</class>
<header location="local">queryview.h</header>
<sizehint>
<width>-1</width>
<height>-1</height>
</sizehint>
<container>0</container>
<sizepolicy>
<hordata>5</hordata>
<verdata>5</verdata>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<pixmap>image0</pixmap>
</customwidget>
</customwidgets>
<images>
<image name="image0">
<data format="XBM.GZ" length="79">789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f</data>
</image>
</images>
<connections>
<connection>
<sender>m_pCloseButton</sender>
<signal>clicked()</signal>
<receiver>BookmarksLayout</receiver>
<slot>reject()</slot>
</connection>
</connections>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>queryview.h</includehint>
</includehints>
</UI>

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

@ -0,0 +1,336 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qfile.h>
#include <qtoolbutton.h>
#include <qbuttongroup.h>
#include <qwidgetstack.h>
#include <klocale.h>
#include <kfiledialog.h>
#include "calltreedlg.h"
#include "graphwidget.h"
#include "treewidget.h"
#include "kscopepixmaps.h"
#include "kscopeconfig.h"
#include "graphprefdlg.h"
/** The currently supported version of saved call-tree files. */
#define FILE_VERSION 5
/** Window flags for call-tree widgets. */
#define CALL_TREE_W_FLAGS \
WStyle_Customize | \
WStyle_NormalBorder | \
WStyle_Title | \
WDestructiveClose
/** File Name index for the file name generation */
int CallTreeDlg::s_nFileNameIndex = 0;
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
CallTreeDlg::CallTreeDlg(QWidget* pParent, const char* szName) :
CallTreeLayout(pParent, szName, CALL_TREE_W_FLAGS)
{
// Set button pixmaps
m_pCalledButton->setPixmap(GET_PIXMAP(CalledTree));
m_pCallingButton->setPixmap(GET_PIXMAP(CallingTree));
m_pGraphButton->setPixmap(GET_PIXMAP(CallGraph));
m_pSaveButton->setPixmap(GET_PIXMAP(ButtonSaveAs));
m_pZoomInButton->setPixmap(GET_PIXMAP(ButtonZoomIn));
m_pZoomOutButton->setPixmap(GET_PIXMAP(ButtonZoomOut));
m_pRotateButton->setPixmap(GET_PIXMAP(ButtonRotate));
m_pPrefButton->setPixmap(GET_PIXMAP(ButtonPref));
// Open the location of a call
connect(m_pGraphWidget, SIGNAL(lineRequested(const QString&, uint)),
this, SIGNAL(lineRequested(const QString&, uint)));
connect(m_pCalledWidget, SIGNAL(lineRequested(const QString&, uint)),
this, SIGNAL(lineRequested(const QString&, uint)));
connect(m_pCallingWidget, SIGNAL(lineRequested(const QString&, uint)),
this, SIGNAL(lineRequested(const QString&, uint)));
m_pCallingWidget->setMode(TreeWidget::Calling);
// Get the default view from KScope's configuration
m_nDefView = Config().getDefGraphView();
}
/**
* Class destructor.
*/
CallTreeDlg::~CallTreeDlg()
{
}
/**
* @param sFunc The function to use as the root of the call tree
*/
void CallTreeDlg::setRoot(const QString& sFunc)
{
m_sRoot = sFunc;
// Generate unique file name to save call tree later
m_sFileName = sFunc;
m_sFileName.replace(' ', '_');
m_sFileName += QString::number(++s_nFileNameIndex);
// Set the root item in all views
m_pGraphWidget->setRoot(sFunc);
m_pCalledWidget->setRoot(sFunc);
m_pCallingWidget->setRoot(sFunc);
}
/**
* Displays the dialogue.
*/
void CallTreeDlg::show()
{
// Set the default view.
m_pViewGroup->setButton(m_nDefView);
m_pStack->raiseWidget(m_nDefView);
slotViewChanged(m_nDefView);
CallTreeLayout::show();
}
/**
* Informs the call tree manager that this object should be removed from the
* list of call tree dialogues.
* The close event is received when the dialogue is explicitly closed by the
* user. This dialogue will not appear when the project is reopened, and it
* is therefore safe to delete the graph file at this point.
* @param pEvent Information on the closing event
*/
void CallTreeDlg::closeEvent(QCloseEvent* pEvent)
{
if (!m_sFilePath.isEmpty())
QFile::remove(m_sFilePath);
emit closed(this);
QWidget::closeEvent(pEvent);
}
extern void yyinit(CallTreeDlg*, FILE*, Encoder*);
extern int yyparse();
/**
* Restores a call tree from the given call tree file.
* NOTE: The call tree file is deleted when loading is complete.
* @param sProjPath The full path of the project directory
* @param sFileName The name of the call tree file to load
* @return true if successful, false otherwise
*/
bool CallTreeDlg::load(const QString& sProjPath, const QString& sFileName)
{
QString sPath;
FILE* pFile;
int nVersion, nView, nResult;
Encoder enc;
// Create the full path name
sPath = sProjPath + "/" + sFileName;
// Open the file for reading
pFile = fopen(sPath.latin1(), "r");
if (pFile == NULL)
return false;
// Check file version
if ((fscanf(pFile, "VERSION=%d\n", &nVersion) != 1) ||
(nVersion != FILE_VERSION)) {
fclose(pFile);
return false;
}
// Get default view
if ((fscanf(pFile, "View=%d\n", &nView) == 1) &&
(nView >= 0) &&
(nView <= 2)) {
m_nDefView = nView;
}
// Read the call trees and the graph stored on this file
yyinit(this, pFile, &enc);
nResult = yyparse();
// Close the file
fclose(pFile);
// Check the result returned by the parser
if (nResult != 0)
return false;
// Store the file name
m_sFileName = sFileName;
m_sFilePath = sPath;
// Draw the graph
m_pGraphWidget->draw();
return true;
}
/**
* Writes the contents of the call tree dialog to a call tree file.
* This method is called for call trees before the owner project is
* closed.
* @param sProjPath The full path of the project directory
*/
void CallTreeDlg::store(const QString& sProjPath)
{
QString sPath;
FILE* pFile;
// Create the full file path
sPath = sProjPath + "/" + m_sFileName;
m_sFilePath = sPath;
// Open a file for writing (create if necessary)
pFile = fopen(sPath.latin1(), "w+");
if (pFile == NULL)
return;
// Write header
fprintf(pFile, "VERSION=%d\n", FILE_VERSION);
fprintf(pFile, "View=%d\n", m_pViewGroup->selectedId());
// Save the contents of all widgets
m_pCalledWidget->save(pFile);
m_pCallingWidget->save(pFile);
m_pGraphWidget->save(pFile);
// Close the file
fclose(pFile);
}
/**
* Saves the graph to a dot file.
* The user is prompted for a name to use for the file, and then graph
* widget writes its information to this file (using the dot language).
* This slot is connected to the clicked() signal of the "Save As..." button.
*/
void CallTreeDlg::slotSaveClicked()
{
QString sFile;
// Prompt the user for a file name
sFile = KFileDialog::getSaveFileName(":kscope");
// Save the graph to a file (unless the user did not give a file name)
if (!sFile.isEmpty())
m_pGraphWidget->save(sFile);
}
/**
* Increases the zoom factor of the graph.
* This slot is connected to the clicked() signal of the "Zoom In" button.
*/
void CallTreeDlg::slotZoomInClicked()
{
m_pGraphWidget->zoom(true);
m_pGraphWidget->draw();
}
/**
* Decreases the zoom factor of the graph.
* This slot is connected to the clicked() signal of the "Zoom Out" button.
*/
void CallTreeDlg::slotZoomOutClicked()
{
m_pGraphWidget->zoom(false);
m_pGraphWidget->draw();
}
/**
* Changes the graph's layout direction.
* This slot is connected to the clicked() signal of the "Rotate" button.
*/
void CallTreeDlg::slotRotateClicked()
{
m_pGraphWidget->rotate();
m_pGraphWidget->draw();
}
/**
* Opens the call graph preferences dialogue.
* This slot is connected to the clicked() signal of the "Preferences" button.
*/
void CallTreeDlg::slotPrefClicked()
{
GraphPrefDlg dlg(this);
int nMaxNodeDegree;
if (dlg.exec() == QDialog::Accepted) {
nMaxNodeDegree = dlg.getMaxNodeDegree();
Config().setGraphMaxNodeDegree(nMaxNodeDegree);
m_pGraphWidget->setMaxNodeDegree(nMaxNodeDegree);
}
}
/**
* Prepares the selected view.
* This slot is called when the user chooses a different view through the
* toggle buttons in the dialogue's toolbar.
* @param nView Identifies the selected view
*/
void CallTreeDlg::slotViewChanged(int nView)
{
switch (nView) {
case 0:
// Call graph
setCaption(i18n("Call Graph"));
m_pGraphGroup->setEnabled(true);
m_pHelpLabel->setText(i18n("Right-click a function node or an arrow "
"head for more options."));
break;
case 1:
// Called functions tree
setCaption(i18n("Called Functions Tree"));
m_pGraphGroup->setEnabled(false);
m_pHelpLabel->setText(i18n("Right-click a tree item for more "
"options."));
m_pCalledWidget->queryRoot();
break;
case 2:
// Calling functions tree
setCaption(i18n("Calling Functions Tree"));
m_pGraphGroup->setEnabled(false);
m_pHelpLabel->setText(i18n("Right-click a tree item for more "
"options."));
m_pCallingWidget->queryRoot();
break;
}
Config().setDefGraphView(nView);
}
#include "calltreedlg.moc"

@ -0,0 +1,111 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef CALLTREEDLG_H
#define CALLTREEDLG_H
#include <qwidget.h>
#include <qlistview.h>
#include <calltreelayout.h>
/**
* A multiple-view window showing function call information.
* The available views are:
* - Call graph, showing both calling and call functions
* - Called functions tree
* - Calling functions tree
* NOTE: This is class is now derived from QWidget instead of QDialog. This
* means that call-trees are independent windows, which can be maximised or
* minimised.
* @author Elad Lahav
*/
class CallTreeDlg : public CallTreeLayout
{
Q_OBJECT
public:
CallTreeDlg(QWidget* pParent = 0, const char* szName = 0);
~CallTreeDlg();
void setRoot(const QString&);
bool load(const QString&, const QString&);
void store(const QString&);
/** Returns Call Tree filename */
QString getFileName() { return m_sFileName; }
public slots:
virtual void show();
signals:
/**
* Emitted when the user makes a request to view the contents of a
* location in the source code.
* This can be the location of a call, the definition of a function,
* etc.
* @param sPath The full path of the file to show
* @param nLine The line number in this file
*/
void lineRequested(const QString& sPath, uint nLine);
/**
* Emitted when the user closes the tree view.
*/
void closed(const CallTreeDlg*);
protected:
virtual void closeEvent(QCloseEvent*);
protected slots:
virtual void slotSaveClicked();
virtual void slotZoomInClicked();
virtual void slotZoomOutClicked();
virtual void slotRotateClicked();
virtual void slotPrefClicked();
virtual void slotViewChanged(int);
private:
/** The root function. */
QString m_sRoot;
/** A unique file name used for storing the call tree on a file.
The name is a combination of the root function and an incremented
index. */
QString m_sFileName;
/** The full path of the file on which the call tree was saved
(empty if this graph was never stored). */
QString m_sFilePath;
/** The view to show when the dialogue is first displayed. */
int m_nDefView;
/** An index for the generating unique file names. */
static int s_nFileNameIndex;
};
#endif

@ -0,0 +1,430 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>CallTreeLayout</class>
<widget class="QWidget">
<property name="name">
<cstring>CallTreeLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>695</width>
<height>578</height>
</rect>
</property>
<property name="caption">
<string>Call Graph</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout2</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QButtonGroup">
<property name="name">
<cstring>m_pViewGroup</cstring>
</property>
<property name="frameShape">
<enum>NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="title">
<string></string>
</property>
<property name="exclusive">
<bool>true</bool>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<widget class="QToolButton">
<property name="name">
<cstring>m_pGraphButton</cstring>
</property>
<property name="text">
<string>...</string>
</property>
<property name="toggleButton">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip" stdset="0">
<string>Call Graph</string>
</property>
</widget>
<widget class="QToolButton">
<property name="name">
<cstring>m_pCalledButton</cstring>
</property>
<property name="text">
<string>...</string>
</property>
<property name="toggleButton">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip" stdset="0">
<string>Called Functions Tree</string>
</property>
</widget>
<widget class="QToolButton">
<property name="name">
<cstring>m_pCallingButton</cstring>
</property>
<property name="text">
<string>...</string>
</property>
<property name="toggleButton">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip" stdset="0">
<string>Calling Functions Tree</string>
</property>
</widget>
</hbox>
</widget>
<widget class="Line">
<property name="name">
<cstring>line1</cstring>
</property>
<property name="frameShape">
<enum>VLine</enum>
</property>
<property name="frameShadow">
<enum>Sunken</enum>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
</widget>
<widget class="QButtonGroup">
<property name="name">
<cstring>m_pGraphGroup</cstring>
</property>
<property name="frameShape">
<enum>NoFrame</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="title">
<string></string>
</property>
<property name="flat">
<bool>true</bool>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<widget class="QToolButton">
<property name="name">
<cstring>m_pSaveButton</cstring>
</property>
<property name="text">
<string>a</string>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip" stdset="0">
<string>Save As...</string>
</property>
</widget>
<widget class="QToolButton">
<property name="name">
<cstring>m_pZoomInButton</cstring>
</property>
<property name="text">
<string>a</string>
</property>
<property name="toggleButton">
<bool>false</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip" stdset="0">
<string>Zoom In</string>
</property>
</widget>
<widget class="QToolButton">
<property name="name">
<cstring>m_pZoomOutButton</cstring>
</property>
<property name="text">
<string>a</string>
</property>
<property name="toggleButton">
<bool>false</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip" stdset="0">
<string>Zoom Out</string>
</property>
</widget>
<widget class="QToolButton">
<property name="name">
<cstring>m_pRotateButton</cstring>
</property>
<property name="text">
<string>a</string>
</property>
<property name="toggleButton">
<bool>false</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip" stdset="0">
<string>Rotate</string>
</property>
</widget>
<widget class="QToolButton">
<property name="name">
<cstring>m_pPrefButton</cstring>
</property>
<property name="text">
<string>a</string>
</property>
<property name="toggleButton">
<bool>false</bool>
</property>
<property name="autoRaise">
<bool>true</bool>
</property>
<property name="toolTip" stdset="0">
<string>Preferences</string>
</property>
</widget>
</hbox>
</widget>
<spacer>
<property name="name">
<cstring>spacer2</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>110</width>
<height>21</height>
</size>
</property>
</spacer>
</hbox>
</widget>
<widget class="QWidgetStack">
<property name="name">
<cstring>m_pStack</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>7</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QWidget">
<property name="name">
<cstring>WStackPage</cstring>
</property>
<attribute name="id">
<number>0</number>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<widget class="GraphWidget">
<property name="name">
<cstring>m_pGraphWidget</cstring>
</property>
</widget>
</vbox>
</widget>
<widget class="QWidget">
<property name="name">
<cstring>WStackPage</cstring>
</property>
<attribute name="id">
<number>1</number>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<widget class="TreeWidget">
<property name="name">
<cstring>m_pCalledWidget</cstring>
</property>
</widget>
</vbox>
</widget>
<widget class="QWidget">
<property name="name">
<cstring>WStackPage</cstring>
</property>
<attribute name="id">
<number>2</number>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<widget class="TreeWidget">
<property name="name">
<cstring>m_pCallingWidget</cstring>
</property>
</widget>
</vbox>
</widget>
</widget>
<widget class="QLabel">
<property name="name">
<cstring>m_pHelpLabel</cstring>
</property>
<property name="text">
<string>Help Message</string>
</property>
</widget>
</vbox>
</widget>
<customwidgets>
<customwidget>
<class>GraphWidget</class>
<header location="local">graphwidget.h</header>
<sizehint>
<width>-1</width>
<height>-1</height>
</sizehint>
<container>0</container>
<sizepolicy>
<hordata>7</hordata>
<verdata>7</verdata>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<pixmap>image0</pixmap>
</customwidget>
<customwidget>
<class>TreeWidget</class>
<header location="local">treewidget.h</header>
<sizehint>
<width>-1</width>
<height>-1</height>
</sizehint>
<container>0</container>
<sizepolicy>
<hordata>7</hordata>
<verdata>7</verdata>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<pixmap>image0</pixmap>
</customwidget>
</customwidgets>
<images>
<image name="image0">
<data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data>
</image>
</images>
<connections>
<connection>
<sender>m_pPrefButton</sender>
<signal>clicked()</signal>
<receiver>CallTreeLayout</receiver>
<slot>slotPrefClicked()</slot>
</connection>
<connection>
<sender>m_pRotateButton</sender>
<signal>clicked()</signal>
<receiver>CallTreeLayout</receiver>
<slot>slotRotateClicked()</slot>
</connection>
<connection>
<sender>m_pZoomOutButton</sender>
<signal>clicked()</signal>
<receiver>CallTreeLayout</receiver>
<slot>slotZoomOutClicked()</slot>
</connection>
<connection>
<sender>m_pZoomInButton</sender>
<signal>clicked()</signal>
<receiver>CallTreeLayout</receiver>
<slot>slotZoomInClicked()</slot>
</connection>
<connection>
<sender>m_pSaveButton</sender>
<signal>clicked()</signal>
<receiver>CallTreeLayout</receiver>
<slot>slotSaveClicked()</slot>
</connection>
<connection>
<sender>m_pViewGroup</sender>
<signal>clicked(int)</signal>
<receiver>CallTreeLayout</receiver>
<slot>slotViewChanged(int)</slot>
</connection>
<connection>
<sender>m_pViewGroup</sender>
<signal>clicked(int)</signal>
<receiver>m_pStack</receiver>
<slot>raiseWidget(int)</slot>
</connection>
</connections>
<slots>
<slot access="protected">slotSaveClicked()</slot>
<slot access="protected">slotZoomInClicked()</slot>
<slot access="protected">slotZoomOutClicked()</slot>
<slot access="protected">slotRotateClicked()</slot>
<slot access="protected">slotViewChanged(int)</slot>
<slot access="protected">slotViewChanged(QWidget*)</slot>
<slot access="protected">slotPrefClicked()</slot>
</slots>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>graphwidget.h</includehint>
<includehint>treewidget.h</includehint>
<includehint>treewidget.h</includehint>
</includehints>
</UI>

@ -0,0 +1,136 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include "calltreemanager.h"
#include "calltreedlg.h"
#include "projectmanager.h"
/**
* Class constructor.
* @param pParent The widget to use as the parent of all Call Tree
* dialogues
*/
CallTreeManager::CallTreeManager(QWidget* pParent) : QObject(pParent)
{
// Delete dialogue objects when they are removed from the list
m_lstDialogs.setAutoDelete(true);
}
/**
* Class destructor.
*/
CallTreeManager::~CallTreeManager()
{
}
/**
* Saves all call trees into the project directory.
* @param sProjPath The project's directory
* @param slFiles Holds a list of saved file names, upon return
*/
void CallTreeManager::saveOpenDialogs(const QString& sProjPath,
QStringList& slFiles)
{
CallTreeDlg *pDlg;
// Iterate over the open dialogues
for (pDlg = m_lstDialogs.first(); pDlg != NULL;
pDlg = m_lstDialogs.next()) {
pDlg->store(sProjPath);
slFiles += pDlg->getFileName();
}
}
/**
* Loads all call trees according to the list of files
* @param sProjPath The project's directory
* @param slFiles A list of file names to open
*/
void CallTreeManager::loadOpenDialogs(const QString& sProjPath,
const QStringList& slFiles)
{
QStringList::ConstIterator itr;
CallTreeDlg *pDlg;
for (itr = slFiles.begin(); itr != slFiles.end(); ++itr) {
// Create a new dialogue for this file
pDlg = addDialog();
// Try to load the graph from the file
if (!pDlg->load(sProjPath, *itr)) {
m_lstDialogs.remove(pDlg);
continue;
}
// Show the call tree
pDlg->show();
}
}
/**
* Creates a new Call Tree dialogue.
* @return The newly allocated dialogue object
*/
CallTreeDlg* CallTreeManager::addDialog()
{
CallTreeDlg* pDlg;
// Create a modeless call tree dialogue
pDlg = new CallTreeDlg();
m_lstDialogs.append(pDlg);
// Open an editor whenever a function name is double-clicked
connect(pDlg, SIGNAL(lineRequested(const QString&, uint)),
this, SIGNAL(lineRequested(const QString&, uint)));
// Track the closing of the call tree dialog
connect(pDlg, SIGNAL(closed(const CallTreeDlg*)), this,
SLOT(slotRemoveDialog(const CallTreeDlg*)));
return pDlg;
}
/**
* Closes all Call Tree dialogues.
*/
void CallTreeManager::closeAll()
{
m_lstDialogs.clear();
}
/**
* Removes a Call Tree dialogue from the list of open Call Trees.
* This slot is connected to the closed() signal emitted by the dialogue.
* @param pDlg The dialogue to remove from the list
*/
void CallTreeManager::slotRemoveDialog(const CallTreeDlg* pDlg)
{
m_lstDialogs.remove(pDlg);
}
#include "calltreemanager.moc"

@ -0,0 +1,71 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef CALLTREEMANAGER_H
#define CALLTREEMANAGER_H
#include <qwidget.h>
#include <qptrlist.h>
class CallTreeDlg;
/**
* Manages all call tree dialogs within the project.
* Responsible for saving/loading of the call tree dialogs.
* @author Albert Yosher
*/
class CallTreeManager : public QObject
{
Q_OBJECT
public:
CallTreeManager(QWidget*);
~CallTreeManager();
void saveOpenDialogs(const QString&, QStringList&);
void loadOpenDialogs(const QString&, const QStringList&);
CallTreeDlg* addDialog();
void closeAll();
signals:
/**
* Emitted when any call tree dialogue sends a request to view a location
* in the source code.
* @param sPath The full path of the file to show
* @param nLine The line number in this file
*/
void lineRequested(const QString& sPath, uint nLine);
private:
/** The list of open call tree dialogues. */
QPtrList<CallTreeDlg> m_lstDialogs;
private slots:
void slotRemoveDialog(const CallTreeDlg*);
};
#endif

@ -0,0 +1,172 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <kstandarddirs.h>
#include "configfrontend.h"
/**
* Class constructor.
* @param bAutoDelete True to destroy the object when the process ends,
* false otherwise
*/
ConfigFrontend::ConfigFrontend(bool bAutoDelete) :
Frontend(1, bAutoDelete)
{
}
/**
* Class destructor.
*/
ConfigFrontend::~ConfigFrontend()
{
}
/**
* Executes the script using the "sh" shell.
* @param sCscopePath If given, overrides the automatic check for Cscope's
* path
* @param sCtagsPath If given, overrides the automatic check for Ctags'
* path
* @param sDotPath If given, overrides the automatic check for Dot's
* path
* @param bCscopeOptsOnly Only verify cscope's path and options
* @return true if successful, false otherwise
*/
bool ConfigFrontend::run(const QString& sCscopePath,
const QString& sCtagsPath, const QString& sDotPath,
bool bCscopeOptsOnly)
{
QStringList slArgs;
KStandardDirs sd;
QString sScript;
// Execute using the user's shell
setUseShell(true);
// Find the configuration script
sScript = sd.findResource("data", "kscope/kscope_config");
if (sScript.isEmpty())
return false;
// Set command line arguments
slArgs.append("sh");
slArgs.append(sScript);
if (bCscopeOptsOnly)
slArgs.append("-co");
// Initialise environment
setEnvironment("CSCOPE_PATH", sCscopePath);
setEnvironment("CTAGS_PATH", sCtagsPath);
setEnvironment("DOT_PATH", sDotPath);
// Parser initialisation
m_delim = Newline;
m_nNextResult = CscopePath;
if (!Frontend::run("sh", slArgs))
return false;
emit test(CscopePath);
return true;
}
/**
* Handles tokens generated by the script.
* Each token represents a line in the script's output, and is the result of
* a different test.
* @param sToken The generated token
*/
Frontend::ParseResult ConfigFrontend::parseStdout(QString& sToken,
ParserDelim)
{
uint nResult;
// Store the type of test for which the given token in the result
nResult = m_nNextResult;
// Determine the next test
switch (m_nNextResult) {
case CscopePath:
if (sToken == "ERROR")
m_nNextResult = CtagsPath;
else
m_nNextResult = CscopeVersion;
break;
case CscopeVersion:
if (sToken == "ERROR")
m_nNextResult = CtagsPath;
else
m_nNextResult = CscopeVerbose;
break;
case CscopeVerbose:
m_nNextResult = CscopeSlowPath;
break;
case CscopeSlowPath:
m_nNextResult = CtagsPath;
break;
case CtagsPath:
if (sToken == "ERROR")
m_nNextResult = END;
else
m_nNextResult = CtagsExub;
break;
case CtagsExub:
if (sToken == "ERROR")
m_nNextResult = END;
else
m_nNextResult = DotPath;
break;
case DotPath:
if (sToken == "ERROR")
m_nNextResult = END;
else
m_nNextResult = DotPlain;
break;
case DotPlain:
m_nNextResult = END;
break;
case END:
return DiscardToken;
}
// Publish the result and the type of the next test
emit result(nResult, sToken);
emit test(m_nNextResult);
return DiscardToken;
}
#include "configfrontend.moc"

@ -0,0 +1,77 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef CONFIGFRONTEND_H
#define CONFIGFRONTEND_H
#include <frontend.h>
/**
* Frontend to the kscope_config shell script.
* The script executes a set of tests and outputs their results.
* @author Elad Lahav
*/
class ConfigFrontend : public Frontend
{
Q_OBJECT
public:
ConfigFrontend(bool bAutoDelete = false);
~ConfigFrontend();
bool run(const QString&, const QString&, const QString&,
bool bCscopeOptsOnly = false);
/**
* The types of tests executed by the script.
*/
enum { CscopePath, CscopeVersion, CscopeVerbose, CscopeSlowPath,
CtagsPath, CtagsExub, DotPath, DotPlain, END };
signals:
/**
* Indicates that the script is now running a given test.
* @param nType The type of test being executed
*/
void test(uint nType);
/**
* Called after a test has produced a result.
* @param nType The type of test executed
* @param sResult The obtained result
*/
void result(uint nType, const QString& sResult);
protected:
virtual ParseResult parseStdout(QString&, ParserDelim);
private:
/** The type of test whose result is expected next. */
uint m_nNextResult;
};
#endif

@ -0,0 +1,524 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qfileinfo.h>
#include <qtimer.h>
#include <kconfig.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <kglobalsettings.h>
#include "cscopefrontend.h"
#include "kscopeconfig.h"
#include "configfrontend.h"
#define BUILD_STR "Building symbol database %d of %d"
#define SEARCH_STR "Search %d of %d"
#define INV_STR "Possible references retrieved %d of %d"
#define REGEXP_STR "Symbols matched %d of %d"
#define SEARCHEND_STR "%d lines"
QString CscopeFrontend::s_sProjPath;
uint CscopeFrontend::s_nProjArgs;
uint CscopeFrontend::s_nSupArgs;
/**
* Class constructor.
* @param bAutoDelete true to delete the object once the process has
* terminated, false otherwise
*/
CscopeFrontend::CscopeFrontend(bool bAutoDelete) :
Frontend(CSCOPE_RECORD_SIZE, bAutoDelete),
m_state(Unknown),
m_sErrMsg(""),
m_bRebuildOnExit(false)
{
}
/**
* Class destructor.
*/
CscopeFrontend::~CscopeFrontend()
{
}
/**
* Executes a Cscope process using the given command line arguments.
* The full path to the Cscope executable should be set in the "Path" key
* under the "Cscope" group.
* @param slArgs Command line arguments for Cscope
* @return true if successful, false otherwise
*/
bool CscopeFrontend::run(const QStringList& slArgs)
{
QStringList slCmdLine;
// Set the command line arguments
slCmdLine.append(Config().getCscopePath());
slCmdLine += slArgs;
// Use verbose mode, if supported
if (s_nSupArgs & VerboseOut)
slCmdLine << "-v";
// Project-specific options
if (s_nProjArgs & Kernel)
slCmdLine << "-k";
if (s_nProjArgs & InvIndex)
slCmdLine << "-q";
if (s_nProjArgs & NoCompression)
slCmdLine << "-c";
if (s_nProjArgs & s_nSupArgs & SlowPathDef)
slCmdLine << "-D";
// Run a new process
if (!Frontend::run("cscope", slCmdLine, s_sProjPath)) {
emit aborted();
return false;
}
return true;
}
/**
* Executes a Cscope query.
* A query is composed of a numeric type and a query text, which are written
* to the stndard input of the currently running Cscope process.
* @param nType The type of query to run
* @param sText The query's text
* @param bCase true for case-sensitive queries, false otherwise
* @param nMaxRecords The maximal number of records to return (abort if this
* number is exceeded)
*/
void CscopeFrontend::query(uint nType, const QString& sText, bool bCase,
uint nMaxRecords)
{
QString sQuery;
QStringList slArgs;
m_nMaxRecords = nMaxRecords;
// Create the Cscope command line
slArgs.append(QString("-L") + QString::number(nType));
slArgs.append(sText);
slArgs.append("-d");
if (!bCase)
slArgs.append("-C");
run(slArgs);
// Initialise stdout parsing
m_state = SearchSymbol;
m_delim = WSpace;
emit progress(0, 1);
}
/**
* Rebuilds the symbol database of the current project.
*/
void CscopeFrontend::rebuild()
{
QStringList slArgs;
// If a process is already running, kill it start a new one
if (isRunning()) {
m_bRebuildOnExit = true;
kill();
return;
}
// Run the database building process
slArgs.append("-b");
run(slArgs);
// Initialise output parsing
m_state = BuildStart;
m_delim = Newline;
emit progress(0, 1);
}
/**
* Sets default parameters for all CscopeFrontend projects based on the
* current project.
* @param sProjPath The full path of the project's directory
* @param nArgs Project-specific command-line arguments
*/
void CscopeFrontend::init(const QString& sProjPath, uint nArgs)
{
s_sProjPath = sProjPath;
s_nProjArgs = nArgs;
}
/**
* Stops a Cscope action.
*/
void CscopeFrontend::slotCancel()
{
kill();
}
/**
* Parses the output of a Cscope process.
* Implements a state machine, where states correspond to the output of the
* controlled Cscope process.
* @param sToken The current token read (the token delimiter is determined
* by the current state)
* @return A value indicating the way this token should be treated: dropped,
* added to the token queue, or finishes a new record
*/
Frontend::ParseResult CscopeFrontend::parseStdout(QString& sToken,
ParserDelim /* ignored */)
{
int nFiles, nTotal, nRecords;
ParseResult result = DiscardToken;
ParserState stPrev;
// Remember previous state
stPrev = m_state;
// Handle the token according to the current state
switch (m_state) {
case BuildStart:
if (sToken == "Building cross-reference...") {
m_state = BuildSymbol;
m_delim = WSpace;
}
else if (sToken == "Building inverted index...") {
emit buildInvIndex();
}
result = DiscardToken;
break;
case BuildSymbol:
// A single angle bracket is the prefix of a progress indication,
// while double brackets is Cscope's prompt for a new query
if (sToken == ">") {
m_state = Building;
m_delim = Newline;
}
result = DiscardToken;
break;
case Building:
// Try to get building progress
if (sscanf(sToken.latin1(), BUILD_STR, &nFiles, &nTotal) == 2) {
emit progress(nFiles, nTotal);
// Check for last progress message
if (nFiles == nTotal) {
m_state = BuildStart;
m_delim = Newline;
result = DiscardToken;
break;
}
}
// Wait for another progress line or the "ready" symbol
m_state = BuildSymbol;
m_delim = WSpace;
result = DiscardToken;
break;
case SearchSymbol:
// Check for more search progress, or the end of the search,
// designated by a line in the format of "cscope: X lines"
if (sToken == ">") {
m_state = Searching;
m_delim = Newline;
result = DiscardToken;
break;
}
else if (sToken == "cscope:") {
m_state = SearchEnd;
m_delim = Newline;
result = DiscardToken;
break;
}
case File:
// Is this the first entry? If so, signal that the query is complete
if (stPrev != LineText)
emit progress(1, 1);
// Treat the token as the name of the file in this record
m_state = Func;
result = AcceptToken;
break;
case Searching:
// Try to get the search progress value (ignore other messages)
if ((sscanf(sToken.latin1(), SEARCH_STR, &nFiles, &nTotal) == 2) ||
(sscanf(sToken.latin1(), INV_STR, &nFiles, &nTotal) == 2) ||
(sscanf(sToken.latin1(), REGEXP_STR, &nFiles, &nTotal) == 2)) {
emit progress(nFiles, nTotal);
}
m_state = SearchSymbol;
m_delim = WSpace;
result = DiscardToken;
break;
case SearchEnd:
// Get the number of results found in this search
if ((sscanf(sToken.latin1(), SEARCHEND_STR, &nRecords) == 1) &&
(m_nMaxRecords > 0) &&
(nRecords > m_nMaxRecords)) {
result = Abort;
}
else {
m_state = File;
m_delim = WSpace;
result = DiscardToken;
}
break;
case Func:
// Treat the token as the name of the function in this record
if (sToken.toInt()) {
// In case of a global definition, there is no function name, and
// instead the line number is given immediately
m_state = LineText;
m_delim = Newline;
}
else {
// Not a number, it is the name of the function
m_state = Line;
}
result = AcceptToken;
break;
case Line:
// Treat the token as the line number in this record
m_state = LineText;
m_delim = Newline;
result = AcceptToken;
break;
case LineText:
// Treat the token as the text of this record, and report a new
// record
m_state = File;
m_delim = WSpace;
result = RecordReady;
break;
default:
// Do nothing (prevents a compilation warning for unused enum values)
break;
}
return result;
}
/**
* Handles Cscope messages sent to the standard error stream.
* @param sText The error message text
*/
void CscopeFrontend::parseStderr(const QString& sText)
{
// Wait for a complete line to arrive
m_sErrMsg += sText;
if (!sText.endsWith("\n"))
return;
// Display the error message
emit error(m_sErrMsg);
// Line displayed, reset the text accumulator
m_sErrMsg = "";
}
/**
* Called when the underlying process exits.
* Checks if the rebuild flag was raised, and if so restarts the building
* process.
*/
void CscopeFrontend::finalize()
{
// Reset the parser state machine
m_state = Unknown;
// Restart the building process, if required
if (m_bRebuildOnExit) {
m_bRebuildOnExit = false;
rebuild();
}
}
/**
* Class constructor.
* @param pMainWidget The parent widget to use for the progress bar and
* label
*/
CscopeProgress::CscopeProgress(QWidget* pMainWidget) : QObject(),
m_pMainWidget(pMainWidget),
m_pProgressBar(NULL),
m_pLabel(NULL)
{
}
/**
* Class destructor.
*/
CscopeProgress::~CscopeProgress()
{
}
/**
* Displays query progress information.
* If the progress value is below the expected final value, a progress bar is
* used to show the advance of the query process. Otherwise, a label is
* displayed asking the user to wait ahile the query output is processed.
* @param nProgress The current progress value
* @param nTotal The expected final value
*/
void CscopeProgress::setProgress(int nProgress, int nTotal)
{
// Was the final value is reached?
if (nProgress == nTotal) {
// Destroy the progress bar
if (m_pProgressBar != NULL) {
delete m_pProgressBar;
m_pProgressBar = NULL;
}
// Show the "Please wait..." label
if (m_pLabel == NULL) {
m_pLabel = new QLabel(i18n("Processing query results, "
"please wait..."), m_pMainWidget);
m_pLabel->setFrameStyle(QFrame::Box | QFrame::Plain);
m_pLabel->setLineWidth(1);
m_pLabel->adjustSize();
m_pLabel->setPaletteBackgroundColor(
KGlobalSettings::highlightColor());
m_pLabel->setPaletteForegroundColor(
KGlobalSettings::highlightedTextColor());
QTimer::singleShot(1000, this, SLOT(slotShowLabel()));
}
return;
}
// Create the progress bar, if it does not exist.
// Note that the progress bar will only be displayed one second after the
// first progress signal is received. Thus the bar will not be displayed
// on very short queries.
if (m_pProgressBar == NULL) {
m_pProgressBar = new QProgressBar(m_pMainWidget);
QTimer::singleShot(1000, this, SLOT(slotShowProgressBar()));
}
// Set the current progress value
m_pProgressBar->setProgress(nProgress, nTotal);
}
/**
* detsroys any progress widgets when the process is terminated.
*/
void CscopeProgress::finished()
{
// Destroy the progress bar
if (m_pProgressBar != NULL) {
delete m_pProgressBar;
m_pProgressBar = NULL;
}
// Destroy the label
if (m_pLabel != NULL) {
delete m_pLabel;
m_pLabel = NULL;
}
}
/**
* Shows the progress bar.
* This slot is connected to a timer activated when the first progress signal
* is received.
*/
void CscopeProgress::slotShowProgressBar()
{
if (m_pProgressBar != NULL)
m_pProgressBar->show();
}
/**
* Shows the "Please wait...".
* This slot is connected to a timer activated when the progress bar
* reaches its final value.
*/
void CscopeProgress::slotShowLabel()
{
if (m_pLabel != NULL)
m_pLabel->show();
}
void CscopeVerifier::verify()
{
ConfigFrontend* pConf;
pConf = new ConfigFrontend(true);
connect(pConf, SIGNAL(result(uint, const QString&)), this,
SLOT(slotConfigResult(uint, const QString&)));
connect(pConf, SIGNAL(finished(uint)), this, SLOT(slotFinished()));
pConf->run(Config().getCscopePath(), "", "", true);
}
void CscopeVerifier::slotConfigResult(uint nType, const QString& sResult)
{
switch (nType) {
case ConfigFrontend::CscopeVerbose:
if (sResult == "Yes")
m_nArgs |= CscopeFrontend::VerboseOut;
break;
case ConfigFrontend::CscopeSlowPath:
if (sResult == "Yes")
m_nArgs |= CscopeFrontend::SlowPathDef;
// If we got this far, then Cscope is configured properly
m_bResult = true;
break;
}
}
void CscopeVerifier::slotFinished()
{
emit done(m_bResult, m_nArgs);
delete this;
}
#include "cscopefrontend.moc"

@ -0,0 +1,186 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef CSCOPEFRONTEND_H
#define CSCOPEFRONTEND_H
#include <qstringlist.h>
#include <qprogressbar.h>
#include <qlabel.h>
#include "frontend.h"
#define CSCOPE_RECORD_SIZE 4
/**
* Controls a Cscope process for the current project.
* This class creates a Cscope process, using the project's files for
* configuration. Once the process is running, KScope uses the query() method
* to initiate Cscope queries on the project's files. The queries' output is
* parsed into a set of records, each consisting of the following fields:
* - File name
* - Function name
* - Line number
* - The line's text
* These records are used to display the output in different windows, such as
* QueryWidget and CallTreeDlg.
* @author Elad Lahav
*/
class CscopeFrontend : public Frontend
{
Q_OBJECT
public:
CscopeFrontend(bool bAutoDelete = false);
~CscopeFrontend();
/**
* The available Cscope query types.
*/
enum QueryType { Reference = 0, Definition = 1, Called = 2, Calling = 3,
Text = 4, Pattern = 6, FileName = 7, Including = 8, None = 9 };
/**
* Options for running Cscope, used to construct the command line.
* Some of these options are global, while some are project specific.
*/
enum Options { VerboseOut = 0x01, SlowPathDef = 0x02,
Kernel = 0x04, InvIndex = 0x08, NoCompression = 0x10 };
void query(uint, const QString&, bool bCase = true, uint nMaxRecords = 0);
void rebuild();
static void init(const QString&, uint);
/**
* @param nArgs The command-line arguments supported by the version of
* Cscope currently in use
*/
static void setSupArgs(uint nArgs) { s_nSupArgs = nArgs; }
public slots:
void slotCancel();
signals:
/**
* Emitted when Cscope starts building the inverted index.
*/
void buildInvIndex();
protected:
virtual ParseResult parseStdout(QString&, ParserDelim);
virtual void parseStderr(const QString&);
virtual void finalize();
private:
/**
* The possible states of the parser state machine.
*/
enum ParserState { Unknown = 0, BuildStart, BuildSymbol, Building,
SearchSymbol, Searching, SearchEnd, File, Func, Line, LineText };
/** The current state of the parser state machine. */
ParserState m_state;
/** Accumulates text sent by Cscope to the standard error stream. */
QString m_sErrMsg;
/** If true, the rebuild process will be restarted when the process
exits. */
bool m_bRebuildOnExit;
/** The maximal number of records requested for the current query.
The process aborts if this number if reached. */
int m_nMaxRecords;
/** The full path of the directory holding the project files. */
static QString s_sProjPath;
/** Project-specific options for the command-line arguments. */
static uint s_nProjArgs;
/** The command line arguments supported by this version of Cscope. */
static uint s_nSupArgs;
bool run(const QStringList&);
};
/**
* Provides progress information on a Cscope query.
* Classes used to display query results can use this class to show a
* progress bar while a query is running, and a "Please Wait..." label while
* output is being processed.
* @author Elad Lahav
*/
class CscopeProgress : public QObject
{
Q_OBJECT
public:
CscopeProgress(QWidget*);
~CscopeProgress();
void setProgress(int, int);
void finished();
private:
/** The parent widget for the progress bar and label. */
QWidget* m_pMainWidget;
/** A bar used to display query progress information. */
QProgressBar* m_pProgressBar;
/** A label used to display a "Please wait..." message. */
QLabel* m_pLabel;
private slots:
void slotShowProgressBar();
void slotShowLabel();
};
class CscopeVerifier : public QObject
{
Q_OBJECT
public:
CscopeVerifier() : m_bResult(false), m_nArgs(0) {}
void verify();
signals:
void done(bool, uint);
private:
bool m_bResult;
uint m_nArgs;
private slots:
void slotConfigResult(uint, const QString&);
void slotFinished();
};
#endif

@ -0,0 +1,66 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qtextedit.h>
#include <qpushbutton.h>
#include "cscopemsgdlg.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
CscopeMsgDlg::CscopeMsgDlg(QWidget* pParent, const char* szName)
: CscopeMsgLayout(pParent, szName, false, 0)
{
// Hide the dialog when the "Hide" button is clicked
connect(m_pHideButton, SIGNAL(clicked()), this, SLOT(hide()));
// Clear all messages when the "Clear" button is clicked
connect(m_pClearButton, SIGNAL(clicked()), m_pMsgText, SLOT(clear()));
}
/**
* Class destructor.
*/
CscopeMsgDlg::~CscopeMsgDlg()
{
}
/**
* Appends a given message to the text box.
* After a new messsage is added, the dialog becomes visible.
* @param sText The text of the message to add
*/
void CscopeMsgDlg::addText(const QString& sText)
{
m_pMsgText->append(sText);
show();
}
#include "cscopemsgdlg.moc"

@ -0,0 +1,49 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef CSCOPEMSGDLG_H
#define CSCOPEMSGDLG_H
#include "cscopemsglayout.h"
/**
* Displays messages sent by Cscope to its standard error stream.
* @author Elad Lahav
*/
class CscopeMsgDlg : public CscopeMsgLayout
{
Q_OBJECT
public:
CscopeMsgDlg(QWidget* pParent = 0, const char* szName = 0);
~CscopeMsgDlg();
void addText(const QString&);
};
#endif

@ -0,0 +1,79 @@
<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
<class>CscopeMsgLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>CscopeMsgLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>451</height>
</rect>
</property>
<property name="caption">
<string>Cscope Error Messages</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QTextEdit">
<property name="name">
<cstring>m_pMsgText</cstring>
</property>
<property name="textFormat">
<enum>PlainText</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout1</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer1</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>321</width>
<height>31</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pClearButton</cstring>
</property>
<property name="text">
<string>Clear</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pHideButton</cstring>
</property>
<property name="text">
<string>Hide</string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<layoutdefaults spacing="6" margin="11"/>
</UI>

@ -0,0 +1,179 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qfileinfo.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <kshell.h>
#include "ctagsfrontend.h"
#include "kscopeconfig.h"
QStringList CtagsFrontend::s_slExtraArgs;
/**
* Class constructor.
*/
CtagsFrontend::CtagsFrontend() : Frontend(CTAGS_RECORD_SIZE)
{
}
/**
* Class destructor.
*/
CtagsFrontend::~CtagsFrontend()
{
}
/**
* Executes a Ctags process on a source file.
* @param sFileName The full path to the source file
* @return true if successful, false otherwise
*/
bool CtagsFrontend::run(const QString& sFileName)
{
QString sPath;
QStringList slArgs;
// Make sure the executable exists
sPath = Config().getCtagsPath();
// Set the command line arguments
slArgs.append(sPath);
slArgs.append("--excmd=n");
slArgs.append("-u"); // don't sort
slArgs.append("-f");
slArgs.append("-");
// Per-project command-line arguments
slArgs += s_slExtraArgs;
slArgs.append(sFileName);
// Run a new process
if (!Frontend::run("ctags", slArgs))
return false;
// Initialize stdout parsing
m_state = Name;
m_delim = Tab;
return true;
}
/**
* Tests that the given file path leads to an executable.
* @param sPath The path to check
* @return true if the file in the given path exists and has executable
* permissions, false otherwise
*/
bool CtagsFrontend::verify(const QString& sPath)
{
QFileInfo fi(sPath);
if (!fi.exists() || !fi.isFile() || !fi.isExecutable() ||
fi.fileName().find("ctags", 0, false) == -1) {
KMessageBox::error(0, i18n("Ctags cannot be found in the given "
"path"));
return false;
}
return true;
}
/**
* Turns the per-project string of additional arguments into a list of
* command-line arguments.
* @param sArgs The per-project command string
*/
void CtagsFrontend::setExtraArgs(const QString& sArgs)
{
s_slExtraArgs = KShell::splitArgs(sArgs);
}
/**
* Parses the output of a Ctags process.
* @param sToken The current token read (the token delimiter is determined
* by the current state)
* @param delim The delimiter that ends this token
* @return A value indicating the way this token should be treated: dropped,
* added to the token queue, or finishes a new record
*/
Frontend::ParseResult CtagsFrontend::parseStdout(QString& sToken,
ParserDelim delim)
{
ParseResult result = DiscardToken;
// Handle the token according to the current state
switch (m_state) {
case Name:
if (sToken.left(6) == "ctags:") {
m_state = Other;
m_delim = Newline;
break;
}
m_state = File;
result = AcceptToken;
break;
case File:
m_state = Line;
result = DiscardToken;
break;
case Line:
sToken = sToken.left(sToken.length() - 2);
m_state = Type;
m_delim = All;
result = AcceptToken;
break;
case Type:
if (delim == Newline) {
m_state = Name;
m_delim = Tab;
}
else {
m_state = Other;
m_delim = Newline;
}
result = RecordReady;
break;
case Other:
m_state = Name;
m_delim = Tab;
result = DiscardToken;
break;
}
return result;
}
#include "ctagsfrontend.moc"

@ -0,0 +1,77 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef CTAGSFRONTEND_H
#define CTAGSFRONTEND_H
#include <frontend.h>
#define CTAGS_RECORD_SIZE 3
/**
* Controls a Ctags process for an file in an EditorPage window.
* A new Ctags process is run each time the file in the editor window is
* loaded (including the initial load, and any subsequent ones which follow a
* 'save' operation.)
* The output of the process is parsed into a set of records, each composed of
* the following fields:
* - Tag type
* - Tag name
* - Line number
* The records are then displayed in the CtagsList widget that is attached to
* each EditorPage window.
* @author Elad Lahav
*/
class CtagsFrontend : public Frontend
{
Q_OBJECT
public:
CtagsFrontend();
~CtagsFrontend();
bool run(const QString&);
static bool verify(const QString&);
static void setExtraArgs(const QString&);
protected:
virtual ParseResult parseStdout(QString&, ParserDelim);
private:
/** State values for the parser state machine. */
enum ParserState { Name = 0, File, Line, Type, Other };
/** The current state of the parser state machine. */
ParserState m_state;
/** Additional ommand-line arguments (per-project). */
static QStringList s_slExtraArgs;
};
#endif

@ -0,0 +1,446 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qheader.h>
#include <klocale.h>
#include "ctagslist.h"
#include "kscopeconfig.h"
#include "kscopepixmaps.h"
/**
* Defines a special list item for the tag list.
* This special definition allows the tag list to be sorted according to
* symbol line numbers. By default, all items are treated as text, hence the
* comparison of line numbers such as "123" and "24" sets "24" to be the
* larger item. By overriding the comparison function, this class allows for
* correct sorting.
* @author Elad Lahav
*/
class CtagsListItem : public QListViewItem
{
public:
/**
* Class constructor.
* @param pParent The owning list view widget
* @param sName The name of the tag
* @param sLine The line in which the tag is defined
* @param sType The type of the tag
*/
CtagsListItem(QListView* pParent, QString sName, QString sLine,
QString sType) : QListViewItem(pParent, sName, sLine, sType),
m_nPendLine (sLine.toUInt()) {}
/**
* Compares two tag list items, and determines their order.
* If comparison is based on a text-column, the default behaviour is
* used. Otherwise, the text is converted to unsigned integers, and then
* compared as numbers.
* @param pItem The item to compare against the local object
* @param nCol The column index by which to compare
* @param bAscend true if sorting in ascending order, false otherwise
* @return 0 if the items are equal, 1 if the local item is greater, -1
* if the local item is lesser
*/
virtual int compare(QListViewItem* pItem, int nCol, bool bAscend) const {
if (nCol == 1) {
uint nLineCur, nLineOther;
int nResult;
// Get the line numbers of each item
nLineCur = text(1).toUInt();
nLineOther = pItem->text(1).toUInt();
// Compare the line numbers
nResult = nLineCur - nLineOther;
if (nResult == 0)
return 0; // Items are equal
else if (nResult > 0)
return 1; // The first item is greater
else
return -1; // The second item is greater
}
// Use default comparison for text columns
return QListViewItem::compare(pItem, nCol, bAscend);
}
/**
* @return The line number associated with this item
*/
inline uint getLine() { return m_nPendLine; }
private:
/** The numeric value of the line number column of this item. */
uint m_nPendLine;
};
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
CtagsList::CtagsList(QWidget* pParent, const char* szName) :
SearchList(0, pParent, szName),
m_arrLines(16),
m_nItems(0),
m_nCurItem(0),
m_bReady(false),
m_nCurLine(0),
m_nPendLine(0)
{
m_pList->setShowSortIndicator(true);
connect(m_pList->header(), SIGNAL(clicked(int)), this,
SLOT(slotSortChanged(int)));
// Determine the default sorting order
switch (Config().getCtagSortOrder()) {
case KScopeConfig::NameAsc:
m_pList->setSorting(0, true);
break;
case KScopeConfig::NameDes:
m_pList->setSorting(0, false);
break;
case KScopeConfig::LineAsc:
m_pList->setSorting(1, true);
break;
case KScopeConfig::LineDes:
m_pList->setSorting(1, false);
break;
case KScopeConfig::TypeAsc:
m_pList->setSorting(2, true);
break;
case KScopeConfig::TypeDes:
m_pList->setSorting(2, false);
break;
}
// Add the list columns
m_pList->addColumn(i18n("Name"));
m_pList->addColumn(i18n("Line"));
m_pList->addColumn(i18n("Type"));
m_pList->setColumnAlignment(1, Qt::AlignRight);
// Set colours and font
applyPrefs();
}
/**
* Class destructor.
*/
CtagsList::~CtagsList()
{
}
/**
* Adds a Ctags output entry to the list.
* This slot is connected to the dataReady() signal of a CtagsFrontend object.
* @param pToken The first token in the entry
*/
void CtagsList::slotDataReady(FrontendToken* pToken)
{
QString sName, sType, sLine;
CtagsListItem* pItem;
KScopePixmaps::PixName pix;
// Get the name of the symbol
sName = pToken->getData();
pToken = pToken->getNext();
// Get the line number
sLine = pToken->getData();
pToken = pToken->getNext();
// Get the type of the symbol
sType = pToken->getData();
pToken = pToken->getNext();
// Set the appropriate pixmap
switch (sType[0].latin1()) {
case 'f':
sType = i18n("Function");
pix = KScopePixmaps::SymFunc;
break;
case 'v':
sType = i18n("Variable");
pix = KScopePixmaps::SymVar;
break;
case 's':
sType = i18n("Struct");
pix = KScopePixmaps::SymStruct;
break;
case 'd':
sType = i18n("Macro");
pix = KScopePixmaps::SymMacro;
break;
case 'm':
sType = i18n("Member");
pix = KScopePixmaps::SymMember;
break;
case 'g':
sType = i18n("Enum");
pix = KScopePixmaps::SymEnum;
break;
case 'e':
sType = i18n("Enumerator");
pix = KScopePixmaps::SymEnumerator;
break;
case 't':
sType = i18n("Typedef");
pix = KScopePixmaps::SymTypedef;
break;
case 'l':
sType = i18n("Label");
pix = KScopePixmaps::SymLabel;
break;
case 'i':
sType = i18n("Include");
pix = KScopePixmaps::SymInclude;
break;
default:
sType = "Unknown";
pix = KScopePixmaps::SymUnknown;
}
// Add a new item to the list
pItem = new CtagsListItem(m_pList, sName, sLine, sType);
pItem->setPixmap(0, Pixmaps().getPixmap(pix));
m_nItems++;
// Resize the line array, if required
if (m_arrLines.size() < m_nItems)
m_arrLines.resize(m_nItems, QGArray::SpeedOptim);
// Add the new item to the line array
m_arrLines[m_nItems - 1] = pItem;
}
/**
* Handles the "resize" event, which occurs when the size of the widget
* changes.
* @param pEvent The event data
*/
void CtagsList::resizeEvent(QResizeEvent* pEvent)
{
SearchList::resizeEvent(pEvent);
emit resized();
}
/**
* Emits the lineRequested() signal when a list item is selected.
* This function is called if either an item is double-clicked, or an item is
* highlighted and the ENTER key is pressed.
* @param pItem The selected list item
*/
void CtagsList::processItemSelected(QListViewItem* pItem)
{
QString sLine;
sLine = pItem->text(1);
emit lineRequested(sLine.toUInt());
}
/**
* Constructs a tool-tip for the given item.
* @param pItem The item for which a tip is required
* @param sTip The constructed tip string (on return)
* @return Always true
*/
bool CtagsList::getTip(QListViewItem* pItem, QString& sTip)
{
sTip = QString("Type: <b>%1</b><br>Name: <b>%2</b><br>Line: <b>%3</b>").
arg(pItem->text(2)).arg(pItem->text(0)).arg(pItem->text(1));
return true;
}
/**
* Sets the list's colours and font, according the user's preferences.
*/
void CtagsList::applyPrefs()
{
// Apply colour settings
m_pList->setPaletteBackgroundColor(Config().getColor(
KScopeConfig::TagListBack));
m_pList->setPaletteForegroundColor(Config().getColor(
KScopeConfig::TagListFore));
m_pList->setFont(Config().getFont(KScopeConfig::TagList));
}
/**
* Selects the symbol that dominates the given line in the source file.
* @param nLine The requested line
*/
void CtagsList::gotoLine(uint nLine)
{
CtagsListItem* pItem;
int nFrom, nTo, nItem, nDiff;
// Wait until Ctags finishes
if (!m_bReady) {
m_nPendLine = nLine;
return;
}
// Do nothing if no tags are available
if (m_nItems == 0)
return;
// Calculate the difference from the current line
nDiff = (int)(nLine - m_nCurLine);
m_nCurLine = nLine;
// In most cases, all the user does is move to the next or prevuious lines
// Handle these simple cases first
if (nDiff == 1) {
if ((m_nCurItem < m_nItems - 1) &&
(m_arrLines[m_nCurItem + 1]->getLine() == nLine)) {
m_nCurItem++;
}
else {
return; // New line corresponds to the same tag
}
}
else if (nDiff == -1) {
if ((m_nCurItem > 0) &&
(m_arrLines[m_nCurItem]->getLine() > nLine)) {
m_nCurItem--;
}
else {
return; // New line corresponds to the same tag
}
}
else {
// Initialise binary search
nFrom = 0;
nTo = m_nItems - 1;
m_nCurItem = 0; // use the first item if nothing else works
// Perform a binary search
// This algorithm finds the greatest line that is smaller or equal to
// the requested line
do {
nItem = (nFrom + nTo) / 2;
pItem = m_arrLines[nItem];
if (pItem->getLine() == nLine) {
m_nCurItem = nItem;
break;
}
else if (nLine > pItem->getLine()) {
m_nCurItem = nItem;
nFrom = nItem + 1;
}
else {
nTo = nItem - 1;
}
} while (nFrom <= nTo);
}
// Mark the selected item
pItem = m_arrLines[m_nCurItem];
m_pList->setSelected(pItem, true);
m_pList->ensureItemVisible(pItem);
m_nPendLine = 0;
}
/**
* Deletes all items in the list.
*/
void CtagsList::clear()
{
m_pList->clear();
m_nItems = 0;
m_nCurItem = 0;
m_nCurLine = 0;
m_nPendLine = 0;
m_bReady = false;
}
/**
* Indicates Ctags has finished processing the current file.
* If a goto operation has been scheduled, it is processed.
* @param nRecords The number of records generated by Ctags
*/
void CtagsList::slotCtagsFinished(uint nRecords)
{
if (nRecords) {
m_bReady = true;
if (m_nPendLine)
gotoLine(m_nPendLine);
}
}
/**
* Determines the new sort order in the tags list.
* This slot is connected to the clicked() signal of the tag list's header.
* @param nSection Identifies the column whose header button was clicked.
*/
void CtagsList::slotSortChanged(int nSection)
{
Qt::SortOrder order;
// Determine whether the new order is ascending or descending
order = m_pList->sortOrder();
// Translate the section number into the order constant
switch (nSection) {
case 0:
// Sort by name
Config().setCtagSortOrder(order == Qt::Ascending ?
KScopeConfig::NameAsc : KScopeConfig::NameDes);
break;
case 1:
// Sort by line
Config().setCtagSortOrder(order == Qt::Ascending ?
KScopeConfig::LineAsc : KScopeConfig::LineDes);
break;
case 2:
// Sort by type
Config().setCtagSortOrder(order == Qt::Ascending ?
KScopeConfig::TypeAsc : KScopeConfig::TypeDes);
break;
}
}
#include "ctagslist.moc"

@ -0,0 +1,108 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef CTAGSLIST_H
#define CTAGSLIST_H
#include <qwidget.h>
#include <qpixmap.h>
#include <qmemarray.h>
#include "searchlist.h"
#include "frontend.h"
class CtagsListItem;
class CtagsToolTip;
/**
* Displays a list of tags for a source file.
* The list is embedded inside an editor page. Whenever a new document is
* opened in that editor, or the current document is changed and saved, the
* source file is re-scanned for tags, and the results are displayed in this
* list.
* @author Elad Lahav
*/
class CtagsList : public SearchList
{
Q_OBJECT
public:
CtagsList(QWidget* pParent = 0, const char* szName = 0);
~CtagsList();
void applyPrefs();
void gotoLine(uint);
void clear();
virtual bool getTip(QListViewItem*, QString&);
public slots:
void slotDataReady(FrontendToken*);
void slotCtagsFinished(uint);
signals:
/**
* Emitted when the size of the list is changed (usually as the result
* of moving the separator between the list and the editor.)
*/
void resized();
/**
* Emitted when the user selects a tag item from the list.
* @param nLine The line number associated with the selected tag
*/
void lineRequested(uint nLine);
protected:
virtual void resizeEvent(QResizeEvent*);
virtual void processItemSelected(QListViewItem*);
private:
/** An array of pointers to the tag list items, sorted by the line
number. */
QMemArray<CtagsListItem*> m_arrLines;
/** The number of items in the tag list. */
uint m_nItems;
/** The last item selected by gotoLine(). */
uint m_nCurItem;
/** This value is set to 'false' while the Ctags process is running. */
bool m_bReady;
/** The current line number. */
uint m_nCurLine;
/** Stores the requested line number during Ctags operation. */
uint m_nPendLine;
private slots:
void slotSortChanged(int);
};
#endif

@ -0,0 +1,164 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qapplication.h>
#include "dirscanner.h"
/**
* Class constructor.
* @param nFiles The number of files scanned since the previous event
* @param bFinished true if all files were scanned, false otherwise
*/
DirScanEvent::DirScanEvent(int nFiles, bool bFinished)
: QCustomEvent(EventId),
m_nFiles(nFiles),
m_bFinished(bFinished)
{
}
/**
* Class constructor.
* @param pEventReceiver Pointer to an object to receive DirScanEvent
* updates
* @param pDicFiles Pointer to a map of current project files (to
avoid duplication)
*/
DirScanner::DirScanner(QObject* pEventReceiver,
QDict<QListViewItem>* pDicFiles) : QThread(),
m_pEventReceiver(pEventReceiver),
m_pDicFiles(pDicFiles)
{
}
/**
* Class destructor.
*/
DirScanner::~DirScanner()
{
}
/**
* Begins a new search for source files.
* Invokes the search thread on a given directory. The search may be either
* recursive (i.e., the search will descend to each sub-directory) or flat
* (will search the given directory only.)
* @param sDir The name of the directory to search
* @param sNameFilter Defines the search pattern
* @param bRecursive true to descend into sub-dorectories, false otherwise
*/
void DirScanner::start(const QString& sDir, const QString& sNameFilter,
bool bRecursive)
{
// Initialise the search parameters
m_dir = QDir(sDir);
m_sNameFilter = sNameFilter;
m_bCancel = false;
m_bRecursive = bRecursive;
m_slFiles.clear();
// Invoke the thread
QThread::start();
}
/**
* Begins a scan of files on the directory associated with this object.
* Note that this function is synchronous: it returns when the scan ends.
*/
void DirScanner::run()
{
int nFiles;
nFiles = scanDir(m_dir);
QApplication::postEvent(m_pEventReceiver,
new DirScanEvent(nFiles, true));
m_setScanned.clear();
}
/**
* Recursively scans a directory for a files matching the current filter.
* @param dir A directory object set to the folder from which files are
* added
* @return The total number of files added
*/
int DirScanner::scanDir(QDir& dir)
{
QString sCanon;
QStringList slDirFiles, slDirs;
QStringList::const_iterator itr;
QString sFile;
int nFiles = 0;
if (m_bCancel)
return -1;
// Make sure this directory has not been previously visited (e.g., through a
// symbolic link)
sCanon = dir.canonicalPath();
if (m_setScanned.exists(sCanon))
return 0;
m_setScanned.insert(sCanon);
// Add all files in this directory
slDirFiles = dir.entryList(m_sNameFilter, QDir::Files);
for (itr = slDirFiles.begin(); itr != slDirFiles.end(); ++itr) {
sFile = dir.absPath() + "/" + *itr;
// Make sure an entry for this file does not exist
if (m_pDicFiles->find(sFile) == NULL) {
m_slFiles.append(sFile);
nFiles++;
}
}
QApplication::postEvent(m_pEventReceiver,
new DirScanEvent(nFiles, false));
// Recurse into sub-directories, if requested
if (!m_bRecursive)
return nFiles;
slDirs = dir.entryList(QDir::Dirs);
// Iterate the list of sub-directories
for (itr = slDirs.begin(); itr != slDirs.end(); ++itr) {
if (m_bCancel)
return -1;
// Skip the "." and ".." directories
if (*itr == "." || *itr == "..")
continue;
// Add the files in each sub-directory
QDir dirSub(dir);
if (dirSub.cd(*itr))
nFiles += scanDir(dirSub);
}
return nFiles;
}

@ -0,0 +1,144 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef DIRSCANNER_H
#define DIRSCANNER_H
#include <qobject.h>
#include <qevent.h>
#include <qthread.h>
#include <qdir.h>
#include <qstringlist.h>
#include <qdict.h>
#include <qlistview.h>
class DirScanner;
/**
* Defines a new event that can be used to pass progress information from the
* dir scanning thread to the main application thread.
* @author Elad Lahav
*/
class DirScanEvent : public QCustomEvent
{
public:
/** The event's unique ID. */
enum { EventId = 6924 };
DirScanEvent(int, bool);
/** The number of files already scanned. */
int m_nFiles;
/** True if the dir scanning thread has finished, false otherwise. */
bool m_bFinished;
};
/**
* A set of unique strings.
* Qt3 does not have a set class, so this is a simple implementation based on
* a QDict of dummy int pointers.
* @author Elad Lahav
*/
class StringSet : public QDict<int>
{
public:
StringSet() : QDict<int>() {}
void insert(const QString& sItem) {
static int nDummy = 0;
QDict<int>::insert(sItem, &nDummy);
}
bool exists(const QString& sItem) {
return find(sItem) != NULL;
}
};
/**
* Scans a directory for files matching a given pattern, using a separate thread.
* @author Elad Lahav
*/
class DirScanner : public QThread
{
public:
DirScanner(QObject*, QDict<QListViewItem>*);
~DirScanner();
void start(const QString&, const QString&, bool);
/**
* @return The list of files scanned by this thread.
*/
const QStringList& getFiles() { return m_slFiles; }
/**
* Stops a scanning process, by setting the object's cancel flag.
*/
void cancel() { m_bCancel = true; }
/**
* @return true if the user has cancelled the process, false otherwise
*/
bool wasCancelled() { return m_bCancel; }
protected:
virtual void run();
private:
/** Pointer to an object that receives the scanner update events. */
QObject* m_pEventReceiver;
/** Currently scanned directory. */
QDir m_dir;
/**
* A set of already-scanned directories (prevents infinite loops in case
* of cyclic symbolic links in the scanned file system).
*/
StringSet m_setScanned;
/** Pointer to a list of files indexed by the file path (used to identify
files that should not appear in the scan results.) */
QDict<QListViewItem>* m_pDicFiles;
/** Regular expression for scanning source files. */
QString m_sNameFilter;
/** The list of scanned file paths. */
QStringList m_slFiles;
/** A cancellation flag. Stops the scanning process when raised. */
bool m_bCancel;
/** true to descend to child directories, false otherwise. */
bool m_bRecursive;
int scanDir(QDir&);
};
#endif

@ -0,0 +1,297 @@
/***************************************************************************
*
* Copyright (C) 2006 Elad Lahav (elad_lahav@users.sf.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qfileinfo.h>
#include <qpaintdevicemetrics.h>
#include <kmessagebox.h>
#include <klocale.h>
#include "dotfrontend.h"
#include "graphwidget.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pGraph The graph widget on which to draw the output
*/
DotFrontend::DotFrontend(GraphWidget* pGraph) : Frontend(1),
m_pGraph(pGraph)
{
}
/**
* Class destructor.
*/
DotFrontend::~DotFrontend()
{
}
/**
* Executes dot on the goven input file.
* @param sFile The path to a temporary file holding the graph's
* description
* @return true if successful, false otherwise
*/
bool DotFrontend::run(const QString& sFile)
{
QString sPath;
QStringList slArgs;
QPaintDeviceMetrics pdm(m_pGraph);
// Set the horizontal and vertical DPI values
m_dDpiX = (double)pdm.logicalDpiX();
m_dDpiY = (double)pdm.logicalDpiY();
// Make sure the executable exists
sPath = Config().getDotPath();
// Set the command line arguments
slArgs.append(sPath);
slArgs.append("-Tplain");
slArgs.append(sFile);
// Run a new process
if (!Frontend::run("dot", slArgs))
return false;
// Initialize stdout parsing
m_state = Graph;
m_delim = All;
return true;
}
/**
* Tests that the given file path leads to an executable.
* @param sPath The path to check
* @return true if the file in the given path exists and has executable
* permissions, false otherwise
*/
bool DotFrontend::verify(const QString& sPath)
{
QFileInfo fi(sPath);
if (!fi.exists() || !fi.isFile() || !fi.isExecutable() ||
fi.fileName() != "dot") {
KMessageBox::error(0, i18n("Dot cannot be found in the given "
"path"));
return false;
}
return true;
}
#define PAD 5
/**
* Parses the output of a Dot process.
* @param sToken The current token read (the token delimiter is determined
* by the current state)
* @param delim The delimiter that ends this token
* @return A value indicating the way this token should be treated: dropped,
* added to the token queue, or finishes a new record
*/
Frontend::ParseResult DotFrontend::parseStdout(QString& sToken,
ParserDelim delim)
{
static int nWidth, nHeight, nXpos, nYpos, nCurveSize, nCurveCount;
static QPointArray arrCurve;
static QString sNode, sEdgeHead, sEdgeTail;
ParseResult result = DiscardToken;
double dVal;
bool bOK;
// Handle the token according to the current state
switch (m_state) {
case Graph:
if (sToken == "graph")
m_state = GraphScale;
break;
case GraphScale:
sToken.toDouble(&bOK);
if (bOK)
m_state = GraphWidth;
break;
case GraphWidth:
// Read and transform the graph's width
dVal = sToken.toDouble(&bOK);
if (bOK) {
nWidth = (int)(dVal * m_dDpiX) + (PAD * 2);
m_state = GraphHeight;
}
break;
case GraphHeight:
// Read and transform the graph's height
dVal = sToken.toDouble(&bOK);
if (bOK) {
nHeight = (int)(dVal * m_dDpiY) + (PAD * 2);
// Set the graph's size
m_pGraph->resize(nWidth, nHeight);
m_state = NodeEdgeStop;
}
break;
case NodeEdgeStop:
// "node" starts a new node
// "edge" starts a new edge
// "stop" ends this graph
if (sToken == "node") {
m_state = NodeName;
}
else if (sToken == "edge") {
m_state = EdgeHead;
}
else if (sToken == "stop") {
m_state = Graph;
}
break;
case NodeName:
// Get a node's name
sNode = sToken;
m_state = NodeCentreX;
break;
case NodeCentreX:
// Read and transform the node's centre location (X coordinate)
dVal = sToken.toDouble(&bOK);
if (bOK) {
nXpos = (int)(dVal * m_dDpiX) + PAD;
m_state = NodeCentreY;
}
break;
case NodeCentreY:
// Read and transform the node's centre location (Y coordinate)
dVal = sToken.toDouble(&bOK);
if (bOK) {
nYpos = (int)(dVal * m_dDpiY) + PAD;
m_state = NodeWidth;
}
break;
case NodeWidth:
// Read and transform the node's width
dVal = sToken.toDouble(&bOK);
if (bOK) {
nWidth = (int)(dVal * m_dDpiX);
m_state = NodeHeight;
}
break;
case NodeHeight:
// Read and transform the node's height
dVal = sToken.toDouble(&bOK);
if (bOK) {
nHeight = (int)(dVal * m_dDpiY);
// Create the bounding rectangle of the node
QRect rect;
rect.setX(nXpos - (nWidth / 2));
rect.setY(nYpos - (nHeight / 2));
rect.setWidth(nWidth);
rect.setHeight(nHeight);
// Draw the node
m_pGraph->drawNode(sNode, rect);
m_state = EndNodeEdge;
}
break;
case EdgeHead:
// Get the edge's head node
sEdgeHead = sToken;
m_state = EdgeTail;
break;
case EdgeTail:
// Get the edge's tail node
sEdgeTail = sToken;
m_state = EdgeCurveSize;
break;
case EdgeCurveSize:
// Get the number of control points in the edge's spline
nCurveSize = sToken.toInt(&bOK);
if (bOK) {
arrCurve.resize(nCurveSize);
nCurveCount = 0;
m_state = EdgeCurveX;
}
break;
case EdgeCurveX:
// Read and a control point (X coordinate)
dVal = sToken.toDouble(&bOK);
if (bOK) {
nXpos = (int)(dVal * m_dDpiX) + PAD;
m_state = EdgeCurveY;
}
break;
case EdgeCurveY:
// Read and a control point (Y coordinate)
dVal = sToken.toDouble(&bOK);
if (bOK) {
nYpos = (int)(dVal * m_dDpiY) + PAD;
// Add the control point to the spline array
arrCurve.setPoint(nCurveCount++, nXpos, nYpos);
// Check if this is the last control point
if (nCurveCount == nCurveSize) {
// Draw the edge
m_pGraph->drawEdge(sEdgeHead, sEdgeTail, arrCurve);
// Must detach from contents since a QPointArray shares data
arrCurve.detach();
m_state = EndNodeEdge;
}
else {
// Another control point available
m_state = EdgeCurveX;
}
}
break;
case EndNodeEdge:
// Discard everything else on a node or edge line
if (delim == Newline)
m_state = NodeEdgeStop;
break;
}
return result;
}
#include "dotfrontend.moc"

@ -0,0 +1,76 @@
/***************************************************************************
*
* Copyright (C) 2006 Elad Lahav (elad_lahav@users.sf.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef DOTFRONTEND_H
#define DOTFRONTEND_H
#include <frontend.h>
#include <qpointarray.h>
class GraphWidget;
/**
* Front-end for executing graphviz's command-line tool.
* This tool accepts the description of a graph in the 'dot' language, and
* outputs a set of drawing instructions for the graph.
* @author Elad Lahav
*/
class DotFrontend : public Frontend
{
Q_OBJECT
public:
DotFrontend(GraphWidget*);
~DotFrontend();
bool run(const QString&);
static bool verify(const QString&);
protected:
virtual ParseResult parseStdout(QString&, ParserDelim);
private:
/** The owner graph widget on which to draw. */
GraphWidget* m_pGraph;
/** State values for the parser state machine. */
enum ParserState { Graph, GraphScale, GraphWidth, GraphHeight,
NodeEdgeStop, NodeName, NodeCentreX, NodeCentreY, NodeWidth, NodeHeight,
EdgeHead, EdgeTail, EdgeCurveSize, EdgeCurveX, EdgeCurveY,
EndNodeEdge };
/** The current state of the parser state machine. */
ParserState m_state;
/** The horizontal DPI value of the graph widget. */
double m_dDpiX;
/** The vertical DPI value of the graph widget. */
double m_dDpiY;
};
#endif

@ -0,0 +1,234 @@
/* dot.y */
%{
#include <qdict.h>
#include <qptrstack.h>
#include <qlistview.h>
#include "calltreedlg.h"
#include "graphwidget.h"
#include "treewidget.h"
#include "encoder.h"
extern FILE* yyin;
int yylex();
void yyinit(CallTreeDlg*, FILE*, Encoder*);
void yyerror(const char*);
static QMap<QString, QString> s_pMapAttr;
static QStack<QListViewItem> s_pParentStack;
static QListView* s_pTree;
static GraphWidget* s_pGraph;
static TreeWidget* s_pCallTree;
static TreeWidget* s_pCallingTree;
static Encoder* s_pEncoder;
// Avoid compiler warnings
#define YYENABLE_NLS 0
#ifndef YYLTYPE_IS_TRIVIAL
#define YYLTYPE_IS_TRIVIAL 0
#endif
%}
%union {
QString* pText;
}
%token GRAPH DIGRAPH NODE NAME STRING NUMBER DIR_EDGE UNDIR_EDGE
%token CALL_TREE CALLING_TREE
%type <pText> NAME STRING NUMBER attr_val
%start file
%%
file
: call_tree calling_tree graph
graph
: graph_type NAME '{' graph_desc_list '}' { delete $2; }
;
graph_type
: GRAPH
| DIGRAPH
;
graph_desc_list
:
| graph_desc_entry graph_desc_list
;
graph_desc_entry
: def_node_attr
| graph_attr
| node_record
| edge_record
;
def_node_attr
: NODE attributes ';'
;
graph_attr
: GRAPH attributes ';'
{
if (s_pMapAttr.find("kscope_zoom") != s_pMapAttr.end())
s_pGraph->setZoom(s_pMapAttr["kscope_zoom"].toDouble());
}
;
node_record
: NAME attributes ';'
{
s_pGraph->addNode(*$1);
delete $1;
s_pMapAttr.clear();
}
;
edge_record
: NAME edge_type NAME attributes ';'
{
GraphWidget::CallData cd;
cd.m_sCaller = *$1;
cd.m_sCallee = *$3;
cd.m_sFile = s_pMapAttr["kscope_file"];
cd.m_sLine = s_pMapAttr["kscope_line"];
cd.m_sText = s_pEncoder->decode(s_pMapAttr["kscope_text"]);
s_pGraph->addCall(cd);
delete $1;
delete $3;
s_pMapAttr.clear();
}
;
edge_type
: DIR_EDGE
| UNDIR_EDGE
;
attributes
:
| '[' attr_list ']'
;
attr_list
:
| non_empty_attr_list
;
non_empty_attr_list
: attr
| attr ',' attr_list
;
attr
: NAME '=' attr_val
{
s_pMapAttr.insert(*$1, *$3);
delete $1;
delete $3;
}
;
attr_val
: NAME
| STRING
| NUMBER
;
call_tree
: call_tree_prepare '{' root_node '}'
;
call_tree_prepare
: CALL_TREE { s_pTree = s_pCallTree; }
;
calling_tree
: calling_tree_prepare '{' root_node '}'
;
calling_tree_prepare
: CALLING_TREE { s_pTree = s_pCallingTree; }
;
root_node
: root_tree_node '{' child_list '}'
{
QListViewItem* pItem;
pItem = s_pParentStack.pop();
if (pItem->firstChild() != NULL)
pItem->setOpen(true);
}
;
root_tree_node
: NAME
{
QListViewItem* pItem;
pItem = new QListViewItem(s_pTree, *$1);
s_pParentStack.push(pItem);
delete $1;
}
;
child_list
:
| child_node child_list
;
child_node
: tree_node tree_attributes '{' child_list '}'
{
QListViewItem* pItem;
pItem = s_pParentStack.pop();
if (pItem->firstChild() != NULL)
pItem->setOpen(true);
}
;
tree_node
: NAME
{
QListViewItem* pItem;
pItem = new QListViewItem(s_pParentStack.top(), *$1);
s_pParentStack.push(pItem);
delete $1;
}
;
tree_attributes
: attributes
{
QListViewItem* pItem;
pItem = s_pParentStack.top();
pItem->setText(1, s_pMapAttr["kscope_file"]);
pItem->setText(2, s_pMapAttr["kscope_line"]);
pItem->setText(3, s_pEncoder->decode(s_pMapAttr["kscope_text"]));
}
;
%%
void yyinit(CallTreeDlg* pDlg, FILE* pFile, Encoder* pEnc)
{
yyin = pFile;
s_pCallTree = pDlg->m_pCalledWidget;
s_pCallingTree = pDlg->m_pCallingWidget;
s_pGraph = pDlg->m_pGraphWidget;
s_pEncoder = pEnc;
}
void yyerror(const char* szError)
{
fprintf(stderr, "%s\n", szError);
}

@ -0,0 +1,36 @@
/* dot.l */
%{
#include <qstring.h>
#include "dotparse.h"
%}
%option noyywrap
name [a-zA-Z_][a-zA-Z0-9_]*
string \"(\\.|[^\"])*\"
space [ \t\n]+
number [1-9][0-9]*
float [0-9]*\.[0-9]+
%%
"graph" return GRAPH;
"digraph" return DIGRAPH;
"calltree" return CALL_TREE;
"callingtree" return CALLING_TREE;
"node" return NODE;
"->" return DIR_EDGE;
"--" return UNDIR_EDGE;
{name} { yylval.pText = new QString(yytext); return NAME; }
{string} {
QString str = &yytext[1];
yylval.pText = new QString(str.left(yyleng - 2));
return STRING;
}
{number} { yylval.pText = new QString(yytext); return NUMBER; }
{float} { yylval.pText = new QString(yytext); return NUMBER; }
{space} ;
. return yytext[0];
%%

@ -0,0 +1,89 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <ktexteditor/editorchooser.h>
#include <kate/document.h>
#include "editormanager.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
EditorManager::EditorManager(QWidget* pParent, const char* szName) :
KParts::PartManager(pParent, szName)
{
applyPrefs();
}
/**
* Class destructor.
*/
EditorManager::~EditorManager()
{
}
/**
* Creates a new document part.
* @return A pointer to the new document
*/
KTextEditor::Document* EditorManager::add()
{
KTextEditor::Document* pDoc;
// Create the document
pDoc = KTextEditor::EditorChooser::createDocument(this);
addPart(pDoc);
return pDoc;
}
/**
* Deletes a document part.
* @param pDoc The document to remove
*/
void EditorManager::remove(KTextEditor::Document* pDoc)
{
removePart(pDoc);
delete pDoc;
}
/**
* Applies the user preferences.
* Determines if Kate warnings are displayed in case the currently edited
* file is modified outside KScope.
* NOTE: This behaviour is determined by a static function, which is why this
* code appears here, rather then for every EditorPage object.
*/
void EditorManager::applyPrefs()
{
Kate::Document::setFileChangedDialogsActivated(
Config().getWarnModifiedOnDisk());
}
#include "editormanager.moc"

@ -0,0 +1,56 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef EDITORMANAGER_H
#define EDITORMANAGER_H
#include <qwidget.h>
#include <kparts/partmanager.h>
#include <klibloader.h>
#include <ktexteditor/document.h>
/**
* Creates text editor parts, used to open source files.
* The EditorManager is responsible for creating parts, and managing their
* GUI integration.
* @author Elad Lahav
*/
class EditorManager : public KParts::PartManager
{
Q_OBJECT
public:
EditorManager(QWidget* pParent = 0, const char* szName = 0);
~EditorManager();
KTextEditor::Document* add();
void remove(KTextEditor::Document*);
void applyPrefs();
};
#endif

@ -0,0 +1,720 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qfileinfo.h>
#include <kdeversion.h>
#include <ktexteditor/selectioninterface.h>
#include <ktexteditor/viewcursorinterface.h>
#include <ktexteditor/popupmenuinterface.h>
#include <ktexteditor/editinterface.h>
#include <kate/document.h>
#include <kate/view.h>
#include "editorpage.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pDoc The document object associated with this page
* @param pMenu A Cscope queries popup menu to use with the editor
* @param pParent The parent widget
* @param szName The widget's name
*/
EditorPage::EditorPage(KTextEditor::Document* pDoc, QPopupMenu* pMenu,
QTabWidget* pParent, const char* szName) : QHBox(pParent, szName),
m_pParentTab(pParent),
m_pDoc(pDoc),
m_bOpen(false),
m_bNewFile(false),
m_sName(""),
m_bWritable(true), /* new documents are writable by default */
m_bModified(false),
m_nLine(0),
m_bSaveNewSizes(false)
{
KTextEditor::PopupMenuInterface* pMenuIf;
KTextEditor::ViewCursorInterface* pCursorIf;
// Create code-completion objects (will be deleted by QObject destructor)
m_pCompletion = new SymbolCompletion(this, this);
// Set read-only mode, if required
if (Config().getReadOnlyMode())
m_pDoc->setReadWrite(false);
// Create the child widgets
m_pSplit = new QSplitter(this);
m_pCtagsList = new CtagsList(m_pSplit);
m_pView = m_pDoc->createView(m_pSplit);
m_pSplit->setResizeMode(m_pCtagsList, QSplitter::KeepSize);
// Perform tasks only when the document has been loaded completely
connect(m_pDoc, SIGNAL(completed()), this, SLOT(slotFileOpened()));
// Be notified when the text in the editor changes
connect(m_pDoc, SIGNAL(textChanged()), this, SLOT(slotSetModified()));
connect(m_pDoc, SIGNAL(undoChanged()), this, SLOT(slotUndoChanged()));
// Store the sizes of the child windows when the tag list is resized
// (since it may imply a move of the splitter divider)
connect(m_pCtagsList, SIGNAL(resized()), this, SLOT(slotChildResized()));
// Go to a symbol's line if it is selected in the tag list
connect(m_pCtagsList, SIGNAL(lineRequested(uint)), this,
SLOT(slotGotoLine(uint)));
// Add Ctag records to the tag list
connect(&m_ctags, SIGNAL(dataReady(FrontendToken*)), m_pCtagsList,
SLOT(slotDataReady(FrontendToken*)));
// Monitor Ctags' operation
connect(&m_ctags, SIGNAL(finished(uint)), m_pCtagsList,
SLOT(slotCtagsFinished(uint)));
// Set the context menu
pMenuIf = dynamic_cast<KTextEditor::PopupMenuInterface*>(m_pView);
if (pMenuIf)
pMenuIf->installPopup(pMenu);
// Emit a signal whenever the cursor's position changes
pCursorIf = dynamic_cast<KTextEditor::ViewCursorInterface*>(m_pView);
if (pCursorIf) {
connect(m_pView, SIGNAL(cursorPositionChanged()), this,
SLOT(slotCursorPosChange()));
}
}
/**
* Class destructor.
*/
EditorPage::~EditorPage()
{
}
/**
* Returns a pointer to the editor document object embedded in this page.
* @returns the document pointer
*/
KTextEditor::Document* EditorPage::getDocument()
{
return m_pDoc;
}
/**
* Returns a pointer to the editor view object embedded in this page.
* @returns the view pointer
*/
KTextEditor::View* EditorPage::getView()
{
return m_pView;
}
/**
* Returns the full path of the file being edited.
* @return The path of the file associated with the Document object, empty
* string if no file is currently open
*/
QString EditorPage::getFilePath()
{
return m_pDoc->url().path();
}
/**
* Returns the name of the file being edited.
* @return The name of the file associated with the Document object, empty
* string if no file is currently open
*/
QString EditorPage::getFileName()
{
return m_sName;
}
/**
* Determines whether this file can be modified, according to the file-system
* permissions, and KScope's global settings.
* @return true if this document can be changed, false otherwise
*/
bool EditorPage::isWritable()
{
// Check global settings first
if (Config().getReadOnlyMode())
return false;
// Return FS write permissions
return m_bWritable;
}
/**
* Determines if the file edited in this page was modified, and the changes
* were not yet saved.
* @return true if the file was modified, false otherwise
*/
bool EditorPage::isModified()
{
return m_pDoc->isModified();
}
/**
* Opens a file for editing.
* @param sFileName The full path name of the file to edit.
*/
void EditorPage::open(const QString& sFileName)
{
// Open the given file
m_bOpen = false;
m_pDoc->openURL(sFileName);
}
/**
* Marks the page as containing a new unnamed file.
*/
void EditorPage::setNewFile()
{
m_bNewFile = true;
emit newFile(this);
}
/**
* Saves the edited file.
*/
void EditorPage::save()
{
if (m_pDoc->isModified())
m_pDoc->save();
}
/**
* Closes an edited file.
* @param bForce true to close the file regardless of any modifications,
* false to prompt the user in case of unsaved chnages
* @return true if the file has been closed, false if the user has aborted
*/
bool EditorPage::close(bool bForce)
{
QString sPath;
// To override the prompt-on-close behaviour, we need to mark the file
// as unmodified
if (bForce)
m_pDoc->setModified(false);
// Close the file, unless the user aborts the action
sPath = m_pDoc->url().path();
if (!m_pDoc->closeURL())
return false;
emit fileClosed(sPath);
return true;
}
/**
* Applies any changes to the user preferences concerning an editor window.
*/
void EditorPage::applyPrefs()
{
// Determine whether the editor should work in a read-only mode
if (m_bWritable)
m_pDoc->setReadWrite(!Config().getReadOnlyMode());
// Apply preferences to the tag list of this window
m_pCtagsList->applyPrefs();
}
/**
* Sets the keyboard focus to the editor part of the page.
* This method is called whenever the page is activated. It is more reasonable
* to set the focus to the editor than to the tag list.
*/
void EditorPage::setEditorFocus()
{
m_pView->setFocus();
slotCursorPosChange();
}
/**
* Sets the keyboard focus to the tag list.
* This method is called when the "Go To Tag" menu command is invoked.
*/
void EditorPage::setTagListFocus()
{
m_pCtagsList->slotSetFocus();
}
/**
* Sets a bookmark at the given line.
* @param nLine The line to mark
*/
void EditorPage::addBookmark(uint nLine)
{
KTextEditor::MarkInterface* pMarkIf;
pMarkIf = dynamic_cast<KTextEditor::MarkInterface*>(m_pDoc);
if (pMarkIf)
pMarkIf->setMark(nLine, KTextEditor::MarkInterface::markType01);
}
/**
* Retrieves a list of all bookmarks in this page.
*/
void EditorPage::getBookmarks(FileLocationList& fll)
{
KTextEditor::MarkInterface* pMarkIf;
QPtrList<KTextEditor::Mark> plMarks;
KTextEditor::Mark* pMark;
// Get the marks interface
pMarkIf = dynamic_cast<KTextEditor::MarkInterface*>(m_pDoc);
if (!pMarkIf)
return;
// Find all bookmarks
plMarks = pMarkIf->marks();
for (pMark = plMarks.first(); pMark; pMark = plMarks.next()) {
if (pMark->type == KTextEditor::MarkInterface::markType01)
fll.append(new FileLocation(getFilePath(), pMark->line, 0));
}
}
/**
* Returns the currently selected text in an open file.
* @return The selected text, or a null string if no text is currently
* selected
*/
QString EditorPage::getSelection()
{
KTextEditor::SelectionInterface* pSelect;
// Get the selected text
pSelect = dynamic_cast<KTextEditor::SelectionInterface*>(m_pDoc);
if (!pSelect || !pSelect->hasSelection())
return QString::null;
// Return the selected text
return pSelect->selection();
}
/**
* Returns a the complete word defined by the current cursor position.
* Attempts to extract a valid C symbol from the location of the cursor, by
* starting at the current line and column, and looking forward and backward
* for non-symbol characters.
* @return A C symbol under the cursor, if any, or QString::null otherwise
*/
QString EditorPage::getWordUnderCursor(uint* pPosInWord)
{
KTextEditor::ViewCursorInterface* pCursor;
KTextEditor::EditInterface* pEditIf;
QString sLine;
uint nLine, nCol, nFrom, nTo, nLast, nLength;
QChar ch;
// Get a cursor object
pCursor = dynamic_cast<KTextEditor::ViewCursorInterface*>(m_pView);
if (pCursor == NULL)
return QString::null;
// Get a pointer to the edit interface
pEditIf = dynamic_cast<KTextEditor::EditInterface*>(m_pDoc);
if (!pEditIf)
return QString::null;
// Get the line on which the cursor is positioned
pCursor->cursorPositionReal(&nLine, &nCol);
sLine = pEditIf->textLine(nLine);
// Find the beginning of the current word
for (nFrom = nCol; nFrom > 0;) {
ch = sLine.at(nFrom - 1);
if (!ch.isLetter() && !ch.isDigit() && ch != '_')
break;
nFrom--;
}
// Find the end of the current word
nLast = sLine.length();
for (nTo = nCol; nTo < nLast;) {
ch = sLine.at(nTo);
if (!ch.isLetter() && !ch.isDigit() && ch != '_')
break;
nTo++;
}
// Mark empty words
nLength = nTo - nFrom;
if (nLength == 0)
return QString::null;
// Return the in-word position, if required
if (pPosInWord != NULL)
*pPosInWord = nCol - nFrom;
// Extract the word under the cursor from the entire line
return sLine.mid(nFrom, nLength);
}
/**
* Combines getSelection() and getWordUnderCursor() to return a suggested
* text for queries.
* The function first looks if any text is selected. If so, the selected text
* is returned. Otherwise, the word under the cursor location is returned, if
* one exists.
* @return Either the currently selected text, or the word under the cursor,
* or QString::null if both options fail
*/
QString EditorPage::getSuggestedText()
{
QString sText;
sText = getSelection();
if (sText == QString::null)
sText = getWordUnderCursor();
return sText;
}
/**
* Returns the contents of the requested line.
* Truncates the leading and trailing white spaces.
* @param nLine The line number
* @return The text of the requested line, if successful, QString::null
* otherwise
*/
QString EditorPage::getLineContents(uint nLine)
{
KTextEditor::EditInterface* pEditIf;
QString sLine;
// Cannot accept line 0
if (nLine == 0)
return QString::null;
// Get a pointer to the edit interface
pEditIf = dynamic_cast<KTextEditor::EditInterface*>(m_pDoc);
if (!pEditIf)
return QString::null;
// Get the line on which the cursor is positioned
sLine = pEditIf->textLine(nLine - 1);
return sLine.stripWhiteSpace();
}
/**
* Moves the editing caret to the beginning of a given line.
* @param nLine The line number to move to
*/
void EditorPage::slotGotoLine(uint nLine)
{
// Ensure there is an open document
if (!m_bOpen)
return;
// Set the cursor to the requested line
if (!setCursorPos(nLine))
return;
// Update Ctags view
m_pCtagsList->gotoLine(nLine);
// Set the focus to the selected line
m_pView->setFocus();
}
/**
* Sets this editor as the current page, when the edited file's name is
* selected in the "Window" menu.
*/
void EditorPage::slotMenuSelect()
{
m_pParentTab->setCurrentPage(m_pParentTab->indexOf(this));
}
/**
* Displays a list of possible completions for the symbol currently under the
* cursor.
*/
void EditorPage::slotCompleteSymbol()
{
m_pCompletion->slotComplete();
}
/**
* Stores the sizes of the child widgets whenever they are changed.
* This slot is connected to the resized() signal of the CtagsList child
* widget.
*/
void EditorPage::slotChildResized()
{
SPLIT_SIZES si;
// Only store sizes when allowed to
if (!m_bSaveNewSizes) {
m_bSaveNewSizes = true;
return;
}
// Get the current widths of the child widgets
si = m_pSplit->sizes();
if (si.count() == 2)
Config().setEditorSizes(si);
}
/**
* Sets the visibility status and sizes of the child widgets.
* @param bShowTagList true to show the tag list, false otherwise
* @param si The new sizes to use
*/
void EditorPage::setLayout(bool bShowTagList, const SPLIT_SIZES& si)
{
// Make sure sizes are not stored during this process
m_bSaveNewSizes = false;
// Adjust the layout
m_pCtagsList->setShown(bShowTagList);
if (bShowTagList)
m_pSplit->setSizes(si);
}
/**
* Returns the current position of the cursor.
* @param nLine Holds the line on which the cursor is currently located
* @param nCol Holds the column on which the cursor is currently located
* @return true if successful, false otherwise (cursor interface was not
* obtained)
*/
bool EditorPage::getCursorPos(uint& nLine, uint& nCol)
{
KTextEditor::ViewCursorInterface* pCursorIf;
// Acquire the view cursor
pCursorIf = dynamic_cast<KTextEditor::ViewCursorInterface*>(m_pView);
if (pCursorIf == NULL)
return false;
// Get the cursor position (adjusted to 1-based counting)
pCursorIf->cursorPosition(&nLine, &nCol);
nLine++;
nCol++;
return true;
}
/**
* Moves the cursor to a given position.
* @param nLine The cursor's new line number
* @param nCol The cursor's new column number
* @return true if successful, false otherwise (cursor interface was not
* obtained)
*/
bool EditorPage::setCursorPos(uint nLine, uint nCol)
{
Kate::View* pKateView;
KTextEditor::ViewCursorInterface* pCursorIf;
// Cannot accept line 0
if (nLine == 0)
return false;
// Adjust to 0-based counting
nLine--;
nCol--;
// Acquire the view cursor
pCursorIf = dynamic_cast<KTextEditor::ViewCursorInterface*>(m_pView);
if (pCursorIf == NULL)
return false;
// NOTE: The following code is a fix to a bug in Kate, which wrongly
// calculates the column number in setCursorPosition.
pKateView = dynamic_cast<Kate::View*>(m_pView);
if (pKateView != NULL) {
KTextEditor::EditInterface* pEditIf;
const char* szLine;
uint nRealCol;
uint nTabAdjust;
// Get a pointer to the edit interface
pEditIf = dynamic_cast<KTextEditor::EditInterface*>(m_pDoc);
if (!pEditIf)
return false;
nRealCol = 0;
// Check for out of bound line numbers
if (nLine < pEditIf->numLines()) {
// Get the contents of the requested line
szLine = pEditIf->textLine(nLine).latin1();
// Check for empty line
if (szLine != NULL) {
// The number of columns which a tab character adds
nTabAdjust = pKateView->tabWidth() - 1;
// Calculate the real column, based on the tab width
for (; nRealCol < nCol && szLine[nRealCol] != 0; nRealCol++) {
if (szLine[nRealCol] == '\t')
nCol -= nTabAdjust;
}
}
}
else {
// Marker set beyond end of file, move to the last line
nLine = pEditIf->numLines() - 1;
}
// Set the cursor position
pCursorIf->setCursorPositionReal(nLine, nRealCol);
}
else {
// Non-Kate editors: set the cursor position normally
pCursorIf->setCursorPosition(nLine, nCol);
}
return true;
}
void EditorPage::setTabWidth(uint nTabWidth)
{
Kate::Document* pKateDoc;
Kate::Command* pKateCmd;
QString sCmd, sResult;
pKateDoc = dynamic_cast<Kate::Document*>(m_pDoc);
if ((pKateDoc) &&
(pKateCmd = pKateDoc->queryCommand("set-tab-width"))) {
sCmd.sprintf("set-tab-width %u", nTabWidth);
pKateCmd->exec((Kate::View*)m_pView, sCmd, sResult);
}
}
/**
* Called when a document has completed loading.
* Determines the file's properties and refreshes the tag list of the editor
* window.
* This slot is connected to the completed() signal of the document object.
* The signal is emitted when a new file is opened, or when a modified file is
* saved.
*/
void EditorPage::slotFileOpened()
{
QFileInfo fi(m_pDoc->url().path());
// Get file information
m_sName = fi.fileName();
m_bWritable = fi.isWritable();
// Set read/write or read-only mode
m_pDoc->setReadWrite(!Config().getReadOnlyMode() && m_bWritable);
// Refresh the tag list
m_pCtagsList->clear();
m_ctags.run(m_pDoc->url().path());
// Check if this is a modified file that has just been saved
if (m_bModified)
emit fileSaved(m_pDoc->url().path(), m_bNewFile);
// Notify that the document has loaded
m_bOpen = true;
m_bModified = false;
emit fileOpened(this, m_pDoc->url().path());
// Set initial position of the cursor
m_nLine = 0;
slotCursorPosChange();
// This is no longer a new file
m_bNewFile = false;
}
/**
* Marks a file as modified when the contents of the editor change.
* This slot is conncted to the textChanged() signal of the Document object.
* In addition to marking the file, this method also emits the modified()
* signal.
*/
void EditorPage::slotSetModified()
{
// Only perform tasks if the file is not already marked
if (!m_bModified && m_pDoc->isModified()) {
m_bModified = true;
emit modified(this, m_bModified);
#if KDE_IS_VERSION(3,3,0)
Kate::DocumentExt* pKateDoc;
// If the editor is a Kate part, check whether it was modified on
// disk as well, and issue a warning if so
pKateDoc = dynamic_cast<Kate::DocumentExt*>(m_pDoc);
if (pKateDoc)
pKateDoc->slotModifiedOnDisk(dynamic_cast<Kate::View*>(m_pView));
#endif
}
// Start/restart the auto-completion timer
m_pCompletion->slotAutoComplete();
}
/**
* Marks a file as not modified if all undo levels have been applied.
* This slot is conncted to the undoChanged() signal of the Document object.
* In addition to marking the file, this method also emits the modified()
* signal.
*/
void EditorPage::slotUndoChanged()
{
// Check if the file contents have been fully restored
if (m_bModified && !m_pDoc->isModified()) {
m_bModified = false;
emit modified(this, m_bModified);
}
}
/**
* Handles changes in the cursor position.
* Emits a signal with the new line and column numbers.
*/
void EditorPage::slotCursorPosChange()
{
uint nLine, nCol;
// Find the new line and column number, and emit the signal
if (!getCursorPos(nLine, nCol))
return;
emit cursorPosChanged(nLine, nCol);
// Select the relevant symbol in the tag list
if (Config().getAutoTagHl() && (m_nLine != nLine)) {
m_pCtagsList->gotoLine(nLine);
m_nLine = nLine;
}
// Abort code completion on cursor changes during the completion
// process
m_pCompletion->abort();
}
#include "editorpage.moc"

@ -0,0 +1,215 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef EDITORPAGE_H
#define EDITORPAGE_H
#include <qwidget.h>
#include <qhbox.h>
#include <qsplitter.h>
#include <qtabwidget.h>
#include <qpopupmenu.h>
#include <ktexteditor/document.h>
#include <ktexteditor/view.h>
#include <ktexteditor/markinterfaceextension.h>
#include "ctagsfrontend.h"
#include "ctagslist.h"
#include "kscopeconfig.h"
#include "symbolcompletion.h"
#include "projectbase.h"
/**
* An editor window based on the system's current editing application.
* The page is divided into two panes. One holds an embedded editor, and the
* other holds a list of tags (generated by Ctags) of the file currently being
* edited.
* The widget creates an instance of the editor application, and uses its
* document and view objects that allow KScope to control it. A page also
* Each page is inserted in a separate tab in the EditorTabs widget.
* @author Elad Lahav
*/
class EditorPage : public QHBox, SymbolCompletion::Interface
{
Q_OBJECT
public:
EditorPage(KTextEditor::Document*, QPopupMenu*, QTabWidget* pParent = 0,
const char* szName = 0);
~EditorPage();
void open(const QString&);
void setNewFile();
void save();
bool close(bool bForce = false);
void applyPrefs();
void setEditorFocus();
void setTagListFocus();
void addBookmark(uint);
void getBookmarks(FileLocationList&);
KTextEditor::Document* getDocument();
KTextEditor::View* getView();
QString getFilePath();
QString getFileName();
bool isWritable();
bool isModified();
QString getSelection();
QString getSuggestedText();
QString getLineContents(uint);
void setLayout(bool bShowTagList, const SPLIT_SIZES&);
bool getCursorPos(uint&, uint&);
bool setCursorPos(uint, uint nCol = 1);
void setTabWidth(uint);
virtual QString getWordUnderCursor(uint* pPosInWord = NULL);
/**
* Implements the SymbolCompletion interface method for returning an
* object that supports KTextEditor::CodeCompletionInterface.
* @return A pointer to the View object of the editor
*/
virtual QObject* getCCObject() { return m_pView; }
/**
* @return true if a previously unsaved file is currently being edited,
* false otherwise
*/
bool isNewFile() { return m_bNewFile; }
/** The identifier of the Window menu item which activates this page. */
int m_nMenuId;
public slots:
void slotGotoLine(uint);
void slotMenuSelect();
void slotCompleteSymbol();
signals:
/**
* Emitted when a file has been fully loaded into the editor.
* @param pPage The emitting object
* @param sPath The full path of the loaded file
*/
void fileOpened(EditorPage* pPage, const QString& sPath);
/**
* Emitted when an editor is opened for editing a new file.
* @param pPage The emitting object
*/
void newFile(EditorPage* pPage);
/**
* Emitted when the 'modified' status of the editor changes.
* This happens when the contents of the editor change, or when the file
* being edited is saved.
* @param pPage The emitting object
* @param bModified true if the new state is 'modified', false if the
* new state is 'unmodified'
*/
void modified(EditorPage* pPage, bool bModified);
/**
* Emitted when the position of the cursor changes.
* @param nLine The new line number
* @param nCol The new column number
*/
void cursorPosChanged(uint nLine, uint nCol);
/**
* Emitted when a file is saved after it was modified.
* Indicates the project's cross-reference database needs to be updated.
* @param sPath The full path of the saved file
* @param bIsNew true if this is a new file, false otherwise
*/
void fileSaved(const QString& sPath, bool bIsNew);
/**
* Emitted when a file is closed.
* @param sPath The full path of the closed file
*/
void fileClosed(const QString& sPath);
private:
/** The tab widget holding this page. */
QTabWidget* m_pParentTab;
/** A Ctags process to use on the edited source file. */
CtagsFrontend m_ctags;
/** An adjustable splitter for separating the tag list from the editor
part. */
QSplitter* m_pSplit;
/** A list view for displaying Ctags results. */
CtagsList* m_pCtagsList;
/** The document part of the editor. */
KTextEditor::Document* m_pDoc;
/** The view part of the editor. */
KTextEditor::View* m_pView;
/** Whether a source file is currently loaded. */
bool m_bOpen;
/** Whether the file being edited is a new one (i.e., never saved
before.) */
bool m_bNewFile;
/** The name of the file being edited. */
QString m_sName;
/** true if the file system allows this file to be modified, false
otherwise. */
bool m_bWritable;
/** This variable is required in addition to m_pDoc->isModified() so
that the modified() signal is emitted only once. */
bool m_bModified;
/** The current line position of the cursor. */
uint m_nLine;
/** Provides symbol completion. */
SymbolCompletion* m_pCompletion;
/** Determines whether size changes in the child widgets should be
stored in the global configuration file.
Needs to be explicitly set to false before _each_ operation that
does not wish to change the defaults. */
bool m_bSaveNewSizes;
private slots:
void slotChildResized();
void slotFileOpened();
void slotSetModified();
void slotUndoChanged();
void slotCursorPosChange();
};
#endif

@ -0,0 +1,640 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qfileinfo.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kurldrag.h>
#include <kate/document.h>
#include "editortabs.h"
#include "kscopepixmaps.h"
#include "queryview.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
EditorTabs::EditorTabs(QWidget* pParent, const char* szName) :
TabWidget(pParent, szName),
m_pCurPage(NULL),
m_pWindowMenu(NULL),
m_nWindowMenuItems(0),
m_nNewFiles(0)
{
// Display close buttons
setHoverCloseButton(true);
// Accept file drops
setAcceptDrops(true);
// Close an editor page when its close button is clicked
connect(this, SIGNAL(closeRequest(QWidget*)), this,
SLOT(slotRemovePage(QWidget*)));
// Set an editor page as the active part, when its tab is selected
connect(this, SIGNAL(currentChanged(QWidget*)), this,
SLOT(slotCurrentChanged(QWidget*)));
// Start dragging a file from a tab
connect(this, SIGNAL(initiateDrag(QWidget*)), this,
SLOT(slotInitiateDrag(QWidget*)));
}
/**
* Class destructor.
*/
EditorTabs::~EditorTabs()
{
}
/**
* @param pWindowMenu Pointer to the main window's "Window" menu (used to
* add an activation menu item for each editor page)
*/
void EditorTabs::setWindowMenu(QPopupMenu* pWindowMenu)
{
m_pWindowMenu = pWindowMenu;
connect(pWindowMenu, SIGNAL(aboutToShow()), this,
SLOT(slotFillWindowMenu()));
connect(pWindowMenu, SIGNAL(activated(int)), this,
SLOT(slotSetCurrentPage(int)));
}
/**
* Adds a new editor page to the tab widget.
* @param pNewPage The page to add
*/
void EditorTabs::addEditorPage(EditorPage* pNewPage)
{
// Create a new tab and set is as the current one
insertTab(pNewPage, "");
showPage(pNewPage);
// Add the file edited by this page to the map, and display its name,
// once the file is opened
connect(pNewPage, SIGNAL(fileOpened(EditorPage*, const QString&)), this,
SLOT(slotAttachFile(EditorPage*, const QString&)));
// Handle new unnamed files
connect(pNewPage, SIGNAL(newFile(EditorPage*)), this,
SLOT(slotNewFile(EditorPage*)));
// Change tab icon when a file is modified
connect(pNewPage, SIGNAL(modified(EditorPage*, bool)), this,
SLOT(slotFileModified(EditorPage*, bool)));
// If this is the first page, the current page will not be set by the
// signal handler, so we need to do it manually
if (count() == 1)
slotCurrentChanged(pNewPage);
}
/**
* Finds and displays a page editing the given file.
* NOTE: The bForceChange parameters is used as a fix for the GUI merge
* problem arising when the found page is the current one.
* @param sFileName The name of the file to search
* @param bForceChange If set to true, the method will emit the signal
* editorChanged() even if the found page is the
* current one
* @return The editor page object, if found, NULL otherwise
*/
EditorPage* EditorTabs::findEditorPage(const QString& sFileName,
bool bForceChange)
{
EditorMap::iterator itr;
EditorPage* pPage;
bool bEmit;
// Find the page according to the associated file name
itr = m_mapEdit.find(sFileName);
if (itr == m_mapEdit.end())
return NULL;
// Set the page as the current one
pPage = *itr;
bEmit = (bForceChange && (pPage == m_pCurPage));
showPage(pPage);
// Emit the editorChanged() signal, if required
if (bEmit)
emit editorChanged(NULL, m_pCurPage);
return *itr;
}
/**
* Returns the page associated with the selected tab.
* @return The current editor page
*/
EditorPage* EditorTabs::getCurrentPage()
{
return (EditorPage*)currentPage();
}
/**
* Deletes the currently active page.
* Finds the current page, closes its editor window and deletes the page.
* If other editors are open, another page becomes active.
*/
void EditorTabs::removeCurrentPage()
{
QWidget* pPage;
// Get the active page, if any
pPage = currentPage();
if (pPage == NULL)
return;
// Close the editor window
removePage(pPage, false);
}
/**
* Removes all editor pages.
* @return true if successful, false if the user aborts the operation
*/
bool EditorTabs::removeAllPages()
{
QWidget* pPage;
// Check if there are any modified files
if (getModifiedFilesCount()) {
// Prompt the user to save these files
switch (KMessageBox::questionYesNoCancel(NULL,
i18n("Some files contain unsaved changes.\nWould you like to "
"save these files?"))) {
case KMessageBox::Yes:
// Save files
slotSaveAll();
break;
case KMessageBox::No:
// Close files, ignoring changes
break;
case KMessageBox::Cancel:
// Abort
return false;
}
}
// Avoid warning about modification on disk
Kate::Document::setFileChangedDialogsActivated(false);
// Iterate pages until none is left
while ((pPage = currentPage()) != NULL)
removePage(pPage, true);
// Restore kate warning if enabled
Kate::Document::setFileChangedDialogsActivated(
Config().getWarnModifiedOnDisk());
// All pages were successfully removed
return true;
}
/**
* Keeps track of the currently active editor page, and notifies on a change
* in the active page.
* This slot is connected to the currentChanged() signal of the QTabWidget
* object.
* @param pWidget The new active page
*/
void EditorTabs::slotCurrentChanged(QWidget* pWidget)
{
EditorPage* pOldPage;
// TODO:
// For some reason, this slot is being called twice for every external
// tab activation (e.g., through the Window menu).
// We avoid it, but this really needs to be fixed properly.
if (pWidget == m_pCurPage)
return;
// Set the new active page
pOldPage = m_pCurPage;
m_pCurPage = (EditorPage*)pWidget;
if (m_pCurPage) {
// Set the keyboard focus to the editor part of the page
m_pCurPage->setEditorFocus();
// Adjust the splitter sizes
m_pCurPage->setLayout(Config().getShowTagList(),
Config().getEditorSizes());
}
/* Notify the main window */
emit editorChanged(pOldPage, m_pCurPage);
}
/**
* Updates the tab of an editor page to reflect the newly opened file.
* This slot is attached to the fileOpened() signal of an EditorPage object.
* @param pEditPage Pointer to the calling object
* @param sFilePath The full path of the file edited in this page
*/
void EditorTabs::slotAttachFile(EditorPage* pEditPage,
const QString& sFilePath)
{
// Set the appropriate tab icon, according to the file permissions
if (pEditPage->isWritable())
setTabIconSet(pEditPage, Pixmaps().getPixmap(KScopePixmaps::TabRW));
else
setTabIconSet(pEditPage, Pixmaps().getPixmap(KScopePixmaps::TabRO));
// Do nothing if the file name has not changed
if (m_mapEdit[sFilePath] == pEditPage)
return;
// Set the tab caption to the file name, and a tool-tip to the full path
changeTab(pEditPage, pEditPage->getFileName());
setTabToolTip(pEditPage, sFilePath);
// Associate the EditorPage object with its file name
m_mapEdit[sFilePath] = pEditPage;
}
/**
* Marks a page as containing a new unnamed file.
* This slot is attached to the newFile() signal of an EditorPage object.
* @param pEditPage Pointer to the calling object
*/
void EditorTabs::slotNewFile(EditorPage* pEditPage)
{
QString sCaption;
// Set the tab caption to mark a new file
m_nNewFiles++;
sCaption = i18n("Untitled ") + QString::number(m_nNewFiles);
changeTab(pEditPage,
Pixmaps().getPixmap(KScopePixmaps::TabRW),
sCaption);
setTabToolTip(pEditPage, i18n("New unsaved file"));
}
/**
* Applies the user's colour and font preferences to all pages.
*/
void EditorTabs::applyPrefs()
{
EditorPage* pPage;
int i;
// Iterate editor pages
for (i = 0; i < count(); i++) {
pPage = (EditorPage*)page(i);
pPage->applyPrefs();
setTabIconSet(pPage, Pixmaps().getPixmap(pPage->isWritable() ?
KScopePixmaps::TabRW : KScopePixmaps::TabRO));
}
}
/**
* Fills a list with the paths and cursor positions of all files currently
* open.
* @param list The list to fill
*/
void EditorTabs::getOpenFiles(FileLocationList& list)
{
int i;
EditorPage* pPage;
uint nLine, nCol;
// Iterate over all editor pages
for (i = 0; i < count(); i++) {
// Obtain file and cursor position information
pPage = (EditorPage*)page(i);
if (!pPage->getCursorPos(nLine, nCol)) {
nLine = 1;
nCol = 1;
}
// Create a new list item
list.append(new FileLocation(pPage->getFilePath(), nLine, nCol));
}
}
/**
* Constructs a list bookmarks set to open files.
* Used to store all currently set bookmarks when a session is closed.
* @param fll The list to fill
*/
void EditorTabs::getBookmarks(FileLocationList& fll)
{
int i;
EditorPage* pPage;
// Iterate over all editor pages
for (i = 0; i < count(); i++) {
pPage = (EditorPage*)page(i);
pPage->getBookmarks(fll);
}
}
/**
* Assigns bookmarks to open files.
* Called when a session is opened, to restore any bookmarks set to existing
* editor pages.
* @param fll A list of bookmark positions
*/
void EditorTabs::setBookmarks(FileLocationList& fll)
{
FileLocation* pLoc;
EditorMap::iterator itr;
EditorPage* pPage;
// Iterate over the list of bookmarks
for (pLoc = fll.first(); pLoc; pLoc = fll.next()) {
itr = m_mapEdit.find(pLoc->m_sPath);
// Get the relevant page, if any
if (itr != m_mapEdit.end()) {
pPage = *itr;
pPage->addBookmark(pLoc->m_nLine);
}
}
}
/**
* Fills a QueryView object with the list of currently active bookmarks.
* @param pView The widget to use for displaying bookmarks
*/
void EditorTabs::showBookmarks(QueryView* pView)
{
int i;
EditorPage* pPage;
FileLocationList fll;
FileLocation* pLoc;
fll.setAutoDelete(true);
// Iterate over all editor pages
for (i = 0; i < count(); i++) {
// Obtain file and cursor position information
pPage = (EditorPage*)page(i);
pPage->getBookmarks(fll);
// Populate the view
for (pLoc = fll.first(); pLoc; pLoc = fll.next()) {
pView->addRecord("", pLoc->m_sPath,
QString::number(pLoc->m_nLine + 1),
pPage->getLineContents(pLoc->m_nLine + 1));
}
fll.clear();
}
}
/**
* Removes an editor page.
* If there are unsaved changes, the user is prompted, and the file is closed
* according to the user's choice.
* This slot is connected to the clicked() signal of the tab's close button.
* @param pPage The EditorPage object to remove
*/
void EditorTabs::slotRemovePage(QWidget* pPage)
{
removePage(pPage, false);
}
/**
* Handles the "View->Show/Hide Tag List" menu item.
* Shows/hides the tag list for the current page, and sets the default values
* for all pages.
*/
void EditorTabs::slotToggleTagList()
{
EditorPage* pPage;
// Change the default value
Config().setShowTagList(!Config().getShowTagList());
// Apply for the current page, if any
if ((pPage = (EditorPage*)currentPage()) != NULL) {
pPage->setLayout(Config().getShowTagList(),
Config().getEditorSizes());
}
}
/**
* Handles drag events over an empty tab widget, or over the tab bar.
* The event is accepted if the dragged object is a list of file paths.
* @param pEvent The drag move event object
*/
void EditorTabs::dragMoveEvent(QDragMoveEvent* pEvent)
{
KURL::List list;
bool bAccept;
bAccept = KURLDrag::decode(pEvent, list);
pEvent->accept(bAccept);
}
/**
* Handles file drops over an empty tab widget, or over the tab bar.
* @param pEvent The drop event object
*/
void EditorTabs::dropEvent(QDropEvent* pEvent)
{
emit filesDropped(pEvent);
}
/**
* Called when an editor tab is dragged from the tab widget.
* Initialises the drag operation with a URL that corresponds to the path of
* the file being edited in the corresponding page.
* This slot is connected to the initiateDrag() signal emitted by the tab
* widget.
* @param pWidget The page whose tab is being dragged
*/
void EditorTabs::slotInitiateDrag(QWidget* pWidget)
{
KURL url;
KURLDrag* pDrag;
// Create a URL list containing the appropriate file path
url.setPath(((EditorPage*)pWidget)->getFilePath());
pDrag = new KURLDrag(KURL::List(url), this);
// Start the drag
pDrag->dragCopy();
}
/**
* Changes the tab icon of a modified file.
* @param pEditPage The editor page whose file was modified
* @param bModified true if the file has changed its status to modified,
* false otherwise (i.e., when undo operations restore it
* to its original contents.)
*/
void EditorTabs::slotFileModified(EditorPage* pEditPage, bool bModified)
{
if (bModified)
setTabIconSet(pEditPage, Pixmaps().getPixmap(KScopePixmaps::TabSave));
else
setTabIconSet(pEditPage, Pixmaps().getPixmap(KScopePixmaps::TabRW));
}
/**
* Counts the number of pages containing modified files.
* @return The number of modified files
*/
int EditorTabs::getModifiedFilesCount()
{
int i, nResult;
// Iterate through pages
for (i = 0, nResult = 0; i < count(); i++) {
if (((EditorPage*)page(i))->isModified())
nResult++;
}
return nResult;
}
/**
* Saves all files open for editing.
*/
void EditorTabs::slotSaveAll()
{
int i;
// Iterate through pages
for (i = 0; i < count(); i++)
((EditorPage*)page(i))->save();
}
/**
* Selects the page to the left of the current one.
*/
void EditorTabs::slotGoLeft()
{
int nIndex;
nIndex = currentPageIndex();
if (nIndex > 0) {
nIndex--;
setCurrentPage(nIndex);
}
}
/**
* Selects the page to the right of the current one.
*/
void EditorTabs::slotGoRight()
{
int nIndex;
nIndex = currentPageIndex();
if (nIndex < count() - 1) {
nIndex++;
setCurrentPage(nIndex);
}
}
/**
* Fills the main window's "Window" menu with the current list of file tabs.
* This slot is attached to the aboutToShow() signal, emitted by the Window
* popup menu.
*/
void EditorTabs::slotFillWindowMenu()
{
QString sLabel;
int i;
// Delete old menu items
// NOTE: We can't use aboutToHide() to do that, since it is emitted
// _before_ the activated() signal
for (i = 0; i < m_nWindowMenuItems; i++)
m_pWindowMenu->removeItem(i);
// Add new items
for (i = 0; i < count(); i++) {
sLabel = (i < 10) ? QString("&%1 %2").arg(i).arg(label(i)) : label(i);
m_pWindowMenu->insertItem(sLabel, i);
}
// Store the number of items added
m_nWindowMenuItems = i;
}
/**
* Sets the current page to the given one.
* This slot is attached to the activated() signal, emitted by the "Window"
* popup menu. The tab number to switch to is given by the menu item ID.
* Note that we do not trust setCurrentPage() to filter out the IDs of other
* menu items (which are supposed to be negative numbers).
*/
void EditorTabs::slotSetCurrentPage(int nId)
{
if (nId >= 0 && nId < count())
setCurrentPage(nId);
}
/**
* Closes an edited file, and removes its page.
* Once a file has been closed, its page is removed from the tab widget stack,
* its menu item in the "Windows" menu is deleted and all other references to
* it are removed.
* Note that the operation may fail if the user chooses not to close the file
* when prompted for unsaved changes.
* @param pPage The EditorPage object to remove
* @param bForce true to close the page even if there are unsaved changes,
* false otherwise
* @return true if the page was removed, false otherwise
*/
bool EditorTabs::removePage(QWidget* pPage, bool bForce)
{
EditorPage* pEditPage;
QString sFilePath;
// Store the file path for later
pEditPage = (EditorPage*)pPage;
sFilePath = pEditPage->getFilePath();
// Close the edited file (may fail if the user aborts the action)
if (!pEditPage->close(bForce))
return false;
// Remove the page and all references to it
m_mapEdit.remove(sFilePath);
TabWidget::removePage(pPage);
// Update the new state if no other page exists (if another page has
// become active, it will update the new state, so there is no need for
// special handling)
if (currentPage() == NULL)
slotCurrentChanged(NULL);
// Notify the page has been removed
emit editorRemoved(pEditPage);
return true;
}
#include "editortabs.moc"

@ -0,0 +1,129 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef EDITORTABS_H
#define EDITORTABS_H
#include <qwidget.h>
#include <qpopupmenu.h>
#include "tabwidget.h"
#include "editorpage.h"
#include "projectmanager.h"
typedef QMap<QString, EditorPage*> EditorMap;
class QueryView;
/**
* A tab widget that holds several editor windows.
* This class provides the main widget in the KScope window. All editors are
* opened as pages of the tab widgets.
* @author Elad Lahav
*/
class EditorTabs : public TabWidget
{
Q_OBJECT
public:
EditorTabs(QWidget* pParent = 0, const char* szName = 0);
~EditorTabs();
void setWindowMenu(QPopupMenu*);
void addEditorPage(EditorPage*);
EditorPage* findEditorPage(const QString&, bool bForceChange = false);
EditorPage* getCurrentPage();
void removeCurrentPage();
bool removeAllPages();
void applyPrefs();
void getOpenFiles(FileLocationList&);
void getBookmarks(FileLocationList&);
void setBookmarks(FileLocationList&);
void showBookmarks(QueryView*);
public slots:
void slotRemovePage(QWidget*);
void slotToggleTagList();
void slotSaveAll();
void slotGoLeft();
void slotGoRight();
signals:
/**
* Emitted when the current editor page changes.
* @param pOld The previous current page
* @param pNew The new current page
*/
void editorChanged(EditorPage* pOld, EditorPage* pNew);
/**
* Emitted when an editor page is closed.
* @param pPage The removed page
*/
void editorRemoved(EditorPage* pPage);
/**
* Indicates that files were dragged and dropped over the tab widget.
* @param pEvent The drop event information
*/
void filesDropped(QDropEvent* pEvent);
protected:
virtual void dragMoveEvent(QDragMoveEvent*);
virtual void dropEvent(QDropEvent*);
private:
/** Links a file name with an editor page that has this file open. */
EditorMap m_mapEdit;
/** We need to keep track of the current page in order to implement the
editorChanged() signal. */
EditorPage* m_pCurPage;
/** A popup menu with Cscope operations for the editor windows. */
QPopupMenu* m_pWindowMenu;
/** The number of items added to the window menu (used for removing old
items). */
int m_nWindowMenuItems;
/** A counter for creating unique tab captions for new files. */
int m_nNewFiles;
int getModifiedFilesCount();
bool removePage(QWidget*, bool);
private slots:
void slotCurrentChanged(QWidget*);
void slotAttachFile(EditorPage*, const QString&);
void slotNewFile(EditorPage*);
void slotFileModified(EditorPage*, bool);
void slotInitiateDrag(QWidget*);
void slotFillWindowMenu();
void slotSetCurrentPage(int);
};
#endif

@ -0,0 +1,114 @@
/***************************************************************************
*
* Copyright (C) 2006 Elad Lahav (elad_lahav@users.sf.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include "qstring.h"
#include "encoder.h"
#define CHAR_TO_HEX(c) ((c) < 0xA ? '0' + (c) : ('A' - 0xA) + (c))
#define HEX_TO_CHAR(h) ((h) > 'A' ? (h) - ('A' - 0xA) : (h) - '0')
/**
* Class constructor.
*/
Encoder::Encoder() : m_pBuf(NULL), m_nBufLen(0)
{
}
/**
* Class destructor.
*/
Encoder::~Encoder() {
if (m_pBuf)
delete[] m_pBuf;
}
/**
* Encodes a string.
* @param str The string to encode
* @return The hex-encoded ASCII string
*/
const char* Encoder::encode(const QString& str)
{
const char* szStr;
int nLen, i, j;
szStr = str.latin1();
nLen = str.length();
// Ensure the buffer is big enough to contain the result
resize((nLen * 2) + 1);
// Encode the string
for (i = 0, j = 0; i < nLen; i++, j += 2) {
m_pBuf[j] = CHAR_TO_HEX(szStr[i] >> 4);
m_pBuf[j + 1] = CHAR_TO_HEX(szStr[i] & 0x0f);
}
m_pBuf[j] = 0;
return m_pBuf;
}
/**
* Decodes a string.
* @param str The string to decode
* @return The decoded string.
*/
const char* Encoder::decode(const QString& str)
{
const char* szStr;
int nLen, i, j;
szStr = str.latin1();
nLen = str.length();
// Ensure the buffer is big enough to contain the result
nLen /= 2;
resize(nLen + 1);
// Decode the string
for (i = 0, j = 0; i < nLen; i++, j += 2) {
m_pBuf[i] = HEX_TO_CHAR(szStr[j]) << 4;
m_pBuf[i] |= HEX_TO_CHAR(szStr[j + 1]);
}
m_pBuf[i] = 0;
return m_pBuf;
}
/**
* Sets a new size to the buffer.
* @param nNewLen The new size of the buffer
*/
void Encoder::resize(int nNewLen)
{
if (m_nBufLen < nNewLen) {
if (m_pBuf)
delete[] m_pBuf;
m_pBuf = new char[nNewLen];
}
}

@ -0,0 +1,53 @@
/***************************************************************************
*
* Copyright (C) 2006 Elad Lahav (elad_lahav@users.sf.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef __ENCODER_H
#define __ENCODER_H
/**
* Translates strings to hex-encoded ASCII, and vice-versa.
* @author Elad Lahav
*/
class Encoder
{
public:
Encoder();
~Encoder();
const char* encode(const QString&);
const char* decode(const QString&);
private:
/** A buffer to contain the result of encoding/decoding. */
char* m_pBuf;
/** The buffer's length. */
int m_nBufLen;
void resize(int);
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

@ -0,0 +1,197 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qlineedit.h>
#include <qfileinfo.h>
#include <klocale.h>
#include "filelist.h"
#include "kscope.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
FileList::FileList(QWidget* pParent, const char* szName) :
SearchList(1, pParent, szName),
m_sRoot("/")
{
// Set the list's columns
m_pList->addColumn("");
m_pList->addColumn(i18n("File"));
m_pList->addColumn(i18n("Path"));
// Sort only when asked to by the user
if (Config().getAutoSortFiles())
m_pList->setSortColumn(1);
else
m_pList->setSortColumn(m_pList->columns() + 1);
m_pList->setAllColumnsShowFocus(true);
// Set colours and font
applyPrefs();
}
/**
* Class destructor.
*/
FileList::~FileList()
{
}
/**
* Adds a single entry to the file list.
* Implements the addItem() virtual method of the FileListTarget base
* class. When a FileList object is given as a parameter to
* ProjectManager::fillList(), this method is called for each file included
* in the project. A new list item is created, containing the file's name and
* path, and is added to the list.
* @param sFilePath The full path of a source file
*/
void FileList::addItem(const QString& sFilePath)
{
QString sFileType, sFileName, sPath;
int nTypePos;
// Extract the file name
sFileName = sFilePath.mid(sFilePath.findRev('/') + 1);
// Get the file's extension (empty string for file names without an
// extension)
nTypePos = sFileName.findRev('.');
if (nTypePos > -1)
sFileType = sFileName.mid(nTypePos + 1);
// If a root path has been set, use a $ sign instead of that part of the
// path
sPath = sFilePath;
if (m_sRoot != "/")
sPath.replace(m_sRoot, "$");
// Create the list item
new QListViewItem(m_pList, sFileType, sFileName, sPath);
}
/**
* Searches the list for the given file path.
* @param sPath The full path of the file to find
* @return true if the file was found in the list, false otherwise
*/
bool FileList::findFile(const QString& sPath)
{
QString sFindPath(sPath);
if (m_sRoot != "/")
sFindPath.replace(m_sRoot, "$");
return (m_pList->findItem(sFindPath, 2) != NULL);
}
/**
* Removes all items from the file list.
*/
void FileList::clear()
{
m_pList->clear();
m_pEdit->setText("");
}
/**
* Opens a file for editing when its entry is clicked in the file list.
* @param pItem The clicked list item
*/
void FileList::processItemSelected(QListViewItem* pItem)
{
QString sPath;
// Get the file path (replace the root symbol, if required)
sPath = pItem->text(2);
if (sPath.startsWith("$"))
sPath.replace("$", m_sRoot);
// Submit a request to open the file for editing
emit fileRequested(sPath, 0);
}
/**
* Sets the list's colours and font, according the user's preferences.
*/
void FileList::applyPrefs()
{
// Apply colour settings
m_pList->setPaletteBackgroundColor(Config().getColor(
KScopeConfig::FileListBack));
m_pList->setPaletteForegroundColor(Config().getColor(
KScopeConfig::FileListFore));
m_pList->setFont(Config().getFont(KScopeConfig::FileList));
}
/**
* Associates a root directory with this list.
* For each file in the list, the part of the path corresponding to the root
* is replaced with a $ sign.
* @param sRoot The new root path
*/
void FileList::setRoot(const QString& sRoot)
{
QListViewItem* pItem;
QString sPath;
// Update all items in the list
for (pItem = m_pList->firstChild(); pItem != NULL;
pItem = pItem->nextSibling()) {
sPath = pItem->text(2);
// Restore the full path
sPath.replace("$", m_sRoot);
// Replace the root with a $ sign
if (sRoot != "/")
sPath.replace(sRoot, "$");
pItem->setText(2, sPath);
}
// Store the new root
m_sRoot = sRoot;
}
/**
* Constructs a tool-tip for the given item.
* @param pItem The item for which a tip is required
* @param sTip The constructed tip string (on return)
* @return Always true
*/
bool FileList::getTip(QListViewItem* pItem, QString& sTip)
{
sTip = pItem->text(2);
return true;
}
#include "filelist.moc"

@ -0,0 +1,75 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef FILELIST_H
#define FILELIST_H
#include <qwidget.h>
#include "searchlist.h"
#include "projectmanager.h"
/**
* Implements a searchable list of files.
* The file list is composed of a list view, and a search box, into which the
* user can enter a file name. The name is matched against the contents of
* the list, and matching items are selected.
* @author Elad Lahav
*/
class FileList : public SearchList, public FileListTarget
{
Q_OBJECT
public:
FileList(QWidget* pParent = 0, const char* szName = 0);
~FileList();
virtual void addItem(const QString&);
bool findFile(const QString&);
void clear();
void applyPrefs();
void setRoot(const QString&);
virtual bool getTip(QListViewItem*, QString&);
signals:
/**
* Emitted when a file is selected, by either double-clicking a list
* item, or by highlighting an item and pressing the ENTER key.
* @param sPath The full path of the selected file
* @param nLine Line number, always set to 0
*/
void fileRequested(const QString& sPath, uint nLine);
protected:
virtual void processItemSelected(QListViewItem*);
private:
/** A common root path for all items in the list. */
QString m_sRoot;
};
#endif

@ -0,0 +1,131 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qpushbutton.h>
#include <qfileinfo.h>
#include <qtabwidget.h>
#include <kfiledialog.h>
#include "fileview.h"
#include "filelist.h"
#include "kscopepixmaps.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
* @param fl Widget creation flags
*/
FileView::FileView(QWidget* pParent, const char* szName, WFlags fl) :
FileViewLayout(pParent, szName, fl),
m_pCurBranch(0),
m_sRoot("")
{
QWidget* pPage;
// Set the tab widget icons
pPage = m_pTabWidget->page(0);
m_pTabWidget->setTabIconSet(pPage, GET_PIXMAP(TabFileList));
pPage = m_pTabWidget->page(1);
m_pTabWidget->setTabIconSet(pPage, GET_PIXMAP(TabFileTree));
// Create a single column for the file tree
m_pFileTree->addColumn("");
// Send the fileRequested() signal whenever a file is selected in either
// the list or the tree
connect(m_pFileList, SIGNAL(fileRequested(const QString&, uint)), this,
SIGNAL(fileRequested(const QString&, uint)));
connect(m_pFileTree, SIGNAL(doubleClicked(QListViewItem*)),
this, SLOT(slotTreeItemSelected(QListViewItem*)));
connect(m_pFileTree, SIGNAL(returnPressed(QListViewItem*)), this,
SLOT(slotTreeItemSelected(QListViewItem*)));
}
/**
* Class destructor.
*/
FileView::~FileView()
{
}
/**
* Sets a new common root path to both the file list and the tree.
* @param sRoot The full path of the new root
*/
void FileView::setRoot(const QString& sRoot)
{
// Nothing to do if the given root is the same as the old one
if (sRoot == m_sRoot)
return;
m_sRoot = sRoot;
// Remove the current branch
if (m_pCurBranch)
m_pFileTree->removeBranch(m_pCurBranch);
// Update the file list
m_pFileList->setRoot(sRoot);
// Nothing more to do for an empty root directory
if (sRoot.isEmpty())
return;
// Create and open a new branch, with the newly specified root
QFileInfo fi(sRoot);
m_pCurBranch = m_pFileTree->addBranch(KURL(sRoot), fi.fileName());
m_pCurBranch->setChildRecurse(false);
m_pFileTree->setOpen(m_pCurBranch->root(), true);
}
/**
* Clears the contents of the file view and file tree.
*/
void FileView::clear()
{
m_pFileList->clear();
setRoot("");
}
/**
* Emits the fileRequested() signal when a file name is selected in the file
* tree. An item is selected by either double-clicking it or by hittin
* "ENTER" when it is highlighted.
* This slot is connected to the doubleClicked() and returnPressed() signals
* of the KFileTreeView object.
* @param pItem The selected tree item
*/
void FileView::slotTreeItemSelected(QListViewItem* pItem)
{
KFileTreeViewItem* pTreeItem;
pTreeItem = (KFileTreeViewItem*)pItem;
if (pTreeItem && !pTreeItem->isDir())
emit fileRequested(pTreeItem->path(), 0);
}
#include "fileview.moc"

@ -0,0 +1,80 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef FILEVIEW_H
#define FILEVIEW_H
#include <kfiletreeview.h>
#include "fileviewlayout.h"
/**
* A tabbed widget that contains a file list and a file tree.
* The list is an object of type FileList, which displays all files included
* in the current project. The tree is a standard KFileTreeView, which can
* browse through the entire file system. Optionally, the root of the tree
* can be set per project.
* @author Elad Lahav
*/
class FileView : public FileViewLayout
{
Q_OBJECT
public:
FileView(QWidget* pParent = 0, const char* szName = 0, WFlags fl = 0);
~FileView();
/**
* @return The file list widget which is a child of this widget.
*/
FileList* getFileList() { return m_pFileList; }
void setRoot(const QString&);
void clear();
signals:
/**
* Emitted when a file is selected, by either double-clicking a list
* item, or by highlighting an item and pressing the ENTER key.
* @param sPath The full path of the selected file
* @param nLine Line number, always set to 0
*/
void fileRequested(const QString& sPath, uint nLine);
private:
/** The current branch in the file tree. */
KFileTreeBranch* m_pCurBranch;
/** The current root of the file tree. */
QString m_sRoot;
private slots:
void slotTreeItemSelected(QListViewItem*);
};
#endif

@ -0,0 +1,136 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>FileViewLayout</class>
<widget class="QWidget">
<property name="name">
<cstring>FileViewLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>364</width>
<height>639</height>
</rect>
</property>
<property name="caption">
<string>Form1</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<widget class="QTabWidget">
<property name="name">
<cstring>m_pTabWidget</cstring>
</property>
<property name="toolTip" stdset="0">
<string></string>
</property>
<widget class="QWidget">
<property name="name">
<cstring>tab</cstring>
</property>
<attribute name="title">
<string></string>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<widget class="FileList">
<property name="name">
<cstring>m_pFileList</cstring>
</property>
<property name="toolTip" stdset="0">
<string>Project File List</string>
</property>
</widget>
</vbox>
</widget>
<widget class="QWidget">
<property name="name">
<cstring>tab</cstring>
</property>
<attribute name="title">
<string></string>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<widget class="KFileTreeView">
<property name="name">
<cstring>m_pFileTree</cstring>
</property>
<property name="toolTip" stdset="0">
<string>File Tree</string>
</property>
</widget>
</vbox>
</widget>
</widget>
</vbox>
</widget>
<customwidgets>
<customwidget>
<class>FileList</class>
<header location="local">filelist.h</header>
<sizehint>
<width>-1</width>
<height>-1</height>
</sizehint>
<container>0</container>
<sizepolicy>
<hordata>7</hordata>
<verdata>7</verdata>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<pixmap>image0</pixmap>
</customwidget>
<customwidget>
<class>KFileTreeView</class>
<header location="global">kfiletreeview.h</header>
<sizehint>
<width>-1</width>
<height>-1</height>
</sizehint>
<container>0</container>
<sizepolicy>
<hordata>7</hordata>
<verdata>7</verdata>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<pixmap>image0</pixmap>
</customwidget>
</customwidgets>
<images>
<image name="image0">
<data format="XBM.GZ" length="79">789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f</data>
</image>
</images>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>filelist.h</includehint>
<includehint>kfiletreeview.h</includehint>
</includehints>
</UI>

@ -0,0 +1,365 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qfileinfo.h>
#include <qdir.h>
#include <klocale.h>
#include "frontend.h"
/**
* Class constructor.
* @param nRecordSize The number of fields in each record
* @param bAutoDelete (Optional) true to delete the object when the process
* terminates, false (default) otherwise
*/
Frontend::Frontend(uint nRecordSize, bool bAutoDelete) : KProcess(),
m_nRecords(0),
m_pHeadToken(NULL),
m_pTailToken(NULL),
m_pCurToken(NULL),
m_bAutoDelete(bAutoDelete),
m_bInToken(false),
m_nRecordSize(nRecordSize)
{
// Parse data on the standard output
connect(this, SIGNAL(receivedStdout(KProcess*, char*, int)), this,
SLOT(slotReadStdout(KProcess*, char*, int)));
// Parse data on the standard error
connect(this, SIGNAL(receivedStderr(KProcess*, char*, int)), this,
SLOT(slotReadStderr(KProcess*, char*, int)));
// Delete the process object when the process exits
connect(this, SIGNAL(processExited(KProcess*)), this,
SLOT(slotProcessExit(KProcess*)));
}
/**
* Class destructor.
*/
Frontend::~Frontend()
{
// Delete all pending tokens
while (m_pHeadToken)
removeToken();
}
/**
* Executes the back-end process.
* @param sName The name of the process (for error messages)
* @param slArgs A list containing the command-line arguments
* @param sWorkDir (Optional) working directory
* @param bBlock (Optional) true to block, false otherwise
* @return true if the process was executed successfully, false otherwise
*/
bool Frontend::run(const QString& sName, const QStringList& slArgs,
const QString& sWorkDir, bool bBlock)
{
// Cannot start if another controlled process is currently running
if (isRunning()) {
m_sError = i18n("Cannot restart while another process is still "
"running");
return false;
}
// Reset variables
m_nRecords = 0;
m_bKilled = false;
// Setup the command-line arguments
clearArguments();
*this << slArgs;
// Set the working directory, if requested
if (!sWorkDir.isEmpty())
setWorkingDirectory(sWorkDir);
// Execute the child process
if (!start(bBlock ? KProcess::Block : KProcess::NotifyOnExit,
KProcess::All)) {
m_sError = sName + i18n(": Failed to start process");
return false;
}
m_sError = i18n("No error");
return true;
}
/**
* Kills the process, and emits the aborted() signal.
* This function should not be called unless the process needs to be
* interrupted.
*/
void Frontend::kill()
{
m_bKilled = true;
KProcess::kill();
emit aborted();
}
/**
* Appends a token to the end of the token list.
* @param pToken The token to add
*/
void Frontend::addToken(FrontendToken* pToken)
{
// Check if this is the firt token
if (m_pHeadToken == NULL) {
m_pHeadToken = pToken;
m_pTailToken = pToken;
}
else {
// Not the first token, append and reset the tail token
m_pTailToken->m_pNext = pToken;
m_pTailToken = pToken;
}
}
/**
* Removes and deletes the token at the head of the token list.
*/
void Frontend::removeToken()
{
FrontendToken* pToken;
if (m_pHeadToken == NULL)
return;
pToken = m_pHeadToken;
m_pHeadToken = m_pHeadToken->m_pNext;
delete pToken;
if (m_pHeadToken == NULL)
m_pTailToken = NULL;
}
/**
* Removes tokens from the head of the list, according to the size of a
* record.
*/
void Frontend::removeRecord()
{
uint i;
for (i = 0; (i < m_nRecordSize) && (m_pHeadToken != NULL); i++)
removeToken();
}
/**
* Extracts tokens of text out of a given buffer.
* @param ppBuf Points to the buffer to parse, and is set to the
* beginning of the next token, upon return
* @param pBufSize Points to the size of the buffer, and is set to the
* remaining size, upon return
* @param sResult Holds the token's text, upon successful return
* @param delim Holds the delimiter by which the token's end was
* determined
* @return true if a token was extracted up to the given delimter(s), false
* if the buffer ended before a delimiter could be identified
*/
bool Frontend::tokenize(char** ppBuf, int* pBufSize, QString& sResult,
ParserDelim& delim)
{
int nSize;
char* pBuf;
bool bDelim, bWhiteSpace, bFoundToken = false;
// Iterate buffer
for (nSize = *pBufSize, pBuf = *ppBuf; (nSize > 0) && !bFoundToken;
nSize--, pBuf++) {
// Test if this is a delimiter character
switch (*pBuf) {
case '\n':
bDelim = ((m_delim & Newline) != 0);
bWhiteSpace = true;
delim = Newline;
break;
case ' ':
bDelim = ((m_delim & Space) != 0);
bWhiteSpace = true;
delim = Space;
break;
case '\t':
bDelim = ((m_delim & Tab) != 0);
bWhiteSpace = true;
delim = Tab;
break;
default:
bDelim = false;
bWhiteSpace = false;
}
if (m_bInToken && bDelim) {
m_bInToken = false;
*pBuf = 0;
bFoundToken = true;
}
else if (!m_bInToken && !bWhiteSpace) {
m_bInToken = true;
*ppBuf = pBuf;
}
}
// Either a token was found, or the search through the buffer was
// finished without a delimiter character
if (bFoundToken) {
sResult = *ppBuf;
*ppBuf = pBuf;
*pBufSize = nSize;
}
else if (m_bInToken) {
sResult = QString::fromLatin1(*ppBuf, *pBufSize);
}
else {
sResult = QString::null;
}
return bFoundToken;
}
/**
* Handles text sent by the back-end process to the standard error stream.
* By default, this method emits the error() signal with the given text.
* @param sText The text sent to the standard error stream
*/
void Frontend::parseStderr(const QString& sText)
{
emit error(sText);
}
/**
* Deletes the process object upon the process' exit.
*/
void Frontend::slotProcessExit(KProcess*)
{
// Allow specialised clean-up by inheriting classes
finalize();
// Signal the process has terminated
emit finished(m_nRecords);
// Delete the object, if required
if (m_bAutoDelete)
delete this;
}
/**
* Reads data written on the standard output by the controlled process.
* This is a private slot called attached to the readyReadStdout() signal of
* the controlled process, which means that it is called whenever data is
* ready to be read from the process' stream.
* The method reads whatever data is queued, and sends it to be interpreted
* by parseStdout().
*/
void Frontend::slotReadStdout(KProcess*, char* pBuffer, int nSize)
{
char* pLocalBuf;
QString sToken;
bool bTokenEnded;
ParserDelim delim;
// Do nothing if waiting for process to die
if (m_bKilled)
return;
pLocalBuf = pBuffer;
// Iterate over the given buffer
while (nSize > 0) {
// Create a new token, if the last iteration has completed one
if (m_pCurToken == NULL)
m_pCurToken = new FrontendToken();
// Extract text until the requested delimiter
bTokenEnded = tokenize(&pLocalBuf, &nSize, sToken, delim);
// Add the extracted text to the current token
m_pCurToken->m_sData += sToken;
// If the buffer has ended before the requested delimiter, we need
// to wait for more output from the process
if (!bTokenEnded)
return;
// Call the process-specific parser function
switch (parseStdout(m_pCurToken->m_sData, delim)) {
case DiscardToken:
// Token should not be saved
delete m_pCurToken;
break;
case AcceptToken:
// Store token in linked list
addToken(m_pCurToken);
break;
case RecordReady:
// Store token, and notify the target object that an entry can
// be read
m_nRecords++;
addToken(m_pCurToken);
emit dataReady(m_pHeadToken);
// Delete all tokens in the entry
removeRecord();
break;
case Abort:
kill();
nSize = 0;
break;
}
m_pCurToken = NULL;
}
}
/**
* Reads data written on the standard error by the controlled process.
* This is a private slot called attached to the readyReadStderr() signal of
* the controlled process, which means that it is called whenever data is
* ready to be read from the process' stream.
* The method reads whatever data is queued, and sends it to be interpreted
* by parseStderr().
*/
void Frontend::slotReadStderr(KProcess*, char* pBuffer, int nSize)
{
QString sBuf;
// Do nothing if waiting for process to die
if (m_bKilled)
return;
sBuf.setLatin1(pBuffer, nSize);
parseStderr(sBuf);
}
#include "frontend.moc"

@ -0,0 +1,212 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef FRONTEND_H
#define FRONTEND_H
#include <qobject.h>
#include <kprocess.h>
/**
* Represents a single token in the parsed output stream.
* @author Elad Lahav
*/
class FrontendToken
{
public:
/**
* Class constructor.
*/
FrontendToken() : m_pNext(NULL) {}
/**
* @return The text associated with this token
*/
const QString& getData() const { return m_sData; }
/**
* @return A pointer to the next token in the strem.
*/
FrontendToken* getNext() const { return m_pNext; }
protected:
/** Free text associated with the token. */
QString m_sData;
/** A pointer to the next token in the stream. */
FrontendToken* m_pNext;
friend class Frontend;
};
/**
* Abstract base class that provides a front-end to console-based programmes.
* Provides a parsing infrastructure which is based on a list of records, all
* of the same structure. Each record is composed of a number of delimited
* fields (tokens.)
* @author Elad Lahav
*/
class Frontend : public KProcess
{
Q_OBJECT
public:
Frontend(uint, bool bAutoDelete = false);
~Frontend();
virtual bool run(const QString&, const QStringList&,
const QString& sWorkDir = "", bool bBlock = false);
void kill();
/**
* @return An string describing the error which made run() fail
*/
const QString& getRunError() { return m_sError; }
signals:
/**
* Indicates tokens can be read.
* The Frontend object parses the back-end output and creates a list of
* tokens. This signal is emitted when a batch of characters has been
* converted into a token list.
* @param pToken The head of the token list
*/
void dataReady(FrontendToken* pToken);
/**
* Emitted when the back-end process terminates.
* @param nRecords The number of complete records parsed
*/
void finished(uint nRecords);
/**
* Indicates that the Cscope process was terminated.
*/
void aborted();
/**
* This signal is used to report the progress of the back-end process.
* @param nProgress The current progress value
* @param nTotal The progress value that indicates the process
* is finished
*/
void progress(int nProgress, int nTotal);
/**
* Emitted when an error message is produced by the back-end process.
*/
void error(const QString& sMsg);
protected:
/** A set of possible delimiters for parsing process output. */
enum ParserDelim { Newline = 0x01, Space = 0x02, Tab = 0x04,
WSpace = Space | Tab, All = WSpace | Newline };
/** Defines the set of return values for parseStdout(). Determines what
needs to be done with a new token passed to this method. */
enum ParseResult {
DiscardToken /** Delete this token */,
AcceptToken /** Add this token to the list */,
RecordReady /** This token completes a record */,
Abort /** Kill the process */
};
/** Number of complete records read so far. */
uint m_nRecords;
/** The head of the list of parsed output tokens. */
FrontendToken* m_pHeadToken;
/** The tail of the list of parsed output tokens. */
FrontendToken* m_pTailToken;
/** An iterator on the list of parsed output tokens. */
FrontendToken* m_pCurToken;
/** The current delimiters used for parsing the output. */
ParserDelim m_delim;
/** An error string produced if run() fails. */
QString m_sError;
/**
* Handles a text token received on the Standard Output stream of the
* controlled process.
* This is called by slotReadStdout whenever a new token is recognised.
* Inheriting classes should implement this method to parse the resutling
* stream of tokens.
* @param sToken A part of the text received on the Standard Output,
* disected according to current delimiter settings
* @param delim The delimiter that ended this token
* @result A ParseResult value, indicating what should be done with the
* new token
*/
virtual ParseResult parseStdout(QString& sToken, ParserDelim delim) = 0;
virtual void parseStderr(const QString&);
/**
* Called when the process exits.
* Allows inheriting classes to implement process termination handlers.
*/
virtual void finalize() {}
protected slots:
virtual void slotProcessExit(KProcess*);
private:
/** Determines whether the object should be deleted once the process has
exited */
bool m_bAutoDelete;
/** Determines whether the parser is in the middle of a token, or between
two tokens */
bool m_bInToken;
/** The number of fields in each parsed record. Should be defined for
every sub-class. */
uint m_nRecordSize;
/** This flag is raised when kill() is called. It signifies that even
though the process may not be dead yet, it should be considered as
such. */
bool m_bKilled;
void addToken(FrontendToken*);
void removeToken();
void removeRecord();
bool tokenize(char**, int*, QString&, ParserDelim&);
private slots:
void slotReadStdout(KProcess*, char*, int);
void slotReadStderr(KProcess*, char*, int);
};
#endif

@ -0,0 +1,306 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <math.h>
#include <stdlib.h>
#include <qpainter.h>
#include "graphedge.h"
#include "graphnode.h"
int GraphEdge::RTTI = 1002;
// Some definitions required by the ConvexHull class
typedef int (*CompFunc)(const void*, const void*);
#define ISLEFT(P0, P1, P2) \
(P1.x() - P0.x()) * (P2.y() - P0.y()) - \
(P2.x() - P0.x()) * (P1.y() - P0.y())
#define FARTHEST(P0, P1, P2) \
((P1.x() - P0.x()) * (P1.x() - P0.x()) - \
(P1.y() - P0.y()) * (P1.y() - P0.y())) - \
((P2.x() - P0.x()) * (P2.x() - P0.x()) - \
(P2.y() - P0.y()) * (P2.y() - P0.y()))
/**
* An array of QPoint objects that can compute the convex hull surrounding all
* points in the array.
* @author Elad Lahav
*/
class ConvexHull : public QPointArray
{
public:
/**
* Class constructor.
*/
ConvexHull() : QPointArray() {}
/**
* Computes the convex hull of the points stored in the array, using
* Graham's scan.
* @param arrHull Holds the coordinates of the convex hull, upon return
*/
void compute(QPointArray& arrHull) {
uint i, nPivot, nTop;
// Find the pivot point
nPivot = 0;
for (i = 1; i < size(); i++) {
if ((*this)[i].y() < (*this)[nPivot].y()) {
nPivot = i;
}
else if ((*this)[i].y() == (*this)[nPivot].y() &&
(*this)[i].x() < (*this)[nPivot].x()) {
nPivot = i;
}
}
// Sort points in radial order, relative to the pivot
s_ptPivot = (*this)[nPivot];
(*this)[nPivot] = (*this)[0];
(*this)[0] = s_ptPivot;
qsort(&(*this).data()[1], (*this).size() - 1, sizeof(QPoint),
(CompFunc)compRadial);
// Initialise Graham's scan algorithm
arrHull.resize(size() + 1);
arrHull[0] = (*this)[0];
arrHull[1] = (*this)[1];
nTop = 1;
// Compute the convex hull
for (i = 2; i < size();) {
// TODO: According to the algorithm, the condition should be >0
// for pushing the point into the stack. For some reason, it works
// only with <0. Why?
if (ISLEFT(arrHull[nTop - 1], arrHull[nTop], (*this)[i]) < 0) {
arrHull[++nTop] = (*this)[i];
i++;
}
else {
nTop--;
}
}
// Close the hull
arrHull[++nTop] = (*this)[0];
arrHull.truncate(nTop + 1);
}
private:
/** The current pivot point, required by compRadial. */
static QPoint s_ptPivot;
/**
* Compares two points based on their angle relative to the current
* pivot point.
* This function is passed as the comparison function of qsort().
* @param pPt1 A pointer to the first point
* @param pPt2 A pointer to the second point
* @return >0 if the first point is to the left of the second, <0 otherwise
*/
static int compRadial(const QPoint* pPt1, const QPoint* pPt2) {
int nResult;
// Determine which point is to the left of the other. If the angle is
// the same, the greater point is the one farther from the pivot
nResult = ISLEFT(s_ptPivot, (*pPt1), (*pPt2));
if (nResult == 0)
return FARTHEST(s_ptPivot, (*pPt1), (*pPt2));
return nResult;
}
};
QPoint ConvexHull::s_ptPivot;
/**
* Class constructor.
* @param pCanvas The canvas on which to draw the edge
* @param pHead The edge's starting point
* @param pTail The edge's end point
*/
GraphEdge::GraphEdge(QCanvas* pCanvas, GraphNode* pHead, GraphNode* pTail) :
QCanvasPolygonalItem(pCanvas),
m_pHead(pHead),
m_pTail(pTail),
m_arrPoly(4)
{
}
/**
* Class destructor.
*/
GraphEdge::~GraphEdge()
{
// Classes derived from QCanvasPolygonalItem must call hide() in their
// detructor (according to the Qt documentation)
hide();
}
/**
* Calculates the area surrounding the edge, and the bounding rectangle of
* the edge's polygonal head.
* The calculated area is used to find items on the canvas and to display
* tips. The bounding rectangle defines the tip's region (@see QToolTip).
* TODO: The function assumes that the we can simply append the polygon's
* array to that of the splines. Is this always the case, or should we sort
* the points of the polygon in radial order?
* @param arrCurve The control points of the edge's spline
* @param ai Used to calculate the arrow head polygon
*/
void GraphEdge::setPoints(const QPointArray& arrCurve, const ArrowInfo& ai)
{
ConvexHull ch;
uint i;
int nXpos, nYpos;
// Redraw an existing edge
if (m_arrArea.size() > 0)
invalidate();
// Store the point array for drawing
m_arrCurve = arrCurve;
// Calculate the arrowhead's polygon
makeArrowhead(ai);
// Compute the convex hull of the edge
ch.resize(m_arrCurve.size() + m_arrPoly.size() - 2);
ch.putPoints(0, m_arrCurve.size() - 1, m_arrCurve);
ch.putPoints(m_arrCurve.size() - 1, m_arrPoly.size() - 1, m_arrPoly);
ch.compute(m_arrArea);
// Calculate the head's bounding rectangle
m_rcTip = QRect(m_arrPoly[0], m_arrPoly[0]);
for (i = 1; i < m_arrPoly.size(); i++) {
nXpos = m_arrPoly[i].x();
if (nXpos < m_rcTip.left())
m_rcTip.setLeft(nXpos);
else if (nXpos > m_rcTip.right())
m_rcTip.setRight(nXpos);
nYpos = m_arrPoly[i].y();
if (nYpos < m_rcTip.top())
m_rcTip.setTop(nYpos);
else if (nYpos > m_rcTip.bottom())
m_rcTip.setBottom(nYpos);
}
}
/**
* Sets the call information associated with this edge.
* @param sFile The call's file path
* @param sLine The call's line number
* @param sText The call's text
*/
void GraphEdge::setCallInfo(const QString& sFile, const QString& sLine,
const QString& sText)
{
m_sFile = sFile;
m_sLine = sLine;
m_sText = sText;
}
/**
* Constructs a tool-tip string for this edge.
* @return The tool-tip text
*/
QString GraphEdge::getTip() const
{
QString sTip;
sTip = m_sText + "<br><i>" + m_sFile + "</i>:" + m_sLine;
return sTip;
}
/**
* Draws the spline as a sequence of cubic Bezier curves.
* @param painter Used for drawing the item on the canvas view
*/
void GraphEdge::drawShape(QPainter& painter)
{
uint i;
// Draw the polygon
painter.drawConvexPolygon(m_arrPoly);
// Draw the Bezier curves
for (i = 0; i < m_arrCurve.size() - 1; i += 3)
painter.drawCubicBezier(m_arrCurve, i);
#if 0
// Draws the convex hull of the edge
QPen pen = painter.pen();
QBrush br = painter.brush();
painter.setPen(QPen(QColor(255, 0, 0)));
painter.setBrush(QBrush());
painter.drawPolygon(m_arrArea);
painter.setPen(pen);
painter.setBrush(br);
#endif
}
/**
* Computes the coordinates of the edge's arrow head, based on its curve.
* @param ai Pre-computed values used for all edges
*/
void GraphEdge::makeArrowhead(const ArrowInfo& ai)
{
QPoint ptLast, ptPrev;
double dX1, dY1, dX0, dY0, dX, dY, dDeltaX, dDeltaY, dNormLen;
// The arrowhead follows the line from the second last to the last points
// in the curve
ptLast = m_arrCurve[m_arrCurve.size() - 1];
ptPrev = m_arrCurve[m_arrCurve.size() - 2];
// The first and last points of the polygon are the end of the curve
m_arrPoly.setPoint(0, ptLast.x(), ptLast.y());
m_arrPoly.setPoint(3, ptLast.x(), ptLast.y());
// Convert integer points to double precision values
dX1 = (double)ptLast.x();
dY1 = (double)ptLast.y();
dX0 = (double)ptPrev.x();
dY0 = (double)ptPrev.y();
// The values (x1-x0), (y1-y0) and sqrt(1 + tan(theta)^2) are useful
dDeltaX = dX1 - dX0;
dDeltaY = dY1 - dY0;
// The normalised length of the arrow's sides
dNormLen = ai.m_dLength / sqrt(dDeltaX * dDeltaX + dDeltaY * dDeltaY);
// Compute the other two points
dX = dX1 - ((dDeltaX - ai.m_dTan * dDeltaY) / ai.m_dSqrt) * dNormLen;
dY = dY1 - ((dDeltaY + ai.m_dTan * dDeltaX) / ai.m_dSqrt) * dNormLen;
m_arrPoly.setPoint(1, (int)dX, (int)dY);
dX = dX1 - ((dDeltaX + ai.m_dTan * dDeltaY) / ai.m_dSqrt) * dNormLen;
dY = dY1 - ((dDeltaY - ai.m_dTan * dDeltaX) / ai.m_dSqrt) * dNormLen;
m_arrPoly.setPoint(2, (int)dX, (int)dY);
}

@ -0,0 +1,143 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef GRAPHEDGE_H
#define GRAPHEDGE_H
#include <qcanvas.h>
class GraphNode;
/**
* Information used to draw arrow heads at the end of graph edges.
*/
struct ArrowInfo
{
/** The length of the arrow. */
double m_dLength;
/** The tangent of the arrow's angle from the main line. */
double m_dTan;
/** Holds the value sqrt(1 + dTan^2). */
double m_dSqrt;
};
/**
* Draws a directed edge on a canvas.
* The edge is composed of a spline, which is its body, and a polygon, which
* is its head.
* @author Elad Lahav
*/
class GraphEdge : public QCanvasPolygonalItem
{
public:
GraphEdge(QCanvas*, GraphNode*, GraphNode*);
~GraphEdge();
void setCallInfo(const QString&, const QString&, const QString&);
void setPoints(const QPointArray&, const ArrowInfo&);
QString getTip() const;
/**
* @return The coordinates of the convex hull surrounding the edge
*/
virtual QPointArray areaPoints() const { return m_arrArea; }
/**
* @return The head node of the edge
*/
GraphNode* getHead() { return m_pHead; }
/**
* @return The tail node of the edge
*/
GraphNode* getTail() { return m_pTail; }
/**
* @return The bounding rectangle of the edge's head
*/
QRect tipRect() const { return m_rcTip; }
/**
* @return The file path for this call
*/
const QString& getFile() const { return m_sFile; }
/**
* @return The line number for this call
*/
uint getLine() const { return m_sLine.toUInt(); }
/**
* @return The call's text
*/
const QString& getText() const { return m_sText; }
/** Identifies this class among other QCanvasItem classes. */
static int RTTI;
/**
* @return The class identifier
*/
virtual int rtti() const { return RTTI; }
protected:
virtual void drawShape(QPainter&);
private:
/** The edge's starting point. */
GraphNode* m_pHead;
/** The edge's end point. */
GraphNode* m_pTail;
/** The points of the polygon part of the edge. */
QPointArray m_arrPoly;
/** Control points for the spline part of the edge. */
QPointArray m_arrCurve;
QPointArray m_arrArea;
/** The bounding rectangle of the edge's head, used for displaying the
edge's tool-tip. */
QRect m_rcTip;
/** The call's source file. */
QString m_sFile;
/** The call's line number. */
QString m_sLine;
/** The call's text. */
QString m_sText;
void makeArrowhead(const ArrowInfo&);
};
#endif

@ -0,0 +1,192 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qpainter.h>
#include <qfontmetrics.h>
#include "graphnode.h"
int GraphNode::RTTI = 1001;
/**
* Class constructor.
* @param pCanvas The owner canvas
* @param sFunc The node's function
* @param bMultiCall Whether this node represents multiple calls
*/
GraphNode::GraphNode(QCanvas* pCanvas, const QString& sFunc, bool bMultiCall) :
QCanvasPolygon(pCanvas),
m_sFunc(sFunc),
m_bMultiCall(bMultiCall),
m_bDfsFlag(false)
{
// Every node deletes its out-edges only
m_dictOutEdges.setAutoDelete(true);
}
/**
* Class destructor.
*/
GraphNode::~GraphNode()
{
}
/**
* Finds an edge leaving this node and reaching the given node.
* If such an edge does not exist, a new one is created.
* @param pTail The destination node
* @return The edge that ends at the given node
*/
GraphEdge* GraphNode::addOutEdge(GraphNode* pTail)
{
GraphEdge* pEdge;
// Look for the edge
if ((pEdge = m_dictOutEdges.find(pTail->getFunc())) == NULL) {
// Create a new edge
pEdge = new GraphEdge(canvas(), this, pTail);
m_dictOutEdges.insert(pTail->getFunc(), pEdge);
pTail->m_dictInEdges.replace(m_sFunc, pEdge);
}
// Return the new/constructed edge
return pEdge;
}
/**
* Performs a weak depth-first-search on the graph.
* The search continues along all edges, both incoming and outgoing.
*/
void GraphNode::dfs()
{
// Stop if this node is already marked
if (m_bDfsFlag)
return;
// Mark the node as visited
m_bDfsFlag = true;
// Continue along outgoing edges
QDictIterator<GraphEdge> itrOut(m_dictOutEdges);
for (; itrOut.current(); ++itrOut)
(*itrOut)->getTail()->dfs();
// Continue along incoming edges
QDictIterator<GraphEdge> itrIn(m_dictInEdges);
for (; itrIn.current(); ++itrIn)
(*itrIn)->getHead()->dfs();
}
/**
* Deletes all outgoing edges.
* Uses the auto-delete property of the dictionary.
*/
void GraphNode::removeOutEdges()
{
m_dictOutEdges.clear();
}
/**
* Deletes all incoming edges.
* To avoid double deletions, the function lets the head node of the edge remove
* it.
*/
void GraphNode::removeInEdges()
{
QDictIterator<GraphEdge> itr(m_dictInEdges);
// Delete edges through their head nodes
for (; itr.current(); ++itr)
(*itr)->getHead()->m_dictOutEdges.remove(m_sFunc);
// remove edges from the local dictionary (will not delete them)
m_dictInEdges.clear();
}
/**
* Returns the first found node connected to this one.
* This function is used with multi-call nodes for retrieving the parent node.
* @param pNode
* @param bCalled
*/
void GraphNode::getFirstNeighbour(GraphNode*& pNode, bool& bCalled)
{
QDictIterator<GraphEdge> itrIn(m_dictInEdges);
QDictIterator<GraphEdge> itrOut(m_dictOutEdges);
if (itrIn.current()) {
pNode = itrIn.current()->getHead();
bCalled = false;
}
else if (itrOut.current()) {
pNode = itrOut.current()->getTail();
bCalled = true;
}
else {
pNode = NULL;
}
}
/**
* Modifies the bounding rectangle of the node.
* @param rect The new coordinates to set
*/
void GraphNode::setRect(const QRect& rect)
{
QPointArray arr(4);
m_rect = rect;
arr.setPoint(0, m_rect.topLeft());
arr.setPoint(1, m_rect.topRight());
arr.setPoint(2, m_rect.bottomRight());
arr.setPoint(3, m_rect.bottomLeft());
setPoints(arr);
}
/**
* Draws the node.
* @param painter Used for drawing the item on the canvas view
*/
void GraphNode::drawShape(QPainter& painter)
{
const QPen& pen = painter.pen();
const QFont& font = painter.font();
// Draw the rectangle
painter.setPen(QPen(Qt::black));
painter.drawRect(m_rect);
// Draw the text
painter.setPen(pen);
painter.setFont(m_font);
if (m_bMultiCall)
painter.drawText(m_rect, Qt::AlignCenter, "...");
else
painter.drawText(m_rect, Qt::AlignCenter, m_sFunc);
painter.setFont(font);
}

@ -0,0 +1,123 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef GRAPHNODE_H
#define GRAPHNODE_H
#include <qcanvas.h>
#include <qdict.h>
#include "graphedge.h"
/**
* A canvas item that draws the name of a function insider a filled rectangle.
* This item represents a function in the call graph.
* @author Elad Lahav
*/
class GraphNode : public QCanvasPolygon
{
public:
GraphNode(QCanvas* pCanvas, const QString&, bool bMultiCall = false);
~GraphNode();
GraphEdge* addOutEdge(GraphNode*);
void dfs();
void removeOutEdges();
void removeInEdges();
void getFirstNeighbour(GraphNode*&, bool&);
/**
* @param rect The bounding rectangle of the node
*/
void setRect(const QRect& rect);
/**
* @param font The font to use for drawing the text
*/
void setFont(const QFont& font) { m_font = font; }
/**
* @return The name of the function
*/
const QString& getFunc() const { return m_sFunc; }
/**
* @return true for a multiple-call node, false otherwise
*/
bool isMultiCall() { return m_bMultiCall; }
/**
* @return The set of outgoing edges
*/
QDict<GraphEdge>& getOutEdges() { return m_dictOutEdges; }
/**
* @return true if this node was already visited during the current DFS,
* false otherwise
*/
bool dfsVisited() { return m_bDfsFlag; }
/**
* Clears the 'DFS-visited' flag, in preparation for the next DFS.
*/
void dfsReset() { m_bDfsFlag = false; }
/** Identifies this class among other QCanvasItem classes. */
static int RTTI;
/**
* @return The class identifier
*/
virtual int rtti() const { return RTTI; }
protected:
virtual void drawShape(QPainter&);
private:
/** Function name. */
QString m_sFunc;
/** A list of outgoing edges indexed by destination. */
QDict<GraphEdge> m_dictOutEdges;
/** A list of incoming edges indexed by destination. */
QDict<GraphEdge> m_dictInEdges;
/** The bounding rectangle for the node. */
QRect m_rect;
/** The font to use for drawing the text. */
QFont m_font;
/** true for a multiple-call node, false otherwise. */
bool m_bMultiCall;
/** Determines whether this node was visited during a depth-first
search. */
bool m_bDfsFlag;
};
#endif

@ -0,0 +1,82 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qspinbox.h>
#include "graphprefdlg.h"
#include "preferencesdlg.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
GraphPrefDlg::GraphPrefDlg(QWidget* pParent, const char* szName) :
GraphPrefLayout(pParent, szName, true, 0)
{
m_pMaxDegSpin->setValue(Config().getGraphMaxNodeDegree());
}
/**
* Class destructor.
*/
GraphPrefDlg::~GraphPrefDlg()
{
}
/**
* @return The maximal degree value set in the spin box
*/
int GraphPrefDlg::getMaxNodeDegree()
{
return m_pMaxDegSpin->value();
}
/**
* Displays the general preferences dialogue, showing the "Colours" page.
* This slot is connected to the clicked() signal of the colours button.
*/
void GraphPrefDlg::slotFontClicked()
{
PreferencesDlg dlg(PreferencesDlg::Fonts);
dlg.exec();
}
/**
* Displays the general preferences dialogue, showing the "Fonts" page.
* This slot is connected to the clicked() signal of the fonts button.
*/
void GraphPrefDlg::slotColorClicked()
{
PreferencesDlg dlg(PreferencesDlg::Colors);
dlg.exec();
}
#include "graphprefdlg.moc"

@ -0,0 +1,54 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef GRAPHPREFDLG_H
#define GRAPHPREFDLG_H
#include "graphpreflayout.h"
/**
* A dialogue that allows the user to configure the appearance and behaviour
* of the call graph.
* @author Elad Lahav
*/
class GraphPrefDlg : public GraphPrefLayout
{
Q_OBJECT
public:
GraphPrefDlg(QWidget* pParent = 0, const char* szName = 0);
~GraphPrefDlg();
int getMaxNodeDegree();
protected slots:
virtual void slotFontClicked();
virtual void slotColorClicked();
};
#endif

@ -0,0 +1,262 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>GraphPrefLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>GraphPrefLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>328</width>
<height>164</height>
</rect>
</property>
<property name="caption">
<string>Call Graph Preferences</string>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout6</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="text">
<string>Maximal In/Out Node Degree</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer2</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>81</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QSpinBox">
<property name="name">
<cstring>m_pMaxDegSpin</cstring>
</property>
</widget>
</hbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout7</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel2</cstring>
</property>
<property name="text">
<string>Colours</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer3</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>131</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pColorButton</cstring>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</hbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout8</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel3</cstring>
</property>
<property name="text">
<string>Fonts</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer4</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>121</width>
<height>31</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pFontButton</cstring>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</hbox>
</widget>
<widget class="Line">
<property name="name">
<cstring>line1</cstring>
</property>
<property name="frameShape">
<enum>HLine</enum>
</property>
<property name="frameShadow">
<enum>Sunken</enum>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>Layout1</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<spacer>
<property name="name">
<cstring>Horizontal Spacing2</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>buttonOk</cstring>
</property>
<property name="text">
<string>&amp;OK</string>
</property>
<property name="accel">
<string></string>
</property>
<property name="autoDefault">
<bool>true</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>buttonCancel</cstring>
</property>
<property name="text">
<string>&amp;Cancel</string>
</property>
<property name="accel">
<string></string>
</property>
<property name="autoDefault">
<bool>true</bool>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<connections>
<connection>
<sender>buttonOk</sender>
<signal>clicked()</signal>
<receiver>GraphPrefLayout</receiver>
<slot>accept()</slot>
</connection>
<connection>
<sender>buttonCancel</sender>
<signal>clicked()</signal>
<receiver>GraphPrefLayout</receiver>
<slot>reject()</slot>
</connection>
<connection>
<sender>m_pColorButton</sender>
<signal>clicked()</signal>
<receiver>GraphPrefLayout</receiver>
<slot>slotColorClicked()</slot>
</connection>
<connection>
<sender>m_pFontButton</sender>
<signal>clicked()</signal>
<receiver>GraphPrefLayout</receiver>
<slot>slotFontClicked()</slot>
</connection>
</connections>
<slots>
<slot access="protected">slotColorClicked()</slot>
<slot access="protected">slotFontClicked()</slot>
</slots>
<layoutdefaults spacing="6" margin="11"/>
</UI>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,213 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef GRAPHWIDGET_H
#define GRAPHWIDGET_H
#include <qcanvas.h>
#include <qpopupmenu.h>
#include <qdict.h>
#include "cscopefrontend.h"
#include "graphnode.h"
#include "dotfrontend.h"
class ProgressDlg;
/**
* A widget that displays call tree graphs generated by graphviz.
* This class is based on a QCanvasView widget, and displays two types of
* canvas items: GraphNode, which draws the name of a function inside a
* polygon, and ArrowEdge, which is a directed graph edge shaped like an
* arrow.
* The call tree graph is populated using the addNode() method. The first
* call creates a root node. Subsequent calls add nodes which represent either
* functions called by a previously inserted node, or that are calling such
* a node. A directed edge is created to depict the relationship between a
* node and its parent.
* Drawing is done through the embedded Agraph_t object (a graph, as defined
* by the graphviz libraray). When the draw() method is called, the graph is
* layed out in memory. The class then uses the CodeGenerator class to
* obtain a set of instructions on how to actually draw the graph. These
* instructions are used to create the appropriate canvas items.
* An application _must_ call GraphWidget::init() before attempting to use
* this class. It should also call GraphWidget::fini() when it no longer needs
* any of these widgets.
* @author Elad Lahav
*/
class GraphWidget : public QCanvasView
{
Q_OBJECT
public:
GraphWidget(QWidget* pParent = 0, const char* szName = 0);
~GraphWidget();
/**
* Information on a function call, as produced by a Cscope query.
* This structure is used for adding calls to the graph.
* @see addCall()
*/
struct CallData
{
/** The name of the calling function. */
QString m_sCaller;
/** The name of the called function. */
QString m_sCallee;
/** Path of the file in which the call appears. */
QString m_sFile;
/** The line number of the call. */
QString m_sLine;
/** The call's text. */
QString m_sText;
};
/** Graph orientation values. */
enum Orientation { Portrait, Landscape };
void setRoot(const QString&);
GraphNode* addNode(const QString&, bool bMultiCall = false);
void addCall(const CallData&);
void addMultiCall(const QString&, bool);
void draw();
void save(FILE*);
void save(const QString&);
void zoom(bool);
void setZoom(double);
void rotate();
QString getTip(const QPoint&, QRect&);
void resize(int, int);
void drawNode(const QString&, const QRect&);
void drawEdge(const QString&, const QString&, const QPointArray&);
/**
* Adjusts the maximal number of calling/called functions shown for
* every node (@see m_nMaxNodeDegree).
* @param nMaxNodeDegree The new value to set
*/
void setMaxNodeDegree(int nMaxNodeDegree) { m_nMaxNodeDegree =
nMaxNodeDegree; }
static void setArrowInfo(int, int);
signals:
/**
* Emitted when the user makes a request to view the contents of a
* location in the source code.
* This can be the location of a call, the definition of a function,
* etc.
* @param sPath The full path of the file to show
* @param nLine The line number in this file
*/
void lineRequested(const QString& sPath, uint nLine);
protected:
virtual void drawContents(QPainter*, int, int, int, int);
virtual void contentsMousePressEvent(QMouseEvent*);
private:
/** The graph is stored as a map of nodes indexed by their names.
Each node holds a list of outgoing edges. */
QDict<GraphNode> m_dictNodes;
/** A Cscope process to use for running queries. */
CscopeFrontend* m_pCscope;
/** Displays query progress information. */
CscopeProgress m_progress;
/** A Dot process used to draw the graph. */
DotFrontend m_dot;
/** Remembers the function the was last queried for calling/called
functions. */
QString m_sQueriedFunc;
/** Remembers whether the last query was for calling or called
functions. */
bool m_bCalled;
/** The node over which the popup menu has been invoked. */
QCanvasPolygonalItem* m_pMenuItem;
/** A popup menu that appears when a node is right-clicked. */
QPopupMenu* m_pNodePopup;
/** A popup menu that appears when a node is right-clicked. */
QPopupMenu* m_pMultiCallPopup;
/** A popup menu that appears when an edge is right-clicked. */
QPopupMenu* m_pEdgePopup;
/** The zoom factor for the graph. */
double m_dZoom;
/** Maximal number of in/out edges per node. If this number is exceeded,
the graph shows a single "multi-call" node. */
int m_nMaxNodeDegree;
/** Holds information used to draw arrow heads. */
static ArrowInfo s_ai;
/** Used for generating unique names for multi-call nodes. */
uint m_nMultiCallNum;
/** Holds the path of the temporary dot file used for drawing the graph. */
QString m_sDrawFilePath;
/** Allows lengthy drawing operations to be cancelled. */
ProgressDlg* m_pProgressDlg;
void write(QTextStream&, const QString&, const QString&, bool);
void removeEdges(GraphNode*, bool);
void removeDisconnected(GraphNode*);
void showNodeMenu(GraphNode*, const QPoint&);
void showEdgeMenu(GraphEdge*, const QPoint&);
private slots:
void slotDotFinished();
void slotDataReady(FrontendToken*);
void slotProgress(int, int);
void slotFinished(uint);
void slotAborted();
void slotShowCalled();
void slotListCalled();
void slotHideCalled();
void slotShowCalling();
void slotListCalling();
void slotHideCalling();
void slotFindDef();
void slotRemoveNode();
void slotMultiCallDetails();
void slotOpenCall();
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1,124 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <klocale.h>
#include "historypage.h"
#include "historyview.h"
int HistoryPage::s_nMaxPageID = 0;
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
HistoryPage::HistoryPage(QWidget* pParent, const char* szName) :
QueryPageBase(pParent, szName),
m_nPageID(++s_nMaxPageID)
{
m_pView = new HistoryView(this);
connect(m_pView, SIGNAL(lineRequested(const QString&, uint)), this,
SIGNAL(lineRequested(const QString&, uint)));
// Set colours and font
applyPrefs();
}
/**
* Class destructor.
*/
HistoryPage::~HistoryPage()
{
if (s_nMaxPageID == m_nPageID)
s_nMaxPageID--;
}
/**
* Creates a new position history record at the top of the list.
* @param sFile The file name associated with the record
* @param nLine The line number
* @param sText The text of the file at the given line
*/
void HistoryPage::addRecord(const QString& sFile, uint nLine,
const QString& sText)
{
HistoryItem* pItem, * pNextItem;
pItem = (HistoryItem*)m_pView->currentItem();
if (pItem != NULL) {
// Do not add duplicate items
if ((pItem->text(1) == sFile) && (pItem->text(2).toUInt() == nLine))
return;
// Remove all items above the current one, so the new item is added to
// the top of the list
pItem = pItem->m_pPrevSibling;
while (pItem != NULL) {
pNextItem = pItem;
pItem = pItem->m_pPrevSibling;
delete pNextItem;
}
}
// Create the new item at the top of the list
m_pView->addRecord("", sFile, QString::number(nLine), sText, NULL);
}
/**
* Creates a new history item.
* This version is used when history records are read from a file.
* @param sFile The file name
* @param sLine The line number
* @param sText The contents of the line
*/
void HistoryPage::addRecord(const QString&, const QString& sFile,
const QString& sLine, const QString& sText)
{
m_pView->addRecord("", sFile, sLine, sText, NULL);
}
/**
* Creates a tab caption for this page, based on the unique page ID.
* @param bBrief true to use brief caption names, false otherwise
*/
QString HistoryPage::getCaption(bool bBrief) const
{
return (bBrief ? QString(i18n("HIS ")) : QString(i18n("History "))) +
QString::number(m_nPageID);
}
/**
* Creates a unique file name for saving the contents of the history page.
* @return The unique file name to use
*/
QString HistoryPage::getFileName(const QString&) const
{
return QString("History_") + QString::number(m_nPageID);
}
#include "historypage.moc"

@ -0,0 +1,72 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef HISTORYPAGE_H
#define HISTORYPAGE_H
#include "querypagebase.h"
/**
* A QueryWidget page for holding position history.
* @author Elad Lahav
*/
class HistoryPage : public QueryPageBase
{
Q_OBJECT
public:
HistoryPage(QWidget* pParent = 0, const char* szName = 0);
~HistoryPage();
void addRecord(const QString&, uint, const QString&);
virtual QString getCaption(bool bBrief = false) const;
protected:
virtual void addRecord(const QString&, const QString&, const QString&,
const QString&);
virtual QString getFileName(const QString&) const;
/**
* @return Always true, since History files do not contain a header
*/
virtual bool readHeader(QTextStream&) { return true; }
/**
* This method does nothing, since History files do not contain a header.
*/
virtual void writeHeader(QTextStream&) {}
private:
/** A unique ID used to create a tab caption for this page. */
int m_nPageID;
/** Used to generate the unique page ID for each object. */
static int s_nMaxPageID;
};
#endif

@ -0,0 +1,124 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include "historyview.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
HistoryView::HistoryView(QWidget* pParent, const char* szName) :
QueryView(pParent, szName)
{
// Disable sorting
setSortColumn(-1);
// Don't show the "Function" column
setColumnWidthMode(0, QListView::Manual);
setColumnWidth(0, 0);
}
/**
* Class destructor.
*/
HistoryView::~HistoryView()
{
}
/**
* Creates a new list item showing a history record.
* @param sFunc The name of the function
* @param sFile The file path
* @param sLine The line number in the above file
* @param sText The line's text
*/
void HistoryView::addRecord(const QString& /* sFunc */, const QString& sFile,
const QString& sLine, const QString& sText, QListViewItem*)
{
HistoryItem* pItem;
pItem = new HistoryItem(this, sFile, sLine, sText);
setSelected(pItem, true);
}
/**
* Moves to the previous item in the history, selecting it for display.
* Note that this function move to the item which chronologically precedes
* the current one, which, in list view terms, is the next item.
*/
void HistoryView::selectPrev()
{
QListViewItem* pItem;
// Get the current item
pItem = currentItem();
// Select the next item in the list
if (pItem != NULL && pItem->nextSibling() != NULL) {
pItem = pItem->nextSibling();
select(pItem);
}
}
/**
* Moves to the next item in the history, selecting it for display.
* Note that this function move to the item which chronologically succedes
* the current one, which, in list view terms, is the previous item.
*/
void HistoryView::selectNext()
{
HistoryItem* pItem;
// Get the current item
pItem = (HistoryItem*)currentItem();
// Select the previous item in the list
if (pItem != NULL && pItem->m_pPrevSibling != NULL) {
pItem = pItem->m_pPrevSibling;
select(pItem);
}
}
/**
* Deletes the item on which a popup-menu has been invoked.
* This slot is connected to the remove() signal of the QueryResultsMenu
* object.
* @param pItem The item to remove
*/
void HistoryView::slotRemoveItem(QListViewItem* pItem)
{
HistoryItem* pCurItem, * pNextItem;
pCurItem = (HistoryItem*)pItem;
if ((pNextItem = (HistoryItem*)pCurItem->nextSibling()) != NULL)
pNextItem->m_pPrevSibling = pCurItem->m_pPrevSibling;
delete pCurItem;
}
#include "historyview.moc"

@ -0,0 +1,91 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef HISTORYVIEW_H
#define HISTORYVIEW_H
#include "queryview.h"
/**
* A list view item for holding position history records.
* A QListViewItem cannot reference its preceding item, which is required to
* create a stack-like history list. Therefore a HistoryItem object
* stores a pointer to the item just above it in the list. The pointer is
* persistent, since the list cannot be sorted.
* @author Elad Lahav
*/
class HistoryItem : public QListViewItem
{
public:
/**
* Class constructor.
* @param pList The parent list view
* @param sFile The file path in this record
* @param sLine The line number
* @param sText The contents of the line in the given file
*/
HistoryItem(QListView* pList, QString sFile, QString sLine,
QString sText) :
QListViewItem(pList, "", sFile, sLine, sText),
m_pPrevSibling(NULL) {
HistoryItem* pNext;
// Mark the new item as the predecessor of its next sibling
if ((pNext = (HistoryItem*)nextSibling()) != NULL)
pNext->m_pPrevSibling = this;
}
/** The item immediately above this one in the list. */
HistoryItem* m_pPrevSibling;
};
/**
* A list view widget for holding position history.
* Position history is kept in a stack-like list. Positions are always added
* to the top of the list, immediately before the current item. If the
* current item is not the top one, all items above it are purged first.
* To keep the stack-like structure, the list cannot be sorted.
* @author Elad Lahav
*/
class HistoryView : public QueryView
{
Q_OBJECT
public:
HistoryView(QWidget* pParent = 0, const char* szName = 0);
~HistoryView();
virtual void addRecord(const QString&, const QString&, const QString&,
const QString&, QListViewItem*);
virtual void selectNext();
virtual void selectPrev();
protected slots:
virtual void slotRemoveItem(QListViewItem*);
};
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,12 @@
[Desktop Entry]
Encoding=UTF-8
Name=KScope
Exec=kscope
Icon=kscope
Type=Application
Comment=Source-editing environment for large C projects
Comment[fr]=Editeur de codes sources pour de gros projets en C
GenericName=Source editing environment
GenericName[fr]=Editeur de code source
Categories=Qt;KDE;Development

@ -0,0 +1,235 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef KSCOPE_H
#define KSCOPE_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <qtimer.h>
#include <kcmdlineargs.h>
#include <kapp.h>
#include <kparts/dockmainwindow.h>
#include <kparts/part.h>
class ProjectManager;
class EditorTabs;
class FileView;
class FileList;
class QueryWidget;
class EditorManager;
class CscopeFrontend;
class EditorPage;
class ProgressDlg;
class CscopeMsgDlg;
class MakeDlg;
class CallTreeManager;
class KScopeActions;
/**
* Defines the main window of KScope.
* The main window has both UI and functional tasks. As a window, it is
* composed of three parts:
* 1. The editing area (EditorTabs - a tab widget with editor pages)
* 2. The project pane (FileList - listing the files in the project)
* 3. The query pane (QueryWidget - a tab widget with pages displaying query
* results in lists)
* The main window also maintains the main menu, the toolbar and the status-
* bar, and is responsible for handling all the actions connected to these
* bars.
* As the application's main class, it is responsible for managing projects
* (using a ProjectManager object) and for running instances of Cscope
* (through a CscopeFrontend object).
* @author Elad Lahav
*/
class KScope : public KParts::DockMainWindow
{
Q_OBJECT
public:
KScope(QWidget* pParent = 0, const char* szName = 0);
~KScope();
void openProject(const QString&);
void openLastProject();
bool openCscopeOut(const QString&);
void parseCmdLine(KCmdLineArgs *pArgs);
void verifyCscope();
public slots:
void slotClose();
protected:
virtual bool queryClose();
private:
/** A project manager used to load projects and read their properties. */
ProjectManager* m_pProjMgr;
/** The editors tabbed window. */
EditorTabs* m_pEditTabs;
/** The file selection widget (project file list and OS file system
tree.) */
FileView* m_pFileView;
/** Pointer to the file list part of the FileView widget. */
FileList* m_pFileList;
/** The query results tabbed window. */
QueryWidget* m_pQueryWidget;
/** A KDE editor part manager, responsible for creating KTextEditor
parts. */
EditorManager* m_pEditMgr;
/** A Cscope process for building the database. */
CscopeFrontend* m_pCscopeBuild;
/** A timer for rebuilding the database after a file has been saved. */
QTimer m_timerRebuild;
/** Whether the query window should be hidden after the user selects an
item. */
bool m_bHideQueryOnSelection;
/** The file view docking area. */
KDockWidget* m_pFileViewDock;
/** The query window docking area. */
KDockWidget* m_pQueryDock;
/** A persistent dialog used to display error messages from Cscope. */
CscopeMsgDlg* m_pMsgDlg;
/** The path of the file currently being edited. */
QString m_sCurFilePath;
/** The line number of the current cursor position. */
int m_nCurLine;
/** Creates and maintains call tree dialogues. */
CallTreeManager* m_pCallTreeMgr;
/** A progress dialogue that is displayed when building the database for
the first time. */
ProgressDlg* m_pProgressDlg;
/** A flag indicating whether the GUI of the embedded editor should be
merged with that of KScope's. Can be turned off to save time when
loading/closing a number of editor parts. */
bool m_bUpdateGUI;
/** Set to true after a shell script has verified that Cscope is installed
and correctly configured on this system.
No Cscope operations should be run if this flag is set to false. */
bool m_bCscopeVerified;
/**
* Used to postpone rebuilding of the database, until Cscope is ready.
*/
bool m_bRebuildDB;
/**
* A widget for running make.
*/
MakeDlg* m_pMakeDlg;
/**
* Manages menu and tool-bar commands.
*/
KScopeActions* m_pActions;
void initMainWindow();
void initCscope();
bool getSymbol(uint&, QString&, bool&, bool bPrompt = true);
EditorPage* addEditor(const QString&s);
EditorPage* createEditorPage();
inline bool isAutoRebuildEnabled();
void restoreSession();
void toggleQueryWindow(bool);
friend class KScopeActions;
private slots:
// Menu actions
void slotNewFile();
void slotOpenFile();
void slotCloseEditor();
void slotCreateProject();
void slotOpenProject();
void slotProjectFiles();
void slotProjectProps();
void slotProjectCscopeOut();
bool slotCloseProject();
void slotQueryReference();
void slotQueryDefinition();
void slotQueryCalled();
void slotQueryCalling();
void slotQueryText();
void slotQueryPattern();
void slotQueryFile();
void slotQueryIncluding();
void slotQueryQuickDef();
void slotCallTree();
void slotRebuildDB();
void slotHistoryShow();
void slotShortcuts();
void slotConfigure();
void slotCloseAllWindows();
void slotExtEdit();
void slotCompleteSymbol();
void slotShowWelcome();
void slotGotoTag();
void slotProjectMake();
void slotProjectRemake();
void slotShowBookmarks();
// Other slots
void slotProjectFilesChanged();
void slotFilesAdded(const QStringList&);
void slotQuery(uint, bool);
void slotDeleteEditor(EditorPage*);
void slotChangeEditor(EditorPage*, EditorPage*);
void slotShowEditor(const QString&, uint);
void slotFileOpened(EditorPage*, const QString&);
void slotFileSaved(const QString&, bool);
void slotCscopeError(const QString&);
void slotBuildProgress(int, int);
void slotBuildInvIndex();
void slotBuildFinished(uint);
void slotBuildAborted();
void slotApplyPref();
void slotShowCursorPos(uint, uint);
void slotQueryShowEditor(const QString&, uint);
void slotDropEvent(QDropEvent*);
void slotCscopeVerified(bool, uint);
};
#endif

@ -0,0 +1,16 @@
Begin4
Title: KScope
Version: 1.4.0
Entered-date: ?
Description: A source-editing environment for KDE bsaed on Cscope
Keywords: KDE Cscope Source Browser Editor IDE C
Author: elad_lahav@users.sourceforge.net (Elad Lahav)
Maintained-by: elad_lahav@users.sourceforge.net (Elad Lahav)
Home-page: http://kscope.sourceforge.net
Alternate-site:
Primary-site: http://download.sourceforge.net/kscope/
?M kscope-1.4.0.tar.gz
? kscope-1.4.0.lsm
Platform: Linux/Unix. Requires KDE.
Copying-policy: BSD
End

@ -0,0 +1,165 @@
# Configures KScope parameters
# Checks that the given executable is indeed a Cscope-compatible application
# and determines which options it supports.
verifyCscope()
{
CSCOPE_EXE=`basename $CSCOPE_PATH`
if [ $DEBUG ]
then
echo -n Checking $CSCOPE_EXE version...
fi
# Get the executable's version
CSCOPE_VER_MAJOR=`$CSCOPE_PATH -V 2>&1 | grep -i $CSCOPE_EXE | sed -e "s/.*version \([1-9][0-9]*\)\.\([0-9]\).*/\1/"`
CSCOPE_VER_MINOR=`$CSCOPE_PATH -V 2>&1 | grep -i $CSCOPE_EXE | sed -e "s/.*version \([1-9][0-9]*\)\.\([0-9]\).*/\2/"`
if [ -n "$CSCOPE_VER_MAJOR" -a "$CSCOPE_VER_MINOR" ]
then
echo $CSCOPE_VER_MAJOR.$CSCOPE_VER_MINOR
if [ $DEBUG ]
then
echo -n Cscope support for line mode verbose output...
fi
# Check for verbose output
if [ "`$CSCOPE_PATH -h 2>&1 | grep "\-v"`" ]
then
CSCOPE_VERBOSE=Yes
else
CSCOPE_VERBOSE=No
fi
echo $CSCOPE_VERBOSE
if [ $DEBUG ]
then
echo -n Cscope support slow path definitions...
fi
# Check for slow-path definitions
if [ "`$CSCOPE_PATH -h 2>&1 | grep "\-D"`" ]
then
CSCOPE_SLOWPATH=Yes
else
CSCOPE_SLOWPATH=No
fi
echo $CSCOPE_SLOWPATH
else
echo ERROR
if [ $DEBUG ]
then
echo -e "\n *** ERROR *** The \"cscope\" executable does not appear to be a Cscope compatible programme"
fi
fi
}
DEBUG=0
CSCOPE_OPTIONS_ONLY=
# Parse command-line parameters
# Supported options:
# -d: Debug mode
# -co: Check Cscope options only
for opt in $@
do
case "$opt" in
"-d") DEBUG=1
;;
"-co") CSCOPE_OPTIONS_ONLY=1
;;
esac
done
if [ $DEBUG ]
then
echo -n Looking for cscope...
fi
if [ -z "$CSCOPE_PATH" ]
then
CSCOPE_PATH=`which cscope`
fi
if [ -n "$CSCOPE_PATH" -a -x "$CSCOPE_PATH" ]
then
echo $CSCOPE_PATH
verifyCscope
else
echo ERROR
if [ $DEBUG ]
then
echo -e "\n *** ERROR *** No Cscope executable found"
fi
fi
if [ -n "$CSCOPE_OPTIONS_ONLY" ]
then
exit
fi
if [ $DEBUG ]
then
echo -n Looking for Ctags...
fi
if [ -z "$CTAGS_PATH" ]
then
for CTAGS_NAME in exctags ctags-exuberant exuberant-ctags ctags
do
CTAGS_PATH=`which $CTAGS_NAME`
if [ -n "$CTAGS_PATH" -a -x "$CTAGS_PATH" ]
then
break
fi
done
fi
if [ -n "$CTAGS_PATH" ]
then
echo $CTAGS_PATH
# echo -n Checking for Exuberant-Ctags compatibility...
CTAGS_EXUB=`$CTAGS_PATH --help | grep -c "\-\-excmd=number"`
if [ $CTAGS_EXUB -gt 0 ]
then
CTAGS_EXUB_PATH=$CTAGS_PATH
echo Yes
else
echo ERROR
# echo -e "\n *** ERROR *** The \"ctags\" executable does not appear to be compatible with Exuberant Ctags"
fi
else
echo ERROR
# echo -e "\n *** ERROR *** No Ctags executable found"
fi
# echo -n Looking for Dot...
if [ -z "$DOT_PATH" ]
then
DOT_PATH=`which dot`
fi
if [ -n "$DOT_PATH" -a -x "$DOT_PATH" ]
then
echo $DOT_PATH
# echo -n Checking if dot handles the -Tplain option...
echo "digraph G {Hello->World}" | $DOT_PATH -Tplain 2>&1 /dev/null
if [ $? -eq 0 ]
then
echo Yes
else
echo ERROR
# echo -e "\n *** ERROR *** The \"dot\" executable does not support -Tplain"
fi
else
echo ERROR
# echo -e "\n *** ERROR *** No Dot executable found"
fi

@ -0,0 +1,533 @@
/***************************************************************************
*
* Copyright (C) 2007 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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, m_pWindow list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, m_pWindow list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 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.
*
***************************************************************************/
#include <klocale.h>
#include "kscope.h"
#include "kscopeactions.h"
#include "kscopeconfig.h"
#include "filelist.h"
#include "editortabs.h"
#include "querywidget.h"
KScopeActions::KScopeActions(KScope* pWindow) : QObject(),
m_pWindow(pWindow),
m_pCollection(pWindow->actionCollection())
{
}
KScopeActions::~KScopeActions()
{
}
/**
* Connects menu bar and toolbar commands with class members. These members
* handle the actions associated with each command.
*/
void KScopeActions::init()
{
// File menu
KStdAction::openNew(m_pWindow, SLOT(slotNewFile()), m_pCollection);
KStdAction::open(m_pWindow, SLOT(slotOpenFile()), m_pCollection);
KStdAction::close(m_pWindow, SLOT(slotCloseEditor()), m_pCollection);
KStdAction::quit(m_pWindow, SLOT(slotClose()), m_pCollection);
addAction(i18n("Go to File List"),
NULL,
"Ctrl+Shift+O",
m_pWindow->m_pFileList,
SLOT(slotSetFocus()),
"file_open_file_from_list",
SIGNAL(toggleProject(bool)));
addAction(i18n("Save Al&l"),
"save_all",
"Ctrl+L",
m_pWindow->m_pEditTabs,
SLOT(slotSaveAll()),
"file_save_all",
NULL);
// Edit menu
m_pExtEditAction = addAction(i18n("Edit in E&xternal Editor"),
NULL,
"Ctrl+E",
m_pWindow,
SLOT(slotExtEdit()),
"edit_external_editor",
SIGNAL(toggleFile(bool)));
addAction(i18n("Go To Tag"),
NULL,
"Ctrl+Shift+T",
m_pWindow,
SLOT(slotGotoTag()),
"edit_goto_tag",
SIGNAL(toggleFile(bool)));
addAction(i18n("Complete Symbol"),
NULL,
"Ctrl+Space",
m_pWindow,
SLOT(slotCompleteSymbol()),
"edit_comp_symbol",
SIGNAL(toggleFile(bool)));
// Project menu
addAction(i18n("&New Project..."),
NULL,
NULL,
m_pWindow,
SLOT(slotCreateProject()),
"project_new",
NULL);
addAction(i18n("&Open Project..."),
"project_open",
NULL,
m_pWindow,
SLOT(slotOpenProject()),
"project_open",
NULL);
addAction(i18n("Open &Cscope.out..."),
NULL,
NULL,
m_pWindow,
SLOT(slotProjectCscopeOut()),
"project_cscope_out",
NULL);
addAction(i18n("Add/Remove &Files..."),
NULL,
NULL,
m_pWindow,
SLOT(slotProjectFiles()),
"project_add_rem_files",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Properties..."),
NULL,
NULL,
m_pWindow,
SLOT(slotProjectProps()),
"project_properties",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Make Project"),
"make_kdevelop",
"Ctrl+M",
m_pWindow,
SLOT(slotProjectMake()),
"project_make",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Remake Project"),
"rebuild",
"Ctrl+Shift+M",
m_pWindow,
SLOT(slotProjectRemake()),
"project_remake",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Close Project"),
"fileclose",
NULL,
m_pWindow,
SLOT(slotCloseProject()),
"project_close",
SIGNAL(toggleProject(bool)));
// Cscope menu
addAction(i18n("&References..."),
NULL,
"Ctrl+0",
m_pWindow,
SLOT(slotQueryReference()),
"cscope_references",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Definition..."),
NULL,
"Ctrl+1",
m_pWindow,
SLOT(slotQueryDefinition()),
"cscope_definition",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Called Functions..."),
NULL,
"Ctrl+2",
m_pWindow,
SLOT(slotQueryCalled()),
"cscope_called",
SIGNAL(toggleProject(bool)));
addAction(i18n("C&alling Functions..."),
NULL,
"Ctrl+3",
m_pWindow,
SLOT(slotQueryCalling()),
"cscope_calling",
SIGNAL(toggleProject(bool)));
addAction(i18n("Find &Text..."),
NULL,
"Ctrl+4",
m_pWindow,
SLOT(slotQueryText()),
"cscope_text",
SIGNAL(toggleProject(bool)));
addAction(i18n("Find &EGrep Pattern..."),
NULL,
"Ctrl+5",
m_pWindow,
SLOT(slotQueryPattern()),
"cscope_pattern",
SIGNAL(toggleProject(bool)));
addAction(i18n("Find &File..."),
NULL,
"Ctrl+7",
m_pWindow,
SLOT(slotQueryFile()),
"cscope_file",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Including Files..."),
NULL,
"Ctrl+8",
m_pWindow,
SLOT(slotQueryIncluding()),
"cscope_including",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Quick Definition"),
NULL,
"Ctrl+]",
m_pWindow,
SLOT(slotQueryQuickDef()),
"cscope_quick_def",
SIGNAL(toggleProject(bool)));
addAction(i18n("Call &Graph..."),
NULL,
"Ctrl+\\",
m_pWindow,
SLOT(slotCallTree()),
"cscope_call_tree",
SIGNAL(toggleProject(bool)));
addAction(i18n("Re&build database"),
"vcs_update",
NULL,
m_pWindow,
SLOT(slotRebuildDB()),
"cscope_rebuild",
SIGNAL(toggleProject(bool)));
// Go menu
addAction(i18n("P&revious Result"),
"up",
"Alt+Up",
m_pWindow->m_pQueryWidget,
SLOT(slotPrevResult()),
"go_prev_result",
SIGNAL(toggleProject(bool)));
addAction(i18n("N&ext Result"),
"down",
"Alt+Down",
m_pWindow->m_pQueryWidget,
SLOT(slotNextResult()),
"go_next_result",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Previous Position"),
"back",
"Alt+Left",
m_pWindow->m_pQueryWidget,
SLOT(slotHistoryPrev()),
"go_prev_pos",
NULL);
addAction(i18n("&Next Position"),
"forward",
"Alt+Right",
m_pWindow->m_pQueryWidget,
SLOT(slotHistoryNext()),
"go_next_pos",
NULL);
addAction(i18n("Position &History"),
"history",
"Ctrl+h",
m_pWindow,
SLOT(slotHistoryShow()),
"go_history",
NULL);
addAction(i18n("Global &Bookmarks"),
"bookmark",
"Ctrl+Shift+G",
m_pWindow,
SLOT(slotShowBookmarks()),
"go_bookmarks",
NULL);
// View menu
m_pToggleFileViewAction = addToggle(i18n("Toggle File List"),
"view_sidetree",
"Ctrl+/",
m_pWindow->m_pFileViewDock,
SLOT(changeHideShowState()),
"view_toggle_filelist_dock",
NULL);
m_pToggleQueryWindowAction = addToggle(i18n("Toggle Query Window"),
"view_top_bottom",
"Ctrl+.",
m_pWindow->m_pQueryDock,
SLOT(changeHideShowState()),
"view_toggle_query_dock",
NULL);
m_pToggleTagListAction = addToggle(i18n("Toggle Tag List"),
"view_detailed",
"Ctrl+'",
m_pWindow->m_pEditTabs,
SLOT(slotToggleTagList()),
"view_toggle_tag_list",
NULL);
// Window menu
addAction(i18n("Close &All"),
"fileclose",
NULL,
m_pWindow,
SLOT(slotCloseAllWindows()),
"window_close_all",
NULL);
addAction(i18n("Go &Left"),
"back",
"Alt+Shift+Left",
m_pWindow->m_pEditTabs,
SLOT(slotGoLeft()),
"window_go_left",
NULL);
addAction(i18n("Go &Right"),
"forward",
"Alt+Shift+Right",
m_pWindow->m_pEditTabs,
SLOT(slotGoRight()),
"window_go_right",
NULL);
// Settings menu
KStdAction::preferences(m_pWindow, SLOT(slotConfigure()), m_pCollection);
KStdAction::keyBindings(m_pWindow, SLOT(slotShortcuts()), m_pCollection);
// Help menu
addAction(i18n("Show &Welcome Message..."),
NULL,
NULL,
m_pWindow,
SLOT(slotShowWelcome()),
"help_welcome",
NULL);
// Query widget popup menu
addAction(i18n("&New"),
"filenew",
NULL,
m_pWindow->m_pQueryWidget,
SLOT(slotNewQueryPage()),
"query_new",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Refresh"),
"reload",
NULL,
m_pWindow->m_pQueryWidget,
SLOT(slotRefreshCurrent()),
"query_refresh",
SIGNAL(toggleProject(bool)));
m_pLockAction = addToggle(i18n("&Lock/Unlock"),
"encrypted",
NULL,
m_pWindow->m_pQueryWidget,
SLOT(slotLockCurrent()),
"query_toggle_locked",
SIGNAL(toggleProject(bool)));
addAction(i18n("&Close"),
"fileclose",
NULL,
m_pWindow->m_pQueryWidget,
SLOT(slotCloseCurrent()),
"query_close",
SIGNAL(toggleProject(bool)));
m_pExtEditAction->setEnabled(Config().useExtEditor());
}
void KScopeActions::initLayoutActions()
{
m_pToggleFileViewAction->setChecked(m_pWindow->m_pFileViewDock->isShown());
m_pToggleQueryWindowAction->setChecked(m_pWindow->m_pQueryDock->isShown());
m_pToggleTagListAction->setChecked(Config().getShowTagList());
}
/**
* Enables/disables the "Edit in External Editor" command.
* @param bEnable true to enable the command, false to disable it
*/
void KScopeActions::enableExtEditor(bool bEnable)
{
m_pExtEditAction->setEnabled(bEnable);
}
void KScopeActions::slotQueryDockToggled(bool bVisible)
{
m_pToggleQueryWindowAction->setChecked(bVisible);
}
/**
* Ensures the "Show/Hide Query Window" action is unchecked when the dock
* is closed through its close button.
* This slot is conncted to the headerCloseButtonClicked() signal of the
* query window dock widget.
*/
void KScopeActions::slotQueryDockClosed()
{
m_pToggleQueryWindowAction->setChecked(false);
}
/**
* Ensures the "Show/Hide File View" action is unchecked when the dock
* is closed through its close button.
* This slot is conncted to the headerCloseButtonClicked() signal of the
* file view dock widget.
*/
void KScopeActions::slotFileViewDockClosed()
{
m_pToggleFileViewAction->setChecked(false);
}
/**
* Enables/disables all actions related to open projects.
* This slot should be called whenever a project is opened or closed.
* @param bEnable true to enable actions, false to disable
*/
void KScopeActions::slotEnableProjectActions(bool bEnable)
{
emit toggleProject(bEnable);
}
/**
* Enables/disables all actions related to open files.
* This slot should be called the first file is opened, or when the last one
* is closed.
* @param bEnable true to enable actions, false to disable
*/
void KScopeActions::slotEnableFileActions(bool bEnable)
{
emit toggleFile(bEnable);
}
/**
* Creates a new action.
* @param sCaption The text to display in the menu item
* @param szIcon Optional icon associated with the action
* @param szShortcut Optional key-combination string
* @param pReceiver The widget to receive the action's signal
* @param szSlot The widget's slot that connect to the signal
* @param szName The XML entry corresponding to the action
* @param szSignal Optional signal to connect to the setEnabled() slot of
* the action
* @return The newly created action object
*/
KAction* KScopeActions::addAction(const QString& sCaption, const char* szIcon,
const char* szShortcut, QWidget* pReceiver, const char* szSlot,
const char* szName, const char* szSignal)
{
KAction* pAction;
// Create the action
pAction = new KAction(sCaption,
szIcon,
szShortcut == NULL ? KShortcut() : KShortcut(szShortcut),
pReceiver,
szSlot,
m_pCollection,
szName);
// Add to the given action list, if any
if (szSignal)
connect(this, szSignal, pAction, SLOT(setEnabled(bool)));
return pAction;
}
/**
* Creates a new toggle action.
* @param sCaption The text to display in the menu item
* @param szIcon Optional icon associated with the action
* @param szShortcut Optional key-combination string
* @param pReceiver The widget to receive the action's signal
* @param szSlot The widget's slot that connect to the signal
* @param szName The XML entry corresponding to the action
* @param szSignal Optional signal to connect to the setEnabled() slot of
* the action
* @return The newly created action object
*/
KToggleAction* KScopeActions::addToggle(const QString& sCaption,
const char* szIcon, const char* szShortcut, QWidget* pReceiver,
const char* szSlot, const char* szName, const char* szSignal)
{
KToggleAction* pAction;
// Create the action
pAction = new KToggleAction(sCaption,
szIcon,
szShortcut == NULL ? KShortcut() : KShortcut(szShortcut),
pReceiver,
szSlot,
m_pCollection,
szName);
// Add to the given action list, if any
if (szSignal)
connect(this, szSignal, pAction, SLOT(setEnabled(bool)));
return pAction;
}
#include "kscopeactions.moc"

@ -0,0 +1,98 @@
/***************************************************************************
*
* Copyright (C) 2007 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef KSCOPEACTIONS_H
#define KSCOPEACTIONS_H
#include <kaction.h>
class KScope;
typedef QPtrList<KAction> ActionList;
/**
* A helper class for managing KScope's menu commands.
* @author Elad Lahav
*/
class KScopeActions : public QObject
{
Q_OBJECT
public:
KScopeActions(KScope*);
~KScopeActions();
void init();
void initPopups();
void initLayoutActions();
void enableExtEditor(bool);
KToggleAction* getLockAction() { return m_pLockAction; }
public slots:
void slotQueryDockToggled(bool);
void slotQueryDockClosed();
void slotFileViewDockClosed();
void slotEnableProjectActions(bool);
void slotEnableFileActions(bool);
signals:
void toggleProject(bool bEnable);
void toggleFile(bool bEnable);
private:
KScope* m_pWindow;
KActionCollection* m_pCollection;
/** A list of actions that require an active project. */
ActionList m_lstProjActions;
/** A list of actions that require an active file. */
ActionList m_lstFileActions;
/** A toggle menu item for locking/unlocking query pages. */
KToggleAction* m_pLockAction;
/** The "Edit in External Editor" menu command. */
KAction* m_pExtEditAction;
/** The "Show/Hide File View" menu command. */
KToggleAction* m_pToggleFileViewAction;
/** The "Show/Hide Query Window" menu command. */
KToggleAction* m_pToggleQueryWindowAction;
/** The "Show/Hide Tag List" menu command. */
KToggleAction* m_pToggleTagListAction;
KAction* addAction(const QString&, const char*, const char*, QWidget*,
const char*, const char*, const char*);
KToggleAction* addToggle(const QString&, const char*, const char*,
QWidget*, const char*, const char*, const char*);
};
#endif

@ -0,0 +1,768 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <kconfig.h>
#include <kapplication.h>
#include <kglobalsettings.h>
#include "kscopeconfig.h"
// NOTE:
// This configuration file entry controls whether the welcome dialogue is
// displayed. Normally it only needs to be shown once, but the entry's name
// can be changed across versions to force the display of new information.
#define SHOW_WELCOME_ENTRY "ShowWelcomeDlg"
/**
* Stores the display name and the configuration file entry for a configurable
* GUI element.
* @author Elad Lahav
*/
struct ElementInfo
{
/** The display name of the element. */
const char* szName;
/** The configuration file entry. */
const char* szEntry;
};
/**
* A list of GUI elements for which the colour can be configured.
*/
const ElementInfo eiColors[] = {
{ "File List (Foreground)", "FileListFore" },
{ "File List (Background)", "FileListBack" },
{ "Tag List (Foreground)", "TagListFore" },
{ "Tag List (Background)", "TagListBack" },
{ "Query Window (Foreground)", "QueryListFore" },
{ "Query Window (Background)", "QueryListBack" },
{ "Call Graph (Background)", "GraphBack" },
{ "Call Graph (Nodes)", "GraphNode" },
{ "Call Graph (Text)", "GraphText" },
{ "Call Graph (Multi-Call Nodes)", "GraphMultiCall" }
};
/**
* A list of GUI elements for which the font can be configured.
*/
const ElementInfo eiFonts[] = {
{ "File List", "FileList" },
{ "Tag List", "TagList" },
{ "Query Page", "QueryList" },
{ "Call Graph", "Graph" }
};
#define COLOR_NAME(_i) eiColors[_i].szName
#define COLOR_ENTRY(_i) eiColors[_i].szEntry
#define FONT_NAME(_i) eiFonts[_i].szName
#define FONT_ENTRY(_i) eiFonts[_i].szEntry
KScopeConfig::ConfParams KScopeConfig::s_cpDef = {
"/usr/bin/cscope", // Cscope path
"/usr/bin/ctags", // Ctags path
"/usr/bin/dot", // Dot path
true, // Show the tag list
SPLIT_SIZES(), // Tag list width
{
QColor(black), // File list foreground
QColor(white), // File list background
QColor(black), // Tag list foreground
QColor(white), // Tag list background
QColor(black), // Query page foreground
QColor(white), // Query page background
QColor("#c0c0c0"), // Call graph background
QColor("#c0ff80"), // Call graph nodes
QColor(black), // Call graph text
QColor("#ff8000")
},
{
QFont(), // Font definitions are overriden in load()
QFont(),
QFont(),
QFont()
},
NameAsc, // Ctags sort order
false, // Read-only mode
true, // Load last project
true, // Automatic tag highlighting
false, // Brief query captions
true, // Warn when file is modified on the disk
true, // Sort files when a project is loaded
"kate --line %L %F", // External editor example
Fast, // System profile
Embedded, // Editor context menu
"TB", // Call graph orientation
10, // Maximum calls per graph node
0 // Default graph view
};
/**
* Class constructor.
*/
KScopeConfig::KScopeConfig() : m_bFontsChanged(false)
{
}
/**
* Class destructor.
*/
KScopeConfig::~KScopeConfig()
{
}
/**
* Reads KScope's parameters from the standard configuration file.
*/
void KScopeConfig::load()
{
uint i;
KConfig* pConf = kapp->config();
// Need a working instance to get the system's default font (cannot be
// initialised statically)
s_cpDef.fonts[FileList] = KGlobalSettings::generalFont();
s_cpDef.fonts[TagList] = KGlobalSettings::generalFont();
s_cpDef.fonts[QueryWindow] = KGlobalSettings::generalFont();
s_cpDef.fonts[Graph] = KGlobalSettings::generalFont();
// Read the paths to required executables
pConf->setGroup("Programs");
m_cp.sCscopePath = pConf->readEntry("CScope");
m_cp.sCtagsPath = pConf->readEntry("CTags");
m_cp.sDotPath = pConf->readEntry("Dot");
// Read size and position parameters
pConf->setGroup("Geometry");
m_cp.bShowTagList = pConf->readBoolEntry("ShowTagList",
s_cpDef.bShowTagList);
m_cp.siEditor = pConf->readIntListEntry("Editor");
if (m_cp.siEditor.empty())
m_cp.siEditor << 200 << 800;
// Read the recent projects list
pConf->setGroup("Projects");
m_slProjects = pConf->readListEntry("Recent");
// Read colour settings
pConf->setGroup("Colors");
for (i = 0; i <= LAST_COLOR; i++) {
m_cp.clrs[i] = pConf->readColorEntry(COLOR_ENTRY(i),
&s_cpDef.clrs[i]);
}
// Read font settings
pConf->setGroup("Fonts");
for (i = 0; i <= LAST_FONT; i++) {
m_cp.fonts[i] = pConf->readFontEntry(FONT_ENTRY(i),
&s_cpDef.fonts[i]);
}
// Other options
pConf->setGroup("Options");
m_cp.ctagSortOrder =
(CtagSort)pConf->readUnsignedNumEntry("CtagSortOrder",
s_cpDef.ctagSortOrder);
m_cp.bReadOnlyMode = pConf->readBoolEntry("ReadOnlyMode",
s_cpDef.bReadOnlyMode);
m_cp.bLoadLastProj = pConf->readBoolEntry("LoadLastProj",
s_cpDef.bLoadLastProj);
m_cp.bAutoTagHl = pConf->readBoolEntry("AutoTagHl",
s_cpDef.bAutoTagHl);
m_cp.bBriefQueryCaptions = pConf->readBoolEntry("BriefQueryCaptions",
s_cpDef.bBriefQueryCaptions);
m_cp.bWarnModifiedOnDisk = pConf->readBoolEntry("WarnModifiedOnDisk",
s_cpDef.bWarnModifiedOnDisk);
m_cp.bAutoSortFiles = pConf->readBoolEntry("AutoSortFiles",
s_cpDef.bAutoSortFiles);
m_cp.sExtEditor = pConf->readEntry("ExternalEditor", s_cpDef.sExtEditor);
m_cp.profile = (SysProfile)pConf->readUnsignedNumEntry("SystemProfile",
s_cpDef.profile);
m_cp.popup = (EditorPopup)pConf->readUnsignedNumEntry("EditorPopup",
s_cpDef.popup);
m_cp.sGraphOrient = pConf->readEntry("GraphOrientation",
s_cpDef.sGraphOrient);
m_cp.nGraphMaxNodeDegree = pConf->readNumEntry("GraphMaxNodeDegree",
s_cpDef.nGraphMaxNodeDegree);
m_cp.nDefGraphView = pConf->readNumEntry("DefGraphView",
s_cpDef.nDefGraphView);
}
/**
* Sets default values to he configuration parameters (except for those where
* a default value has no meaning, such as the recent projects list).
*/
void KScopeConfig::loadDefault()
{
m_cp = s_cpDef;
}
/**
* Loads the layout of the main window.
* @param pMainWindow Pointer to the main docking window
*/
void KScopeConfig::loadWorkspace(KDockMainWindow* pMainWindow)
{
pMainWindow->readDockConfig(kapp->config(), "Workspace");
}
/**
* Writes KScope's parameters from the standard configuration file.
*/
void KScopeConfig::store()
{
uint i;
KConfig* pConf = kapp->config();
// Write the paths to required executables
pConf->setGroup("Programs");
pConf->writeEntry("CScope", m_cp.sCscopePath);
pConf->writeEntry("CTags", m_cp.sCtagsPath);
pConf->writeEntry("Dot", m_cp.sDotPath);
// Write size and position parameters
pConf->setGroup("Geometry");
pConf->writeEntry("ShowTagList", m_cp.bShowTagList);
pConf->writeEntry("Editor", m_cp.siEditor);
// Write the recent projects list
pConf->setGroup("Projects");
pConf->writeEntry("Recent", m_slProjects);
// Write colour settings
pConf->setGroup("Colors");
for (i = 0; i <= LAST_COLOR; i++)
pConf->writeEntry(COLOR_ENTRY(i), m_cp.clrs[i]);
// Write font settings
if (m_bFontsChanged) {
pConf->setGroup("Fonts");
for (i = 0; i <= LAST_FONT; i++)
pConf->writeEntry(FONT_ENTRY(i), m_cp.fonts[i]);
m_bFontsChanged = false;
}
// Other options
pConf->setGroup("Options");
pConf->writeEntry("CtagSortOrder", (uint)m_cp.ctagSortOrder);
pConf->writeEntry("ReadOnlyMode", m_cp.bReadOnlyMode);
pConf->writeEntry("LoadLastProj", m_cp.bLoadLastProj);
pConf->writeEntry("AutoTagHl", m_cp.bAutoTagHl);
pConf->writeEntry("BriefQueryCaptions", m_cp.bBriefQueryCaptions);
pConf->writeEntry("WarnModifiedOnDisk", m_cp.bWarnModifiedOnDisk);
pConf->writeEntry("AutoSortFiles", m_cp.bAutoSortFiles);
pConf->writeEntry("ExternalEditor", m_cp.sExtEditor);
pConf->writeEntry("SystemProfile", (uint)m_cp.profile);
pConf->writeEntry("EditorPopup", (uint)m_cp.popup);
pConf->writeEntry("GraphOrientation", m_cp.sGraphOrient);
pConf->writeEntry("GraphMaxNodeDegree", m_cp.nGraphMaxNodeDegree);
pConf->writeEntry("DefGraphView", m_cp.nDefGraphView);
// Do not report it's the first time on the next run
pConf->setGroup("General");
pConf->writeEntry("FirstTime", false);
pConf->writeEntry(SHOW_WELCOME_ENTRY, false);
}
/**
* Stores the layout of the main window.
* @param pMainWindow Pointer to the main docking window
*/
void KScopeConfig::storeWorkspace(KDockMainWindow* pMainWindow)
{
pMainWindow->writeDockConfig(kapp->config(), "Workspace");
}
/**
* Determines if this is the first time KScope was launched by the current
* user.
* @return true if this is the first time, false otherwise
*/
bool KScopeConfig::isFirstTime()
{
KConfig* pConf = kapp->config();
pConf->setGroup("General");
return pConf->readBoolEntry("FirstTime", true);
}
/**
* Determines if the welcome dialogue should be displayed.
* Note that while the dialogue is displayed on the first invocation of KScope,
* it may be required on other occasions (e.g., to display important information
* on a per-version basis) and thus it is separated from isFirstTime().
* @return true if the dialogue should be shown, false otherwise
*/
bool KScopeConfig::showWelcomeDlg()
{
KConfig* pConf = kapp->config();
pConf->setGroup("General");
return pConf->readBoolEntry(SHOW_WELCOME_ENTRY, true);
}
/**
* @return The full path of the Cscope executable
*/
const QString& KScopeConfig::getCscopePath() const
{
return m_cp.sCscopePath;
}
/**
* @param sPath The full path of the Cscope executable
*/
void KScopeConfig::setCscopePath(const QString& sPath)
{
m_cp.sCscopePath = sPath;
}
/**
* @return The full path of the Ctags executable
*/
const QString& KScopeConfig::getCtagsPath() const
{
return m_cp.sCtagsPath;
}
/**
* @param sPath The full path of the Ctags executable
*/
void KScopeConfig::setCtagsPath(const QString& sPath)
{
m_cp.sCtagsPath = sPath;
}
/**
* @return The full path of the Dot executable
*/
const QString& KScopeConfig::getDotPath() const
{
return m_cp.sDotPath;
}
/**
* @param sPath The full path of the Dot executable
*/
void KScopeConfig::setDotPath(const QString& sPath)
{
m_cp.sDotPath = sPath;
}
/**
* @return A sorted list of recently used project paths.
*/
const QStringList& KScopeConfig::getRecentProjects() const
{
return m_slProjects;
}
/**
* Adds the given project path to the beginning of the recently used projects
* list.
* @param sProjPath The path of the project to add
*/
void KScopeConfig::addRecentProject(const QString& sProjPath)
{
QStringList::Iterator itr;
itr = m_slProjects.find(sProjPath);
if (itr != m_slProjects.end())
m_slProjects.remove(itr);
m_slProjects.prepend(sProjPath);
}
/**
* Removes the given project path from recently used projects list.
* @param sProjPath The path of the project to remove
*/
void KScopeConfig::removeRecentProject(const QString& sProjPath)
{
m_slProjects.remove(sProjPath);
}
/**
* @return true if the tag list should be visible, false otherwise
*/
bool KScopeConfig::getShowTagList() const
{
return m_cp.bShowTagList;
}
/**
* @param bShowTagList true to make the tag list visible, false otherwise
*/
void KScopeConfig::setShowTagList(bool bShowTagList)
{
m_cp.bShowTagList = bShowTagList;
}
/**
* @return A list containing the widths of the Ctags list part and the
* editor part in an editor page.
*/
const SPLIT_SIZES& KScopeConfig::getEditorSizes() const
{
return m_cp.siEditor;
}
/**
* @param siEditor A list containing the widths of the Ctags list part
* and the editor part in an editor page.
*/
void KScopeConfig::setEditorSizes(const SPLIT_SIZES& siEditor)
{
m_cp.siEditor = siEditor;
}
/**
* Finds a colour to use for a GUI element.
* @param ce Identifies the GUI element
* @return A reference to the colour object to use
*/
const QColor& KScopeConfig::getColor(ColorElement ce) const
{
return m_cp.clrs[ce];
}
/**
* Returns the display name of a GUI element whose colour can be configured.
* @param ce The GUI element
* @return A name used in the colour configuration page
*/
QString KScopeConfig::getColorName(ColorElement ce) const
{
return COLOR_NAME(ce);
}
/**
* Sets a new colour to a GUI element.
* @param ce Identifies the GUI element
* @param clr The colour to use
*/
void KScopeConfig::setColor(ColorElement ce, const QColor& clr)
{
m_cp.clrs[ce] = clr;
}
/**
* Finds a font to use for a GUI element.
* @param fe Identifies the GUI element
* @return A reference to the font object to use
*/
const QFont& KScopeConfig::getFont(FontElement fe) const
{
return m_cp.fonts[fe];
}
/**
* Returns the display name of a GUI element whose font can be configured.
* @param ce The GUI element
* @return A name used in the font configuration page
*/
QString KScopeConfig::getFontName(FontElement ce) const
{
return FONT_NAME(ce);
}
/**
* Sets a new font to a GUI element.
* @param fe Identifies the GUI element
* @param font The font to use
*/
void KScopeConfig::setFont(FontElement fe, const QFont& font)
{
m_bFontsChanged = true;
m_cp.fonts[fe] = font;
}
/**
* @return The column and direction by which the tags should be sorted
*/
KScopeConfig::CtagSort KScopeConfig::getCtagSortOrder()
{
return m_cp.ctagSortOrder;
}
/**
* @param ctagSortOrder The column and direction by which the tags should
* be sorted
*/
void KScopeConfig::setCtagSortOrder(CtagSort ctagSortOrder)
{
m_cp.ctagSortOrder = ctagSortOrder;
}
/**
* @return true to work in Read-Only mode, false otherwise
*/
bool KScopeConfig::getReadOnlyMode()
{
return m_cp.bReadOnlyMode;
}
/**
* @param bReadOnlyMode true to work in Read-Only mode, false otherwise
*/
void KScopeConfig::setReadOnlyMode(bool bReadOnlyMode)
{
m_cp.bReadOnlyMode = bReadOnlyMode;
}
/**
* @return true to load the last project on start-up, false otherwise
*/
bool KScopeConfig::getLoadLastProj()
{
return m_cp.bLoadLastProj;
}
/**
* @param bLoadLastProj true to load the last project on start-up, false
* otherwise
*/
void KScopeConfig::setLoadLastProj(bool bLoadLastProj)
{
m_cp.bLoadLastProj = bLoadLastProj;
}
/**
* @return true to enable tag highlighting based on cursor position, false
* to disable this feature
*/
bool KScopeConfig::getAutoTagHl()
{
return m_cp.bAutoTagHl;
}
/**
* @param bAutoTagHl true to enable tag highlighting based on cursor
* position, false to disable this feature
*/
void KScopeConfig::setAutoTagHl(bool bAutoTagHl)
{
m_cp.bAutoTagHl = bAutoTagHl;
}
/**
* @return true to use the short version of the query captions, false to use
* the long version
*/
bool KScopeConfig::getUseBriefQueryCaptions()
{
return m_cp.bBriefQueryCaptions;
}
/**
* @param bBrief true to use the short version of the query captions, false
* to use the long version
*/
void KScopeConfig::setUseBriefQueryCaptions(bool bBrief)
{
m_cp.bBriefQueryCaptions = bBrief;
}
/**
* @return true to warn user when file is modified on disk, false
* otherwise
*/
bool KScopeConfig::getWarnModifiedOnDisk()
{
return m_cp.bWarnModifiedOnDisk;
}
/**
* @param bWarn true to warn user when file is modified on disk,
* false otherwise
*/
void KScopeConfig::setWarnModifiedOnDisk(bool bWarn)
{
m_cp.bWarnModifiedOnDisk = bWarn;
}
/**
* @return true to sort files when a project is loaded, false otherwise
*/
bool KScopeConfig::getAutoSortFiles()
{
return m_cp.bAutoSortFiles;
}
/**
* @param bSort true to sort files when a project is loaded, false
* otherwise
*/
void KScopeConfig::setAutoSortFiles(bool bSort)
{
m_cp.bAutoSortFiles = bSort;
}
/**
* @return A command line for launching an external editor
*/
const QString& KScopeConfig::getExtEditor()
{
return m_cp.sExtEditor;
}
/**
* @param sExtEditor A command line for launching an external editor
*/
void KScopeConfig::setExtEditor(const QString& sExtEditor)
{
m_cp.sExtEditor = sExtEditor;
}
/**
* Determines if an external editor should be used.
* An external editor is used if KScope is in Read-Only mode, and a command-
* line for the editor was specified.
* @return true to use an external editor, false otherwise
*/
bool KScopeConfig::useExtEditor()
{
return !m_cp.sExtEditor.isEmpty();
}
/**
* @return The chosen profile for this system (@see SysProfile)
*/
KScopeConfig::SysProfile KScopeConfig::getSysProfile() const
{
return m_cp.profile;
}
/**
* @param profile The system profile to use (@see SysProfile)
*/
void KScopeConfig::setSysProfile(KScopeConfig::SysProfile profile)
{
m_cp.profile = profile;
}
/**
* @return The chosen popup menu type for the embedded editor (@see
* EditorPopup)
*/
KScopeConfig::EditorPopup KScopeConfig::getEditorPopup() const
{
return m_cp.popup;
}
/**
* @return The name of the popup menu to use in the embedded editor
*/
QString KScopeConfig::getEditorPopupName() const
{
switch (m_cp.popup) {
case Embedded:
return "ktexteditor_popup";
case KScopeOnly:
return "kscope_popup";
}
// Will not happen, but the compiler complains if no return statement is
// given here
return "";
}
/**
* @param popup The popup menu to use for the embedded editor (@see
* EditorPopup)
*/
void KScopeConfig::setEditorPopup(KScopeConfig::EditorPopup popup)
{
m_cp.popup = popup;
}
/**
* @return The default orientation for call graphs
*/
QString KScopeConfig::getGraphOrientation() const
{
return m_cp.sGraphOrient;
}
/**
* @param sOrient The default orientation for call graphs
*/
void KScopeConfig::setGraphOrientation(const QString& sOrient)
{
m_cp.sGraphOrient = sOrient;
}
/**
* @return The maximal number of calls per graph node
*/
int KScopeConfig::getGraphMaxNodeDegree() const
{
return m_cp.nGraphMaxNodeDegree;
}
/**
* @param nMaxNodeDegree The maximal number of calls per graph node
*/
void KScopeConfig::setGraphMaxNodeDegree(int nMaxNodeDegree)
{
m_cp.nGraphMaxNodeDegree = nMaxNodeDegree;
}
/**
* @return The default view in the call graph dialogue
*/
int KScopeConfig::getDefGraphView() const
{
return m_cp.nDefGraphView;
}
/**
* @param nDefGraphView The default view in the call graph dialogue
*/
void KScopeConfig::setDefGraphView(int nDefGraphView)
{
m_cp.nDefGraphView = nDefGraphView;
}
/**
* Returns a reference to a global configuration object.
* The static object defined is this function should be the only KSCopeConfig
* object in this programme. Any code that wishes to get or set global
* configuration parameters, should call Config(), instead of defining its
* own object.
* @return Reference to a statically allocated configuration object
*/
KScopeConfig& Config()
{
static KScopeConfig conf;
return conf;
}
#include "kscopeconfig.moc"

@ -0,0 +1,218 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef KSCOPECONFIG_H
#define KSCOPECONFIG_H
#include <qobject.h>
#include <qstringlist.h>
#include <qcolor.h>
#include <kdockwidget.h>
typedef QValueList<int> SPLIT_SIZES;
/**
* Loads and stores global configuration parameters.
* @author Elad Lahav
*/
class KScopeConfig : public QObject
{
Q_OBJECT
public:
KScopeConfig();
~KScopeConfig();
/** GUI elements whose colours can be set. */
enum ColorElement { FileListFore = 0, FileListBack, TagListFore,
TagListBack, QueryWindowFore, QueryWindowBack, GraphBack,
GraphNode, GraphText, GraphMultiCall, LAST_COLOR = GraphMultiCall };
/** GUI elements whose fonts can be set. */
enum FontElement { FileList = 0, TagList, QueryWindow, Graph,
LAST_FONT = Graph };
/** Sort order values for the tags list. */
enum CtagSort { NameAsc = 0, NameDes, LineAsc, LineDes, TypeAsc,
TypeDes };
/** Types of systems that determine certain aspects in KScope's
behaviour.
For fast systems, certain time-consuming operations, such as
rebuilding the database, may be performed automatically. Such
behaviour, however, is not desired on slow systems, in which the user
should handle such operations manually. */
enum SysProfile { Fast, Slow };
/** The different options for a popup menu to be installed in the editor
parts. */
enum EditorPopup { Embedded, KScopeOnly };
void load();
void loadDefault();
void loadWorkspace(KDockMainWindow*);
void store();
void storeWorkspace(KDockMainWindow*);
bool isFirstTime();
bool showWelcomeDlg();
const QString& getCscopePath() const;
void setCscopePath(const QString&);
const QString& getCtagsPath() const;
void setCtagsPath(const QString&);
const QString& getDotPath() const;
void setDotPath(const QString&);
const QStringList& getRecentProjects() const;
void addRecentProject(const QString&);
void removeRecentProject(const QString&);
bool getShowTagList() const;
void setShowTagList(bool);
const SPLIT_SIZES& getEditorSizes() const;
void setEditorSizes(const SPLIT_SIZES&);
const QColor& getColor(ColorElement) const;
QString getColorName(ColorElement) const;
void setColor(ColorElement, const QColor&);
const QFont& getFont(FontElement) const;
QString getFontName(FontElement) const;
void setFont(FontElement, const QFont&);
CtagSort getCtagSortOrder();
void setCtagSortOrder(CtagSort);
bool getReadOnlyMode();
void setReadOnlyMode(bool);
bool getLoadLastProj();
void setLoadLastProj(bool);
bool getAutoTagHl();
void setAutoTagHl(bool);
bool getUseBriefQueryCaptions();
void setUseBriefQueryCaptions(bool);
bool getWarnModifiedOnDisk();
void setWarnModifiedOnDisk(bool);
bool getAutoSortFiles();
void setAutoSortFiles(bool);
const QString& getExtEditor();
void setExtEditor(const QString&);
bool useExtEditor();
SysProfile getSysProfile() const;
void setSysProfile(SysProfile);
EditorPopup getEditorPopup() const;
QString getEditorPopupName() const;
void setEditorPopup(EditorPopup);
QString getGraphOrientation() const;
void setGraphOrientation(const QString&);
int getGraphMaxNodeDegree() const;
void setGraphMaxNodeDegree(int);
int getDefGraphView() const;
void setDefGraphView(int);
private:
/** A list of previously loaded projects. */
QStringList m_slProjects;
/** Defines the list of all configurable parameters in KScope.
The use of a structure helps define default values (@see s_cpDef) */
struct ConfParams {
/** The full path of the Cscope executable. */
QString sCscopePath;
/** The full path of the Ctags executable. */
QString sCtagsPath;
/** The full path of the Dot executable. */
QString sDotPath;
/** Whether the tag list should be visible. */
bool bShowTagList;
/** The widths of the tag list and editor panes inside an editor
page. */
SPLIT_SIZES siEditor;
/** Colours for GUI elements. */
QColor clrs[LAST_COLOR + 1];
/** Fonts for GUI elements. */
QFont fonts[LAST_FONT + 1];
/** Sort order of the tag lists. */
CtagSort ctagSortOrder;
/** Whether KScope should operate in code read-only mode. */
bool bReadOnlyMode;
/** Whether the last open project should be reloaded on start-up. */
bool bLoadLastProj;
/** Whether tags should be highlighted based on the current cursor
position. */
bool bAutoTagHl;
/** Whether query page captions should use mnemonics for query types,
instead of the full description. */
bool bBriefQueryCaptions;
/** Whether the warning should be displayed when file is modified on
disk by external process. */
bool bWarnModifiedOnDisk;
/** Should files be sorted automatically when a project is loaded. */
bool bAutoSortFiles;
/** A command line pattern for an external editor (in read-only
mode.)*/
QString sExtEditor;
/** How KScope should treat time-consuming operations. */
SysProfile profile;
/** The type of popup menu to use in the embedded editor. */
EditorPopup popup;
/** The default orientation of call graphs. */
QString sGraphOrient;
/** Maximal number of called/calling functions per call graph node. */
int nGraphMaxNodeDegree;
/** Default view for the call graph dialogue. */
int nDefGraphView;
};
/** The current configuration parameters */
ConfParams m_cp;
/** Holds default values for the configuration parameters */
static ConfParams s_cpDef;
/** Write font preferences only if modified by the user (keep default
setting otherwise) */
bool m_bFontsChanged;
};
extern KScopeConfig& Config();
#endif

@ -0,0 +1,376 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <kglobal.h>
#include <kiconloader.h>
#include "kscopepixmaps.h"
static const char* XPM_FUNC[] = {
"12 12 2 1",
". c #000000",
"# c #58a8ff",
"............",
".##########.",
".###....###.",
".###.######.",
".###.######.",
".###.######.",
".###....###.",
".###.######.",
".###.######.",
".###.######.",
".##########.",
"............"
};
static const char* XPM_VAR[] = {
"12 12 3 1",
". c #000000",
"a c #c00000",
"# c #ff0000",
"............",
".##########.",
".##########.",
".##.####.##.",
".##.####.##.",
".##.a##a.##.",
".##a.##.a##.",
".###.aa.###.",
".###a..a###.",
".####..####.",
".##########.",
"............"
};
static const char* XPM_STRUCT[] = {
"12 12 2 1",
". c #000000",
"# c #ffff00",
"............",
".##########.",
".####...###.",
".###.###.##.",
".###.######.",
".####.#####.",
".#####.####.",
".######.###.",
".##.###.###.",
".###...####.",
".##########.",
"............"
};
static const char* XPM_MACRO[] = {
"12 12 2 1",
". c #000000",
"# c #00c000",
"............",
".##########.",
".##.####.##.",
".##..##..##.",
".##.#..#.##.",
".##.####.##.",
".##.####.##.",
".##.####.##.",
".##.####.##.",
".##.####.##.",
".##########.",
"............"
};
static const char* XPM_MEMBER[] = {
"12 12 3 1",
". c #000000",
"a c #0000c0",
"# c #c0c0ff",
"............",
".##########.",
".##########.",
".##########.",
".##a.##.a##.",
".##.a..a.##.",
".##.#aa#.##.",
".##.####.##.",
".##.####.##.",
".##########.",
".##########.",
"............"
};
static const char* XPM_ENUM[] = {
"12 12 2 1",
". c #000000",
"# c #ff00ff",
"............",
".##########.",
".##########.",
".##......##.",
".##.#######.",
".##.#######.",
".##.....###.",
".##.#######.",
".##.#######.",
".##......##.",
".##########.",
"............"
};
static const char* XPM_ENUMERATOR[] = {
"12 12 2 1",
". c #000000",
"# c #ffc0c0",
"............",
".##########.",
".##########.",
".###...####.",
".##.###.###.",
".##.###.###.",
".##.....###.",
".##.#######.",
".##.###.###.",
".###...####.",
".##########.",
"............"
};
static const char* XPM_TYPEDEF[] = {
"12 12 2 1",
". c #000000",
"# c #c0ffc0",
"............",
".##########.",
".#.......##.",
".####.#####.",
".####.#####.",
".####.#####.",
".####.#####.",
".####.#####.",
".####.#####.",
".####.#####.",
".##########.",
"............"
};
static const char* XPM_LABEL[] = {
"12 12 2 1",
". c #000000",
"# c #c0ff00",
"............",
".##########.",
".#.########.",
".#.########.",
".#.########.",
".#.########.",
".#.########.",
".#.########.",
".#.########.",
".#.......##.",
".##########.",
"............"
};
static const char* XPM_INCLUDE[] = {
"12 12 2 1",
". c #000000",
"# c #c0c0c0",
"............",
".##########.",
".##.....###.",
".####.#####.",
".####.#####.",
".####.#####.",
".####.#####.",
".####.#####.",
".####.#####.",
".##.....###.",
".##########.",
"............"
};
static const char* XPM_UNKNOWN[] = {
"12 12 2 1",
". c #000000",
"# c #ffffff",
"............",
".##########.",
".##.....###.",
".#.#####.##.",
".########.#.",
".########.#.",
".#######.##.",
".######.###.",
".####.#####.",
".##########.",
".####.#####.",
"............"
};
/**
* Class constructor.
*/
KScopePixmaps::KScopePixmaps() :
m_pPixArray(NULL),
m_loader()
{
}
/**
* Class destructor.
*/
KScopePixmaps::~KScopePixmaps()
{
int i;
for (i = 0; i < PIX_ARRAY_SIZE; i++)
delete m_pPixArray[i];
delete [] m_pPixArray;
}
/**
* Creates the array of embedded pixmaps.
* This function is separated from the constructor since QPixmap objects
* cannot be created at the time the static KScopePixmaps object is
* allocated.
*/
void KScopePixmaps::init()
{
// Create the pixmap array
m_pPixArray = new QPixmap * [PIX_ARRAY_SIZE];
// Create all pixmaps
m_pPixArray[SymFunc] = new QPixmap(XPM_FUNC);
m_pPixArray[SymVar] = new QPixmap(XPM_VAR);
m_pPixArray[SymStruct] = new QPixmap(XPM_STRUCT);
m_pPixArray[SymMacro] = new QPixmap(XPM_MACRO);
m_pPixArray[SymMember] = new QPixmap(XPM_MEMBER);
m_pPixArray[SymEnum] = new QPixmap(XPM_ENUM);
m_pPixArray[SymEnumerator] = new QPixmap(XPM_ENUMERATOR);
m_pPixArray[SymTypedef] = new QPixmap(XPM_TYPEDEF);
m_pPixArray[SymLabel] = new QPixmap(XPM_LABEL);
m_pPixArray[SymInclude] = new QPixmap(XPM_INCLUDE);
m_pPixArray[SymUnknown] = new QPixmap(XPM_UNKNOWN);
}
/**
* Returns a reference to an embedded pixmap.
* @param name The pixmap's identifier
* @return A reference to the requested pixmap
*/
const QPixmap& KScopePixmaps::getPixmap(PixName name) const
{
return *m_pPixArray[name];
}
/**
* Loads a pixmap with the KIconLoader mechanism.
* @param name The pixmap's identifier
* @return The requested pixmap
*/
QPixmap KScopePixmaps::getPixmap(LoadPixName name)
{
switch (name) {
case TabUnlocked:
return m_loader.loadIcon("query_unlocked", KIcon::Small, 0,
false);
case TabLocked:
return m_loader.loadIcon("query_locked", KIcon::Small, 0,
false);
case TabBookmark:
return m_loader.loadIcon("bookmark", KIcon::Small, 0,
false);
case TabRW:
return m_loader.loadIcon("file_rw", KIcon::Small, 0,
false);
case TabRO:
return m_loader.loadIcon("file_ro", KIcon::Small, 0,
false);
case TabSave:
return m_loader.loadIcon("file_save", KIcon::Small, 0,
false);
case TabFileList:
return m_loader.loadIcon("view_detailed", KIcon::Small, 0,
false);
case TabFileTree:
return m_loader.loadIcon("view_tree", KIcon::Small, 0,
false);
case TabList:
return m_loader.loadIcon("tab_list", KIcon::Small, 0,
false);
case ButtonSaveAs:
return m_loader.loadIcon("filesaveas", KIcon::Toolbar,
0, false);
case ButtonZoomIn:
return m_loader.loadIcon("viewmag+", KIcon::Toolbar,
0, false);
case ButtonZoomOut:
return m_loader.loadIcon("viewmag-", KIcon::Toolbar,
0, false);
case ButtonRotate:
return m_loader.loadIcon("rotate", KIcon::Toolbar,
0, false);
case ButtonPref:
return m_loader.loadIcon("configure", KIcon::Toolbar,
0, false);
case CalledTree:
return m_loader.loadIcon("called_tree", KIcon::Toolbar,
0, false);
case CallingTree:
return m_loader.loadIcon("calling_tree", KIcon::Toolbar,
0, false);
case CallGraph:
return m_loader.loadIcon("call_graph", KIcon::Toolbar,
0, false);
}
return QPixmap();
}
/**
* @return A reference to a global KScopePixmaps object
*/
KScopePixmaps& Pixmaps()
{
static KScopePixmaps pix;
return pix;
}

@ -0,0 +1,77 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef KSCOPEPIXMAPS_H
#define KSCOPEPIXMAPS_H
#include <qpixmap.h>
#include <kiconloader.h>
#define GET_PIXMAP(_pix) \
Pixmaps().getPixmap(KScopePixmaps::_pix)
/**
* Handles all pixmaps required by KScope.
* There are two types of pixmaps: embedded, i.e., pixmaps whose pixels are
* given by static two-dimensional arrays, and loadable, which are retrieved
* through the KIconLoader mechanism.
* The application uses a single global instance of this class.
* @author Elad Lahav
*/
class KScopePixmaps
{
public:
KScopePixmaps();
~KScopePixmaps();
/** Identifiers for embedded pixmaps. */
enum PixName { SymFunc, SymVar, SymStruct, SymMacro, SymMember, SymEnum,
SymEnumerator, SymTypedef, SymLabel, SymInclude, SymUnknown,
PIX_ARRAY_SIZE };
/** Identifiers for loadable pixmaps. */
enum LoadPixName { TabUnlocked, TabLocked, TabBookmark, TabRW, TabRO,
TabSave, TabFileList, TabFileTree, TabList, ButtonSaveAs, ButtonZoomIn,
ButtonZoomOut, ButtonRotate, ButtonPref, CalledTree,
CallingTree, CallGraph };
void init();
const QPixmap& getPixmap(PixName name) const;
QPixmap getPixmap(LoadPixName name);
private:
/** An array of pointers to the embedded pixmaps. */
QPixmap** m_pPixArray;
/** An icon loader used to retrieve pixmaps through the KDE mechanism. */
KIconLoader m_loader;
};
extern KScopePixmaps& Pixmaps();
#endif

@ -0,0 +1,141 @@
<!DOCTYPE kpartgui>
<kpartgui name="kscope">
<MenuBar>
<Menu name="file"><text>&amp;File</text>
<Merge/>
</Menu>
<Menu name="edit"><text>&amp;Edit</text>
<Action name="edit_external_editor"/>
<Separator/>
<Merge/>
<Action name="edit_goto_tag"/>
<Action name="edit_comp_symbol"/>
</Menu>
<Menu name="view"><text>&amp;View</text>
<Action name="view_toggle_filelist_dock"/>
<Action name="view_toggle_query_dock"/>
<Action name="view_toggle_tag_list"/>
<Separator/>
<Merge/>
</Menu>
<Menu name="project"><text>&amp;Project</text>
<Action name="project_new"/>
<Action name="project_open"/>
<Action name="project_cscope_out"/>
<Action name="project_add_rem_files"/>
<Action name="project_properties"/>
<Separator/>
<Action name="project_make"/>
<Action name="project_remake"/>
<Separator/>
<Action name="project_close"/>
</Menu>
<Menu name="cscope"><text>&amp;Cscope</text>
<Action name="cscope_rebuild"/>
<Separator/>
<Action name="cscope_references"/>
<Action name="cscope_definition"/>
<Action name="cscope_called"/>
<Action name="cscope_calling"/>
<Action name="cscope_text"/>
<Action name="cscope_pattern"/>
<Action name="cscope_file"/>
<Action name="cscope_including"/>
<Separator/>
<Action name="cscope_quick_def"/>
<Action name="cscope_call_tree"/>
</Menu>
<Menu name="go"><text>&amp;Go</text>
<Action name="go_prev_result"/>
<Action name="go_next_result"/>
<Separator/>
<Action name="go_prev_pos"/>
<Action name="go_next_pos"/>
<Action name="go_history"/>
<Separator/>
<Action name="go_bookmarks"/>
</Menu>
<Merge/>
<Menu name="window"><text>&amp;Window</text>
<Action name="window_close_all"/>
<Action name="window_go_left"/>
<Action name="window_go_right"/>
<Separator/>
</Menu>
<Menu name="settings"><text>&amp;Settings</text>
<Merge/>
</Menu>
<Menu name="help"><text>&amp;Help</text>
<Action name="help_welcome"/>
<Merge/>
</Menu>
</MenuBar>
<Menu name="query_popup"><text>&amp;Query</text>
<Action name="query_new"/>
<Action name="query_refresh"/>
<Action name="query_toggle_locked"/>
<Separator/>
<Action name="query_close"/>
</Menu>
<Menu name="ktexteditor_popup">
<Merge/>
<Menu name="cscope"><text>Cscope</text>
<Action name="cscope_references"/>
<Action name="cscope_definition"/>
<Action name="cscope_called"/>
<Action name="cscope_calling"/>
<Action name="cscope_text"/>
<Action name="cscope_pattern"/>
<Action name="cscope_file"/>
<Action name="cscope_including"/>
<Separator/>
<Action name="cscope_quick_def"/>
<Action name="cscope_call_tree"/>
</Menu>
<Action name="edit_external_editor"/>
<Action name="file_close"/>
</Menu>
<Menu name="kscope_popup">
<Action name="cscope_references"/>
<Action name="cscope_definition"/>
<Action name="cscope_called"/>
<Action name="cscope_calling"/>
<Action name="cscope_text"/>
<Action name="cscope_pattern"/>
<Action name="cscope_file"/>
<Action name="cscope_including"/>
<Separator/>
<Action name="cscope_quick_def"/>
<Action name="cscope_call_tree"/>
<Action name="edit_external_editor"/>
<Separator/>
<Action name="file_close"/>
</Menu>
<ToolBar fullWidth="true" name="mainToolBar">
<Action name="file_close"/>
</ToolBar>
<ToolBar fullWidth="true" name="projectToolBar"><text>Project</text>
<Action name="project_open"/>
<Action name="cscope_rebuild"/>
</ToolBar>
<ToolBar fullWidth="true" name="navigateToolBar"><text>Navigation</text>
<Action name="go_prev_pos"/>
<Action name="go_next_pos"/>
<Action name="go_history"/>
<Action name="go_bookmarks"/>
</ToolBar>
<ToolBar fullWidth="true" name="queryToolBar"><text>Query</text>
<Action name="query_new"/>
<Action name="query_refresh"/>
<Action name="query_toggle_locked"/>
<Action name="query_close"/>
<Separator/>
<Action name="go_prev_result"/>
<Action name="go_next_result"/>
</ToolBar>
<ToolBar fullWidth="true" name="workspaceToolBar"><text>Workspace</text>
<Action name="view_toggle_tag_list"/>
<Action name="view_toggle_query_dock"/>
<Action name="view_toggle_filelist_dock"/>
</ToolBar>
</kpartgui>

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

@ -0,0 +1,97 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <klocale.h>
#include "kscope.h"
#include "kscopeconfig.h"
static const char *description =
I18N_NOOP("KScope\nA source-editing environment for KDE, based on "
"Cscope");
static KCmdLineOptions options[] =
{
{ "+[CSCOPE.OUT path]",
I18N_NOOP("Opens a cscope.out file in a temporary project"), 0 },
{ "+[CSCOPE.PROJ path | KScope project directory path]",
I18N_NOOP("Opens a KScope project"), 0 },
KCmdLineLastOption
};
/**
* Defines the programme's entry point.
* Creates KScope's main window, and starts the event loop.
* @param argc Number of command line arguments
* @param argv Command line arguments
* @return Programme's exit value
*/
int main(int argc, char *argv[])
{
// Create the "About" dialogue
KAboutData aboutData( "kscope", I18N_NOOP("KScope"),
VERSION, description, KAboutData::License_BSD,
"(c) 2003-2007, Elad Lahav", 0, "http://kscope.sourceforge.net",
"elad_lahav@users.sf.net");
aboutData.addAuthor("Elad Lahav", "Developer",
"elad_lahav@users.sf.net");
aboutData.addCredit("Albert Yosher",
"Code completion, patches and bug fixes", "ayosher@users.sf.net");
aboutData.addCredit("Gabor Fekete", "Bug fixes and patches",
"feketgai@index.hu");
// Initialise command-line argument parsing
KCmdLineArgs::init(argc, argv, &aboutData);
KCmdLineArgs::addCmdLineOptions(options);
// Parse command line arguments
KCmdLineArgs* pArgs = KCmdLineArgs::parsedArgs();
// Create the main window
KApplication a;
KScope* pKScope = new KScope();
a.setMainWidget(pKScope);
// Display the main window
pKScope->show();
// Handle command-line arguments
if (pArgs->count() > 0) {
pKScope->parseCmdLine(pArgs);
} else if (Config().getLoadLastProj()) {
// No arguments given, load the most recent project
pKScope->openLastProject();
}
// Make sure Cscope is properly installed
pKScope->verifyCscope();
// Start the event loop
return a.exec();
}

@ -0,0 +1,267 @@
/***************************************************************************
*
* Copyright (C) 2006 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qtextcodec.h>
#include <ktextbrowser.h>
#include <kcombobox.h>
#include <kurlrequester.h>
#include <kmessagebox.h>
#include <klocale.h>
#include "makedlg.h"
#include "makefrontend.h"
#include "queryview.h"
/** Window flags for call-tree widgets. */
#define MAKE_DLG_W_FLAGS \
WStyle_Customize | \
WStyle_NormalBorder | \
WStyle_Title
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
MakeDlg::MakeDlg(QWidget* pParent, const char* szName) :
MakeLayout(pParent, szName, MAKE_DLG_W_FLAGS)
{
// Don't show the "Function" column
m_pErrorView->setColumnWidthMode(0, QListView::Manual);
m_pErrorView->setColumnWidth(0, 0);
// Create a new make front-end
m_pMake = new MakeFrontend();
connect(m_pMake, SIGNAL(dataReady(FrontendToken*)), this,
SLOT(slotShowOutput(FrontendToken*)));
connect(m_pMake, SIGNAL(finished(uint)), this, SLOT(slotFinished(uint)));
connect(m_pMake,
SIGNAL(error(const QString&, const QString&, const QString&)),
this,
SLOT(slotAddError(const QString&, const QString&, const QString&)));
// The Root URL control should browse directories
m_pRootURL->setMode(KFile::Directory);
// Handle URL links in the browser
m_pOutputBrowser->setNotifyClick(true);
connect(m_pOutputBrowser, SIGNAL(urlClick(const QString&)), this,
SLOT(slotBrowserClicked(const QString&)));
// Handle selections in the error view
connect(m_pErrorView, SIGNAL(lineRequested(const QString& , uint)), this,
SIGNAL(fileRequested(const QString&, uint)));
// Do not allow duplicates in the command history
m_pCommandHistory->setDuplicatesEnabled(false);
}
/**
* Class destructor.
*/
MakeDlg::~ MakeDlg()
{
delete m_pMake;
}
/**
* @return The currently set make command
*/
QString MakeDlg::getCommand() const
{
return m_pCommandHistory->currentText();
}
/**
* @param sCmd The new make command to use
*/
void MakeDlg::setCommand(const QString& sCmd)
{
m_pCommandHistory->setCurrentText(sCmd);
m_pCommandHistory->addToHistory(sCmd);
}
/**
* @return The directory in which to run the make command
*/
QString MakeDlg::getDir() const
{
return m_pRootURL->url();
}
/**
* @param sURL The new root directory to use
*/
void MakeDlg::setDir(const QString& sURL)
{
m_pRootURL->setURL(sURL);
}
/**
* Overrides the default close behaviour.
* Makes sure that a window is not closed while a make process is running,
* unless the user explicitly requests it. In this case, the make process
* is killed.
* @param pEvent The close event descriptor
*/
void MakeDlg::closeEvent(QCloseEvent* pEvent)
{
// Check if a process is currently running
if (m_pMake->isRunning()) {
// Prompt the user
switch (KMessageBox::questionYesNoCancel(this,
i18n("A make process is running. Would you like to stop it first?"),
i18n("Close Make Window"))) {
case KMessageBox::Yes:
// Stop the process first
m_pMake->kill();
break;
case KMessageBox::No:
// Do nothing
break;
case KMessageBox::Cancel:
// Abort closing
pEvent->ignore();
return;
}
}
QWidget::closeEvent(pEvent);
}
/**
* Starts a make process using the user-supplied command.
* This slot is connected to the clicked() signal of the "Make" button.
*/
void MakeDlg::slotMake()
{
QString sCommand;
// Clear the current contents
m_pOutputBrowser->clear();
m_pErrorView->clear();
// Run the make command
sCommand = m_pCommandHistory->currentText();
if (!m_pMake->run("make", QStringList::split(" ", sCommand),
m_pRootURL->url())) {
KMessageBox::error(this, m_pMake->getRunError());
return;
}
// Add the command to the command history
m_pCommandHistory->addToHistory(sCommand);
// Disbale the make button
m_pMakeButton->setEnabled(false);
m_pStopButton->setEnabled(true);
}
/**
* Terminates the current make process.
* This slot is connected to the clicked() signal of the stop button.
*/
void MakeDlg::slotStop()
{
m_pMake->kill();
}
/**
* Displays the parsed output, as generated by the MakeFrontend object.
* This slot is connected to the dataReady() signal of the make front-end.
* @param pToken Holds the parsed data
*/
void MakeDlg::slotShowOutput(FrontendToken* pToken)
{
QString sData;
// GCC uses unicode quote characters - this should ensure that they are
// treated correctly by the text browser widget
sData = QTextCodec::codecForLocale()->toUnicode(pToken->getData());
m_pOutputBrowser->append(sData);
}
/**
* Displays the results of the make command.
* This slot is connected to the finished() signal of the make front-end.
*/
void MakeDlg::slotFinished(uint)
{
// Add "Success" or "Error" at the end of the output
if (m_pMake->exitStatus() == 0) {
m_pOutputBrowser->append("<font color=\"#008000\"><b>Success</b>"
"</font>");
}
else {
m_pOutputBrowser->append("<font color=\"#ff0000\"><b>Error</b></font>");
}
// Re-enable the "Make" button
m_pMakeButton->setEnabled(true);
m_pStopButton->setEnabled(false);
}
/**
* Emits the fileRequested() signal when a browser link is clicked.
* This slot is connected to the urlClick() signal of the browser.
* @param sURL The requested URL
*/
void MakeDlg::slotBrowserClicked(const QString& sURL)
{
QString sFile;
QString sLine;
// Exract the file name and the line number from the URL
sFile = sURL.section('&', 0, 0);
sLine = sURL.section('&', 1, 1);
// Add root path for relative paths
if (!sFile.startsWith("/"))
sFile = m_pRootURL->url() + "/" + sFile;
// Emit the signal
emit fileRequested(sFile, sLine.toUInt());
}
/**
* Show an error/warning on a deidicated list.
* This slot is connected to the error() signal of the make front-end.
* @param sFile The file name containing the error/warning
* @param sLine The line number
* @param sText An explanation of the error
*/
void MakeDlg::slotAddError(const QString& sFile, const QString& sLine,
const QString& sText)
{
QString sUniText;
sUniText = QTextCodec::codecForLocale()->toUnicode(sText);
m_pErrorView->addRecord("", sFile, sLine, sUniText);
}
#include "makedlg.moc"

@ -0,0 +1,78 @@
/***************************************************************************
*
* Copyright (C) 2006 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef MAKEDLG_H
#define MAKEDLG_H
#include "makelayout.h"
class MakeFrontend;
class FrontendToken;
/**
* A window that displays the output of make-like commands.
* The window contains a text browser showing errors as links to source
* locations.
* The make process is determined by a user-specified command, and is run in
* a user-specified directory. Controls are provided for modifying these values.
* @author Elad Lahav
*/
class MakeDlg: public MakeLayout
{
Q_OBJECT
public:
MakeDlg(QWidget* pParent = 0, const char* szName = 0);
virtual ~MakeDlg();
QString getCommand() const;
void setCommand(const QString&);
QString getDir() const;
void setDir(const QString&);
public slots:
virtual void slotMake();
signals:
void fileRequested(const QString&, uint);
protected:
virtual void closeEvent(QCloseEvent*);
protected slots:
virtual void slotStop();
void slotShowOutput(FrontendToken*);
void slotFinished(uint);
void slotBrowserClicked(const QString&);
void slotAddError(const QString&, const QString&, const QString&);
private:
/** Handles the make process. */
MakeFrontend* m_pMake;
};
#endif

@ -0,0 +1,134 @@
/***************************************************************************
*
* Copyright (C) 2006 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qregexp.h>
#include "makefrontend.h"
// TODO:
// This should probably be configurable on a per-project basis.
#define PATH_ELEM "[a-zA-Z0-9_\\.\\-]+"
#define RE_FILE_LINE \
"((?:\\/)?(?:"PATH_ELEM"\\/)*"PATH_ELEM"):([0-9]+)(:[0-9]+)?: (.*)"
#define RE_ENTER_DIR \
"Entering directory " \
"\\`((\\/)?("PATH_ELEM"\\/)*"PATH_ELEM")"
#define RE_EXIT_DIR "Leaving directory"
/**
* Class constructor.
* @param bAutoDelete If true, the object is deleted when the process
* terminates (false by default)
*/
MakeFrontend::MakeFrontend(bool bAutoDelete) : Frontend(1, bAutoDelete)
{
// Execute inside a shell
setUseShell(true);
// Each token represent a complete line
m_delim = Newline;
}
/**
* Class destructor.
*/
MakeFrontend::~MakeFrontend()
{
}
/**
* Executes the make command.
* @param sName The name of the process (for error messages)
* @param slArgs A list containing the command-line arguments
* @param sWorkDir Initial build directory
* @param bBlock (Optional) true to block, false otherwise
* @return true if the process was executed successfully, false otherwise
*/
bool MakeFrontend::run(const QString& sName, const QStringList& slArgs,
const QString& sWorkDir, bool bBlock)
{
QStringList slShellArgs;
// Store the current build directory
m_slPathStack.push_back(sWorkDir);
// Join the output streams, so that they can both be parsed by
// parseStdout()
slShellArgs = slArgs;
slShellArgs << "2>&1";
// Execute the command
return Frontend::run(sName, slShellArgs, sWorkDir, bBlock);
}
/**
* Parses lines of output produced by the make command.
* @param sToken A single line of output
*/
Frontend::ParseResult MakeFrontend::parseStdout(QString& sToken, ParserDelim)
{
static QRegExp reErrWarn(RE_FILE_LINE);
static QRegExp reEntDir(RE_ENTER_DIR);
static QRegExp reExtDir(RE_EXIT_DIR);
QString sRep;
int nPos;
QString sFile, sLine, sText;
if ((nPos = reErrWarn.search(sToken)) >= 0) {
// An error/warning message
if (sToken.at(nPos) == '/') {
sFile = reErrWarn.capturedTexts()[1];
}
else {
sFile = m_slPathStack.last() + "/" +
reErrWarn.capturedTexts()[1];
}
sLine = reErrWarn.capturedTexts()[2];
sText = reErrWarn.capturedTexts()[4];
emit error(sFile, sLine, sText);
sRep = QString("<a href=\"") + sFile + "&\\2\">\\1:\\2</a>\\3: \\4";
sToken.replace(reErrWarn, sRep);
}
else if ((nPos = reEntDir.search(sToken)) >= 0) {
// Recursing into a directory
m_slPathStack.push_back(reEntDir.capturedTexts()[1]);
sToken = QString("<b>Entering directory</b> ") +
m_slPathStack.last();
}
else if ((nPos = reExtDir.search(sToken)) >= 0) {
// Leaving a directory
sToken = QString("<b>Leaving directory</b> ") +
m_slPathStack.last();
m_slPathStack.pop_back();
}
return RecordReady;
}
#include "makefrontend.moc"

@ -0,0 +1,61 @@
/***************************************************************************
*
* Copyright (C) 2006 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef MAKEFRONTEND_H
#define MAKEFRONTEND_H
#include <frontend.h>
/**
* A shell-process front-end intended for running make-like tasks.
* Records are single-line tokens delimited by newline characters. The parser
* replaces references to source lines (e.g., filename:123) with hypertext
* links for use in a browser.
* @author Elad Lahav
*/
class MakeFrontend : public Frontend
{
Q_OBJECT
public:
MakeFrontend(bool bAutoDelete = false);
~MakeFrontend();
virtual bool run(const QString&, const QStringList&,
const QString&, bool bBlock = false);
virtual ParseResult parseStdout(QString&, ParserDelim);
signals:
void error(const QString& sFile, const QString& sLine,
const QString& sText);
private:
/** A stack of paths used to track the current build directory. */
QStringList m_slPathStack;
};
#endif

@ -0,0 +1,245 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>MakeLayout</class>
<widget class="QWidget">
<property name="name">
<cstring>MakeLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>768</width>
<height>642</height>
</rect>
</property>
<property name="caption">
<string>KScope - Make</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout10</cstring>
</property>
<grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel" row="0" column="0">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="text">
<string>Root Directory:</string>
</property>
</widget>
<widget class="KHistoryCombo" row="1" column="1">
<property name="name">
<cstring>m_pCommandHistory</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
<widget class="KURLRequester" row="0" column="1">
<property name="name">
<cstring>m_pRootURL</cstring>
</property>
</widget>
<widget class="QLabel" row="1" column="0">
<property name="name">
<cstring>textLabel2</cstring>
</property>
<property name="text">
<string>Command:</string>
</property>
</widget>
</grid>
</widget>
<widget class="QTabWidget">
<property name="name">
<cstring>tabWidget2</cstring>
</property>
<widget class="QWidget">
<property name="name">
<cstring>tab</cstring>
</property>
<attribute name="title">
<string>Output</string>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="KTextBrowser">
<property name="name">
<cstring>m_pOutputBrowser</cstring>
</property>
</widget>
</vbox>
</widget>
<widget class="QWidget">
<property name="name">
<cstring>tab</cstring>
</property>
<attribute name="title">
<string>Errors a&amp;nd Warnings</string>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QueryView">
<property name="name">
<cstring>m_pErrorView</cstring>
</property>
</widget>
</vbox>
</widget>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout7</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer1</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>520</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pMakeButton</cstring>
</property>
<property name="text">
<string>&amp;Make</string>
</property>
<property name="accel">
<string>Alt+M</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pStopButton</cstring>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>&amp;Stop</string>
</property>
<property name="accel">
<string>Alt+S</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCloseButton</cstring>
</property>
<property name="text">
<string>&amp;Close</string>
</property>
<property name="accel">
<string>Alt+C</string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<customwidgets>
<customwidget>
<class>QueryView</class>
<header location="local">queryview.h</header>
<sizehint>
<width>-1</width>
<height>-1</height>
</sizehint>
<container>0</container>
<sizepolicy>
<hordata>5</hordata>
<verdata>5</verdata>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<pixmap>image0</pixmap>
</customwidget>
</customwidgets>
<images>
<image name="image0">
<data format="XBM.GZ" length="79">789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f</data>
</image>
</images>
<connections>
<connection>
<sender>m_pCloseButton</sender>
<signal>clicked()</signal>
<receiver>MakeLayout</receiver>
<slot>close()</slot>
</connection>
<connection>
<sender>m_pMakeButton</sender>
<signal>clicked()</signal>
<receiver>MakeLayout</receiver>
<slot>slotMake()</slot>
</connection>
<connection>
<sender>m_pStopButton</sender>
<signal>clicked()</signal>
<receiver>MakeLayout</receiver>
<slot>slotStop()</slot>
</connection>
<connection>
<sender>m_pCommandHistory</sender>
<signal>returnPressed()</signal>
<receiver>MakeLayout</receiver>
<slot>slotMake()</slot>
</connection>
</connections>
<tabstops>
<tabstop>m_pRootURL</tabstop>
<tabstop>m_pCommandHistory</tabstop>
<tabstop>m_pMakeButton</tabstop>
<tabstop>m_pStopButton</tabstop>
<tabstop>m_pCloseButton</tabstop>
</tabstops>
<slots>
<slot access="protected">slotStop()</slot>
<slot access="protected">slotMake()</slot>
</slots>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>kcombobox.h</includehint>
<includehint>klineedit.h</includehint>
<includehint>kurlrequester.h</includehint>
<includehint>klineedit.h</includehint>
<includehint>kpushbutton.h</includehint>
<includehint>ktextbrowser.h</includehint>
<includehint>queryview.h</includehint>
</includehints>
</UI>

@ -0,0 +1,354 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qregexp.h>
#include <qpushbutton.h>
#include <qspinbox.h>
#include <qlabel.h>
#include <qtextedit.h>
#include <kurlrequester.h>
#include <klineedit.h>
#include <kmessagebox.h>
#include <klocale.h>
#include "newprojectdlg.h"
/**
* Class constructor.
* @param bNewProj true to create a new project dialog, false to display
* the properties of an existing project
* @param pParent The parent widget
* @param szName The widget's name
*/
NewProjectDlg::NewProjectDlg(bool bNewProj, QWidget* pParent,
const char* szName) :
NewProjectLayout(pParent, szName),
m_bNewProj(bNewProj)
{
ProjectBase::Options opt;
// Create the auto-completion sub-dialogue
m_pAutoCompDlg = new AutoCompletionDlg(this);
// Restrict the path requester to existing directories.
m_pPathRequester->setMode(KFile::Directory | KFile::ExistingOnly |
KFile::LocalOnly);
m_pSrcRootRequester->setMode(KFile::Directory | KFile::ExistingOnly |
KFile::LocalOnly);
// Set up the Create/Cancel buttons
connect(m_pCreateButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(reject()));
// Show the auto-completion properties dialogue
connect(m_pACButton, SIGNAL(clicked()), m_pAutoCompDlg, SLOT(exec()));
// Perform actions specific to the type of dialog (new project or
// project properties)
if (bNewProj) {
// Set default project properties
ProjectBase::getDefOptions(opt);
setProperties("", "", opt);
}
else {
// Give appropriate titles to the dialog and the accept button
setCaption(i18n("Project Properties"));
m_pCreateButton->setText(i18n("OK"));
// Disable the non-relevant widgets
m_pNameEdit->setEnabled(false);
m_pPathRequester->setEnabled(false);
}
}
/**
* Class destructor.
*/
NewProjectDlg::~NewProjectDlg()
{
}
/**
* Configures the dialog's widget to display the properties of the current
* project.
* @param sName The project's name
* @param sPath The project's path
* @param opt Project parameters configurable in this dialogue
*/
void NewProjectDlg::setProperties(const QString& sName, const QString& sPath,
const ProjectBase::Options& opt)
{
QStringList::ConstIterator itr;
// Set values for current project
m_pNameEdit->setText(sName);
m_pPathRequester->setURL(sPath);
m_pSrcRootRequester->setURL(opt.sSrcRootPath);
m_pKernelCheck->setChecked(opt.bKernel);
m_pInvCheck->setChecked(opt.bInvIndex);
m_pNoCompCheck->setChecked(opt.bNoCompress);
m_pSlowPathCheck->setChecked(opt.bSlowPathDef);
if (opt.nAutoRebuildTime >= 0) {
m_pAutoRebuildCheck->setChecked(true);
m_pAutoRebuildSpin->setValue(opt.nAutoRebuildTime);
}
if (opt.bACEnabled) {
m_pACCheck->setChecked(true);
}
if (opt.nTabWidth > 0) {
m_pTabWidthCheck->setChecked(true);
m_pTabWidthSpin->setValue(opt.nTabWidth);
}
// Initialise the auto-completion sub-dialogue
m_pAutoCompDlg->m_nMinChars = opt.nACMinChars;
m_pAutoCompDlg->m_nDelay = opt.nACDelay;
m_pAutoCompDlg->m_nMaxEntries = opt.nACMaxEntries;
// Add type strings to the types list box
for (itr = opt.slFileTypes.begin(); itr != opt.slFileTypes.end(); ++itr)
m_pTypesList->insertItem(*itr);
m_pCtagsCmdEdit->setText(opt.sCtagsCmd);
}
/**
* Retrieves the text entered by the user in the dialog's "Project Name" edit
* box.
* @return The name of the new project
*/
QString NewProjectDlg::getName()
{
return m_pNameEdit->text();
}
/**
* Retrieves the text entered by the user in the dialog's "Project Path" edit
* box.
* Note that the chosen path will be the parent of the new project's
* directory, created under it using the project's name.
* @return The full path of the parent directory for the new project
*/
QString NewProjectDlg::getPath()
{
if (m_pHiddenDirCheck->isChecked())
return QString(m_pSrcRootRequester->url()) + "/.cscope";
return m_pPathRequester->url();
}
/**
* Fills a structure with all user-configured project options.
* @param opt The structure to fill
*/
void NewProjectDlg::getOptions(ProjectBase::Options& opt)
{
opt.sSrcRootPath = m_pSrcRootRequester->url();
opt.slFileTypes = m_slTypes;
opt.bKernel = m_pKernelCheck->isChecked();
opt.bInvIndex = m_pInvCheck->isChecked();
opt.bNoCompress = m_pNoCompCheck->isChecked();
opt.bSlowPathDef = m_pSlowPathCheck->isChecked();
if (m_pAutoRebuildCheck->isChecked())
opt.nAutoRebuildTime = m_pAutoRebuildSpin->value();
else
opt.nAutoRebuildTime = -1;
if (m_pTabWidthCheck->isChecked())
opt.nTabWidth = m_pTabWidthSpin->value();
else
opt.nTabWidth = 0;
opt.bACEnabled = m_pACCheck->isChecked();
opt.nACMinChars = m_pAutoCompDlg->m_nMinChars;
opt.nACDelay = m_pAutoCompDlg->m_nDelay;
opt.nACMaxEntries = m_pAutoCompDlg->m_nMaxEntries;
opt.sCtagsCmd = m_pCtagsCmdEdit->text();
}
/**
* Ends the dialog after the user has clicked the "OK" button.
*/
void NewProjectDlg::accept()
{
int i, nCount;
// Validate the name of a new project
if (m_bNewProj) {
QRegExp re("[^ \\t\\n]+");
if (!re.exactMatch(m_pNameEdit->text())) {
KMessageBox::error(0, i18n("Project names must not contain "
"whitespace."));
return;
}
}
// Fill the string list with all file types
nCount = (int)m_pTypesList->count();
for (i = 0; i < nCount; i++)
m_slTypes.append(m_pTypesList->text(i));
// Clean-up the source root
QDir dir(m_pSrcRootRequester->url());
if (dir.exists())
m_pSrcRootRequester->setURL(dir.absPath());
else
m_pSrcRootRequester->setURL("/");
// Close the dialog
QDialog::accept();
}
/**
* Adds the the file type string in the edit-box to the list of project types.
* This slot is called when the "Add.." button is clicked.
*/
void NewProjectDlg::slotAddType()
{
QString sType;
// Try the custom type edit-box first.
sType = m_pTypesEdit->text();
sType.stripWhiteSpace();
if (sType.isEmpty())
return;
// Validate the type string
QRegExp reg("[ \\t\\n\\|\\\\\\/]");
if (sType.contains(reg)) {
KMessageBox::error(0, i18n("This is not a valid file type!"));
return;
}
// Do not add an existing type.
if (m_pTypesList->findItem(sType, Qt::CaseSensitive | Qt::ExactMatch) !=
NULL) {
return;
}
// Add the file type to the list
m_pTypesList->insertItem(sType);
m_pTypesEdit->clear();
}
/**
* Removes the selected item from the list of file types.
* This slot is called when the "Remove" button is clicked.
*/
void NewProjectDlg::slotRemoveType()
{
int nItem;
QString sType;
// Verify an item is selected
nItem = m_pTypesList->currentItem();
if (nItem == -1)
return;
// Remove the selected item
sType = m_pTypesList->currentText();
m_pTypesList->removeItem(nItem);
// Add to the list of available types.
if (m_pAvailTypesList->findItem(sType, Qt::CaseSensitive | Qt::ExactMatch)
== NULL) {
m_pAvailTypesList->insertItem(sType);
}
}
/**
* Changes the text in the types edit-box to reflect the current selection in
* the list of available types.
* This slot is called whenever a new item is highlighted in the list of
* available types.
* @param sType The newly selected type
*/
void NewProjectDlg::slotAvailTypesChanged(const QString& sType)
{
m_pTypesEdit->setText(sType);
}
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
AutoCompletionDlg::AutoCompletionDlg(QWidget* pParent,
const char* szName ) :
AutoCompletionLayout(pParent, szName)
{
connect(m_pOKButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(reject()));
}
/**
* Class destructor.
*/
AutoCompletionDlg::~AutoCompletionDlg()
{
}
/**
* Displays the dialogue, and waits for either the "OK" or "Cancel" button to
* be clicked.
* Before the dialogue is displayed, the stored values are set to the widgets.
* @return The dialogue's termination code
*/
int AutoCompletionDlg::exec()
{
// Set current values
m_pMinCharsSpin->setValue(m_nMinChars);
m_pDelaySpin->setValue(m_nDelay);
m_pMaxEntriesSpin->setValue(m_nMaxEntries);
// Show the dialogue
return QDialog::exec();
}
/**
* Stores the values set by the user in the dialogue widgets, and terminates
* the dialogue.
* This slot is connected to the clicked() signal of the "OK" button.
*/
void AutoCompletionDlg::accept()
{
// Store widget values
m_nMinChars = m_pMinCharsSpin->value();
m_nDelay = m_pDelaySpin->value();
m_nMaxEntries = m_pMaxEntriesSpin->value();
// Close the dialogue, indicating acceptance
QDialog::accept();
}
#include "newprojectdlg.moc"

@ -0,0 +1,112 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef NEWPROJECTDLG_H
#define NEWPROJECTDLG_H
#include <qlineedit.h>
#include <qcheckbox.h>
#include <newprojectlayout.h>
#include <autocompletionlayout.h>
#include "projectbase.h"
/**
* A sub-dialogue of the New Project dialogue.
* Allows the user to configure auto-completion parameters.
* @author Elad Lahav
*/
class AutoCompletionDlg : public AutoCompletionLayout
{
Q_OBJECT
public:
AutoCompletionDlg(QWidget* pParent, const char* szName = NULL);
~AutoCompletionDlg();
public slots:
int exec();
protected slots:
virtual void accept();
private:
/** The minimum number of characters in a symbol required for automatic
completion. */
uint m_nMinChars;
/** The time, in seconds, to wait before automatic completion is
attempted. */
uint m_nDelay;
/** The maximal number of results. */
uint m_nMaxEntries;
friend class NewProjectDlg;
};
/**
* A dialog for creating new projects.
* Prompts the user for the project's name, the directory for Cscope's files,
* the types of files included in the project and several options.
* Can also be used to change some of the properties of a project after it
* has been created.
* @author Elad Lahav
*/
class NewProjectDlg : public NewProjectLayout
{
Q_OBJECT
public:
NewProjectDlg(bool, QWidget* pParent = NULL, const char* szName = NULL);
~NewProjectDlg();
void setProperties(const QString&, const QString&,
const ProjectBase::Options&);
QString getName();
QString getPath();
void getOptions(ProjectBase::Options&);
protected slots:
virtual void accept();
virtual void slotAddType();
virtual void slotRemoveType();
virtual void slotAvailTypesChanged(const QString&);
private:
/** The file MIME-types associated with the new project. */
QStringList m_slTypes;
/** A sub-dialogue for configuring symbol auto-completion parameters. */
AutoCompletionDlg* m_pAutoCompDlg;
/** Whether the dialogue represents a new or existing project. */
bool m_bNewProj;
};
#endif

@ -0,0 +1,778 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>NewProjectLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>NewProjectLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>539</width>
<height>383</height>
</rect>
</property>
<property name="caption">
<string>Create Project</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QTabWidget">
<property name="name">
<cstring>tabWidget2</cstring>
</property>
<widget class="QWidget">
<property name="name">
<cstring>tab</cstring>
</property>
<attribute name="title">
<string>Detai&amp;ls</string>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout18</cstring>
</property>
<grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel" row="1" column="0">
<property name="name">
<cstring>textLabel2</cstring>
</property>
<property name="text">
<string>Path</string>
</property>
</widget>
<widget class="QLineEdit" row="0" column="1">
<property name="name">
<cstring>m_pNameEdit</cstring>
</property>
<property name="whatsThis" stdset="0">
<string>Enter a name for this project.
The name must conform to the file system's naming conventions for directories (e.g., no spaces, exclamaion marks, etc.).</string>
</property>
</widget>
<widget class="QLabel" row="0" column="0">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="text">
<string>Name</string>
</property>
</widget>
<widget class="KURLRequester" row="1" column="1">
<property name="name">
<cstring>m_pPathRequester</cstring>
</property>
<property name="whatsThis" stdset="0">
<string>The path to hold this project.
KScope will create a directory with the given name under this project, and populate it with the project configuration and database files.
This does not need to be the path in which the source files reside.</string>
</property>
</widget>
</grid>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pHiddenDirCheck</cstring>
</property>
<property name="text">
<string>&amp;Use a hidden folder under the source root directory</string>
</property>
<property name="accel">
<string>Alt+U</string>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout19</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1_2</cstring>
</property>
<property name="text">
<string>Source Root (Optional)</string>
</property>
</widget>
<widget class="KURLRequester">
<property name="name">
<cstring>m_pSrcRootRequester</cstring>
</property>
</widget>
</hbox>
</widget>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1_3</cstring>
</property>
<property name="text">
<string>&lt;blockquote&gt;A project consists of several files located in a directory
with the given name and path. The project's name needs to be a valid directory
name and must not contain any whitespace.&lt;/blockquote&gt;
&lt;br&gt;
&lt;blockquote&gt;The Source Root is a convinient way to specify a common
path for all source files, but is not required.&lt;/blockquote&gt;</string>
</property>
<property name="alignment">
<set>WordBreak|AlignVCenter</set>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer29</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>31</width>
<height>50</height>
</size>
</property>
</spacer>
</vbox>
</widget>
<widget class="QWidget">
<property name="name">
<cstring>tab</cstring>
</property>
<attribute name="title">
<string>File T&amp;ypes</string>
</attribute>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QGroupBox">
<property name="name">
<cstring>groupBox1</cstring>
</property>
<property name="title">
<string>This Project</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QListBox">
<property name="name">
<cstring>m_pTypesList</cstring>
</property>
<property name="whatsThis" stdset="0">
<string>KScope uses these filters to locate source files to include in this project.</string>
</property>
</widget>
</vbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout5</cstring>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer7</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>21</width>
<height>61</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pAddButton</cstring>
</property>
<property name="text">
<string>&lt;&lt; &amp;Add</string>
</property>
<property name="accel">
<string>Alt+A</string>
</property>
<property name="whatsThis" stdset="0">
<string>Adds the selected file type to the current project.</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pRemoveButton</cstring>
</property>
<property name="text">
<string>&gt;&gt; &amp;Remove</string>
</property>
<property name="accel">
<string>Alt+R</string>
</property>
<property name="whatsThis" stdset="0">
<string>Remove the selected file type from the project.</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer2</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>21</width>
<height>50</height>
</size>
</property>
</spacer>
</vbox>
</widget>
<widget class="QGroupBox">
<property name="name">
<cstring>groupBox2</cstring>
</property>
<property name="title">
<string>Available Types</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLineEdit">
<property name="name">
<cstring>m_pTypesEdit</cstring>
</property>
<property name="whatsThis" stdset="0">
<string>You can enter custom file types here.</string>
</property>
</widget>
<widget class="QListBox">
<item>
<property name="text">
<string>*.c</string>
</property>
</item>
<item>
<property name="text">
<string>*.h</string>
</property>
</item>
<item>
<property name="text">
<string>*.l</string>
</property>
</item>
<item>
<property name="text">
<string>*.y</string>
</property>
</item>
<item>
<property name="text">
<string>*.S</string>
</property>
</item>
<item>
<property name="text">
<string>*.cc</string>
</property>
</item>
<item>
<property name="text">
<string>*.cpp</string>
</property>
</item>
<item>
<property name="text">
<string>*.cxx</string>
</property>
</item>
<item>
<property name="text">
<string>*.C</string>
</property>
</item>
<item>
<property name="text">
<string>*.hh</string>
</property>
</item>
<item>
<property name="text">
<string>*.hpp</string>
</property>
</item>
<item>
<property name="text">
<string>*.hxx</string>
</property>
</item>
<item>
<property name="text">
<string>*.H</string>
</property>
</item>
<property name="name">
<cstring>m_pAvailTypesList</cstring>
</property>
<property name="whatsThis" stdset="0">
<string>A list of standard file types.</string>
</property>
</widget>
</vbox>
</widget>
<spacer>
<property name="name">
<cstring>spacer8_2</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>61</width>
<height>21</height>
</size>
</property>
</spacer>
</hbox>
</widget>
<widget class="QWidget">
<property name="name">
<cstring>TabPage</cstring>
</property>
<attribute name="title">
<string>&amp;Options</string>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pKernelCheck</cstring>
</property>
<property name="text">
<string>Kernel project (-k)</string>
</property>
<property name="accel">
<string></string>
</property>
<property name="whatsThis" stdset="0">
<string>For kernel projects, symbols are not looked up in the standard include path.</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pInvCheck</cstring>
</property>
<property name="text">
<string>Build inverted inde&amp;x (-q)</string>
</property>
<property name="accel">
<string>Alt+X</string>
</property>
<property name="whatsThis" stdset="0">
<string>An inverted index may greatly speed up searches in a large project. The project's building process is longer, though.</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pNoCompCheck</cstring>
</property>
<property name="text">
<string>Do not compress the database (-c)</string>
</property>
<property name="accel">
<string></string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pSlowPathCheck</cstring>
</property>
<property name="text">
<string>Slower, but more accurate, function definition detection (-D)</string>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout31</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pAutoRebuildCheck</cstring>
</property>
<property name="text">
<string>Refresh data&amp;base automatically</string>
</property>
<property name="accel">
<string>Alt+B</string>
</property>
<property name="whatsThis" stdset="0">
<string>Rebuild the database after changed files are saved to disk.</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer32</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>125</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QLabel">
<property name="name">
<cstring>m_pAutoRebuildLabel</cstring>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>(Seconds)</string>
</property>
</widget>
<widget class="QSpinBox">
<property name="name">
<cstring>m_pAutoRebuildSpin</cstring>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="whatsThis" stdset="0">
<string>Wait this number of seconds after the last save before rebuilding the database.</string>
</property>
</widget>
</hbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout30</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pACCheck</cstring>
</property>
<property name="text">
<string>&amp;Use symbol auto-completion</string>
</property>
<property name="accel">
<string>Alt+U</string>
</property>
<property name="whatsThis" stdset="0">
<string>As-you-type symbol completion.</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer33</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>61</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pACButton</cstring>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Options...</string>
</property>
</widget>
</hbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout6</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pTabWidthCheck</cstring>
</property>
<property name="text">
<string>Override default tab width (Kate only)</string>
</property>
<property name="toolTip" stdset="0">
<string>Overrides the editor's configured tab width</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer9</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>211</width>
<height>31</height>
</size>
</property>
</spacer>
<widget class="QSpinBox">
<property name="name">
<cstring>m_pTabWidthSpin</cstring>
</property>
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</hbox>
</widget>
<spacer>
<property name="name">
<cstring>spacer31</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>21</width>
<height>40</height>
</size>
</property>
</spacer>
</vbox>
</widget>
<widget class="QWidget">
<property name="name">
<cstring>TabPage</cstring>
</property>
<attribute name="title">
<string>&amp;Advanced</string>
</attribute>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1_4</cstring>
</property>
<property name="text">
<string>Ctags command line (Do not change unless you know what you are doing!)</string>
</property>
</widget>
<widget class="QTextEdit">
<property name="name">
<cstring>m_pCtagsCmdEdit</cstring>
</property>
<property name="textFormat">
<enum>PlainText</enum>
</property>
<property name="autoFormatting">
<set>AutoAll</set>
</property>
</widget>
</vbox>
</widget>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout19</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer8</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>141</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCreateButton</cstring>
</property>
<property name="text">
<string>&amp;Create</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCancelButton</cstring>
</property>
<property name="text">
<string>Ca&amp;ncel</string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<connections>
<connection>
<sender>m_pAddButton</sender>
<signal>clicked()</signal>
<receiver>NewProjectLayout</receiver>
<slot>slotAddType()</slot>
</connection>
<connection>
<sender>m_pRemoveButton</sender>
<signal>clicked()</signal>
<receiver>NewProjectLayout</receiver>
<slot>slotRemoveType()</slot>
</connection>
<connection>
<sender>m_pAutoRebuildCheck</sender>
<signal>toggled(bool)</signal>
<receiver>m_pAutoRebuildSpin</receiver>
<slot>setEnabled(bool)</slot>
</connection>
<connection>
<sender>m_pACCheck</sender>
<signal>toggled(bool)</signal>
<receiver>m_pACButton</receiver>
<slot>setEnabled(bool)</slot>
</connection>
<connection>
<sender>m_pAvailTypesList</sender>
<signal>highlighted(const QString&amp;)</signal>
<receiver>NewProjectLayout</receiver>
<slot>slotAvailTypesChanged(const QString&amp;)</slot>
</connection>
<connection>
<sender>m_pTabWidthCheck</sender>
<signal>toggled(bool)</signal>
<receiver>m_pTabWidthSpin</receiver>
<slot>setEnabled(bool)</slot>
</connection>
<connection>
<sender>m_pAutoRebuildCheck</sender>
<signal>toggled(bool)</signal>
<receiver>m_pAutoRebuildLabel</receiver>
<slot>setEnabled(bool)</slot>
</connection>
<connection>
<sender>m_pHiddenDirCheck</sender>
<signal>toggled(bool)</signal>
<receiver>m_pPathRequester</receiver>
<slot>setDisabled(bool)</slot>
</connection>
</connections>
<tabstops>
<tabstop>m_pNameEdit</tabstop>
<tabstop>m_pPathRequester</tabstop>
<tabstop>m_pHiddenDirCheck</tabstop>
<tabstop>m_pSrcRootRequester</tabstop>
<tabstop>m_pAddButton</tabstop>
<tabstop>m_pRemoveButton</tabstop>
<tabstop>m_pKernelCheck</tabstop>
<tabstop>m_pInvCheck</tabstop>
<tabstop>m_pNoCompCheck</tabstop>
<tabstop>m_pSlowPathCheck</tabstop>
<tabstop>m_pAutoRebuildCheck</tabstop>
<tabstop>m_pAutoRebuildSpin</tabstop>
<tabstop>m_pACCheck</tabstop>
<tabstop>m_pACButton</tabstop>
<tabstop>m_pTabWidthCheck</tabstop>
<tabstop>m_pTabWidthSpin</tabstop>
<tabstop>m_pCreateButton</tabstop>
<tabstop>m_pCancelButton</tabstop>
<tabstop>tabWidget2</tabstop>
<tabstop>m_pTypesList</tabstop>
<tabstop>m_pTypesEdit</tabstop>
<tabstop>m_pAvailTypesList</tabstop>
<tabstop>m_pCtagsCmdEdit</tabstop>
</tabstops>
<slots>
<slot access="protected">slotAddType()</slot>
<slot access="protected">slotRemoveType()</slot>
<slot access="protected">slotAutoRebuildChanged(bool)</slot>
<slot access="protected">slotAutoCompletionChanged(bool)</slot>
<slot access="protected">slotAvailTypesChanged(const QString&amp;)</slot>
</slots>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>kurlrequester.h</includehint>
<includehint>klineedit.h</includehint>
<includehint>kpushbutton.h</includehint>
<includehint>kurlrequester.h</includehint>
<includehint>klineedit.h</includehint>
<includehint>kpushbutton.h</includehint>
</includehints>
</UI>

@ -0,0 +1,131 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qlistbox.h>
#include <kurlrequester.h>
#include "openprojectdlg.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
OpenProjectDlg::OpenProjectDlg(QWidget* pParent, const char* szName) :
OpenProjectLayout(pParent, szName)
{
loadRecent();
m_pProjPathRequester->setFilter("cscope.proj");
}
/**
* Class destructor.
*/
OpenProjectDlg::~OpenProjectDlg()
{
}
/**
* @return The selected project path
*/
QString OpenProjectDlg::getPath() const
{
return m_pProjPathRequester->url();
}
/**
* Sets the requester to reflect the selected project's directory, instead of
* the cscope.proj file.
* @param sProjPath The full path of the selected cscope.proj file
*/
void OpenProjectDlg::slotProjectSelected(const QString& sProjPath)
{
QFileInfo fi(sProjPath);
m_pProjPathRequester->setURL(fi.dirPath(true));
}
/**
* Removes a project from the recent projects list.
* This slot is connected to the clicked() signal of the "Remove" button.
*/
void OpenProjectDlg::slotRemoveRecent()
{
QListBoxItem* pItem;
// Remove the selected item, if any
pItem = m_pRecentList->selectedItem();
if (pItem != NULL) {
Config().removeRecentProject(pItem->text());
m_pRecentList->removeItem(m_pRecentList->currentItem());
}
}
/**
* Selects a project for opening when an item is highlighted in the recent
* projects list.
* This slot is connected to the highlighted() signal of the recent projects
* list box.
* @param pItem The selected project item
*/
void OpenProjectDlg::slotSelectRecent(QListBoxItem* pItem)
{
if (pItem != NULL)
m_pProjPathRequester->setURL(pItem->text());
}
/**
* Selects a project for opening and closes the dialogue when an item in the
* recent projects list is double-clicked.
* This slot is connected to the doubleClicked() signal of the recent
* projects list box.
* @param pItem The selected project item
*/
void OpenProjectDlg::slotOpenRecent(QListBoxItem* pItem)
{
if (pItem != NULL) {
m_pProjPathRequester->setURL(pItem->text());
accept();
}
}
/**
* Fills the recent projects list box with the project paths read from the
* configuration file.
*/
void OpenProjectDlg::loadRecent()
{
const QStringList& slProjects = Config().getRecentProjects();
QStringList::const_iterator itr;
// Create a list item for each project in the list
for (itr = slProjects.begin(); itr != slProjects.end(); ++itr)
m_pRecentList->insertItem(*itr);
}
#include "openprojectdlg.moc"

@ -0,0 +1,61 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef OPENPROJECTDLG_H
#define OPENPROJECTDLG_H
#include <qwidget.h>
#include <openprojectlayout.h>
/**
* A dialogue for selecting a project to open.
* Allows projects to be searched, and displays a list of previosuly loaded
* projects.
* @author Elad Lahav
*/
class OpenProjectDlg : public OpenProjectLayout
{
Q_OBJECT
public:
OpenProjectDlg(QWidget* pParent = 0, const char* szName = 0);
~OpenProjectDlg();
QString getPath() const;
protected slots:
virtual void slotProjectSelected(const QString&);
virtual void slotRemoveRecent();
virtual void slotSelectRecent(QListBoxItem*);
virtual void slotOpenRecent(QListBoxItem*);
private:
void loadRecent();
};
#endif

@ -0,0 +1,202 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>OpenProjectLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>OpenProjectLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>417</width>
<height>384</height>
</rect>
</property>
<property name="caption">
<string>Open Project</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QButtonGroup">
<property name="name">
<cstring>buttonGroup5</cstring>
</property>
<property name="title">
<string>Project Path</string>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="KURLRequester">
<property name="name">
<cstring>m_pProjPathRequester</cstring>
</property>
</widget>
</hbox>
</widget>
<widget class="QButtonGroup">
<property name="name">
<cstring>buttonGroup6</cstring>
</property>
<property name="title">
<string>Recent Projects</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QListBox">
<property name="name">
<cstring>m_pRecentList</cstring>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout9</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer4</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>281</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pRemoveButton</cstring>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout9</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer6</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>201</width>
<height>31</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pOpenButton</cstring>
</property>
<property name="text">
<string>&amp;Open</string>
</property>
<property name="accel">
<string>Alt+O</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCancelButton</cstring>
</property>
<property name="text">
<string>C&amp;ancel</string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<customwidgets>
</customwidgets>
<connections>
<connection>
<sender>m_pOpenButton</sender>
<signal>clicked()</signal>
<receiver>OpenProjectLayout</receiver>
<slot>accept()</slot>
</connection>
<connection>
<sender>m_pCancelButton</sender>
<signal>clicked()</signal>
<receiver>OpenProjectLayout</receiver>
<slot>reject()</slot>
</connection>
<connection>
<sender>m_pRemoveButton</sender>
<signal>clicked()</signal>
<receiver>OpenProjectLayout</receiver>
<slot>slotRemoveRecent()</slot>
</connection>
<connection>
<sender>m_pRecentList</sender>
<signal>highlighted(QListBoxItem*)</signal>
<receiver>OpenProjectLayout</receiver>
<slot>slotSelectRecent(QListBoxItem*)</slot>
</connection>
<connection>
<sender>m_pRecentList</sender>
<signal>doubleClicked(QListBoxItem*)</signal>
<receiver>OpenProjectLayout</receiver>
<slot>slotOpenRecent(QListBoxItem*)</slot>
</connection>
<connection>
<sender>m_pProjPathRequester</sender>
<signal>urlSelected(const QString&amp;)</signal>
<receiver>OpenProjectLayout</receiver>
<slot>slotProjectSelected(const QString&amp;)</slot>
</connection>
<connection>
<sender>m_pRecentList</sender>
<signal>returnPressed(QListBoxItem*)</signal>
<receiver>OpenProjectLayout</receiver>
<slot>slotOpenRecent(QListBoxItem*)</slot>
</connection>
</connections>
<slots>
<slot access="protected">slotRemoveRecent()</slot>
<slot access="protected">slotSelectRecent(QListBoxItem*)</slot>
<slot access="protected">slotOpenRecent(QListBoxItem*)</slot>
<slot access="protected">slotProjectSelected(const QString&amp;)</slot>
</slots>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>kurlrequester.h</includehint>
<includehint>klineedit.h</includehint>
<includehint>kpushbutton.h</includehint>
</includehints>
</UI>

@ -0,0 +1,172 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qlistview.h>
#include <qpainter.h>
#include <kcolordialog.h>
#include "prefcolor.h"
#include "kscopeconfig.h"
/**
* A list view item that shows the name of a GUI element and the colour
* associated with it.
* The colour is presented in the form of a rectangle filled with that
* colour.
* @author Elad Lahav
*/
class ColorListItem : public QListViewItem
{
public:
/**
* Class constructor.
* @param pList The owner list view
* @param ce The GUI element shown by this item
*/
ColorListItem(QListView* pList, KScopeConfig::ColorElement ce) :
QListViewItem(pList, Config().getColorName(ce), ""),
m_ce(ce) {
setColor(Config().getColor(ce));
}
/**
* @return The GUI element shown by this item
*/
KScopeConfig::ColorElement getElement() { return m_ce; }
/**
* Changes the colour associated with this item.
* The function assigns a pixmap to the item which shows a rectangle
* filled with the requested colour.
* The colour set by this function is returned by getColor().
* @param clr The colour to set
*/
void setColor(QColor clr) {
QPixmap pix;
QPainter painter;
int nWidth, nHeight;
// Remember the colour
m_clr = clr;
// Set the pixmap's size to fit into the list field
nWidth = listView()->columnWidth(1) - 1;
nHeight = height();
pix.resize(nWidth, nHeight);
// Draw on the pixmap
painter.begin(&pix);
painter.setBrush(clr);
painter.drawRect(0, 0, nWidth, nHeight);
painter.end();
// Set the pixmap to the item
setPixmap(1, pix);
}
/**
* @return The colour associated with this item
*/
QColor getColor() { return m_clr; }
private:
/** The GUI element shown by this item. */
KScopeConfig::ColorElement m_ce;
/** The colour associated with this item. */
QColor m_clr;
};
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
PrefColor::PrefColor(QWidget* pParent, const char* szName) :
PrefColorLayout(pParent, szName)
{
m_pList->setColumnWidthMode(1, QListView::Manual);
// Set initial values
load();
}
/**
* Class destructor.
*/
PrefColor::~PrefColor()
{
}
/**
* Reads the current settings from the configuration object, and applies them
* the the page's widget.
*/
void PrefColor::load()
{
uint i;
ColorListItem* pItem;
// Create a list item for every GUI element
for (i = 0; i <= KScopeConfig::LAST_COLOR; i++)
pItem = new ColorListItem(m_pList, (KScopeConfig::ColorElement)i);
}
/**
* Commits settings changes to the configuration object.
*/
void PrefColor::apply()
{
ColorListItem* pItem;
// Create a list item for every GUI element
for (pItem = (ColorListItem*)m_pList->firstChild(); pItem != NULL;
pItem = (ColorListItem*)pItem->nextSibling()) {
Config().setColor(pItem->getElement(), pItem->getColor());
}
}
/**
* Displays a colour selection dialogue when an item is selected.
* If the user chooses a new colour, it is set to the selected item.
* This slot is connected to both the doubleClicked() and the returnPressed()
* signals of the list view.
* @param pItem The selected item
*/
void PrefColor::slotItemSelected(QListViewItem* pItem)
{
ColorListItem* pClrItem;
QColor clr;
pClrItem = (ColorListItem*)pItem;
if (KColorDialog::getColor(clr, pClrItem->getColor()) ==
QDialog::Accepted) {
pClrItem->setColor(clr);
emit modified();
}
}
#include "prefcolor.moc"

@ -0,0 +1,59 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PREFCOLORDLG_H
#define PREFCOLORDLG_H
#include <prefcolorlayout.h>
/**
* A widget for selecting colours for KScope's main child-windows.
* @author Elad Lahav
*/
class PrefColor : public PrefColorLayout
{
Q_OBJECT
public:
PrefColor(QWidget* pParent = 0, const char* szName = 0);
~PrefColor();
void load();
void apply();
signals:
/**
* Emitted whenever the user makes a change to the dialogue's input
* widgets.
*/
void modified();
protected slots:
void slotItemSelected(QListViewItem*);
};
#endif

@ -0,0 +1,69 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>PrefColorLayout</class>
<widget class="QWidget">
<property name="name">
<cstring>PrefColorLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>210</height>
</rect>
</property>
<property name="caption">
<string>Form4</string>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QListView">
<column>
<property name="text">
<string>GUI Element</string>
</property>
<property name="clickable">
<bool>true</bool>
</property>
<property name="resizable">
<bool>true</bool>
</property>
</column>
<column>
<property name="text">
<string>Colour</string>
</property>
<property name="clickable">
<bool>true</bool>
</property>
<property name="resizable">
<bool>false</bool>
</property>
</column>
<property name="name">
<cstring>m_pList</cstring>
</property>
</widget>
</hbox>
</widget>
<connections>
<connection>
<sender>m_pList</sender>
<signal>doubleClicked(QListViewItem*)</signal>
<receiver>PrefColorLayout</receiver>
<slot>slotItemSelected(QListViewItem*)</slot>
</connection>
<connection>
<sender>m_pList</sender>
<signal>returnPressed(QListViewItem*)</signal>
<receiver>PrefColorLayout</receiver>
<slot>slotItemSelected(QListViewItem*)</slot>
</connection>
</connections>
<slots>
<slot access="protected">slotItemSelected(QListViewItem*)</slot>
</slots>
<layoutdefaults spacing="6" margin="11"/>
</UI>

@ -0,0 +1,206 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qlayout.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kurlrequester.h>
#include <klineedit.h>
#include <qcheckbox.h>
#include <kcolorbutton.h>
#include <kmessagebox.h>
#include <kfontrequester.h>
#include "preferencesdlg.h"
#include "preffrontend.h"
#include "prefcolor.h"
#include "preffont.h"
#include "prefopt.h"
#include "kscopeconfig.h"
#include "cscopefrontend.h"
#include "ctagsfrontend.h"
#include "dotfrontend.h"
/**
* Class constructor.
* @param nPage The initial page to show
* @param pParent The parent widget
* @param szName The widget's name
*/
PreferencesDlg::PreferencesDlg(uint nPage, QWidget* pParent,
const char* szName) :
KDialogBase(IconList, i18n("Preferences"), Default | Ok | Apply | Cancel,
Ok, pParent, szName, 0)
{
QFrame* pFrame;
QVBoxLayout* pLayout;
// Create and add the "Frontend" page
pFrame = addPage(i18n("Programmes"),
i18n("Paths to back-end programmes"),
KGlobal::iconLoader()->loadIcon("run", KIcon::Panel, 0, false));
pLayout = new QVBoxLayout(pFrame, 0, 0);
m_pPrefFrontend = new PrefFrontend(pFrame);
pLayout->addWidget(m_pPrefFrontend);
// Create and add the "Colours" page
pFrame = addPage(i18n("Colours"), i18n("Window colours"),
KGlobal::iconLoader()->loadIcon("colors", KIcon::Panel, 0, false));
pLayout = new QVBoxLayout(pFrame, 0, 0);
m_pPrefColor = new PrefColor(pFrame);
pLayout->addWidget(m_pPrefColor);
// Create and add the "Fonts" page
pFrame = addPage(i18n("Fonts"), i18n("Window fonts"),
KGlobal::iconLoader()->loadIcon("fonts", KIcon::Panel, 0, false));
pLayout = new QVBoxLayout(pFrame, 0, 0);
m_pPrefFont = new PrefFont(pFrame);
pLayout->addWidget(m_pPrefFont);
// Create and add the "Options" page
pFrame = addPage(i18n("Options"), i18n("Misc. Options"),
KGlobal::iconLoader()->loadIcon("package_settings",
KIcon::Panel, 0, false));
pLayout = new QVBoxLayout(pFrame, 0, 0);
m_pPrefOpt = new PrefOpt(pFrame);
pLayout->addWidget(m_pPrefOpt);
// Make sure the "Apply" button is initially disabled
enableButtonApply(false);
// Enable the "Apply" button when a parameter changes its value
connect(m_pPrefFrontend, SIGNAL(modified()), this,
SLOT(slotModified()));
connect(m_pPrefColor, SIGNAL(modified()), this, SLOT(slotModified()));
connect(m_pPrefFont, SIGNAL(modified()), this, SLOT(slotModified()));
connect(m_pPrefOpt, SIGNAL(modified()), this, SLOT(slotModified()));
// Set the active page
showPage(nPage);
}
/**
* Class destructor.
*/
PreferencesDlg::~PreferencesDlg()
{
}
/**
* Updates the dialog's widgets with the current configuration parameters.
*/
void PreferencesDlg::loadConfig()
{
m_pPrefFrontend->load();
m_pPrefColor->load();
m_pPrefFont->load();
m_pPrefOpt->load();
}
/**
* Sets the configured parameters to the global configuration object.
* This method is called when either the "OK" or the "Apply" button are
* clicked. Before the new settings are applied, their values are verified.
* @return true if the new parameters were applied successfully, false
* otherwise
*/
bool PreferencesDlg::updateConfig()
{
// Verify configured paths lead to the executables
if (!verifyPaths())
return false;
// Apply the changes
m_pPrefFrontend->apply();
m_pPrefColor->apply();
m_pPrefFont->apply();
m_pPrefOpt->apply();
emit applyPref();
return true;
}
/**
* Tests whether the paths set for Cscope and Ctags lead to executables.
* Cscope is verified by a different process.
*/
bool PreferencesDlg::verifyPaths()
{
return (CtagsFrontend::verify(m_pPrefFrontend->m_pCtagsURL->url()) &&
DotFrontend::verify(m_pPrefFrontend->m_pDotURL->url()));
}
/**
* Updates the global configuration based on the values given in the
* preferences dialogue, and then closes the dialogue.
* This function is called after the user clicks the dialogue's "OK" button.
*/
void PreferencesDlg::accept()
{
if (updateConfig())
KDialogBase::accept();
}
/**
* Updates the global configuration based on the values given in the
* preferences dialogue, leaving the dialogue open.
* This function is called after the user clicks the dialogue's "Apply"
* button.
*/
void PreferencesDlg::slotApply()
{
if (updateConfig())
enableButtonApply(false);
}
/**
* Resets all configuration parameters to their default values.
* This slot is called when the user clicks the "Default" button.
*/
void PreferencesDlg::slotDefault()
{
// Prompt the user before applying default values
if (KMessageBox::questionYesNo(0, i18n("This would reset all your "
"configuration settings! Continue?")) == KMessageBox::Yes) {
// Load the default values
Config().loadDefault();
loadConfig();
// Apply the default values
slotApply();
}
}
/**
* Enables the "Apply" button.
*/
void PreferencesDlg::slotModified()
{
enableButtonApply(true);
}
#include "preferencesdlg.moc"

@ -0,0 +1,93 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PREFERENCESDLG_H
#define PREFERENCESDLG_H
#include <qwidget.h>
#include <kdialogbase.h>
class PrefFrontend;
class PrefColor;
class PrefFont;
class PrefOpt;
/**
* The main configuration dialog for KScope.
* This dialog displays a set of configuration pages, each dedicated to a
* different subject (frontend programme paths, colours, etc.)
* This code is based on a tutorial by Andreas Nicolai which can be found at
* http://www.kdevelop.org/doc/tutorial_settings
* @author Elad Lahav
*/
class PreferencesDlg : public KDialogBase
{
Q_OBJECT
public:
PreferencesDlg(uint nPage = Frontend, QWidget* pParent = 0, const char*
szName = 0);
~PreferencesDlg();
/** Available pages. */
enum { Frontend = 0, Colors, Fonts, Options };
signals:
/**
* Emitted when the global configuration changes as a result of using
* this dialogue.
*/
void applyPref();
protected slots:
virtual void accept();
virtual void slotApply();
virtual void slotDefault();
private:
/** The front-end programmes page. */
PrefFrontend* m_pPrefFrontend;
/** The colours preference page. */
PrefColor* m_pPrefColor;
/** The fonts preference page. */
PrefFont* m_pPrefFont;
/** The additional options page. */
PrefOpt* m_pPrefOpt;
void loadConfig();
bool updateConfig();
bool verifyPaths();
private slots:
void slotModified();
};
#endif

@ -0,0 +1,174 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qlistview.h>
#include <qpainter.h>
#include <kfontdialog.h>
#include <klocale.h>
#include "preffont.h"
#include "kscopeconfig.h"
/**
* A list view item that shows the name of a GUI element and the font
* associated with it.
* The font is presented in the form of a sample text drawn using this font.
* @author Elad Lahav
*/
class FontListItem : public QListViewItem
{
public:
/**
* Class constructor.
* @param pList The owner list view
* @param fe The GUI element shown by this item
*/
FontListItem(QListView* pList, KScopeConfig::FontElement fe) :
QListViewItem(pList, Config().getFontName(fe), ""),
m_fe(fe) {
setFont(Config().getFont(fe));
}
/**
* @return The GUI element shown by this item
*/
KScopeConfig::FontElement getElement() { return m_fe; }
/**
* Changes the font associated with this item.
* The function a sample text on a pixmap using this font, and then
* assigns the pixmap to the list item.
* The font set by this function is returned by getFont().
* @param font The font to set
*/
void setFont(QFont font) {
QPixmap pix;
QFontMetrics fm(font);
QPainter painter;
QRect rc;
// Remember the font
m_font = font;
// Set the pixmap's size so it can contain the sample text
rc = fm.boundingRect(i18n("Sample"));
rc.moveTopLeft(QPoint(0, 0));
pix.resize(rc.width(), rc.height());
// Draw on the pixmap
pix.fill();
painter.begin(&pix);
painter.setFont(font);
painter.setPen(black);
painter.drawText(rc, Qt::AlignHCenter | Qt::AlignVCenter,
i18n("Sample"));
painter.end();
// Set the pixmap to the item
setPixmap(1, pix);
}
/**
* @return The font associated with this item
*/
QFont getFont() { return m_font; }
private:
/** The GUI element shown by this item. */
KScopeConfig::FontElement m_fe;
/** The font associated with this item. */
QFont m_font;
};
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
PrefFont::PrefFont(QWidget* pParent, const char* szName) :
PrefFontLayout(pParent, szName)
{
// Set initial values
load();
}
/**
* Class destructor.
*/
PrefFont::~PrefFont()
{
}
/**
* Reads the current settings from the configuration object, and applies them
* the the page's widget.
*/
void PrefFont::load()
{
uint i;
FontListItem* pItem;
// Create a list item for every GUI element
for (i = 0; i <= KScopeConfig::LAST_FONT; i++)
pItem = new FontListItem(m_pList, (KScopeConfig::FontElement)i);
}
/**
* Commits settings changes to the configuration object.
*/
void PrefFont::apply()
{
FontListItem* pItem;
// Create a list item for every GUI element
for (pItem = (FontListItem*)m_pList->firstChild(); pItem != NULL;
pItem = (FontListItem*)pItem->nextSibling()) {
Config().setFont(pItem->getElement(), pItem->getFont());
}
}
/**
* Displays a font selection dialogue when an item is selected.
* If the user chooses a new font, it is set to the selected item.
* This slot is connected to both the doubleClicked() and the returnPressed()
* signals of the list view.
* @param pItem The selected item
*/
void PrefFont::slotItemSelected(QListViewItem* pItem)
{
FontListItem* pFontItem;
QFont font;
pFontItem = (FontListItem*)pItem;
font = pFontItem->getFont();
if (KFontDialog::getFont(font) == QDialog::Accepted) {
pFontItem->setFont(font);
emit modified();
}
}
#include "preffont.moc"

@ -0,0 +1,60 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PREFFONT_H
#define PREFFONT_H
#include "preffontlayout.h"
/**
* A widget for selecting fonts for KScope's main child-windows.
* @author Elad Lahav
*/
class PrefFont : public PrefFontLayout
{
Q_OBJECT
public:
PrefFont(QWidget* pParent = 0, const char* szName = 0);
~PrefFont();
void load();
void apply();
signals:
/**
* Emitted whenever the user makes a change to the dialogue's input
* widgets.
*/
void modified();
protected slots:
void slotItemSelected(QListViewItem*);
};
#endif

@ -0,0 +1,69 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>PrefFontLayout</class>
<widget class="QWidget">
<property name="name">
<cstring>PrefFontLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>363</width>
<height>210</height>
</rect>
</property>
<property name="caption">
<string>Form4</string>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QListView">
<column>
<property name="text">
<string>GUI Element</string>
</property>
<property name="clickable">
<bool>true</bool>
</property>
<property name="resizable">
<bool>true</bool>
</property>
</column>
<column>
<property name="text">
<string>Font</string>
</property>
<property name="clickable">
<bool>true</bool>
</property>
<property name="resizable">
<bool>false</bool>
</property>
</column>
<property name="name">
<cstring>m_pList</cstring>
</property>
</widget>
</hbox>
</widget>
<connections>
<connection>
<sender>m_pList</sender>
<signal>doubleClicked(QListViewItem*)</signal>
<receiver>PrefFontLayout</receiver>
<slot>slotItemSelected(QListViewItem*)</slot>
</connection>
<connection>
<sender>m_pList</sender>
<signal>returnPressed(QListViewItem*)</signal>
<receiver>PrefFontLayout</receiver>
<slot>slotItemSelected(QListViewItem*)</slot>
</connection>
</connections>
<slots>
<slot access="protected">slotItemSelected(QListViewItem*)</slot>
</slots>
<layoutdefaults spacing="6" margin="11"/>
</UI>

@ -0,0 +1,238 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qcheckbox.h>
#include <qtextedit.h>
#include <kurlrequester.h>
#include <klineedit.h>
#include <kstandarddirs.h>
#include <klocale.h>
#include "preffrontend.h"
#include "kscopeconfig.h"
#include "configfrontend.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
PrefFrontend::PrefFrontend(QWidget* pParent, const char* szName) :
PrefFrontendLayout(pParent, szName)
{
// Set initial values
load();
// Attempt to guess paths based on the user's PATH environment variable
connect(m_pGuessButton, SIGNAL(clicked()), this,
SLOT(slotGuessPaths()));
// Emit the modified() signal when a new path is set
connect(m_pCscopeURL, SIGNAL(textChanged(const QString&)), this,
SIGNAL(modified()));
connect(m_pCtagsURL, SIGNAL(textChanged(const QString&)), this,
SIGNAL(modified()));
connect(m_pDotURL, SIGNAL(textChanged(const QString&)), this,
SIGNAL(modified()));
}
/**
* Class destructor.
*/
PrefFrontend::~PrefFrontend()
{
}
/**
* Reads the current settings from the configuration object, and applies them
* the the page's widget.
*/
void PrefFrontend::load()
{
m_pCscopeURL->lineEdit()->setText(Config().getCscopePath());
m_pCtagsURL->lineEdit()->setText(Config().getCtagsPath());
m_pDotURL->lineEdit()->setText(Config().getDotPath());
}
/**
* Commits settings changes to the configuration object.
*/
void PrefFrontend::apply()
{
Config().setCscopePath(m_pCscopeURL->url());
Config().setCtagsPath(m_pCtagsURL->url());
Config().setDotPath(m_pDotURL->url());
}
/**
* Emits the modified() signal whenever any of the paths edit widgets changes
* its contents.
* This slot is connected to the textChanged() signal of each of the path
* edit widgets. By emitting the modified() signal, the widget notifies the
* parent dialog it should enable the "Apply" button.
*/
void PrefFrontend::slotChanged(const QString&)
{
emit modified();
}
/**
* Checks the user's PATH environment variable for a Cscope and Ctags
* executables.
* This is done by running the kscope_config script.
*/
void PrefFrontend::slotGuessPaths()
{
ConfigFrontend* pConf;
// Start with an empty results text widget
m_pScriptText->clear();
// Create a frontend object for the script
pConf = new ConfigFrontend(true);
// Show tests and results in the text widget
connect(pConf, SIGNAL(test(uint)), this,
SLOT(slotAutoConfigTest(uint)));
connect(pConf, SIGNAL(result(uint, const QString&)), this,
SLOT(slotAutoConfigResult(uint, const QString&)));
// Run the script
pConf->run(m_pCscopeURL->url(), m_pCtagsURL->url(),
m_pDotURL->url());
}
/**
* Shows the test being executed by the script in the text widget.
* This slot is connected to the test() signal of the ConfigFrontend object.
* @param nType The type of test being executed
*/
void PrefFrontend::slotAutoConfigTest(uint nType)
{
switch (nType) {
case ConfigFrontend::CscopePath:
m_pScriptText->insert(i18n("Looking for Cscope..."));
break;
case ConfigFrontend::CscopeVersion:
m_pScriptText->insert(i18n("Checking Cscope version..."));
break;
case ConfigFrontend::CscopeVerbose:
m_pScriptText->insert(i18n("Cscope support for line mode verbose "
"output..."));
break;
case ConfigFrontend::CscopeSlowPath:
m_pScriptText->insert(i18n("Cscope support slow path definitions... "));
break;
case ConfigFrontend::CtagsPath:
m_pScriptText->insert(i18n("Looking for Ctags..."));
break;
case ConfigFrontend::CtagsExub:
m_pScriptText->insert(i18n("Ctags compatibilty with ctags-exuberant"
"..."));
break;
case ConfigFrontend::DotPath:
m_pScriptText->insert(i18n("Looking for Dot..."));
break;
case ConfigFrontend::DotPlain:
m_pScriptText->insert(i18n("Checking -Tplain..."));
break;
}
}
/**
* Shows the result of a test executed by the configuration script, and
* adjusts the configuration widgets accordingly.
* @param nType The type of test that was executed
* @param sResult The test's result
*/
void PrefFrontend::slotAutoConfigResult(uint nType, const QString& sResult)
{
QString sLine;
sLine = sResult + "\n";
switch (nType) {
case ConfigFrontend::CscopePath:
m_pScriptText->insert(sLine);
if (sResult == "ERROR")
m_pCscopeURL->lineEdit()->setText("");
else
m_pCscopeURL->lineEdit()->setText(sResult);
break;
case ConfigFrontend::CscopeVersion:
m_pScriptText->insert(sLine);
if (sResult == "ERROR")
m_pCscopeURL->lineEdit()->setText("");
break;
case ConfigFrontend::CscopeVerbose:
m_pScriptText->insert(sLine);
break;
case ConfigFrontend::CscopeSlowPath:
m_pScriptText->insert(sLine);
break;
case ConfigFrontend::CtagsPath:
m_pScriptText->insert(sLine);
if (sResult == "ERROR")
m_pCtagsURL->lineEdit()->setText("");
else
m_pCtagsURL->lineEdit()->setText(sResult);
break;
case ConfigFrontend::CtagsExub:
m_pScriptText->insert(sLine);
if (sResult == "ERROR")
m_pCtagsURL->lineEdit()->setText("");
break;
case ConfigFrontend::DotPath:
m_pScriptText->insert(sLine);
if (sResult == "ERROR")
m_pDotURL->lineEdit()->setText("");
else
m_pDotURL->lineEdit()->setText(sResult);
break;
case ConfigFrontend::DotPlain:
m_pScriptText->insert(sLine);
if (sResult == "ERROR")
m_pDotURL->lineEdit()->setText("");
break;
}
}
#include "preffrontend.moc"

@ -0,0 +1,65 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PREFFRONTENDDLG_H
#define PREFFRONTENDDLG_H
#include <qwidget.h>
#include <preffrontendlayout.h>
/**
* A widget for setting the paths to various programmes to which KScope
* provides a front-end.
* @author Elad Lahav
*/
class PrefFrontend : public PrefFrontendLayout
{
Q_OBJECT
public:
PrefFrontend(QWidget* pParent = 0, const char* szName = 0);
~PrefFrontend();
void load();
void apply();
signals:
/**
* Emitted whenever the user makes a change to the dialogue's input
* widgets.
*/
void modified();
private slots:
void slotChanged(const QString&);
void slotGuessPaths();
void slotAutoConfigTest(uint);
void slotAutoConfigResult(uint, const QString&);
};
#endif

@ -0,0 +1,193 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>PrefFrontendLayout</class>
<widget class="QWidget">
<property name="name">
<cstring>PrefFrontendLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>415</width>
<height>368</height>
</rect>
</property>
<property name="caption">
<string>Form3</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout20</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout19</cstring>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>5</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cscope path:</string>
</property>
</widget>
<widget class="QLabel">
<property name="name">
<cstring>textLabel2</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>5</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Ctags path:</string>
</property>
</widget>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1_2</cstring>
</property>
<property name="text">
<string>Dot path:</string>
</property>
</widget>
</vbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout18</cstring>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="KURLRequester">
<property name="name">
<cstring>m_pCscopeURL</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>5</hsizetype>
<vsizetype>5</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
<widget class="KURLRequester">
<property name="name">
<cstring>m_pCtagsURL</cstring>
</property>
</widget>
<widget class="KURLRequester">
<property name="name">
<cstring>m_pDotURL</cstring>
</property>
</widget>
</vbox>
</widget>
</hbox>
</widget>
<widget class="Line">
<property name="name">
<cstring>line2</cstring>
</property>
<property name="frameShape">
<enum>HLine</enum>
</property>
<property name="frameShadow">
<enum>Sunken</enum>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout4</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer8</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>261</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pGuessButton</cstring>
</property>
<property name="text">
<string>G&amp;uess</string>
</property>
</widget>
</hbox>
</widget>
<widget class="QTextEdit">
<property name="name">
<cstring>m_pScriptText</cstring>
</property>
<property name="enabled">
<bool>true</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</vbox>
</widget>
<customwidgets>
</customwidgets>
<tabstops>
</tabstops>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>kurlrequester.h</includehint>
<includehint>klineedit.h</includehint>
<includehint>kpushbutton.h</includehint>
<includehint>kurlrequester.h</includehint>
<includehint>klineedit.h</includehint>
<includehint>kpushbutton.h</includehint>
<includehint>kurlrequester.h</includehint>
<includehint>klineedit.h</includehint>
<includehint>kpushbutton.h</includehint>
</includehints>
</UI>

@ -0,0 +1,145 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qcheckbox.h>
#include <qradiobutton.h>
#include <qlineedit.h>
#include <qlabel.h>
#include "prefopt.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
PrefOpt::PrefOpt(QWidget* pParent, const char* szName)
: PrefOptLayout(pParent, szName)
{
// Set initial values
load();
// Emit the "modified" signal whenever any of the widgets changes its
// its. This will notify the parent dialogue to enable its "Apply"
// button
connect(m_pReadOnlyCheck, SIGNAL(toggled(bool)), this,
SIGNAL(modified()));
connect(m_pLastProjCheck, SIGNAL(toggled(bool)), this,
SIGNAL(modified()));
connect(m_pTagHlCheck, SIGNAL(toggled(bool)), this,
SIGNAL(modified()));
connect(m_pBriefQueryCaptCheck, SIGNAL(toggled(bool)), this,
SIGNAL(modified()));
connect(m_pWarnModifiedOnDiskCheck, SIGNAL(toggled(bool)), this,
SIGNAL(modified()));
connect(m_pAutoSortCheck, SIGNAL(toggled(bool)), this,
SIGNAL(modified()));
connect(m_pExtEditorEdit, SIGNAL(textChanged(const QString&)), this,
SIGNAL(modified()));
connect(m_pSysProfileCB, SIGNAL(activated(int)), this,
SIGNAL(modified()));
connect(m_pEditorPopupCB, SIGNAL(activated(int)), this,
SIGNAL(modified()));
}
/**
* Class destructor.
*/
PrefOpt::~PrefOpt()
{
}
/**
* Reads the current settings from the configuration object, and applies them
* the the page's widget.
*/
void PrefOpt::load()
{
m_pReadOnlyCheck->setChecked(Config().getReadOnlyMode());
m_pLastProjCheck->setChecked(Config().getLoadLastProj());
m_pTagHlCheck->setChecked(Config().getAutoTagHl());
m_pBriefQueryCaptCheck->setChecked(Config().getUseBriefQueryCaptions());
m_pWarnModifiedOnDiskCheck->setChecked(Config().getWarnModifiedOnDisk());
m_pAutoSortCheck->setChecked(Config().getAutoSortFiles());
m_pExtEditorEdit->setText(Config().getExtEditor());
switch (Config().getSysProfile()) {
case KScopeConfig::Fast:
m_pSysProfileCB->setCurrentItem(0);
break;
case KScopeConfig::Slow:
m_pSysProfileCB->setCurrentItem(1);
break;
}
switch (Config().getEditorPopup()) {
case KScopeConfig::Embedded:
m_pEditorPopupCB->setCurrentItem(0);
break;
case KScopeConfig::KScopeOnly:
m_pEditorPopupCB->setCurrentItem(1);
break;
}
}
/**
* Commits settings changes to the configuration object.
*/
void PrefOpt::apply()
{
Config().setReadOnlyMode(m_pReadOnlyCheck->isChecked());
Config().setLoadLastProj(m_pLastProjCheck->isChecked());
Config().setAutoTagHl(m_pTagHlCheck->isChecked());
Config().setUseBriefQueryCaptions(m_pBriefQueryCaptCheck->isChecked());
Config().setWarnModifiedOnDisk(m_pWarnModifiedOnDiskCheck->isChecked());
Config().setAutoSortFiles(m_pAutoSortCheck->isChecked());
Config().setExtEditor(m_pExtEditorEdit->text());
switch (m_pSysProfileCB->currentItem()) {
case 0 :
Config().setSysProfile(KScopeConfig::Fast);
break;
case 1:
Config().setSysProfile(KScopeConfig::Slow);
break;
}
switch (m_pEditorPopupCB->currentItem()) {
case 0:
Config().setEditorPopup(KScopeConfig::Embedded);
break;
case 1:
Config().setEditorPopup(KScopeConfig::KScopeOnly);
break;
}
}
#include "prefopt.moc"

@ -0,0 +1,58 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PREFOPT_H
#define PREFOPT_H
#include "prefoptlayout.h"
/**
* A widget for setting different global options.
* @author Elad Lahav
*/
class PrefOpt : public PrefOptLayout
{
Q_OBJECT
public:
PrefOpt(QWidget* pParent = 0, const char* szName = 0);
~PrefOpt();
void load();
void apply();
signals:
/**
* Emitted whenever the user makes a change to the dialogue's input
* widgets.
*/
void modified();
};
#endif

@ -0,0 +1,217 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>PrefOptLayout</class>
<widget class="QWidget">
<property name="name">
<cstring>PrefOptLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>354</width>
<height>312</height>
</rect>
</property>
<property name="caption">
<string>Form4</string>
</property>
<property name="whatsThis" stdset="0">
<string>Determines whether KScope should automatically load the last project when started.</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout7</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>m_pExtEditorLabel</cstring>
</property>
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>External Editor</string>
</property>
</widget>
<widget class="QLineEdit">
<property name="name">
<cstring>m_pExtEditorEdit</cstring>
</property>
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</hbox>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pReadOnlyCheck</cstring>
</property>
<property name="text">
<string>Read-Onl&amp;y Mode</string>
</property>
<property name="accel">
<string>Alt+Y</string>
</property>
<property name="whatsThis" stdset="0">
<string>Forces all editor windows to work in a read-only mode, so that the user cannot modify the displayed files.</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pLastProjCheck</cstring>
</property>
<property name="text">
<string>Open Last Project on Start-Up</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pTagHlCheck</cstring>
</property>
<property name="text">
<string>Automatic Tag Highlighting</string>
</property>
<property name="whatsThis" stdset="0">
<string>Determines whether the tag list should highlight the relevant tag based on the cursor's position.</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pBriefQueryCaptCheck</cstring>
</property>
<property name="text">
<string>Brief Tab Captions for &amp;Query Pages</string>
</property>
<property name="whatsThis" stdset="0">
<string>If set, the tab captions for query pages will be shortened, by using aliases for the query types.</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pWarnModifiedOnDiskCheck</cstring>
</property>
<property name="text">
<string>Warn When a File is Modified Outside KScope</string>
</property>
<property name="whatsThis" stdset="0">
<string>If set, the user is prompted whenever the currently edited file is changed by an external programme.</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pAutoSortCheck</cstring>
</property>
<property name="text">
<string>Automatically Sort Files in the File List</string>
</property>
<property name="accel">
<string></string>
</property>
<property name="whatsThis" stdset="0">
<string>Sorts files in the project's file list when a project is loaded. This may be too slow for large projects on older machines.</string>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout2</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="text">
<string>System Profile</string>
</property>
</widget>
<widget class="QComboBox">
<item>
<property name="text">
<string>Fast</string>
</property>
</item>
<item>
<property name="text">
<string>Slow</string>
</property>
</item>
<property name="name">
<cstring>m_pSysProfileCB</cstring>
</property>
</widget>
</hbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout3</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel2</cstring>
</property>
<property name="text">
<string>Editor Popup Menu</string>
</property>
</widget>
<widget class="QComboBox">
<item>
<property name="text">
<string>Embedded</string>
</property>
</item>
<item>
<property name="text">
<string>KScope Only</string>
</property>
</item>
<property name="name">
<cstring>m_pEditorPopupCB</cstring>
</property>
</widget>
</hbox>
</widget>
<spacer>
<property name="name">
<cstring>spacer11</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>21</width>
<height>20</height>
</size>
</property>
</spacer>
</vbox>
</widget>
<layoutdefaults spacing="6" margin="11"/>
</UI>

@ -0,0 +1,116 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include "progressdlg.h"
/**
* Class constructor.
* @param sCaption The dialogue's title
* @param sText The text to display
* @param pParent The parent widget
* @param szName The widget's name
*/
ProgressDlg::ProgressDlg(const QString& sCaption, const QString& sText,
QWidget* pParent, const char* szName) :
KProgressDialog(pParent, szName, sCaption, sText, true),
m_nIdleValue(-1)
{
setAutoClose(false);
setAllowCancel(false);
// Create the idle-progress timer
m_pIdleTimer = new QTimer(this);
// Display a busy indicator by increasing the value of the idle counter
connect (m_pIdleTimer, SIGNAL(timeout()), this, SLOT(slotShowBusy()));
}
/**
* Class destructor.
*/
ProgressDlg::~ProgressDlg()
{
}
/**
* Sets a new value to the progress bar.
* If the new value is non-zero, the progress bar is advanced. Otherwise, the
* idle timer is initiated to display a busy indicator.
* @param nValue The new value to set.
*/
void ProgressDlg::setValue(int nValue)
{
KProgress* pProgress;
pProgress = progressBar();
if (nValue != 0) {
// Do nothing if the value hasn't changed
if (nValue == pProgress->progress())
return;
// Handle first non-zero value
if (m_nIdleValue >= 0) {
m_pIdleTimer->stop();
m_nIdleValue = -1;
pProgress->setPercentageVisible(true);
}
// Set the new value
pProgress->setValue(nValue);
}
else if (m_nIdleValue == -1) {
// Handle first 0 value
pProgress->setValue(0);
pProgress->setPercentageVisible(false);
m_nIdleValue = 0;
m_pIdleTimer->start(200);
}
}
void ProgressDlg::setIdle()
{
m_nIdleValue = -1;
setValue(0);
}
/**
* Increaes the value of the dummy counter by 1.
* This slot is called by the timeout() event of the idle timer.
*/
void ProgressDlg::slotShowBusy()
{
// Increase the counter
m_nIdleValue += 5;
if (m_nIdleValue == 100)
m_nIdleValue = 0;
// Set the value of the progress-bar
progressBar()->setValue(m_nIdleValue);
}
#include "progressdlg.moc"

@ -0,0 +1,66 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PROGRESSDLG_H
#define PROGRESSDLG_H
#include <qwidget.h>
#include <qtimer.h>
#include <kprogress.h>
/**
* An improved progress dialog.
* This variation of the standard KDE progress dialog displays a busy
* indicator while waiting for the first value greater than 0.
* @author Elad Lahav
*/
class ProgressDlg : public KProgressDialog
{
Q_OBJECT
public:
ProgressDlg(const QString&, const QString&, QWidget* pParent = 0, const
char* szName = 0);
~ProgressDlg();
void setValue(int);
void setIdle();
private:
/** When the value is 0, this timer initiates value changes that cause
the progress-bar to move. */
QTimer* m_pIdleTimer;
/** A dummy value used to move the progress-bar while the value is 0. */
int m_nIdleValue;
private slots:
void slotShowBusy();
};
#endif

@ -0,0 +1,442 @@
/***************************************************************************
*
* Copyright (C) 2007 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <kmessagebox.h>
#include <klocale.h>
#include "project.h"
#include "kscopeconfig.h"
#include "cscopefrontend.h"
#define PROJECT_CONFIG_VER 2
inline void flListFromStringList(FileLocationList& fll, const QStringList& sl)
{
QStringList::ConstIterator itr;
QString sPath;
uint nLine, nCol;
// Transform the string into a list of file locations
for (itr = sl.begin(); itr != sl.end(); ++itr) {
sPath = (*itr).section(':', 0, 0);
nLine = (*itr).section(':', 1, 1).toUInt();
nCol = (*itr).section(':', 2, 2).toUInt();
fll.append(new FileLocation(sPath, nLine, nCol));
}
}
inline void stringListFromFlList(QStringList& sl, const FileLocationList& fll)
{
FileLocationList* pList;
FileLocation* pLoc;
QString sLoc;
// Nasty...
pList = (FileLocationList*)&fll;
sl.clear();
// Turn the object list into a string list, so that it can be written in
// the configuration file
for (pLoc = pList->first(); pLoc != NULL; pLoc = pList->next()) {
sLoc = "";
QTextOStream(&sLoc) << pLoc->m_sPath << ":" << pLoc->m_nLine << ":"
<< pLoc->m_nCol;
sl.append(sLoc);
}
}
/**
*/
Project::Project() : ProjectBase(),
m_pConf(NULL)
{
}
/**
*/
Project::~Project()
{
close();
}
/**
*/
bool Project::open(const QString& sPath)
{
QString sConfFile;
Options opt;
// Associate the object with the project directory
m_dir.setPath(sPath);
if (!m_dir.exists()) {
KMessageBox::error(0, i18n("Project directory does not exist"));
return false;
}
// Initialise the file-list file object
m_fiFileList.setName(sPath + "/cscope.files");
// Open the configuration files
m_pConf = new KConfig(sPath + "/cscope.proj");
// Verify the configuration file's version is compatible
m_pConf->setGroup("");
if (m_pConf->readUnsignedNumEntry("Version", 0) != PROJECT_CONFIG_VER) {
KMessageBox::error(0, i18n("Your project is not compatible with this "
"version of KScope.\nPlease re-create the project."));
return false;
}
// Get the project name
m_pConf->setGroup("Project");
m_sName = m_pConf->readEntry("Name");
if (m_sName == QString::null) {
KMessageBox::error(0, i18n("Cannot read project name"));
return false;
}
// Get stored options
initOptions();
// Set default make values for new projects (overriden in loadSession(),
// which is not called for new projects)
m_sMakeRoot = getSourceRoot();
m_sMakeCmd = "make";
return true;
}
/**
*/
void Project::close()
{
if (m_pConf)
delete m_pConf;
m_fiFileList.close();
}
/**
* Returns a semi-colon separated list of the file types included in the
* current project.
*/
QString Project::getFileTypes() const
{
QString sTypes;
m_pConf->setGroup("Project");
return m_pConf->readEntry("FileTypes");
}
/**
* Reads the project's options from the configuration file.
* @param opt A structure to fill with the read options
*/
void Project::getOptions(Options& opt) const
{
// Get project properties
m_pConf->setGroup("Project");
opt.sSrcRootPath = m_pConf->readEntry("RootPath", "/");
opt.slFileTypes = m_pConf->readListEntry("FileTypes", ' ');
opt.bKernel = m_pConf->readBoolEntry("Kernel", DEF_IS_KERNEL);
opt.bInvIndex = m_pConf->readBoolEntry("InvIndex", DEF_INV_INDEX);
opt.bNoCompress = m_pConf->readBoolEntry("NoCompress", DEF_NO_COMPRESS);
opt.bSlowPathDef = m_pConf->readBoolEntry("SlowPathDef", DEF_SLOW_PATH);
opt.nAutoRebuildTime = m_pConf->readNumEntry("AutoRebuildTime");
opt.nTabWidth = m_pConf->readUnsignedNumEntry("TabWidth");
opt.sCtagsCmd = m_pConf->readEntry("CtagsCommand", DEF_CTAGS_COMMAND);
// Get auto-completion options
m_pConf->setGroup("AutoCompletion");
opt.bACEnabled = m_pConf->readBoolEntry("Enabled");
opt.nACMinChars = m_pConf->readUnsignedNumEntry("MinChars",
DEF_AC_MIN_CHARS);
opt.nACDelay = m_pConf->readUnsignedNumEntry("Delay", DEF_AC_DELAY);
opt.nACMaxEntries = m_pConf->readUnsignedNumEntry("MaxEntries",
DEF_AC_MAX_ENTRIES);
}
/**
* Sets project options.
* @param opt A structure containing the new parameters to set
*/
void Project::setOptions(const Options& opt)
{
// Write the options to the configuration nfile
writeOptions(m_pConf, opt);
// Update project parameters
initOptions();
}
/**
*/
void Project::loadSession(Session& sess)
{
QStringList slEntry;
m_pConf->setGroup("Session");
// Read the list of open file locations
slEntry = m_pConf->readListEntry("OpenFiles");
flListFromStringList(sess.fllOpenFiles, slEntry);
// Get the path of the last viewed file
sess.sLastFile = m_pConf->readEntry("LastOpenFile");
// Read the lists of locked query files and call-tree/graph files
sess.slQueryFiles = m_pConf->readListEntry("QueryFiles");
sess.slCallTreeFiles = m_pConf->readListEntry("CallTreeFiles");
// Read the list of bookmarks
slEntry = m_pConf->readListEntry("Bookmarks");
flListFromStringList(sess.fllBookmarks, slEntry);
// Read make-related information
sess.sMakeCmd = m_pConf->readEntry("MakeCommand", "make");
sess.sMakeRoot = m_pConf->readEntry("MakeRoot", getSourceRoot());
// Cache make values
m_sMakeCmd = sess.sMakeCmd;
m_sMakeRoot = sess.sMakeRoot;
}
/**
* Saves session-related information in the project's configuration file.
* @param sess Session parameters
*/
void Project::storeSession(const Session& sess)
{
QStringList slEntry;
m_pConf->setGroup("Session");
// Write the list of open file locations
stringListFromFlList(slEntry, sess.fllOpenFiles);
m_pConf->writeEntry("OpenFiles", slEntry);
// Write the path of the last viewed file
m_pConf->writeEntry("LastOpenFile", sess.sLastFile);
// Write the lists of locked query files and call-tree/graph files
m_pConf->writeEntry("QueryFiles", sess.slQueryFiles);
m_pConf->writeEntry("CallTreeFiles", sess.slCallTreeFiles);
// Write the list of bookmarks
stringListFromFlList(slEntry, sess.fllBookmarks);
m_pConf->writeEntry("Bookmarks", slEntry);
// Write make-related information
// Be careful not to write empty strings, as they may occur if the make
// dialogue was not invoked during this session
if (!sess.sMakeCmd.isEmpty())
m_pConf->writeEntry("MakeCommand", sess.sMakeCmd);
if (!sess.sMakeRoot.isEmpty())
m_pConf->writeEntry("MakeRoot", sess.sMakeRoot);
}
/**
* Fills a list object with all files in the project.
* List items are created by reading and parsing all file name entries from
* the project's 'cscope.files' file.
* Note that the file may contain option lines, beginning with a dash. These
* should be ignored.
* @param pList Pointer to the object to fill
*/
bool Project::loadFileList(FileListTarget* pList)
{
QString sFilePath;
// Open the 'cscope.files' file
if (!m_fiFileList.open(IO_ReadOnly))
return false;
// Read all file names from the file
QTextStream str(&m_fiFileList);
while ((sFilePath = str.readLine()) != QString::null) {
// Skip option lines
if (sFilePath.at(0) == '-')
continue;
// Set the new list item
pList->addItem(sFilePath);
}
m_fiFileList.close();
return true;
}
/**
* Writes all file entries in a list view widget to the project's
* 'cscope.files' file (replacing current file contents.)
* @param pList Pointer to the object from which to take the new entries
*/
bool Project::storeFileList(FileListSource* pList)
{
QString sFilePath;
// Open the 'cscope.files' file
if (!m_fiFileList.open(IO_WriteOnly | IO_Truncate))
return false;
QTextStream str(&m_fiFileList);
// Write all file names
if (pList->firstItem(sFilePath)) {
do {
str << sFilePath << "\n";
} while (pList->nextItem(sFilePath));
}
m_fiFileList.close();
return true;
}
/**
* Adds a single file to the file list.
* @param sPath The path of the file to add
* @return true if successful, false otherwise
*/
bool Project::addFile(const QString& sPath)
{
// Open the 'cscope.files' file
if (!m_fiFileList.open(IO_WriteOnly | IO_Append))
return false;
// Write the file path
QTextStream str(&m_fiFileList);
str << sPath << "\n";
m_fiFileList.close();
return true;
}
/**
* Determines whether the project includes any files.
* Reads the 'cscope.files' file and looks for any file names in it. If none
* is present, then the project is considered empty.
* Note that the file may contain option lines, beginning with a dash. These
* should be ignored.
* @return true if no files are included in the project, false otherwise
*/
bool Project::isEmpty()
{
QString sPath, sFileName;
bool bResult = true;
// Open the 'cscope.files' file
if (!m_fiFileList.open(IO_ReadOnly))
return true;
// Find at least one file name entry in the file
QTextStream str(&m_fiFileList);
while ((sPath = str.readLine()) != QString::null) {
if (sPath.at(0) != '-') {
bResult = false;
break;
}
}
m_fiFileList.close();
return bResult;
}
/**
* Copies the list of previously queried symbols to the target object.
* @param slSymHistory The list object to copy into
*/
void Project::getSymHistory(QStringList& slSymHistory) const
{
slSymHistory = m_slSymHistory;
}
/**
* Copies the list of previously queried symbols from the target object.
* @param slSymHistory The list object to copy from
*/
void Project::setSymHistory(QStringList& slSymHistory)
{
m_slSymHistory = slSymHistory;
}
void Project::getMakeParams(QString& sCmd, QString& sDir) const
{
sCmd = m_sMakeCmd;
sDir = m_sMakeRoot;
}
/**
* Creates a project by writing a configuration file inside the given
* directory.
* @param sName The project's name
* @param sPath The full path of the project's directory
* @param opt Project options
*/
bool Project::create(const QString& sName, const QString& sPath,
const Options& opt)
{
// Prepare the project's files
KConfig conf(sPath + "/cscope.proj");
// Write the configuration file version
conf.setGroup("");
conf.writeEntry("Version", PROJECT_CONFIG_VER);
// Write project properties in the configuration file
conf.setGroup("Project");
conf.writeEntry("Name", sName);
writeOptions(&conf, opt);
// Flush the config file data, so the project is created even if KScope
// crashes...
conf.sync();
return true;
}
void Project::writeOptions(KConfig* pConf, const Options& opt)
{
pConf->setGroup("Project");
pConf->writeEntry("RootPath", opt.sSrcRootPath);
pConf->writeEntry("FileTypes", opt.slFileTypes.join(" "));
pConf->writeEntry("Kernel", opt.bKernel);
pConf->writeEntry("InvIndex", opt.bInvIndex);
pConf->writeEntry("NoCompress", opt.bNoCompress);
pConf->writeEntry("SlowPathDef", opt.bSlowPathDef);
pConf->writeEntry("AutoRebuildTime", opt.nAutoRebuildTime);
pConf->writeEntry("TabWidth", opt.nTabWidth);
pConf->writeEntry("CtagsCommand", opt.sCtagsCmd);
// Set auto-completion options
pConf->setGroup("AutoCompletion");
pConf->writeEntry("Enabled", opt.bACEnabled);
pConf->writeEntry("MinChars", opt.nACMinChars);
pConf->writeEntry("Delay", opt.nACDelay);
pConf->writeEntry("MaxEntries", opt.nACMaxEntries);
}

@ -0,0 +1,92 @@
/***************************************************************************
*
* Copyright (C) 2007 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PROJECT_H
#define PROJECT_H
#include <projectbase.h>
/**
* @author Elad Lahav
*/
class Project : public ProjectBase
{
public:
Project();
virtual ~Project();
struct Session {
FileLocationList fllOpenFiles;
QString sLastFile;
QStringList slQueryFiles;
QStringList slCallTreeFiles;
FileLocationList fllBookmarks;
QString sMakeCmd;
QString sMakeRoot;
};
virtual bool open(const QString&);
virtual bool loadFileList(FileListTarget*);
virtual bool storeFileList(FileListSource*);
virtual bool addFile(const QString&);
virtual bool isEmpty();
virtual void close();
virtual QString getFileTypes() const;
virtual void getOptions(Options&) const;
virtual void setOptions(const Options&);
virtual void loadSession(Session&);
virtual void storeSession(const Session&);
virtual void getSymHistory(QStringList&) const;
virtual void setSymHistory(QStringList&);
virtual void getMakeParams(QString&, QString&) const;
/**
* Determines whether a project is based on a Cscope.out file, and is
* therefore considered as a temporary project.
* @return true if this is a temporary project, false otherwise
*/
virtual bool isTemporary() { return false; }
static bool create(const QString&, const QString&, const Options&);
private:
/** The configuration file ("cscope.proj") */
KConfig* m_pConf;
/** The file that holds the paths of all source files in this project
("cscope.files") */
QFile m_fiFileList;
QString m_sMakeCmd;
QString m_sMakeRoot;
static void writeOptions(KConfig*, const Options&);
};
#endif

@ -0,0 +1,190 @@
/***************************************************************************
*
* Copyright (C) 2007 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include "projectbase.h"
#include "kscopeconfig.h"
#include "cscopefrontend.h"
ProjectBase::ProjectBase()
{
}
ProjectBase::~ProjectBase()
{
}
bool ProjectBase::open(const QString& sPath)
{
QFileInfo fi(sPath);
// Make sure the file exists, and that is is a cross-reference file
if (!fi.exists() || !isCscopeOut(fi.absFilePath()))
return false;
// Set the project's directory
m_dir = fi.dirPath(true);
// Set the name of the project to be the full path of the file
m_sName = fi.absFilePath();
// Initialise project options (assume source root is the folder holding the
// cscope.out file)
getDefOptions(m_opt);
m_opt.sSrcRootPath = m_dir.absPath();
return true;
}
/**
* Determines if the cscope.out file for this project exists.
* @return true if the database exists, false otherwise
*/
bool ProjectBase::dbExists()
{
return m_dir.exists("cscope.out");
}
void ProjectBase::getOptions(Options& opt) const
{
getDefOptions(opt);
}
void ProjectBase::getMakeParams(QString& sCmd, QString& sDir) const
{
sCmd = "make";
sDir = getSourceRoot();
}
/**
* Fills a structure with default properties for a new project.
* Default properties are partly based on the system profile.
* @param opt The structure to fill
*/
void ProjectBase::getDefOptions(Options& opt)
{
// Set default source path to file-system root
opt.sSrcRootPath = "/";
// Initialise MIME-type list
opt.slFileTypes.append("*.c");
opt.slFileTypes.append("*.h");
// Set other options
opt.bKernel = DEF_IS_KERNEL;
opt.bInvIndex = DEF_INV_INDEX;
opt.bNoCompress = DEF_NO_COMPRESS;
opt.bSlowPathDef = DEF_SLOW_PATH;
opt.nACMinChars = DEF_AC_MIN_CHARS;
opt.nACDelay = DEF_AC_DELAY;
opt.nACMaxEntries = DEF_AC_MAX_ENTRIES;
opt.nTabWidth = DEF_TAB_WIDTH;
// Set profile-dependant options
if (Config().getSysProfile() == KScopeConfig::Fast) {
opt.nAutoRebuildTime = 10;
opt.bACEnabled = true;
}
else {
opt.nAutoRebuildTime = -1;
opt.bACEnabled = false;
}
}
void ProjectBase::initOptions()
{
// Load the options
getOptions(m_opt);
// Create the argument list for invoking Cscope
m_nArgs = 0;
if (m_opt.bKernel)
m_nArgs |= CscopeFrontend::Kernel;
if (m_opt.bInvIndex)
m_nArgs |= CscopeFrontend::InvIndex;
if (m_opt.bNoCompress)
m_nArgs |= CscopeFrontend::NoCompression;
if (m_opt.bSlowPathDef)
m_nArgs |= CscopeFrontend::SlowPathDef;
}
/**
* Determines if the given file is a Cscope cross-reference database.
* @param sPath The full path of the file to check
* @return true if the given file is a cscope.out file, false otherwise
*/
bool ProjectBase::isCscopeOut(const QString& sPath)
{
QFile file(sPath);
QString sLine;
int nVer;
char szDir[PATH_MAX];
// Try to open the file
if (!file.open(IO_ReadOnly))
return false;
// Check if the first line matches the expected format
sLine = QTextStream(&file).readLine();
return sscanf(sLine.latin1(), "cscope %d %s", &nVer, szDir) == 2;
}
/**
* Fills a list object with all files in the project.
* List items are created by reading and parsing all file name entries from
* the project's 'cscope.files' file.
* Note that the file may contain option lines, beginning with a dash. These
* should be ignored.
* @param pList Pointer to the object to fill
*/
bool ProjectBase::loadFileList(FileListTarget* pList)
{
QString sFilePath;
QFile file;
// Make sure the file exists
if (!m_dir.exists("cscope.files"))
return false;
// Open the file
file.setName(m_dir.absPath() + "/cscope.files");
if (!file.open(IO_ReadOnly))
return false;
// Read all file names from the file
QTextStream str(&file);
while ((sFilePath = str.readLine()) != QString::null) {
// Skip option lines
if (sFilePath.at(0) == '-')
continue;
// Set the new list item
pList->addItem(sFilePath);
}
file.close();
return true;
}

@ -0,0 +1,281 @@
/***************************************************************************
*
* Copyright (C) 2007 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PROJECTBASE_H
#define PROJECTBASE_H
#include <qstringlist.h>
#include <qdir.h>
#include <qfile.h>
#include <kconfig.h>
#define DEF_IS_KERNEL false
#define DEF_INV_INDEX true
#define DEF_NO_COMPRESS false
#define DEF_SLOW_PATH false
#define DEF_AC_MIN_CHARS 3
#define DEF_AC_DELAY 500
#define DEF_AC_MAX_ENTRIES 100
#define DEF_TAB_WIDTH 0 /* Use editor's default */
#define DEF_CTAGS_COMMAND \
"--regex-c=\"/^[ \\t]*([_a-zA-Z][_a-zA-Z0-9]*):/\\1/l,label/\" " \
"--regex-c=\"/^[ \\t]*#[ \\t]*include[ \\t]*[\\\"<]" \
"([_a-zA-Z0-9\\.\\/]*)[\\\">]/\\1/i,include/\" " \
"--regex-c++=\"/^[ \\t]*#[ \\t]*include[ \\t]*[\\\"<]" \
"([_a-zA-Z0-9\\.\\/]*)[\\\">]/\\1/i,include/\""
/**
* Abstract base class for classes that need the list of project files.
* Objects of classes derived from this one are used as a parameter to
* ProjectManager::fillList(), which reads all file entries in the project,
* and calls addItem() for each.
* Any class that wishes to retrieve the project's file list, should inherit
* from this class, and implement addItem().
* @author Elad Lahav
*/
class FileListTarget
{
public:
/**
* Class constructor.
*/
FileListTarget() {}
/**
* Class destructor.
*/
virtual ~FileListTarget() {}
/**
* Appends a file to the list.
* @param sFilePath The full path of the file to add
*/
virtual void addItem(const QString& sFilePath) = 0;
};
/**
* Abstract base class for classes that need the list of project files.
* Objects of classes derived from this one are used as a parameter to
* ProjectManager::writeList(), which calls getFirstItem() and getNextItem(),
* and writes the returned values to the project's 'cscope.files' file.
* Any class that wishes to retrieve the project's file list, should inherit
* from this class, and implement firstItem() and nextItem().
* @author Elad Lahav
*/
class FileListSource
{
public:
/**
* Class constructor.
*/
FileListSource() {}
/**
* Class destructor.
*/
virtual ~FileListSource() {}
/**
* Returns the first file in the list, and initiates a new iteration.
* @param sFilePath Holds the path of the first file, upon return
* @return true if there are more files, false otherwise
*/
virtual bool firstItem(QString& sFilePath) = 0;
/**
* Returns the next file in the list.
* @param sFilePath Holds the path of the file, upon return
* @return true if there are more files, false otherwise
*/
virtual bool nextItem(QString& sFilePath) = 0;
};
/**
* Defines a cursor location inside a file.
* This structure is used to store project session information.
* @author Elad Lahav
*/
struct FileLocation
{
/**
* Struct constructor.
* @param sPath The full path of the file
* @param nLine The line position of the cursor
* @param nCol The column position of the cursor
*/
FileLocation(QString sPath, uint nLine, uint nCol) : m_sPath(sPath),
m_nLine(nLine), m_nCol(nCol) {}
/** The full path of the file. */
QString m_sPath;
/** The line position of the cursor. */
uint m_nLine;
/** The column position of the cursor. */
uint m_nCol;
};
/**
* A list of file locations used for restoring a session.
*/
typedef QPtrList<FileLocation> FileLocationList;
class FileSemaphore;
/**
* @author Elad Lahav
*/
class ProjectBase
{
public:
ProjectBase();
virtual ~ProjectBase();
/**
* Configurable project options.
*/
struct Options {
QString sSrcRootPath;
/** A list of MIME-types that determines which files are included in
the project. */
QStringList slFileTypes;
/** true if the -k option for CScope should be used. */
bool bKernel;
/** true if Cscope should build an inverted index. */
bool bInvIndex;
/** true if the -c option for CScope should be used. */
bool bNoCompress;
/** true if the -D option for CScope should be used. */
bool bSlowPathDef;
/** The time, in milliseconds, after which the database should be
automatically rebuilt (-1 if this option is disabled). */
int nAutoRebuildTime;
/** true to use auto-completion. */
bool bACEnabled;
/** Minimum number of characters in a symbol for auto-completion. */
uint nACMinChars;
/** Time interval, in milliseconds, before auto-completion is
started. */
uint nACDelay;
/** Maximal number of entries for auto-completion. */
uint nACMaxEntries;
/** Per-project tab width (overrides editor settings). */
uint nTabWidth;
/** Ctags command line. */
QString sCtagsCmd;
};
virtual bool open(const QString&);
virtual bool loadFileList(FileListTarget*);
virtual bool storeFileList(FileListSource*) { return false; }
virtual bool isEmpty() { return false; }
bool dbExists();
virtual void close() {}
virtual QString getFileTypes() const { return QString::null; }
virtual void getOptions(Options&) const;
virtual void setOptions(const Options&) {}
virtual void getSymHistory(QStringList&) const {}
virtual void setSymHistory(QStringList&) {}
virtual void getMakeParams(QString&, QString&) const;
/**
* Determines whether a project is based on a Cscope.out file, and is
* therefore considered as a temporary project.
* @return true if this is a temporary project, false otherwise
*/
virtual bool isTemporary() { return true; }
/**
* @return The name of the current project
*/
QString getName() const { return m_sName; }
/**
* @return The full path of the project's directory
*/
QString getPath() const { return m_dir.absPath(); }
/**
* @return Command-line arguments to pass to a Cscope object, based on
* project's options
*/
uint getArgs() const { return m_nArgs; }
const QString& getSourceRoot() const { return m_opt.sSrcRootPath; }
/**
* @return The time, in seconds, to wait before rebuilding the
* cross-refernce database.
*/
int getAutoRebuildTime() const { return m_opt.nAutoRebuildTime; }
/**
* @return The tab width to use (0 to use the editor's default)
*/
uint getTabWidth() const { return m_opt.nTabWidth; }
static void getDefOptions(Options&);
protected:
/** The name of the project, as written in the configuration file */
QString m_sName;
/** The directory associated with the project */
QDir m_dir;
/** A cached version of the project's options. */
Options m_opt;
/** A list of Cscope command-line arguments based on the project's
options. */
uint m_nArgs;
/** A list of symbols previously queried. */
QStringList m_slSymHistory;
void initOptions();
static bool isCscopeOut(const QString&);
};
#endif

@ -0,0 +1,439 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qpushbutton.h>
#include <qlistview.h>
#include <qlineedit.h>
#include <qregexp.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kfiledialog.h>
#include "projectfilesdlg.h"
#include "dirscanner.h"
#include "scanprogressdlg.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pProjMgr Pointer the KScope's project manager object
* @param pParent The parent widget
* @param szName The widget's name
*/
ProjectFilesDlg::ProjectFilesDlg(Project* pProj, QWidget* pParent,
const char* szName) :
ProjectFilesLayout(pParent, szName),
m_pProj(pProj),
m_pScanDlg(NULL),
m_pItrItem(NULL),
m_pLastItem(NULL)
{
// Create the scanner object
m_pScanner = new DirScanner(this, &m_dicFiles);
// Initialise the list view
m_pFileList->setSelectionMode(QListView::Extended);
m_pFileList->addColumn("File Path");
// Sort only when asked to by the user
if (Config().getAutoSortFiles())
m_pFileList->setSortColumn(0);
else
m_pFileList->setSortColumn(m_pFileList->columns() + 1);
// Add file/directory/tree when the appropriate button is clicked
connect(m_pAddFilesButton, SIGNAL(clicked()), this,
SLOT(slotAddFiles()));
connect(m_pAddDirButton, SIGNAL(clicked()), this, SLOT(slotAddDir()));
connect(m_pAddTreeButton, SIGNAL(clicked()), this, SLOT(slotAddTree()));
// Remove selected files/directory/tree when the appropriate button is
// clicked
connect(m_pRemSelButton, SIGNAL(clicked()), this, SLOT(slotRemSel()));
connect(m_pRemDirButton, SIGNAL(clicked()), this, SLOT(slotRemDir()));
connect(m_pRemTreeButton, SIGNAL(clicked()), this, SLOT(slotRemTree()));
// Hide/show files according to filter
connect(m_pFilterButton, SIGNAL(clicked()), this, SLOT(slotFilter()));
connect(m_pShowAllButton, SIGNAL(clicked()), this, SLOT(slotShowAll()));
// Close the dialog when OK/Cancel are clicked
connect(m_pOKButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(reject()));
// Fill the list with the project's files
m_pFileList->setUpdatesEnabled(false);
m_pProj->loadFileList(this);
m_pFileList->setUpdatesEnabled(true);
m_pFileList->triggerUpdate();
}
/**
* Class destructor.
*/
ProjectFilesDlg::~ProjectFilesDlg()
{
delete m_pScanner;
}
/**
* Adds a single entry to the file list.
* Implements the addItem() virtual method of the FileListTarget base
* class. When a ProjectFilesDlg object is given as a parameter to
* ProjectManager::fillList(), this method is called for each file included
* in the project. A new list item is created, containing the file's path,
* and is added to the list.
* @param sFilePath The full path of a source file
*/
void ProjectFilesDlg::addItem(const QString& sFilePath)
{
QListViewItem* pItem;
pItem = new QListViewItem(m_pFileList, m_pLastItem);
pItem->setText(0, sFilePath);
m_pLastItem = pItem;
m_dicFiles.insert(sFilePath, pItem);
}
/**
* Retrieves the first file path in the list.
* Imlpements the firstItem() virtual method of the FileListSource base
* class.
* @param sFilePath Contains the file path, upon successful return
* @return bool true if successful, false if the list is empty
*/
bool ProjectFilesDlg::firstItem(QString& sFilePath)
{
m_pItrItem = m_pFileList->firstChild();
return nextItem(sFilePath);
}
/**
* Retrieves the next file path in the list.
* Imlpements the nextItem() virtual method of the FileListSource base
* class. The function requires that firstItem() will be called to begin an
* iteration through the file paths.
* @param sFilePath Contains the file path, upon successful return
* @return bool true if successful, false if no more items are
* available
*/
bool ProjectFilesDlg::nextItem(QString& sFilePath)
{
if (m_pItrItem == NULL)
return false;
sFilePath = m_pItrItem->text(0);
m_pItrItem = m_pItrItem->nextSibling();
return true;
}
/**
* Notifies the user on the progress of a directory scan (when adding a new
* directory), and, if finished, allows the user to add these files to the
* project.
* @param pEvent The event object
*/
void ProjectFilesDlg::customEvent(QCustomEvent* pEvent)
{
DirScanEvent* pDSE;
QString sMsg;
// Process only directory scan progress events
if (((uint)pEvent->type()) != DirScanEvent::EventId)
return;
pDSE = (DirScanEvent*)pEvent;
// Check if the scan has terminated
if (!pDSE->m_bFinished) {
// Create the scan progress dialog, if required
if (m_pScanDlg == NULL) {
m_pScanDlg = new ScanProgressDlg(this);
connect(m_pScanDlg, SIGNAL(cancelled()), this,
SLOT(slotCancelDirScan()));
}
// Set progress indication
m_pScanDlg->addFiles(pDSE->m_nFiles);
return;
}
// Destroy the scan progress dialog
delete m_pScanDlg;
m_pScanDlg = NULL;
// Verify the thread has terminated
m_pScanner->wait(500);
if (!m_pScanner->finished())
m_pScanner->terminate();
// Do nothing if the operation was cancelled
if (m_pScanner->wasCancelled())
return;
// Abort if no files were found
if (pDSE->m_nFiles == 0) {
KMessageBox::sorry(0, "No files were found");
return;
}
// Prompt the user for the files to add
sMsg.sprintf(i18n("Would you like to add %d files to your project?"),
pDSE->m_nFiles);
if (KMessageBox::questionYesNo(0, sMsg) == KMessageBox::No)
return;
// Add the files to the list
const QStringList& slFiles = m_pScanner->getFiles();
QStringList::const_iterator itr;
for (itr = slFiles.begin(); itr != slFiles.end(); ++itr)
addItem(*itr);
}
/**
* Removes a single item from the file list.
*/
void ProjectFilesDlg::removeItem(QListViewItem* pItem)
{
m_dicFiles.remove(pItem->text(0));
delete pItem;
}
/**
* Adds a list of files to the project.
* Prompts the user for source files, and adds the selected files to the
* current project.
*/
void ProjectFilesDlg::slotAddFiles()
{
QStringList slFiles;
QStringList::const_iterator itr;
// Prompt the user
slFiles = KFileDialog::getOpenFileNames(m_pProj->getSourceRoot(),
m_pProj->getFileTypes());
// Add the selected files, skipping existing entries
for (itr = slFiles.begin(); itr != slFiles.end(); ++itr) {
if (m_dicFiles.find(*itr) == NULL)
addItem(*itr);
}
}
/**
* Adds all source files in a given directory to the project.
* Prompts the user for a directory, and adds all files matching the
* project's pattern to the current project.
* Note that only source files in the selected directory are added, i.e., the
* search does not descend to sub-directories.
*/
void ProjectFilesDlg::slotAddDir()
{
QString sDir;
QStringList slFiles;
QStringList::const_iterator itr;
// Prompt the user for a directory
sDir = KFileDialog::getExistingDirectory(m_pProj->getSourceRoot());
if (sDir.isEmpty())
return;
// Search for source files in this directory
m_pScanner->start(sDir, m_pProj->getFileTypes(), false);
}
/**
* Adds all source files in a given file system tree to the project.
* Prompts the user for a directory, and adds all files matching the
* project's pattern to the current project.
* Note that source files are searched for in the given directory, as well as
* in any of its sub-directories.
*/
void ProjectFilesDlg::slotAddTree()
{
QString sDir;
QStringList slFiles;
QStringList::const_iterator itr;
// Prompt the user for a directory
sDir = KFileDialog::getExistingDirectory(m_pProj->getSourceRoot());
if (sDir.isEmpty())
return;
// Search for source files in this directory
m_pScanner->start(sDir, m_pProj->getFileTypes(), true);
}
/**
* Removes the selected files from the project.
*/
void ProjectFilesDlg::slotRemSel()
{
QListViewItem* pItem, * pPrevItem;
// Prompt the user before removing the files
if (KMessageBox::questionYesNo(0, i18n("Are you sure you want to remove "
"the selected files from the project?")) == KMessageBox::No) {
return;
}
// Remove the selected files
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
pPrevItem = pItem;
pItem = pItem->nextSibling();
if (pPrevItem->isSelected())
removeItem(pPrevItem);
}
}
/**
* Removes all source files in a directory from the project.
*/
void ProjectFilesDlg::slotRemDir()
{
QString sDir, sFilePath;
QListViewItem* pItem, * pPrevItem;
// Prompt the user for a directory
sDir = KFileDialog::getExistingDirectory(m_pProj->getSourceRoot());
if (sDir.isEmpty())
return;
// Confirm the directory removal
if (KMessageBox::questionYesNo(0, i18n("Are you sure you want to remove "
"the selected directory from the project?")) == KMessageBox::No) {
return;
}
// Remove the files under the selected directory
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
pPrevItem = pItem;
pItem = pItem->nextSibling();
// Check if the file is under the selected directory
sFilePath = pPrevItem->text(0);
if (sFilePath.left(sFilePath.findRev('/') + 1) == sDir)
removeItem(pPrevItem);
}
}
/**
* Removes all source files in a directory or any of its sub-directories from
* the project.
*/
void ProjectFilesDlg::slotRemTree()
{
QString sDir, sFilePath;
QListViewItem* pItem, * pPrevItem;
// Prompt the user for a directory
sDir = KFileDialog::getExistingDirectory(m_pProj->getSourceRoot());
if (sDir.isEmpty())
return;
// Confirm the directory removal
if (KMessageBox::questionYesNo(0, i18n("Are you sure you want to remove "
"all files in the selected tree from the project?")) ==
KMessageBox::No) {
return;
}
// Remove the files under the selected directory
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
pPrevItem = pItem;
pItem = pItem->nextSibling();
// Check if the file is under the selected directory
sFilePath = pPrevItem->text(0);
if (sFilePath.startsWith(sDir))
removeItem(pPrevItem);
}
}
/**
* Filter files according to a pattern.
* Hides all entries in the file list, except for those that match a given
* pattern.
*/
void ProjectFilesDlg::slotFilter()
{
QString sFilter;
QListViewItem* pItem;
// Get the user's filter string
sFilter = m_pFilterEdit->text().stripWhiteSpace();
if (sFilter.isEmpty())
return;
// Create the regular expression
QRegExp reFilter(sFilter);
reFilter.setWildcard(true);
// Iterate over the list entries, and hide all items not matching the
// filter string
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
if (reFilter.search(pItem->text(0)) == -1) {
pItem->setVisible(false);
pItem->setSelectable(false);
}
pItem = pItem->nextSibling();
}
}
/**
* Shows all entries in the file list, after a filter has been applied.
*/
void ProjectFilesDlg::slotShowAll()
{
QListViewItem* pItem;
// Iterate over the list entries, and make all items visible
pItem = m_pFileList->firstChild();
while (pItem != NULL) {
pItem->setVisible(true);
pItem->setSelectable(true);
pItem = pItem->nextSibling();
}
}
/**
* Stops a directory scan process.
* This slot is called when the user clicks on the "Cancel" button in the
* scan progress dialog.
*/
void ProjectFilesDlg::slotCancelDirScan()
{
m_pScanner->cancel();
}
#include "projectfilesdlg.moc"

@ -0,0 +1,104 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PROJECTFILESDLG_H
#define PROJECTFILESDLG_H
#include <qwidget.h>
#include <projectfileslayout.h>
#include <qdict.h>
#include "project.h"
class DirScanner;
class ScanProgressDlg;
/**
* A dialog to manipulate the project's files.
* The dialog allows the user to add source files to the current project, or
* remove files from it. The main widget of the dialog is a list view, that
* displays all files currently in the project. When files are added or
* removed, this list view is updated. The project, however, is only modified
* if the user closes the dialog using the "OK" button.
* Since searches through a list view are very slow, the class also maintains
* a QDict object, that connects file names with their respective list items.
* This dictionary is used to ensure duplicated items are not added to the
* list.
* @author Elad Lahav
*/
class ProjectFilesDlg : public ProjectFilesLayout, public FileListTarget,
public FileListSource
{
Q_OBJECT
public:
ProjectFilesDlg(Project*, QWidget* pParent = 0, const char* szName = 0);
~ProjectFilesDlg();
virtual void addItem(const QString&);
virtual bool firstItem(QString&);
virtual bool nextItem(QString&);
protected:
virtual void customEvent(QCustomEvent*);
private:
/** The project to manipulate. */
Project* m_pProj;
/** Holds all file paths in a quickly searchable format (for duplicate
entries lookup). */
QDict<QListViewItem> m_dicFiles;
/** A thread object to a-synchronously scan directories for source files
to add to the project. */
DirScanner* m_pScanner;
/** Displays the progress of a directory scan operation. */
ScanProgressDlg* m_pScanDlg;
/** A file list item that serves as an iterator. */
QListViewItem* m_pItrItem;
/** The last item added. */
QListViewItem* m_pLastItem;
void removeItem(QListViewItem*);
private slots:
void slotAddFiles();
void slotAddDir();
void slotAddTree();
void slotRemSel();
void slotRemDir();
void slotRemTree();
void slotFilter();
void slotShowAll();
void slotCancelDirScan();
};
#endif

@ -0,0 +1,201 @@
<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
<class>ProjectFilesLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>ProjectFilesLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>585</width>
<height>480</height>
</rect>
</property>
<property name="caption">
<string>Project Files</string>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout5</cstring>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout4</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLineEdit">
<property name="name">
<cstring>m_pFilterEdit</cstring>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pFilterButton</cstring>
</property>
<property name="text">
<string>Filter</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pShowAllButton</cstring>
</property>
<property name="text">
<string>Show All</string>
</property>
</widget>
</hbox>
</widget>
<widget class="QListView">
<property name="name">
<cstring>m_pFileList</cstring>
</property>
</widget>
</vbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout5</cstring>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QGroupBox">
<property name="name">
<cstring>groupBox1</cstring>
</property>
<property name="title">
<string>Add</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QPushButton">
<property name="name">
<cstring>m_pAddFilesButton</cstring>
</property>
<property name="text">
<string>Files...</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pAddDirButton</cstring>
</property>
<property name="text">
<string>Directory...</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pAddTreeButton</cstring>
</property>
<property name="text">
<string>Tree...</string>
</property>
</widget>
</vbox>
</widget>
<widget class="QGroupBox">
<property name="name">
<cstring>groupBox2</cstring>
</property>
<property name="title">
<string>Remove</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QPushButton">
<property name="name">
<cstring>m_pRemSelButton</cstring>
</property>
<property name="text">
<string>Selected</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pRemDirButton</cstring>
</property>
<property name="text">
<string>Directory...</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pRemTreeButton</cstring>
</property>
<property name="text">
<string>Tree...</string>
</property>
</widget>
</vbox>
</widget>
<spacer>
<property name="name">
<cstring>spacer3</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>21</width>
<height>118</height>
</size>
</property>
</spacer>
<widget class="QGroupBox">
<property name="name">
<cstring>groupBox3</cstring>
</property>
<property name="title">
<string></string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QPushButton">
<property name="name">
<cstring>m_pOKButton</cstring>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCancelButton</cstring>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</vbox>
</widget>
</vbox>
</widget>
</hbox>
</widget>
<layoutdefaults spacing="6" margin="11"/>
</UI>

@ -0,0 +1,180 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <kmessagebox.h>
#include <klocale.h>
#include "projectmanager.h"
#include "project.h"
#include "kscopeconfig.h"
/**
* Class constructor.
*/
ProjectManager::ProjectManager() : m_pCurProj(NULL)
{
}
/**
* Class destructor.
*/
ProjectManager::~ProjectManager()
{
close();
}
/**
* Creates a project's directory, and associates this directory with the
* current object. This directory is created under the given path, and using
* the project's name (which, thus, has to be a legal file name).
* Note: this function attempts to create a new directory, so the given path
* and name must not lead to an existing one.
* @param sName The project's name
* @param sPath The parent directory under which to create the
* project's directory
* @param opt A structure containing project options
* @return true if successful, false otherwise
*/
bool ProjectManager::create(const QString& sName, const QString& sPath,
const ProjectBase::Options& opt, QString& sProjDir)
{
QDir dir(sPath);
QString sParentPath;
QString sDirName = sName;
QString sMsg;
// Handle requests for a hidden .cscope directory
if (dir.dirName() == ".cscope") {
sParentPath = QDir::cleanDirPath(dir.absPath());
sParentPath = sParentPath.section('/', 0, -2);
dir.cd(sParentPath);
sDirName = ".cscope";
}
// The parent directory must exist
if (!dir.exists()) {
sMsg = i18n("The requested parent directory (%1) does not exist").
arg(sParentPath);
KMessageBox::error(0, sMsg);
return false;
}
// Make sure the directory doesn't exist
if (dir.exists(sDirName)) {
sMsg = i18n("Cannot create a project inside an existing directory "
"(%1/%2)").arg(dir.canonicalPath()).arg(sDirName);
KMessageBox::error(0, sMsg);
return false;
}
// Try to create the projcet's directory
if (!dir.mkdir(sDirName, false) || !dir.cd(sDirName, false)) {
sMsg = i18n("Failed to create the project directory (%1/%2)").
arg(dir.canonicalPath()).arg(sDirName);
KMessageBox::error(0, sMsg);
return false;
}
if (!Project::create(sName, dir.absPath(), opt))
return false;
sProjDir = dir.path();
return true;
}
/**
* Opens a project and makes it the current one.
* @param sPath The directory containing the project's files
* @return true if successful, false otherwise
*/
bool ProjectManager::open(const QString& sPath)
{
Project* pProj;
// Close the current project
close();
// Try to open the new project
pProj = new Project();
if (!pProj->open(sPath)) {
delete pProj;
return false;
}
// Add to the list of recently opened projects
Config().addRecentProject(sPath);
// Project opened successfully
m_pCurProj = pProj;
return true;
}
/**
* Opens a Cscope.out file as a temporary project.
* @param sFilePath The full path of the Cscope.out file
* @return true if successful, false otherwise
*/
bool ProjectManager::openCscopeOut(const QString& sFilePath)
{
ProjectBase* pProj;
// Close the current project
close();
// Try to open the new project
pProj = new ProjectBase();
if (!pProj->open(sFilePath)) {
delete pProj;
return false;
}
// Add to the list of recently opened projects
Config().addRecentProject(sFilePath);
// Project opened successfully
m_pCurProj = pProj;
return true;
}
/**
* Performs clean-up on the project's variables, and detaches the associated
* directory.
*/
void ProjectManager::close()
{
if (m_pCurProj) {
delete m_pCurProj;
m_pCurProj = NULL;
}
}
QString ProjectManager::getProjName() const
{
if (!m_pCurProj)
return i18n("No Project");
return m_pCurProj->getName();
}

@ -0,0 +1,56 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef PROJECTMANAGER_H
#define PROJECTMANAGER_H
#include "projectbase.h"
/**
* @author Elad Lahav
*/
class ProjectManager : public QObject
{
public:
ProjectManager();
virtual ~ProjectManager();
bool create(const QString&, const QString&, const ProjectBase::Options&,
QString&);
bool open(const QString&);
bool openCscopeOut(const QString&);
void close();
QString getProjName() const;
ProjectBase* curProject() const { return m_pCurProj; }
private:
/** The current project (NULL if no project is open). */
ProjectBase* m_pCurProj;
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

@ -0,0 +1,211 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qfile.h>
#include <klocale.h>
#include "querypage.h"
#include "queryview.h"
#include "queryviewdriver.h"
const char* QUERY_TYPES[][2] = {
{ "References to ", "REF " },
{ "Definition of ", "DEF " },
{ "Functions called by ", "<-- " },
{ "Functions calling ", "-->" },
{ "Search for ", "TXT " },
{ "", "" },
{ "EGrep Search for ", "GRP " },
{ "Files named ", "FIL " },
{ "Files #including ", "INC " },
{ "Query", "Query" }
};
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
QueryPage::QueryPage(QWidget* pParent, const char * szName) :
QueryPageBase(pParent, szName),
m_nType(CscopeFrontend::None)
{
m_pView = new QueryView(this);
m_pDriver = new QueryViewDriver(m_pView, this);
connect(m_pView, SIGNAL(lineRequested(const QString&, uint)), this,
SIGNAL(lineRequested(const QString&, uint)));
// Set colours and font
applyPrefs();
}
/**
* Class destructor.
*/
QueryPage::~QueryPage()
{
}
/**
* Runs a query, using the current page to display the results.
* @param nType The type of the query
* @param sText The text of the query
* @param bCase true for case-sensitive queries, false otherwise
*/
void QueryPage::query(uint nType, const QString& sText, bool bCase)
{
m_nType = nType;
m_sText = sText;
m_bCase = bCase;
m_sName = getCaption();
m_pDriver->query(nType, sText, bCase);
}
/**
* Re-runs the last query.
*/
void QueryPage::refresh()
{
m_pView->clear();
if (!m_sText.isEmpty())
m_pDriver->query(m_nType, m_sText, m_bCase);
}
/**
* Resets the query page by deleting all records.
*/
void QueryPage::clear()
{
m_pView->clear();
m_nType = CscopeFrontend::None;
m_sText = QString();
m_sName = QString();
}
/**
* @return true if a query is currently running in this page, false otherwise
*/
bool QueryPage::isRunning()
{
return m_pDriver->isRunning();
}
/**
* Constructs a caption for this page, based on the query's type and text.
* @param bBrief true to use a shortened version of the caption, false
* (default) for the full version
* @return The caption for this page
*/
QString QueryPage::getCaption(bool bBrief) const
{
return QString(QUERY_TYPES[m_nType][bBrief ? 1 : 0] + m_sText);
}
/**
* Creates a new query result item.
* @param sFile The file name
* @param sFunc The function defining the scope of the result
* @param sLine The line number
* @param sText The contents of the line
*/
void QueryPage::addRecord(const QString& sFile, const QString& sFunc,
const QString& sLine, const QString& sText)
{
new QListViewItem(m_pView, sFile, sFunc, sLine, sText);
}
/**
* Creates a unique file name for saving the contents of the query page.
* @param sProjPath The full path of the project directory
* @return The unique file name to use
*/
QString QueryPage::getFileName(const QString& sProjPath) const
{
QString sFileName, sFileNameBase;
int i = 0;
// Do nothing if not initialised
if (m_sName.isEmpty())
return "";
// Create a unique file name
sFileNameBase = m_sName;
sFileNameBase.replace(' ', '_');
do {
sFileName = sFileNameBase + QString::number(++i);
} while (QFile(sProjPath + "/" + sFileName).exists());
return sFileName;
}
/**
* Reads query parameters from a file.
* This mehtod is used as part of the loading process.
* @param str A text stream set to the correct place in the file
* @return true if successful, false otherwise
*/
bool QueryPage::readHeader(QTextStream& str)
{
QString sTemp;
// Read the query name
m_sName = str.readLine();
if (m_sName == QString::null || m_sName.isEmpty())
return false;
// Read the query's type
sTemp = str.readLine();
if (sTemp == QString::null || sTemp.isEmpty())
return false;
// Convert the type string to an integer
m_nType = sTemp.toUInt();
if (m_nType >= CscopeFrontend::None) {
m_nType = CscopeFrontend::None;
return false;
}
// Read the query's text
m_sText = str.readLine();
if (m_sText == QString::null || m_sText.isEmpty())
return false;
return true;
}
/**
* Writes query parameters to a file.
* This mehtod is used as part of the storing process.
* @param str A text stream set to the correct place in the file
*/
void QueryPage::writeHeader(QTextStream& str)
{
str << m_sName << "\n" << m_nType << "\n" << m_sText << "\n";
}
#include "querypage.moc"

@ -0,0 +1,86 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef QUERYPAGE_H
#define QUERYPAGE_H
#include <qwidget.h>
#include <qlistview.h>
#include <qregexp.h>
#include "querypagebase.h"
#include "cscopefrontend.h"
class QueryViewDriver;
/**
* A QueryWidget page that runs and displays Cscope queries.
* The page uses a QueryViewDriver object to run queries, and an embedded
* QueryView widget for displaying query results.
* @author Elad Lahav
*/
class QueryPage : public QueryPageBase
{
Q_OBJECT
public:
QueryPage(QWidget* pParent = 0, const char* szName = 0);
~QueryPage();
void query(uint, const QString&, bool);
void refresh();
void clear();
bool isRunning();
virtual QString getCaption(bool bBrief = false) const;
protected:
virtual void addRecord(const QString&, const QString&, const QString&,
const QString&);
virtual QString getFileName(const QString&) const;
virtual bool readHeader(QTextStream&);
virtual void writeHeader(QTextStream&);
private:
/** The type of query whose results are listed on this page. */
uint m_nType;
/** The text given as a parameter to the query. */
QString m_sText;
/** Whether the query is case-sensitive. */
bool m_bCase;
/** A formatted caption for this query, including the type of query and
its text. */
QString m_sName;
private:
/** Runs Cscope queries whose results are displayed in this page. */
QueryViewDriver* m_pDriver;
};
#endif

@ -0,0 +1,194 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qfile.h>
#include "querypagebase.h"
#include "queryview.h"
#include "kscopeconfig.h"
#define FILE_VERSION "VERSION=2"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
QueryPageBase::QueryPageBase(QWidget* pParent, const char* szName) :
QHBox(pParent, szName),
m_bLocked(false)
{
}
/**
* Class destructor.
*/
QueryPageBase::~QueryPageBase()
{
}
/**
* Sets the list's colours and font, according the user's preferences.
*/
void QueryPageBase::applyPrefs()
{
// Apply colour settings
m_pView->setPaletteBackgroundColor(Config().getColor(
KScopeConfig::QueryWindowBack));
m_pView->setPaletteForegroundColor(Config().getColor(
KScopeConfig::QueryWindowFore));
m_pView->setFont(Config().getFont(KScopeConfig::QueryWindow));
}
/**
* Restores a locked query from the given query file.
* NOTE: The query file is deleted when loading is complete.
* @param sProjPath The full path of the project directory
* @param sFileName The name of the query file to load
* @return true if successful, false otherwise
*/
bool QueryPageBase::load(const QString& sProjPath, const QString& sFileName)
{
QString sTemp, sFile, sFunc, sLine, sText;
int nState;
// Try to open the query file for reading
QFile file(sProjPath + "/" + sFileName);
if (!file.open(IO_ReadOnly))
return false;
{
// Use a new scope for the QTextStream object, to ensure its
// destruction before the file is deleted
QTextStream str(&file);
// Make sure the file's version is correct
sTemp = str.readLine();
if (sTemp != FILE_VERSION) {
file.remove();
return false;
}
// Try to read the file header
if (!readHeader(str))
return false;
// Read query records
sTemp = str.readLine();
nState = 0;
while (sTemp != QString::null) {
switch (nState) {
// File path
case 0:
sFile = sTemp;
break;
// Function name
case 1:
sFunc = sTemp;
break;
// Line number
case 2:
sLine = sTemp;
break;
// Text string
case 3:
sText = sTemp;
addRecord(sFile, sFunc, sLine, sText);
break;
}
nState = (nState + 1) % 4;
sTemp = str.readLine();
}
}
// Delete the query file
file.remove();
return true;
}
/**
* Writes the contents of the page to a file.
* This method is called for pages that shoukld be stored before the owner
* project is closed (@see shouldSave()).
* @param sProjPath The full path of the project directory
* @param sFileName Holds the file name to which the page was saved, upon
* return
* @return true if successful, false otherwise
*/
bool QueryPageBase::save(const QString& sProjPath, QString& sFileName)
{
QListViewItemIterator itr(m_pView);
// Get the file name to use
sFileName = getFileName(sProjPath);
if (sFileName.isEmpty())
return false;
// Open the query file for writing
QFile file(sProjPath + "/" + sFileName);
if (!file.open(IO_WriteOnly))
return false;
QTextStream str(&file);
// Write the version string
str << FILE_VERSION << "\n";
writeHeader(str);
// Write all records
for(; itr.current(); ++itr) {
str << itr.current()->text(0) << "\n"
<< itr.current()->text(1) << "\n"
<< itr.current()->text(2) << "\n"
<< itr.current()->text(3) << "\n";
}
return true;
}
/**
* Selects the next record in the view.
*/
void QueryPageBase::selectNext()
{
m_pView->selectNext();
}
/**
* Selects the previous record in the view.
*/
void QueryPageBase::selectPrev()
{
m_pView->selectPrev();
}
#include "querypagebase.moc"

@ -0,0 +1,148 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef QUERYPAGEBASE_H
#define QUERYPAGEBASE_H
#include <qhbox.h>
class QueryView;
/**
* Defines a page in a QueryWidget's tab widget.
* This is a abstract base class for QueryPage and HistoryPage. It defines
* the common behaviour for all pages, which includes appearance, display
* of tab text, page locking, storage and retrieval of information to
* and from files and basic navigation.
* Each page embeds a list widget derived from QueryView. The actual type
* of widget is defined by the different page classes.
* @author Elad Lahav
*/
class QueryPageBase : public QHBox
{
Q_OBJECT
public:
QueryPageBase(QWidget* pParent = 0, const char* szName = 0);
~QueryPageBase();
void applyPrefs();
bool load(const QString&, const QString&);
bool save(const QString&, QString&);
void selectNext();
void selectPrev();
/**
* Determines whether this page can be locked.
* Can be used by inheriting classes to define non-lockable pages.
* @return Always true
*/
virtual bool canLock() { return true; }
/**
* Locks or unlocks this page.
* @param bLocked true to lock the page, false to unlock it.
*/
void setLocked(bool bLocked) { m_bLocked = bLocked; }
/**
* Determines whether this page is locked.
* @return true if the page is locked, false otherwise
*/
bool isLocked() { return m_bLocked; }
/**
* Determines whether this page should be saved when the project is closed.
* By default, pages are saved if and only if they are locked.
* @return true to save the page, false otherwise
*/
virtual bool shouldSave() const { return m_bLocked; };
/**
* Constructs a caption for this page.
* The caption appears in the page's tab button and as the page's
* tooltip.
* @param bBrief true to generate a brief caption, false otherwise
* @return The page's title
*/
virtual QString getCaption(bool bBrief = false) const = 0;
signals:
/**
* Emitted when a record is selected in the view widget.
* @param sFile The "File" field of the selected record
* @param nLine The "Line" field of the selected record
*/
void lineRequested(const QString& sFile, uint nLine);
protected:
/** The embedded list. */
QueryView* m_pView;
/** Indicates whether this page is locked. A locked page is never
overriden by new data, and is also saved to a disc file when the
session is closed. */
bool m_bLocked;
/**
* Creates a new list item and adds it to the embedded view.
* This method is used to add records read from a stored file.
* @param sFile The "File" field of the record
* @param sFunc The "Function" field of the record
* @param sLine The "Line" field of the record
* @param sText The "Text" field of the record
*/
virtual void addRecord(const QString& sFile, const QString& sFunc,
const QString& sLine, const QString& sText) = 0;
/**
* Creates a file path to store this page.
* The path is composed of the project's path and a unique file name
* in that directory.
* @param sProjPath The project's directory
* @return The page's file path
*/
virtual QString getFileName(const QString& sProjPath) const = 0;
/**
* Tries to read the file header of a stored page.
* The contents of the header differ among inheriting classes.
* @param str A text stream initialised to the open page file
* @return true if the header was read successfully and contains the
* expected information, false otherwise
*/
virtual bool readHeader(QTextStream& str) = 0;
/**
* Writes a header to a page's file.
* The contents of the header differ among inheriting classes.
* @param str A text stream initialised to the open page file
*/
virtual void writeHeader(QTextStream& str) = 0;
};
#endif

@ -0,0 +1,170 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <klocale.h>
#include "queryresultsmenu.h"
/**
* Class constructor.
* @param pParent Parent widget
* @param szName Optional object name
*/
QueryResultsMenu::QueryResultsMenu(QWidget* pParent, const char* szName) :
QPopupMenu(pParent, szName),
m_pItem(NULL)
{
// Create the menu
insertItem(i18n("&View Source"), this, SLOT(slotViewSource()), 0,
ViewSource);
insertItem(i18n("Find &Definition"), this, SLOT(slotFindDef()), 0,
FindDef);
insertSeparator();
insertItem(i18n("&Copy"), this, SLOT(slotCopy()), 0, Copy);
insertSeparator();
insertItem(i18n("&Filter..."), this, SLOT(slotFilter()), 0, Filter);
insertItem(i18n("&Show All"), this, SIGNAL(showAll()), 0, ShowAll);
insertSeparator();
insertItem(i18n("&Remove Item"), this, SLOT(slotRemove()), 0, Remove);
}
/**
* Class destructor.
*/
QueryResultsMenu::~QueryResultsMenu()
{
}
/**
* Displays the popup-menu at the requested coordinates.
* @param pItem The item on which the menu was requested
* @param ptPos The requested position for the menu
* @param nCol The column over which the menu was requested, -1 if no
* column is associated with the request
*/
void QueryResultsMenu::slotShow(QListViewItem* pItem, const QPoint& ptPos,
int nCol)
{
// Save the requested item and column number to use in signals
m_pItem = pItem;
m_nCol = nCol;
if (m_pItem == NULL) {
// No item selected, disable everything but the "Filter" and "Show All"
// items
setItemEnabled(ViewSource, false);
setItemEnabled(FindDef, false);
setItemEnabled(Copy, false);
setItemEnabled(Remove, false);
}
else {
// Item selected, enable record-specific actions
setItemEnabled(ViewSource, true);
setItemEnabled(Copy, true);
setItemEnabled(Remove, true);
// The "Find Definition" item should only be enabled if the mouse
// was clicked over a valid function name
setItemEnabled(FindDef, (m_nCol == 0) &&
(m_pItem->text(0) != "<global>"));
// Set menu contents according to the column number
switch (m_nCol) {
case 0:
changeItem(Copy, "&Copy Function");
break;
case 1:
changeItem(Copy, "&Copy File");
break;
case 2:
changeItem(Copy, "&Copy Line Number");
break;
case 3:
changeItem(Copy, "&Copy Text");
break;
default:
m_nCol = 0;
}
}
// Show the menu
popup(ptPos);
}
/**
* Emits the viewSource() signal.
* This slot is activated when the "View Source" item is selected.
*/
void QueryResultsMenu::slotViewSource()
{
if (m_pItem != NULL)
emit viewSource(m_pItem);
}
/**
* Emits the findDef() signal.
* This slot is activated when the "Find Definition" item is selected.
*/
void QueryResultsMenu::slotFindDef()
{
if (m_pItem != NULL)
emit findDef(m_pItem->text(0));
}
/**
* Emits the copy() signal.
* This slot is activated when the "Copy [Column]" item is selected.
*/
void QueryResultsMenu::slotCopy()
{
if (m_pItem != NULL)
emit copy(m_pItem, m_nCol);
}
/**
* Emits the filter() signal.
* This slot is activated when the "Filter..." item is selected.
*/
void QueryResultsMenu::slotFilter()
{
emit filter(m_nCol);
}
/**
* Emits the remove() signal.
* This slot is activated when the "Remove" item is selected.
*/
void QueryResultsMenu::slotRemove()
{
if (m_pItem != NULL)
emit remove(m_pItem);
}
#include "queryresultsmenu.moc"

@ -0,0 +1,110 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef QUERYRESULTSMENU_H
#define QUERYRESULTSMENU_H
#include <qpopupmenu.h>
#include <qlistview.h>
#include <qregexp.h>
/**
* Provides a popup-menu for list views containing query results.
* The popup menu contains commands for copying field text out of items and
* for removing items.
* This class assumes a certain ordering of the list columns. If an owner
* object uses a different configuration, it needs to call setColumns() after
* constructing the object.
* @author Elad Lahav
*/
class QueryResultsMenu : public QPopupMenu
{
Q_OBJECT
public:
QueryResultsMenu(QWidget* pParent = 0, const char* szName = 0);
~QueryResultsMenu();
public slots:
void slotShow(QListViewItem*, const QPoint&, int nCol);
signals:
/**
* Indicates that the "View Source" menu item was selected.
* @param pItem The item for which the menu was displayed
*/
void viewSource(QListViewItem* pItem);
/**
* Indicates that the "Find Definition" menu item was selected.
* @param sFunc The function to look for
*/
void findDef(const QString& sFunc);
/**
* Indicates that the "Copy [Column]" menu item was selected.
* @param pItem The item for which the menu was displayed
* @param nCol The requested column
*/
void copy(QListViewItem* pItem, int nCol);
/**
* Indicates that the "Filter..." menu item was selected.
* @param nCol The column in which to search
*/
void filter(int nCol);
/**
* Indicates that the "Show All" menu item was selected.
*/
void showAll();
/**
* Indicates that the "Remove Item" menu item was selected.
* @param pItem The item for which the menu was displayed
*/
void remove(QListViewItem* pItem);
private:
/** Menu item IDs. */
enum { ViewSource, FindDef, Copy, Filter, ShowAll, Remove };
/** The item for which the popup menu is provided (cannot be NULL). */
QListViewItem* m_pItem;
/** The list column for which the query was invoked. */
int m_nCol;
private slots:
void slotViewSource();
void slotFindDef();
void slotCopy();
void slotFilter();
void slotRemove();
};
#endif

@ -0,0 +1,444 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qapplication.h>
#include <qclipboard.h>
#include <klocale.h>
#include "queryview.h"
#include "queryresultsmenu.h"
#include "queryviewdlg.h"
#include "cscopefrontend.h"
#include "searchresultsdlg.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The name of the widget
*/
QueryView::QueryView(QWidget* pParent, const char* szName) :
QListView(pParent, szName),
m_pLastItem(NULL)
{
// Create the popup-menu
m_pQueryMenu = new QueryResultsMenu(this);
// Initialise the list's columns
setAllColumnsShowFocus(true);
addColumn(i18n("Function"));
addColumn(i18n("File"));
addColumn(i18n("Line"));
addColumn(i18n("Text"));
setColumnAlignment(2, Qt::AlignRight);
setShowSortIndicator(true);
// A record is selected if it is either double-clicked, or the ENTER
// key is pressed while the record is highlighted
connect(this, SIGNAL(doubleClicked(QListViewItem*)), this,
SLOT(slotRecordSelected(QListViewItem*)));
connect(this, SIGNAL(returnPressed(QListViewItem*)), this,
SLOT(slotRecordSelected(QListViewItem*)));
// Show the popup-menu when requested
connect(this,
SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&, int)),
m_pQueryMenu, SLOT(slotShow(QListViewItem*, const QPoint&, int)));
// Handle popup-menu commands
connect(m_pQueryMenu, SIGNAL(viewSource(QListViewItem*)), this,
SLOT(slotRecordSelected(QListViewItem*)));
connect(m_pQueryMenu, SIGNAL(findDef(const QString&)), this,
SLOT(slotFindDef(const QString&)));
connect(m_pQueryMenu, SIGNAL(copy(QListViewItem*, int)), this,
SLOT(slotCopy(QListViewItem*, int)));
connect(m_pQueryMenu, SIGNAL(filter(int)), this, SLOT(slotFilter(int)));
connect(m_pQueryMenu, SIGNAL(showAll()), this,
SLOT(slotShowAll()));
connect(m_pQueryMenu, SIGNAL(remove(QListViewItem*)), this,
SLOT(slotRemoveItem(QListViewItem*)));
}
/**
* Class destructor.
*/
QueryView::~QueryView()
{
}
/**
* Creates a new list item showing a query result record.
* @param sFunc The name of the function
* @param sFile The file path
* @param sLine The line number in the above file
* @param sText The line's text
* @param pParent The parent item (ignored)
*/
void QueryView::addRecord(const QString& sFunc, const QString& sFile,
const QString& sLine, const QString& sText, QListViewItem* /* pParent */)
{
QListViewItem* pItem;
pItem = new QueryViewItem(this, m_pLastItem, 2);
pItem->setText(0, sFunc);
pItem->setText(1, sFile);
pItem->setText(2, sLine);
pItem->setText(3, sText);
m_pLastItem = pItem;
}
/**
* Selects an item.
* When an item is selected, it is highlighted and made visible. By
* definition, the lineRequested() signal is also emitted.
* This method is used for selecting records programmatically (@see
* selectNext() for example). It has nothing to do with user selection.
* @param pItem The list item to select
*/
void QueryView::select(QListViewItem* pItem)
{
ensureItemVisible(pItem);
setSelected(pItem, true);
slotRecordSelected(pItem);
}
/**
* Selects the next record in the list (if one exists).
* The function selects the next item as follows:
* - The first item in the list, if there is no current item
* - The current item, if it is not selected
* - The item immediately below the current item, otherwise
*/
void QueryView::selectNext()
{
QListViewItem* pItem;
// Do nothing if the list is empty
if (firstChild() == NULL)
return;
// Find the next record
pItem = currentItem();
if (pItem == NULL) {
pItem = firstChild();
}
else if (pItem->isSelected()) {
pItem = pItem->itemBelow();
if (pItem == NULL)
return;
}
// Select the new item
select(pItem);
}
/**
* Selects the previous record in the list (if one exists).
* The function selects the previous item as follows:
* - The first item in the list, if there is no current item
* - The current item, if it is not selected
* - The item immediately above the current item, otherwise
*/
void QueryView::selectPrev()
{
QListViewItem* pItem;
// Do nothing if the list is empty
if (firstChild() == NULL)
return;
// Find the item immediately above this one
pItem = currentItem();
if (pItem == NULL) {
pItem = firstChild();
}
else if (pItem->isSelected()) {
pItem = pItem->itemAbove();
if (pItem == NULL)
return;
}
// Select the new item
select(pItem);
}
/**
* Informs the view that query progress information has been received.
* The view emits the needToShow() signal telling its parent that the widget
* should become visible (if not already so).
*/
void QueryView::queryProgress()
{
if (!isVisible())
emit needToShow();
}
/**
* Called when a query using this view terminates.
* @param nRecords Number of records generated by the query
*/
void QueryView::queryFinished(uint nRecords, QListViewItem*)
{
// Auto-select a single record (no need to emit the show() signal in
// that case)
if (nRecords == 1) {
emit select(firstChild());
return;
}
// Report a query that has returned an empty record set
if (nRecords == 0)
addRecord(i18n("No results"), "", "", "", NULL);
// Data is available, instruct the owner object to show the view
emit needToShow();
}
/**
* Creates an iterator and initialises it to point to the first _visible_
* item in the list.
* @return A new iterator initialised to the beginning of the list
*/
QueryView::Iterator QueryView::getIterator()
{
QListViewItem* pItem;
for (pItem = firstChild(); pItem != NULL && !pItem->isVisible();
pItem = pItem->nextSibling());
return Iterator(pItem);
}
/**
* Handles double-click events over the view.
* NOTE: We override this method since the QListView implementation opens
* expandable items. This is undesired for tree-like query views (such as the
* call tree.
* @param pEvent Event description object
*/
void QueryView::contentsMouseDoubleClickEvent(QMouseEvent* pEvent)
{
QListViewItem* pItem;
// Handle only left button double-clicks
if (pEvent == NULL || pEvent->button() != LeftButton)
return;
// Find the clicked item
pItem = itemAt(contentsToViewport(pEvent->pos()));
if (pItem == NULL)
return;
// Emit the doubleClicked() signal
emit doubleClicked(pItem);
}
/**
* Emits the lineRequested() signal when a list item is selected.
* This slot is connected to the doubleClicked() and returnPressed()
* signals of the list view.
* @param pItem The selected item
*/
void QueryView::slotRecordSelected(QListViewItem* pItem)
{
QString sFileName, sLine;
// Get the file name and line number
sFileName = pItem->text(1);
sLine = pItem->text(2);
// Do not process the "No results" item
if (!sLine.isEmpty())
emit lineRequested(sFileName, sLine.toUInt());
}
/**
* Looks up the definition of a given function.
* Results are displayed in a popup window.
* This slot is connected to the findDef() signal emitted by the results menu.
* @param sFunc The function to look for
*/
void QueryView::slotFindDef(const QString& sFunc)
{
QueryViewDlg* pDlg;
// Create a query view dialogue
pDlg = new QueryViewDlg(QueryViewDlg::DestroyOnSelect, this);
// Display a line when it is selected in the dialogue
connect(pDlg, SIGNAL(lineRequested(const QString&, uint)), this,
SIGNAL(lineRequested(const QString&, uint)));
// Start the query
pDlg->query(CscopeFrontend::Definition, sFunc);
}
/**
* Copies the text of the requested field (item+column) to the clipboard.
* This slot is connected to the copy() signal of the QueryResultsMenu object.
* @param pItem The item from which to copy
* @param nCol The index of the item field to copy
*/
void QueryView::slotCopy(QListViewItem* pItem, int nCol)
{
QApplication::clipboard()->setText(pItem->text(nCol),
QClipboard::Clipboard);
}
/**
* Hides all items in the page that do not meet the given search criteria.
* This slot is connected to the search() signal of the QueryResultsMenu
* object.
* The search is incremental: only visible items are checked, so that a new
* search goes over the results of the previous one.
* @param nCol The list column to search in
*/
void QueryView::slotFilter(int nCol)
{
SearchResultsDlg dlg(this);
QRegExp re;
QListViewItem* pItem;
bool bNegate;
// Prepare the dialogue
dlg.setColumn(nCol);
// Show the dialogue
if (dlg.exec() != QDialog::Accepted)
return;
// Get the selected regular expression
dlg.getPattern(re);
bNegate = dlg.isNegated();
// Disable visual updates while search is in progress
setUpdatesEnabled(false);
// Iterate over all items in the list
pItem = firstChild();
while (pItem != NULL) {
// Filter visible items only
if (pItem->isVisible() &&
(re.search(pItem->text(nCol)) == -1) != bNegate) {
pItem->setVisible(false);
}
pItem = pItem->nextSibling();
}
// Redraw the list
setUpdatesEnabled(true);
triggerUpdate();
}
/**
* Makes all list items visible.
* This slot is connected to the showAll() signal of the QueryResultsMenu
* object.
*/
void QueryView::slotShowAll()
{
QListViewItem* pItem;
// Iterate over all items in the list
pItem = firstChild();
while (pItem != NULL) {
pItem->setVisible(true);
pItem = pItem->nextSibling();
}
}
/**
* Deletes the item on which a popup-menu has been invoked.
* This slot is connected to the remove() signal of the QueryResultsMenu
* object.
* @param pItem The item to remove
*/
void QueryView::slotRemoveItem(QListViewItem* pItem)
{
delete pItem;
}
/**
* Moves the iterator to the next _visible_ item in the list.
*/
void QueryView::Iterator::next()
{
if (m_pItem == NULL)
return;
do {
m_pItem = m_pItem->nextSibling();
} while (m_pItem != NULL && !m_pItem->isVisible());
}
/**
* @return The function associated with the list item the iterator points to
*/
QString QueryView::Iterator::getFunc()
{
if (m_pItem == NULL)
return "";
return m_pItem->text(0);
}
/**
* @return The file associated with the list item the iterator points to
*/
QString QueryView::Iterator::getFile()
{
if (m_pItem == NULL)
return "";
return m_pItem->text(1);
}
/**
* @return The line number associated with the list item the iterator points
* to
*/
QString QueryView::Iterator::getLine()
{
if (m_pItem == NULL)
return "";
return m_pItem->text(2);
}
/**
* @return The text associated with the list item the iterator points to
*/
QString QueryView::Iterator::getText()
{
if (m_pItem == NULL)
return "";
return m_pItem->text(3);
}
#include "queryview.moc"

@ -0,0 +1,217 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef QUERYVIEW_H
#define QUERYVIEW_H
#include <qlistview.h>
#include <qregexp.h>
class QueryResultsMenu;
/**
* Items in a query view.
* The sole purpose for creating a new class is to be able to sort query
* results numerically by line number.
* @author Elad Lahav
*/
class QueryViewItem : public QListViewItem
{
public:
/**
* Class constructor.
* Used for list views.
* @param pView The view widget
* @param pAfter The item to preceed the new one
* @param nLineCol The index of the line column
*/
QueryViewItem(QListView* pView, QListViewItem* pAfter,
int nLineCol) : QListViewItem(pView, pAfter), m_nLineCol(nLineCol)
{}
/**
* Class constructor.
* Used for tree views.
* @param pParent The parent item
* @param pAfter The item to preceed the new one
* @param nLineCol The index of the line column
*/
QueryViewItem(QListViewItem* pParent, QListViewItem* pAfter,
int nLineCol) : QListViewItem(pParent, pAfter), m_nLineCol(nLineCol)
{}
/**
* Compares two items.
* If the given column holds line numbers, than the items are compared
* by their numeric values. Otherwise, a standard text comparison is
* performed.
* @param pItem The item to compare to
* @param nCol The column by which to compare
* @param bAscend Whether sorting in ascending or descending order
* @return 0 if the items are equal, 1 if the current item is greater,
* -1 if the current item is smaller
*/
virtual int compare(QListViewItem* pItem, int nCol, bool bAscend) const {
if (nCol == m_nLineCol) {
uint nLineCur, nLineOther;
int nResult;
// Get the line numbers of each item
nLineCur = text(nCol).toUInt();
nLineOther = pItem->text(nCol).toUInt();
// Compare the line numbers
nResult = nLineCur - nLineOther;
if (nResult == 0)
return 0; // Items are equal
else if (nResult > 0)
return 1; // The first item is greater
else
return -1; // The second item is greater
}
return QListViewItem::compare(pItem, nCol, bAscend);
}
private:
/** The index of the column holding the line numbers. */
int m_nLineCol;
};
/**
* A list view widget for displaying locations in the source code. Each record
* (list item) represents a single line of code.
* The main purpose of this class is for showing query results (@see
* QueryViewDriver), but is can also serve as a base class for any widget
* which needs to refer to locations in the source code (@see
* HistoryView).
* The view has 4 columns, for showing the file path, function name, line
* number and line text of a code location.
* The widget owns a popup menu which allows users to copy information
* from records, filter records, and more.
* @author Elad Lahav
*/
class QueryView : public QListView
{
Q_OBJECT
public:
QueryView(QWidget* pParent = 0, const char* szName = 0);
~QueryView();
virtual void addRecord(const QString&, const QString&, const QString&,
const QString&, QListViewItem* pParent = NULL);
virtual void select(QListViewItem*);
virtual void selectNext();
virtual void selectPrev();
virtual void queryProgress();
virtual void queryFinished(uint, QListViewItem* pParent = NULL);
/**
* Provides an iterator over the list of query results.
* @author Elad Lahav
*/
class Iterator
{
public:
/**
* Default constructor.
*/
Iterator() : m_pItem(NULL) {}
/**
* Copy constructor.
* @param itr The copied object
*/
Iterator(const Iterator& itr) : m_pItem(itr.m_pItem) {}
/**
* @return true if the iterator points _beyond_ the end of the list,
* false otherwise
*/
bool isEOF() { return m_pItem == NULL; }
void next();
QString getFunc();
QString getFile();
QString getLine();
QString getText();
private:
/** Points to the current list item. */
QListViewItem* m_pItem;
/**
* Private constructor used to return initialised iterators.
* This constructor can only be called from within QueryView.
* @param pItem The initial list item
*/
Iterator(QListViewItem* pItem) : m_pItem(pItem) {}
friend class QueryView;
};
Iterator getIterator();
signals:
/**
* Notifies the owner widget that it needs to be visible since some
* information is available to display.
* This information may be an advancement of the progress bar,
* availability of query results, etc.
*/
void needToShow();
/**
* Emitted when a list record is selected.
* Selection is done by either double-clicking a query or by highlighting
* it and then pressing the ENTER key.
* @param sFile The "File" field of the selected record
* @param nLine The "Line" field of the selected record
*/
void lineRequested(const QString& sFile, uint nLine);
protected:
/** A popup-menu for manipulating query result items. */
QueryResultsMenu* m_pQueryMenu;
/** A pointer to the last item (used for appending results). */
QListViewItem* m_pLastItem;
void contentsMouseDoubleClickEvent(QMouseEvent*);
protected slots:
virtual void slotRecordSelected(QListViewItem*);
virtual void slotFindDef(const QString&);
virtual void slotCopy(QListViewItem*, int);
virtual void slotFilter(int);
virtual void slotShowAll();
virtual void slotRemoveItem(QListViewItem*);
};
#endif

@ -0,0 +1,111 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include "queryviewdlg.h"
#include "queryviewdriver.h"
/**
* Class constructor.
* @param nFlags Controls the behaviour of the diaogue
* @param pParent The parent widget
* @param szName The widget's name
*/
QueryViewDlg::QueryViewDlg(uint nFlags, QWidget* pParent,
const char* szName) :
QueryViewLayout(pParent, szName),
m_nFlags(nFlags)
{
// Set the destructive flag, if required
if (nFlags & DestroyOnClose)
setWFlags(getWFlags() | WDestructiveClose);
// Create a driver for running queries
m_pDriver = new QueryViewDriver(m_pView, this);
// Show the dialogue when instructed by the driver
connect(m_pView, SIGNAL(needToShow()), this, SLOT(slotShow()));
// Propagate the lineRequested() signal from the QueryView object
connect(m_pView, SIGNAL(lineRequested(const QString&, uint)), this,
SLOT(slotLineRequested(const QString&, uint)));
// Make the dialogue modal
setModal(true);
}
/**
* Class destructor.
*/
QueryViewDlg::~QueryViewDlg()
{
}
/**
* Starts a query.
* @param nType The type of the query
* @param sText The query's text
* @param bCase true for case-sensitive queries, false otherwise
*/
void QueryViewDlg::query(uint nType, const QString& sText, bool bCase)
{
m_pDriver->query(nType, sText, bCase);
}
/**
* Make the dialogue visible when instructed by the driver.
* This slot is connected to the show() signal emitted by the QueryViewDriver
* object.
*/
void QueryViewDlg::slotShow()
{
show();
}
/**
* Propagates the lineRequested() signal from the view object.
* If the CloseOnSelect flag is set, the dialogue is closed.
* This slot is connected to the lineRequested() signal emitted by the
* QueryView widget.
*/
void QueryViewDlg::slotLineRequested(const QString& sFileName, uint nLine)
{
emit lineRequested(sFileName, nLine);
if (m_nFlags & CloseOnSelect)
close();
}
/**
* @return A QueryView iterator initialised to the beginning of the result
* list
*/
QueryView::Iterator QueryViewDlg::getIterator()
{
return m_pView->getIterator();
}
#include "queryviewdlg.moc"

@ -0,0 +1,88 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef QUERYVIEWDLG_H
#define QUERYVIEWDLG_H
#include "queryviewlayout.h"
#include "queryview.h"
class QueryViewDriver;
/**
* A dialogue for running and displaying queries.
* The dialogue is built around a QueryView widget, and uses a QueryViewDriver
* object to run a query. The dialogue is used in different contexts, such
* as executing quick definitions, displaying multiple call nodes in a graph,
* etc.
* The dialogue is always modal, but should not be launched using exec().
* Instead, it is created as a modeless, hidden, dialogue. It then becomes
* modal (and visible) only if and when information is available (@see
* QueryViewDriver::show()).
* @author Elad Lahav
*/
class QueryViewDlg : public QueryViewLayout
{
Q_OBJECT
public:
QueryViewDlg(uint nFlags = 0, QWidget* pParent = 0,
const char* szName = 0);
~QueryViewDlg();
/** These flags control the behaviour of the dialogue. */
enum { CloseOnSelect = 0x1, DestroyOnClose = 0x2,
DestroyOnSelect = CloseOnSelect | DestroyOnClose };
void query(uint, const QString&, bool bCase = true);
QueryView::Iterator getIterator();
signals:
/**
* Propagates the lineRequested() signal of the embedded QueryView
* widget.
* @param sFile The "File" field of the selected record
* @param nLine The "Line" field of the selected record
*/
void lineRequested(const QString& sFile, uint nLine);
private:
/** Flags the control the behaviour of the dialogue. */
uint m_nFlags;
/** Used for running Cscope queries and displaying their results in the
view. */
QueryViewDriver* m_pDriver;
private slots:
void slotShow();
void slotLineRequested(const QString&, uint);
};
#endif

@ -0,0 +1,180 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <klocale.h>
#include "queryviewdriver.h"
#include "queryview.h"
/**
* Class constructor.
* Creates a driver that adds new records as root items in the given view.
* @param pView The view to which this driver should add records
* @param pParent The parent object of the driver
* @param szName The name of the object
*/
QueryViewDriver::QueryViewDriver(QueryView* pView, QObject* pParent,
const char* szName) : QObject(pParent, szName),
m_pView(pView),
m_pItem(NULL),
m_progress(pView),
m_bRunning(false)
{
m_pCscope = new CscopeFrontend();
// Add records to the page when Cscope outputs them
connect(m_pCscope, SIGNAL(dataReady(FrontendToken*)), this,
SLOT(slotDataReady(FrontendToken*)));
// Report progress information
connect(m_pCscope, SIGNAL(progress(int, int)), this,
SLOT(slotProgress(int, int)));
// Perform tasks when the query process terminates
connect(m_pCscope, SIGNAL(finished(uint)), this,
SLOT(slotFinished(uint)));
connect(m_pView, SIGNAL(destroyed()), this, SLOT(slotViewClosed()));
}
/**
* Class destructor.
*/
QueryViewDriver::~QueryViewDriver()
{
delete m_pCscope;
}
/**
* Executes a query.
* @param nType The type of the query (@see CscopeFrontend)
* @param sText The query's text
* @param bCase true for case-sensitive queries, false otherwise
* @param pItem If non-null, represents an view item passed back to
* the view in a call to addRecord()
*/
void QueryViewDriver::query(uint nType, const QString& sText, bool bCase,
QListViewItem* pItem)
{
m_pItem = pItem;
// Make sure sorting is disabled while entries are added
m_pView->setSorting(100);
// Execute the query
m_pCscope->query(nType, sText, bCase);
m_bRunning = true;
m_pView->setEnabled(false);
m_pView->setUpdatesEnabled(false);
}
/**
* Adds a query entry to the view.
* Called by a CscopeFrontend object, when a new entry was received in its
* whole from the Cscope back-end process.
* @param pToken The first token in the entry
*/
void QueryViewDriver::slotDataReady(FrontendToken* pToken)
{
QString sFile, sFunc, sLine, sText;
// Get the file name
sFile = pToken->getData();
pToken = pToken->getNext();
// Get the function name
sFunc = pToken->getData();
pToken = pToken->getNext();
// Get the line number
sLine = pToken->getData();
if (!sLine.toInt()) {
// Line number could not be 0!
// means that function name was empty
sLine = sFunc;
sFunc = "<global>";
}
else {
pToken = pToken->getNext();
}
// Get the line's text
sText = pToken->getData();
pToken = pToken->getNext();
// Add a new item at the end of the list
m_pView->addRecord(sFunc, sFile, sLine, sText, m_pItem);
}
/**
* Handles a finished query event, reported by the Cscope frontend object.
* If no resutls are available, a proper message is displayed. If only one
* record was generated by Cscope, it is automatically selected for viewing.
* @param nRecords The number of records the query has generated
*/
void QueryViewDriver::slotFinished(uint nRecords)
{
// The query is no longer running
m_bRunning = false;
m_pView->setEnabled(true);
m_pView->setUpdatesEnabled(true);
m_pView->triggerUpdate();
// Destroy the progress bar
m_progress.finished();
// Let owner widget decide what to do based on the number of records
m_pView->queryFinished(nRecords, m_pItem);
}
/**
* Displays search progress information.
* This slot is connected to the progress() signal emitted by a
* CscopeFrontend object.
* @param nFiles The number of files scanned
* @param nTotal The total number of files in the project
*/
void QueryViewDriver::slotProgress(int nFiles, int nTotal)
{
// A progress report is available, instruct the owner object to show the
// view
if (nTotal > 1)
m_pView->queryProgress();
// Set the progress bar
m_progress.setProgress(nFiles, nTotal);
}
/**
* Called when the owner view is destroyed.
*/
void QueryViewDriver::slotViewClosed()
{
m_pView = NULL;
m_pCscope->kill();
}
#include "queryviewdriver.moc"

@ -0,0 +1,84 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef QUERYVIEWDRIVER_H
#define QUERYVIEWDRIVER_H
#include <qobject.h>
#include <qlistview.h>
#include "cscopefrontend.h"
class QueryView;
/**
* Executes a Cscope query and displays the results in a QueryView widget.
* This class is used in conjunction with QueryView to create a query
* display object. The driver uses the view widget to display result records
* of an executed query. It also uses the view as a parent widget for the
* query progress bar.
* @author Elad Lahav
*/
class QueryViewDriver : public QObject
{
Q_OBJECT
public:
QueryViewDriver(QueryView*, QObject* pParent = 0, const char* szName = 0);
~QueryViewDriver();
void query(uint, const QString&, bool bCase, QListViewItem* pItem = NULL);
/**
* @return true if a query is currently running, false otherwise
*/
bool isRunning() { return m_bRunning; }
private:
/** Cscope object for running queries. */
CscopeFrontend* m_pCscope;
/** The view to which this object adds result records. */
QueryView* m_pView;
/** QueryView item passed to addRecord(). */
QListViewItem* m_pItem;
/** Displays query progress information. */
CscopeProgress m_progress;
/** This flag is set to true when a query is executed, and back to false
when the the CscopeFrontend object emits the finished() signal. */
bool m_bRunning;
private slots:
void slotDataReady(FrontendToken*);
void slotFinished(uint);
void slotProgress(int, int);
void slotViewClosed();
};
#endif

@ -0,0 +1,167 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>QueryViewLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>QueryViewLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>654</width>
<height>499</height>
</rect>
</property>
<property name="caption">
<string>Query Results</string>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QueryView">
<property name="name">
<cstring>m_pView</cstring>
</property>
</widget>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>5</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Right-click inside the list for more options.</string>
</property>
</widget>
<widget class="Line">
<property name="name">
<cstring>line1</cstring>
</property>
<property name="frameShape">
<enum>HLine</enum>
</property>
<property name="frameShadow">
<enum>Sunken</enum>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>Layout1</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<spacer>
<property name="name">
<cstring>Horizontal Spacing2</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>buttonOk</cstring>
</property>
<property name="text">
<string>&amp;OK</string>
</property>
<property name="accel">
<string></string>
</property>
<property name="autoDefault">
<bool>true</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>buttonCancel</cstring>
</property>
<property name="text">
<string>&amp;Cancel</string>
</property>
<property name="accel">
<string></string>
</property>
<property name="autoDefault">
<bool>true</bool>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<customwidgets>
<customwidget>
<class>QueryView</class>
<header location="local">queryview.h</header>
<sizehint>
<width>-1</width>
<height>-1</height>
</sizehint>
<container>0</container>
<sizepolicy>
<hordata>5</hordata>
<verdata>5</verdata>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<pixmap>image0</pixmap>
</customwidget>
</customwidgets>
<images>
<image name="image0">
<data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data>
</image>
</images>
<connections>
<connection>
<sender>buttonOk</sender>
<signal>clicked()</signal>
<receiver>QueryViewLayout</receiver>
<slot>accept()</slot>
</connection>
<connection>
<sender>buttonCancel</sender>
<signal>clicked()</signal>
<receiver>QueryViewLayout</receiver>
<slot>reject()</slot>
</connection>
</connections>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>queryview.h</includehint>
</includehints>
</UI>

@ -0,0 +1,601 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qtoolbutton.h>
#include <qtooltip.h>
#include <klocale.h>
#include <kmessagebox.h>
#include "querywidget.h"
#include "kscopepixmaps.h"
#include "kscopeconfig.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
QueryWidget::QueryWidget(QWidget* pParent, const char* szName) :
QueryWidgetLayout(pParent, szName),
m_pPageMenu(NULL),
m_pLockAction(NULL),
m_pHistPage(NULL),
m_bHistEnabled(true),
m_nQueryPages(0)
{
// Pages can be closed by clicking their tabs
m_pQueryTabs->setHoverCloseButton(true);
// Change the lock action state according to the current page
connect(m_pQueryTabs, SIGNAL(currentChanged(QWidget*)), this,
SLOT(slotCurrentChanged(QWidget*)));
// Close a query when its tab button is clicked
connect(m_pQueryTabs, SIGNAL(closeRequest(QWidget*)), this,
SLOT(slotClosePage(QWidget*)));
// Show the menu when requested
connect(m_pQueryTabs, SIGNAL(contextMenu(const QPoint&)), this,
SLOT(slotContextMenu(const QPoint&)));
connect(m_pQueryTabs, SIGNAL(contextMenu(QWidget*, const QPoint&)), this,
SLOT(slotContextMenu(QWidget*, const QPoint&)));
}
/**
* Class destructor.
*/
QueryWidget::~QueryWidget()
{
}
/**
* Runs a query in a query page.
* A query page is first selected, with a new one created if required. The
* method then creates a Cscope process and runs the query.
* @param nType The query's numeric type code
* @param sText The query's text, as entered by the user
* @param bCase true for case-sensitive queries, false otherwise
*/
void QueryWidget::initQuery(uint nType, const QString& sText, bool bCase)
{
QueryPage* pPage;
// Make sure we have a query page
findQueryPage();
pPage = (QueryPage*)currentPage();
// Use the current page, or a new page if the current one is locked
if (pPage->isLocked()) {
addQueryPage();
pPage = (QueryPage*)currentPage();
}
// Reset the page's results list
pPage->clear();
pPage->query(nType, sText, bCase);
// Set the page's tab text according to the new query
setPageCaption(pPage);
}
/**
* Applies the user's colour and font preferences to all pages.
*/
void QueryWidget::applyPrefs()
{
QueryPage* pPage;
int nPages, i;
// Iterate query pages
nPages = m_pQueryTabs->count();
for (i = 0; i < nPages; i++) {
pPage = (QueryPage*)m_pQueryTabs->page(i);
pPage->applyPrefs();
setPageCaption(pPage);
}
}
/**
* Loads all pages saved when the project was closed.
* @param sProjPath The full path of the project directory
* @param slFiles The list of query file names to load
*/
void QueryWidget::loadPages(const QString& sProjPath,
const QStringList& slFiles)
{
QStringList::ConstIterator itr;
QueryPageBase* pPage;
QString sName;
// Iterate through query files
for (itr = slFiles.begin(); itr != slFiles.end(); ++itr) {
// Set the target page, based on the file type (query or history)
if ((*itr).startsWith("History")) {
findHistoryPage();
pPage = m_pHistPage;
}
else {
findQueryPage();
pPage = (QueryPage*)currentPage();
}
// Load a query file to this page, and lock the page
if (pPage->load(sProjPath, *itr)) {
setPageCaption(pPage);
setPageLocked(pPage, true);
}
}
}
/**
* Stores all pages marked for saving into files in the project directory.
* @param sProjPath The full path of the project directory
* @param slFiles Holds a list of query file names, upon return
*/
void QueryWidget::savePages(const QString& sProjPath, QStringList& slFiles)
{
int nPageCount, i;
QueryPage* pPage;
QString sFileName;
// Iterate pages
nPageCount = m_pQueryTabs->count();
for (i = 0; i < nPageCount; i++) {
pPage = (QueryPage*)m_pQueryTabs->page(i);
if (pPage->shouldSave()) {
// Store this query page
if (pPage->save(sProjPath, sFileName) && !sFileName.isEmpty())
slFiles.append(sFileName);
}
}
}
/**
* Adds a new position record to the active history page.
* @param sFile The file path
* @param nLine The line number
* @param sText The contents of the line pointed to by the file path and
* line number
*/
void QueryWidget::addHistoryRecord(const QString& sFile, uint nLine,
const QString& sText)
{
// Validate file name and line number
if (sFile.isEmpty() || nLine == 0)
return;
// Do nothing if history logging is disabled
if (!m_bHistEnabled)
return;
// Make sure there is an active history page
findHistoryPage();
// Add the position entry to the active page
m_pHistPage->addRecord(sFile, nLine, sText);
}
/**
* Sets the tab caption and tool-tip for the given page.
* @param pPage The page whose tab needs to be changed
*/
void QueryWidget::setPageCaption(QueryPageBase* pPage)
{
m_pQueryTabs->changeTab(pPage,
pPage->getCaption(Config().getUseBriefQueryCaptions()));
m_pQueryTabs->setTabToolTip(pPage, pPage->getCaption());
}
/**
* Creates a new query page, and adds it to the tab widget.
* The new page is set as the current one.
*/
void QueryWidget::addQueryPage()
{
QueryPage* pPage;
QString sTitle;
// Create the page
pPage = new QueryPage(this);
// Add the page, and set it as the current one
m_pQueryTabs->insertTab(pPage, GET_PIXMAP(TabUnlocked), "Query",
m_nQueryPages++);
setCurrentPage(pPage);
// Emit the lineRequested() signal when a query record is selected on
// this page
connect(pPage, SIGNAL(lineRequested(const QString&, uint)), this,
SLOT(slotRequestLine(const QString&, uint)));
}
/**
* Creates a new query page, and emits signal about it.
*/
void QueryWidget::slotNewQueryPage()
{
addQueryPage();
emit newQuery();
}
/**
* Locks or unlocks a query.
* This slot is connected to the toggled() signal of the lock query button.
* @param bOn true if the new state of the button is "on", false if it is
* "off"
*/
void QueryWidget::slotLockCurrent(bool bOn)
{
QueryPageBase* pPage;
pPage = currentPage();
if (pPage != NULL)
setPageLocked(currentPage(), bOn);
}
/**
* Locks or unlocks a query, by toggling the current state.
*/
void QueryWidget::slotLockCurrent()
{
QueryPageBase* pPage;
pPage = currentPage();
if (pPage != NULL)
setPageLocked(pPage, !pPage->isLocked());
}
/**
* Reruns the query whose results are displayed in the current page.
*/
void QueryWidget::slotRefreshCurrent()
{
QueryPage* pPage;
// Make sure the current page is a valid, non-empty one
pPage = dynamic_cast<QueryPage*>(currentPage());
if (pPage == NULL)
return;
// Clear the current page contents
pPage->refresh();
}
/**
* Selects the next query result record in the current query page.
*/
void QueryWidget::slotNextResult()
{
QueryPage* pPage;
// Select the next record in the current page
pPage = dynamic_cast<QueryPage*>(currentPage());
if (pPage != NULL)
pPage->selectNext();
}
/**
* Selects the next query result record in the current query page.
*/
void QueryWidget::slotPrevResult()
{
QueryPage* pPage;
// Select the next record in the current page
pPage = dynamic_cast<QueryPage*>(currentPage());
if (pPage != NULL)
pPage->selectPrev();
}
/**
* Closes the current query page.
*/
void QueryWidget::slotCloseCurrent()
{
QWidget* pPage;
// Close the current page
pPage = currentPage();
if (pPage != NULL)
slotClosePage(pPage);
}
/**
* Closes all query pages.
*/
void QueryWidget::slotCloseAll()
{
int nPageCount, i;
QueryPage* pPage;
// Close all pages
nPageCount = m_pQueryTabs->count();
for (i = 0; i < nPageCount; i++) {
pPage = (QueryPage*)m_pQueryTabs->page(0);
m_pQueryTabs->removePage(pPage);
delete pPage;
}
m_pHistPage = NULL;
}
/**
* Handles the "Go->Back" menu command.
* Moves to the previous position in the position history.
*/
void QueryWidget::slotHistoryPrev()
{
if (m_pHistPage != NULL) {
m_bHistEnabled = false;
m_pHistPage->selectPrev();
m_bHistEnabled = true;
}
}
/**
* Handles the "Go->Forward" menu command.
* Moves to the next position in the position history.
*/
void QueryWidget::slotHistoryNext()
{
if (m_pHistPage != NULL) {
m_bHistEnabled = false;
m_pHistPage->selectNext();
m_bHistEnabled = true;
}
}
/**
* Sets the active history page, if any, as the current page.
*/
void QueryWidget::selectActiveHistory()
{
if (m_pHistPage)
setCurrentPage(m_pHistPage);
}
/**
* Attaches the page operations menu to this widget.
* The page menu is a popup menu that handles such operations as opening a
* new page, closing a page, locking a page, etc.
* @param pMenu Pointer to the popup menu
* @param pAction Pointer to the "Lock/Unlock" toggle action
*/
void QueryWidget::setPageMenu(QPopupMenu* pMenu, KToggleAction* pAction)
{
m_pPageMenu = pMenu;
m_pLockAction = pAction;
}
/**
* Emits a signal indicating a certain source file and line number are
* requested.
* This slot is connected to the recordSelected() signal emitted by any of
* the query pages. The signal emitted by this slot is used to display an
* editor page at the requested line.
* @param sFileName The file's path
* @param nLine The requested line in the file
*/
void QueryWidget::slotRequestLine(const QString& sFileName, uint nLine)
{
// Disable history if the request came from the active history page
if (currentPage() == m_pHistPage)
m_bHistEnabled = false;
// Emit the signal
emit lineRequested(sFileName, nLine);
// Re-enable history
if (currentPage() == m_pHistPage)
m_bHistEnabled = true;
}
/**
* Update the lock button when the current query page changes.
* @param pWidget The new current page
*/
void QueryWidget::slotCurrentChanged(QWidget* pWidget)
{
QueryPage* pPage;
pPage = (QueryPage*)pWidget;
m_pLockAction->setChecked(pPage->isLocked());
}
/**
* Removes the given page from the tab widget.
* This slot is connected to the closeRequest() signal of the KTabBar object.
* @param pPage The page to close
*/
void QueryWidget::slotClosePage(QWidget* pPage)
{
// Prompt the user before closing a locked query
if (((QueryPage*)pPage)->isLocked()) {
if (KMessageBox::questionYesNo(NULL, i18n("You about about to close"
" a locked page.\nAre you sure?")) == KMessageBox::No) {
return;
}
}
// Check if the closed page is the active history page
if (pPage == m_pHistPage)
m_pHistPage = NULL;
// Update the number of open history pages
else if (dynamic_cast<HistoryPage*>(pPage) == NULL)
m_nQueryPages--;
// Remove the page and delete the object
m_pQueryTabs->removePage(pPage);
delete pPage;
}
/**
* Displays a context menu for page operations.
* This slot is connected to the contextMenu() signal, emitted by
* m_pQueryTabs.
* NOTE: We assume that the first item in the menu is "New".
* @param pt The point over which the mouse was clicked in request for the
* context menu
*/
void QueryWidget::slotContextMenu(const QPoint& pt)
{
uint i;
// Disable everything but the "new" action (clicked outside any widget)
for (i = 1; i < m_pPageMenu->count(); i++)
m_pPageMenu->setItemEnabled(m_pPageMenu->idAt(i), false);
// Show the menu
m_pPageMenu->popup(pt);
}
/**
* Displays a context menu for page operations.
* This slot is connected to the contextMenu() signal, emitted by
* m_pQueryTabs.
* @param pWidget The page under the mouse
* @param pt The point over which the mouse was clicked in request for
* the context menu
*/
void QueryWidget::slotContextMenu(QWidget* pWidget, const QPoint& pt)
{
uint i;
// Operations are on the current page, so we must ensure the clicked
// tab becomes the current one
setCurrentPage(pWidget);
// Enable all operations
for (i = 1; i < m_pPageMenu->count(); i++)
m_pPageMenu->setItemEnabled(m_pPageMenu->idAt(i), true);
// Show the menu
m_pPageMenu->popup(pt);
}
/**
* Locks/unlocks the give page.
* @param pPage The page to lock or unlock
* @param bLock true to lock the page, false to unlock it
*/
void QueryWidget::setPageLocked(QueryPageBase* pPage, bool bLock)
{
if (!pPage->canLock())
return;
// Set the locking state of the current page
pPage->setLocked(bLock);
m_pQueryTabs->setTabIconSet(pPage, bLock ? GET_PIXMAP(TabLocked) :
GET_PIXMAP(TabUnlocked));
// There can only be one unlocked history page. Check if a non-active
// query page is being unlocked
if (isHistoryPage(pPage) && (pPage != m_pHistPage) && !bLock) {
// Lock the active history page (may be NULL)
if (m_pHistPage != NULL)
setPageLocked(m_pHistPage, true);
// Set the unlock page as the new active history page
m_pHistPage = (HistoryPage*)pPage;
}
}
/**
* Ensures the current page is a query page that is ready to accept new
* queries.
* The function first checks the current page. If it is an unlocked query
* page, then nothing needs to be done. Otherwise, it checks for the first
* unlocked query page by iterating over all pages in the tab widget. If this
* fails as well, a new query page is created.
*/
void QueryWidget::findQueryPage()
{
QueryPage* pPage;
int nPages, i;
// First check if the current page is an unlocked query page
pPage = dynamic_cast<QueryPage*>(currentPage());
if (pPage != NULL) {
if (!pPage->isLocked() && !pPage->isRunning())
return;
}
// Look for the first unlocked query page
nPages = m_pQueryTabs->count();
for (i = 0; i < nPages; i++) {
pPage = dynamic_cast<QueryPage*>(m_pQueryTabs->page(i));
if (pPage != NULL) {
if (!pPage->isLocked() && !pPage->isRunning()) {
setCurrentPage(pPage);
return;
}
}
}
// Couldn't find an unlocked query page, create a new one
addQueryPage();
}
/**
* Ensures an active history page exists.
* The active history page is the only unlocked history page. If one does not
* exist, it is created.
*/
void QueryWidget::findHistoryPage()
{
HistoryPage* pPage;
int nPages, i;
QString sTitle;
// First check if the active history page is unlocked
if (m_pHistPage != NULL && !m_pHistPage->isLocked())
return;
// Look for the first unlocked history page
nPages = m_pQueryTabs->count();
for (i = 0; i < nPages; i++) {
pPage = dynamic_cast<HistoryPage*>(m_pQueryTabs->page(i));
if (pPage != NULL && !pPage->isLocked()) {
m_pHistPage = pPage;
return;
}
}
// Couldn't find an unlocked query page, create a new one
m_pHistPage = new HistoryPage(this);
// Add the page, and set it as the current one
m_pQueryTabs->insertTab(m_pHistPage, GET_PIXMAP(TabUnlocked), "");
setPageCaption(m_pHistPage);
// Emit the lineRequested() signal when a query record is selected on
// this page
connect(m_pHistPage, SIGNAL(lineRequested(const QString&, uint)), this,
SLOT(slotRequestLine(const QString&, uint)));
}
#include "querywidget.moc"

@ -0,0 +1,152 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef QUERYWIDGET_H
#define QUERYWIDGET_H
#include <qlistview.h>
#include <qpopupmenu.h>
#include <kaction.h>
#include "querywidgetlayout.h"
#include "tabwidget.h"
#include "querypage.h"
#include "historypage.h"
#include "projectmanager.h"
/**
* A tabbed-window holding Cscope query results pages.
* @author Elad Lahav
*/
class QueryWidget : public QueryWidgetLayout
{
Q_OBJECT
public:
QueryWidget(QWidget* pParent = 0, const char* szName = 0);
~QueryWidget();
void addQueryPage();
void initQuery(uint, const QString&, bool);
void applyPrefs();
void loadPages(const QString&, const QStringList&);
void savePages(const QString&, QStringList&);
void addHistoryRecord(const QString&, uint, const QString&);
void selectActiveHistory();
void setPageMenu(QPopupMenu*, KToggleAction*);
void getBookmarks(FileLocationList&);
/**
* Enables/disables new history items.
* @param bEnabled true to enable new history items, false to
* disable
*/
void setHistoryEnabled(bool bEnabled) { m_bHistEnabled = bEnabled; }
public slots:
void slotNewQueryPage();
void slotLockCurrent(bool);
void slotLockCurrent();
void slotRefreshCurrent();
void slotNextResult();
void slotPrevResult();
void slotCloseCurrent();
void slotCloseAll();
void slotHistoryPrev();
void slotHistoryNext();
signals:
/**
* Emitted when the a lineRequested() signal is received from any of the
* currently open query pages.
* @param sPath The full path of the requested source file
* @param nLine The requested line number
*/
void lineRequested(const QString& sPath, uint nLine);
/**
* Emitted when new query page is requested by user
*/
void newQuery();
private:
/** A popup menu with query page commands (new query, lock/unlock, close
query, etc.). */
QPopupMenu* m_pPageMenu;
/** A toggle-like action for changing the locked state of a query. */
KToggleAction* m_pLockAction;
/** The active history page. */
HistoryPage* m_pHistPage;
/** Determines whether history items should be added to the active
history page. */
bool m_bHistEnabled;
/** The number of query pages currently open. */
int m_nQueryPages;
void setPageCaption(QueryPageBase*);
/**
* @return The active page in the tab widget
*/
inline QueryPageBase* currentPage() {
return (QueryPageBase*)m_pQueryTabs->currentPage();
}
/**
* @param pWidget A query page to set as the current one
*/
inline void setCurrentPage(QWidget* pWidget) {
if (pWidget)
m_pQueryTabs->setCurrentPage(m_pQueryTabs->indexOf(pWidget));
}
/**
* Determines if a page is a history page.
* @param pPage The page to check
* @return true if the given page is a history page
*/
inline bool isHistoryPage(QWidget* pPage) {
return (dynamic_cast<HistoryPage*>(pPage) != NULL);
}
void setPageLocked(QueryPageBase*, bool);
void findQueryPage();
void findHistoryPage();
private slots:
void slotRequestLine(const QString&, uint);
void slotCurrentChanged(QWidget*);
void slotClosePage(QWidget*);
void slotContextMenu(const QPoint&);
void slotContextMenu(QWidget*, const QPoint&);
};
#endif

@ -0,0 +1,62 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>QueryWidgetLayout</class>
<widget class="QWidget">
<property name="name">
<cstring>QueryWidgetLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>740</width>
<height>343</height>
</rect>
</property>
<property name="caption">
<string>Form2</string>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<widget class="TabWidget">
<property name="name">
<cstring>m_pQueryTabs</cstring>
</property>
</widget>
</hbox>
</widget>
<customwidgets>
<customwidget>
<class>TabWidget</class>
<header location="local">tabwidget.h</header>
<sizehint>
<width>-1</width>
<height>-1</height>
</sizehint>
<container>1</container>
<sizepolicy>
<hordata>7</hordata>
<verdata>7</verdata>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<pixmap>image0</pixmap>
</customwidget>
</customwidgets>
<images>
<image name="image0">
<data format="PNG" length="437">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000017c49444154388dad95db71c32010458f322e652966f3ef325031a68bf8df14c3f6e27c80c4338927e39df1182474b85c2ed2465f4fde53db76b4bcbf3e55af98414af79709c778b3815cfe9f8fc7576e39803b249afe1ff074e716c062bd76696716cd83a0519c2019dd444e66b8035ad12738a53ba274d0142146a6658a802a386d2ff6632e5d2fd5668c10430f3b56660621801a783fab9fc1add20255cdbf56d131698c45fd0ec49ef1d1f55c7df084fa19eab52a0d012c31d5a43859f554b5bf77dbcbbd62c1e17fb291322a86d367915ee90925a70707aeac70a578062faa854213b745ec7e061f2a0a6815b77dcf2a53d90b591ca2c96327d906b30c5505cae17192a118ec9ff5191508831d4b2b8e4d8b21abf23e5f1307b7db30d6b33cf6cb1cab56c5a1e4d53940eaf28f4a114c67bbbb77c5d926ab142939b5d967f5bdff63e2ceb79b08ecc332c5954db21a2971d9535c1fb331392718ca0691978cf16b9cda6169919c0efcce7ae980fca7b6a6fd56d5dbd07fdbc7f41bcb78aa0bdc5b1e190000000049454e44ae426082</data>
</image>
</images>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>tabwidget.h</includehint>
</includehints>
</UI>

@ -0,0 +1,82 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qlabel.h>
#include <qpushbutton.h>
#include <klocale.h>
#include "scanprogressdlg.h"
/**
* Class constructor.
* @param pParent The parent widget
* @param szName The widget's name
*/
ScanProgressDlg::ScanProgressDlg(QWidget* pParent, const char* szName) :
ScanProgressLayout(pParent, szName),
m_nFiles(0),
m_nCurFiles(0)
{
show();
// Emit the cancelled() signal when the "Cancel" button is clicked
connect(m_pCancelButton, SIGNAL(clicked()), this, SIGNAL(cancelled()));
}
/**
* Class destructor.
*/
ScanProgressDlg::~ScanProgressDlg()
{
}
/**
* Adds the given number of files to the total count of files already scanned.
* A visual indication of the progress is given in intervals of more than 100
* files (to prevent too-frequent GUI updates.)
* @param nFiles The number of files scanned since the last call
*/
void ScanProgressDlg::addFiles(int nFiles)
{
QString sText;
// Do nothing if no files were scanned
if (nFiles <= 0)
return;
// Update the total number of files scanned
m_nFiles += nFiles;
// Update progress only if more than 100 files were scanned since the last
// update
if ((m_nFiles - m_nCurFiles) > 100) {
sText.sprintf(i18n("Scanned %d files..."), m_nFiles);
m_pText->setText(sText);
m_nCurFiles = m_nFiles;
}
}
#include "scanprogressdlg.moc"

@ -0,0 +1,69 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef SCANPROGRESSDLG_H
#define SCANPROGRESSDLG_H
#include <qwidget.h>
#include <scanprogresslayout.h>
/**
* Displays the progress of a file scan operation.
* This dialogue is displayed while a ProjectFilesDlg dialogue scans a
* directory tree for all files matching the patterns defined for the
* project's source files.
* @author Elad Lahav
*/
class ScanProgressDlg : public ScanProgressLayout
{
Q_OBJECT
public:
ScanProgressDlg(QWidget* pParent = 0, const char* szName = 0);
~ScanProgressDlg();
void addFiles(int);
signals:
/**
* Indicates that the dialogue's "Cancel" button hsa been clicked by the
* user.
*/
void cancelled();
private:
/** The total number of files scanned thus far. */
int m_nFiles;
/** The number of files currently displayed in the progress report (which
may be smaller than m_nFiles since not every call to addFiles() updates
the progress display.)*/
int m_nCurFiles;
};
#endif

@ -0,0 +1,115 @@
<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
<class>ScanProgressLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>ScanProgressLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>198</width>
<height>103</height>
</rect>
</property>
<property name="caption">
<string>Scanning Directory</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout4</cstring>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>m_pText</cstring>
</property>
<property name="text">
<string>Scanned 0 files...</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer3</cstring>
</property>
<property name="orientation">
<enum>Vertical</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout2</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer2</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCancelButton</cstring>
</property>
<property name="text">
<string>Cancel</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer1</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</hbox>
</widget>
</vbox>
</widget>
</vbox>
</widget>
<layoutdefaults spacing="6" margin="11"/>
</UI>

@ -0,0 +1,270 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qheader.h>
#include "searchlist.h"
/**
* Intercepting additional key events of QLineEdit to browse the list
* @param pKey The pressed key event
*/
void SearchLineEdit::keyPressEvent(QKeyEvent* pKey)
{
switch(pKey->key()) {
case Qt::Key_Up:
case Qt::Key_Down:
case Qt::Key_PageUp:
case Qt::Key_PageDown:
emit keyPressed(pKey);
break;
default:
QLineEdit::keyPressEvent(pKey);
break;
}
}
/**
* Class constructor.
* @param pParent Owner list view widget
*/
ListToolTip::ListToolTip(SearchList* pParent) :
QToolTip(pParent->getList()->viewport()),
m_pList(pParent)
{
}
/**
* Displays a tool-tip according to the current location of the mouse
* pointer.
* @param pt The mouse pointer coordinates
*/
void ListToolTip::maybeTip(const QPoint& pt)
{
QString str;
QListView* pList;
QListViewItem* pItem;
// Get the item at the given point
pList = m_pList->getList();
pItem = pList->itemAt(pt);
if (pItem == NULL)
return;
// Get the tip string for this item
if (!m_pList->getTip(pItem, str))
return;
// Get the bounding rectangle of the item
const QRect rcItem = pList->itemRect(pItem);
if (!rcItem.isValid())
return;
// Get the header coordinates
const QRect rcHead = pList->header()->rect();
if (!rcHead.isValid())
return;
// Calculate the tool-tip rectangle
QRect rcCell(rcHead.left(), rcItem.top(), rcItem.width(), rcItem.height());
// Display the tool-tip
tip(rcCell, str);
}
/**
* Class constructor.
* @param nSearchCol The list column on which to perform string look-ups
* @param pParent The parent widget
* @param szName The widget's name
*/
SearchList::SearchList(int nSearchCol, QWidget* pParent, const char* szName) :
QVBox(pParent, szName),
m_nSearchCol(nSearchCol)
{
// Create the child widgets
m_pEdit = new SearchLineEdit(this);
m_pList = new QListView(this);
// Set up the tooltip generator
QToolTip::remove(m_pList);
m_pToolTip = new ListToolTip(this);
connect(m_pEdit, SIGNAL(textChanged(const QString&)), this,
SLOT(slotFindItem(const QString&)));
connect(m_pList, SIGNAL(doubleClicked(QListViewItem*)), this,
SLOT(slotItemSelected(QListViewItem*)));
connect(m_pList, SIGNAL(returnPressed(QListViewItem*)), this,
SLOT(slotItemSelected(QListViewItem*)));
connect(m_pEdit, SIGNAL(returnPressed()), this,
SLOT(slotItemSelected()));
connect(m_pEdit, SIGNAL(keyPressed(QKeyEvent*)), this,
SLOT(slotKeyPressed(QKeyEvent*)));
}
/**
* Class destructor.
*/
SearchList::~SearchList()
{
delete m_pToolTip;
}
/**
* Sets the keyboad focus to the search box.
*/
void SearchList::slotSetFocus()
{
m_pEdit->setFocus();
}
/**
* Selects a list item whose string begins with the text entered in the edit
* widget.
* This slot is connected to the textChanged() signal of the line edit widget.
* @param sText The new text in the edit widget
*/
void SearchList::slotFindItem(const QString& sText)
{
QListViewItem* pItem;
// Try to find an item that contains this text
// Priority to exactly matched,
// then try to find line begins with the text,
// and if not found, then try to find the line contains the text
pItem = m_pList->findItem(sText, m_nSearchCol,
ExactMatch | BeginsWith | Contains);
// Select this item
if (pItem != 0) {
m_pList->setSelected(pItem, true);
m_pList->ensureItemVisible(pItem);
}
}
/**
* Lets inheriting classes process an item selection made through the list
* widget.
* This slot is connected to the doubleClicked() and returnPressed()
* signals of the list widget.
*/
void SearchList::slotItemSelected(QListViewItem* pItem)
{
processItemSelected(pItem);
m_pEdit->setText("");
}
/**
* Lets inheriting classes process an item selection made through the edit
* widget.
* This slot is connected to the returnPressed() signal of the edit widget.
*/
void SearchList::slotItemSelected()
{
QListViewItem* pItem;
if ((pItem = m_pList->selectedItem()) != NULL) {
m_pEdit->setText(pItem->text(m_nSearchCol));
processItemSelected(pItem);
}
m_pEdit->setText("");
}
#define SEARCH_MATCH(pItem) \
pItem->text(m_nSearchCol).startsWith(m_pEdit->text())
/**
* Sets a new current item based on key events in the edit box.
* This slot is connected to the keyPressed() signal of the edit widget.
* @param pKey The key evant passed by the edit box
*/
void SearchList::slotKeyPressed(QKeyEvent* pKey)
{
QListViewItem* pItem, * pNewItem;
int nPageSize, nPos;
// Select the current item, or the first one if there is no current item
pItem = m_pList->currentItem();
// Set a new current item based on the pressed key
switch (pKey->key()) {
case Qt::Key_Up:
if (pItem) {
for (pNewItem = pItem->itemAbove();
pNewItem && !SEARCH_MATCH(pNewItem);
pNewItem = pNewItem->itemAbove());
if (pNewItem)
pItem = pNewItem;
}
break;
case Qt::Key_Down:
if (pItem) {
for (pNewItem = pItem->itemBelow();
pNewItem && !SEARCH_MATCH(pNewItem);
pNewItem = pNewItem->itemBelow());
if (pNewItem)
pItem = pNewItem;
}
break;
case Qt::Key_PageUp:
nPageSize = m_pList->visibleHeight() / pItem->height();
for (nPos = 0;
pItem && pItem->itemAbove() && (nPos < nPageSize);
nPos++)
pItem = pItem->itemAbove();
break;
case Qt::Key_PageDown:
nPageSize = m_pList->visibleHeight() / pItem->height();
for (nPos = 0;
pItem && pItem->itemBelow() && (nPos < nPageSize);
nPos++)
pItem = pItem->itemBelow();
break;
default:
pKey->ignore();
return;
}
// Select the first item if no other item was selected
if (pItem == NULL)
pItem = m_pList->firstChild();
// Select the new item
if (pItem) {
m_pList->setSelected(pItem, true);
m_pList->ensureItemVisible(pItem);
}
}
#include "searchlist.moc"

@ -0,0 +1,144 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef SEARCHLIST_H
#define SEARCHLIST_H
#include <qwidget.h>
#include <qvbox.h>
#include <qlineedit.h>
#include <qlistview.h>
#include <qtooltip.h>
class SearchList;
/**
* Defines a line text edit for searchable list view.
* The widget is based on QLineEdit with additional key functions
* Supported key events (up and down) are emitted as signals
* @author Albert Yosher
*/
class SearchLineEdit : public QLineEdit
{
Q_OBJECT
public:
SearchLineEdit(QWidget* pParent) : QLineEdit(pParent) {};
~SearchLineEdit() {};
signals:
/**
* Emitted when one of the up/down or page up/page down keys were pressed
* inside this edit widget.
* @param pEvent The event received for this key press
*/
void keyPressed(QKeyEvent* pEvent);
private:
virtual void keyPressEvent(QKeyEvent*);
};
/**
* A tool-tip class for the search list.
* Enables sub-classes of the list to provide a customised tool-tip for each
* list item.
* @author Gabor Fekete
*/
class ListToolTip : public QToolTip
{
public:
ListToolTip(SearchList* pParent);
protected:
virtual void maybeTip(const QPoint& pt);
private:
/** The owner widget. */
SearchList* m_pList;
};
/**
* Defines a searchable list view.
* The widget is composed of a list view, and an edit box used to enter
* search data. Whenever the text in the edit box changes, the list view is
* set to point to the first item that matches the new text.
* @author Elad Lahav
*/
class SearchList : public QVBox
{
Q_OBJECT
public:
SearchList(int nSearchCol, QWidget* pParent = 0, const char* szName = 0);
~SearchList();
/**
* @return A pointer to the list part of the widget.
*/
QListView* getList() { return m_pList; }
/**
* Constructs a tool-tip for the given item.
* @param pItem The item for which a tip is required
* @param sTip The constructed tip string (on return)
* @return True to display the tip, false otherwise
*/
virtual bool getTip(QListViewItem* pItem, QString& sTip) = 0;
public slots:
void slotSetFocus();
protected:
/** The search edit-box. */
QLineEdit* m_pEdit;
/** The list part of the widget. */
QListView* m_pList;
/**
* Called whenever the user selects an item in the list by either double-
* clicking it, or by highlighting the item and pressing the ENTER key.
* @param pItem The selected list item
*/
virtual void processItemSelected(QListViewItem* pItem) = 0;
protected slots:
void slotFindItem(const QString&);
void slotItemSelected(QListViewItem*);
void slotItemSelected();
void slotKeyPressed(QKeyEvent*);
private:
/** Specifies the search column, i.e., the list column whose strings are
compared with the text in the search edit-box. */
int m_nSearchCol;
/** A tool-tip for the list entries. */
ListToolTip* m_pToolTip;
};
#endif

@ -0,0 +1,160 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qpushbutton.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include <qradiobutton.h>
#include "searchresultsdlg.h"
int SearchResultsDlg::s_nType = PlainText;
bool SearchResultsDlg::s_bCaseSensitive = true;
bool SearchResultsDlg::s_bNegate = false;
/**
* Class constructor.
* @param pParent The parent widget
* @param szName Optional widget name
*/
SearchResultsDlg::SearchResultsDlg(QWidget* pParent, const char* szName) :
SearchResultsLayout(pParent, szName, true, 0)
{
// Select the last selected type radio button
switch (s_nType) {
case PlainText:
m_pTextRadio->setChecked(true);
break;
case RegExp:
m_pRegExpRadio->setChecked(true);
break;
case SimpRegExp:
m_pSimpRegExpRadio->setChecked(true);
break;
}
// Set the default value of the check-boxes
m_pCaseSenCheck->setChecked(s_bCaseSensitive);
m_pNegateCheck->setChecked(s_bNegate);
// Terminate the dialogue when either the "OK" or "Cancel" buttons are
// clicked
connect(m_pOKButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(reject()));
}
/**
* Class destructor.
*/
SearchResultsDlg::~SearchResultsDlg()
{
}
/**
* Determines the default column on which to search.
* The column's name appears in the column combo-box.
*/
void SearchResultsDlg::setColumn(int nCol)
{
m_pColumnCB->setCurrentItem(nCol);
}
/**
* @return The selected column on which to perform the search
*/
int SearchResultsDlg::getColumn()
{
return m_pColumnCB->currentItem();
}
/**
* Creates a regular expression based on the given pattern and type of search.
* @param re A regular expression object to set
*/
void SearchResultsDlg::getPattern(QRegExp& re)
{
QString sPattern;
sPattern = m_pSearchEdit->text();
// Create the regular expression
switch (s_nType) {
case PlainText:
re.setPattern(QRegExp::escape(sPattern));
re.setWildcard(false);
break;
case RegExp:
re.setPattern(sPattern);
re.setWildcard(false);
break;
case SimpRegExp:
re.setPattern(sPattern);
re.setWildcard(true);
break;
}
// Set the case-(in)sensitive parameter
re.setCaseSensitive(s_bCaseSensitive);
}
/**
* Reads user values from the widgets, and closes the dialogue.
* This slot is connected to the clicked() signal emitted by the "OK" button.
*/
void SearchResultsDlg::accept()
{
QString sText;
// Determine the selected type and store its value for the next invocation
if (m_pTextRadio->isChecked())
s_nType = PlainText;
else if (m_pRegExpRadio->isChecked())
s_nType = RegExp;
else if (m_pSimpRegExpRadio->isChecked())
s_nType = SimpRegExp;
// Determine search parameters
s_bCaseSensitive = m_pCaseSenCheck->isChecked();
s_bNegate = m_pNegateCheck->isChecked();
// Remove white space from the search text
sText = m_pSearchEdit->text();
sText.stripWhiteSpace();
if (sText.isEmpty()) {
QDialog::reject();
return;
}
// Close the dialogue
QDialog::accept();
}
#include "searchresultsdlg.moc"

@ -0,0 +1,74 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef SEARCHRESULTSDLG_H
#define SEARCHRESULTSDLG_H
#include <qregexp.h>
#include <qcheckbox.h>
#include "searchresultslayout.h"
/**
* A dialogue for defining searches on query results.
* The dialogue is activated from the query results menu.
* @author Elad Lahav
*/
class SearchResultsDlg : public SearchResultsLayout
{
Q_OBJECT
public:
SearchResultsDlg(QWidget* pParent = 0, const char* szName = 0);
~SearchResultsDlg();
void setColumn(int);
int getColumn();
void getPattern(QRegExp&);
/**
* @return true if the search pattern should be negated, false otherwise
*/
bool isNegated() { return m_pNegateCheck->isChecked(); }
protected slots:
virtual void accept();
private:
/** Possible search types. */
enum { PlainText = 0, RegExp, SimpRegExp };
/** Remembers the last search type. */
static int s_nType;
/** Remembers the last value of the Case Sensitive check-box. */
static bool s_bCaseSensitive;
/** Remembers the last value of the Negate Search check-box. */
static bool s_bNegate;
};
#endif

@ -0,0 +1,214 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>SearchResultsLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>SearchResultsLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>361</width>
<height>307</height>
</rect>
</property>
<property name="caption">
<string>Filter Query Results</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout2</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel2</cstring>
</property>
<property name="text">
<string>Search For:</string>
</property>
</widget>
<widget class="QLineEdit">
<property name="name">
<cstring>m_pSearchEdit</cstring>
</property>
</widget>
</hbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout4</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="text">
<string>Search In:</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer2</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>171</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="QComboBox">
<item>
<property name="text">
<string>Function</string>
</property>
</item>
<item>
<property name="text">
<string>File</string>
</property>
</item>
<item>
<property name="text">
<string>Line</string>
</property>
</item>
<item>
<property name="text">
<string>Text</string>
</property>
</item>
<property name="name">
<cstring>m_pColumnCB</cstring>
</property>
</widget>
</hbox>
</widget>
<widget class="QButtonGroup">
<property name="name">
<cstring>buttonGroup1</cstring>
</property>
<property name="title">
<string>Search Type</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QRadioButton">
<property name="name">
<cstring>m_pTextRadio</cstring>
</property>
<property name="text">
<string>Plain Text</string>
</property>
</widget>
<widget class="QRadioButton">
<property name="name">
<cstring>m_pRegExpRadio</cstring>
</property>
<property name="text">
<string>RegE&amp;xp</string>
</property>
</widget>
<widget class="QRadioButton">
<property name="name">
<cstring>m_pSimpRegExpRadio</cstring>
</property>
<property name="text">
<string>Simplified RegExp</string>
</property>
</widget>
</vbox>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pCaseSenCheck</cstring>
</property>
<property name="text">
<string>Case Sensitive</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pNegateCheck</cstring>
</property>
<property name="text">
<string>Negate Search</string>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout3</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer1</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>201</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pOKButton</cstring>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCancelButton</cstring>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<tabstops>
<tabstop>m_pSearchEdit</tabstop>
<tabstop>m_pColumnCB</tabstop>
<tabstop>m_pTextRadio</tabstop>
<tabstop>m_pRegExpRadio</tabstop>
<tabstop>m_pSimpRegExpRadio</tabstop>
<tabstop>m_pCaseSenCheck</tabstop>
<tabstop>m_pOKButton</tabstop>
<tabstop>m_pCancelButton</tabstop>
</tabstops>
<layoutdefaults spacing="6" margin="11"/>
</UI>

@ -0,0 +1,344 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qtimer.h>
#include <klocale.h>
#include "symbolcompletion.h"
bool SymbolCompletion::s_bACEnabled;
uint SymbolCompletion::s_nACMinChars;
uint SymbolCompletion::s_nACDelay;
uint SymbolCompletion::s_nACMaxEntries;
/**
* Class constructor.
* @param pEditor The editor object for which symbol completion is required
* @param pParent Parent object
* @param szName Optional object name
*/
SymbolCompletion::SymbolCompletion(SymbolCompletion::Interface* pEditor,
QObject* pParent, const char* szName) :
QObject(pParent, szName),
m_pEditor(pEditor),
m_pCCObject(NULL)
{
// Initialise member objects
m_pCscope = new CscopeFrontend();
m_pAutoCompTimer = new QTimer(this);
// Add entries to the completion list when they are available
connect(m_pCscope, SIGNAL(dataReady(FrontendToken*)), this,
SLOT(slotAddEntry(FrontendToken*)));
// Show the completion list when the query finishes
connect(m_pCscope, SIGNAL(finished(uint)), this,
SLOT(slotQueryFinished(uint)));
// Initiate automatic symbol completion when timer expires
connect(m_pAutoCompTimer, SIGNAL(timeout()), this,
SLOT(slotAutoCompleteTimeout()));
}
/**
* Class destructor.
*/
SymbolCompletion::~SymbolCompletion()
{
delete m_pCscope;
}
/**
* Stops a completion process.
* This includes killing a running query, and stoping the auto-completion
* timer.
*/
void SymbolCompletion::abort()
{
if (m_pCscope->isRunning())
m_pCscope->kill();
m_pAutoCompTimer->stop();
}
/**
* Configures auto-completion parameters.
* @param bEnabled true to enable auto-completion, false otherwise
* @param nMinChars Minimal number of characters a symbol needs to start
* auto-completion
* @param nDelay Auto-completion time interval (in milliseconds)
* @param nMaxEntries The maximal number of completion entries
*/
void SymbolCompletion::initAutoCompletion(bool bEnabled, uint nMinChars,
uint nDelay, uint nMaxEntries)
{
s_bACEnabled = bEnabled;
s_nACMinChars = nMinChars;
s_nACDelay = nDelay;
s_nACMaxEntries = nMaxEntries;
}
/**
* Starts a completion process immediately for the symbol currently under the
* cursor in the editor object.
* Symbol completion is only available if the cursor is positioned at the end
* of the symbol.
*/
void SymbolCompletion::slotComplete()
{
QString sSymbol;
uint nPosInWord;
// Read the symbol currently under the cursor
sSymbol = m_pEditor->getWordUnderCursor(&nPosInWord);
// The completion was triggered by user
m_bAutoCompletion = false;
// start completion process, prefix is only on the left from the cursor
complete(sSymbol.left(nPosInWord));
}
/**
* Initiates an auto-completion timer.
* When the timer times-out, is starts the symbol completion process.
*/
void SymbolCompletion::slotAutoComplete()
{
if (s_bACEnabled)
m_pAutoCompTimer->start(s_nACDelay, true);
}
/**
* Creates a list of possible completions to the symbol currently being
* edited.
* @param sPrefix The symbol to complete
* @param nMaxEntries The maximal number of entries to display
*/
void SymbolCompletion::complete(const QString& sPrefix, int nMaxEntries)
{
// Create a regular expression to extract symbol names from the query
// results
m_reSymbol.setPattern(sPrefix + "[a-zA-Z0-9_]*");
// If the new prefix is itself a prefix of the old one, we only need to
// filter the current entries
if (!m_sPrefix.isEmpty() && sPrefix.startsWith(m_sPrefix)) {
filterEntries();
m_sPrefix = sPrefix;
slotQueryFinished(0);
return;
}
// Prepare member variables
m_sPrefix = sPrefix;
m_nMaxEntries = nMaxEntries;
m_elEntries.clear();
// Run the code-completion query
m_pCscope->query(CscopeFrontend::Definition, sPrefix + ".*");
}
/**
* Removes from the current completion list all symbols that do not match
* the current regular expression.
* This function is used to aviod requerying the database on certain
* situations.
*/
void SymbolCompletion::filterEntries()
{
EntryList::Iterator itr;
// Iterate over the list and check each entry against the current RE
for (itr = m_elEntries.begin(); itr != m_elEntries.end();) {
if (m_reSymbol.search((*itr).text) == -1)
itr = m_elEntries.erase(itr);
else
++itr;
}
}
/**
* Conevrts the completion list into a single-entry one, containing the given
* message.
* @param sMsg The text of the message to include in the list.
*/
void SymbolCompletion::makeErrMsg(const QString& sMsg)
{
Entry entry;
// Clear the current list
m_elEntries.clear();
// Create the message item and add it to the list
entry.text = sMsg;
entry.userdata = "NO_INSERT"; // The message should not be insertable
m_elEntries.append(entry);
// Make sure a new completion request will start a new query
m_sPrefix = "";
}
/**
* Creates a new entry in the list when a query record is available.
* This slot is connected to the dataReady() signal of the CscopeFrontend
* object.
* @param pToken Points to the head of a record's linked-list
*/
void SymbolCompletion::slotAddEntry(FrontendToken* pToken)
{
Entry entry;
QString sText;
// Do not add entries beyond the requested limit
if (m_elEntries.count() > m_nMaxEntries)
return;
// Get the line text
pToken = pToken->getNext()->getNext()->getNext();
sText = pToken->getData();
// Find the symbol within the line
if (m_reSymbol.search(sText) == -1)
return;
// Add the new entry to the completion list
entry.text = m_reSymbol.capturedTexts().first();
entry.userdata = "";
entry.comment = sText;
m_elEntries.append(entry);
}
/**
* Displays a code completion list, based on the results of the last query.
* @param nRecords (ingnored)
*/
void SymbolCompletion::slotQueryFinished(uint /* nRecords */)
{
KTextEditor::CodeCompletionInterface* pCCI;
uint nEntryCount;
EntryList::Iterator itr;
QString sPrevText;
// Get the number of entries
nEntryCount = m_elEntries.count();
// Do not show the box the only completion option is the prefix itself
if (m_bAutoCompletion && (nEntryCount == 1) &&
(m_elEntries.first().text == m_sPrefix)) {
return;
}
// Get a pointer to the CC interface
m_pCCObject = m_pEditor->getCCObject();
pCCI = dynamic_cast<KTextEditor::CodeCompletionInterface*>(m_pCCObject);
if (!pCCI)
return;
// Insert the correct part of the completed symbol, when chosen by the
// user
connect(m_pCCObject,
SIGNAL(filterInsertString(KTextEditor::CompletionEntry*, QString*)),
this,
SLOT(slotFilterInsert(KTextEditor::CompletionEntry*, QString*)));
// Check the number of entries in the list
if (nEntryCount == 0) {
// No completion options, display an appropriate message
makeErrMsg(i18n("No matching completion found..."));
}
else if (nEntryCount > m_nMaxEntries) {
// The query has resulted in too many entries, display an
// appropriate message
makeErrMsg(i18n("Too many options..."));
}
else {
// Sort the entries
m_elEntries.sort();
// Make sure entries are unique
for (itr = m_elEntries.begin(); itr != m_elEntries.end();) {
if ((*itr).text == sPrevText) {
itr = m_elEntries.erase(itr);
}
else {
sPrevText = (*itr).text;
++itr;
}
}
}
// Display the completion list
pCCI->showCompletionBox(m_elEntries);
}
/**
* Determines which part of the completion entry should be added to the code
* when that entry is selected.
* @param pEntry Points to the selected entry
* @param pTextToInsert Contains the string to insert, upon return
*/
void SymbolCompletion::slotFilterInsert(KTextEditor::CompletionEntry* pEntry,
QString* pTextToInsert)
{
// Insert the completed entry, unless it contains an error message
if (pEntry->userdata.isEmpty())
*pTextToInsert = pEntry->text.mid(m_sPrefix.length());
else
*pTextToInsert = "";
// Disconnect the CC object signals
disconnect(m_pCCObject, 0, this, 0);
m_pCCObject = NULL;
}
/**
* Checks if the current symbol is eligible for auto-completion, and if so,
* starts the completion process.
* Auto-completion is performed for symbols that have the required minimal
* number of entries, and the cursor is positioned at the end of the word.
* This slot is connected to the timeout() signal of the auto-completion
* timer.
*/
void SymbolCompletion::slotAutoCompleteTimeout()
{
QString sPrefix;
uint nPosInWord, nLength;
// Read the symbol currently under the cursor
sPrefix = m_pEditor->getWordUnderCursor(&nPosInWord);
nLength = sPrefix.length();
// Check conditions, and start the completion process
if ((nLength >= s_nACMinChars) && (nPosInWord == nLength)) {
// The completion was triggered by auto-completion
m_bAutoCompletion = true;
complete(sPrefix, s_nACMaxEntries);
}
}
#include "symbolcompletion.moc"

@ -0,0 +1,195 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef SYMBOLCOMPLETION_H
#define SYMBOLCOMPLETION_H
#include <qobject.h>
#include <qregexp.h>
#include <ktexteditor/codecompletioninterface.h>
#include <ktexteditor/view.h>
#include "cscopefrontend.h"
/**
* This class executes symbol definition queries based on symbol prefixes.
* The results can then be displayed as symbol completion lists.
* @author Albert Yosher
*/
class SymbolCompletion : public QObject
{
Q_OBJECT
public:
/**
* A pure-virtual class that allows a SymbolCompletion object access to
* text-editing objects.
* Classes that wish to utilise SymbolCompletion need to inplement this
* interface.
* @author Albert Yosher
*/
struct Interface
{
/**
* Class destructor.
* NOTE: A virtual destructor is required by GCC 4.0
*/
virtual ~Interface() {}
/**
* Returns the word currently under the editing cursor.
* Symbol completion will be provided for this word only if the cursor
* is positioned at the end of this word.
* @param pPosInWord Set this value to the offset in the word on
* which the cursor is positioned
*/
virtual QString getWordUnderCursor(uint* pPosInWord) = 0;
/**
* Returns a target object for displaying the completion list.
* @return A pointer to an object implementing
* KTextEditor::CodeCompletionInterface, or NULL if the
* implementation does not support this interface.
*/
virtual QObject* getCCObject() = 0;
};
SymbolCompletion(SymbolCompletion::Interface*, QObject* pParent = 0,
const char* szName = 0);
~SymbolCompletion();
void abort();
static void initAutoCompletion(bool, uint, uint, uint);
public slots:
void slotComplete();
void slotAutoComplete();
private:
/**
* Symbol completion entry object, used in the completion list.
* Implements operators required for sorting the completion list.
* @author Albert Yosher
*/
class Entry : public KTextEditor::CompletionEntry
{
public:
/**
* Determines whether a given entry is smaller than this one.
* @param entry The entry to compare with
* @return true if the given entry is smaller, false otherwise
*/
bool operator < (const SymbolCompletion::Entry& entry) const {
return (text < entry.text);
}
/**
* Determines whether a given entry is equal to this one.
* @param entry The entry to compare with
* @return true if the given entry equals this one, false otherwise
*/
bool operator == (const SymbolCompletion::Entry& entry) const {
return (text == entry.text);
}
};
/**
* A sortable version of the value list used by CodeCompletionInterface.
* @author Albert Yosher
*/
class EntryList : public QValueList<Entry>
{
public:
/**
* Sorts completion list.
*/
void sort() { qHeapSort(*this); }
/**
* Type casting support required for calling showCompletionBox().
* @return A casted reference to this object
*/
operator QValueList<KTextEditor::CompletionEntry>()
{ return *(QValueList<KTextEditor::CompletionEntry>*)this; }
};
/** Editor object for which symbol completion is provided. */
Interface* m_pEditor;
/** An object that supports KTextEditor::CodeCompletionInterface, as
supplied by the editor. */
QObject* m_pCCObject;
/** Cscope process used to run completion queries. */
CscopeFrontend* m_pCscope;
/** The prefix used for the current query. */
QString m_sPrefix;
/** A list of possible completions for the given prefix. */
EntryList m_elEntries;
/** The maximal number of completions to accept. */
uint m_nMaxEntries;
/** Regular expression for extracting a symbol out of Cscope's text field.
NOTE: This member is required due to a bug in Cscope that renders the
symbol field useless. */
QRegExp m_reSymbol;
/** Auto-completion timer. */
QTimer* m_pAutoCompTimer;
/** Auto-completion flag */
bool m_bAutoCompletion;
void complete(const QString&, int nMaxEntries = 1000);
void filterEntries();
void makeErrMsg(const QString&);
/** true if auto-completion is enabled, false otherwise. */
static bool s_bACEnabled;
/** The minimum number of characters a symbol must have for
auto-completion. */
static uint s_nACMinChars;
/** The interval between the time slotAutoComplete() is called and the
time the completion process begins (in milliseconds). */
static uint s_nACDelay;
/** The maximal number of entries for auto-completion. */
static uint s_nACMaxEntries;
private slots:
void slotAutoCompleteTimeout();
void slotAddEntry(FrontendToken*);
void slotQueryFinished(uint);
void slotFilterInsert(KTextEditor::CompletionEntry*, QString*);
};
#endif

@ -0,0 +1,334 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qlabel.h>
#include <qlistview.h>
#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <kcombobox.h>
#include <klocale.h>
#include "symboldlg.h"
#include "cscopefrontend.h"
#include "kscopeconfig.h"
QStringList SymbolDlg::s_slHistory;
/**
* Class constructor.
* @param pParent Parent widget
* @param szName This widget's name
*/
SymbolDlg::SymbolDlg(QWidget* pParent, const char* szName) :
SymbolLayout(pParent, szName, true, 0),
m_progress(m_pHintList)
{
// Create a persistent Cscope process
m_pCscope = new CscopeFrontend();
// Initialise the hint list (hidden by default)
m_pHintList->addColumn(i18n("Suggested Symbols"));
m_pHintList->hide();
((QWidget*)m_pHintGroup)->hide();
m_pBeginWithRadio->toggle();
adjustSize();
// Close the dialogue when either the "OK" or "Cancel" button are clicked
connect(m_pOKButton, SIGNAL(clicked()), this, SLOT(accept()));
connect(m_pCancelButton, SIGNAL(clicked()), this, SLOT(reject()));
// Run a symbol completion query when the "Hint" button is clicked
connect(m_pHintButton, SIGNAL(clicked()), this, SLOT(slotHintClicked()));
// Add results to the hint list
connect(m_pCscope, SIGNAL(dataReady(FrontendToken*)), this,
SLOT(slotHintDataReady(FrontendToken*)));
// Set hint button availability based on the type of query
connect(m_pTypeCombo, SIGNAL(activated(int)), this,
SLOT(slotTypeChanged(int)));
// Selecting an item in the hint list sets it as the current text
connect(m_pHintList, SIGNAL(selectionChanged(QListViewItem*)), this,
SLOT(slotHintItemSelected(QListViewItem*)));
// Double-clicking an item in the hint list accepts that item as the
// result of the query (i.e., the item is selcted and the dialogue is
// closed)
connect(m_pHintList, SIGNAL(doubleClicked(QListViewItem*)), this,
SLOT(accept()));
// Refresh the hint list when the hint options change
connect(m_pBeginWithRadio, SIGNAL(toggled(bool)), this,
SLOT(slotHintOptionChanged(bool)));
connect(m_pContainRadio, SIGNAL(toggled(bool)), this,
SLOT(slotHintOptionChanged(bool)));
// Show hint query progress information
connect(m_pCscope, SIGNAL(progress(int, int)), this,
SLOT(slotHintProgress(int, int)));
connect(m_pCscope, SIGNAL(finished(uint)), this,
SLOT(slotHintFinished(uint)));
}
/**
* Class destructor.
*/
SymbolDlg::~SymbolDlg()
{
delete m_pCscope;
}
/**
* Displays the requested type of query in the type combo-box.
* @param nType The requested type
*/
void SymbolDlg::setType(uint nType)
{
m_pTypeCombo->setCurrentItem(nType);
slotTypeChanged(nType);
}
/**
* @param sSymbol The initial text of the combo-box
*/
void SymbolDlg::setSymbol(const QString& sSymbol)
{
m_pSymbolHC->setCurrentText(sSymbol);
}
/**
* @param slSymHistory A list of previously queried symbols
*/
void SymbolDlg::setHistory(QStringList& slSymHistory)
{
m_pSymbolHC->setHistoryItems(slSymHistory);
}
/**
* @return The current text of the symbol combo-box
*/
QString SymbolDlg::getSymbol() const
{
QString sResult;
sResult = m_pSymbolHC->currentText().stripWhiteSpace();
if (m_pSubStringCheck->isChecked())
sResult = ".*" + sResult + ".*";
return sResult;
}
/**
* @return The type of query requested by the user
* @note The returned value does not conform to the type used for running
* Cscope queries. Use getQueryType() to translate between these
* values.
*/
uint SymbolDlg::getType() const
{
return m_pTypeCombo->currentItem();
}
bool SymbolDlg::getCase() const
{
return !m_pCaseCheck->isChecked();
}
/**
* A convinience static function for creating and showing SymbolDlg dialogue.
* @param pParent The parent widget
* @param nType The type of query requested by the user (may be
* changed in the dialogue)
* @param sSymbol The initial text of the combo-box
* @return The text entered by the user in the symbol combo-box, or an empty
* string if the dialogue was cancelled
*/
QString SymbolDlg::promptSymbol(QWidget* pParent, uint& nType,
const QString& sSymbol, bool& bCase)
{
SymbolDlg dlg(pParent);
// Initialise the dialogue
dlg.setType(nType);
dlg.setHistory(s_slHistory);
dlg.setSymbol(sSymbol);
// Display the dialogue
if (dlg.exec() != QDialog::Accepted)
return "";
// Return the text entered by the user
nType = dlg.getType();
bCase = dlg.getCase();
dlg.m_pSymbolHC->addToHistory(dlg.getSymbol());
s_slHistory = dlg.m_pSymbolHC->historyItems();
return dlg.getSymbol();
}
/**
* Translates a symbol dialogue type into a Cscope query type.
* @param nType The type to translate
* @return A query type matching the symbol dialogue type
*/
uint SymbolDlg::getQueryType(uint nType)
{
if (nType == CallTree)
return CscopeFrontend::None;
if (nType <= Text)
return nType;
return nType + 1;
}
/**
* Runs a symbol definition query, looking for symbols starting with the
* currently entered text.
* If the hint list is not visible, it is shown first.
* This slot is connected to the clicked() signal of the "Hint" button.
*/
void SymbolDlg::slotHintClicked()
{
QString sText, sRegExp;
// Show the hint list if necessary
if (!m_pHintList->isVisible()) {
m_pHintList->show();
((QWidget*)m_pHintGroup)->show();
adjustSize();
}
// Clear the previous contents
m_pHintList->clear();
// Get the currently entered text (must have at least one character)
sText = m_pSymbolHC->currentText().stripWhiteSpace();
if (sText.isEmpty())
return;
// Create the regular expression
if (m_pBeginWithRadio->isOn())
sRegExp = sText + "[a-zA-Z0-9_]*";
else
sRegExp = "[a-zA-Z0-9_]*" + sText + "[a-zA-Z0-9_]*";
m_reHint.setPattern(sRegExp);
// Run a Cscope symbol definition query using a regular expression
m_pCscope->query(CscopeFrontend::Definition, sRegExp);
}
/**
* Called when a new record is ready to be added to the hint list.
* NOTE: Cscope 15.5 has a bug where the "function" field of the record
* displays the regular expression instead of the matched symbol name. For
* this reason, we need to extract the symbol from the "Text" field.
* @param pToken The head of the record's token list
*/
void SymbolDlg::slotHintDataReady(FrontendToken* pToken)
{
QString sText;
// Get the line text
pToken = pToken->getNext()->getNext()->getNext();
sText = pToken->getData();
// Find the symbol within the line
if (m_reHint.search(sText) == -1)
return;
// Find the symbol within the list, if found - do not add
if (m_pHintList->findItem(m_reHint.capturedTexts().first(), 0))
return;
// Add a list item
(void)new QListViewItem(m_pHintList, m_reHint.capturedTexts().first());
}
/**
* Sets the text of a selected hint list item as the current text of the
* symbol combo-box.
* This slot is connected to the doubleClicked() signal of the hint list-view.
* @param pItem The clicked list item
*/
void SymbolDlg::slotHintItemSelected(QListViewItem* pItem)
{
m_pSymbolHC->setCurrentText(pItem->text(0));
}
/**
* Refreshes the hint list based on the newly selected option.
* This slot is connected to the toggled() signal of the hint options radio
* buttons.
* NOTE: The list is only refreshed if the system profile is set to Fast.
* @param bOn true if the button was toggled on
*/
void SymbolDlg::slotHintOptionChanged(bool bOn)
{
if (bOn && Config().getSysProfile() == KScopeConfig::Fast)
slotHintClicked();
}
/**
* Display a progress bar while the hint query is working.
* This slot is connected to the progress() signal emitted by the Cscope
* frontend object.
* @param nProgress Progress value
* @param nTotal The final expected value
*/
void SymbolDlg::slotHintProgress(int nProgress, int nTotal)
{
m_progress.setProgress(nProgress, nTotal);
}
/**
* Destroys all progress information widget when the query process terminates.
* This slot is connected to the finished() signal emitted by the Cscope
* process.
*/
void SymbolDlg::slotHintFinished(uint /* ignored */)
{
m_progress.finished();
}
/**
* Enables/disables the hint button, based on the newly selected type.
* This slot is connected to the activated() signal of the type combo-box.
* @param nType The newly selected type
*/
void SymbolDlg::slotTypeChanged(int nType)
{
if (nType == FileName || nType == Including)
m_pHintButton->setEnabled(false);
else
m_pHintButton->setEnabled(true);
}
#include "symboldlg.moc"

@ -0,0 +1,91 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef SYMBOLDLG_H
#define SYMBOLDLG_H
#include <qregexp.h>
#include "symbollayout.h"
#include "cscopefrontend.h"
/**
* A dialogue that prompts the user for the text of a query.
* When a query is requested, the user needs to fill in the required
* information (usually a symbol name). This dialogue allows the user to
* enter this information, as well as complete a symbol name, and use
* previously entered text.
* @author Elad Lahav
*/
class SymbolDlg : public SymbolLayout
{
Q_OBJECT
public:
SymbolDlg(QWidget* pParent = 0, const char* szName = 0);
~SymbolDlg();
enum { Reference = 0, Definition, Called, Calling, Text, Pattern,
FileName, Including, CallTree };
void setType(uint);
void setSymbol(const QString&);
void setHistory(QStringList&);
QString getSymbol() const;
uint getType() const;
bool getCase() const;
static QString promptSymbol(QWidget*, uint&, const QString&, bool&);
static uint getQueryType(uint);
static void resetHistory() { s_slHistory.clear(); }
private:
/** A cscope process used for symbol completion. */
CscopeFrontend* m_pCscope;
/** A regular expression for extracting the symbol name out of the text
token of a Cscope record.
@see note in slotHintDataReady(). */
QRegExp m_reHint;
/** Displays query progress information. */
CscopeProgress m_progress;
static QStringList s_slHistory;
private slots:
void slotHintClicked();
void slotHintDataReady(FrontendToken*);
void slotHintItemSelected(QListViewItem*);
void slotHintOptionChanged(bool);
void slotHintProgress(int, int);
void slotHintFinished(uint);
void slotTypeChanged(int);
};
#endif

@ -0,0 +1,297 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>SymbolLayout</class>
<widget class="QDialog">
<property name="name">
<cstring>SymbolLayout</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>343</width>
<height>456</height>
</rect>
</property>
<property name="caption">
<string>KScope Query</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout15</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout14</cstring>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QLabel">
<property name="name">
<cstring>textLabel1</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>5</hsizetype>
<vsizetype>5</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Type</string>
</property>
</widget>
<widget class="QLabel">
<property name="name">
<cstring>textLabel2</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>5</hsizetype>
<vsizetype>5</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Symbol</string>
</property>
</widget>
</vbox>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout13</cstring>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QComboBox">
<item>
<property name="text">
<string>References to</string>
</property>
</item>
<item>
<property name="text">
<string>Definition of</string>
</property>
</item>
<item>
<property name="text">
<string>Functions called by</string>
</property>
</item>
<item>
<property name="text">
<string>Functions calling</string>
</property>
</item>
<item>
<property name="text">
<string>Find text</string>
</property>
</item>
<item>
<property name="text">
<string>Find EGrep pattern</string>
</property>
</item>
<item>
<property name="text">
<string>Find file</string>
</property>
</item>
<item>
<property name="text">
<string>Files #including</string>
</property>
</item>
<item>
<property name="text">
<string>Call graph for</string>
</property>
</item>
<property name="name">
<cstring>m_pTypeCombo</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
<widget class="KHistoryCombo">
<property name="name">
<cstring>m_pSymbolHC</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="insertionPolicy">
<enum>AtTop</enum>
</property>
<property name="duplicatesEnabled">
<bool>false</bool>
</property>
</widget>
</vbox>
</widget>
</hbox>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pSubStringCheck</cstring>
</property>
<property name="text">
<string>Search for &amp;a Sub-String</string>
</property>
<property name="accel">
<string>Alt+A</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
<cstring>m_pCaseCheck</cstring>
</property>
<property name="text">
<string>Case Insensitive</string>
</property>
</widget>
<widget class="Line">
<property name="name">
<cstring>line2</cstring>
</property>
<property name="frameShape">
<enum>HLine</enum>
</property>
<property name="frameShadow">
<enum>Sunken</enum>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout3</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer2</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>71</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pOKButton</cstring>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pHintButton</cstring>
</property>
<property name="text">
<string>Hi&amp;nt</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCancelButton</cstring>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</hbox>
</widget>
<widget class="QListView">
<property name="name">
<cstring>m_pHintList</cstring>
</property>
</widget>
<widget class="QButtonGroup">
<property name="name">
<cstring>m_pHintGroup</cstring>
</property>
<property name="title">
<string>Hint Options</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QRadioButton">
<property name="name">
<cstring>m_pBeginWithRadio</cstring>
</property>
<property name="text">
<string>S&amp;ymbols Beginning With...</string>
</property>
</widget>
<widget class="QRadioButton">
<property name="name">
<cstring>m_pContainRadio</cstring>
</property>
<property name="text">
<string>Sym&amp;bols Containing...</string>
</property>
</widget>
</vbox>
</widget>
</vbox>
</widget>
<tabstops>
<tabstop>m_pSymbolHC</tabstop>
<tabstop>m_pTypeCombo</tabstop>
<tabstop>m_pSubStringCheck</tabstop>
<tabstop>m_pOKButton</tabstop>
<tabstop>m_pHintButton</tabstop>
<tabstop>m_pCancelButton</tabstop>
<tabstop>m_pHintList</tabstop>
<tabstop>m_pBeginWithRadio</tabstop>
<tabstop>m_pContainRadio</tabstop>
</tabstops>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>kcombobox.h</includehint>
<includehint>klineedit.h</includehint>
</includehints>
</UI>

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

@ -0,0 +1,84 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include <qtooltip.h>
#include <klocale.h>
#include "tabwidget.h"
#include "kscopepixmaps.h"
/**
* Class constructor.
* @param pParent A pointer to the parent widget
* @param szName Optional widget name
*/
TabWidget::TabWidget(QWidget* pParent, const char* szName) :
KTabWidget(pParent, szName)
{
// Create a popup menu
m_pMenu = new QPopupMenu(this);
// Set the current tab based on the menu selection
connect(m_pMenu, SIGNAL(activated(int)), this, SLOT(setCurrentPage(int)));
// Create a button at the top-right corner of the tab widget
m_pButton = new QToolButton(this);
m_pButton->setIconSet(Pixmaps().getPixmap(KScopePixmaps::TabList));
QToolTip::add(m_pButton, i18n("Shows a list of all open tabs"));
m_pButton->adjustSize();
setCornerWidget(m_pButton, TopRight);
// Show the popup-menu when the button is clicked
connect(m_pButton, SIGNAL(clicked()), this, SLOT(slotShowTabList()));
}
/**
* Class destructor.
*/
TabWidget::~TabWidget()
{
}
/**
* Creates and displays a popup-menu containing all tab labels.
* This slot is connected to the clicked() signal emitted by the list button.
*/
void TabWidget::slotShowTabList()
{
int i;
// Delete the previous menu
m_pMenu->clear();
// Create and populate the menu
for (i = 0; i < count(); i++)
m_pMenu->insertItem(label(i), i);
// Show the menu
m_pMenu->popup(mapToGlobal(m_pButton->pos()));
}
#include "tabwidget.moc"

@ -0,0 +1,59 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef TABWIDGET_H
#define TABWIDGET_H
#include <qtoolbutton.h>
#include <qpopupmenu.h>
#include <ktabwidget.h>
/**
* An extension to the standard KDE tab widget that allows the user to select
* a tab from a list displayed as a popup menu.
* @author Elad Lahav
*/
class TabWidget : public KTabWidget
{
Q_OBJECT
public:
TabWidget(QWidget* pParent = 0, const char* szName = 0);
~TabWidget();
private:
/** The list button. */
QToolButton* m_pButton;
/** A popup-menu containing all tab labels. */
QPopupMenu* m_pMenu;
private slots:
void slotShowTabList();
};
#endif

@ -0,0 +1,260 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#include "treewidget.h"
#include "queryviewdriver.h"
/**
* Class constructor.
* @param pParent Parent widget
* @param szName The name of the widget
*/
TreeWidget::TreeWidget(QWidget* pParent, const char* szName) :
QueryView(pParent, szName),
m_nQueryType(CscopeFrontend::Called)
{
setRootIsDecorated(true);
// Create a driver object
m_pDriver = new QueryViewDriver(this, this);
// Query a tree item when it is expanded for the first time
connect(this, SIGNAL(expanded(QListViewItem*)), this,
SLOT(slotQueryItem(QListViewItem*)));
}
/**
* Class destructor.
*/
TreeWidget::~TreeWidget()
{
}
/**
* Determines the mode of the tree.
* @param mode The new mode (@see Mode)
*/
void TreeWidget::setMode(Mode mode)
{
m_nQueryType = (mode == Called) ? CscopeFrontend::Called :
CscopeFrontend::Calling;
}
/**
* Sets a new root item for the tree.
* @param sFunc The name of the function to serve as root
*/
void TreeWidget::setRoot(const QString& sFunc)
{
QListViewItem* pRoot;
// Remove the current root, if any
if ((pRoot = firstChild()) != NULL)
delete pRoot;
// Create a new root item
pRoot = new QListViewItem(this, sFunc);
pRoot->setExpandable(true);
}
/**
* Runs a query on the root item.
*/
void TreeWidget::queryRoot()
{
QListViewItem* pRoot;
if ((pRoot = firstChild()) != NULL)
slotQueryItem(pRoot);
}
/**
* Stores the tree contents in the given file.
* @param pFile An open file to write to
*/
void TreeWidget::save(FILE* pFile)
{
QTextStream str(pFile, IO_WriteOnly);
QListViewItem* pRoot;
Encoder enc;
if (m_nQueryType == CscopeFrontend::Called)
str << "calltree {" << endl;
else
str << "callingtree {" << endl;
// Write the tree to the file
pRoot = firstChild();
str << pRoot->text(0) << endl;
str << '{' << endl;
saveItems(pRoot->firstChild(), str, enc);
str << '}' << endl;
str << '}' << endl;
}
/**
* Recursively writes tree items to a file.
* Given an item, the method writes this item and all of its siblings.
* Child items are written recursively.
* @param pItem The first item to write
* @param str An initialised text stream to use for writing
* @param enc An encoder for free-text strings
*/
void TreeWidget::saveItems(QListViewItem* pItem, QTextStream& str, Encoder& enc)
{
// Iterate over all items in this level
for (; pItem != NULL; pItem = pItem->nextSibling()) {
// Write function parameters
str << pItem->text(0) << " [ "
<< "kscope_file=\"" << pItem->text(1) << "\", "
<< "kscope_line=" << pItem->text(2) << ", "
<< "kscope_text=\"" << enc.encode(pItem->text(3)) << "\""
<< "]" << endl;
// Write child items
str << "{" << endl;
saveItems(pItem->firstChild(), str, enc);
str << "}" << endl;
}
}
/**
* Creates a new tree item showing a query result record.
* @param sFunc The name of the function
* @param sFile The file path
* @param sLine The line number in the above file
* @param sText The line's text
* @param pParent The parent for the new item
*/
void TreeWidget::addRecord(const QString& sFunc, const QString& sFile,
const QString& sLine, const QString& sText, QListViewItem* pParent)
{
QListViewItem* pItem;
pItem = new QueryViewItem(pParent, m_pLastItem, 2);
pItem->setText(0, sFunc);
pItem->setText(1, sFile);
pItem->setText(2, sLine);
pItem->setText(3, sText);
pItem->setExpandable(true);
m_pLastItem = pItem;
}
/**
* Called when a query running on the tree terminates.
* If there were no results, the item becomes non-expandable.
* NOTE: On top of its current behaviour, this function is required in order to
* override the default behaviour, as specified by QueryView.
* @param nResults Number of results
* @param pParent The item for which the query was executed
*/
void TreeWidget::queryFinished(uint nResults, QListViewItem* pParent)
{
if (nResults == 0)
pParent->setExpandable(false);
else
pParent->setOpen(true);
}
/**
* Runs a query on the given item, unless it was queried before.
* This slot is connected to the expanded() signal of the list view.
* @param pItem The item to query
*/
void TreeWidget::slotQueryItem(QListViewItem* pItem)
{
// Do nothing if the item was already queried
// An item has been queried if it has children or marked as non-expandable
if (pItem->firstChild() != NULL || !pItem->isExpandable())
return;
// Run the query
m_pDriver->query(m_nQueryType, pItem->text(0), true, pItem);
}
/**
* Hides all descendant that do not meet the given search criteria.
* This slot is connected to the search() signal of the QueryResultsMenu
* object.
* The search is incremental: only visible items are checked, so that a new
* search goes over the results of the previous one.
* @param pParent The parent item whose child are searched
* @param re The pattern to search
* @param nCol The list column to search in
*/
void TreeWidget::slotSearch(QListViewItem* pParent, const QRegExp& re,
int nCol)
{
QListViewItem* pItem;
// Get the first child
if (pParent != NULL)
pItem = pParent->firstChild();
else
pItem = firstChild();
// Iterate over all child items
while (pItem != NULL) {
// Filter visible items only
if (pItem->isVisible() && re.search(pItem->text(nCol)) == -1)
pItem->setVisible(false);
// Search child items recursively
slotSearch(pItem, re, nCol);
pItem = pItem->nextSibling();
}
}
/**
* Makes all descendants of the given item visible.
* This slot is connected to the showAll() signal of the QueryResultsMenu
* object.
*/
void TreeWidget::slotShowAll(QListViewItem* pParent)
{
QListViewItem* pItem;
// Get the first child
if (pParent != NULL)
pItem = pParent->firstChild();
else
pItem = firstChild();
// Iterate over all child items
while (pItem != NULL) {
pItem->setVisible(true);
// Show child items recursively
slotShowAll(pItem);
pItem = pItem->nextSibling();
}
}
#include "treewidget.moc"

@ -0,0 +1,82 @@
/***************************************************************************
*
* Copyright (C) 2005 Elad Lahav (elad_lahav@users.sourceforge.net)
*
* 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.
*
* 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.
*
***************************************************************************/
#ifndef TREEWIDGET_H
#define TREEWIDGET_H
#include "queryview.h"
#include "encoder.h"
class QueryViewDriver;
/**
* A tree-like widget displaying a hierarchical list of functions.
* The widget has two modes: called functions and calling functions. Depending
* on this mode, child items represent functions called by or calling their
* parent item.
* @author Elad Lahav
*/
class TreeWidget : public QueryView
{
Q_OBJECT
public:
TreeWidget(QWidget* pParent = 0, const char* szName = 0);
~TreeWidget();
/**
* The type of tree to display.
*/
enum Mode { Called, Calling };
void setMode(Mode);
void setRoot(const QString&);
void queryRoot();
void save(FILE*);
virtual void addRecord(const QString&, const QString&, const QString&,
const QString&, QListViewItem*);
virtual void queryFinished(uint, QListViewItem*);
protected slots:
virtual void slotSearch(QListViewItem*, const QRegExp&, int);
virtual void slotShowAll(QListViewItem*);
private:
/** The CscopeFrontend query type to use (based on the current mode). */
uint m_nQueryType;
/** Runs queries and outputs the results as tree items. */
QueryViewDriver* m_pDriver;
void saveItems(QListViewItem*, QTextStream&, Encoder&);
private slots:
void slotQueryItem(QListViewItem*);
};
#endif

@ -0,0 +1,126 @@
<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
<class>WelcomeDlg</class>
<widget class="QDialog">
<property name="name">
<cstring>WelcomeDlg</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>519</width>
<height>386</height>
</rect>
</property>
<property name="caption">
<string>Welcome</string>
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="KTextBrowser">
<property name="name">
<cstring>m_pBrowser</cstring>
</property>
<property name="paletteBackgroundColor">
<color>
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</property>
<property name="text">
<string>&lt;h1&gt;Welcome to &lt;font color="#c00000"&gt;KScope&lt;/font&gt;!&lt;/h1&gt;
If this is the first time you are running Kscope, please follow these steps (click on the links for detailed instructions):
&lt;p&gt;
1. &lt;a href="help:/kscope/configuration.html#config-progs"&gt;Configure&lt;/a&gt; paths to the required back-end executables&lt;br&gt;
2. &lt;a href="help:/kscope/projects.html#project-create"&gt;Create&lt;/a&gt; a new project&lt;br&gt;
3. &lt;a href="help:/kscope/projects.html#project-files"&gt;Populate&lt;/a&gt; the project with source files&lt;br&gt;
4. &lt;a href="help:/kscope/queries.html"&gt;Browse&lt;/a&gt; the project and &lt;a href="help:/kscope/editing.html"&gt;edit&lt;/a&gt; files&lt;br&gt;
&lt;/p&gt;
&lt;p&gt;
For more information, please take a look at KScope's &lt;a href="help:/kscope"&gt;manual&lt;/a&gt;, or visit the KScope &lt;a href="http://kscope.sourceforge.net"&gt;website&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
Enjoy!
&lt;/p&gt;
&lt;p&gt;
&lt;font size="-1"&gt;This message will only appear once. Use the "&lt;b&gt;Help-&gt;Show Welcome Message...&lt;/b&gt;" menu command to show it again at any time.&lt;/font&gt;
&lt;/p&gt;</string>
</property>
</widget>
<widget class="Line">
<property name="name">
<cstring>line1</cstring>
</property>
<property name="frameShape">
<enum>HLine</enum>
</property>
<property name="frameShadow">
<enum>Sunken</enum>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
</widget>
<widget class="QLayoutWidget">
<property name="name">
<cstring>layout1</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer1</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>381</width>
<height>21</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>m_pCloseButton</cstring>
</property>
<property name="text">
<string>Close</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<customwidgets>
</customwidgets>
<connections>
<connection>
<sender>m_pCloseButton</sender>
<signal>clicked()</signal>
<receiver>WelcomeDlg</receiver>
<slot>accept()</slot>
</connection>
</connections>
<layoutdefaults spacing="6" margin="11"/>
<includehints>
<includehint>ktextbrowser.h</includehint>
</includehints>
</UI>

@ -0,0 +1,3 @@
doc
po
src

@ -0,0 +1,26 @@
/***************************************************************************
*
* Copyright (C) $YEAR$ $AUTHOR$ ($EMAIL$)
*
* 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.
*
* 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.
*
***************************************************************************/

@ -0,0 +1,26 @@
/***************************************************************************
*
* Copyright (C) $YEAR$ $AUTHOR$ ($EMAIL$)
*
* 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.
*
* 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.
*
***************************************************************************/
Loading…
Cancel
Save